@marimo-team/islands 0.25.3-dev267 → 0.25.3-dev269

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.
Files changed (140) hide show
  1. package/dist/{ConnectedDataExplorerComponent-C4yCN38h.js → ConnectedDataExplorerComponent-eLHPh6uu.js} +8 -8
  2. package/dist/{ErrorBoundary-CewXPyL5.js → ErrorBoundary-DCtynjHZ.js} +4 -4
  3. package/dist/{abnfDiagram-VCTEODGH-o6Ay6Q63.js → abnfDiagram-VCTEODGH-hqd0IBtX.js} +2 -2
  4. package/dist/{architectureDiagram-5GKGNRK7-BhiwwlVg.js → architectureDiagram-5GKGNRK7-BzLAFcc0.js} +1 -1
  5. package/dist/{strings-BCKpLFNU.js → assertNever-DIU3JJbt.js} +14 -14
  6. package/dist/{chat-ui-CbgR5ivy.js → chat-ui-BWIkve2R.js} +17 -17
  7. package/dist/{chunk-IMKFNOWR-WMSMf4Nj.js → chunk-IMKFNOWR-DOeVvuyE.js} +1 -1
  8. package/dist/{chunk-SHT3W25Y-BRfADrzD.js → chunk-SHT3W25Y-DZoFI8wR.js} +1 -1
  9. package/dist/{chunk-SVP7TREG-CuK5QFre.js → chunk-SVP7TREG-CWu86PSW.js} +1 -1
  10. package/dist/{chunk-TICWLB2K-Bcun_jhJ.js → chunk-TICWLB2K-BrM0GoP3.js} +1 -1
  11. package/dist/{classDiagram-ZZMXUADV-CgWDbUDT.js → classDiagram-ZZMXUADV-DYi4V2bB.js} +2 -2
  12. package/dist/{classDiagram-v2-VYDZK3BY-DYmc9SFU.js → classDiagram-v2-VYDZK3BY-tN7FIk-m.js} +2 -2
  13. package/dist/{code-visibility-BKBl9Rh6.js → code-visibility-CMF5tcNj.js} +44 -47
  14. package/dist/{common-N3Jd_6m9.js → common-DYAjQ1bK.js} +4866 -4857
  15. package/dist/{config-CmeG_Pb6.js → config-BsPruWMR.js} +2 -2
  16. package/dist/{createReducer-C_syF8Td.js → createReducer-DdtT_7ji.js} +1 -1
  17. package/dist/{cynefinDiagram-5FMLGOSQ-PPKWipjT.js → cynefinDiagram-5FMLGOSQ-D5nCnDc-.js} +1 -1
  18. package/dist/{dagre-GXQ25YYZ-niRBZh--.js → dagre-GXQ25YYZ-BHkd7f_i.js} +1 -1
  19. package/dist/{data-grid-overlay-editor-Cp59CrqZ.js → data-grid-overlay-editor-B6oND8pX.js} +1 -1
  20. package/dist/{diagram-S7CK7UJ4-DPiP9rot.js → diagram-S7CK7UJ4-D1ALppT2.js} +1 -1
  21. package/dist/{diagram-UQ7AKVKN-B0WZuaxV.js → diagram-UQ7AKVKN-DLv0b83L.js} +1 -1
  22. package/dist/{diagram-VX7I27RA-Rn42WBuN.js → diagram-VX7I27RA-7XJ7J6qg.js} +1 -1
  23. package/dist/{diagram-Z3DM3KII-BB93--ry.js → diagram-Z3DM3KII-7M7zbHp_.js} +1 -1
  24. package/dist/{dialog-BtprQCUw.js → dialog-DzCj1qQv.js} +1 -1
  25. package/dist/{dropdown-menu-BpImEfn3.js → dropdown-menu-CdXE15an.js} +3 -3
  26. package/dist/{ebnfDiagram-PWID7BFC-V4t5h6mZ.js → ebnfDiagram-PWID7BFC-DHH1qlmV.js} +2 -2
  27. package/dist/{erDiagram-RLTQ6QDP-C1MsAKXd.js → erDiagram-RLTQ6QDP-fI_0dGef.js} +1 -1
  28. package/dist/{error-entries-CJGdD2ky.js → error-entries-CxN-Nq3V.js} +519 -458
  29. package/dist/{feedback-button-Qc1f9iPq.js → feedback-button-BelKx6R5.js} +22 -22
  30. package/dist/{flowDiagram-HODETNUW-DHjeJP96.js → flowDiagram-HODETNUW-Brg9MA6i.js} +2 -2
  31. package/dist/{formats-gGospKWJ.js → formats-DbSvAPY-.js} +1 -1
  32. package/dist/{glide-data-editor-hCq3K0sd.js → glide-data-editor-CMZ-kv0S.js} +11 -11
  33. package/dist/{glide-utils-DC3sk6EX.js → glide-utils-BSw3SSHF.js} +1 -1
  34. package/dist/{globals-B2_uMYDY.js → globals-DV77npCG.js} +2 -2
  35. package/dist/{html-to-image-S7spRQCi.js → html-to-image-Bc2AvXHG.js} +5121 -5121
  36. package/dist/{infoDiagram-27XIBGKW-Dovv6iKx.js → infoDiagram-27XIBGKW-E9e403YT.js} +1 -1
  37. package/dist/{ishikawaDiagram-5VMMS53U-D2nyygsc.js → ishikawaDiagram-5VMMS53U-C-RlYDRo.js} +1 -1
  38. package/dist/{kanban-definition-UXKFOSKX-KyVx0uTY.js → kanban-definition-UXKFOSKX-CLFl_uqK.js} +1 -1
  39. package/dist/main.js +5972 -6003
  40. package/dist/{mermaid-B-jKSwGt.js → mermaid-rd09e1JL.js} +34 -34
  41. package/dist/{mindmap-definition-YA3MSWOX-Bz9tKQFl.js → mindmap-definition-YA3MSWOX-BQ8TWtyB.js} +1 -1
  42. package/dist/{number-overlay-editor-CfNYvbdz.js → number-overlay-editor-CFTuKnrY.js} +1 -1
  43. package/dist/{pegDiagram-XKGWAZYB-C_qpq6Tv.js → pegDiagram-XKGWAZYB-CN8UHFPi.js} +2 -2
  44. package/dist/{pieDiagram-E7YTZNPT-Bp9ucgI4.js → pieDiagram-E7YTZNPT-DGuJ0EBd.js} +1 -1
  45. package/dist/{process-output-f34bkXTm.js → process-output-qecD7Dk8.js} +3 -3
  46. package/dist/{railroadDiagram-O6MQD6OU-tq-VEH6j.js → railroadDiagram-O6MQD6OU-BPDA8wy8.js} +2 -2
  47. package/dist/{requirementDiagram-BXWQKSXE-DW-vHadb.js → requirementDiagram-BXWQKSXE-ChzLGbGW.js} +1 -1
  48. package/dist/{reveal-component-CUxv-kkP.js → reveal-component-Doix35eL.js} +1094 -1094
  49. package/dist/{select-C33FVPPN.js → select-OxgozOC8.js} +1 -1
  50. package/dist/{sequenceDiagram-WJ2MYXX4-Dv9U9qRP.js → sequenceDiagram-WJ2MYXX4-DFX-bE6O.js} +1 -1
  51. package/dist/{spec-DH1lmF7Q.js → spec-oJn0RhpQ.js} +2 -2
  52. package/dist/{stateDiagram-D77RDMKH-DTmPQ0EB.js → stateDiagram-D77RDMKH-BR7cI3wK.js} +2 -2
  53. package/dist/{stateDiagram-v2-MP3YSRHH-CkCif0Iw.js → stateDiagram-v2-MP3YSRHH-oGqB5UDI.js} +2 -2
  54. package/dist/{static-state-BldGd99T.js → static-state-CuV6Pc3a.js} +1 -1
  55. package/dist/{swimlanes-42K2YHIH-21kCq6l8.js → swimlanes-42K2YHIH-DwSZl1yC.js} +1 -1
  56. package/dist/{swimlanesDiagram-VR7AAH4N-BpRJP6KU.js → swimlanesDiagram-VR7AAH4N-BHlcd-Ri.js} +2 -2
  57. package/dist/{timeline-definition-24CTP7MA-Ckgh4lS4.js → timeline-definition-24CTP7MA-DMmP-G2O.js} +1 -1
  58. package/dist/{toast-DpczUryP.js → toast-DbBHmxmB.js} +1 -1
  59. package/dist/{useAsyncData-DsZMvNXn.js → useAsyncData-BYIAoMqn.js} +1 -1
  60. package/dist/{useDateFormatter-Dk_xFci4.js → useDateFormatter-ButWkdcK.js} +1 -1
  61. package/dist/{useDeepCompareMemoize-KMBBux8C.js → useDeepCompareMemoize-Bz0c5GN6.js} +1 -1
  62. package/dist/{useTheme-BZ2GGLgm.js → useTheme-DPLobSFs.js} +7 -7
  63. package/dist/{utils-DXkj82sK.js → utils-EBklsC5R.js} +31 -31
  64. package/dist/{vega-component-CF9kI6C4.js → vega-component-rxIxAAh9.js} +6 -6
  65. package/dist/{vennDiagram-4TSXK5OY-CDei2Bt3.js → vennDiagram-4TSXK5OY-Db8GtH1G.js} +1 -1
  66. package/dist/{wardleyDiagram-VM6X3IG4-CXavT601.js → wardleyDiagram-VM6X3IG4-DmIiC3FU.js} +1 -1
  67. package/dist/{xychartDiagram-S5SC5T6Z-CvJhcZri.js → xychartDiagram-S5SC5T6Z-DS9OPrNq.js} +1 -1
  68. package/package.json +1 -1
  69. package/src/__mocks__/executions.ts +195 -0
  70. package/src/__mocks__/notebook.ts +0 -1
  71. package/src/__tests__/CellStatus.test.tsx +19 -20
  72. package/src/components/dependency-graph/minimap-content.tsx +3 -2
  73. package/src/components/editor/__tests__/data-attributes.test.tsx +0 -7
  74. package/src/components/editor/__tests__/output-persistence.test.tsx +2 -2
  75. package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +1 -0
  76. package/src/components/editor/actions/useCellActionButton.tsx +7 -3
  77. package/src/components/editor/alerts/stdin-blocking-alert.tsx +3 -1
  78. package/src/components/editor/cell/CellStatus.tsx +23 -19
  79. package/src/components/editor/cell/RunButton.tsx +16 -6
  80. package/src/components/editor/cell/__tests__/useRunCells.test.ts +45 -0
  81. package/src/components/editor/cell/cell-context-menu.tsx +4 -1
  82. package/src/components/editor/cell/code/cell-editor.tsx +7 -5
  83. package/src/components/editor/cell/collapse.tsx +4 -0
  84. package/src/components/editor/cell/useRunCells.ts +18 -3
  85. package/src/components/editor/chrome/wrapper/sidebar.tsx +2 -4
  86. package/src/components/editor/header/status.tsx +4 -2
  87. package/src/components/editor/navigation/navigation.ts +3 -2
  88. package/src/components/editor/notebook-cell.tsx +82 -83
  89. package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
  90. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +22 -16
  91. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
  92. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +12 -33
  93. package/src/components/editor/stdin-blocking-alert.tsx +3 -1
  94. package/src/components/scratchpad/scratchpad.tsx +4 -1
  95. package/src/components/slides/minimap.tsx +4 -2
  96. package/src/components/slides/reveal-component.tsx +14 -10
  97. package/src/components/slides/slide-cell-view.tsx +28 -24
  98. package/src/components/slides/slide.tsx +3 -4
  99. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -389
  100. package/src/core/cells/__tests__/cell.test.ts +49 -154
  101. package/src/core/cells/__tests__/cells.test.ts +18 -127
  102. package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
  103. package/src/core/cells/__tests__/utils.test.ts +75 -247
  104. package/src/core/cells/actions.ts +5 -2
  105. package/src/core/cells/cell.ts +31 -133
  106. package/src/core/cells/cells.ts +14 -29
  107. package/src/core/cells/document.ts +3 -3
  108. package/src/core/cells/focus.ts +27 -6
  109. package/src/core/cells/layout.ts +1 -1
  110. package/src/core/cells/pending-delete-service.ts +5 -7
  111. package/src/core/cells/types.ts +13 -36
  112. package/src/core/cells/utils.ts +37 -68
  113. package/src/core/edit-app.tsx +2 -1
  114. package/src/core/executions/__tests__/atoms.test.ts +99 -0
  115. package/src/core/executions/__tests__/select.test.ts +268 -0
  116. package/src/core/executions/atoms.ts +206 -0
  117. package/src/core/executions/hooks.ts +31 -0
  118. package/src/core/executions/index.ts +31 -0
  119. package/src/core/executions/select.ts +175 -0
  120. package/src/core/export/__tests__/hooks.test.ts +0 -5
  121. package/src/core/islands/bootstrap.ts +4 -1
  122. package/src/core/islands/components/output-wrapper.tsx +5 -5
  123. package/src/core/kernel/handlers.ts +2 -11
  124. package/src/core/kernel/state.ts +0 -15
  125. package/src/core/lifecycle/render-policy.ts +12 -26
  126. package/src/core/network/__tests__/requests-lazy.test.ts +5 -5
  127. package/src/core/network/requests-lazy.ts +3 -3
  128. package/src/core/notebook/operations.ts +1 -1
  129. package/src/core/run-app.tsx +2 -1
  130. package/src/core/runtime/__tests__/adapter.test.ts +3 -3
  131. package/src/core/runtime/adapter.ts +4 -4
  132. package/src/core/session/useNotebookSession.tsx +3 -3
  133. package/src/core/wasm/bridge.ts +1 -1
  134. package/src/plugins/core/RenderHTML.tsx +3 -5
  135. package/src/plugins/core/__test__/RenderHTML-copy.test.tsx +60 -0
  136. package/src/plugins/core/registerReactComponent.tsx +4 -13
  137. package/src/stories/cell-status.stories.tsx +17 -10
  138. package/src/stories/cell.stories.tsx +0 -31
  139. package/src/stories/layout/vertical/one-column.stories.tsx +0 -9
  140. package/src/utils/time.ts +10 -0
@@ -15,6 +15,12 @@ import {
15
15
  it,
16
16
  vi,
17
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";
18
24
  import { MockNotebook } from "@/__mocks__/notebook";
19
25
  import { cellId } from "@/__tests__/branded";
20
26
  import type { CellHandle } from "@/components/editor/notebook-cell";
@@ -293,7 +299,6 @@ describe("cell reducer", () => {
293
299
  /////////////////
294
300
  // Initial state
295
301
  let cell = cells[0];
296
- expect(cell.status).toBe("idle");
297
302
  expect(cell.lastCodeRun).toBe(null);
298
303
  expect(cell.edited).toBe(false);
299
304
  expect(cell).toMatchSnapshot("initial state");
@@ -301,7 +306,6 @@ describe("cell reducer", () => {
301
306
  // Update code
302
307
  editCode(firstCellId, "import marimo as mo");
303
308
  cell = cells[0];
304
- expect(cell.status).toBe("idle");
305
309
  expect(cell.lastCodeRun).toBe(null);
306
310
  expect(cell.edited).toBe(true);
307
311
  expect(cell).toMatchSnapshot("code edited");
@@ -311,7 +315,6 @@ describe("cell reducer", () => {
311
315
  cellId: firstCellId,
312
316
  });
313
317
  cell = cells[0];
314
- expect(cell.status).toBe("queued");
315
318
  expect(cell.lastCodeRun).toBe("import marimo as mo");
316
319
  expect(cell.edited).toBe(false);
317
320
  expect(cell).toMatchSnapshot("prepared for run");
@@ -326,12 +329,8 @@ describe("cell reducer", () => {
326
329
  timestamp: new Date(10).getTime() as Seconds,
327
330
  });
328
331
  cell = cells[0];
329
- expect(cell.status).toBe("queued");
330
332
  expect(cell.lastCodeRun).toBe("import marimo as mo");
331
333
  expect(cell.edited).toBe(false);
332
- expect(cell.runElapsedTimeMs).toBe(null);
333
- expect(cell.runStartTimestamp).toBe(null);
334
- expect(cell.lastRunStartTimestamp).toBe(null);
335
334
  expect(cell).toMatchSnapshot("queued message received");
336
335
 
337
336
  // Receive running messages
@@ -344,12 +343,8 @@ describe("cell reducer", () => {
344
343
  timestamp: new Date(20).getTime() as Seconds,
345
344
  });
346
345
  cell = cells[0];
347
- expect(cell.status).toBe("running");
348
346
  expect(cell.lastCodeRun).toBe("import marimo as mo");
349
347
  expect(cell.edited).toBe(false);
350
- expect(cell.runElapsedTimeMs).toBe(null);
351
- expect(cell.runStartTimestamp).toBe(20);
352
- expect(cell.lastRunStartTimestamp).toBe(20);
353
348
  expect(cell).toMatchSnapshot("running message received");
354
349
 
355
350
  // Console messages shouldn't transition status
@@ -367,11 +362,7 @@ describe("cell reducer", () => {
367
362
  timestamp: new Date(22).getTime() as Seconds,
368
363
  });
369
364
  cell = cells[0];
370
- expect(cell.status).toBe("running");
371
365
  expect(cell.edited).toBe(false);
372
- expect(cell.runElapsedTimeMs).toBe(null);
373
- expect(cell.runStartTimestamp).toBe(20);
374
- expect(cell.lastRunStartTimestamp).toBe(20);
375
366
  expect(cell).toMatchSnapshot("console message received");
376
367
 
377
368
  // Receive output messages
@@ -394,11 +385,7 @@ describe("cell reducer", () => {
394
385
  timestamp: new Date(33).getTime() as Seconds,
395
386
  });
396
387
  cell = cells[0];
397
- expect(cell.status).toBe("idle");
398
388
  expect(cell.edited).toBe(false);
399
- expect(cell.runElapsedTimeMs).toBe(13_000);
400
- expect(cell.runStartTimestamp).toBe(null);
401
- expect(cell.lastRunStartTimestamp).toBe(20);
402
389
  expect(cell).toMatchSnapshot("output received");
403
390
 
404
391
  // EDITING BACK AND FORTH
@@ -406,7 +393,6 @@ describe("cell reducer", () => {
406
393
  // Update code again
407
394
  editCode(firstCellId, "import marimo as mo\nimport numpy");
408
395
  cell = cells[0];
409
- expect(cell.status).toBe("idle");
410
396
  expect(cell.edited).toBe(true);
411
397
  expect(cell).toMatchSnapshot("code edited again");
412
398
 
@@ -419,7 +405,6 @@ describe("cell reducer", () => {
419
405
  // Update code should be edited again
420
406
  editCode(firstCellId, "import marimo as mo\nimport numpy");
421
407
  cell = cells[0];
422
- expect(cell.status).toBe("idle");
423
408
  expect(cell.lastCodeRun).toBe("import marimo as mo");
424
409
  expect(cell.edited).toBe(true);
425
410
  expect(cell).toMatchSnapshot("code changed after revert");
@@ -472,11 +457,8 @@ describe("cell reducer", () => {
472
457
  });
473
458
  cell = cells[0];
474
459
  expect(cell.output).not.toBe(null); // keep old output
475
- expect(cell.status).toBe("idle");
476
460
  expect(cell.lastCodeRun).toBe("import marimo as mo\nimport numpy");
477
461
  expect(cell.edited).toBe(false);
478
- expect(cell.runElapsedTimeMs).toBe(11_000);
479
- expect(cell.runStartTimestamp).toBe(null);
480
462
  expect(cell).toMatchSnapshot("error response received");
481
463
 
482
464
  // INTERRUPT RESPONSE
@@ -524,73 +506,11 @@ describe("cell reducer", () => {
524
506
  timestamp: new Date(61).getTime() as Seconds,
525
507
  });
526
508
  cell = cells[0];
527
- expect(cell.status).toBe("idle");
528
509
  expect(cell.lastCodeRun).toBe(cell.code);
529
510
  expect(cell.edited).toBe(false);
530
- expect(cell.runElapsedTimeMs).toBe(11_000);
531
- expect(cell.runStartTimestamp).toBe(null);
532
511
  expect(cell).toMatchSnapshot("interruption response received");
533
512
  });
534
513
 
535
- it("errors reset status to idle", () => {
536
- // Initial state
537
- let cell = cells[0];
538
- expect(cell.status).toBe("idle");
539
- expect(cell.lastCodeRun).toBe(null);
540
- expect(cell.edited).toBe(false);
541
- expect(cell).toMatchSnapshot("initial state");
542
-
543
- // Update code
544
- editCode(firstCellId, "import marimo as mo");
545
- cell = cells[0];
546
- expect(cell.status).toBe("idle");
547
- expect(cell.lastCodeRun).toBe(null);
548
- expect(cell.edited).toBe(true);
549
- expect(cell).toMatchSnapshot("code edited");
550
-
551
- // Prepare for run
552
- actions.prepareForRun({
553
- cellId: firstCellId,
554
- });
555
- cell = cells[0];
556
- expect(cell.status).toBe("queued");
557
- expect(cell.lastCodeRun).toBe("import marimo as mo");
558
- expect(cell.edited).toBe(false);
559
- expect(cell).toMatchSnapshot("prepared for run");
560
-
561
- // ERROR RESPONSE
562
- //
563
- // should reset status to idle
564
- /////////////////
565
- // Prepare for run
566
- actions.prepareForRun({
567
- cellId: firstCellId,
568
- });
569
- cell = cells[0];
570
- // Receive error
571
- actions.handleCellMessage({
572
- cell_id: firstCellId,
573
- output: {
574
- channel: "marimo-error",
575
- mimetype: "application/vnd.marimo+error",
576
- data: [
577
- { type: "exception", exception_type: "SyntaxError", msg: "Oh no!" },
578
- ],
579
- timestamp: 0,
580
- },
581
- console: null,
582
- stale_inputs: null,
583
- timestamp: new Date(61).getTime() as Seconds,
584
- });
585
- cell = cells[0];
586
- expect(cell.status).toBe("idle");
587
- expect(cell.lastCodeRun).toBe("import marimo as mo");
588
- expect(cell.edited).toBe(false);
589
- expect(cell.runElapsedTimeMs).toBe(null);
590
- expect(cell.runStartTimestamp).toBe(null);
591
- expect(cell).toMatchSnapshot("error response received");
592
- });
593
-
594
514
  it("can run a stale cell", () => {
595
515
  // Update code of first cell
596
516
  editCode(firstCellId, "import marimo as mo");
@@ -618,11 +538,8 @@ describe("cell reducer", () => {
618
538
  timestamp: new Date(10).getTime() as Seconds,
619
539
  });
620
540
  let cell = cells[1];
621
- expect(cell.status).toBe("queued");
622
541
  expect(cell.lastCodeRun).toBe("mo.slider()");
623
542
  expect(cell.edited).toBe(false);
624
- expect(cell.runElapsedTimeMs).toBe(null);
625
- expect(cell.runStartTimestamp).toBe(null);
626
543
  expect(cell).toMatchSnapshot("queued message received");
627
544
 
628
545
  // Receive stale message
@@ -635,11 +552,8 @@ describe("cell reducer", () => {
635
552
  timestamp: new Date(20).getTime() as Seconds,
636
553
  });
637
554
  cell = cells[1];
638
- expect(cell.status).toBe("queued");
639
555
  expect(cell.lastCodeRun).toBe("mo.slider()");
640
556
  expect(cell.edited).toBe(false);
641
- expect(cell.runElapsedTimeMs).toBe(null);
642
- expect(cell.runStartTimestamp).toBe(null);
643
557
  expect(cell).toMatchSnapshot("stale inputs received");
644
558
  });
645
559
 
@@ -647,7 +561,6 @@ describe("cell reducer", () => {
647
561
  const firstCellId = cells[0].id;
648
562
  editCode(firstCellId, "import marimo as mo");
649
563
  let cell = cells[0];
650
- expect(cell.status).toBe("idle");
651
564
  expect(cell.lastCodeRun).toBe(null);
652
565
  expect(cell.edited).toBe(true);
653
566
 
@@ -676,14 +589,12 @@ describe("cell reducer", () => {
676
589
 
677
590
  // Check steady state
678
591
  cell = cells[0];
679
- expect(cell.status).toBe("idle");
680
592
  expect(cell.edited).toBe(false);
681
593
  expect(cell.lastCodeRun).toBe("import marimo as mo");
682
594
 
683
595
  // Format code
684
596
  formatCode(firstCellId, "import marimo as mo");
685
597
  cell = cells[0];
686
- expect(cell.status).toBe("idle");
687
598
  expect(cell.lastCodeRun).toBe("import marimo as mo");
688
599
  expect(cell.edited).toBe(false);
689
600
  });
@@ -707,13 +618,10 @@ describe("cell reducer", () => {
707
618
  timestamp: new Date(10).getTime() as Seconds,
708
619
  });
709
620
  let cell = cells[0];
710
- expect(cell.status).toBe("queued");
711
621
  expect(cell.lastCodeRun).toBe(
712
622
  "mo.md('This has an ancestor that was stopped')",
713
623
  );
714
624
  expect(cell.edited).toBe(false);
715
- expect(cell.runElapsedTimeMs).toBe(null);
716
- expect(cell.runStartTimestamp).toBe(null);
717
625
  expect(cell).toMatchSnapshot("queued message received");
718
626
 
719
627
  // Receive idle message
@@ -749,12 +657,10 @@ describe("cell reducer", () => {
749
657
  timestamp: new Date(20).getTime() as Seconds,
750
658
  });
751
659
  cell = cells[0];
752
- expect(cell.status).toBe("idle");
753
660
  // oxlint-disable-next-line typescript/no-explicit-any no-unsafe-optional-chaining
754
661
  expect((cell.output?.data as any)[0].msg).toBe(
755
662
  "This cell wasn't run because an ancestor was stopped with `mo.stop`: ",
756
663
  );
757
- expect(cell.stopped).toBe(true);
758
664
  expect(cell).toMatchSnapshot("ancestor stopped");
759
665
 
760
666
  // Receive queued message
@@ -767,8 +673,6 @@ describe("cell reducer", () => {
767
673
  timestamp: new Date(30).getTime() as Seconds,
768
674
  });
769
675
  cell = cells[0];
770
- expect(cell.status).toBe("queued");
771
- expect(cell.stopped).toBe(true);
772
676
  expect(cell).toMatchSnapshot("queued after stop");
773
677
 
774
678
  // Receive running message
@@ -781,8 +685,6 @@ describe("cell reducer", () => {
781
685
  timestamp: new Date(40).getTime() as Seconds,
782
686
  });
783
687
  cell = cells[0];
784
- expect(cell.status).toBe("running");
785
- expect(cell.stopped).toBe(false);
786
688
  expect(cell.output).toBe(null);
787
689
  expect(cell).toMatchSnapshot("running after stop");
788
690
  });
@@ -809,7 +711,6 @@ describe("cell reducer", () => {
809
711
 
810
712
  // Initial state
811
713
  let cell = cells[0];
812
- expect(cell.status).toBe("idle");
813
714
  expect(cell.consoleOutputs).toEqual([]);
814
715
  expect(cell).toMatchSnapshot("initial state");
815
716
 
@@ -818,7 +719,6 @@ describe("cell reducer", () => {
818
719
  cellId: firstCellId,
819
720
  });
820
721
  cell = cells[0];
821
- expect(cell.status).toBe("queued");
822
722
  expect(cell.consoleOutputs).toEqual([]);
823
723
  expect(cell).toMatchSnapshot("prepared for run");
824
724
 
@@ -832,7 +732,6 @@ describe("cell reducer", () => {
832
732
  timestamp: new Date(10).getTime() as Seconds,
833
733
  });
834
734
  cell = cells[0];
835
- expect(cell.status).toBe("queued");
836
735
  expect(cell).toMatchSnapshot("queued message received");
837
736
 
838
737
  // Receive running messages
@@ -845,7 +744,6 @@ describe("cell reducer", () => {
845
744
  timestamp: new Date(20).getTime() as Seconds,
846
745
  });
847
746
  cell = cells[0];
848
- expect(cell.status).toBe("running");
849
747
  expect(cell).toMatchSnapshot("running message received");
850
748
 
851
749
  // Add console
@@ -858,12 +756,10 @@ describe("cell reducer", () => {
858
756
  timestamp: new Date(22).getTime() as Seconds,
859
757
  });
860
758
  cell = cells[0];
861
- expect(cell.status).toBe("running");
862
759
  expect(cell).toMatchSnapshot("stdout received");
863
760
 
864
761
  cell = cells[0];
865
762
  expect(cell.consoleOutputs[0]).toMatchObject(STDOUT);
866
- expect(cell.status).toBe("running");
867
763
  expect(cell).toMatchSnapshot("stdout verified");
868
764
 
869
765
  // Ask via stdin
@@ -878,7 +774,6 @@ describe("cell reducer", () => {
878
774
  cell = cells[0];
879
775
  expect(cell.consoleOutputs[0]).toMatchObject(STDOUT);
880
776
  expect(cell.consoleOutputs[1]).toMatchObject(STD_IN_1);
881
- expect(cell.status).toBe("running");
882
777
  expect(cell).toMatchSnapshot("stdin requested");
883
778
 
884
779
  // Response to stdin
@@ -892,7 +787,6 @@ describe("cell reducer", () => {
892
787
  ...STD_IN_1,
893
788
  response: "Marimo!",
894
789
  });
895
- expect(cell.status).toBe("running");
896
790
  expect(cell).toMatchSnapshot("stdin answered");
897
791
 
898
792
  // Ask via stdin, again
@@ -910,7 +804,6 @@ describe("cell reducer", () => {
910
804
  { ...STD_IN_1, response: "Marimo!" },
911
805
  STD_IN_2,
912
806
  ]);
913
- expect(cell.status).toBe("running");
914
807
  expect(cell).toMatchSnapshot("second stdin requested");
915
808
 
916
809
  // Interrupt, so we respond with ""
@@ -928,7 +821,6 @@ describe("cell reducer", () => {
928
821
  timestamp: new Date(61).getTime() as Seconds,
929
822
  });
930
823
  cell = cells[0];
931
- expect(cell.status).toBe("idle");
932
824
  expect(cell.consoleOutputs).toMatchObject([
933
825
  STDOUT,
934
826
  { ...STD_IN_1, response: "Marimo!" },
@@ -1022,7 +914,6 @@ describe("cell reducer", () => {
1022
914
 
1023
915
  // Initial state
1024
916
  let cell = cells[0];
1025
- expect(cell.status).toBe("idle");
1026
917
  expect(cell.consoleOutputs).toEqual([]);
1027
918
  expect(cell).toMatchSnapshot("initial state");
1028
919
 
@@ -1041,7 +932,6 @@ describe("cell reducer", () => {
1041
932
  cellId: firstCellId,
1042
933
  });
1043
934
  cell = cells[0];
1044
- expect(cell.status).toBe("queued");
1045
935
  expect(cell.consoleOutputs).toMatchObject([OLD_STDOUT]); // Old stays there until it starts running
1046
936
  expect(cell).toMatchSnapshot("prepared for run");
1047
937
 
@@ -1055,7 +945,6 @@ describe("cell reducer", () => {
1055
945
  timestamp: new Date(10).getTime() as Seconds,
1056
946
  });
1057
947
  cell = cells[0];
1058
- expect(cell.status).toBe("queued");
1059
948
  expect(cell.consoleOutputs).toMatchObject([OLD_STDOUT]); // Old stays there until it starts running
1060
949
  expect(cell).toMatchSnapshot("queued message received");
1061
950
 
@@ -1069,7 +958,6 @@ describe("cell reducer", () => {
1069
958
  timestamp: new Date(20).getTime() as Seconds,
1070
959
  });
1071
960
  cell = cells[0];
1072
- expect(cell.status).toBe("running");
1073
961
  expect(cell.consoleOutputs).toMatchObject([]);
1074
962
  expect(cell).toMatchSnapshot("console cleared while running");
1075
963
 
@@ -1084,7 +972,6 @@ describe("cell reducer", () => {
1084
972
  });
1085
973
  cell = cells[0];
1086
974
  expect(cell.consoleOutputs).toMatchObject([STDOUT]);
1087
- expect(cell.status).toBe("idle");
1088
975
  expect(cell).toMatchSnapshot("console received while idle");
1089
976
  });
1090
977
 
@@ -1338,6 +1225,15 @@ describe("cell reducer", () => {
1338
1225
  expect(handleAtom2).toBe(handleAtom1);
1339
1226
  });
1340
1227
  });
1228
+ it("withdraws the submission of a cell that leaves the document", () => {
1229
+ MockExecutions.seed(store, []);
1230
+ submitCells(store, [firstCellId]);
1231
+ expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(1);
1232
+
1233
+ actions.reconcileDocument({ order: [], cells: new Map() });
1234
+
1235
+ expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(0);
1236
+ });
1341
1237
  });
1342
1238
 
1343
1239
  describe("createTracebackInfoAtom", () => {
@@ -1519,11 +1415,11 @@ describe("createTracebackInfoAtom", () => {
1519
1415
  data: [{ type: "syntax", msg: "Syntax error", lineno: 1 }],
1520
1416
  mimetype: "application/vnd.marimo+error",
1521
1417
  },
1522
- status: "queued",
1523
1418
  },
1524
1419
  },
1525
1420
  }),
1526
1421
  );
1422
+ MockExecutions.seed(store, [MockExecutions.queued(cellId("cell1"))]);
1527
1423
 
1528
1424
  const tracebackAtom = exportedForTesting.createTracebackInfoAtom(
1529
1425
  cellId("cell1"),
@@ -1551,11 +1447,11 @@ describe("createTracebackInfoAtom", () => {
1551
1447
  data: [{ type: "syntax", msg: "Syntax error", lineno: 1 }],
1552
1448
  mimetype: "application/vnd.marimo+error",
1553
1449
  },
1554
- status: "running",
1555
1450
  },
1556
1451
  },
1557
1452
  }),
1558
1453
  );
1454
+ MockExecutions.seed(store, [MockExecutions.running(cellId("cell1"))]);
1559
1455
 
1560
1456
  const tracebackAtom = exportedForTesting.createTracebackInfoAtom(
1561
1457
  cellId("cell1"),
@@ -1602,20 +1498,15 @@ describe("kernel-ready", () => {
1602
1498
  const state = hydratedState();
1603
1499
  const next = exportedForTesting.reducer(state, {
1604
1500
  type: "setLastRun",
1605
- payload: {
1606
- lastCodeRun: { [CELL_A]: "0" },
1607
- lastExecutionTime: { [CELL_A]: 5 },
1608
- },
1501
+ payload: { lastCodeRun: { [CELL_A]: "0" } },
1609
1502
  });
1610
1503
 
1611
1504
  expect(next.cellData[CELL_A]).toMatchObject({
1612
1505
  lastCodeRun: "0",
1613
- lastExecutionTime: 5,
1614
1506
  edited: true,
1615
1507
  });
1616
1508
  expect(next.cellData[CELL_B]).toMatchObject({
1617
1509
  lastCodeRun: null,
1618
- lastExecutionTime: null,
1619
1510
  edited: false,
1620
1511
  });
1621
1512
  expect(next.cellRuntime).toBe(state.cellRuntime);
@@ -3,13 +3,12 @@
3
3
  import { act, renderHook, waitFor } from "@testing-library/react";
4
4
  import { createStore, Provider } from "jotai";
5
5
  import { beforeEach, describe, expect, it, vi } from "vitest";
6
+ import { MockExecutions } from "@/__mocks__/executions";
6
7
  import { MockNotebook } from "@/__mocks__/notebook";
7
8
  import { variableName } from "@/__tests__/branded";
8
9
  import { notebookAtom } from "@/core/cells/cells";
9
10
  import { CellId } from "@/core/cells/ids";
10
- import { createCellRuntimeState } from "@/core/cells/types";
11
11
  import { variablesAtom } from "@/core/variables/state";
12
- import type { Milliseconds } from "@/utils/time";
13
12
  import {
14
13
  usePendingDelete,
15
14
  usePendingDeleteService,
@@ -46,9 +45,7 @@ describe("pending-delete-service", () => {
46
45
  },
47
46
  });
48
47
 
49
- notebook.cellRuntime[cellId] = createCellRuntimeState({
50
- runElapsedTimeMs: 1 as Milliseconds,
51
- });
48
+ MockExecutions.seed(store, [MockExecutions.took(cellId, 1)]);
52
49
 
53
50
  store.set(notebookAtom, notebook);
54
51
  store.set(variablesAtom, {});
@@ -82,9 +79,7 @@ describe("pending-delete-service", () => {
82
79
  },
83
80
  });
84
81
 
85
- notebook.cellRuntime[cellId] = createCellRuntimeState({
86
- runElapsedTimeMs: 100_000 as Milliseconds,
87
- });
82
+ MockExecutions.seed(store, [MockExecutions.took(cellId, 100_000)]);
88
83
 
89
84
  store.set(notebookAtom, notebook);
90
85
  store.set(variablesAtom, {});
@@ -129,12 +124,10 @@ describe("pending-delete-service", () => {
129
124
  });
130
125
 
131
126
  // Both have short execution times
132
- notebook.cellRuntime[cell1Id] = createCellRuntimeState({
133
- runElapsedTimeMs: 100 as Milliseconds,
134
- });
135
- notebook.cellRuntime[cell2Id] = createCellRuntimeState({
136
- runElapsedTimeMs: 50 as Milliseconds,
137
- });
127
+ MockExecutions.seed(store, [
128
+ MockExecutions.took(cell1Id, 100),
129
+ MockExecutions.took(cell2Id, 50),
130
+ ]);
138
131
 
139
132
  store.set(notebookAtom, notebook);
140
133
  store.set(variablesAtom, {
@@ -172,12 +165,10 @@ describe("pending-delete-service", () => {
172
165
  },
173
166
  });
174
167
 
175
- notebook.cellRuntime[cell1Id] = createCellRuntimeState({
176
- runElapsedTimeMs: 3000 as Milliseconds,
177
- });
178
- notebook.cellRuntime[cell2Id] = createCellRuntimeState({
179
- runElapsedTimeMs: 4000 as Milliseconds,
180
- });
168
+ MockExecutions.seed(store, [
169
+ MockExecutions.took(cell1Id, 3000),
170
+ MockExecutions.took(cell2Id, 4000),
171
+ ]);
181
172
 
182
173
  store.set(notebookAtom, notebook);
183
174
  store.set(variablesAtom, {});