@marimo-team/islands 0.25.3-dev3 → 0.25.3-dev301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ConnectedDataExplorerComponent-CNSxdKyJ.js → ConnectedDataExplorerComponent-X-_Gsw0B.js} +153 -177
- package/dist/{ErrorBoundary-iHE9DnZC.js → ErrorBoundary-D2XuUNty.js} +79 -85
- package/dist/{ImageComparisonComponent-uU8FSKZE.js → ImageComparisonComponent-DgvSuY9B.js} +20 -20
- package/dist/{Plot-DdYOe1UK.js → Plot-Bfd0pJea.js} +2474 -3107
- package/dist/_baseSet-Bd5zh2yg.js +327 -0
- package/dist/{abnfDiagram-VCTEODGH-DQDjNXt3.js → abnfDiagram-VCTEODGH-B8nNWmL7.js} +5 -5
- package/dist/any-language-editor-DhAtCzlx.js +75 -0
- package/dist/{apl-GEW9-ZP1.js → apl-stFrI2NB.js} +1 -1
- package/dist/{arc-7ra3iNdN.js → arc-4W6H62B5.js} +1 -1
- package/dist/architecture-7GRP2DOG-GlkXha5_.js +2 -0
- package/dist/{architectureDiagram-5GKGNRK7-Nmls7Wxn.js → architectureDiagram-5GKGNRK7-DcfTzRDz.js} +48 -64
- package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
- package/dist/{asciiarmor-BWNxzkG7.js → asciiarmor-DHwFuaIC.js} +1 -1
- package/dist/{asn1-Bcn2QutK.js → asn1-KIH4fwAq.js} +1 -1
- package/dist/assertNever-De6m1Aro.js +507 -0
- package/dist/assets/__vite-browser-external-BzfoKXxV.js +1 -0
- package/dist/assets/worker-DVG30pr3.js +171 -0
- package/dist/{blockDiagram-I7D4REHJ-Cg25UrxT.js → blockDiagram-I7D4REHJ-B4cvqWJn.js} +28 -39
- package/dist/{brainfuck-BQCYDheZ.js → brainfuck-UPAij4U9.js} +1 -1
- package/dist/{button-CvjkwdSk.js → button-BuSV-mLI.js} +64 -64
- package/dist/{c4Diagram-7LVT6UL2-BxFgrnNV.js → c4Diagram-7LVT6UL2-k-4SLDdM.js} +8 -8
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-BiN90k7v.js} +2 -2
- package/dist/{channel-CPObtJXj.js → channel-CuTaWMxU.js} +1 -1
- package/dist/{chat-ui-BDpymeoe.js → chat-ui-CtbON6Zl.js} +1712 -1440
- package/dist/{check-EDwSwP89.js → check-C7fmwkwt.js} +1 -1
- package/dist/{chunk-4HAMMTFA-D4eFPyFh.js → chunk-4HAMMTFA-Bk_5S_m9.js} +6 -6
- package/dist/{chunk-75Z2AOVW-D7gxIs2Q.js → chunk-75Z2AOVW-9jQIEAxd.js} +4 -4
- package/dist/{chunk-DU6HZSFF-BwiyaNpg.js → chunk-DU6HZSFF-B20LZ-hE.js} +14 -22
- package/dist/{chunk-F27PBJKO-ufseIn5y.js → chunk-F27PBJKO-YjRXlNkT.js} +3 -3
- package/dist/{chunk-FOHPRMQF-BpYR8RqP.js → chunk-FOHPRMQF-ezmr_yWy.js} +49 -58
- package/dist/{chunk-GMAD6QVW-BhaJx0X3.js → chunk-GMAD6QVW-DokpSFdf.js} +16 -75
- package/dist/{chunk-GVQU2GXP-Cwbt-lF0.js → chunk-GVQU2GXP-DGvySV5W.js} +3 -3
- package/dist/{chunk-IMKFNOWR-CoIFEo-1.js → chunk-IMKFNOWR-BHJ3ZxAy.js} +8 -8
- package/dist/{chunk-L3NEJ4N5-n-zgIVSy.js → chunk-L3NEJ4N5-D9-ekjZc.js} +6 -6
- package/dist/{chunk-OSK3NFVY-DXa-Cxbn.js → chunk-OSK3NFVY-p7meGiY-.js} +8 -8
- package/dist/{chunk-P2QGCYS3-B_Zd3-X0.js → chunk-P2QGCYS3-74rxrEwb.js} +1 -1
- package/dist/{chunk-POPQ4Y6H-hYOXbYH_.js → chunk-POPQ4Y6H-EOTPk9Tj.js} +2 -2
- package/dist/{chunk-PWAF6VOD-CQw5qATZ.js → chunk-PWAF6VOD-oT_Qd2OU.js} +2 -2
- package/dist/{chunk-SHT3W25Y-lHiGx3ZC.js → chunk-SHT3W25Y-CkOPJgVC.js} +10 -10
- package/dist/{chunk-SVP7TREG-BvsHIrY_.js → chunk-SVP7TREG-rDd35EZ7.js} +3 -3
- package/dist/{chunk-TICWLB2K-BC8YIm_n.js → chunk-TICWLB2K-uKdr5PNy.js} +10 -10
- package/dist/{chunk-XXDRQBXY-Dnl5VBqG.js → chunk-XXDRQBXY-BM-YIt-_.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-KxncHymC.js} +171 -396
- package/dist/classDiagram-ZZMXUADV-DctWoMRF.js +30 -0
- package/dist/classDiagram-v2-VYDZK3BY-DyanDjSq.js +30 -0
- package/dist/{clike-CxK9W55Z.js → clike-xU8sCVU1.js} +2 -6
- package/dist/{clojure-Dzcvwpxk.js → clojure-psoSEo36.js} +1 -1
- package/dist/{cmake-DYr-71zp.js → cmake-DDHBwlE7.js} +1 -1
- package/dist/{cobol-DC3g37Kq.js → cobol-C4qjDcIq.js} +1 -1
- package/dist/code-visibility-Y0zfGGT1.js +131 -0
- package/dist/{coffeescript-C-eFwH5N.js → coffeescript-D6UgrGgo.js} +1 -1
- package/dist/{common-BrBUdtPy.js → common-B_rBSwAA.js} +10980 -10178
- package/dist/{commonlisp-CyaNXrJR.js → commonlisp-B0ChVjnu.js} +1 -1
- package/dist/{compiler-runtime-CldRdSsv.js → compiler-runtime-DNezxW8I.js} +2 -2
- package/dist/{toDate-BNJf01u1.js → config-C4oddKcw.js} +107 -177
- package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-CVrC6aa6.js} +21 -22
- package/dist/{cose-bilkent-JH36ORCC-_LyRKVqm.js → cose-bilkent-JH36ORCC-B_Oz4vMP.js} +58 -71
- package/dist/createReducer-DzlYBqjn.js +67 -0
- package/dist/{crystal-ih5ax5tQ.js → crystal-DZsc9Ue0.js} +1 -1
- package/dist/{css-CN_wP7_R.js → css-DkYRnQ9U.js} +1 -1
- package/dist/{cubic-OaEBhQPK.js → cubic-CA80xY_e.js} +6 -7
- package/dist/cynefin-OW5HDTMX-0-HehVvH.js +2 -0
- package/dist/{cynefinDiagram-5FMLGOSQ-CgWra7wt.js → cynefinDiagram-5FMLGOSQ-uEhVcLHR.js} +5 -5
- package/dist/{cypher-CqGRcmZo.js → cypher-CpWPqgvy.js} +1 -1
- package/dist/{cytoscape.esm-jJhXJpLB.js → cytoscape.esm-BbeMznK5.js} +411 -512
- package/dist/{d-Cj0sOW2z.js → d-Bx2ggfYO.js} +1 -1
- package/dist/{dagre-BGSfXNEb.js → dagre-CpjuekF1.js} +550 -700
- package/dist/{dagre-GXQ25YYZ-CFZ8-35c.js → dagre-GXQ25YYZ-B_NBKhOr.js} +14 -16
- package/dist/{data-grid-overlay-editor-Ch2SgmvG.js → data-grid-overlay-editor-04SWN9ol.js} +8 -8
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-CSElxhxo.js} +2 -2
- package/dist/{debounce-C3jyATpc.js → debounce-DrhhziJv.js} +2 -2
- package/dist/{diagram-S7CK7UJ4-lCNQrW7d.js → diagram-S7CK7UJ4-BQr1iw91.js} +7 -15
- package/dist/{diagram-UQ7AKVKN-CQPQ6pP_.js → diagram-UQ7AKVKN-DsAjdQ2j.js} +5 -5
- package/dist/{diagram-VSXAHHWV-BJWcVVJY.js → diagram-VSXAHHWV-CodTjaL3.js} +6 -6
- package/dist/{diagram-VX7I27RA-Cf3b0llz.js → diagram-VX7I27RA-0VAUrHmz.js} +7 -7
- package/dist/{diagram-Z3DM3KII-Bt4QLrpn.js → diagram-Z3DM3KII-C1aEuADo.js} +5 -5
- package/dist/{dialog-CEBFZNyc.js → dialog-U3stKkkL.js} +35 -35
- package/dist/{diff-B_hUkiat.js → diff-DNXaJS8v.js} +1 -1
- package/dist/{dist-D6d86eNJ.js → dist-B-Id1kt3.js} +48 -47
- package/dist/{dist-DiDibOYr.js → dist-BDw9g6PC.js} +152 -151
- package/dist/{dist-diIx5qJW.js → dist-B_EswY8r.js} +33 -32
- package/dist/{dist-DoE4XJBC.js → dist-B_xgcU0N.js} +9800 -10654
- package/dist/{dist-CLdpGQVr.js → dist-BcGGwW1q.js} +119 -121
- package/dist/dist-BdZQUzPS.js +850 -0
- package/dist/{dist-CN_BeG2I.js → dist-Bj8s59mu.js} +59 -58
- package/dist/{dist-CkTTIdBe.js → dist-C3dYgyiI.js} +337 -337
- package/dist/{dist-PXYI_yuP.js → dist-C6ttp2Iy.js} +24 -23
- package/dist/{dist-DUAh96QY.js → dist-CB9MzCXv.js} +1 -1
- package/dist/{dist-CSbh1PNP.js → dist-CCYz0qJ2.js} +24 -23
- package/dist/{dist-BMQf5zIS.js → dist-CDjivQ67.js} +124 -123
- package/dist/{dist-D-wwqlzJ.js → dist-CNT4u03u.js} +159 -158
- package/dist/{dist-F8Ep36rk.js → dist-DVVzH9mP.js} +60 -59
- package/dist/{dist-OR1OnN-y.js → dist-DlniJvh2.js} +32 -31
- package/dist/{dist-CSJ0MDRw.js → dist-Dq-hanx8.js} +57 -56
- package/dist/{dist-DpBpA_n1.js → dist-Du4PgaYp.js} +5 -5
- package/dist/{dist-C8fAKSH1.js → dist-FakvNY2e.js} +54 -53
- package/dist/{dist-BuaRHxOc.js → dist-K-qmZv0f.js} +45 -44
- package/dist/{dist-Cg7gzw-a.js → dist-NPImE_g9.js} +79 -78
- package/dist/{dist-CN8zI-XC.js → dist-PKX4HaX5.js} +239 -239
- package/dist/{dist-CrSP_H1M.js → dist-U4WlxEDL.js} +243 -243
- package/dist/{dist-BK4Oj99o.js → dist-UKKHsqHo.js} +19 -18
- package/dist/{dist-Bvs24R_E.js → dist-VRN9rDqa.js} +32 -31
- package/dist/{dist-BorMD-uX.js → dist-f1h5p-fp.js} +76 -75
- package/dist/{dist-BLfKmR-l.js → dist-h8Te4SvD.js} +17 -16
- package/dist/{dist-DBtSl3sf.js → dist-ymIUQ4tH.js} +48 -50
- package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-BMtxnyHc.js} +2798 -1494
- package/dist/{dtd-B8FGSWWe.js → dtd-D1YZQCVT.js} +1 -1
- package/dist/{dylan-DbIBYIrw.js → dylan-CxbG-PUm.js} +2 -2
- package/dist/{ebnfDiagram-PWID7BFC-D3NAyPFY.js → ebnfDiagram-PWID7BFC-oBie_-vi.js} +5 -5
- package/dist/{ecl-DBmkdWAd.js → ecl-DIXH6vul.js} +1 -1
- package/dist/{eiffel-CcWSDDzK.js → eiffel-D0de-eQr.js} +1 -1
- package/dist/{elm-MC-b8a6C.js → elm-DrQrn4VD.js} +1 -1
- package/dist/{erDiagram-RLTQ6QDP-Tlu09_Nm.js → erDiagram-RLTQ6QDP-DtWDCiaw.js} +14 -14
- package/dist/{erlang-AdO1-xtV.js → erlang-2KpKpfC7.js} +1 -1
- package/dist/{error-banner-Da600cwz.js → error-banner-CfIck83X.js} +94 -89
- package/dist/error-entries-CjsQY6ym.js +2581 -0
- package/dist/{esm-G4Fhsgng.js → esm-BUoz9Vvv.js} +4 -4
- package/dist/{esm-AMFssoNp.js → esm-BvhFNYzM.js} +333 -333
- package/dist/{esm-D2gTsXEV.js → esm-wKplZtOX.js} +580 -581
- package/dist/eventmodeling-NTZA5JFV-DoBvB4Lj.js +2 -0
- package/dist/{factor-Ys-13HOP.js → factor-Bwu3ZGOk.js} +1 -1
- package/dist/{feedback-button-DxXNcC6q.js → feedback-button-DoriP8b7.js} +116 -126
- package/dist/flowDiagram-HODETNUW-EXK7bg_t.js +15 -0
- package/dist/{formats-BGh2thRc.js → formats-G0-mQsFy.js} +9 -9
- package/dist/{forth-DiMuIXFe.js → forth-DYatDpr6.js} +2 -3
- package/dist/{fortran-hkrF2eM4.js → fortran-n8mcQPkL.js} +1 -1
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-DyUab7aO.js} +17 -17
- package/dist/{gas-DlhqN9k8.js → gas-BUZOHBVw.js} +1 -1
- package/dist/{gherkin-0SlhEZ3t.js → gherkin-CrSjX26K.js} +1 -1
- package/dist/gitGraph-4MIJSDKK-Ch7kj-d2.js +2 -0
- package/dist/{gitGraphDiagram-WWUBYQGX-D5nSIzdE.js → gitGraphDiagram-WWUBYQGX-BPeDECwG.js} +4 -4
- package/dist/{glide-data-editor-BQ7uKbeo.js → glide-data-editor-BU_jOTDv.js} +6663 -2919
- package/dist/{glide-utils-DJyqh0EM.js → glide-utils-BkcGyXLQ.js} +109 -78
- package/dist/{globals-DSavh2ZB.js → globals-DziKJCFY.js} +3 -3
- package/dist/{graphlib-BmY_CCV9.js → graphlib-nlwT3Wvy.js} +177 -220
- package/dist/{groovy-YhcTMyvX.js → groovy-IgGNjeU9.js} +1 -1
- package/dist/hasIn-C20JsQ2m.js +28 -0
- package/dist/{haskell-CodLxrtT.js → haskell-Bs1k3a9s.js} +1 -1
- package/dist/{haxe-CiRWNFkH.js → haxe-CQ8Yb3XF.js} +1 -1
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-XbLtWlYz.js} +5 -5
- package/dist/{cells-C8iCYvLU.js → html-to-image-CIm3PqDi.js} +26098 -26387
- package/dist/{idl-DZgBq75I.js → idl-DjnxoAWx.js} +1 -1
- package/dist/info-A6RAGUB7-DCz_Egh9.js +2 -0
- package/dist/{infoDiagram-27XIBGKW-XrDxhr0x.js → infoDiagram-27XIBGKW-N4ajFTXv.js} +4 -4
- package/dist/isArrayLikeObject-B-HXCsex.js +626 -0
- package/dist/isEmpty-CdX7MTE1.js +14 -0
- package/dist/{ishikawaDiagram-5VMMS53U-CD1muzov.js → ishikawaDiagram-5VMMS53U-Bb2itmv5.js} +5 -7
- package/dist/{javascript-BfNytHiM.js → javascript-BQtCoAFy.js} +2 -2
- package/dist/{journeyDiagram-3NMN7TZE-BaLqn-dZ.js → journeyDiagram-3NMN7TZE-D7hcb3Vx.js} +4 -4
- package/dist/{jsx-runtime-3BD1kT0s.js → jsx-runtime-6ZiU38At.js} +1 -1
- package/dist/{julia--tLIAG7q.js → julia-BfgtHJE5.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-Dg9W142_.js → kanban-definition-UXKFOSKX-DWfkIEDX.js} +10 -10
- package/dist/{katex-BIdZGsyO.js → katex-BmPSeP5t.js} +15 -24
- package/dist/linear-BhKepphY.js +251 -0
- package/dist/{livescript-CVPfYnY_.js → livescript-gIdRPKtg.js} +1 -1
- package/dist/{loader-BQOfjTIJ.js → loader-BIlwkY0d.js} +12 -12
- package/dist/{lua-4Fa-T-qq.js → lua-CxFpWvnv.js} +2 -2
- package/dist/main.js +10300 -8421
- package/dist/{mathematica-CtYAy6GG.js → mathematica-QSveeEoW.js} +1 -1
- package/dist/{mbox-D0w9Ah1C.js → mbox-2JtaCPNT.js} +1 -1
- package/dist/{mermaid-CiAXjLpA.js → mermaid-BEBd0PHi.js} +170 -176
- package/dist/mermaid-HWGCJPDP-_lKUMvTM.js +1 -0
- package/dist/{mermaid-parser.core-DxuSfYwJ.js → mermaid-parser.core-DtOnl7m4.js} +19 -25
- package/dist/{mhchem-CdWPJK6g.js → mhchem-CjWbCsjZ.js} +1 -1
- package/dist/{micromark-factory-space-DGxAzmw8.js → micromark-factory-space-C5soVmaM.js} +1 -1
- package/dist/{mindmap-definition-YA3MSWOX-DgCidgYJ.js → mindmap-definition-YA3MSWOX-CmGSiRxU.js} +13 -13
- package/dist/{mirc-De9aSAZM.js → mirc-BqD6ade4.js} +1 -1
- package/dist/{mllike-BbugeaY_.js → mllike-CT0hgEOO.js} +1 -1
- package/dist/{modelica-BjJwWw1F.js → modelica-DKKebcvq.js} +1 -1
- package/dist/{mscgen-DwiRH5ma.js → mscgen-BJCCsWjR.js} +1 -1
- package/dist/{mumps--plbDM9o.js → mumps-DVQAXZkU.js} +1 -1
- package/dist/{nginx-C4Df7REc.js → nginx-AP4LH2NN.js} +1 -1
- package/dist/{node-sql-parser-BiZOJ-FS.js → node-sql-parser-C9dndbfr.js} +7184 -7195
- package/dist/{now-jM8-M7IR.js → now-BKZCLE5P.js} +12 -13
- package/dist/{nsis-fiiOqLc3.js → nsis-Cah9xkdT.js} +1 -1
- package/dist/{ntriples-jV77I4k8.js → ntriples-CQoaLOV6.js} +2 -2
- package/dist/{number-overlay-editor-D6kYaqh5.js → number-overlay-editor-BaZBWVbO.js} +16 -21
- package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
- package/dist/{octave-Cztd01tF.js → octave-CeDj2bTn.js} +1 -1
- package/dist/{once-BtE-wKRL.js → once-NnpX_HnX.js} +1 -1
- package/dist/{oz-Bl8o3BDl.js → oz-BksQrg3k.js} +1 -1
- package/dist/packet-AYTQ26CC-DEMHgLPq.js +2 -0
- package/dist/{pascal-BO5JqysR.js → pascal-BKL17mpl.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-coOYYKB6.js → pegDiagram-XKGWAZYB-dXflGNi0.js} +5 -5
- package/dist/pencil-BGy5pfXo.js +10 -0
- package/dist/{perl-Drlh9s6m.js → perl-CacqJ-Ss.js} +1 -1
- package/dist/pick-DgpAbcwP.js +35 -0
- package/dist/pie-WAS4IAKB-DMjTEeHd.js +2 -0
- package/dist/{pieDiagram-E7YTZNPT-BnXTc3bj.js → pieDiagram-E7YTZNPT-Bl9G_NNa.js} +7 -7
- package/dist/{pig-BWGR8wZw.js → pig-CXSGZ_K9.js} +1 -1
- package/dist/{powershell-DT99xlz_.js → powershell-DY_yIxBM.js} +3 -6
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-e4jj9Ijt.js → process-output-DAVapIAQ.js} +6 -6
- package/dist/{properties-Q-rkxld0.js → properties-Om0IDE07.js} +1 -1
- package/dist/{protobuf-DKyWZbs7.js → protobuf-B8nxxb4Q.js} +1 -1
- package/dist/{pug-42ZJUbEC.js → pug-lkUBPvVS.js} +3 -7
- package/dist/{puppet-B4UozHhh.js → puppet-DMkXsi4d.js} +1 -1
- package/dist/purify.es-DmnrIjg4.js +877 -0
- package/dist/{python-DREjAV__.js → python-JQVycMgr.js} +1 -1
- package/dist/{q-Bi63IpBO.js → q-DqE__nNB.js} +1 -1
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-DLJJzlPi.js} +3 -3
- package/dist/{r-DSwXWKMR.js → r-Cbliap7Q.js} +1 -1
- package/dist/radar-RG4KPBEZ-9PwdCvai.js +2 -0
- package/dist/railroad-74A4TZTK-8N9kF5jl.js +2 -0
- package/dist/railroad-abnf-HS5TGJTU-Sg6YmzlR.js +2 -0
- package/dist/railroad-ebnf-LZEXJU2U-CYwp2Oee.js +2 -0
- package/dist/railroad-peg-WCYAUIDC-BfDkAuQ3.js +2 -0
- package/dist/{railroadDiagram-O6MQD6OU-B28-u83n.js → railroadDiagram-O6MQD6OU-Dg7GUHj4.js} +5 -5
- package/dist/{react-sHtZdjeP.js → react-CHbZqgBF.js} +1 -1
- package/dist/{react-dom-DUmH0GXv.js → react-dom-DhWGW7e0.js} +3 -3
- package/dist/{react-vega-BED0DjiB.js → react-vega-DVr24mNk.js} +13653 -13722
- package/dist/{requirementDiagram-BXWQKSXE-CdYCTMu0.js → requirementDiagram-BXWQKSXE-JNZB3XKK.js} +13 -13
- package/dist/{reveal-component-BTBfJ3ju.js → reveal-component-vRQ0ZbEq.js} +1171 -1284
- package/dist/{rolldown-runtime-Cb76FRpK.js → rolldown-runtime-BPCzCO3I.js} +1 -1
- package/dist/{rpm-DPb1DeKM.js → rpm-DmT_LNpE.js} +1 -1
- package/dist/{ruby-U7fZA4DP.js → ruby-BHVZTtLW.js} +1 -1
- package/dist/{sankeyDiagram-P5KCCOFB-ELvOcnZH.js → sankeyDiagram-P5KCCOFB-Bd7wvmbF.js} +2 -2
- package/dist/{sas-CLk1JpTn.js → sas-CrG5N1he.js} +1 -1
- package/dist/{scheme-CT-2k2Tl.js → scheme-BHUnz-IB.js} +1 -1
- package/dist/select-Ba_tMQWZ.js +1200 -0
- package/dist/{semaphore-89jsoHtS.js → semaphore-8KhQouXt.js} +4 -5
- package/dist/{sequenceDiagram-WJ2MYXX4-CM3aRAe_.js → sequenceDiagram-WJ2MYXX4-DekbwWOI.js} +6 -6
- package/dist/{shell-BLO7fcsk.js → shell-C5IBmRU5.js} +1 -1
- package/dist/{sieve-nG3C7WNH.js → sieve-BzCnt_E6.js} +2 -2
- package/dist/{sizeCapture-INFHLROL-Dx5SpkQF.js → sizeCapture-INFHLROL-DBeZ20mI.js} +1 -1
- package/dist/{smalltalk-BROcZybA.js → smalltalk-DQFAQul3.js} +1 -1
- package/dist/{solr-mVltHNc5.js → solr-BiapYPCk.js} +1 -1
- package/dist/{sparql-Cv1Ksr4v.js → sparql-BcUKO1is.js} +1 -1
- package/dist/{spec-BwarBpUJ.js → spec-CN3OxHz7.js} +42 -12
- package/dist/{src-CA_m4ONl.js → src-D5uZaZib.js} +8 -14
- package/dist/{stateDiagram-D77RDMKH-DOZUMVj8.js → stateDiagram-D77RDMKH-COzvSaN-.js} +18 -18
- package/dist/stateDiagram-v2-MP3YSRHH-rCvxZ0L8.js +30 -0
- package/dist/static-state-BJdfR8Bn.js +68 -0
- package/dist/{stex-Btf3omL8.js → stex-CQ_aCGTF.js} +1 -1
- package/dist/style.css +1 -1
- package/dist/{stylus-Dt4VvLXL.js → stylus-D4gHF5lg.js} +1 -1
- package/dist/{swift-DHsn_CVI.js → swift-CnvIBnbt.js} +1 -1
- package/dist/{swimlanes-42K2YHIH-BkSppxp8.js → swimlanes-42K2YHIH-DX2mMlXc.js} +37 -59
- package/dist/swimlanesDiagram-VR7AAH4N-DswSPZ5e.js +30 -0
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-FBPvIqLf.js} +45 -78
- package/dist/{tcl-CV0OLBOl.js → tcl-DkOjjZYO.js} +1 -1
- package/dist/{textile-D320oKVM.js → textile-DgzBVSEW.js} +1 -1
- package/dist/{tiki-BF2aDPlB.js → tiki-MighF8A_.js} +1 -1
- package/dist/{time-BieKwdYS.js → time-Cc-G3e31.js} +19 -19
- package/dist/{timeline-definition-24CTP7MA-CaMQayqK.js → timeline-definition-24CTP7MA-DAT9AlwV.js} +5 -5
- package/dist/toast-BRd_eTIj.js +491 -0
- package/dist/{toml-CaUN7UHo.js → toml-B0B7UAba.js} +1 -1
- package/dist/{tooltip-BO1REbqs.js → tooltip-CHvXUQVs.js} +332 -308
- package/dist/treeView-Q6P3EWNA-BQywp0E1.js +2 -0
- package/dist/treemap-WGGIJYW6-P2ZJnldw.js +2 -0
- package/dist/{troff-DQUFcClZ.js → troff-B4IRX71y.js} +1 -1
- package/dist/{ttcn-CQL1duJS.js → ttcn-B4tpvdJD.js} +1 -1
- package/dist/{ttcn-cfg-BMmEFJPu.js → ttcn-cfg-pfE-1FV8.js} +1 -1
- package/dist/{turtle-C3esgsRr.js → turtle-Bc97ufp6.js} +1 -1
- package/dist/use-restore-focus-Ckq0jQzc.js +7534 -0
- package/dist/{use-vega-container-remeasure-Bz4PZMtt.js → use-vega-container-remeasure-DFBTESqc.js} +4 -8
- package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-DMBliR6D.js} +21 -20
- package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-CIPe17AG.js} +4 -4
- package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-Kg-7A4b-.js} +3 -3
- package/dist/useEvent-xDnF2X04.js +19 -0
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities--px_wpZL.js} +2 -2
- package/dist/useLifecycle-BKVRcyGu.js +112 -0
- package/dist/{vb-RK1eDXRl.js → vb-C5kpOY_q.js} +1 -1
- package/dist/{vbscript-BCOeM0de.js → vbscript-Ck0hgOg5.js} +1 -1
- package/dist/{vega-component-DG29TAB7.js → vega-component-C23pVuni.js} +167 -172
- package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container-DAT8OHp9.js} +7 -7
- package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-Cnf7IHA8.js} +331 -543
- package/dist/{velocity-CZKOFbOI.js → velocity-2Doc6dgJ.js} +1 -1
- package/dist/{vennDiagram-4TSXK5OY-CF8pfaK3.js → vennDiagram-4TSXK5OY-E7CMtY2M.js} +4 -4
- package/dist/{verilog-DqQTzVn8.js → verilog-CmZmYe4R.js} +2 -2
- package/dist/{vhdl-vQr2bfmi.js → vhdl-esMnUHZm.js} +1 -1
- package/dist/wardley-WFR3VGLG-CIBJ6O2G.js +2 -0
- package/dist/{wardleyDiagram-VM6X3IG4-dGPu39d-.js → wardleyDiagram-VM6X3IG4-BjtOazpV.js} +5 -5
- package/dist/{webidl-DzX7N40e.js → webidl-G_RlXG7G.js} +1 -1
- package/dist/{xquery-Cw_Q_hGR.js → xquery-IUQpMoMl.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CP6-9q56.js → xychartDiagram-S5SC5T6Z-DC09jtph.js} +8 -8
- package/dist/{yacas-DiC4jJBE.js → yacas-ObL0t2h9.js} +1 -1
- package/dist/{z80-CUOQDEJO.js → z80-jyuJhy0k.js} +1 -1
- package/package.json +18 -21
- package/src/__mocks__/document.tsx +63 -0
- package/src/__mocks__/executions.ts +197 -0
- package/src/__mocks__/notebook.ts +3 -7
- package/src/__mocks__/partial.ts +26 -0
- package/src/__mocks__/requests.ts +1 -4
- package/src/__tests__/CellStatus.test.tsx +25 -26
- package/src/__tests__/fixtures/{pair-preview.ts → pair-config.ts} +4 -3
- package/src/__tests__/main.test.tsx +24 -1
- package/src/__tests__/module-entry.test.ts +44 -0
- package/src/__tests__/mount.test.ts +9 -9
- package/src/__tests__/{host-imports.test.ts → replica-imports.test.ts} +12 -11
- package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
- package/src/components/ai/ai-model-dropdown.tsx +11 -6
- package/src/components/app-config/__tests__/state.test.tsx +50 -0
- package/src/components/app-config/ai-config.tsx +156 -150
- package/src/components/app-config/app-config-button.tsx +6 -5
- package/src/components/app-config/app-config-form.tsx +5 -9
- package/src/components/app-config/common.tsx +7 -9
- package/src/components/app-config/data-form.tsx +112 -113
- package/src/components/app-config/mcp-config.tsx +30 -53
- package/src/components/app-config/user-config-form.css +91 -0
- package/src/components/app-config/user-config-form.tsx +266 -349
- package/src/components/chat/__tests__/capabilities-popover.test.tsx +0 -1
- package/src/components/chat/__tests__/chat-display.test.tsx +196 -0
- package/src/components/chat/__tests__/chat-markdown.test.tsx +43 -0
- package/src/components/chat/__tests__/chat-utils.test.ts +93 -1
- package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
- package/src/components/chat/__tests__/notebook-access-selector.test.tsx +64 -0
- package/src/components/chat/__tests__/turn-timing.test.ts +84 -0
- package/src/components/chat/__tests__/use-assistant-turn.test.ts +95 -0
- package/src/components/chat/__tests__/user-message.test.tsx +27 -0
- package/src/components/chat/acp/__tests__/agent-panel-initialization.test.tsx +1 -1
- package/src/components/chat/acp/__tests__/agent-panel.test.tsx +22 -17
- package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
- package/src/components/chat/acp/__tests__/state.test.ts +2 -2
- package/src/components/chat/acp/agent-panel.tsx +6 -3
- package/src/components/chat/acp/blocks.tsx +13 -12
- package/src/components/chat/acp/common.tsx +4 -5
- package/src/components/chat/acp/model-selector.tsx +1 -1
- package/src/components/chat/acp/session-tabs.tsx +8 -3
- package/src/components/chat/agent-activity.tsx +132 -0
- package/src/components/chat/capabilities-popover.tsx +2 -11
- package/src/components/chat/chat-components.tsx +9 -4
- package/src/components/chat/chat-display.tsx +131 -57
- package/src/components/chat/chat-history-popover.tsx +6 -1
- package/src/components/chat/chat-markdown.tsx +15 -0
- package/src/components/chat/chat-panel.tsx +216 -294
- package/src/components/chat/chat-typography.css +108 -0
- package/src/components/chat/chat-utils.ts +24 -35
- package/src/components/chat/notebook-access-selector.stories.tsx +22 -0
- package/src/components/chat/notebook-access-selector.tsx +100 -0
- package/src/components/chat/tool-call/__tests__/tool-labels.test.ts +76 -0
- package/src/components/chat/tool-call/__tests__/tool-step.test.tsx +57 -0
- package/src/components/chat/tool-call/shared.ts +6 -0
- package/src/components/chat/tool-call/tool-call-view.tsx +22 -76
- package/src/components/chat/tool-call/tool-labels.ts +172 -0
- package/src/components/chat/tool-call/tool-result.tsx +1 -1
- package/src/components/chat/tool-call/tool-step.tsx +145 -0
- package/src/components/chat/turn-timing.ts +73 -0
- package/src/components/chat/use-assistant-turn.ts +65 -0
- package/src/components/chat/use-chat-generation.ts +20 -0
- package/src/components/chat/user-message.tsx +145 -0
- package/src/components/data-table/TableBottomBar.tsx +4 -1
- package/src/components/data-table/TableTopBar.tsx +2 -0
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
- package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
- package/src/components/data-table/__tests__/columns.test.tsx +105 -0
- package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
- package/src/components/data-table/__tests__/context-menu.test.ts +176 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
- package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +434 -6
- package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
- package/src/components/data-table/__tests__/pagination.test.tsx +28 -1
- package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
- package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
- package/src/components/data-table/cell-selection/feature.ts +2 -2
- package/src/components/data-table/cell-selection/types.ts +2 -2
- package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
- package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
- package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
- package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
- package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
- package/src/components/data-table/charts/charts.tsx +40 -30
- package/src/components/data-table/charts/storage.ts +16 -5
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-formatting/types.ts +1 -2
- package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
- package/src/components/data-table/column-summary/column-summary.tsx +2 -4
- package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
- package/src/components/data-table/columns.tsx +45 -46
- package/src/components/data-table/context-menu.tsx +161 -46
- package/src/components/data-table/data-table.tsx +17 -1
- package/src/components/data-table/date-filter-inputs.tsx +15 -42
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +267 -163
- package/src/components/data-table/pagination.tsx +44 -33
- package/src/components/data-table/range-focus/atoms.ts +4 -6
- package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
- package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
- package/src/components/data-table/renderers.tsx +16 -7
- package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
- package/src/components/data-table/schemas.ts +14 -36
- package/src/components/data-table/search-highlight.tsx +79 -0
- package/src/components/data-table/types.ts +1 -0
- package/src/components/data-table/url-detector.tsx +49 -9
- package/src/components/data-table/utils.ts +18 -0
- package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +96 -5
- package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/__tests__/utils.test.ts +57 -6
- package/src/components/datasources/column-preview.tsx +17 -12
- package/src/components/datasources/datasources.tsx +56 -43
- package/src/components/datasources/utils.ts +32 -23
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/custom-node.tsx +1 -1
- package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
- package/src/components/dependency-graph/elements.ts +24 -21
- package/src/components/dependency-graph/minimap-content.tsx +15 -20
- package/src/components/dependency-graph/panels.tsx +4 -2
- package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
- package/src/components/editor/Output.tsx +9 -2
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/Output.test.tsx +50 -32
- package/src/components/editor/__tests__/agent-toast.test.tsx +58 -0
- package/src/components/editor/__tests__/data-attributes.test.tsx +28 -23
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/output-persistence.test.tsx +28 -9
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +69 -260
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +222 -43
- package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +6 -24
- package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +131 -0
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/pair-with-agent-commands.ts +48 -54
- package/src/components/editor/actions/pair-with-agent-modal.tsx +102 -43
- package/src/components/editor/actions/pair-with-agent.tsx +16 -39
- package/src/components/editor/actions/useCellActionButton.tsx +47 -35
- package/src/components/editor/actions/useConfigActions.tsx +3 -4
- package/src/components/editor/actions/useNotebookActions.tsx +25 -29
- package/src/components/editor/actions/useRestartKernel.tsx +1 -1
- package/src/components/editor/actions/useSetCodeVisibility.ts +11 -12
- package/src/components/editor/actions/useSetOutputsExpanded.ts +14 -19
- package/src/components/editor/agent-toast.ts +15 -0
- package/src/components/editor/ai/ai-completion-editor.tsx +2 -1
- package/src/components/editor/ai/completion-handlers.tsx +0 -37
- package/src/components/editor/ai/prompt-input.tsx +189 -0
- package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +1 -1
- package/src/components/editor/alerts/connection-notice.tsx +1 -1
- package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
- package/src/components/editor/alerts/stdin-blocking-alert.tsx +4 -2
- package/src/components/editor/app-container.tsx +1 -1
- package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +1 -1
- package/src/components/editor/cell/CellStatus.tsx +28 -23
- package/src/components/editor/cell/CreateCellButton.tsx +15 -21
- package/src/components/editor/cell/DeleteButton.tsx +3 -2
- package/src/components/editor/cell/RunButton.tsx +18 -8
- package/src/components/editor/cell/StagedAICell.tsx +52 -137
- package/src/components/editor/cell/StopButton.tsx +2 -2
- package/src/components/editor/cell/__tests__/useRunCells.test.tsx +169 -0
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/cell-actions.tsx +12 -1
- package/src/components/editor/cell/cell-context-menu.tsx +4 -1
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +65 -169
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +16 -6
- package/src/components/editor/cell/useAddCell.ts +4 -8
- package/src/components/editor/cell/useDeleteCell.tsx +10 -36
- package/src/components/editor/cell/useRunCells.ts +49 -8
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/cell/useSplitCell.tsx +10 -6
- package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +1 -1
- package/src/components/editor/chrome/components/feedback-button.tsx +2 -8
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +31 -2
- package/src/components/editor/chrome/panels/__tests__/runtime-details.test.tsx +1 -1
- package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +1 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/error-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
- package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
- package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/panels/panel-header.tsx +13 -0
- package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/session-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +10 -12
- package/src/components/editor/chrome/panels/variable-panel.tsx +1 -5
- package/src/components/editor/chrome/types.ts +1 -1
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +364 -0
- package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +265 -37
- package/src/components/editor/chrome/wrapper/__tests__/useAskAiAboutCell.test.tsx +58 -0
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +91 -74
- package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +237 -0
- package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
- package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/footer.tsx +4 -2
- package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +143 -72
- package/src/components/editor/chrome/wrapper/pending-ai-changes-badge.tsx +25 -0
- package/src/components/editor/chrome/wrapper/sidebar.tsx +8 -4
- package/src/components/editor/chrome/wrapper/storage.ts +1 -1
- package/src/components/editor/chrome/wrapper/useAskAiAboutCell.ts +36 -0
- package/src/components/editor/columns/__tests__/cell-column.test.tsx +1 -1
- package/src/components/editor/columns/cell-column.tsx +1 -1
- package/src/components/editor/columns/sortable-column.tsx +2 -2
- package/src/components/editor/connections/components.tsx +5 -10
- package/src/components/editor/controls/Controls.tsx +4 -4
- package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
- package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
- package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +10 -4
- package/src/components/editor/controls/command-palette.tsx +22 -10
- package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
- package/src/components/editor/documentation.css +34 -11
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +541 -0
- package/src/components/editor/errors/auto-fix.tsx +4 -8
- package/src/components/editor/errors/send-error-report-button.tsx +66 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +48 -15
- package/src/components/editor/file-tree/file-name-input.tsx +1 -0
- package/src/components/editor/file-tree/file-viewer.tsx +4 -2
- package/src/components/editor/file-tree/use-file-search.ts +35 -21
- package/src/components/editor/header/__tests__/filename-form.test.tsx +1 -4
- package/src/components/editor/header/__tests__/status.test.tsx +5 -3
- package/src/components/editor/header/app-header.tsx +1 -1
- package/src/components/editor/header/filename-form.tsx +1 -1
- package/src/components/editor/header/status.tsx +44 -22
- package/src/components/editor/links/__tests__/cell-link.test.tsx +148 -0
- package/src/components/editor/links/cell-link-list.tsx +1 -1
- package/src/components/editor/links/cell-link.tsx +21 -11
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
- package/src/components/editor/navigation/__tests__/navigation.test.ts +108 -85
- package/src/components/editor/navigation/__tests__/selection.test.ts +43 -21
- package/src/components/editor/navigation/clipboard.ts +17 -14
- package/src/components/editor/navigation/focus-utils.ts +23 -4
- package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +17 -33
- package/src/components/editor/navigation/navigation.ts +74 -72
- package/src/components/editor/navigation/selection.ts +30 -29
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/notebook-cell.tsx +126 -152
- package/src/components/editor/output/MarimoErrorOutput.tsx +60 -7
- package/src/components/editor/output/MarimoTracebackOutput.tsx +54 -37
- package/src/components/editor/output/Outputs.css +8 -0
- package/src/components/editor/output/VideoOutput.tsx +6 -0
- package/src/components/editor/output/__tests__/VideoOutput.test.tsx +131 -0
- package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
- package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
- package/src/components/editor/output/ansi-reduce.ts +36 -17
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
- package/src/components/editor/package-alert.tsx +14 -7
- package/src/components/editor/renderers/__tests__/add-cell-buttons.test.tsx +18 -0
- package/src/components/editor/renderers/cell-array.tsx +32 -100
- package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +28 -22
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -4
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +1 -1
- package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +4 -4
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
- package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +1 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +19 -37
- package/src/components/editor/stdin-blocking-alert.tsx +4 -2
- package/src/components/home/components.tsx +17 -31
- package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
- package/src/components/icons/large-spinner.tsx +3 -14
- package/src/components/icons/spinner.tsx +1 -1
- package/src/components/markdown/__tests__/markdown-renderer.test.tsx +32 -2
- package/src/components/markdown/markdown-renderer.tsx +43 -28
- package/src/components/mcp/mcp-status-indicator.tsx +18 -14
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/edit-page.tsx +19 -17
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +89 -0
- package/src/components/scratchpad/scratchpad.tsx +47 -33
- package/src/components/scratchpad/state.ts +7 -0
- package/src/components/slides/__tests__/minimap-actions.test.tsx +22 -29
- package/src/components/slides/__tests__/minimap.test.ts +38 -19
- package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +37 -0
- package/src/components/slides/minimap.tsx +22 -14
- package/src/components/slides/reveal-component.tsx +73 -36
- package/src/components/slides/reveal-slides.css +5 -4
- package/src/components/slides/slide-cell-view.tsx +37 -34
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/slides/slide-scroll-hint.tsx +3 -1
- package/src/components/slides/slide.tsx +3 -4
- package/src/components/sort/SortableCellsProvider.tsx +8 -25
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +46 -42
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/__tests__/fullscreen.test.tsx +44 -2
- package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/components/ui/fullscreen.tsx +25 -1
- package/src/components/ui/range-slider.tsx +22 -9
- package/src/components/ui/toast.tsx +1 -1
- package/src/core/MarimoApp.tsx +3 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +89 -608
- package/src/core/ai/context/context.ts +2 -0
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
- package/src/core/ai/context/providers/__tests__/cell.test.ts +49 -0
- package/src/core/ai/context/providers/cell-output.ts +2 -2
- package/src/core/ai/context/providers/cell.ts +54 -0
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/staged-cells.ts +56 -323
- package/src/core/ai/state.ts +3 -0
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +40 -88
- package/src/core/ai/tools/__tests__/registry.test.ts +17 -0
- package/src/core/ai/tools/base.ts +18 -15
- package/src/core/ai/tools/edit-notebook-tool.ts +86 -80
- package/src/core/ai/tools/registry.ts +13 -10
- package/src/core/ai/tools/sample-tool.ts +6 -7
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -529
- package/src/core/cells/__tests__/actions.test.ts +623 -35
- package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
- package/src/core/cells/__tests__/arrange.test.ts +432 -0
- package/src/core/cells/__tests__/cell.test.ts +148 -150
- package/src/core/cells/__tests__/cells.test.ts +408 -2891
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/document.test.ts +158 -0
- package/src/core/cells/__tests__/editor.test.ts +57 -0
- package/src/core/cells/__tests__/error-report.test.ts +139 -0
- package/src/core/cells/__tests__/flush-document.test.ts +40 -0
- package/src/core/cells/__tests__/harness.ts +106 -0
- package/src/core/cells/__tests__/layout.test.ts +176 -0
- package/src/core/cells/__tests__/logs.test.ts +0 -13
- package/src/core/cells/__tests__/notebook-outline.test.ts +122 -0
- package/src/core/cells/__tests__/outputs.test.tsx +71 -53
- package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
- package/src/core/cells/__tests__/session.test.ts +594 -210
- package/src/core/cells/__tests__/utils.test.ts +135 -337
- package/src/core/cells/actions.ts +677 -6
- package/src/core/cells/add-missing-import.ts +47 -43
- package/src/core/cells/arrange.ts +529 -0
- package/src/core/cells/cell.ts +78 -146
- package/src/core/cells/cells.ts +109 -1460
- package/src/core/cells/columns.ts +38 -0
- package/src/core/cells/document.ts +167 -0
- package/src/core/cells/edit.ts +30 -0
- package/src/core/cells/editor.ts +82 -0
- package/src/core/cells/error-report.ts +63 -0
- package/src/core/cells/focus.ts +27 -6
- package/src/core/cells/layout.ts +221 -0
- package/src/core/cells/outputs.ts +12 -28
- package/src/core/cells/pending-delete-service.ts +8 -14
- package/src/core/cells/scrollCellIntoView.ts +6 -0
- package/src/core/cells/session.ts +184 -59
- package/src/core/cells/types.ts +21 -51
- package/src/core/cells/utils.ts +85 -87
- package/src/core/codemirror/__tests__/format.test.ts +0 -34
- package/src/core/codemirror/__tests__/setup.test.ts +61 -29
- package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
- package/src/core/codemirror/ai/resources.ts +1 -1
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +2 -6
- package/src/core/codemirror/cells/extensions.ts +18 -30
- package/src/core/codemirror/cells/state.ts +2 -6
- package/src/core/codemirror/cm.ts +5 -1
- package/src/core/codemirror/config/types.ts +1 -1
- package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +6 -7
- package/src/core/codemirror/copilot/getCodes.ts +2 -2
- package/src/core/codemirror/format.ts +6 -23
- package/src/core/codemirror/keymaps/vim.ts +4 -8
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
- package/src/core/codemirror/language/cell-code.ts +114 -0
- package/src/core/codemirror/language/extension.ts +52 -35
- package/src/core/codemirror/language/languages/markdown.ts +8 -6
- package/src/core/codemirror/language/languages/python.ts +19 -13
- package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/language/utils.ts +9 -39
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
- package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
- package/src/core/codemirror/lsp/utils.ts +1 -1
- package/src/core/codemirror/misc/__tests__/paste.test.ts +3 -1
- package/src/core/codemirror/misc/paste.ts +1 -1
- package/src/core/codemirror/placeholder/__tests__/extensions.test.ts +75 -0
- package/src/core/codemirror/placeholder/extensions.ts +80 -19
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/readonly/extension.ts +2 -2
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/config/__tests__/app-config.test.ts +64 -0
- package/src/core/config/__tests__/config-schema.test.ts +56 -6
- package/src/core/config/config-schema.ts +17 -4
- package/src/core/config/config.ts +65 -20
- package/src/core/config/feature-flag.tsx +0 -2
- package/src/core/config/pair.ts +5 -3
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/documentation/doc-lookup.ts +1 -1
- package/src/core/dom/outline.ts +4 -1
- package/src/core/edit-app.tsx +22 -28
- package/src/core/errors/__tests__/error-entries.test.ts +40 -1
- package/src/core/errors/error-entries.ts +6 -4
- package/src/core/executions/__tests__/atoms.test.ts +98 -0
- package/src/core/executions/__tests__/freshness.test.ts +482 -0
- package/src/core/executions/__tests__/hooks.test.tsx +151 -0
- package/src/core/executions/__tests__/output.test.ts +266 -0
- package/src/core/executions/__tests__/select.test.ts +268 -0
- package/src/core/executions/atoms.ts +263 -0
- package/src/core/executions/freshness.ts +171 -0
- package/src/core/executions/hooks.ts +86 -0
- package/src/core/executions/index.ts +48 -0
- package/src/core/executions/output.ts +242 -0
- package/src/core/executions/select.ts +175 -0
- package/src/core/export/__tests__/hooks.test.ts +0 -5
- package/src/core/export/hooks.ts +1 -1
- package/src/core/export/layout.ts +2 -2
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/hotkeys/hotkeys.ts +2 -1
- package/src/core/islands/__tests__/bootstrap.test.ts +69 -17
- package/src/core/islands/__tests__/bridge.test.ts +85 -27
- package/src/core/islands/bootstrap.ts +49 -54
- package/src/core/islands/bridge.ts +84 -25
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/islands/components/__tests__/web-components.test.tsx +63 -0
- package/src/core/islands/components/output-wrapper.tsx +5 -5
- package/src/core/islands/components/web-components.tsx +12 -1
- package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
- package/src/core/islands/worker/controller.ts +4 -10
- package/src/core/islands/worker/worker.tsx +33 -33
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/kernel/__tests__/handlers.test.ts +7 -157
- package/src/core/kernel/handlers.ts +13 -79
- package/src/core/kernel/state.ts +0 -15
- package/src/core/lifecycle/render-policy.ts +12 -26
- package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
- package/src/core/meta/code-visibility.ts +18 -9
- package/src/core/network/__tests__/connection.test.ts +1 -1
- package/src/core/network/__tests__/requests-lazy.test.ts +6 -8
- package/src/core/network/connection-notice.ts +1 -1
- package/src/core/network/connection.ts +5 -3
- package/src/core/network/requests-lazy.ts +5 -8
- package/src/core/network/requests-network.ts +5 -31
- package/src/core/network/requests-static.ts +1 -4
- package/src/core/network/requests-toasting.tsx +1 -4
- package/src/core/network/types.ts +6 -14
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/notebook/__tests__/operations.test.ts +51 -0
- package/src/core/notebook/attachments.ts +38 -0
- package/src/core/notebook/document/__tests__/codemirror.test.ts +759 -0
- package/src/core/notebook/document/__tests__/draft.test.ts +363 -0
- package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
- package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
- package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/notebook/document/__tests__/model.test.ts +247 -0
- package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/notebook/document/__tests__/state.test.ts +459 -0
- package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
- package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
- package/src/core/notebook/document/__tests__/test-host.ts +247 -0
- package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
- package/src/core/notebook/document/__tests__/user.ts +61 -0
- package/src/core/notebook/document/codemirror.ts +216 -0
- package/src/core/notebook/document/draft.ts +502 -0
- package/src/core/notebook/document/hooks.tsx +118 -0
- package/src/core/notebook/document/index.ts +24 -0
- package/src/core/notebook/document/model.ts +102 -0
- package/src/core/notebook/document/select.ts +41 -0
- package/src/core/notebook/document/state.ts +378 -0
- package/src/core/notebook/document/sync.ts +369 -0
- package/src/core/notebook/index.ts +19 -0
- package/src/core/notebook/operations.ts +30 -0
- package/src/core/notebook/replica/AGENTS.md +11 -0
- package/src/core/notebook/replica/__tests__/attachments.test.ts +56 -0
- package/src/core/notebook/replica/__tests__/document.test.ts +126 -0
- package/src/core/notebook/replica/__tests__/executions.test.ts +200 -0
- package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
- package/src/core/notebook/replica/__tests__/replica.test.ts +559 -0
- package/src/core/notebook/replica/__tests__/results.test.ts +193 -0
- package/src/core/notebook/replica/__tests__/runtime.test.ts +78 -0
- package/src/core/notebook/replica/backend.ts +19 -0
- package/src/core/{websocket/types.ts → notebook/replica/connection.ts} +10 -15
- package/src/core/notebook/replica/index.ts +20 -0
- package/src/core/notebook/replica/replica.ts +336 -0
- package/src/core/notebook/replica/resources/attachments.ts +22 -0
- package/src/core/notebook/replica/resources/document.ts +101 -0
- package/src/core/notebook/replica/resources/executions.ts +157 -0
- package/src/core/notebook/replica/resources/results.ts +48 -0
- package/src/core/notebook/replica/resources/runtime.ts +14 -0
- package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
- package/src/core/packages/useSandboxController.ts +1 -1
- package/src/core/run-app.tsx +49 -51
- package/src/core/runtime/__tests__/adapter.test.ts +4 -4
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +33 -31
- package/src/core/runtime/adapter.ts +5 -5
- package/src/core/runtime/config.ts +2 -2
- package/src/core/runtime/runtime.ts +33 -32
- package/src/core/saving/__tests__/document.test.tsx +123 -0
- package/src/core/saving/__tests__/state.test.ts +111 -0
- package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
- package/src/core/saving/document.ts +33 -0
- package/src/core/saving/filename.ts +1 -1
- package/src/core/saving/save-component.tsx +39 -60
- package/src/core/saving/state.ts +38 -39
- package/src/core/saving/useAutoSave.ts +17 -53
- package/src/core/session/__tests__/backend.test.ts +236 -0
- package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +186 -0
- package/src/core/{websocket/__tests__/useMarimoKernelConnection.hook.test.tsx → session/__tests__/useNotebookSession.hook.test.tsx} +282 -183
- package/src/core/session/active-notebook.ts +28 -0
- package/src/core/session/backend.ts +123 -0
- package/src/core/session/embedded.ts +7 -0
- package/src/core/session/types.ts +17 -0
- package/src/core/session/useNotebookReplica.ts +74 -0
- package/src/core/{websocket/useMarimoKernelConnection.tsx → session/useNotebookSession.tsx} +123 -276
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/__tests__/files.test.ts +38 -10
- package/src/core/static/files.ts +2 -0
- package/src/core/{websocket/__tests__/useMarimoKernelConnection.test.ts → transports/__tests__/connection-state.test.ts} +16 -30
- package/src/core/transports/__tests__/server.test.ts +408 -0
- package/src/core/transports/__tests__/static.test.ts +340 -0
- package/src/core/transports/__tests__/wasm.test.ts +166 -0
- package/src/core/transports/connection-state.ts +63 -0
- package/src/core/transports/server.ts +152 -0
- package/src/core/transports/static.ts +173 -0
- package/src/core/transports/wasm.ts +97 -0
- package/src/core/vscode/__tests__/vscode-bindings.test.ts +125 -0
- package/src/core/vscode/vscode-bindings.ts +14 -2
- package/src/core/wasm/__tests__/bridge.test.ts +210 -64
- package/src/core/wasm/__tests__/worker.test.ts +188 -0
- package/src/core/wasm/bridge.ts +120 -73
- package/src/core/wasm/rpc.ts +15 -3
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +55 -51
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/wasm/worker/save-worker.ts +9 -10
- package/src/core/wasm/worker/types.ts +30 -18
- package/src/core/wasm/worker/worker.ts +118 -72
- package/src/css/app/Cell.css +7 -36
- package/src/css/app/codemirror.css +1 -1
- package/src/css/common.css +1 -1
- package/src/css/globals.css +72 -24
- package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
- package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
- package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
- package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
- package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
- package/src/hooks/__tests__/useScript.test.tsx +77 -0
- package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
- package/src/hooks/useAsyncData.ts +3 -3
- package/src/hooks/useDataSourceDiscovery.ts +6 -4
- package/src/hooks/useDebounce.ts +6 -10
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- package/src/hooks/useEventListener.ts +1 -2
- package/src/hooks/useInputHistory.ts +4 -7
- package/src/hooks/useInternalStateWithSync.ts +6 -6
- package/src/hooks/useResizeObserver.ts +4 -7
- package/src/hooks/useScript.ts +67 -70
- package/src/hooks/useStateForKey.ts +93 -0
- package/src/mount.tsx +23 -14
- package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
- package/src/plugins/core/RenderHTML.tsx +3 -5
- package/src/plugins/core/__test__/PluginSlot.test.tsx +202 -0
- package/src/plugins/core/__test__/RenderHTML-copy.test.tsx +60 -0
- package/src/plugins/core/__test__/registerReactComponent.test.ts +45 -0
- package/src/plugins/core/__test__/sanitize.test.ts +8 -0
- package/src/plugins/core/registerReactComponent.tsx +29 -29
- package/src/plugins/core/sanitize-html.ts +6 -0
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +34 -13
- package/src/plugins/impl/DataTablePlugin.tsx +69 -37
- package/src/plugins/impl/DropdownPlugin.tsx +2 -6
- package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataEditorPlugin.test.ts +93 -4
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +471 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +153 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- package/src/plugins/impl/anywidget/model.ts +3 -1
- package/src/plugins/impl/anywidget/registry.ts +18 -14
- package/src/plugins/impl/anywidget/runtime.ts +21 -9
- package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
- package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
- package/src/plugins/impl/chat/chat-ui.tsx +17 -15
- package/src/plugins/impl/code/any-language-editor.tsx +2 -2
- package/src/plugins/impl/common/error-banner.tsx +5 -3
- package/src/plugins/impl/data-editor/__tests__/column-types.test.ts +42 -0
- package/src/plugins/impl/data-editor/__tests__/editor-state.test.ts +52 -1
- package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +120 -4
- package/src/plugins/impl/data-editor/__tests__/glide-utils.test.ts +116 -0
- package/src/plugins/impl/data-editor/column-types.ts +55 -0
- package/src/plugins/impl/data-editor/editor-state.ts +18 -2
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +74 -12
- package/src/plugins/impl/data-editor/glide-utils.ts +39 -38
- package/src/plugins/impl/data-editor/types.ts +5 -0
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
- package/src/plugins/impl/data-frames/panel.tsx +44 -16
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
- package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
- package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
- package/src/plugins/impl/panel/utils.ts +17 -0
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
- package/src/plugins/impl/plotly/selection.ts +25 -19
- package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/DownloadPlugin.tsx +7 -11
- package/src/plugins/layout/LazyPlugin.tsx +7 -4
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/plugins/layout/__test__/DownloadPlugin.test.tsx +205 -0
- package/src/plugins/layout/__tests__/LazyPlugin.test.tsx +98 -0
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/cell-status.stories.tsx +29 -24
- package/src/stories/cell.stories.tsx +46 -46
- package/src/stories/data-table.stories.tsx +31 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/layout/vertical/one-column.stories.tsx +28 -42
- package/src/stories/runtime-story.tsx +23 -17
- package/src/stories/select.stories.tsx +2 -2
- package/src/stories/switchable-multi-select.stories.tsx +1 -1
- package/src/theme/__tests__/islands-theme.test.tsx +276 -0
- package/src/theme/namespace.tsx +4 -3
- package/src/theme/useTheme.ts +71 -41
- package/src/utils/__tests__/arrays.test.ts +35 -0
- package/src/utils/__tests__/batch-requests.test.ts +3 -3
- package/src/utils/__tests__/{createReducer.test.ts → createReducer.test.tsx} +127 -1
- package/src/utils/__tests__/dates.test.ts +116 -0
- package/src/utils/__tests__/download.test.tsx +183 -23
- package/src/utils/__tests__/numbers.test.ts +105 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +11 -2
- package/src/utils/blob.ts +1 -1
- package/src/utils/createReducer.ts +115 -79
- package/src/utils/dates.ts +94 -0
- package/src/utils/download.ts +67 -6
- package/src/utils/maps.ts +0 -3
- package/src/utils/numbers.ts +79 -18
- package/src/utils/objects.ts +4 -9
- package/src/utils/once.ts +19 -19
- package/src/utils/time.ts +10 -0
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/_baseMerge-BiGRwuqv.js +0 -165
- package/dist/any-language-editor-B9REGlD9.js +0 -76
- package/dist/architecture-7GRP2DOG-BWLylgiA.js +0 -3
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/assets/worker-HPY9fbhz.js +0 -114
- package/dist/classDiagram-ZZMXUADV-Bt98lkkv.js +0 -30
- package/dist/classDiagram-v2-VYDZK3BY-D9bfbcC3.js +0 -30
- package/dist/code-visibility-BCpXa0Xh.js +0 -138
- package/dist/cynefin-OW5HDTMX-obq-i80l.js +0 -3
- package/dist/error-entries-CzoYkIQZ.js +0 -56
- package/dist/eventmodeling-NTZA5JFV-D7nP7Uyu.js +0 -3
- package/dist/flowDiagram-HODETNUW-CAYbpJmV.js +0 -16
- package/dist/gitGraph-4MIJSDKK-Dy9uQXGh.js +0 -3
- package/dist/hasIn-o2Us0uVx.js +0 -132
- package/dist/html-to-image-CZY1pIZH.js +0 -3251
- package/dist/info-A6RAGUB7-DKoayiHY.js +0 -3
- package/dist/isArrayLikeObject-BZl-15ir.js +0 -450
- package/dist/isEmpty-BSZ1LaUo.js +0 -35
- package/dist/isSymbol-kQcfYbNX.js +0 -8
- package/dist/label-BDKF3Afc.js +0 -281
- package/dist/linear-Cnaq3Tfb.js +0 -204
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/packet-AYTQ26CC-Yw7ajchJ.js +0 -3
- package/dist/pick-CJeoxYOS.js +0 -51
- package/dist/pie-WAS4IAKB-BKdKOAkL.js +0 -3
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- package/dist/purify.es-DMv5zIkJ.js +0 -866
- package/dist/radar-RG4KPBEZ-ScR_D_Ts.js +0 -3
- package/dist/railroad-74A4TZTK-DQvPSdo5.js +0 -3
- package/dist/railroad-abnf-HS5TGJTU-CsJQG2O8.js +0 -3
- package/dist/railroad-ebnf-LZEXJU2U-BgEobkSn.js +0 -3
- package/dist/railroad-peg-WCYAUIDC-DjLAjofI.js +0 -3
- package/dist/select-BButFi-d.js +0 -1344
- package/dist/stateDiagram-v2-MP3YSRHH-CISYxma6.js +0 -30
- package/dist/swimlanesDiagram-VR7AAH4N-c8G5pGxC.js +0 -30
- package/dist/toast-B9UMEi8u.js +0 -1830
- package/dist/treeView-Q6P3EWNA-DuRV97YF.js +0 -3
- package/dist/treemap-WGGIJYW6-AsLq-uwC.js +0 -3
- package/dist/use-restore-focus-BEM7sFWl.js +0 -6369
- package/dist/useLifecycle-j7D9uD1o.js +0 -169
- package/dist/useTheme-CRnjkku0.js +0 -904
- package/dist/wardley-WFR3VGLG-Na-tFhQJ.js +0 -3
- package/src/components/chat/reasoning-accordion.tsx +0 -61
- package/src/components/chat/tool-call/tool-error-card.tsx +0 -81
- package/src/components/chat/tool-call/tool-history-row.tsx +0 -174
- package/src/components/editor/ai/__tests__/staged-cell-submission.test.ts +0 -106
- package/src/components/editor/ai/add-cell-with-ai.tsx +0 -506
- package/src/components/editor/ai/staged-cell-submission.ts +0 -46
- package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +0 -64
- package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +0 -50
- package/src/components/editor/chrome/wrapper/footer-items/rtc-status.tsx +0 -65
- package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
- package/src/components/editor/navigation/state.ts +0 -65
- package/src/components/icons/loading-ellipsis.tsx +0 -46
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +0 -656
- package/src/core/ai/tools/run-cells-tool.ts +0 -303
- package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
- package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
- package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
- package/src/core/cells/document-changes.ts +0 -944
- package/src/core/codemirror/rtc/extension.ts +0 -453
- package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +0 -52
- package/src/core/codemirror/rtc/loro/awareness.ts +0 -531
- package/src/core/codemirror/rtc/loro/colors.ts +0 -38
- package/src/core/codemirror/rtc/loro/sync.ts +0 -168
- package/src/core/host/AGENTS.md +0 -6
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/rtc/state.ts +0 -34
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/wasm/worker/message-buffer.ts +0 -33
- package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
- package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
- package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
- package/src/core/websocket/transports/basic.ts +0 -102
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -61
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useWebSocket.tsx +0 -88
- package/src/utils/__tests__/id-tree.test.ts +0 -2145
- package/src/utils/id-tree.tsx +0 -1134
- /package/src/core/{websocket → session}/connection-utils.ts +0 -0
|
@@ -4,29 +4,32 @@ import { python } from "@codemirror/lang-python";
|
|
|
4
4
|
import { EditorState } from "@codemirror/state";
|
|
5
5
|
import { EditorView } from "@codemirror/view";
|
|
6
6
|
import { createStore } from "jotai";
|
|
7
|
+
import { createRef } from "react";
|
|
7
8
|
import {
|
|
8
9
|
afterAll,
|
|
9
|
-
afterEach,
|
|
10
10
|
beforeAll,
|
|
11
|
+
afterEach,
|
|
11
12
|
beforeEach,
|
|
12
13
|
describe,
|
|
13
14
|
expect,
|
|
14
15
|
it,
|
|
15
16
|
vi,
|
|
16
17
|
} from "vitest";
|
|
18
|
+
import { MockExecutions } from "@/__mocks__/executions";
|
|
19
|
+
import {
|
|
20
|
+
notebookQueuedOrRunningCountAtom,
|
|
21
|
+
submitCells,
|
|
22
|
+
} from "@/core/executions";
|
|
23
|
+
import { store } from "@/core/state/jotai";
|
|
17
24
|
import { MockNotebook } from "@/__mocks__/notebook";
|
|
18
25
|
import { cellId } from "@/__tests__/branded";
|
|
19
26
|
import type { CellHandle } from "@/components/editor/notebook-cell";
|
|
20
|
-
import { CellId, SCRATCH_CELL_ID
|
|
27
|
+
import { CellId, SCRATCH_CELL_ID } from "@/core/cells/ids";
|
|
21
28
|
import { foldAllBulk, unfoldAllBulk } from "@/core/codemirror/editing/commands";
|
|
22
29
|
import { adaptiveLanguageConfiguration } from "@/core/codemirror/language/extension";
|
|
23
30
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
24
31
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
25
|
-
import {
|
|
26
|
-
type CollapsibleTree,
|
|
27
|
-
MultiColumn,
|
|
28
|
-
type CellColumnId,
|
|
29
|
-
} from "@/utils/id-tree";
|
|
32
|
+
import type { CellConfig } from "@/core/network/types";
|
|
30
33
|
import type { Seconds } from "@/utils/time";
|
|
31
34
|
import {
|
|
32
35
|
exportedForTesting,
|
|
@@ -34,13 +37,12 @@ import {
|
|
|
34
37
|
type NotebookState,
|
|
35
38
|
notebookAtom,
|
|
36
39
|
} from "../cells";
|
|
37
|
-
import { exportedForTesting as documentTransactionTestExports } from "../document-changes";
|
|
38
40
|
import {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
type CellData,
|
|
42
|
+
createCell,
|
|
43
|
+
createCellConfig,
|
|
44
|
+
createCellRuntimeState,
|
|
45
|
+
} from "../types";
|
|
44
46
|
|
|
45
47
|
vi.mock("@/core/codemirror/editing/commands", () => ({
|
|
46
48
|
foldAllBulk: vi.fn(),
|
|
@@ -60,9 +62,6 @@ vi.mock("../scrollCellIntoView", async (importOriginal) => {
|
|
|
60
62
|
};
|
|
61
63
|
});
|
|
62
64
|
|
|
63
|
-
const FIRST_COLUMN = 0;
|
|
64
|
-
const SECOND_COLUMN = 1;
|
|
65
|
-
|
|
66
65
|
const { initialNotebookState, reducer, createActions } = exportedForTesting;
|
|
67
66
|
|
|
68
67
|
function formatCells(notebook: NotebookState) {
|
|
@@ -78,14 +77,7 @@ function formatCells(notebook: NotebookState) {
|
|
|
78
77
|
const cells = cellsId.map((cellId) => cellData[cellId]);
|
|
79
78
|
return cells.map((cell) => printCell(cell)).join("\n\n");
|
|
80
79
|
};
|
|
81
|
-
|
|
82
|
-
return `> col ${columnIdx}\n${printCells(column.inOrderIds)}`;
|
|
83
|
-
};
|
|
84
|
-
const columns = cellIds.getColumns();
|
|
85
|
-
if (columns.length > 1) {
|
|
86
|
-
return wrap(columns.map(printColumn).join("\n\n"));
|
|
87
|
-
}
|
|
88
|
-
return wrap(printCells(cellIds.inOrderIds));
|
|
80
|
+
return wrap(printCells(cellIds));
|
|
89
81
|
}
|
|
90
82
|
|
|
91
83
|
function createEditor(content: string) {
|
|
@@ -121,8 +113,7 @@ describe("cell reducer", () => {
|
|
|
121
113
|
let cells: ReturnType<typeof flattenTopLevelNotebookCells>;
|
|
122
114
|
let firstCellId: CellId;
|
|
123
115
|
|
|
124
|
-
const
|
|
125
|
-
state = reducer(state, action);
|
|
116
|
+
const mountEditors = () => {
|
|
126
117
|
for (const [cellIdString, handle] of Object.entries(state.cellHandles)) {
|
|
127
118
|
// @ts-expect-error - Typescript Object.entries doesn't know that keys are CellId
|
|
128
119
|
const cid: CellId = cellIdString;
|
|
@@ -136,7 +127,83 @@ describe("cell reducer", () => {
|
|
|
136
127
|
}
|
|
137
128
|
}
|
|
138
129
|
cells = flattenTopLevelNotebookCells(state);
|
|
139
|
-
}
|
|
130
|
+
};
|
|
131
|
+
const actions = createActions((action) => {
|
|
132
|
+
state = reducer(state, action);
|
|
133
|
+
mountEditors();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
/** Put a cell into the notebook the way the document would. */
|
|
137
|
+
function seedCell({
|
|
138
|
+
cellId,
|
|
139
|
+
before,
|
|
140
|
+
code = "",
|
|
141
|
+
name,
|
|
142
|
+
config,
|
|
143
|
+
newCellId,
|
|
144
|
+
hideCode,
|
|
145
|
+
autoFocus = true,
|
|
146
|
+
}: {
|
|
147
|
+
cellId: CellId | "__end__";
|
|
148
|
+
before: boolean;
|
|
149
|
+
code?: string;
|
|
150
|
+
name?: string;
|
|
151
|
+
config?: CellConfig;
|
|
152
|
+
newCellId?: CellId;
|
|
153
|
+
hideCode?: boolean;
|
|
154
|
+
autoFocus?: boolean;
|
|
155
|
+
}): CellId {
|
|
156
|
+
const cellIndex =
|
|
157
|
+
cellId === "__end__"
|
|
158
|
+
? state.cellIds.length
|
|
159
|
+
: state.cellIds.indexOf(cellId);
|
|
160
|
+
const id = newCellId ?? CellId.create();
|
|
161
|
+
const cellIds = [...state.cellIds];
|
|
162
|
+
cellIds.splice(before ? cellIndex : cellIndex + 1, 0, id);
|
|
163
|
+
state = {
|
|
164
|
+
...state,
|
|
165
|
+
cellIds,
|
|
166
|
+
cellData: {
|
|
167
|
+
...state.cellData,
|
|
168
|
+
[id]: createCell({
|
|
169
|
+
id,
|
|
170
|
+
code,
|
|
171
|
+
name,
|
|
172
|
+
config: createCellConfig({
|
|
173
|
+
...config,
|
|
174
|
+
...(hideCode != null && { hide_code: hideCode }),
|
|
175
|
+
}),
|
|
176
|
+
}),
|
|
177
|
+
},
|
|
178
|
+
cellRuntime: { ...state.cellRuntime, [id]: createCellRuntimeState() },
|
|
179
|
+
cellHandles: { ...state.cellHandles, [id]: createRef() },
|
|
180
|
+
scrollKey: autoFocus ? id : null,
|
|
181
|
+
};
|
|
182
|
+
mountEditors();
|
|
183
|
+
return id;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Edit a cell's code as the document delivers it. */
|
|
187
|
+
function editCode(cellId: CellId, code: string) {
|
|
188
|
+
const cells = state.cellIds.map((id) => {
|
|
189
|
+
const cell = state.cellData[id];
|
|
190
|
+
return {
|
|
191
|
+
id,
|
|
192
|
+
code: id === cellId ? code : cell.code,
|
|
193
|
+
name: cell.name,
|
|
194
|
+
config: {
|
|
195
|
+
column: cell.config.column ?? null,
|
|
196
|
+
disabled: cell.config.disabled ?? false,
|
|
197
|
+
hide_code: cell.config.hide_code ?? false,
|
|
198
|
+
expand_output: cell.config.expand_output ?? false,
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
});
|
|
202
|
+
actions.reconcileDocument({
|
|
203
|
+
order: state.cellIds,
|
|
204
|
+
cells: new Map(cells.map((cell) => [cell.id, cell])),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
140
207
|
|
|
141
208
|
let i = 0;
|
|
142
209
|
const originalCreate = CellId.create.bind(CellId);
|
|
@@ -151,878 +218,235 @@ describe("cell reducer", () => {
|
|
|
151
218
|
i = 0;
|
|
152
219
|
|
|
153
220
|
state = initialNotebookState();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
firstCellId = state.cellIds.inOrderIds[0];
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
afterEach(() => {
|
|
160
|
-
documentTransactionTestExports.cancelPendingChanges();
|
|
221
|
+
seedCell({ cellId: "__end__", before: false });
|
|
222
|
+
firstCellId = state.cellIds[0];
|
|
161
223
|
});
|
|
162
224
|
|
|
163
225
|
afterAll(() => {
|
|
164
226
|
CellId.create = originalCreate;
|
|
165
227
|
});
|
|
166
228
|
|
|
167
|
-
it("can
|
|
168
|
-
|
|
169
|
-
cellId: firstCellId,
|
|
170
|
-
before: false,
|
|
171
|
-
});
|
|
229
|
+
it("can update a cell", () => {
|
|
230
|
+
editCode(firstCellId, "import numpy as np");
|
|
172
231
|
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
173
232
|
"
|
|
174
|
-
[0] ''
|
|
175
|
-
|
|
176
|
-
[1] ''
|
|
233
|
+
[0] 'import numpy as np'
|
|
177
234
|
"
|
|
178
235
|
`);
|
|
179
236
|
});
|
|
180
237
|
|
|
181
|
-
it("
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
238
|
+
it("keeps error evidence after an edit and a new queued run", () => {
|
|
239
|
+
const code = "raise ValueError('old failure')";
|
|
240
|
+
const output: OutputMessage = {
|
|
241
|
+
channel: "marimo-error",
|
|
242
|
+
mimetype: "application/vnd.marimo+error",
|
|
243
|
+
data: [
|
|
244
|
+
{
|
|
245
|
+
type: "exception",
|
|
246
|
+
msg: "old failure",
|
|
247
|
+
exception_type: "ValueError",
|
|
248
|
+
raising_cell: null,
|
|
249
|
+
traceback: "<pre>ValueError: old failure</pre>",
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
code,
|
|
253
|
+
timestamp: 1,
|
|
254
|
+
};
|
|
255
|
+
actions.handleCellMessage({
|
|
256
|
+
cell_id: firstCellId,
|
|
257
|
+
output,
|
|
258
|
+
console: {
|
|
259
|
+
channel: "stderr",
|
|
260
|
+
mimetype: "application/vnd.marimo+traceback",
|
|
261
|
+
data: "<pre>ValueError: old failure</pre>",
|
|
262
|
+
code,
|
|
263
|
+
timestamp: 1,
|
|
264
|
+
},
|
|
265
|
+
status: "idle",
|
|
266
|
+
timestamp: 1,
|
|
186
267
|
});
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
268
|
+
editCode(firstCellId, "print('new code')");
|
|
269
|
+
actions.prepareForRun({ cellId: firstCellId });
|
|
270
|
+
actions.handleCellMessage({
|
|
271
|
+
cell_id: firstCellId,
|
|
272
|
+
output: null,
|
|
273
|
+
console: null,
|
|
274
|
+
status: "queued",
|
|
275
|
+
timestamp: 2,
|
|
276
|
+
});
|
|
277
|
+
const runtime = state.cellRuntime[firstCellId];
|
|
278
|
+
expect(runtime.output).toEqual(output);
|
|
279
|
+
expect(runtime.consoleOutputs[0].code).toBe(code);
|
|
280
|
+
expect(runtime.consoleOutputs[0].data).toContain("old failure");
|
|
281
|
+
});
|
|
190
282
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
283
|
+
it("can run cell and receive cell messages", () => {
|
|
284
|
+
// HAPPY PATH
|
|
285
|
+
/////////////////
|
|
286
|
+
// Initial state
|
|
287
|
+
let cell = cells[0];
|
|
288
|
+
expect(cell).toMatchSnapshot("initial state");
|
|
194
289
|
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
expect(
|
|
199
|
-
});
|
|
290
|
+
// Update code
|
|
291
|
+
editCode(firstCellId, "import marimo as mo");
|
|
292
|
+
cell = cells[0];
|
|
293
|
+
expect(cell).toMatchSnapshot("code edited");
|
|
200
294
|
|
|
201
|
-
|
|
202
|
-
actions.
|
|
295
|
+
// Prepare for run
|
|
296
|
+
actions.prepareForRun({
|
|
203
297
|
cellId: firstCellId,
|
|
204
|
-
before: true,
|
|
205
298
|
});
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
[1] ''
|
|
299
|
+
cell = cells[0];
|
|
300
|
+
expect(cell).toMatchSnapshot("prepared for run");
|
|
209
301
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
302
|
+
// Receive queued messages
|
|
303
|
+
actions.handleCellMessage({
|
|
304
|
+
cell_id: firstCellId,
|
|
305
|
+
output: undefined,
|
|
306
|
+
console: null,
|
|
307
|
+
status: "queued",
|
|
308
|
+
timestamp: new Date(10).getTime() as Seconds,
|
|
309
|
+
});
|
|
310
|
+
cell = cells[0];
|
|
311
|
+
expect(cell).toMatchSnapshot("queued message received");
|
|
214
312
|
|
|
215
|
-
|
|
216
|
-
actions.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
313
|
+
// Receive running messages
|
|
314
|
+
actions.handleCellMessage({
|
|
315
|
+
cell_id: firstCellId,
|
|
316
|
+
output: undefined,
|
|
317
|
+
console: null,
|
|
318
|
+
status: "running",
|
|
319
|
+
timestamp: new Date(20).getTime() as Seconds,
|
|
222
320
|
});
|
|
223
|
-
|
|
224
|
-
expect(
|
|
225
|
-
expect(state.cellData[newCellId].config.hide_code).toBe(true);
|
|
226
|
-
expect(state.cellData[newCellId].config.disabled).toBe(false);
|
|
227
|
-
});
|
|
321
|
+
cell = cells[0];
|
|
322
|
+
expect(cell).toMatchSnapshot("running message received");
|
|
228
323
|
|
|
229
|
-
|
|
230
|
-
actions.
|
|
231
|
-
|
|
232
|
-
|
|
324
|
+
// Console messages shouldn't transition status
|
|
325
|
+
actions.handleCellMessage({
|
|
326
|
+
cell_id: firstCellId,
|
|
327
|
+
output: undefined,
|
|
328
|
+
console: {
|
|
329
|
+
channel: "stdout",
|
|
330
|
+
mimetype: "text/plain",
|
|
331
|
+
data: "hello!",
|
|
332
|
+
timestamp: 0,
|
|
333
|
+
},
|
|
334
|
+
status: undefined,
|
|
335
|
+
timestamp: new Date(22).getTime() as Seconds,
|
|
233
336
|
});
|
|
234
|
-
|
|
235
|
-
|
|
337
|
+
cell = cells[0];
|
|
338
|
+
expect(cell).toMatchSnapshot("console message received");
|
|
339
|
+
|
|
340
|
+
// Receive output messages
|
|
341
|
+
actions.handleCellMessage({
|
|
342
|
+
cell_id: firstCellId,
|
|
343
|
+
output: {
|
|
344
|
+
channel: "output",
|
|
345
|
+
mimetype: "text/plain",
|
|
346
|
+
data: "ok",
|
|
347
|
+
timestamp: 0,
|
|
348
|
+
},
|
|
349
|
+
console: {
|
|
350
|
+
channel: "stdout",
|
|
351
|
+
mimetype: "text/plain",
|
|
352
|
+
data: "hello!",
|
|
353
|
+
timestamp: 0,
|
|
354
|
+
},
|
|
355
|
+
status: "idle",
|
|
356
|
+
timestamp: new Date(33).getTime() as Seconds,
|
|
236
357
|
});
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
[1] ''
|
|
240
|
-
"
|
|
241
|
-
`);
|
|
358
|
+
cell = cells[0];
|
|
359
|
+
expect(cell).toMatchSnapshot("output received");
|
|
242
360
|
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
361
|
+
// EDITING BACK AND FORTH
|
|
362
|
+
/////////////////
|
|
363
|
+
// Update code again
|
|
364
|
+
editCode(firstCellId, "import marimo as mo\nimport numpy");
|
|
365
|
+
cell = cells[0];
|
|
366
|
+
expect(cell).toMatchSnapshot("code edited again");
|
|
248
367
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
368
|
+
// Update code should be unedited
|
|
369
|
+
editCode(firstCellId, "import marimo as mo");
|
|
370
|
+
cell = cells[0];
|
|
371
|
+
expect(cell).toMatchSnapshot("code reverted");
|
|
252
372
|
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
|
|
373
|
+
// Update code should be edited again
|
|
374
|
+
editCode(firstCellId, "import marimo as mo\nimport numpy");
|
|
375
|
+
cell = cells[0];
|
|
376
|
+
expect(cell).toMatchSnapshot("code changed after revert");
|
|
256
377
|
|
|
257
|
-
|
|
258
|
-
|
|
378
|
+
// ERROR RESPONSE
|
|
379
|
+
/////////////////
|
|
380
|
+
// Prepare for run
|
|
381
|
+
actions.prepareForRun({
|
|
259
382
|
cellId: firstCellId,
|
|
260
|
-
before: false,
|
|
261
|
-
code: `df = mo.sql("""SELECT * FROM table""")`,
|
|
262
383
|
});
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
384
|
+
cell = cells[0];
|
|
385
|
+
expect(cell.output).not.toBe(null); // keep old output
|
|
386
|
+
// Queue
|
|
387
|
+
actions.handleCellMessage({
|
|
388
|
+
cell_id: firstCellId,
|
|
389
|
+
output: undefined,
|
|
390
|
+
console: null,
|
|
391
|
+
status: "queued",
|
|
392
|
+
timestamp: new Date(40).getTime() as Seconds,
|
|
266
393
|
});
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
"
|
|
277
|
-
[0] ''
|
|
278
|
-
|
|
279
|
-
[2] 'df = mo.sql("""SELECT * FROM table""")'
|
|
280
|
-
"
|
|
281
|
-
`);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
it("can delete a Markdown cell and undo delete", () => {
|
|
285
|
-
const text = "The quick brown fox jumps over the lazy dog.";
|
|
286
|
-
actions.createNewCell({
|
|
287
|
-
cellId: firstCellId,
|
|
288
|
-
before: false,
|
|
289
|
-
code: `mo.md(r"""${text}""")`,
|
|
394
|
+
cell = cells[0];
|
|
395
|
+
expect(cell.output).not.toBe(null); // keep old output
|
|
396
|
+
// Running
|
|
397
|
+
actions.handleCellMessage({
|
|
398
|
+
cell_id: firstCellId,
|
|
399
|
+
output: undefined,
|
|
400
|
+
console: null,
|
|
401
|
+
status: "running",
|
|
402
|
+
timestamp: new Date(50).getTime() as Seconds,
|
|
290
403
|
});
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
404
|
+
cell = cells[0];
|
|
405
|
+
expect(cell.output).not.toBe(null); // keep old output
|
|
406
|
+
// Receive error
|
|
407
|
+
actions.handleCellMessage({
|
|
408
|
+
cell_id: firstCellId,
|
|
409
|
+
output: {
|
|
410
|
+
channel: "marimo-error",
|
|
411
|
+
mimetype: "application/vnd.marimo+error",
|
|
412
|
+
data: [
|
|
413
|
+
{ type: "exception", exception_type: "ValueError", msg: "Oh no!" },
|
|
414
|
+
],
|
|
415
|
+
timestamp: 0,
|
|
416
|
+
},
|
|
417
|
+
console: null,
|
|
418
|
+
status: "idle",
|
|
419
|
+
timestamp: new Date(61).getTime() as Seconds,
|
|
294
420
|
});
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
"
|
|
299
|
-
`);
|
|
300
|
-
|
|
301
|
-
// undo
|
|
302
|
-
actions.undoDeleteCell();
|
|
303
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
304
|
-
"
|
|
305
|
-
[0] ''
|
|
306
|
-
|
|
307
|
-
[2] 'mo.md(r"""The quick brown fox jumps over the lazy dog.""")'
|
|
308
|
-
"
|
|
309
|
-
`);
|
|
310
|
-
});
|
|
421
|
+
cell = cells[0];
|
|
422
|
+
expect(cell.output).not.toBe(null); // keep old output
|
|
423
|
+
expect(cell).toMatchSnapshot("error response received");
|
|
311
424
|
|
|
312
|
-
|
|
313
|
-
|
|
425
|
+
// INTERRUPT RESPONSE
|
|
426
|
+
/////////////////
|
|
427
|
+
// Prepare for run
|
|
428
|
+
actions.prepareForRun({
|
|
314
429
|
cellId: firstCellId,
|
|
315
|
-
before: false,
|
|
316
|
-
code: "x = 1",
|
|
317
430
|
});
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
//
|
|
321
|
-
actions.
|
|
322
|
-
|
|
323
|
-
|
|
431
|
+
cell = cells[0];
|
|
432
|
+
expect(cell.output).not.toBe(null); // keep old output
|
|
433
|
+
// Queue
|
|
434
|
+
actions.handleCellMessage({
|
|
435
|
+
cell_id: firstCellId,
|
|
436
|
+
output: undefined,
|
|
437
|
+
console: null,
|
|
438
|
+
status: "queued",
|
|
439
|
+
timestamp: new Date(40).getTime() as Seconds,
|
|
324
440
|
});
|
|
325
|
-
|
|
326
|
-
expect(
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const restoredCellId =
|
|
335
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
336
|
-
|
|
337
|
-
// Config should be preserved
|
|
338
|
-
expect(state.cellData[restoredCellId].config.hide_code).toBe(true);
|
|
339
|
-
expect(state.cellData[restoredCellId].config.disabled).toBe(true);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it("can update a cell", () => {
|
|
343
|
-
actions.updateCellCode({
|
|
344
|
-
cellId: firstCellId,
|
|
345
|
-
code: "import numpy as np",
|
|
346
|
-
formattingChange: false,
|
|
347
|
-
});
|
|
348
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
349
|
-
"
|
|
350
|
-
[0] 'import numpy as np'
|
|
351
|
-
"
|
|
352
|
-
`);
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it("can move a cell", () => {
|
|
356
|
-
actions.createNewCell({
|
|
357
|
-
cellId: firstCellId,
|
|
358
|
-
before: false,
|
|
359
|
-
});
|
|
360
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
361
|
-
"
|
|
362
|
-
[0] ''
|
|
363
|
-
|
|
364
|
-
[1] ''
|
|
365
|
-
"
|
|
366
|
-
`);
|
|
367
|
-
|
|
368
|
-
// move first cell to the end
|
|
369
|
-
actions.moveCell({
|
|
370
|
-
cellId: firstCellId,
|
|
371
|
-
before: false,
|
|
372
|
-
});
|
|
373
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
374
|
-
"
|
|
375
|
-
[1] ''
|
|
376
|
-
|
|
377
|
-
[0] ''
|
|
378
|
-
"
|
|
379
|
-
`);
|
|
380
|
-
|
|
381
|
-
// move it back
|
|
382
|
-
actions.moveCell({
|
|
383
|
-
cellId: firstCellId,
|
|
384
|
-
before: true,
|
|
385
|
-
});
|
|
386
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
387
|
-
"
|
|
388
|
-
[0] ''
|
|
389
|
-
|
|
390
|
-
[1] ''
|
|
391
|
-
"
|
|
392
|
-
`);
|
|
393
|
-
|
|
394
|
-
// Add a column breakpoint to test left/right movement
|
|
395
|
-
actions.addColumnBreakpoint({ cellId: cellId("1") });
|
|
396
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
397
|
-
"
|
|
398
|
-
> col 0
|
|
399
|
-
[0] ''
|
|
400
|
-
|
|
401
|
-
> col 1
|
|
402
|
-
[1] ''
|
|
403
|
-
"
|
|
404
|
-
`);
|
|
405
|
-
|
|
406
|
-
// Move cell right
|
|
407
|
-
actions.moveCell({
|
|
408
|
-
cellId: firstCellId,
|
|
409
|
-
direction: "right",
|
|
410
|
-
});
|
|
411
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
412
|
-
"
|
|
413
|
-
> col 0
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
> col 1
|
|
417
|
-
[0] ''
|
|
418
|
-
|
|
419
|
-
[1] ''
|
|
420
|
-
"
|
|
421
|
-
`);
|
|
422
|
-
|
|
423
|
-
// Move cell left
|
|
424
|
-
actions.moveCell({
|
|
425
|
-
cellId: firstCellId,
|
|
426
|
-
direction: "left",
|
|
427
|
-
});
|
|
428
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
429
|
-
"
|
|
430
|
-
> col 0
|
|
431
|
-
[0] ''
|
|
432
|
-
|
|
433
|
-
> col 1
|
|
434
|
-
[1] ''
|
|
435
|
-
"
|
|
436
|
-
`);
|
|
437
|
-
|
|
438
|
-
// Try to move cell left when it's already in leftmost column (should noop)
|
|
439
|
-
actions.moveCell({
|
|
440
|
-
cellId: firstCellId,
|
|
441
|
-
direction: "left",
|
|
442
|
-
});
|
|
443
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
444
|
-
"
|
|
445
|
-
> col 0
|
|
446
|
-
[0] ''
|
|
447
|
-
|
|
448
|
-
> col 1
|
|
449
|
-
[1] ''
|
|
450
|
-
"
|
|
451
|
-
`);
|
|
452
|
-
|
|
453
|
-
// Try to move cell right when it's already in rightmost column (should noop)
|
|
454
|
-
actions.moveCell({
|
|
455
|
-
cellId: cellId("1"),
|
|
456
|
-
direction: "right",
|
|
457
|
-
});
|
|
458
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
459
|
-
"
|
|
460
|
-
> col 0
|
|
461
|
-
[0] ''
|
|
462
|
-
|
|
463
|
-
> col 1
|
|
464
|
-
[1] ''
|
|
465
|
-
"
|
|
466
|
-
`);
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
it("can drag and drop a cell", () => {
|
|
470
|
-
actions.createNewCell({
|
|
471
|
-
cellId: firstCellId,
|
|
472
|
-
before: false,
|
|
473
|
-
});
|
|
474
|
-
actions.createNewCell({
|
|
475
|
-
cellId: cellId("1"),
|
|
476
|
-
before: false,
|
|
477
|
-
});
|
|
478
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
479
|
-
"
|
|
480
|
-
[0] ''
|
|
481
|
-
|
|
482
|
-
[1] ''
|
|
483
|
-
|
|
484
|
-
[2] ''
|
|
485
|
-
"
|
|
486
|
-
`);
|
|
487
|
-
|
|
488
|
-
// drag first cell to the end
|
|
489
|
-
actions.dropCellOverCell({
|
|
490
|
-
cellId: firstCellId,
|
|
491
|
-
overCellId: cellId("2"),
|
|
492
|
-
});
|
|
493
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
494
|
-
"
|
|
495
|
-
[1] ''
|
|
496
|
-
|
|
497
|
-
[2] ''
|
|
498
|
-
|
|
499
|
-
[0] ''
|
|
500
|
-
"
|
|
501
|
-
`);
|
|
502
|
-
|
|
503
|
-
// drag it back to the middle
|
|
504
|
-
actions.dropCellOverCell({
|
|
505
|
-
cellId: firstCellId,
|
|
506
|
-
overCellId: cellId("2"),
|
|
507
|
-
});
|
|
508
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
509
|
-
"
|
|
510
|
-
[1] ''
|
|
511
|
-
|
|
512
|
-
[0] ''
|
|
513
|
-
|
|
514
|
-
[2] ''
|
|
515
|
-
"
|
|
516
|
-
`);
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
it("can move a cell to an exact index within a column", () => {
|
|
520
|
-
actions.createNewCell({
|
|
521
|
-
cellId: firstCellId,
|
|
522
|
-
before: false,
|
|
523
|
-
});
|
|
524
|
-
actions.createNewCell({
|
|
525
|
-
cellId: cellId("1"),
|
|
526
|
-
before: false,
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
const columnId = state.cellIds.atOrThrow(0).id;
|
|
530
|
-
actions.moveCellToIndex({
|
|
531
|
-
cellId: firstCellId,
|
|
532
|
-
columnId,
|
|
533
|
-
index: 3,
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
537
|
-
"
|
|
538
|
-
[1] ''
|
|
539
|
-
|
|
540
|
-
[2] ''
|
|
541
|
-
|
|
542
|
-
[0] ''
|
|
543
|
-
"
|
|
544
|
-
`);
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
it("can move a cell to an exact index across columns", () => {
|
|
548
|
-
actions.createNewCell({
|
|
549
|
-
cellId: firstCellId,
|
|
550
|
-
before: false,
|
|
551
|
-
});
|
|
552
|
-
actions.createNewCell({
|
|
553
|
-
cellId: cellId("1"),
|
|
554
|
-
before: false,
|
|
555
|
-
});
|
|
556
|
-
actions.addColumnBreakpoint({ cellId: cellId("1") });
|
|
557
|
-
|
|
558
|
-
const secondColumnId = state.cellIds.atOrThrow(1).id;
|
|
559
|
-
actions.moveCellToIndex({
|
|
560
|
-
cellId: firstCellId,
|
|
561
|
-
columnId: secondColumnId,
|
|
562
|
-
index: 1,
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
566
|
-
"
|
|
567
|
-
> col 0
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
> col 1
|
|
571
|
-
[1] ''
|
|
572
|
-
|
|
573
|
-
[0] ''
|
|
574
|
-
|
|
575
|
-
[2] ''
|
|
576
|
-
"
|
|
577
|
-
`);
|
|
578
|
-
});
|
|
579
|
-
|
|
580
|
-
it("moveCellToIndex is a no-op when moving to the same position", () => {
|
|
581
|
-
actions.createNewCell({
|
|
582
|
-
cellId: firstCellId,
|
|
583
|
-
before: false,
|
|
584
|
-
});
|
|
585
|
-
actions.createNewCell({
|
|
586
|
-
cellId: cellId("1"),
|
|
587
|
-
before: false,
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
const columnId = state.cellIds.atOrThrow(0).id;
|
|
591
|
-
const before = formatCells(state);
|
|
592
|
-
|
|
593
|
-
actions.moveCellToIndex({
|
|
594
|
-
cellId: firstCellId,
|
|
595
|
-
columnId,
|
|
596
|
-
index: 0,
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
expect(formatCells(state)).toBe(before);
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
it("moveCellToIndex is a no-op for an invalid columnId", () => {
|
|
603
|
-
actions.createNewCell({
|
|
604
|
-
cellId: firstCellId,
|
|
605
|
-
before: false,
|
|
606
|
-
});
|
|
607
|
-
|
|
608
|
-
const before = formatCells(state);
|
|
609
|
-
|
|
610
|
-
actions.moveCellToIndex({
|
|
611
|
-
cellId: firstCellId,
|
|
612
|
-
columnId: "nonexistent-column" as CellColumnId,
|
|
613
|
-
index: 0,
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
expect(formatCells(state)).toBe(before);
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
it("can move multiple cells relative to target", () => {
|
|
620
|
-
actions.createNewCell({
|
|
621
|
-
cellId: firstCellId,
|
|
622
|
-
before: false,
|
|
623
|
-
});
|
|
624
|
-
actions.createNewCell({
|
|
625
|
-
cellId: cellId("1"),
|
|
626
|
-
before: false,
|
|
627
|
-
});
|
|
628
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
629
|
-
"
|
|
630
|
-
[0] ''
|
|
631
|
-
|
|
632
|
-
[1] ''
|
|
633
|
-
|
|
634
|
-
[2] ''
|
|
635
|
-
"
|
|
636
|
-
`);
|
|
637
|
-
|
|
638
|
-
// Move first two cells after the third
|
|
639
|
-
actions.moveCellsRelativeTo({
|
|
640
|
-
cellIds: [firstCellId, cellId("1")],
|
|
641
|
-
targetCellId: cellId("2"),
|
|
642
|
-
position: "after",
|
|
643
|
-
});
|
|
644
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
645
|
-
"
|
|
646
|
-
[2] ''
|
|
647
|
-
|
|
648
|
-
[0] ''
|
|
649
|
-
|
|
650
|
-
[1] ''
|
|
651
|
-
"
|
|
652
|
-
`);
|
|
653
|
-
});
|
|
654
|
-
|
|
655
|
-
it("can undo cut-paste (move with previousPlacements)", () => {
|
|
656
|
-
actions.createNewCell({
|
|
657
|
-
cellId: firstCellId,
|
|
658
|
-
before: false,
|
|
659
|
-
});
|
|
660
|
-
actions.createNewCell({
|
|
661
|
-
cellId: cellId("1"),
|
|
662
|
-
before: false,
|
|
663
|
-
});
|
|
664
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
665
|
-
"
|
|
666
|
-
[0] ''
|
|
667
|
-
|
|
668
|
-
[1] ''
|
|
669
|
-
|
|
670
|
-
[2] ''
|
|
671
|
-
"
|
|
672
|
-
`);
|
|
673
|
-
|
|
674
|
-
const col = state.cellIds.findWithId(firstCellId);
|
|
675
|
-
const previousPlacements = [
|
|
676
|
-
{
|
|
677
|
-
columnId: col.id,
|
|
678
|
-
index: col.indexOfOrThrow(
|
|
679
|
-
firstCellId,
|
|
680
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
681
|
-
},
|
|
682
|
-
{
|
|
683
|
-
columnId: col.id,
|
|
684
|
-
index: col.indexOfOrThrow(
|
|
685
|
-
cellId("1"),
|
|
686
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
687
|
-
},
|
|
688
|
-
];
|
|
689
|
-
|
|
690
|
-
actions.moveCellsRelativeTo({
|
|
691
|
-
cellIds: [firstCellId, cellId("1")],
|
|
692
|
-
targetCellId: cellId("2"),
|
|
693
|
-
position: "after",
|
|
694
|
-
previousPlacements,
|
|
695
|
-
});
|
|
696
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
697
|
-
"
|
|
698
|
-
[2] ''
|
|
699
|
-
|
|
700
|
-
[0] ''
|
|
701
|
-
|
|
702
|
-
[1] ''
|
|
703
|
-
"
|
|
704
|
-
`);
|
|
705
|
-
|
|
706
|
-
actions.undoDeleteCell();
|
|
707
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
708
|
-
"
|
|
709
|
-
[0] ''
|
|
710
|
-
|
|
711
|
-
[1] ''
|
|
712
|
-
|
|
713
|
-
[2] ''
|
|
714
|
-
"
|
|
715
|
-
`);
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
it("undo order: cut-paste then delete — first undo restores delete, second undo undoes move", () => {
|
|
719
|
-
actions.createNewCell({
|
|
720
|
-
cellId: firstCellId,
|
|
721
|
-
before: false,
|
|
722
|
-
});
|
|
723
|
-
actions.createNewCell({
|
|
724
|
-
cellId: cellId("1"),
|
|
725
|
-
before: false,
|
|
726
|
-
});
|
|
727
|
-
|
|
728
|
-
const col = state.cellIds.findWithId(firstCellId);
|
|
729
|
-
const previousPlacements = [
|
|
730
|
-
{
|
|
731
|
-
columnId: col.id,
|
|
732
|
-
index: col.indexOfOrThrow(
|
|
733
|
-
firstCellId,
|
|
734
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
735
|
-
},
|
|
736
|
-
{
|
|
737
|
-
columnId: col.id,
|
|
738
|
-
index: col.indexOfOrThrow(
|
|
739
|
-
cellId("1"),
|
|
740
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
741
|
-
},
|
|
742
|
-
];
|
|
743
|
-
|
|
744
|
-
actions.moveCellsRelativeTo({
|
|
745
|
-
cellIds: [firstCellId, cellId("1")],
|
|
746
|
-
targetCellId: cellId("2"),
|
|
747
|
-
position: "after",
|
|
748
|
-
previousPlacements,
|
|
749
|
-
});
|
|
750
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
751
|
-
"
|
|
752
|
-
[2] ''
|
|
753
|
-
|
|
754
|
-
[0] ''
|
|
755
|
-
|
|
756
|
-
[1] ''
|
|
757
|
-
"
|
|
758
|
-
`);
|
|
759
|
-
|
|
760
|
-
actions.deleteCell({ cellId: cellId("2") });
|
|
761
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
762
|
-
"
|
|
763
|
-
[0] ''
|
|
764
|
-
|
|
765
|
-
[1] ''
|
|
766
|
-
"
|
|
767
|
-
`);
|
|
768
|
-
|
|
769
|
-
actions.undoDeleteCell();
|
|
770
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
771
|
-
"
|
|
772
|
-
[3] ''
|
|
773
|
-
|
|
774
|
-
[0] ''
|
|
775
|
-
|
|
776
|
-
[1] ''
|
|
777
|
-
"
|
|
778
|
-
`);
|
|
779
|
-
|
|
780
|
-
actions.undoDeleteCell();
|
|
781
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
782
|
-
"
|
|
783
|
-
[0] ''
|
|
784
|
-
|
|
785
|
-
[1] ''
|
|
786
|
-
|
|
787
|
-
[3] ''
|
|
788
|
-
"
|
|
789
|
-
`);
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
it("can run cell and receive cell messages", () => {
|
|
793
|
-
// HAPPY PATH
|
|
794
|
-
/////////////////
|
|
795
|
-
// Initial state
|
|
796
|
-
let cell = cells[0];
|
|
797
|
-
expect(cell.status).toBe("idle");
|
|
798
|
-
expect(cell.lastCodeRun).toBe(null);
|
|
799
|
-
expect(cell.edited).toBe(false);
|
|
800
|
-
expect(cell).toMatchSnapshot("initial state");
|
|
801
|
-
|
|
802
|
-
// Update code
|
|
803
|
-
actions.updateCellCode({
|
|
804
|
-
cellId: firstCellId,
|
|
805
|
-
code: "import marimo as mo",
|
|
806
|
-
formattingChange: false,
|
|
807
|
-
});
|
|
808
|
-
cell = cells[0];
|
|
809
|
-
expect(cell.status).toBe("idle");
|
|
810
|
-
expect(cell.lastCodeRun).toBe(null);
|
|
811
|
-
expect(cell.edited).toBe(true);
|
|
812
|
-
expect(cell).toMatchSnapshot("code edited");
|
|
813
|
-
|
|
814
|
-
// Prepare for run
|
|
815
|
-
actions.prepareForRun({
|
|
816
|
-
cellId: firstCellId,
|
|
817
|
-
});
|
|
818
|
-
cell = cells[0];
|
|
819
|
-
expect(cell.status).toBe("queued");
|
|
820
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
821
|
-
expect(cell.edited).toBe(false);
|
|
822
|
-
expect(cell).toMatchSnapshot("prepared for run");
|
|
823
|
-
|
|
824
|
-
// Receive queued messages
|
|
825
|
-
actions.handleCellMessage({
|
|
826
|
-
cell_id: firstCellId,
|
|
827
|
-
output: undefined,
|
|
828
|
-
console: null,
|
|
829
|
-
status: "queued",
|
|
830
|
-
stale_inputs: null,
|
|
831
|
-
timestamp: new Date(10).getTime() as Seconds,
|
|
832
|
-
});
|
|
833
|
-
cell = cells[0];
|
|
834
|
-
expect(cell.status).toBe("queued");
|
|
835
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
836
|
-
expect(cell.edited).toBe(false);
|
|
837
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
838
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
839
|
-
expect(cell.lastRunStartTimestamp).toBe(null);
|
|
840
|
-
expect(cell).toMatchSnapshot("queued message received");
|
|
841
|
-
|
|
842
|
-
// Receive running messages
|
|
843
|
-
actions.handleCellMessage({
|
|
844
|
-
cell_id: firstCellId,
|
|
845
|
-
output: undefined,
|
|
846
|
-
console: null,
|
|
847
|
-
status: "running",
|
|
848
|
-
stale_inputs: null,
|
|
849
|
-
timestamp: new Date(20).getTime() as Seconds,
|
|
850
|
-
});
|
|
851
|
-
cell = cells[0];
|
|
852
|
-
expect(cell.status).toBe("running");
|
|
853
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
854
|
-
expect(cell.edited).toBe(false);
|
|
855
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
856
|
-
expect(cell.runStartTimestamp).toBe(20);
|
|
857
|
-
expect(cell.lastRunStartTimestamp).toBe(20);
|
|
858
|
-
expect(cell).toMatchSnapshot("running message received");
|
|
859
|
-
|
|
860
|
-
// Console messages shouldn't transition status
|
|
861
|
-
actions.handleCellMessage({
|
|
862
|
-
cell_id: firstCellId,
|
|
863
|
-
output: undefined,
|
|
864
|
-
console: {
|
|
865
|
-
channel: "stdout",
|
|
866
|
-
mimetype: "text/plain",
|
|
867
|
-
data: "hello!",
|
|
868
|
-
timestamp: 0,
|
|
869
|
-
},
|
|
870
|
-
status: undefined,
|
|
871
|
-
stale_inputs: null,
|
|
872
|
-
timestamp: new Date(22).getTime() as Seconds,
|
|
873
|
-
});
|
|
874
|
-
cell = cells[0];
|
|
875
|
-
expect(cell.status).toBe("running");
|
|
876
|
-
expect(cell.edited).toBe(false);
|
|
877
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
878
|
-
expect(cell.runStartTimestamp).toBe(20);
|
|
879
|
-
expect(cell.lastRunStartTimestamp).toBe(20);
|
|
880
|
-
expect(cell).toMatchSnapshot("console message received");
|
|
881
|
-
|
|
882
|
-
// Receive output messages
|
|
883
|
-
actions.handleCellMessage({
|
|
884
|
-
cell_id: firstCellId,
|
|
885
|
-
output: {
|
|
886
|
-
channel: "output",
|
|
887
|
-
mimetype: "text/plain",
|
|
888
|
-
data: "ok",
|
|
889
|
-
timestamp: 0,
|
|
890
|
-
},
|
|
891
|
-
console: {
|
|
892
|
-
channel: "stdout",
|
|
893
|
-
mimetype: "text/plain",
|
|
894
|
-
data: "hello!",
|
|
895
|
-
timestamp: 0,
|
|
896
|
-
},
|
|
897
|
-
status: "idle",
|
|
898
|
-
stale_inputs: null,
|
|
899
|
-
timestamp: new Date(33).getTime() as Seconds,
|
|
900
|
-
});
|
|
901
|
-
cell = cells[0];
|
|
902
|
-
expect(cell.status).toBe("idle");
|
|
903
|
-
expect(cell.edited).toBe(false);
|
|
904
|
-
expect(cell.runElapsedTimeMs).toBe(13_000);
|
|
905
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
906
|
-
expect(cell.lastRunStartTimestamp).toBe(20);
|
|
907
|
-
expect(cell).toMatchSnapshot("output received");
|
|
908
|
-
|
|
909
|
-
// EDITING BACK AND FORTH
|
|
910
|
-
/////////////////
|
|
911
|
-
// Update code again
|
|
912
|
-
actions.updateCellCode({
|
|
913
|
-
cellId: firstCellId,
|
|
914
|
-
code: "import marimo as mo\nimport numpy",
|
|
915
|
-
formattingChange: false,
|
|
916
|
-
});
|
|
917
|
-
cell = cells[0];
|
|
918
|
-
expect(cell.status).toBe("idle");
|
|
919
|
-
expect(cell.edited).toBe(true);
|
|
920
|
-
expect(cell).toMatchSnapshot("code edited again");
|
|
921
|
-
|
|
922
|
-
// Update code should be unedited
|
|
923
|
-
actions.updateCellCode({
|
|
924
|
-
cellId: firstCellId,
|
|
925
|
-
code: "import marimo as mo",
|
|
926
|
-
formattingChange: false,
|
|
927
|
-
});
|
|
928
|
-
cell = cells[0];
|
|
929
|
-
expect(cell.edited).toBe(false);
|
|
930
|
-
expect(cell).toMatchSnapshot("code reverted");
|
|
931
|
-
|
|
932
|
-
// Update code should be edited again
|
|
933
|
-
actions.updateCellCode({
|
|
934
|
-
cellId: firstCellId,
|
|
935
|
-
code: "import marimo as mo\nimport numpy",
|
|
936
|
-
formattingChange: false,
|
|
937
|
-
});
|
|
938
|
-
cell = cells[0];
|
|
939
|
-
expect(cell.status).toBe("idle");
|
|
940
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
941
|
-
expect(cell.edited).toBe(true);
|
|
942
|
-
expect(cell).toMatchSnapshot("code changed after revert");
|
|
943
|
-
|
|
944
|
-
// ERROR RESPONSE
|
|
945
|
-
/////////////////
|
|
946
|
-
// Prepare for run
|
|
947
|
-
actions.prepareForRun({
|
|
948
|
-
cellId: firstCellId,
|
|
949
|
-
});
|
|
950
|
-
cell = cells[0];
|
|
951
|
-
expect(cell.output).not.toBe(null); // keep old output
|
|
952
|
-
// Queue
|
|
953
|
-
actions.handleCellMessage({
|
|
954
|
-
cell_id: firstCellId,
|
|
955
|
-
output: undefined,
|
|
956
|
-
console: null,
|
|
957
|
-
status: "queued",
|
|
958
|
-
stale_inputs: null,
|
|
959
|
-
timestamp: new Date(40).getTime() as Seconds,
|
|
960
|
-
});
|
|
961
|
-
cell = cells[0];
|
|
962
|
-
expect(cell.output).not.toBe(null); // keep old output
|
|
963
|
-
// Running
|
|
964
|
-
actions.handleCellMessage({
|
|
965
|
-
cell_id: firstCellId,
|
|
966
|
-
output: undefined,
|
|
967
|
-
console: null,
|
|
968
|
-
status: "running",
|
|
969
|
-
stale_inputs: null,
|
|
970
|
-
timestamp: new Date(50).getTime() as Seconds,
|
|
971
|
-
});
|
|
972
|
-
cell = cells[0];
|
|
973
|
-
expect(cell.output).not.toBe(null); // keep old output
|
|
974
|
-
// Receive error
|
|
975
|
-
actions.handleCellMessage({
|
|
976
|
-
cell_id: firstCellId,
|
|
977
|
-
output: {
|
|
978
|
-
channel: "marimo-error",
|
|
979
|
-
mimetype: "application/vnd.marimo+error",
|
|
980
|
-
data: [
|
|
981
|
-
{ type: "exception", exception_type: "ValueError", msg: "Oh no!" },
|
|
982
|
-
],
|
|
983
|
-
timestamp: 0,
|
|
984
|
-
},
|
|
985
|
-
console: null,
|
|
986
|
-
status: "idle",
|
|
987
|
-
stale_inputs: null,
|
|
988
|
-
timestamp: new Date(61).getTime() as Seconds,
|
|
989
|
-
});
|
|
990
|
-
cell = cells[0];
|
|
991
|
-
expect(cell.output).not.toBe(null); // keep old output
|
|
992
|
-
expect(cell.status).toBe("idle");
|
|
993
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo\nimport numpy");
|
|
994
|
-
expect(cell.edited).toBe(false);
|
|
995
|
-
expect(cell.runElapsedTimeMs).toBe(11_000);
|
|
996
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
997
|
-
expect(cell).toMatchSnapshot("error response received");
|
|
998
|
-
|
|
999
|
-
// INTERRUPT RESPONSE
|
|
1000
|
-
/////////////////
|
|
1001
|
-
// Prepare for run
|
|
1002
|
-
actions.prepareForRun({
|
|
1003
|
-
cellId: firstCellId,
|
|
1004
|
-
});
|
|
1005
|
-
cell = cells[0];
|
|
1006
|
-
expect(cell.output).not.toBe(null); // keep old output
|
|
1007
|
-
// Queue
|
|
1008
|
-
actions.handleCellMessage({
|
|
1009
|
-
cell_id: firstCellId,
|
|
1010
|
-
output: undefined,
|
|
1011
|
-
console: null,
|
|
1012
|
-
status: "queued",
|
|
1013
|
-
stale_inputs: null,
|
|
1014
|
-
timestamp: new Date(40).getTime() as Seconds,
|
|
1015
|
-
});
|
|
1016
|
-
cell = cells[0];
|
|
1017
|
-
expect(cell.output).not.toBe(null); // keep old output
|
|
1018
|
-
// Running
|
|
1019
|
-
actions.handleCellMessage({
|
|
1020
|
-
cell_id: firstCellId,
|
|
1021
|
-
output: undefined,
|
|
1022
|
-
console: null,
|
|
1023
|
-
status: "running",
|
|
1024
|
-
stale_inputs: null,
|
|
1025
|
-
timestamp: new Date(50).getTime() as Seconds,
|
|
441
|
+
cell = cells[0];
|
|
442
|
+
expect(cell.output).not.toBe(null); // keep old output
|
|
443
|
+
// Running
|
|
444
|
+
actions.handleCellMessage({
|
|
445
|
+
cell_id: firstCellId,
|
|
446
|
+
output: undefined,
|
|
447
|
+
console: null,
|
|
448
|
+
status: "running",
|
|
449
|
+
timestamp: new Date(50).getTime() as Seconds,
|
|
1026
450
|
});
|
|
1027
451
|
cell = cells[0];
|
|
1028
452
|
expect(cell.output).not.toBe(null); // keep old output
|
|
@@ -1037,100 +461,23 @@ describe("cell reducer", () => {
|
|
|
1037
461
|
},
|
|
1038
462
|
console: null,
|
|
1039
463
|
status: "idle",
|
|
1040
|
-
stale_inputs: null,
|
|
1041
464
|
timestamp: new Date(61).getTime() as Seconds,
|
|
1042
465
|
});
|
|
1043
466
|
cell = cells[0];
|
|
1044
|
-
expect(cell.status).toBe("idle");
|
|
1045
|
-
expect(cell.lastCodeRun).toBe(cell.code);
|
|
1046
|
-
expect(cell.edited).toBe(false);
|
|
1047
|
-
expect(cell.runElapsedTimeMs).toBe(11_000);
|
|
1048
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
1049
467
|
expect(cell).toMatchSnapshot("interruption response received");
|
|
1050
468
|
});
|
|
1051
469
|
|
|
1052
|
-
it("errors reset status to idle", () => {
|
|
1053
|
-
// Initial state
|
|
1054
|
-
let cell = cells[0];
|
|
1055
|
-
expect(cell.status).toBe("idle");
|
|
1056
|
-
expect(cell.lastCodeRun).toBe(null);
|
|
1057
|
-
expect(cell.edited).toBe(false);
|
|
1058
|
-
expect(cell).toMatchSnapshot("initial state");
|
|
1059
|
-
|
|
1060
|
-
// Update code
|
|
1061
|
-
actions.updateCellCode({
|
|
1062
|
-
cellId: firstCellId,
|
|
1063
|
-
code: "import marimo as mo",
|
|
1064
|
-
formattingChange: false,
|
|
1065
|
-
});
|
|
1066
|
-
cell = cells[0];
|
|
1067
|
-
expect(cell.status).toBe("idle");
|
|
1068
|
-
expect(cell.lastCodeRun).toBe(null);
|
|
1069
|
-
expect(cell.edited).toBe(true);
|
|
1070
|
-
expect(cell).toMatchSnapshot("code edited");
|
|
1071
|
-
|
|
1072
|
-
// Prepare for run
|
|
1073
|
-
actions.prepareForRun({
|
|
1074
|
-
cellId: firstCellId,
|
|
1075
|
-
});
|
|
1076
|
-
cell = cells[0];
|
|
1077
|
-
expect(cell.status).toBe("queued");
|
|
1078
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
1079
|
-
expect(cell.edited).toBe(false);
|
|
1080
|
-
expect(cell).toMatchSnapshot("prepared for run");
|
|
1081
|
-
|
|
1082
|
-
// ERROR RESPONSE
|
|
1083
|
-
//
|
|
1084
|
-
// should reset status to idle
|
|
1085
|
-
/////////////////
|
|
1086
|
-
// Prepare for run
|
|
1087
|
-
actions.prepareForRun({
|
|
1088
|
-
cellId: firstCellId,
|
|
1089
|
-
});
|
|
1090
|
-
cell = cells[0];
|
|
1091
|
-
// Receive error
|
|
1092
|
-
actions.handleCellMessage({
|
|
1093
|
-
cell_id: firstCellId,
|
|
1094
|
-
output: {
|
|
1095
|
-
channel: "marimo-error",
|
|
1096
|
-
mimetype: "application/vnd.marimo+error",
|
|
1097
|
-
data: [
|
|
1098
|
-
{ type: "exception", exception_type: "SyntaxError", msg: "Oh no!" },
|
|
1099
|
-
],
|
|
1100
|
-
timestamp: 0,
|
|
1101
|
-
},
|
|
1102
|
-
console: null,
|
|
1103
|
-
stale_inputs: null,
|
|
1104
|
-
timestamp: new Date(61).getTime() as Seconds,
|
|
1105
|
-
});
|
|
1106
|
-
cell = cells[0];
|
|
1107
|
-
expect(cell.status).toBe("idle");
|
|
1108
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
1109
|
-
expect(cell.edited).toBe(false);
|
|
1110
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
1111
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
1112
|
-
expect(cell).toMatchSnapshot("error response received");
|
|
1113
|
-
});
|
|
1114
|
-
|
|
1115
470
|
it("can run a stale cell", () => {
|
|
1116
471
|
// Update code of first cell
|
|
1117
|
-
|
|
1118
|
-
cellId: firstCellId,
|
|
1119
|
-
code: "import marimo as mo",
|
|
1120
|
-
formattingChange: false,
|
|
1121
|
-
});
|
|
472
|
+
editCode(firstCellId, "import marimo as mo");
|
|
1122
473
|
// Add cell
|
|
1123
|
-
|
|
474
|
+
seedCell({
|
|
1124
475
|
cellId: firstCellId,
|
|
1125
476
|
before: false,
|
|
1126
477
|
});
|
|
1127
478
|
const secondCell = cells[1].id;
|
|
1128
479
|
// Update code
|
|
1129
|
-
|
|
1130
|
-
code: "mo.slider()",
|
|
1131
|
-
cellId: secondCell,
|
|
1132
|
-
formattingChange: false,
|
|
1133
|
-
});
|
|
480
|
+
editCode(secondCell, "mo.slider()");
|
|
1134
481
|
|
|
1135
482
|
// Prepare for run
|
|
1136
483
|
actions.prepareForRun({
|
|
@@ -1143,15 +490,9 @@ describe("cell reducer", () => {
|
|
|
1143
490
|
output: undefined,
|
|
1144
491
|
console: null,
|
|
1145
492
|
status: "queued",
|
|
1146
|
-
stale_inputs: null,
|
|
1147
493
|
timestamp: new Date(10).getTime() as Seconds,
|
|
1148
494
|
});
|
|
1149
495
|
let cell = cells[1];
|
|
1150
|
-
expect(cell.status).toBe("queued");
|
|
1151
|
-
expect(cell.lastCodeRun).toBe("mo.slider()");
|
|
1152
|
-
expect(cell.edited).toBe(false);
|
|
1153
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
1154
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
1155
496
|
expect(cell).toMatchSnapshot("queued message received");
|
|
1156
497
|
|
|
1157
498
|
// Receive stale message
|
|
@@ -1160,105 +501,15 @@ describe("cell reducer", () => {
|
|
|
1160
501
|
output: undefined,
|
|
1161
502
|
console: null,
|
|
1162
503
|
status: undefined,
|
|
1163
|
-
stale_inputs: true,
|
|
1164
504
|
timestamp: new Date(20).getTime() as Seconds,
|
|
1165
505
|
});
|
|
1166
506
|
cell = cells[1];
|
|
1167
|
-
expect(cell.status).toBe("queued");
|
|
1168
|
-
expect(cell.lastCodeRun).toBe("mo.slider()");
|
|
1169
|
-
expect(cell.edited).toBe(false);
|
|
1170
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
1171
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
1172
507
|
expect(cell).toMatchSnapshot("stale inputs received");
|
|
1173
508
|
});
|
|
1174
509
|
|
|
1175
|
-
it("can format code and update cell", () => {
|
|
1176
|
-
const firstCellId = cells[0].id;
|
|
1177
|
-
actions.updateCellCode({
|
|
1178
|
-
cellId: firstCellId,
|
|
1179
|
-
code: "import marimo as mo",
|
|
1180
|
-
formattingChange: false,
|
|
1181
|
-
});
|
|
1182
|
-
let cell = cells[0];
|
|
1183
|
-
expect(cell.status).toBe("idle");
|
|
1184
|
-
expect(cell.lastCodeRun).toBe(null);
|
|
1185
|
-
expect(cell.edited).toBe(true);
|
|
1186
|
-
|
|
1187
|
-
// Run
|
|
1188
|
-
actions.prepareForRun({
|
|
1189
|
-
cellId: firstCellId,
|
|
1190
|
-
});
|
|
1191
|
-
actions.handleCellMessage({
|
|
1192
|
-
cell_id: firstCellId,
|
|
1193
|
-
output: {
|
|
1194
|
-
channel: "output",
|
|
1195
|
-
mimetype: "text/plain",
|
|
1196
|
-
data: "ok",
|
|
1197
|
-
timestamp: 0,
|
|
1198
|
-
},
|
|
1199
|
-
console: {
|
|
1200
|
-
channel: "stdout",
|
|
1201
|
-
mimetype: "text/plain",
|
|
1202
|
-
data: "hello!",
|
|
1203
|
-
timestamp: 0,
|
|
1204
|
-
},
|
|
1205
|
-
status: "idle",
|
|
1206
|
-
stale_inputs: null,
|
|
1207
|
-
timestamp: new Date(33).getTime() as Seconds,
|
|
1208
|
-
});
|
|
1209
|
-
|
|
1210
|
-
// Check steady state
|
|
1211
|
-
cell = cells[0];
|
|
1212
|
-
expect(cell.status).toBe("idle");
|
|
1213
|
-
expect(cell.edited).toBe(false);
|
|
1214
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
1215
|
-
|
|
1216
|
-
// Format code
|
|
1217
|
-
actions.updateCellCode({
|
|
1218
|
-
cellId: firstCellId,
|
|
1219
|
-
code: "import marimo as mo",
|
|
1220
|
-
formattingChange: true,
|
|
1221
|
-
});
|
|
1222
|
-
cell = cells[0];
|
|
1223
|
-
expect(cell.status).toBe("idle");
|
|
1224
|
-
expect(cell.lastCodeRun).toBe("import marimo as mo");
|
|
1225
|
-
expect(cell.edited).toBe(false);
|
|
1226
|
-
});
|
|
1227
|
-
|
|
1228
|
-
it("can update a cells config", () => {
|
|
1229
|
-
const firstCellId = cells[0].id;
|
|
1230
|
-
let cell = cells[0];
|
|
1231
|
-
// Starts empty
|
|
1232
|
-
expect(cell.config).toEqual({
|
|
1233
|
-
disabled: false,
|
|
1234
|
-
hide_code: false,
|
|
1235
|
-
column: null,
|
|
1236
|
-
expand_output: false,
|
|
1237
|
-
});
|
|
1238
|
-
|
|
1239
|
-
actions.updateCellConfig({
|
|
1240
|
-
cellId: firstCellId,
|
|
1241
|
-
config: { disabled: true },
|
|
1242
|
-
});
|
|
1243
|
-
cell = cells[0];
|
|
1244
|
-
expect(cell.config.disabled).toBe(true);
|
|
1245
|
-
|
|
1246
|
-
// Revert
|
|
1247
|
-
actions.updateCellConfig({
|
|
1248
|
-
cellId: firstCellId,
|
|
1249
|
-
config: { disabled: false },
|
|
1250
|
-
});
|
|
1251
|
-
cell = cells[0];
|
|
1252
|
-
expect(cell.config.disabled).toBe(false);
|
|
1253
|
-
});
|
|
1254
|
-
|
|
1255
510
|
it("can run a stopped cell", () => {
|
|
1256
511
|
// Update code of first cell
|
|
1257
|
-
|
|
1258
|
-
cellId: firstCellId,
|
|
1259
|
-
code: "mo.md('This has an ancestor that was stopped')",
|
|
1260
|
-
formattingChange: false,
|
|
1261
|
-
});
|
|
512
|
+
editCode(firstCellId, "mo.md('This has an ancestor that was stopped')");
|
|
1262
513
|
|
|
1263
514
|
// Prepare for run
|
|
1264
515
|
actions.prepareForRun({
|
|
@@ -1271,17 +522,9 @@ describe("cell reducer", () => {
|
|
|
1271
522
|
output: undefined,
|
|
1272
523
|
console: null,
|
|
1273
524
|
status: "queued",
|
|
1274
|
-
stale_inputs: null,
|
|
1275
525
|
timestamp: new Date(10).getTime() as Seconds,
|
|
1276
526
|
});
|
|
1277
527
|
let cell = cells[0];
|
|
1278
|
-
expect(cell.status).toBe("queued");
|
|
1279
|
-
expect(cell.lastCodeRun).toBe(
|
|
1280
|
-
"mo.md('This has an ancestor that was stopped')",
|
|
1281
|
-
);
|
|
1282
|
-
expect(cell.edited).toBe(false);
|
|
1283
|
-
expect(cell.runElapsedTimeMs).toBe(null);
|
|
1284
|
-
expect(cell.runStartTimestamp).toBe(null);
|
|
1285
528
|
expect(cell).toMatchSnapshot("queued message received");
|
|
1286
529
|
|
|
1287
530
|
// Receive idle message
|
|
@@ -1290,7 +533,6 @@ describe("cell reducer", () => {
|
|
|
1290
533
|
output: undefined,
|
|
1291
534
|
console: null,
|
|
1292
535
|
status: "idle",
|
|
1293
|
-
stale_inputs: null,
|
|
1294
536
|
timestamp: new Date(20).getTime() as Seconds,
|
|
1295
537
|
});
|
|
1296
538
|
cell = cells[0];
|
|
@@ -1313,16 +555,13 @@ describe("cell reducer", () => {
|
|
|
1313
555
|
},
|
|
1314
556
|
console: null,
|
|
1315
557
|
status: "idle",
|
|
1316
|
-
stale_inputs: null,
|
|
1317
558
|
timestamp: new Date(20).getTime() as Seconds,
|
|
1318
559
|
});
|
|
1319
560
|
cell = cells[0];
|
|
1320
|
-
expect(cell.status).toBe("idle");
|
|
1321
561
|
// oxlint-disable-next-line typescript/no-explicit-any no-unsafe-optional-chaining
|
|
1322
562
|
expect((cell.output?.data as any)[0].msg).toBe(
|
|
1323
563
|
"This cell wasn't run because an ancestor was stopped with `mo.stop`: ",
|
|
1324
564
|
);
|
|
1325
|
-
expect(cell.stopped).toBe(true);
|
|
1326
565
|
expect(cell).toMatchSnapshot("ancestor stopped");
|
|
1327
566
|
|
|
1328
567
|
// Receive queued message
|
|
@@ -1331,12 +570,9 @@ describe("cell reducer", () => {
|
|
|
1331
570
|
output: undefined,
|
|
1332
571
|
console: null,
|
|
1333
572
|
status: "queued",
|
|
1334
|
-
stale_inputs: null,
|
|
1335
573
|
timestamp: new Date(30).getTime() as Seconds,
|
|
1336
574
|
});
|
|
1337
575
|
cell = cells[0];
|
|
1338
|
-
expect(cell.status).toBe("queued");
|
|
1339
|
-
expect(cell.stopped).toBe(true);
|
|
1340
576
|
expect(cell).toMatchSnapshot("queued after stop");
|
|
1341
577
|
|
|
1342
578
|
// Receive running message
|
|
@@ -1345,12 +581,9 @@ describe("cell reducer", () => {
|
|
|
1345
581
|
output: undefined,
|
|
1346
582
|
console: null,
|
|
1347
583
|
status: "running",
|
|
1348
|
-
stale_inputs: null,
|
|
1349
584
|
timestamp: new Date(40).getTime() as Seconds,
|
|
1350
585
|
});
|
|
1351
586
|
cell = cells[0];
|
|
1352
|
-
expect(cell.status).toBe("running");
|
|
1353
|
-
expect(cell.stopped).toBe(false);
|
|
1354
587
|
expect(cell.output).toBe(null);
|
|
1355
588
|
expect(cell).toMatchSnapshot("running after stop");
|
|
1356
589
|
});
|
|
@@ -1377,7 +610,6 @@ describe("cell reducer", () => {
|
|
|
1377
610
|
|
|
1378
611
|
// Initial state
|
|
1379
612
|
let cell = cells[0];
|
|
1380
|
-
expect(cell.status).toBe("idle");
|
|
1381
613
|
expect(cell.consoleOutputs).toEqual([]);
|
|
1382
614
|
expect(cell).toMatchSnapshot("initial state");
|
|
1383
615
|
|
|
@@ -1386,7 +618,6 @@ describe("cell reducer", () => {
|
|
|
1386
618
|
cellId: firstCellId,
|
|
1387
619
|
});
|
|
1388
620
|
cell = cells[0];
|
|
1389
|
-
expect(cell.status).toBe("queued");
|
|
1390
621
|
expect(cell.consoleOutputs).toEqual([]);
|
|
1391
622
|
expect(cell).toMatchSnapshot("prepared for run");
|
|
1392
623
|
|
|
@@ -1396,11 +627,9 @@ describe("cell reducer", () => {
|
|
|
1396
627
|
output: undefined,
|
|
1397
628
|
console: null,
|
|
1398
629
|
status: "queued",
|
|
1399
|
-
stale_inputs: null,
|
|
1400
630
|
timestamp: new Date(10).getTime() as Seconds,
|
|
1401
631
|
});
|
|
1402
632
|
cell = cells[0];
|
|
1403
|
-
expect(cell.status).toBe("queued");
|
|
1404
633
|
expect(cell).toMatchSnapshot("queued message received");
|
|
1405
634
|
|
|
1406
635
|
// Receive running messages
|
|
@@ -1409,11 +638,9 @@ describe("cell reducer", () => {
|
|
|
1409
638
|
output: undefined,
|
|
1410
639
|
console: null,
|
|
1411
640
|
status: "running",
|
|
1412
|
-
stale_inputs: null,
|
|
1413
641
|
timestamp: new Date(20).getTime() as Seconds,
|
|
1414
642
|
});
|
|
1415
643
|
cell = cells[0];
|
|
1416
|
-
expect(cell.status).toBe("running");
|
|
1417
644
|
expect(cell).toMatchSnapshot("running message received");
|
|
1418
645
|
|
|
1419
646
|
// Add console
|
|
@@ -1422,16 +649,13 @@ describe("cell reducer", () => {
|
|
|
1422
649
|
output: undefined,
|
|
1423
650
|
console: STDOUT,
|
|
1424
651
|
status: undefined,
|
|
1425
|
-
stale_inputs: null,
|
|
1426
652
|
timestamp: new Date(22).getTime() as Seconds,
|
|
1427
653
|
});
|
|
1428
654
|
cell = cells[0];
|
|
1429
|
-
expect(cell.status).toBe("running");
|
|
1430
655
|
expect(cell).toMatchSnapshot("stdout received");
|
|
1431
656
|
|
|
1432
657
|
cell = cells[0];
|
|
1433
658
|
expect(cell.consoleOutputs[0]).toMatchObject(STDOUT);
|
|
1434
|
-
expect(cell.status).toBe("running");
|
|
1435
659
|
expect(cell).toMatchSnapshot("stdout verified");
|
|
1436
660
|
|
|
1437
661
|
// Ask via stdin
|
|
@@ -1440,13 +664,11 @@ describe("cell reducer", () => {
|
|
|
1440
664
|
output: undefined,
|
|
1441
665
|
console: STD_IN_1,
|
|
1442
666
|
status: undefined,
|
|
1443
|
-
stale_inputs: null,
|
|
1444
667
|
timestamp: new Date(22).getTime() as Seconds,
|
|
1445
668
|
});
|
|
1446
669
|
cell = cells[0];
|
|
1447
670
|
expect(cell.consoleOutputs[0]).toMatchObject(STDOUT);
|
|
1448
671
|
expect(cell.consoleOutputs[1]).toMatchObject(STD_IN_1);
|
|
1449
|
-
expect(cell.status).toBe("running");
|
|
1450
672
|
expect(cell).toMatchSnapshot("stdin requested");
|
|
1451
673
|
|
|
1452
674
|
// Response to stdin
|
|
@@ -1460,7 +682,6 @@ describe("cell reducer", () => {
|
|
|
1460
682
|
...STD_IN_1,
|
|
1461
683
|
response: "Marimo!",
|
|
1462
684
|
});
|
|
1463
|
-
expect(cell.status).toBe("running");
|
|
1464
685
|
expect(cell).toMatchSnapshot("stdin answered");
|
|
1465
686
|
|
|
1466
687
|
// Ask via stdin, again
|
|
@@ -1469,7 +690,6 @@ describe("cell reducer", () => {
|
|
|
1469
690
|
output: undefined,
|
|
1470
691
|
console: STD_IN_2,
|
|
1471
692
|
status: undefined,
|
|
1472
|
-
stale_inputs: null,
|
|
1473
693
|
timestamp: new Date(22).getTime() as Seconds,
|
|
1474
694
|
});
|
|
1475
695
|
cell = cells[0];
|
|
@@ -1478,7 +698,6 @@ describe("cell reducer", () => {
|
|
|
1478
698
|
{ ...STD_IN_1, response: "Marimo!" },
|
|
1479
699
|
STD_IN_2,
|
|
1480
700
|
]);
|
|
1481
|
-
expect(cell.status).toBe("running");
|
|
1482
701
|
expect(cell).toMatchSnapshot("second stdin requested");
|
|
1483
702
|
|
|
1484
703
|
// Interrupt, so we respond with ""
|
|
@@ -1492,11 +711,9 @@ describe("cell reducer", () => {
|
|
|
1492
711
|
},
|
|
1493
712
|
console: null,
|
|
1494
713
|
status: "idle",
|
|
1495
|
-
stale_inputs: null,
|
|
1496
714
|
timestamp: new Date(61).getTime() as Seconds,
|
|
1497
715
|
});
|
|
1498
716
|
cell = cells[0];
|
|
1499
|
-
expect(cell.status).toBe("idle");
|
|
1500
717
|
expect(cell.consoleOutputs).toMatchObject([
|
|
1501
718
|
STDOUT,
|
|
1502
719
|
{ ...STD_IN_1, response: "Marimo!" },
|
|
@@ -1516,7 +733,6 @@ describe("cell reducer", () => {
|
|
|
1516
733
|
output: undefined,
|
|
1517
734
|
console: prompt,
|
|
1518
735
|
status: "running",
|
|
1519
|
-
stale_inputs: null,
|
|
1520
736
|
timestamp: 1 as Seconds,
|
|
1521
737
|
});
|
|
1522
738
|
|
|
@@ -1527,7 +743,9 @@ describe("cell reducer", () => {
|
|
|
1527
743
|
response: secret,
|
|
1528
744
|
});
|
|
1529
745
|
|
|
1530
|
-
expect(cells[0].consoleOutputs).toEqual([
|
|
746
|
+
expect(cells[0].consoleOutputs).toEqual([
|
|
747
|
+
{ ...prompt, id: 1, response: "" },
|
|
748
|
+
]);
|
|
1531
749
|
expect(JSON.stringify(cells[0].consoleOutputs)).not.toContain(secret);
|
|
1532
750
|
});
|
|
1533
751
|
|
|
@@ -1546,7 +764,6 @@ describe("cell reducer", () => {
|
|
|
1546
764
|
output: undefined,
|
|
1547
765
|
console: null,
|
|
1548
766
|
status: "running",
|
|
1549
|
-
stale_inputs: null,
|
|
1550
767
|
timestamp: new Date(20).getTime() as Seconds,
|
|
1551
768
|
});
|
|
1552
769
|
actions.handleCellMessage({
|
|
@@ -1554,7 +771,6 @@ describe("cell reducer", () => {
|
|
|
1554
771
|
output: undefined,
|
|
1555
772
|
console: STDOUT,
|
|
1556
773
|
status: undefined,
|
|
1557
|
-
stale_inputs: null,
|
|
1558
774
|
timestamp: new Date(22).getTime() as Seconds,
|
|
1559
775
|
});
|
|
1560
776
|
|
|
@@ -1588,7 +804,6 @@ describe("cell reducer", () => {
|
|
|
1588
804
|
|
|
1589
805
|
// Initial state
|
|
1590
806
|
let cell = cells[0];
|
|
1591
|
-
expect(cell.status).toBe("idle");
|
|
1592
807
|
expect(cell.consoleOutputs).toEqual([]);
|
|
1593
808
|
expect(cell).toMatchSnapshot("initial state");
|
|
1594
809
|
|
|
@@ -1598,7 +813,6 @@ describe("cell reducer", () => {
|
|
|
1598
813
|
output: undefined,
|
|
1599
814
|
console: [OLD_STDOUT],
|
|
1600
815
|
status: undefined,
|
|
1601
|
-
stale_inputs: null,
|
|
1602
816
|
timestamp: new Date(1).getTime() as Seconds,
|
|
1603
817
|
});
|
|
1604
818
|
|
|
@@ -1607,7 +821,6 @@ describe("cell reducer", () => {
|
|
|
1607
821
|
cellId: firstCellId,
|
|
1608
822
|
});
|
|
1609
823
|
cell = cells[0];
|
|
1610
|
-
expect(cell.status).toBe("queued");
|
|
1611
824
|
expect(cell.consoleOutputs).toMatchObject([OLD_STDOUT]); // Old stays there until it starts running
|
|
1612
825
|
expect(cell).toMatchSnapshot("prepared for run");
|
|
1613
826
|
|
|
@@ -1617,11 +830,9 @@ describe("cell reducer", () => {
|
|
|
1617
830
|
output: undefined,
|
|
1618
831
|
console: null,
|
|
1619
832
|
status: "queued",
|
|
1620
|
-
stale_inputs: null,
|
|
1621
833
|
timestamp: new Date(10).getTime() as Seconds,
|
|
1622
834
|
});
|
|
1623
835
|
cell = cells[0];
|
|
1624
|
-
expect(cell.status).toBe("queued");
|
|
1625
836
|
expect(cell.consoleOutputs).toMatchObject([OLD_STDOUT]); // Old stays there until it starts running
|
|
1626
837
|
expect(cell).toMatchSnapshot("queued message received");
|
|
1627
838
|
|
|
@@ -1631,11 +842,9 @@ describe("cell reducer", () => {
|
|
|
1631
842
|
output: undefined,
|
|
1632
843
|
console: [], // Backend sends an empty array to clearu
|
|
1633
844
|
status: "running",
|
|
1634
|
-
stale_inputs: null,
|
|
1635
845
|
timestamp: new Date(20).getTime() as Seconds,
|
|
1636
846
|
});
|
|
1637
847
|
cell = cells[0];
|
|
1638
|
-
expect(cell.status).toBe("running");
|
|
1639
848
|
expect(cell.consoleOutputs).toMatchObject([]);
|
|
1640
849
|
expect(cell).toMatchSnapshot("console cleared while running");
|
|
1641
850
|
|
|
@@ -1644,611 +853,39 @@ describe("cell reducer", () => {
|
|
|
1644
853
|
cell_id: firstCellId,
|
|
1645
854
|
output: undefined,
|
|
1646
855
|
console: [STDOUT],
|
|
1647
|
-
status: "idle",
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
cell
|
|
1652
|
-
expect(cell
|
|
1653
|
-
expect(cell.status).toBe("idle");
|
|
1654
|
-
expect(cell).toMatchSnapshot("console received while idle");
|
|
1655
|
-
});
|
|
1656
|
-
|
|
1657
|
-
it("can send a cell to the top", () => {
|
|
1658
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
1659
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
1660
|
-
actions.sendToTop({ cellId: cellId("2") });
|
|
1661
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
1662
|
-
"
|
|
1663
|
-
[2] ''
|
|
1664
|
-
|
|
1665
|
-
[0] ''
|
|
1666
|
-
|
|
1667
|
-
[1] ''
|
|
1668
|
-
"
|
|
1669
|
-
`);
|
|
1670
|
-
});
|
|
1671
|
-
|
|
1672
|
-
it("can send a cell to the bottom", () => {
|
|
1673
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
1674
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
1675
|
-
actions.sendToBottom({ cellId: firstCellId });
|
|
1676
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
1677
|
-
"
|
|
1678
|
-
[1] ''
|
|
1679
|
-
|
|
1680
|
-
[2] ''
|
|
1681
|
-
|
|
1682
|
-
[0] ''
|
|
1683
|
-
"
|
|
1684
|
-
`);
|
|
1685
|
-
});
|
|
1686
|
-
|
|
1687
|
-
it("can focus cells", () => {
|
|
1688
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
1689
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
1690
|
-
|
|
1691
|
-
actions.focusCell({ cellId: cellId("1"), where: "before" });
|
|
1692
|
-
expect(focusAndScrollCellIntoView).toHaveBeenCalledWith(
|
|
1693
|
-
expect.objectContaining({
|
|
1694
|
-
cellId: cellId("0"),
|
|
1695
|
-
}),
|
|
1696
|
-
);
|
|
1697
|
-
|
|
1698
|
-
actions.focusTopCell();
|
|
1699
|
-
expect(scrollToTop).toHaveBeenCalled();
|
|
1700
|
-
|
|
1701
|
-
actions.focusBottomCell();
|
|
1702
|
-
expect(scrollToBottom).toHaveBeenCalled();
|
|
1703
|
-
});
|
|
1704
|
-
|
|
1705
|
-
it("can update cell name", () => {
|
|
1706
|
-
actions.updateCellName({ cellId: firstCellId, name: "Test Cell" });
|
|
1707
|
-
expect(state.cellData[firstCellId].name).toBe("Test Cell");
|
|
1708
|
-
});
|
|
1709
|
-
|
|
1710
|
-
it("can set cell IDs and codes", () => {
|
|
1711
|
-
const newIds = [cellId("3"), cellId("4"), cellId("5")];
|
|
1712
|
-
const newCodes = ["code1", "code2", "code3"];
|
|
1713
|
-
|
|
1714
|
-
actions.setCellIds({ cellIds: newIds });
|
|
1715
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).topLevelIds).toEqual(newIds);
|
|
1716
|
-
|
|
1717
|
-
// When codeIsStale is false, lastCodeRun should match code
|
|
1718
|
-
actions.setCellCodes({
|
|
1719
|
-
codes: newCodes,
|
|
1720
|
-
ids: newIds,
|
|
1721
|
-
codeIsStale: false,
|
|
1722
|
-
});
|
|
1723
|
-
newIds.forEach((id, index) => {
|
|
1724
|
-
expect(state.cellData[id].code).toBe(newCodes[index]);
|
|
1725
|
-
expect(state.cellData[id].lastCodeRun).toBe(newCodes[index]);
|
|
1726
|
-
expect(state.cellData[id].edited).toBe(false);
|
|
1727
|
-
});
|
|
1728
|
-
|
|
1729
|
-
// When codeIsStale is true, lastCodeRun should not change
|
|
1730
|
-
const staleCodes = ["stale1", "stale2", "stale3"];
|
|
1731
|
-
actions.setCellCodes({
|
|
1732
|
-
codes: staleCodes,
|
|
1733
|
-
ids: newIds,
|
|
1734
|
-
codeIsStale: true,
|
|
1735
|
-
});
|
|
1736
|
-
newIds.forEach((id, index) => {
|
|
1737
|
-
expect(state.cellData[id].code).toBe(staleCodes[index]);
|
|
1738
|
-
expect(state.cellData[id].lastCodeRun).toBe(newCodes[index]);
|
|
1739
|
-
expect(state.cellData[id].edited).toBe(true);
|
|
1740
|
-
});
|
|
1741
|
-
});
|
|
1742
|
-
|
|
1743
|
-
it("can can add a new cell with/without stale code", () => {
|
|
1744
|
-
actions.setCellCodes({
|
|
1745
|
-
codes: ["new code"],
|
|
1746
|
-
ids: [cellId("2")],
|
|
1747
|
-
codeIsStale: false,
|
|
1748
|
-
});
|
|
1749
|
-
|
|
1750
|
-
expect(state.cellData[cellId("2")].code).toBe("new code");
|
|
1751
|
-
expect(state.cellData[cellId("2")].edited).toBe(false);
|
|
1752
|
-
expect(state.cellData[cellId("2")].lastCodeRun).toBe("new code");
|
|
1753
|
-
|
|
1754
|
-
actions.setCellCodes({
|
|
1755
|
-
codes: ["new code 2"],
|
|
1756
|
-
ids: [cellId("9")],
|
|
1757
|
-
codeIsStale: true,
|
|
1758
|
-
});
|
|
1759
|
-
|
|
1760
|
-
expect(state.cellData[cellId("9")].code).toBe("new code 2");
|
|
1761
|
-
expect(state.cellData[cellId("9")].edited).toBe(true);
|
|
1762
|
-
expect(state.cellData[cellId("9")].lastCodeRun).toBe(null);
|
|
1763
|
-
});
|
|
1764
|
-
|
|
1765
|
-
it("can partial update cell codes", () => {
|
|
1766
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
1767
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
1768
|
-
|
|
1769
|
-
expect(state.cellIds.inOrderIds).toEqual([
|
|
1770
|
-
cellId("0"),
|
|
1771
|
-
cellId("1"),
|
|
1772
|
-
cellId("2"),
|
|
1773
|
-
]);
|
|
1774
|
-
expect(state.cellData[cellId("0")].code).toBe("");
|
|
1775
|
-
expect(state.cellData[cellId("1")].code).toBe("");
|
|
1776
|
-
expect(state.cellData[cellId("2")].code).toBe("");
|
|
1777
|
-
|
|
1778
|
-
// Update cell 1
|
|
1779
|
-
actions.setCellCodes({
|
|
1780
|
-
codes: ["new code 2"],
|
|
1781
|
-
ids: [cellId("1")],
|
|
1782
|
-
codeIsStale: false,
|
|
1783
|
-
});
|
|
1784
|
-
|
|
1785
|
-
expect(state.cellIds.inOrderIds).toEqual([
|
|
1786
|
-
cellId("0"),
|
|
1787
|
-
cellId("1"),
|
|
1788
|
-
cellId("2"),
|
|
1789
|
-
]);
|
|
1790
|
-
expect(state.cellData[cellId("0")].code).toBe("");
|
|
1791
|
-
expect(state.cellData[cellId("1")].code).toBe("new code 2");
|
|
1792
|
-
expect(state.cellData[cellId("1")].edited).toBe(false);
|
|
1793
|
-
expect(state.cellData[cellId("2")].code).toBe("");
|
|
1794
|
-
});
|
|
1795
|
-
|
|
1796
|
-
it("can set cell codes with new cell ids, while preserving the old cell data", () => {
|
|
1797
|
-
actions.setCellCodes({
|
|
1798
|
-
codes: ["code1", "code2", "code3"],
|
|
1799
|
-
ids: [cellId("3"), cellId("4"), cellId("5")],
|
|
1800
|
-
codeIsStale: false,
|
|
1801
|
-
});
|
|
1802
|
-
expect(state.cellData[cellId("3")].code).toBe("code1");
|
|
1803
|
-
expect(state.cellData[cellId("4")].code).toBe("code2");
|
|
1804
|
-
expect(state.cellData[cellId("5")].code).toBe("code3");
|
|
1805
|
-
|
|
1806
|
-
// Update with some new cell ids and some old cell ids
|
|
1807
|
-
actions.setCellIds({
|
|
1808
|
-
cellIds: [cellId("1"), cellId("2"), cellId("3"), cellId("4")],
|
|
1809
|
-
});
|
|
1810
|
-
actions.setCellCodes({
|
|
1811
|
-
codes: ["new1", "new2", "code1", "code2"],
|
|
1812
|
-
ids: [cellId("1"), cellId("2"), cellId("3"), cellId("4")],
|
|
1813
|
-
codeIsStale: false,
|
|
1814
|
-
});
|
|
1815
|
-
expect(state.cellData[cellId("1")].code).toBe("new1");
|
|
1816
|
-
expect(state.cellData[cellId("2")].code).toBe("new2");
|
|
1817
|
-
expect(state.cellData[cellId("3")].code).toBe("code1");
|
|
1818
|
-
expect(state.cellData[cellId("4")].code).toBe("code2");
|
|
1819
|
-
expect(state.cellIds.inOrderIds).toEqual([
|
|
1820
|
-
cellId("1"),
|
|
1821
|
-
cellId("2"),
|
|
1822
|
-
cellId("3"),
|
|
1823
|
-
cellId("4"),
|
|
1824
|
-
]);
|
|
1825
|
-
// Cell 5 data is preserved (possibly used for tracing), but it's not in the cellIds
|
|
1826
|
-
expect(state.cellData[cellId("5")]).not.toBeUndefined();
|
|
1827
|
-
});
|
|
1828
|
-
|
|
1829
|
-
it("can set cell codes with names and configs", () => {
|
|
1830
|
-
const newIds = [cellId("3"), cellId("4")];
|
|
1831
|
-
actions.setCellIds({ cellIds: newIds });
|
|
1832
|
-
actions.setCellCodes({
|
|
1833
|
-
codes: ["code1", "code2"],
|
|
1834
|
-
ids: newIds,
|
|
1835
|
-
codeIsStale: false,
|
|
1836
|
-
names: ["setup_cell", "analysis"],
|
|
1837
|
-
configs: [
|
|
1838
|
-
{ hide_code: true, disabled: false, column: null },
|
|
1839
|
-
{ hide_code: false, disabled: true, column: null },
|
|
1840
|
-
],
|
|
1841
|
-
});
|
|
1842
|
-
|
|
1843
|
-
expect(state.cellData[cellId("3")].name).toBe("setup_cell");
|
|
1844
|
-
expect(state.cellData[cellId("3")].config.hide_code).toBe(true);
|
|
1845
|
-
expect(state.cellData[cellId("3")].config.disabled).toBe(false);
|
|
1846
|
-
|
|
1847
|
-
expect(state.cellData[cellId("4")].name).toBe("analysis");
|
|
1848
|
-
expect(state.cellData[cellId("4")].config.hide_code).toBe(false);
|
|
1849
|
-
expect(state.cellData[cellId("4")].config.disabled).toBe(true);
|
|
1850
|
-
});
|
|
1851
|
-
|
|
1852
|
-
it("can set cell codes without names/configs (backward compat)", () => {
|
|
1853
|
-
const newIds = [cellId("3")];
|
|
1854
|
-
actions.setCellIds({ cellIds: newIds });
|
|
1855
|
-
actions.setCellCodes({
|
|
1856
|
-
codes: ["code1"],
|
|
1857
|
-
ids: newIds,
|
|
1858
|
-
codeIsStale: false,
|
|
1859
|
-
});
|
|
1860
|
-
|
|
1861
|
-
// Should use defaults when names/configs not provided
|
|
1862
|
-
expect(state.cellData[cellId("3")].code).toBe("code1");
|
|
1863
|
-
expect(state.cellData[cellId("3")].config.hide_code).toBe(false);
|
|
1864
|
-
expect(state.cellData[cellId("3")].config.disabled).toBe(false);
|
|
1865
|
-
});
|
|
1866
|
-
|
|
1867
|
-
it("can update names and configs on existing cells via setCellCodes", () => {
|
|
1868
|
-
// Set initial state
|
|
1869
|
-
actions.setCellCodes({
|
|
1870
|
-
codes: ["x = 1"],
|
|
1871
|
-
ids: [firstCellId],
|
|
1872
|
-
codeIsStale: false,
|
|
1873
|
-
names: ["old_name"],
|
|
1874
|
-
configs: [{ hide_code: false, disabled: false, column: null }],
|
|
1875
|
-
});
|
|
1876
|
-
expect(state.cellData[firstCellId].name).toBe("old_name");
|
|
1877
|
-
expect(state.cellData[firstCellId].config.hide_code).toBe(false);
|
|
1878
|
-
|
|
1879
|
-
// Update with new name and config (same code)
|
|
1880
|
-
actions.setCellCodes({
|
|
1881
|
-
codes: ["x = 1"],
|
|
1882
|
-
ids: [firstCellId],
|
|
1883
|
-
codeIsStale: true,
|
|
1884
|
-
names: ["new_name"],
|
|
1885
|
-
configs: [{ hide_code: true, disabled: false, column: null }],
|
|
1886
|
-
});
|
|
1887
|
-
expect(state.cellData[firstCellId].name).toBe("new_name");
|
|
1888
|
-
expect(state.cellData[firstCellId].config.hide_code).toBe(true);
|
|
1889
|
-
});
|
|
1890
|
-
|
|
1891
|
-
it("can fold and unfold all cells", () => {
|
|
1892
|
-
actions.foldAll();
|
|
1893
|
-
expect(foldAllBulk).toHaveBeenCalled();
|
|
1894
|
-
|
|
1895
|
-
actions.unfoldAll();
|
|
1896
|
-
expect(unfoldAllBulk).toHaveBeenCalled();
|
|
1897
|
-
});
|
|
1898
|
-
|
|
1899
|
-
it("can clear logs", () => {
|
|
1900
|
-
state.cellLogs = [
|
|
1901
|
-
{
|
|
1902
|
-
level: "stderr",
|
|
1903
|
-
message: "log1",
|
|
1904
|
-
timestamp: 0,
|
|
1905
|
-
source: { type: "cell", cellId: firstCellId },
|
|
1906
|
-
},
|
|
1907
|
-
{
|
|
1908
|
-
level: "stderr",
|
|
1909
|
-
message: "log1",
|
|
1910
|
-
timestamp: 0,
|
|
1911
|
-
source: { type: "cell", cellId: firstCellId },
|
|
1912
|
-
},
|
|
1913
|
-
];
|
|
1914
|
-
actions.clearLogs();
|
|
1915
|
-
expect(state.cellLogs).toEqual([]);
|
|
1916
|
-
});
|
|
1917
|
-
|
|
1918
|
-
it("can collapse and expand cells", () => {
|
|
1919
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
1920
|
-
actions.createNewCell({
|
|
1921
|
-
cellId: cellId("1"),
|
|
1922
|
-
before: false,
|
|
1923
|
-
code: "# Header",
|
|
1924
|
-
});
|
|
1925
|
-
actions.createNewCell({
|
|
1926
|
-
cellId: cellId("2"),
|
|
1927
|
-
before: false,
|
|
1928
|
-
code: "## Subheader",
|
|
1929
|
-
});
|
|
1930
|
-
|
|
1931
|
-
const id = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(1);
|
|
1932
|
-
state.cellRuntime[id] = {
|
|
1933
|
-
...state.cellRuntime[id],
|
|
1934
|
-
outline: {
|
|
1935
|
-
items: [{ name: "Header", level: 1, by: { id: "header" } }],
|
|
1936
|
-
},
|
|
1937
|
-
};
|
|
1938
|
-
|
|
1939
|
-
actions.collapseCell({ cellId: id });
|
|
1940
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(id)).toBe(true);
|
|
1941
|
-
|
|
1942
|
-
actions.expandCell({ cellId: id });
|
|
1943
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(id)).toBe(false);
|
|
1944
|
-
});
|
|
1945
|
-
|
|
1946
|
-
it("can collapse and expand all cells in multiple columns", () => {
|
|
1947
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
1948
|
-
actions.createNewCell({
|
|
1949
|
-
cellId: cellId("1"),
|
|
1950
|
-
before: false,
|
|
1951
|
-
code: "# First Column Header",
|
|
1952
|
-
});
|
|
1953
|
-
actions.createNewCell({
|
|
1954
|
-
cellId: cellId("2"),
|
|
1955
|
-
before: false,
|
|
1956
|
-
code: "## First Column Subheader",
|
|
1957
|
-
});
|
|
1958
|
-
|
|
1959
|
-
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
1960
|
-
|
|
1961
|
-
actions.createNewCell({
|
|
1962
|
-
cellId: cellId("3"),
|
|
1963
|
-
before: false,
|
|
1964
|
-
code: "# Second Column Header",
|
|
1965
|
-
});
|
|
1966
|
-
actions.createNewCell({
|
|
1967
|
-
cellId: cellId("4"),
|
|
1968
|
-
before: false,
|
|
1969
|
-
code: "## Second Column Subheader",
|
|
1970
|
-
});
|
|
1971
|
-
|
|
1972
|
-
const firstColumnHeaderId = state.cellIds
|
|
1973
|
-
.atOrThrow(FIRST_COLUMN)
|
|
1974
|
-
.atOrThrow(1);
|
|
1975
|
-
state.cellRuntime[firstColumnHeaderId] = {
|
|
1976
|
-
...state.cellRuntime[firstColumnHeaderId],
|
|
1977
|
-
outline: {
|
|
1978
|
-
items: [
|
|
1979
|
-
{ name: "First Column Header", level: 1, by: { id: "header" } },
|
|
1980
|
-
],
|
|
1981
|
-
},
|
|
1982
|
-
};
|
|
1983
|
-
|
|
1984
|
-
const secondColumnHeaderId = state.cellIds
|
|
1985
|
-
.atOrThrow(SECOND_COLUMN)
|
|
1986
|
-
.atOrThrow(0);
|
|
1987
|
-
state.cellRuntime[secondColumnHeaderId] = {
|
|
1988
|
-
...state.cellRuntime[secondColumnHeaderId],
|
|
1989
|
-
outline: {
|
|
1990
|
-
items: [
|
|
1991
|
-
{ name: "Second Column Header", level: 1, by: { id: "header" } },
|
|
1992
|
-
],
|
|
1993
|
-
},
|
|
1994
|
-
};
|
|
1995
|
-
|
|
1996
|
-
actions.collapseAllCells();
|
|
1997
|
-
expect(
|
|
1998
|
-
state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(firstColumnHeaderId),
|
|
1999
|
-
).toBe(true);
|
|
2000
|
-
expect(
|
|
2001
|
-
state.cellIds.atOrThrow(SECOND_COLUMN).isCollapsed(secondColumnHeaderId),
|
|
2002
|
-
).toBe(true);
|
|
2003
|
-
|
|
2004
|
-
actions.expandAllCells();
|
|
2005
|
-
expect(
|
|
2006
|
-
state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(firstColumnHeaderId),
|
|
2007
|
-
).toBe(false);
|
|
2008
|
-
expect(
|
|
2009
|
-
state.cellIds.atOrThrow(SECOND_COLUMN).isCollapsed(secondColumnHeaderId),
|
|
2010
|
-
).toBe(false);
|
|
2011
|
-
});
|
|
2012
|
-
|
|
2013
|
-
it("can collapse and expand nested cells in one call", () => {
|
|
2014
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2015
|
-
actions.createNewCell({
|
|
2016
|
-
cellId: cellId("1"),
|
|
2017
|
-
before: false,
|
|
2018
|
-
code: "# Header",
|
|
2019
|
-
});
|
|
2020
|
-
actions.createNewCell({
|
|
2021
|
-
cellId: cellId("2"),
|
|
2022
|
-
before: false,
|
|
2023
|
-
code: "## Subheader",
|
|
2024
|
-
});
|
|
2025
|
-
actions.createNewCell({
|
|
2026
|
-
cellId: cellId("3"),
|
|
2027
|
-
before: false,
|
|
2028
|
-
code: "### Subsubheader",
|
|
2029
|
-
});
|
|
2030
|
-
|
|
2031
|
-
const headerId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(1);
|
|
2032
|
-
state.cellRuntime[headerId] = {
|
|
2033
|
-
...state.cellRuntime[headerId],
|
|
2034
|
-
outline: {
|
|
2035
|
-
items: [{ name: "Header", level: 1, by: { id: "header" } }],
|
|
2036
|
-
},
|
|
2037
|
-
};
|
|
2038
|
-
|
|
2039
|
-
const subheaderId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(2);
|
|
2040
|
-
state.cellRuntime[subheaderId] = {
|
|
2041
|
-
...state.cellRuntime[subheaderId],
|
|
2042
|
-
outline: {
|
|
2043
|
-
items: [{ name: "Subheader", level: 2, by: { id: "subheader" } }],
|
|
2044
|
-
},
|
|
2045
|
-
};
|
|
2046
|
-
|
|
2047
|
-
// Check if both the parent and child are collapsed
|
|
2048
|
-
actions.collapseAllCells();
|
|
2049
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(headerId)).toBe(
|
|
2050
|
-
true,
|
|
2051
|
-
);
|
|
2052
|
-
actions.expandCell({ cellId: headerId });
|
|
2053
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(subheaderId)).toBe(
|
|
2054
|
-
true,
|
|
2055
|
-
);
|
|
2056
|
-
actions.collapseCell({ cellId: headerId });
|
|
2057
|
-
|
|
2058
|
-
// Check if both the parent and child are expanded
|
|
2059
|
-
actions.expandAllCells();
|
|
2060
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(headerId)).toBe(
|
|
2061
|
-
false,
|
|
2062
|
-
);
|
|
2063
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(subheaderId)).toBe(
|
|
2064
|
-
false,
|
|
2065
|
-
);
|
|
2066
|
-
});
|
|
2067
|
-
|
|
2068
|
-
it("can collapse all cells when nested heading ranges end at the same cell", () => {
|
|
2069
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2070
|
-
actions.createNewCell({
|
|
2071
|
-
cellId: cellId("1"),
|
|
2072
|
-
before: false,
|
|
2073
|
-
code: "# Header",
|
|
2074
|
-
});
|
|
2075
|
-
actions.createNewCell({
|
|
2076
|
-
cellId: cellId("2"),
|
|
2077
|
-
before: false,
|
|
2078
|
-
code: "## Subheader",
|
|
2079
|
-
});
|
|
2080
|
-
actions.createNewCell({
|
|
2081
|
-
cellId: cellId("3"),
|
|
2082
|
-
before: false,
|
|
2083
|
-
code: "### Subsubheader",
|
|
2084
|
-
});
|
|
2085
|
-
|
|
2086
|
-
const headerId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(1);
|
|
2087
|
-
state.cellRuntime[headerId] = {
|
|
2088
|
-
...state.cellRuntime[headerId],
|
|
2089
|
-
outline: {
|
|
2090
|
-
items: [{ name: "Header", level: 1, by: { id: "header" } }],
|
|
2091
|
-
},
|
|
2092
|
-
};
|
|
2093
|
-
|
|
2094
|
-
const subheaderId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(2);
|
|
2095
|
-
state.cellRuntime[subheaderId] = {
|
|
2096
|
-
...state.cellRuntime[subheaderId],
|
|
2097
|
-
outline: {
|
|
2098
|
-
items: [{ name: "Subheader", level: 2, by: { id: "subheader" } }],
|
|
2099
|
-
},
|
|
2100
|
-
};
|
|
2101
|
-
|
|
2102
|
-
const subsubheaderId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(3);
|
|
2103
|
-
state.cellRuntime[subsubheaderId] = {
|
|
2104
|
-
...state.cellRuntime[subsubheaderId],
|
|
2105
|
-
outline: {
|
|
2106
|
-
items: [{ name: "Subsubheader", level: 3, by: { id: "subsubheader" } }],
|
|
2107
|
-
},
|
|
2108
|
-
};
|
|
2109
|
-
|
|
2110
|
-
// The header, subheader and subsubheader ranges all end at the last
|
|
2111
|
-
// cell. Collapsing all used to throw "Node ... not found in tree" and
|
|
2112
|
-
// leave the whole notebook unchanged.
|
|
2113
|
-
actions.collapseAllCells();
|
|
2114
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(headerId)).toBe(
|
|
2115
|
-
true,
|
|
2116
|
-
);
|
|
2117
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).topLevelIds).toEqual([
|
|
2118
|
-
firstCellId,
|
|
2119
|
-
headerId,
|
|
2120
|
-
]);
|
|
2121
|
-
|
|
2122
|
-
// Each level is nested under its parent, collapsed
|
|
2123
|
-
actions.expandCell({ cellId: headerId });
|
|
2124
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(subheaderId)).toBe(
|
|
2125
|
-
true,
|
|
2126
|
-
);
|
|
2127
|
-
actions.expandCell({ cellId: subheaderId });
|
|
2128
|
-
expect(
|
|
2129
|
-
state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(subsubheaderId),
|
|
2130
|
-
).toBe(true);
|
|
2131
|
-
});
|
|
2132
|
-
|
|
2133
|
-
it("can collapse all cells when a deep chain is followed by a later section", () => {
|
|
2134
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2135
|
-
actions.createNewCell({
|
|
2136
|
-
cellId: cellId("1"),
|
|
2137
|
-
before: false,
|
|
2138
|
-
code: "# Header",
|
|
2139
|
-
});
|
|
2140
|
-
actions.createNewCell({
|
|
2141
|
-
cellId: cellId("2"),
|
|
2142
|
-
before: false,
|
|
2143
|
-
code: "## Section A",
|
|
2144
|
-
});
|
|
2145
|
-
actions.createNewCell({
|
|
2146
|
-
cellId: cellId("3"),
|
|
2147
|
-
before: false,
|
|
2148
|
-
code: "### Sub of A",
|
|
2149
|
-
});
|
|
2150
|
-
actions.createNewCell({
|
|
2151
|
-
cellId: cellId("4"),
|
|
2152
|
-
before: false,
|
|
2153
|
-
code: "## Section B",
|
|
2154
|
-
});
|
|
2155
|
-
|
|
2156
|
-
const headerId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(1);
|
|
2157
|
-
state.cellRuntime[headerId] = {
|
|
2158
|
-
...state.cellRuntime[headerId],
|
|
2159
|
-
outline: {
|
|
2160
|
-
items: [{ name: "Header", level: 1, by: { id: "header" } }],
|
|
2161
|
-
},
|
|
2162
|
-
};
|
|
2163
|
-
|
|
2164
|
-
const sectionAId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(2);
|
|
2165
|
-
state.cellRuntime[sectionAId] = {
|
|
2166
|
-
...state.cellRuntime[sectionAId],
|
|
2167
|
-
outline: {
|
|
2168
|
-
items: [{ name: "Section A", level: 2, by: { id: "section-a" } }],
|
|
2169
|
-
},
|
|
2170
|
-
};
|
|
2171
|
-
|
|
2172
|
-
const subsectionId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(3);
|
|
2173
|
-
state.cellRuntime[subsectionId] = {
|
|
2174
|
-
...state.cellRuntime[subsectionId],
|
|
2175
|
-
outline: {
|
|
2176
|
-
items: [{ name: "Sub of A", level: 3, by: { id: "sub-of-a" } }],
|
|
2177
|
-
},
|
|
2178
|
-
};
|
|
2179
|
-
|
|
2180
|
-
const sectionBId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(4);
|
|
2181
|
-
state.cellRuntime[sectionBId] = {
|
|
2182
|
-
...state.cellRuntime[sectionBId],
|
|
2183
|
-
outline: {
|
|
2184
|
-
items: [{ name: "Section B", level: 2, by: { id: "section-b" } }],
|
|
2185
|
-
},
|
|
2186
|
-
};
|
|
2187
|
-
|
|
2188
|
-
actions.collapseAllCells();
|
|
2189
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(headerId)).toBe(
|
|
2190
|
-
true,
|
|
2191
|
-
);
|
|
2192
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).topLevelIds).toEqual([
|
|
2193
|
-
firstCellId,
|
|
2194
|
-
headerId,
|
|
2195
|
-
]);
|
|
2196
|
-
|
|
2197
|
-
// Both sections sit under the header, collapsed, with the subsection
|
|
2198
|
-
// nested under section A
|
|
2199
|
-
actions.expandCell({ cellId: headerId });
|
|
2200
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(sectionAId)).toBe(
|
|
2201
|
-
true,
|
|
2202
|
-
);
|
|
2203
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(sectionBId)).toBe(
|
|
2204
|
-
true,
|
|
2205
|
-
);
|
|
2206
|
-
actions.expandCell({ cellId: sectionAId });
|
|
2207
|
-
expect(
|
|
2208
|
-
state.cellIds.atOrThrow(FIRST_COLUMN).isCollapsed(subsectionId),
|
|
2209
|
-
).toBe(true);
|
|
856
|
+
status: "idle",
|
|
857
|
+
timestamp: new Date(22).getTime() as Seconds,
|
|
858
|
+
});
|
|
859
|
+
cell = cells[0];
|
|
860
|
+
expect(cell.consoleOutputs).toMatchObject([STDOUT]);
|
|
861
|
+
expect(cell).toMatchSnapshot("console received while idle");
|
|
2210
862
|
});
|
|
2211
863
|
|
|
2212
|
-
it("can
|
|
2213
|
-
actions.
|
|
2214
|
-
|
|
2215
|
-
actions.collapseCell({ cellId: firstCellId });
|
|
864
|
+
it("can fold and unfold all cells", () => {
|
|
865
|
+
actions.foldAll();
|
|
866
|
+
expect(foldAllBulk).toHaveBeenCalled();
|
|
2216
867
|
|
|
2217
|
-
actions.
|
|
2218
|
-
expect(
|
|
2219
|
-
false,
|
|
2220
|
-
);
|
|
868
|
+
actions.unfoldAll();
|
|
869
|
+
expect(unfoldAllBulk).toHaveBeenCalled();
|
|
2221
870
|
});
|
|
2222
871
|
|
|
2223
|
-
it("can
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
actions.
|
|
2239
|
-
expect(state.
|
|
2240
|
-
originalCellCount + 1,
|
|
2241
|
-
);
|
|
2242
|
-
expect(state.cellData[nextCellId].code).toBe("line1");
|
|
2243
|
-
expect(
|
|
2244
|
-
state.cellData[state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(2)].code,
|
|
2245
|
-
).toBe("line2");
|
|
2246
|
-
|
|
2247
|
-
actions.undoSplitCell({ cellId: nextCellId, snapshot: "line1\nline2" });
|
|
2248
|
-
expect(state.cellIds.atOrThrow(FIRST_COLUMN).length).toBe(
|
|
2249
|
-
originalCellCount,
|
|
2250
|
-
);
|
|
2251
|
-
expect(state.cellData[nextCellId].code).toBe("line1\nline2");
|
|
872
|
+
it("can clear logs", () => {
|
|
873
|
+
state.cellLogs = [
|
|
874
|
+
{
|
|
875
|
+
level: "stderr",
|
|
876
|
+
message: "log1",
|
|
877
|
+
timestamp: 0,
|
|
878
|
+
source: { type: "cell", cellId: firstCellId },
|
|
879
|
+
},
|
|
880
|
+
{
|
|
881
|
+
level: "stderr",
|
|
882
|
+
message: "log1",
|
|
883
|
+
timestamp: 0,
|
|
884
|
+
source: { type: "cell", cellId: firstCellId },
|
|
885
|
+
},
|
|
886
|
+
];
|
|
887
|
+
actions.clearLogs();
|
|
888
|
+
expect(state.cellLogs).toEqual([]);
|
|
2252
889
|
});
|
|
2253
890
|
|
|
2254
891
|
it("can handle multiple console outputs", () => {
|
|
@@ -2270,7 +907,6 @@ describe("cell reducer", () => {
|
|
|
2270
907
|
output: undefined,
|
|
2271
908
|
console: [STDOUT1, STDOUT2],
|
|
2272
909
|
status: "running",
|
|
2273
|
-
stale_inputs: null,
|
|
2274
910
|
timestamp: new Date(20).getTime() as Seconds,
|
|
2275
911
|
});
|
|
2276
912
|
|
|
@@ -2287,407 +923,6 @@ describe("cell reducer", () => {
|
|
|
2287
923
|
`);
|
|
2288
924
|
});
|
|
2289
925
|
|
|
2290
|
-
it("can add a column breakpoint", () => {
|
|
2291
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2292
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2293
|
-
actions.createNewCell({ cellId: cellId("2"), before: false });
|
|
2294
|
-
|
|
2295
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2296
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2297
|
-
"
|
|
2298
|
-
[0] ''
|
|
2299
|
-
|
|
2300
|
-
[1] ''
|
|
2301
|
-
|
|
2302
|
-
[2] ''
|
|
2303
|
-
|
|
2304
|
-
[3] ''
|
|
2305
|
-
"
|
|
2306
|
-
`);
|
|
2307
|
-
|
|
2308
|
-
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2309
|
-
|
|
2310
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2311
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2312
|
-
"
|
|
2313
|
-
> col 0
|
|
2314
|
-
[0] ''
|
|
2315
|
-
|
|
2316
|
-
[1] ''
|
|
2317
|
-
|
|
2318
|
-
> col 1
|
|
2319
|
-
[2] ''
|
|
2320
|
-
|
|
2321
|
-
[3] ''
|
|
2322
|
-
"
|
|
2323
|
-
`);
|
|
2324
|
-
|
|
2325
|
-
// Check that the cells are in the correct columns
|
|
2326
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2327
|
-
cellId("0"),
|
|
2328
|
-
cellId("1"),
|
|
2329
|
-
]);
|
|
2330
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([
|
|
2331
|
-
cellId("2"),
|
|
2332
|
-
cellId("3"),
|
|
2333
|
-
]);
|
|
2334
|
-
});
|
|
2335
|
-
|
|
2336
|
-
it("cannot add a column breakpoint before the first cell", () => {
|
|
2337
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2338
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2339
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2340
|
-
actions.addColumnBreakpoint({ cellId: firstCellId });
|
|
2341
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2342
|
-
});
|
|
2343
|
-
|
|
2344
|
-
it("can delete a column", () => {
|
|
2345
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2346
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2347
|
-
actions.createNewCell({ cellId: cellId("2"), before: false });
|
|
2348
|
-
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2349
|
-
|
|
2350
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2351
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2352
|
-
"
|
|
2353
|
-
> col 0
|
|
2354
|
-
[0] ''
|
|
2355
|
-
|
|
2356
|
-
[1] ''
|
|
2357
|
-
|
|
2358
|
-
> col 1
|
|
2359
|
-
[2] ''
|
|
2360
|
-
|
|
2361
|
-
[3] ''
|
|
2362
|
-
"
|
|
2363
|
-
`);
|
|
2364
|
-
|
|
2365
|
-
const columnId = state.cellIds.atOrThrow(0).id;
|
|
2366
|
-
actions.deleteColumn({ columnId: columnId });
|
|
2367
|
-
|
|
2368
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2369
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2370
|
-
"
|
|
2371
|
-
[2] ''
|
|
2372
|
-
|
|
2373
|
-
[3] ''
|
|
2374
|
-
|
|
2375
|
-
[0] ''
|
|
2376
|
-
|
|
2377
|
-
[1] ''
|
|
2378
|
-
"
|
|
2379
|
-
`);
|
|
2380
|
-
|
|
2381
|
-
// Check that all cells are now in the remaining column
|
|
2382
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2383
|
-
"2",
|
|
2384
|
-
"3",
|
|
2385
|
-
"0",
|
|
2386
|
-
"1",
|
|
2387
|
-
]);
|
|
2388
|
-
});
|
|
2389
|
-
|
|
2390
|
-
it("deleting the last column does nothing", () => {
|
|
2391
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2392
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2393
|
-
|
|
2394
|
-
const initialState = { ...state };
|
|
2395
|
-
|
|
2396
|
-
actions.deleteColumn({ columnId: initialState.cellIds.atOrThrow(0).id });
|
|
2397
|
-
|
|
2398
|
-
// State should not change
|
|
2399
|
-
expect(state).toEqual(initialState);
|
|
2400
|
-
});
|
|
2401
|
-
|
|
2402
|
-
it("can drop a cell over another cell", () => {
|
|
2403
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2404
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2405
|
-
actions.createNewCell({ cellId: cellId("2"), before: false });
|
|
2406
|
-
|
|
2407
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2408
|
-
"
|
|
2409
|
-
[0] ''
|
|
2410
|
-
|
|
2411
|
-
[1] ''
|
|
2412
|
-
|
|
2413
|
-
[2] ''
|
|
2414
|
-
|
|
2415
|
-
[3] ''
|
|
2416
|
-
"
|
|
2417
|
-
`);
|
|
2418
|
-
|
|
2419
|
-
actions.dropCellOverCell({
|
|
2420
|
-
cellId: cellId("0"),
|
|
2421
|
-
overCellId: cellId("3"),
|
|
2422
|
-
});
|
|
2423
|
-
|
|
2424
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2425
|
-
"
|
|
2426
|
-
[1] ''
|
|
2427
|
-
|
|
2428
|
-
[2] ''
|
|
2429
|
-
|
|
2430
|
-
[3] ''
|
|
2431
|
-
|
|
2432
|
-
[0] ''
|
|
2433
|
-
"
|
|
2434
|
-
`);
|
|
2435
|
-
});
|
|
2436
|
-
|
|
2437
|
-
it("can drop a cell over a new column", () => {
|
|
2438
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2439
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2440
|
-
|
|
2441
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2442
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2443
|
-
"
|
|
2444
|
-
[0] ''
|
|
2445
|
-
|
|
2446
|
-
[1] ''
|
|
2447
|
-
|
|
2448
|
-
[2] ''
|
|
2449
|
-
"
|
|
2450
|
-
`);
|
|
2451
|
-
|
|
2452
|
-
actions.dropOverNewColumn({ cellId: cellId("1") });
|
|
2453
|
-
|
|
2454
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2455
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2456
|
-
"
|
|
2457
|
-
> col 0
|
|
2458
|
-
[0] ''
|
|
2459
|
-
|
|
2460
|
-
[2] ''
|
|
2461
|
-
|
|
2462
|
-
> col 1
|
|
2463
|
-
[1] ''
|
|
2464
|
-
"
|
|
2465
|
-
`);
|
|
2466
|
-
|
|
2467
|
-
// Check that the cells are in the correct columns
|
|
2468
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2469
|
-
cellId("0"),
|
|
2470
|
-
cellId("2"),
|
|
2471
|
-
]);
|
|
2472
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([cellId("1")]);
|
|
2473
|
-
});
|
|
2474
|
-
|
|
2475
|
-
it("can drop a column over another column", () => {
|
|
2476
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2477
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2478
|
-
actions.createNewCell({ cellId: cellId("2"), before: false });
|
|
2479
|
-
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2480
|
-
|
|
2481
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2482
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2483
|
-
"
|
|
2484
|
-
> col 0
|
|
2485
|
-
[0] ''
|
|
2486
|
-
|
|
2487
|
-
[1] ''
|
|
2488
|
-
|
|
2489
|
-
> col 1
|
|
2490
|
-
[2] ''
|
|
2491
|
-
|
|
2492
|
-
[3] ''
|
|
2493
|
-
"
|
|
2494
|
-
`);
|
|
2495
|
-
|
|
2496
|
-
const columnId0 = state.cellIds.atOrThrow(0).id;
|
|
2497
|
-
const columnId1 = state.cellIds.atOrThrow(1).id;
|
|
2498
|
-
expect(columnId0).not.toBe(columnId1);
|
|
2499
|
-
actions.moveColumn({ column: columnId1, overColumn: columnId0 });
|
|
2500
|
-
|
|
2501
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2502
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2503
|
-
"
|
|
2504
|
-
> col 0
|
|
2505
|
-
[2] ''
|
|
2506
|
-
|
|
2507
|
-
[3] ''
|
|
2508
|
-
|
|
2509
|
-
> col 1
|
|
2510
|
-
[0] ''
|
|
2511
|
-
|
|
2512
|
-
[1] ''
|
|
2513
|
-
"
|
|
2514
|
-
`);
|
|
2515
|
-
|
|
2516
|
-
// Check that the columns have swapped positions
|
|
2517
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2518
|
-
cellId("2"),
|
|
2519
|
-
cellId("3"),
|
|
2520
|
-
]);
|
|
2521
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([
|
|
2522
|
-
cellId("0"),
|
|
2523
|
-
cellId("1"),
|
|
2524
|
-
]);
|
|
2525
|
-
});
|
|
2526
|
-
|
|
2527
|
-
it("can compact columns", () => {
|
|
2528
|
-
// Create initial state with 3 columns, including an empty one
|
|
2529
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2530
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2531
|
-
actions.addColumnBreakpoint({ cellId: cellId("1") });
|
|
2532
|
-
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2533
|
-
actions.dropOverNewColumn({ cellId: cellId("2") });
|
|
2534
|
-
|
|
2535
|
-
expect(state.cellIds.getColumns().length).toBe(4);
|
|
2536
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2537
|
-
"
|
|
2538
|
-
> col 0
|
|
2539
|
-
[0] ''
|
|
2540
|
-
|
|
2541
|
-
> col 1
|
|
2542
|
-
[1] ''
|
|
2543
|
-
|
|
2544
|
-
> col 2
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
> col 3
|
|
2548
|
-
[2] ''
|
|
2549
|
-
"
|
|
2550
|
-
`);
|
|
2551
|
-
|
|
2552
|
-
// Check initial column structure
|
|
2553
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([cellId("0")]);
|
|
2554
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([cellId("1")]);
|
|
2555
|
-
expect(state.cellIds.getColumns()[2].topLevelIds).toEqual([]);
|
|
2556
|
-
expect(state.cellIds.getColumns()[3].topLevelIds).toEqual([cellId("2")]);
|
|
2557
|
-
|
|
2558
|
-
// Compact columns
|
|
2559
|
-
actions.compactColumns();
|
|
2560
|
-
|
|
2561
|
-
expect(state.cellIds.getColumns().length).toBe(3);
|
|
2562
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2563
|
-
"
|
|
2564
|
-
> col 0
|
|
2565
|
-
[0] ''
|
|
2566
|
-
|
|
2567
|
-
> col 1
|
|
2568
|
-
[1] ''
|
|
2569
|
-
|
|
2570
|
-
> col 2
|
|
2571
|
-
[2] ''
|
|
2572
|
-
"
|
|
2573
|
-
`);
|
|
2574
|
-
|
|
2575
|
-
// Check compacted column structure
|
|
2576
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([cellId("0")]);
|
|
2577
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([cellId("1")]);
|
|
2578
|
-
expect(state.cellIds.getColumns()[2].topLevelIds).toEqual([cellId("2")]);
|
|
2579
|
-
});
|
|
2580
|
-
|
|
2581
|
-
it("rebuildCellColumns regroups cells by config.column", () => {
|
|
2582
|
-
// Create four cells in a single column.
|
|
2583
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2584
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2585
|
-
actions.createNewCell({ cellId: cellId("2"), before: false });
|
|
2586
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2587
|
-
|
|
2588
|
-
// Explicitly set config.column on each cell. This ONLY updates metadata —
|
|
2589
|
-
// updateCellConfig does not touch the MultiColumn tree.
|
|
2590
|
-
actions.updateCellConfig({
|
|
2591
|
-
cellId: cellId("0"),
|
|
2592
|
-
config: { column: 0 },
|
|
2593
|
-
});
|
|
2594
|
-
actions.updateCellConfig({
|
|
2595
|
-
cellId: cellId("2"),
|
|
2596
|
-
config: { column: 1 },
|
|
2597
|
-
});
|
|
2598
|
-
|
|
2599
|
-
// Tree is still a single column at this point.
|
|
2600
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2601
|
-
|
|
2602
|
-
// Now rebuild the column tree from metadata.
|
|
2603
|
-
actions.rebuildCellColumns({
|
|
2604
|
-
cellIds: [cellId("0"), cellId("1"), cellId("2"), cellId("3")],
|
|
2605
|
-
});
|
|
2606
|
-
|
|
2607
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2608
|
-
// Cell 1 inherits from 0 (col 0), cell 3 inherits from 2 (col 1).
|
|
2609
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2610
|
-
cellId("0"),
|
|
2611
|
-
cellId("1"),
|
|
2612
|
-
]);
|
|
2613
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([
|
|
2614
|
-
cellId("2"),
|
|
2615
|
-
cellId("3"),
|
|
2616
|
-
]);
|
|
2617
|
-
});
|
|
2618
|
-
|
|
2619
|
-
it("rebuildCellColumns with explicit column on every cell", () => {
|
|
2620
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2621
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2622
|
-
actions.createNewCell({ cellId: cellId("2"), before: false });
|
|
2623
|
-
|
|
2624
|
-
for (const [id, col] of [
|
|
2625
|
-
["0", 1],
|
|
2626
|
-
["1", 0],
|
|
2627
|
-
["2", 1],
|
|
2628
|
-
["3", 0],
|
|
2629
|
-
] as const) {
|
|
2630
|
-
actions.updateCellConfig({ cellId: cellId(id), config: { column: col } });
|
|
2631
|
-
}
|
|
2632
|
-
|
|
2633
|
-
actions.rebuildCellColumns({
|
|
2634
|
-
cellIds: [cellId("0"), cellId("1"), cellId("2"), cellId("3")],
|
|
2635
|
-
});
|
|
2636
|
-
|
|
2637
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2638
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2639
|
-
cellId("1"),
|
|
2640
|
-
cellId("3"),
|
|
2641
|
-
]);
|
|
2642
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([
|
|
2643
|
-
cellId("0"),
|
|
2644
|
-
cellId("2"),
|
|
2645
|
-
]);
|
|
2646
|
-
});
|
|
2647
|
-
|
|
2648
|
-
it("rebuildCellColumns collapses to one column when all cells are col 0", () => {
|
|
2649
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2650
|
-
actions.addColumnBreakpoint({ cellId: cellId("1") });
|
|
2651
|
-
expect(state.cellIds.getColumns().length).toBe(2);
|
|
2652
|
-
|
|
2653
|
-
// Wipe column metadata back to 0 for both cells.
|
|
2654
|
-
actions.updateCellConfig({ cellId: cellId("0"), config: { column: 0 } });
|
|
2655
|
-
actions.updateCellConfig({ cellId: cellId("1"), config: { column: 0 } });
|
|
2656
|
-
|
|
2657
|
-
actions.rebuildCellColumns({
|
|
2658
|
-
cellIds: [cellId("0"), cellId("1")],
|
|
2659
|
-
});
|
|
2660
|
-
|
|
2661
|
-
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2662
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([
|
|
2663
|
-
cellId("0"),
|
|
2664
|
-
cellId("1"),
|
|
2665
|
-
]);
|
|
2666
|
-
});
|
|
2667
|
-
|
|
2668
|
-
it("rebuildCellColumns follows the provided order, not current tree order", () => {
|
|
2669
|
-
// Start with a single column.
|
|
2670
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
2671
|
-
actions.createNewCell({ cellId: cellId("1"), before: false });
|
|
2672
|
-
actions.updateCellConfig({ cellId: cellId("0"), config: { column: 0 } });
|
|
2673
|
-
actions.updateCellConfig({ cellId: cellId("2"), config: { column: 1 } });
|
|
2674
|
-
|
|
2675
|
-
// Pass the reversed order. The rebuild should honor it.
|
|
2676
|
-
actions.rebuildCellColumns({
|
|
2677
|
-
cellIds: [cellId("2"), cellId("1"), cellId("0")],
|
|
2678
|
-
});
|
|
2679
|
-
|
|
2680
|
-
// cellIds iteration:
|
|
2681
|
-
// 2 → col=1, pushed to col1, prev=1
|
|
2682
|
-
// 1 → col=null, pushed to col[prev=1] = col1
|
|
2683
|
-
// 0 → col=0, pushed to col0
|
|
2684
|
-
expect(state.cellIds.getColumns()[0].topLevelIds).toEqual([cellId("0")]);
|
|
2685
|
-
expect(state.cellIds.getColumns()[1].topLevelIds).toEqual([
|
|
2686
|
-
cellId("2"),
|
|
2687
|
-
cellId("1"),
|
|
2688
|
-
]);
|
|
2689
|
-
});
|
|
2690
|
-
|
|
2691
926
|
it("can clear output of a single cell", () => {
|
|
2692
927
|
// Set up initial state with output
|
|
2693
928
|
actions.handleCellMessage({
|
|
@@ -2705,7 +940,6 @@ describe("cell reducer", () => {
|
|
|
2705
940
|
timestamp: 0,
|
|
2706
941
|
},
|
|
2707
942
|
status: "idle",
|
|
2708
|
-
stale_inputs: null,
|
|
2709
943
|
timestamp: new Date(33).getTime() as Seconds,
|
|
2710
944
|
});
|
|
2711
945
|
|
|
@@ -2740,7 +974,6 @@ describe("cell reducer", () => {
|
|
|
2740
974
|
timestamp: 0,
|
|
2741
975
|
},
|
|
2742
976
|
status: "idle",
|
|
2743
|
-
stale_inputs: null,
|
|
2744
977
|
timestamp: new Date(33).getTime() as Seconds,
|
|
2745
978
|
});
|
|
2746
979
|
|
|
@@ -2754,7 +987,6 @@ describe("cell reducer", () => {
|
|
|
2754
987
|
timestamp: 0,
|
|
2755
988
|
},
|
|
2756
989
|
status: "idle",
|
|
2757
|
-
stale_inputs: null,
|
|
2758
990
|
timestamp: new Date(34).getTime() as Seconds,
|
|
2759
991
|
});
|
|
2760
992
|
|
|
@@ -2776,8 +1008,8 @@ describe("cell reducer", () => {
|
|
|
2776
1008
|
|
|
2777
1009
|
it("can clear output of all cells", () => {
|
|
2778
1010
|
// Create multiple cells with output
|
|
2779
|
-
|
|
2780
|
-
const secondCellId = state.cellIds
|
|
1011
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1012
|
+
const secondCellId = state.cellIds[1];
|
|
2781
1013
|
|
|
2782
1014
|
// Add output to both cells
|
|
2783
1015
|
const outputMessage = {
|
|
@@ -2794,7 +1026,6 @@ describe("cell reducer", () => {
|
|
|
2794
1026
|
timestamp: 0,
|
|
2795
1027
|
},
|
|
2796
1028
|
status: "idle",
|
|
2797
|
-
stale_inputs: null,
|
|
2798
1029
|
timestamp: new Date(33).getTime() as Seconds,
|
|
2799
1030
|
} as const;
|
|
2800
1031
|
|
|
@@ -2802,142 +1033,30 @@ describe("cell reducer", () => {
|
|
|
2802
1033
|
...outputMessage,
|
|
2803
1034
|
cell_id: firstCellId,
|
|
2804
1035
|
});
|
|
2805
|
-
actions.handleCellMessage({
|
|
2806
|
-
...outputMessage,
|
|
2807
|
-
cell_id: secondCellId,
|
|
2808
|
-
});
|
|
2809
|
-
|
|
2810
|
-
// Verify initial state has output
|
|
2811
|
-
expect(state.cellRuntime[firstCellId].output).not.toBeNull();
|
|
2812
|
-
expect(state.cellRuntime[firstCellId].consoleOutputs.length).toBe(1);
|
|
2813
|
-
expect(state.cellRuntime[secondCellId].output).not.toBeNull();
|
|
2814
|
-
expect(state.cellRuntime[secondCellId].consoleOutputs.length).toBe(1);
|
|
2815
|
-
|
|
2816
|
-
// Clear all outputs
|
|
2817
|
-
actions.clearAllCellOutputs();
|
|
2818
|
-
|
|
2819
|
-
// Verify all outputs are cleared
|
|
2820
|
-
expect(state.cellRuntime[firstCellId].output).toBeNull();
|
|
2821
|
-
expect(state.cellRuntime[firstCellId].consoleOutputs).toEqual([]);
|
|
2822
|
-
expect(state.cellRuntime[secondCellId].output).toBeNull();
|
|
2823
|
-
expect(state.cellRuntime[secondCellId].consoleOutputs).toEqual([]);
|
|
2824
|
-
});
|
|
2825
|
-
|
|
2826
|
-
it("skips creating new cell if code exists and skipIfCodeExists is true", () => {
|
|
2827
|
-
// Add initial cell with code
|
|
2828
|
-
actions.updateCellCode({
|
|
2829
|
-
cellId: firstCellId,
|
|
2830
|
-
code: "import numpy as np",
|
|
2831
|
-
formattingChange: false,
|
|
2832
|
-
});
|
|
2833
|
-
|
|
2834
|
-
// Try to create new cell with same code and skipIfCodeExists
|
|
2835
|
-
actions.createNewCell({
|
|
2836
|
-
cellId: "__end__",
|
|
2837
|
-
code: "import numpy as np",
|
|
2838
|
-
before: false,
|
|
2839
|
-
skipIfCodeExists: true,
|
|
2840
|
-
});
|
|
2841
|
-
|
|
2842
|
-
// Should still only have one cell
|
|
2843
|
-
expect(state.cellIds.inOrderIds.length).toBe(1);
|
|
2844
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2845
|
-
"
|
|
2846
|
-
[0] 'import numpy as np'
|
|
2847
|
-
"
|
|
2848
|
-
`);
|
|
2849
|
-
|
|
2850
|
-
// Verify we can still add cell with different code
|
|
2851
|
-
actions.createNewCell({
|
|
2852
|
-
cellId: "__end__",
|
|
2853
|
-
code: "import pandas as pd",
|
|
2854
|
-
before: false,
|
|
2855
|
-
skipIfCodeExists: true,
|
|
2856
|
-
});
|
|
2857
|
-
|
|
2858
|
-
expect(state.cellIds.inOrderIds.length).toBe(2);
|
|
2859
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2860
|
-
"
|
|
2861
|
-
[0] 'import numpy as np'
|
|
2862
|
-
|
|
2863
|
-
[1] 'import pandas as pd'
|
|
2864
|
-
"
|
|
2865
|
-
`);
|
|
2866
|
-
});
|
|
2867
|
-
|
|
2868
|
-
it("can create and noop-update a setup cell", () => {
|
|
2869
|
-
// Create the setup cell
|
|
2870
|
-
actions.addSetupCellIfDoesntExist({ code: "# Setup code" });
|
|
2871
|
-
|
|
2872
|
-
// Check that setup cell was created
|
|
2873
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2874
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2875
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2876
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2877
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2878
|
-
|
|
2879
|
-
// Update the setup cell
|
|
2880
|
-
actions.addSetupCellIfDoesntExist({ code: "# Updated setup code" });
|
|
2881
|
-
|
|
2882
|
-
// Check that the setup cell did not change, since it already exists
|
|
2883
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2884
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2885
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2886
|
-
});
|
|
2887
|
-
|
|
2888
|
-
it("can delete and undelete the setup cell", () => {
|
|
2889
|
-
// Create the setup cell
|
|
2890
|
-
actions.addSetupCellIfDoesntExist({ code: "# Setup code" });
|
|
2891
|
-
|
|
2892
|
-
// Check that setup cell was created
|
|
2893
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2894
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2895
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2896
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2897
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2898
|
-
|
|
2899
|
-
// Delete the setup cell
|
|
2900
|
-
actions.deleteCell({ cellId: SETUP_CELL_ID });
|
|
2901
|
-
|
|
2902
|
-
// Check that setup cell was deleted
|
|
2903
|
-
expect(state.cellData[SETUP_CELL_ID]).toBeDefined(); // we keep old state
|
|
2904
|
-
expect(state.cellIds.inOrderIds).not.toContain(SETUP_CELL_ID);
|
|
2905
|
-
|
|
2906
|
-
// Undo delete the setup cell
|
|
2907
|
-
actions.undoDeleteCell();
|
|
2908
|
-
|
|
2909
|
-
// Check that setup cell was restored
|
|
2910
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2911
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2912
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2913
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2914
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2915
|
-
|
|
2916
|
-
// Verify scrollKey is set to the restored setup cell
|
|
2917
|
-
expect(state.scrollKey).toBe(SETUP_CELL_ID);
|
|
2918
|
-
});
|
|
2919
|
-
|
|
2920
|
-
it("can delete and then create a new setup cell", () => {
|
|
2921
|
-
// Create the setup cell
|
|
2922
|
-
actions.addSetupCellIfDoesntExist({ code: "# Setup code" });
|
|
1036
|
+
actions.handleCellMessage({
|
|
1037
|
+
...outputMessage,
|
|
1038
|
+
cell_id: secondCellId,
|
|
1039
|
+
});
|
|
2923
1040
|
|
|
2924
|
-
//
|
|
2925
|
-
|
|
1041
|
+
// Verify initial state has output
|
|
1042
|
+
expect(state.cellRuntime[firstCellId].output).not.toBeNull();
|
|
1043
|
+
expect(state.cellRuntime[firstCellId].consoleOutputs.length).toBe(1);
|
|
1044
|
+
expect(state.cellRuntime[secondCellId].output).not.toBeNull();
|
|
1045
|
+
expect(state.cellRuntime[secondCellId].consoleOutputs.length).toBe(1);
|
|
2926
1046
|
|
|
2927
|
-
//
|
|
2928
|
-
actions.
|
|
1047
|
+
// Clear all outputs
|
|
1048
|
+
actions.clearAllCellOutputs();
|
|
2929
1049
|
|
|
2930
|
-
//
|
|
2931
|
-
expect(state.
|
|
2932
|
-
expect(state.
|
|
2933
|
-
expect(state.
|
|
2934
|
-
expect(state.
|
|
2935
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
1050
|
+
// Verify all outputs are cleared
|
|
1051
|
+
expect(state.cellRuntime[firstCellId].output).toBeNull();
|
|
1052
|
+
expect(state.cellRuntime[firstCellId].consoleOutputs).toEqual([]);
|
|
1053
|
+
expect(state.cellRuntime[secondCellId].output).toBeNull();
|
|
1054
|
+
expect(state.cellRuntime[secondCellId].consoleOutputs).toEqual([]);
|
|
2936
1055
|
});
|
|
2937
1056
|
|
|
2938
1057
|
it("can clear all outputs", () => {
|
|
2939
1058
|
// Add a cell and give it output
|
|
2940
|
-
|
|
1059
|
+
seedCell({
|
|
2941
1060
|
cellId: firstCellId,
|
|
2942
1061
|
before: false,
|
|
2943
1062
|
});
|
|
@@ -2965,522 +1084,13 @@ describe("cell reducer", () => {
|
|
|
2965
1084
|
expect(state.cellRuntime[cell2Id].output).toBeNull();
|
|
2966
1085
|
});
|
|
2967
1086
|
|
|
2968
|
-
describe("moveToNextCell", () => {
|
|
2969
|
-
let cell1Id: CellId;
|
|
2970
|
-
let cell2Id: CellId;
|
|
2971
|
-
let cell3Id: CellId;
|
|
2972
|
-
|
|
2973
|
-
beforeEach(() => {
|
|
2974
|
-
// Create a few cells to work with
|
|
2975
|
-
actions.createNewCell({ cellId: "__end__", before: false });
|
|
2976
|
-
actions.createNewCell({ cellId: "__end__", before: false });
|
|
2977
|
-
|
|
2978
|
-
cell1Id = state.cellIds.inOrderIds[0];
|
|
2979
|
-
cell2Id = state.cellIds.inOrderIds[1];
|
|
2980
|
-
cell3Id = state.cellIds.inOrderIds[2];
|
|
2981
|
-
});
|
|
2982
|
-
|
|
2983
|
-
it("creates new cell when moving after last cell with noCreate=false", () => {
|
|
2984
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2985
|
-
|
|
2986
|
-
actions.moveToNextCell({
|
|
2987
|
-
cellId: cell3Id,
|
|
2988
|
-
before: false,
|
|
2989
|
-
noCreate: false,
|
|
2990
|
-
});
|
|
2991
|
-
|
|
2992
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount + 1);
|
|
2993
|
-
});
|
|
2994
|
-
|
|
2995
|
-
it("creates new cell when moving before first cell with noCreate=false", () => {
|
|
2996
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2997
|
-
|
|
2998
|
-
actions.moveToNextCell({
|
|
2999
|
-
cellId: cell1Id,
|
|
3000
|
-
before: true,
|
|
3001
|
-
noCreate: false,
|
|
3002
|
-
});
|
|
3003
|
-
|
|
3004
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount + 1);
|
|
3005
|
-
});
|
|
3006
|
-
|
|
3007
|
-
it("does not create new cell when moving after last cell with noCreate=true", () => {
|
|
3008
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
3009
|
-
const initialState = { ...state };
|
|
3010
|
-
|
|
3011
|
-
actions.moveToNextCell({
|
|
3012
|
-
cellId: cell3Id,
|
|
3013
|
-
before: false,
|
|
3014
|
-
noCreate: true,
|
|
3015
|
-
});
|
|
3016
|
-
|
|
3017
|
-
// Should not create a new cell
|
|
3018
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount);
|
|
3019
|
-
// Should not crash or throw an error
|
|
3020
|
-
expect(state.cellIds.inOrderIds).toEqual(initialState.cellIds.inOrderIds);
|
|
3021
|
-
});
|
|
3022
|
-
|
|
3023
|
-
it("does not create new cell when moving before first cell with noCreate=true", () => {
|
|
3024
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
3025
|
-
const initialState = { ...state };
|
|
3026
|
-
|
|
3027
|
-
actions.moveToNextCell({ cellId: cell1Id, before: true, noCreate: true });
|
|
3028
|
-
|
|
3029
|
-
// Should not create a new cell
|
|
3030
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount);
|
|
3031
|
-
// Should not crash or throw an error
|
|
3032
|
-
expect(state.cellIds.inOrderIds).toEqual(initialState.cellIds.inOrderIds);
|
|
3033
|
-
});
|
|
3034
|
-
|
|
3035
|
-
it("focuses next cell when moving within bounds", () => {
|
|
3036
|
-
const focusSpy = vi.mocked(focusAndScrollCellIntoView);
|
|
3037
|
-
focusSpy.mockClear();
|
|
3038
|
-
|
|
3039
|
-
actions.moveToNextCell({
|
|
3040
|
-
cellId: cell1Id,
|
|
3041
|
-
before: false,
|
|
3042
|
-
noCreate: true,
|
|
3043
|
-
});
|
|
3044
|
-
|
|
3045
|
-
expect(focusSpy).toHaveBeenCalledWith({
|
|
3046
|
-
cellId: cell2Id,
|
|
3047
|
-
cell: state.cellHandles[cell2Id],
|
|
3048
|
-
isCodeHidden: false,
|
|
3049
|
-
codeFocus: "top",
|
|
3050
|
-
variableName: undefined,
|
|
3051
|
-
});
|
|
3052
|
-
});
|
|
3053
|
-
|
|
3054
|
-
it("focuses previous cell when moving backward within bounds", () => {
|
|
3055
|
-
const focusSpy = vi.mocked(focusAndScrollCellIntoView);
|
|
3056
|
-
focusSpy.mockClear();
|
|
3057
|
-
|
|
3058
|
-
actions.moveToNextCell({ cellId: cell2Id, before: true, noCreate: true });
|
|
3059
|
-
|
|
3060
|
-
expect(focusSpy).toHaveBeenCalledWith({
|
|
3061
|
-
cellId: cell1Id,
|
|
3062
|
-
cell: state.cellHandles[cell1Id],
|
|
3063
|
-
isCodeHidden: false,
|
|
3064
|
-
codeFocus: "bottom",
|
|
3065
|
-
variableName: undefined,
|
|
3066
|
-
});
|
|
3067
|
-
});
|
|
3068
|
-
|
|
3069
|
-
it("does not move focus from scratch cell", () => {
|
|
3070
|
-
const focusSpy = vi.mocked(focusAndScrollCellIntoView);
|
|
3071
|
-
focusSpy.mockClear();
|
|
3072
|
-
const initialState = { ...state };
|
|
3073
|
-
|
|
3074
|
-
actions.moveToNextCell({
|
|
3075
|
-
cellId: SCRATCH_CELL_ID,
|
|
3076
|
-
before: false,
|
|
3077
|
-
noCreate: false,
|
|
3078
|
-
});
|
|
3079
|
-
|
|
3080
|
-
expect(focusSpy).not.toHaveBeenCalled();
|
|
3081
|
-
expect(state.cellIds.inOrderIds).toEqual(initialState.cellIds.inOrderIds);
|
|
3082
|
-
});
|
|
3083
|
-
});
|
|
3084
|
-
|
|
3085
|
-
describe("untouched cells functionality", () => {
|
|
3086
|
-
it("starts with empty untouchedNewCells set", () => {
|
|
3087
|
-
expect(state.untouchedNewCells).toEqual(new Set());
|
|
3088
|
-
});
|
|
3089
|
-
|
|
3090
|
-
it("can create a new cell with hideCode option", () => {
|
|
3091
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
3092
|
-
|
|
3093
|
-
actions.createNewCell({
|
|
3094
|
-
cellId: "__end__",
|
|
3095
|
-
before: false,
|
|
3096
|
-
hideCode: true,
|
|
3097
|
-
});
|
|
3098
|
-
|
|
3099
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount + 1);
|
|
3100
|
-
const newCellId =
|
|
3101
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3102
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3103
|
-
});
|
|
3104
|
-
|
|
3105
|
-
it("adds interactively-created hidden cell with boilerplate code to untouchedNewCells", () => {
|
|
3106
|
-
// Markdown cells are created with hideCode and non-empty default code
|
|
3107
|
-
// (e.g. `mo.md(r"""\n""")`). They are user-initiated, so their editor
|
|
3108
|
-
// should be shown until first blur.
|
|
3109
|
-
actions.createNewCell({
|
|
3110
|
-
cellId: "__end__",
|
|
3111
|
-
before: false,
|
|
3112
|
-
code: 'mo.md(r"""\n""")',
|
|
3113
|
-
hideCode: true,
|
|
3114
|
-
autoFocus: true,
|
|
3115
|
-
});
|
|
3116
|
-
|
|
3117
|
-
const newCellId =
|
|
3118
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3119
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3120
|
-
});
|
|
3121
|
-
|
|
3122
|
-
it("does not add programmatically-created hidden cell with code to untouchedNewCells", () => {
|
|
3123
|
-
// Cells created by the kernel (e.g. via code_mode) carry code and
|
|
3124
|
-
// autoFocus=false; their hide_code must take effect immediately.
|
|
3125
|
-
actions.createNewCell({
|
|
3126
|
-
cellId: "__end__",
|
|
3127
|
-
before: false,
|
|
3128
|
-
code: "x = 1",
|
|
3129
|
-
hideCode: true,
|
|
3130
|
-
autoFocus: false,
|
|
3131
|
-
});
|
|
3132
|
-
|
|
3133
|
-
const newCellId =
|
|
3134
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3135
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3136
|
-
});
|
|
3137
|
-
|
|
3138
|
-
it("does not add cell to untouchedNewCells when hideCode is false", () => {
|
|
3139
|
-
actions.createNewCell({
|
|
3140
|
-
cellId: "__end__",
|
|
3141
|
-
before: false,
|
|
3142
|
-
hideCode: false,
|
|
3143
|
-
});
|
|
3144
|
-
|
|
3145
|
-
const newCellId =
|
|
3146
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3147
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3148
|
-
});
|
|
3149
|
-
|
|
3150
|
-
it("does not add cell to untouchedNewCells when hideCode is undefined", () => {
|
|
3151
|
-
actions.createNewCell({
|
|
3152
|
-
cellId: "__end__",
|
|
3153
|
-
before: false,
|
|
3154
|
-
});
|
|
3155
|
-
|
|
3156
|
-
const newCellId =
|
|
3157
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3158
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3159
|
-
});
|
|
3160
|
-
|
|
3161
|
-
it("can mark a cell as touched", () => {
|
|
3162
|
-
// Create a cell with hideCode
|
|
3163
|
-
actions.createNewCell({
|
|
3164
|
-
cellId: "__end__",
|
|
3165
|
-
before: false,
|
|
3166
|
-
hideCode: true,
|
|
3167
|
-
});
|
|
3168
|
-
|
|
3169
|
-
const newCellId =
|
|
3170
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3171
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3172
|
-
|
|
3173
|
-
// Mark it as touched
|
|
3174
|
-
actions.markTouched({ cellId: newCellId });
|
|
3175
|
-
|
|
3176
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3177
|
-
});
|
|
3178
|
-
|
|
3179
|
-
it("markTouched is idempotent", () => {
|
|
3180
|
-
// Create a cell with hideCode
|
|
3181
|
-
actions.createNewCell({
|
|
3182
|
-
cellId: "__end__",
|
|
3183
|
-
before: false,
|
|
3184
|
-
hideCode: true,
|
|
3185
|
-
});
|
|
3186
|
-
|
|
3187
|
-
const newCellId =
|
|
3188
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3189
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3190
|
-
|
|
3191
|
-
// Mark it as touched multiple times
|
|
3192
|
-
actions.markTouched({ cellId: newCellId });
|
|
3193
|
-
actions.markTouched({ cellId: newCellId });
|
|
3194
|
-
actions.markTouched({ cellId: newCellId });
|
|
3195
|
-
|
|
3196
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3197
|
-
});
|
|
3198
|
-
|
|
3199
|
-
it("can mark a non-existent cell as touched without error", () => {
|
|
3200
|
-
const nonExistentCellId = cellId("non-existent");
|
|
3201
|
-
|
|
3202
|
-
expect(() => {
|
|
3203
|
-
actions.markTouched({ cellId: nonExistentCellId });
|
|
3204
|
-
}).not.toThrow();
|
|
3205
|
-
|
|
3206
|
-
expect(state.untouchedNewCells.has(nonExistentCellId)).toBe(false);
|
|
3207
|
-
});
|
|
3208
|
-
|
|
3209
|
-
it("can handle multiple untouched cells", () => {
|
|
3210
|
-
// Create multiple cells with hideCode
|
|
3211
|
-
actions.createNewCell({
|
|
3212
|
-
cellId: "__end__",
|
|
3213
|
-
before: false,
|
|
3214
|
-
hideCode: true,
|
|
3215
|
-
});
|
|
3216
|
-
actions.createNewCell({
|
|
3217
|
-
cellId: "__end__",
|
|
3218
|
-
before: false,
|
|
3219
|
-
hideCode: true,
|
|
3220
|
-
});
|
|
3221
|
-
actions.createNewCell({
|
|
3222
|
-
cellId: "__end__",
|
|
3223
|
-
before: false,
|
|
3224
|
-
hideCode: false,
|
|
3225
|
-
});
|
|
3226
|
-
|
|
3227
|
-
const cellIds = state.cellIds.inOrderIds;
|
|
3228
|
-
const cell1Id = cellIds[cellIds.length - 3];
|
|
3229
|
-
const cell2Id = cellIds[cellIds.length - 2];
|
|
3230
|
-
const cell3Id = cellIds[cellIds.length - 1];
|
|
3231
|
-
|
|
3232
|
-
expect(state.untouchedNewCells.has(cell1Id)).toBe(true);
|
|
3233
|
-
expect(state.untouchedNewCells.has(cell2Id)).toBe(true);
|
|
3234
|
-
expect(state.untouchedNewCells.has(cell3Id)).toBe(false);
|
|
3235
|
-
|
|
3236
|
-
// Mark one as touched
|
|
3237
|
-
actions.markTouched({ cellId: cell1Id });
|
|
3238
|
-
|
|
3239
|
-
expect(state.untouchedNewCells.has(cell1Id)).toBe(false);
|
|
3240
|
-
expect(state.untouchedNewCells.has(cell2Id)).toBe(true);
|
|
3241
|
-
expect(state.untouchedNewCells.has(cell3Id)).toBe(false);
|
|
3242
|
-
});
|
|
3243
|
-
|
|
3244
|
-
it("preserves untouched state when cells are moved", () => {
|
|
3245
|
-
// Create cells with hideCode
|
|
3246
|
-
actions.createNewCell({
|
|
3247
|
-
cellId: "__end__",
|
|
3248
|
-
before: false,
|
|
3249
|
-
hideCode: true,
|
|
3250
|
-
});
|
|
3251
|
-
actions.createNewCell({
|
|
3252
|
-
cellId: "__end__",
|
|
3253
|
-
before: false,
|
|
3254
|
-
hideCode: true,
|
|
3255
|
-
});
|
|
3256
|
-
|
|
3257
|
-
const cellIds = state.cellIds.inOrderIds;
|
|
3258
|
-
const cell1Id = cellIds[cellIds.length - 2];
|
|
3259
|
-
const cell2Id = cellIds[cellIds.length - 1];
|
|
3260
|
-
|
|
3261
|
-
expect(state.untouchedNewCells.has(cell1Id)).toBe(true);
|
|
3262
|
-
expect(state.untouchedNewCells.has(cell2Id)).toBe(true);
|
|
3263
|
-
|
|
3264
|
-
// Move cell1 to the end
|
|
3265
|
-
actions.moveCell({
|
|
3266
|
-
cellId: cell1Id,
|
|
3267
|
-
before: false,
|
|
3268
|
-
});
|
|
3269
|
-
|
|
3270
|
-
// Both cells should still be untouched
|
|
3271
|
-
expect(state.untouchedNewCells.has(cell1Id)).toBe(true);
|
|
3272
|
-
expect(state.untouchedNewCells.has(cell2Id)).toBe(true);
|
|
3273
|
-
});
|
|
3274
|
-
|
|
3275
|
-
it("does not remove untouched state when cell is deleted", () => {
|
|
3276
|
-
// We could implement this, but it doesn't actually affect downstream behavior.
|
|
3277
|
-
// It is easier to leave it, so `undo` works as expected.
|
|
3278
|
-
|
|
3279
|
-
// Create a cell with hideCode
|
|
3280
|
-
actions.createNewCell({
|
|
3281
|
-
cellId: "__end__",
|
|
3282
|
-
before: false,
|
|
3283
|
-
hideCode: true,
|
|
3284
|
-
});
|
|
3285
|
-
|
|
3286
|
-
const newCellId =
|
|
3287
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3288
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3289
|
-
|
|
3290
|
-
// Delete the cell
|
|
3291
|
-
actions.deleteCell({ cellId: newCellId });
|
|
3292
|
-
|
|
3293
|
-
// Does not actually remove untouched state
|
|
3294
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3295
|
-
});
|
|
3296
|
-
|
|
3297
|
-
it("restores untouched state when cell deletion is undone", () => {
|
|
3298
|
-
// Create a cell with hideCode
|
|
3299
|
-
actions.createNewCell({
|
|
3300
|
-
cellId: "__end__",
|
|
3301
|
-
before: false,
|
|
3302
|
-
hideCode: true,
|
|
3303
|
-
});
|
|
3304
|
-
|
|
3305
|
-
const newCellId =
|
|
3306
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3307
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3308
|
-
|
|
3309
|
-
// Delete the cell
|
|
3310
|
-
actions.deleteCell({ cellId: newCellId });
|
|
3311
|
-
// Still exists in untouchedNewCells
|
|
3312
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3313
|
-
|
|
3314
|
-
// Undo the deletion
|
|
3315
|
-
actions.undoDeleteCell();
|
|
3316
|
-
|
|
3317
|
-
// The cell should be restored but no longer untouched
|
|
3318
|
-
// (this is expected behavior - undoing doesn't restore untouched state)
|
|
3319
|
-
const restoredCellId =
|
|
3320
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3321
|
-
expect(state.untouchedNewCells.has(restoredCellId)).toBe(false);
|
|
3322
|
-
});
|
|
3323
|
-
|
|
3324
|
-
it("untouched cell behavior with hide_code config", () => {
|
|
3325
|
-
// Create a cell with hideCode and hide_code config
|
|
3326
|
-
actions.createNewCell({
|
|
3327
|
-
cellId: "__end__",
|
|
3328
|
-
before: false,
|
|
3329
|
-
hideCode: true,
|
|
3330
|
-
});
|
|
3331
|
-
|
|
3332
|
-
const newCellId =
|
|
3333
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3334
|
-
|
|
3335
|
-
// Update the cell config to hide code
|
|
3336
|
-
actions.updateCellConfig({
|
|
3337
|
-
cellId: newCellId,
|
|
3338
|
-
config: { hide_code: true },
|
|
3339
|
-
});
|
|
3340
|
-
|
|
3341
|
-
// Cell should be untouched and have hide_code config
|
|
3342
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3343
|
-
expect(state.cellData[newCellId].config.hide_code).toBe(true);
|
|
3344
|
-
|
|
3345
|
-
// Code should not be hidden because cell is untouched
|
|
3346
|
-
expect(exportedForTesting.isCellCodeHidden(state, newCellId)).toBe(false);
|
|
3347
|
-
|
|
3348
|
-
// Mark as touched
|
|
3349
|
-
actions.markTouched({ cellId: newCellId });
|
|
3350
|
-
|
|
3351
|
-
// Now code should be hidden
|
|
3352
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3353
|
-
expect(exportedForTesting.isCellCodeHidden(state, newCellId)).toBe(true);
|
|
3354
|
-
});
|
|
3355
|
-
|
|
3356
|
-
it("can mark an existing cell as untouched", () => {
|
|
3357
|
-
// Create a cell without hideCode (not in untouchedNewCells)
|
|
3358
|
-
actions.createNewCell({
|
|
3359
|
-
cellId: "__end__",
|
|
3360
|
-
before: false,
|
|
3361
|
-
hideCode: false,
|
|
3362
|
-
});
|
|
3363
|
-
|
|
3364
|
-
const newCellId =
|
|
3365
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3366
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3367
|
-
|
|
3368
|
-
// Mark it as untouched
|
|
3369
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3370
|
-
|
|
3371
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3372
|
-
});
|
|
3373
|
-
|
|
3374
|
-
it("markUntouched is idempotent", () => {
|
|
3375
|
-
// Create a cell without hideCode
|
|
3376
|
-
actions.createNewCell({
|
|
3377
|
-
cellId: "__end__",
|
|
3378
|
-
before: false,
|
|
3379
|
-
hideCode: false,
|
|
3380
|
-
});
|
|
3381
|
-
|
|
3382
|
-
const newCellId =
|
|
3383
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3384
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3385
|
-
|
|
3386
|
-
// Mark as untouched multiple times
|
|
3387
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3388
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3389
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3390
|
-
|
|
3391
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3392
|
-
});
|
|
3393
|
-
|
|
3394
|
-
it("markUntouched does not affect already untouched cells", () => {
|
|
3395
|
-
// Create a cell with hideCode (already in untouchedNewCells)
|
|
3396
|
-
actions.createNewCell({
|
|
3397
|
-
cellId: "__end__",
|
|
3398
|
-
before: false,
|
|
3399
|
-
hideCode: true,
|
|
3400
|
-
});
|
|
3401
|
-
|
|
3402
|
-
const newCellId =
|
|
3403
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3404
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3405
|
-
|
|
3406
|
-
// Calling markUntouched should not change anything
|
|
3407
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3408
|
-
|
|
3409
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3410
|
-
});
|
|
3411
|
-
|
|
3412
|
-
it("markTouched and markUntouched can toggle cell state", () => {
|
|
3413
|
-
// Create a cell without hideCode
|
|
3414
|
-
actions.createNewCell({
|
|
3415
|
-
cellId: "__end__",
|
|
3416
|
-
before: false,
|
|
3417
|
-
hideCode: false,
|
|
3418
|
-
});
|
|
3419
|
-
|
|
3420
|
-
const newCellId =
|
|
3421
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3422
|
-
|
|
3423
|
-
// Initially not untouched
|
|
3424
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3425
|
-
|
|
3426
|
-
// Mark as untouched
|
|
3427
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3428
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3429
|
-
|
|
3430
|
-
// Mark as touched
|
|
3431
|
-
actions.markTouched({ cellId: newCellId });
|
|
3432
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
3433
|
-
|
|
3434
|
-
// Mark as untouched again
|
|
3435
|
-
actions.markUntouched({ cellId: newCellId });
|
|
3436
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3437
|
-
});
|
|
3438
|
-
|
|
3439
|
-
it("markUntouched works for markdown cell conversion scenario", () => {
|
|
3440
|
-
// Simulates converting a Python cell to Markdown
|
|
3441
|
-
// 1. Create a regular cell (no hideCode)
|
|
3442
|
-
actions.createNewCell({
|
|
3443
|
-
cellId: "__end__",
|
|
3444
|
-
before: false,
|
|
3445
|
-
hideCode: false,
|
|
3446
|
-
});
|
|
3447
|
-
|
|
3448
|
-
const cellId =
|
|
3449
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3450
|
-
|
|
3451
|
-
// Cell starts without hide_code and not in untouchedNewCells
|
|
3452
|
-
expect(state.cellData[cellId].config.hide_code).toBe(false);
|
|
3453
|
-
expect(state.untouchedNewCells.has(cellId)).toBe(false);
|
|
3454
|
-
expect(exportedForTesting.isCellCodeHidden(state, cellId)).toBe(false);
|
|
3455
|
-
|
|
3456
|
-
// 2. Convert to markdown: set hide_code and mark as untouched
|
|
3457
|
-
actions.updateCellConfig({
|
|
3458
|
-
cellId,
|
|
3459
|
-
config: { hide_code: true },
|
|
3460
|
-
});
|
|
3461
|
-
actions.markUntouched({ cellId });
|
|
3462
|
-
|
|
3463
|
-
// Code should NOT be hidden because cell is untouched (user can edit)
|
|
3464
|
-
expect(state.cellData[cellId].config.hide_code).toBe(true);
|
|
3465
|
-
expect(state.untouchedNewCells.has(cellId)).toBe(true);
|
|
3466
|
-
expect(exportedForTesting.isCellCodeHidden(state, cellId)).toBe(false);
|
|
3467
|
-
|
|
3468
|
-
// 3. User blurs the cell (markTouched)
|
|
3469
|
-
actions.markTouched({ cellId });
|
|
3470
|
-
|
|
3471
|
-
// Now code should be hidden
|
|
3472
|
-
expect(state.untouchedNewCells.has(cellId)).toBe(false);
|
|
3473
|
-
expect(exportedForTesting.isCellCodeHidden(state, cellId)).toBe(true);
|
|
3474
|
-
});
|
|
3475
|
-
});
|
|
3476
|
-
|
|
3477
1087
|
describe("releaseCellAtoms", () => {
|
|
3478
1088
|
it("atom families cache atoms until explicitly removed", () => {
|
|
3479
1089
|
const { cellDataAtom, cellRuntimeAtom, cellHandleAtom } =
|
|
3480
1090
|
exportedForTesting;
|
|
3481
1091
|
|
|
3482
|
-
|
|
3483
|
-
const newCellId = state.cellIds
|
|
1092
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1093
|
+
const newCellId = state.cellIds[1];
|
|
3484
1094
|
|
|
3485
1095
|
const dataAtom1 = cellDataAtom(newCellId);
|
|
3486
1096
|
const runtimeAtom1 = cellRuntimeAtom(newCellId);
|
|
@@ -3495,116 +1105,15 @@ describe("cell reducer", () => {
|
|
|
3495
1105
|
expect(runtimeAtom2).toBe(runtimeAtom1);
|
|
3496
1106
|
expect(handleAtom2).toBe(handleAtom1);
|
|
3497
1107
|
});
|
|
3498
|
-
|
|
3499
|
-
it("cleans up atom family cache when cells are deleted", () => {
|
|
3500
|
-
const { cellDataAtom, cellRuntimeAtom, cellHandleAtom } =
|
|
3501
|
-
exportedForTesting;
|
|
3502
|
-
|
|
3503
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
3504
|
-
const newCellId = state.cellIds.inOrderIds[1];
|
|
3505
|
-
|
|
3506
|
-
// Access to create cache entries
|
|
3507
|
-
const dataAtom1 = cellDataAtom(newCellId);
|
|
3508
|
-
const runtimeAtom1 = cellRuntimeAtom(newCellId);
|
|
3509
|
-
const handleAtom1 = cellHandleAtom(newCellId);
|
|
3510
|
-
|
|
3511
|
-
// Triggers purge
|
|
3512
|
-
actions.deleteCell({ cellId: newCellId });
|
|
3513
|
-
|
|
3514
|
-
// Access again (should be new instances after cleanup)
|
|
3515
|
-
const dataAtom2 = cellDataAtom(newCellId);
|
|
3516
|
-
const runtimeAtom2 = cellRuntimeAtom(newCellId);
|
|
3517
|
-
const handleAtom2 = cellHandleAtom(newCellId);
|
|
3518
|
-
|
|
3519
|
-
expect(dataAtom2).not.toBe(dataAtom1);
|
|
3520
|
-
expect(runtimeAtom2).not.toBe(runtimeAtom1);
|
|
3521
|
-
expect(handleAtom2).not.toBe(handleAtom1);
|
|
3522
|
-
});
|
|
3523
|
-
});
|
|
3524
|
-
});
|
|
3525
|
-
|
|
3526
|
-
describe("isCellCodeHidden", () => {
|
|
3527
|
-
const state = initialNotebookState();
|
|
3528
|
-
const firstCellId = state.cellIds.inOrderIds[0];
|
|
3529
|
-
|
|
3530
|
-
it("returns false when hide_code is false and cell is not untouched", () => {
|
|
3531
|
-
const testCellId = cellId("test-cell");
|
|
3532
|
-
const testState: NotebookState = {
|
|
3533
|
-
...state,
|
|
3534
|
-
cellData: {
|
|
3535
|
-
...state.cellData,
|
|
3536
|
-
[testCellId]: {
|
|
3537
|
-
...state.cellData[firstCellId],
|
|
3538
|
-
id: testCellId,
|
|
3539
|
-
config: { hide_code: false, disabled: false, column: null },
|
|
3540
|
-
},
|
|
3541
|
-
},
|
|
3542
|
-
untouchedNewCells: new Set(),
|
|
3543
|
-
};
|
|
3544
|
-
|
|
3545
|
-
expect(exportedForTesting.isCellCodeHidden(testState, testCellId)).toBe(
|
|
3546
|
-
false,
|
|
3547
|
-
);
|
|
3548
|
-
});
|
|
3549
|
-
|
|
3550
|
-
it("returns true when hide_code is true and cell is not untouched", () => {
|
|
3551
|
-
const testCellId = cellId("test-cell");
|
|
3552
|
-
const testState: NotebookState = {
|
|
3553
|
-
...state,
|
|
3554
|
-
cellData: {
|
|
3555
|
-
...state.cellData,
|
|
3556
|
-
[testCellId]: {
|
|
3557
|
-
...state.cellData[firstCellId],
|
|
3558
|
-
id: testCellId,
|
|
3559
|
-
config: { hide_code: true, disabled: false, column: null },
|
|
3560
|
-
},
|
|
3561
|
-
},
|
|
3562
|
-
untouchedNewCells: new Set(),
|
|
3563
|
-
};
|
|
3564
|
-
|
|
3565
|
-
expect(exportedForTesting.isCellCodeHidden(testState, testCellId)).toBe(
|
|
3566
|
-
true,
|
|
3567
|
-
);
|
|
3568
|
-
});
|
|
3569
|
-
|
|
3570
|
-
it("returns false when hide_code is true but cell is untouched", () => {
|
|
3571
|
-
const testCellId = cellId("test-cell");
|
|
3572
|
-
const testState: NotebookState = {
|
|
3573
|
-
...state,
|
|
3574
|
-
cellData: {
|
|
3575
|
-
...state.cellData,
|
|
3576
|
-
[testCellId]: {
|
|
3577
|
-
...state.cellData[firstCellId],
|
|
3578
|
-
id: testCellId,
|
|
3579
|
-
config: { hide_code: true, disabled: false, column: null },
|
|
3580
|
-
},
|
|
3581
|
-
},
|
|
3582
|
-
untouchedNewCells: new Set([testCellId]),
|
|
3583
|
-
};
|
|
3584
|
-
|
|
3585
|
-
expect(exportedForTesting.isCellCodeHidden(testState, testCellId)).toBe(
|
|
3586
|
-
false,
|
|
3587
|
-
);
|
|
3588
1108
|
});
|
|
1109
|
+
it("withdraws the submission of a cell that leaves the document", () => {
|
|
1110
|
+
MockExecutions.seed(store, []);
|
|
1111
|
+
submitCells(store, [firstCellId]);
|
|
1112
|
+
expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(1);
|
|
3589
1113
|
|
|
3590
|
-
|
|
3591
|
-
const testCellId = cellId("test-cell");
|
|
3592
|
-
const testState: NotebookState = {
|
|
3593
|
-
...state,
|
|
3594
|
-
cellData: {
|
|
3595
|
-
...state.cellData,
|
|
3596
|
-
[testCellId]: {
|
|
3597
|
-
...state.cellData[firstCellId],
|
|
3598
|
-
id: testCellId,
|
|
3599
|
-
config: { hide_code: false, disabled: false, column: null },
|
|
3600
|
-
},
|
|
3601
|
-
},
|
|
3602
|
-
untouchedNewCells: new Set([testCellId]),
|
|
3603
|
-
};
|
|
1114
|
+
actions.reconcileDocument({ order: [], cells: new Map() });
|
|
3604
1115
|
|
|
3605
|
-
expect(
|
|
3606
|
-
false,
|
|
3607
|
-
);
|
|
1116
|
+
expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(0);
|
|
3608
1117
|
});
|
|
3609
1118
|
});
|
|
3610
1119
|
|
|
@@ -3787,11 +1296,11 @@ describe("createTracebackInfoAtom", () => {
|
|
|
3787
1296
|
data: [{ type: "syntax", msg: "Syntax error", lineno: 1 }],
|
|
3788
1297
|
mimetype: "application/vnd.marimo+error",
|
|
3789
1298
|
},
|
|
3790
|
-
status: "queued",
|
|
3791
1299
|
},
|
|
3792
1300
|
},
|
|
3793
1301
|
}),
|
|
3794
1302
|
);
|
|
1303
|
+
MockExecutions.seed(store, [MockExecutions.queued(cellId("cell1"))]);
|
|
3795
1304
|
|
|
3796
1305
|
const tracebackAtom = exportedForTesting.createTracebackInfoAtom(
|
|
3797
1306
|
cellId("cell1"),
|
|
@@ -3819,11 +1328,11 @@ describe("createTracebackInfoAtom", () => {
|
|
|
3819
1328
|
data: [{ type: "syntax", msg: "Syntax error", lineno: 1 }],
|
|
3820
1329
|
mimetype: "application/vnd.marimo+error",
|
|
3821
1330
|
},
|
|
3822
|
-
status: "running",
|
|
3823
1331
|
},
|
|
3824
1332
|
},
|
|
3825
1333
|
}),
|
|
3826
1334
|
);
|
|
1335
|
+
MockExecutions.seed(store, [MockExecutions.running(cellId("cell1"))]);
|
|
3827
1336
|
|
|
3828
1337
|
const tracebackAtom = exportedForTesting.createTracebackInfoAtom(
|
|
3829
1338
|
cellId("cell1"),
|
|
@@ -3834,31 +1343,9 @@ describe("createTracebackInfoAtom", () => {
|
|
|
3834
1343
|
});
|
|
3835
1344
|
});
|
|
3836
1345
|
|
|
3837
|
-
describe("
|
|
1346
|
+
describe("kernel-ready", () => {
|
|
3838
1347
|
const CELL_A = cellId("A");
|
|
3839
1348
|
const CELL_B = cellId("B");
|
|
3840
|
-
const newCells: CellData[] = [
|
|
3841
|
-
{
|
|
3842
|
-
id: CELL_A,
|
|
3843
|
-
name: "a",
|
|
3844
|
-
code: "1",
|
|
3845
|
-
edited: false,
|
|
3846
|
-
lastCodeRun: null,
|
|
3847
|
-
lastExecutionTime: null,
|
|
3848
|
-
config: { hide_code: false, disabled: false, column: null },
|
|
3849
|
-
serializedEditorState: null,
|
|
3850
|
-
},
|
|
3851
|
-
{
|
|
3852
|
-
id: CELL_B,
|
|
3853
|
-
name: "b",
|
|
3854
|
-
code: "2",
|
|
3855
|
-
edited: false,
|
|
3856
|
-
lastCodeRun: null,
|
|
3857
|
-
lastExecutionTime: null,
|
|
3858
|
-
config: { hide_code: false, disabled: false, column: null },
|
|
3859
|
-
serializedEditorState: null,
|
|
3860
|
-
},
|
|
3861
|
-
];
|
|
3862
1349
|
|
|
3863
1350
|
const hydratedState = () =>
|
|
3864
1351
|
MockNotebook.notebookState({
|
|
@@ -3888,44 +1375,74 @@ describe("setCells snapshot preservation", () => {
|
|
|
3888
1375
|
},
|
|
3889
1376
|
});
|
|
3890
1377
|
|
|
3891
|
-
|
|
3892
|
-
const { isWasm } = await import("@/core/wasm/utils");
|
|
3893
|
-
vi.mocked(isWasm).mockReturnValue(true);
|
|
3894
|
-
});
|
|
3895
|
-
|
|
3896
|
-
it("preserves hydrated output in WASM", () => {
|
|
1378
|
+
it("resetCellRuntimes starts every cell's runtime over", () => {
|
|
3897
1379
|
const next = exportedForTesting.reducer(hydratedState(), {
|
|
3898
|
-
type: "
|
|
3899
|
-
payload:
|
|
1380
|
+
type: "resetCellRuntimes",
|
|
1381
|
+
payload: undefined,
|
|
3900
1382
|
});
|
|
3901
1383
|
|
|
3902
|
-
expect(next.cellRuntime[CELL_A].output).
|
|
3903
|
-
|
|
1384
|
+
expect(next.cellRuntime[CELL_A].output).toBeNull();
|
|
1385
|
+
expect(next.cellRuntime[CELL_B].consoleOutputs).toEqual([]);
|
|
1386
|
+
});
|
|
1387
|
+
|
|
1388
|
+
it("resetCellRuntimes starts the scratch cell over too", () => {
|
|
1389
|
+
const state = MockNotebook.notebookState({
|
|
1390
|
+
cellData: { [CELL_A]: { id: CELL_A, code: "1" } },
|
|
1391
|
+
cellRuntime: {
|
|
1392
|
+
[SCRATCH_CELL_ID]: {
|
|
1393
|
+
output: {
|
|
1394
|
+
channel: "output",
|
|
1395
|
+
mimetype: "text/plain",
|
|
1396
|
+
data: "scratch",
|
|
1397
|
+
timestamp: 0,
|
|
1398
|
+
},
|
|
1399
|
+
},
|
|
1400
|
+
},
|
|
3904
1401
|
});
|
|
1402
|
+
const next = exportedForTesting.reducer(state, {
|
|
1403
|
+
type: "resetCellRuntimes",
|
|
1404
|
+
payload: undefined,
|
|
1405
|
+
});
|
|
1406
|
+
|
|
1407
|
+
expect(next.cellRuntime[SCRATCH_CELL_ID].output).toBeNull();
|
|
3905
1408
|
});
|
|
3906
1409
|
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
1410
|
+
describe("resetCellRuntimes in WASM", () => {
|
|
1411
|
+
beforeEach(async () => {
|
|
1412
|
+
const { isWasm } = await import("@/core/wasm/utils");
|
|
1413
|
+
vi.mocked(isWasm).mockReturnValue(true);
|
|
3911
1414
|
});
|
|
3912
1415
|
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
1416
|
+
afterEach(async () => {
|
|
1417
|
+
const { isWasm } = await import("@/core/wasm/utils");
|
|
1418
|
+
vi.mocked(isWasm).mockReturnValue(false);
|
|
3916
1419
|
});
|
|
3917
|
-
});
|
|
3918
1420
|
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
1421
|
+
it("keeps hydrated outputs and console", () => {
|
|
1422
|
+
const next = exportedForTesting.reducer(hydratedState(), {
|
|
1423
|
+
type: "resetCellRuntimes",
|
|
1424
|
+
payload: undefined,
|
|
1425
|
+
});
|
|
1426
|
+
|
|
1427
|
+
expect(next.cellRuntime[CELL_A].output).toMatchObject({
|
|
1428
|
+
data: "hydrated-A",
|
|
1429
|
+
});
|
|
1430
|
+
expect(next.cellRuntime[CELL_B].consoleOutputs[0]).toMatchObject({
|
|
1431
|
+
data: "hydrated-B-stdout",
|
|
1432
|
+
});
|
|
3924
1433
|
});
|
|
3925
1434
|
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
1435
|
+
it("starts cells with no prior runtime over", () => {
|
|
1436
|
+
const state = MockNotebook.notebookState({
|
|
1437
|
+
cellData: { [CELL_A]: { id: CELL_A, code: "1" } },
|
|
1438
|
+
});
|
|
1439
|
+
const next = exportedForTesting.reducer(state, {
|
|
1440
|
+
type: "resetCellRuntimes",
|
|
1441
|
+
payload: undefined,
|
|
1442
|
+
});
|
|
1443
|
+
|
|
1444
|
+
expect(next.cellRuntime[CELL_A].output).toBeNull();
|
|
1445
|
+
expect(next.cellRuntime[CELL_A].consoleOutputs).toEqual([]);
|
|
1446
|
+
});
|
|
3930
1447
|
});
|
|
3931
1448
|
});
|