@marimo-team/islands 0.25.3-dev170 → 0.25.3-dev175
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-BbSXV-Xa.js → ConnectedDataExplorerComponent-Le_OBfmt.js} +9 -9
- package/dist/{ErrorBoundary-NE86qEWZ.js → ErrorBoundary-DNvcAIsP.js} +8 -8
- package/dist/{abnfDiagram-VCTEODGH-D7n07nXf.js → abnfDiagram-VCTEODGH-Tf1ghyQQ.js} +2 -2
- package/dist/{any-language-editor-3E24SnCV.js → any-language-editor-BVFHDDQ3.js} +4 -4
- package/dist/{architectureDiagram-5GKGNRK7-D6CjRib5.js → architectureDiagram-5GKGNRK7-xlnbTG0T.js} +1 -1
- package/dist/{chat-ui-CC7GekpG.js → chat-ui-X-cWrL9u.js} +1218 -1218
- package/dist/{check-SpOMoCLP.js → check-C9Mp9eCK.js} +1 -1
- package/dist/{chunk-IMKFNOWR-6dtPz7uS.js → chunk-IMKFNOWR-Cmd4a5jy.js} +1 -1
- package/dist/{chunk-SHT3W25Y-BwnFNKDA.js → chunk-SHT3W25Y-mSNp-WpO.js} +1 -1
- package/dist/{chunk-SVP7TREG-D2eV4vBJ.js → chunk-SVP7TREG-CWC49D8X.js} +1 -1
- package/dist/{chunk-TICWLB2K-BDs4-_-r.js → chunk-TICWLB2K-De9FINtG.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-DCJnf_8v.js → classDiagram-ZZMXUADV-DweTkYdp.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-BOmSzPBD.js → classDiagram-v2-VYDZK3BY-A6MR2TiE.js} +2 -2
- package/dist/{code-visibility-Bzvc6ajl.js → code-visibility-CH1lmM1h.js} +5 -5
- package/dist/{common-Ciw4zkh2.js → common-DIrS1UR9.js} +1081 -1085
- package/dist/{copy-icon-C1trdvVt.js → copy-icon-De584pZ4.js} +2 -2
- package/dist/{cynefinDiagram-5FMLGOSQ-Bln_Soky.js → cynefinDiagram-5FMLGOSQ-BSvo5le-.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-D-nf7WzW.js → dagre-GXQ25YYZ-tXRQslO6.js} +1 -1
- package/dist/{data-grid-overlay-editor-AQREmxI7.js → data-grid-overlay-editor-DFLZvFK0.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-PsgSMkY2.js → diagram-S7CK7UJ4-r3t5VtwI.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-DfwfUuSw.js → diagram-UQ7AKVKN-qgbC8YnT.js} +1 -1
- package/dist/{diagram-VX7I27RA-C9_e-oMc.js → diagram-VX7I27RA-CiHxEwtp.js} +1 -1
- package/dist/{diagram-Z3DM3KII-CWLa5tuY.js → diagram-Z3DM3KII-D95u15Ev.js} +1 -1
- package/dist/{dialog-DgeqyrEZ.js → dialog-DVRfQuhD.js} +24 -24
- package/dist/{dist-F8Ep36rk.js → dist-B1M0bGO3.js} +1 -1
- package/dist/{dist-D6d86eNJ.js → dist-BA13RJj5.js} +1 -1
- package/dist/{dist-Bvs24R_E.js → dist-BJtmSgcE.js} +48 -48
- package/dist/{dist-CN_BeG2I.js → dist-Ba2VIn1K.js} +53 -53
- package/dist/{dist-PXYI_yuP.js → dist-Bj4bmwUm.js} +12 -12
- package/dist/{dist-DoE4XJBC.js → dist-BmS-ZGjl.js} +8626 -8626
- package/dist/{dist-BorMD-uX.js → dist-Bzogh7CW.js} +87 -87
- package/dist/{dist-CN8zI-XC.js → dist-CThPVKaP.js} +1385 -1382
- package/dist/{dist-DiDibOYr.js → dist-CTi5FTiV.js} +87 -87
- package/dist/{dist-diIx5qJW.js → dist-Ck_C32ye.js} +2 -2
- package/dist/{dist-BLfKmR-l.js → dist-D1fnFp1J.js} +1 -1
- package/dist/{dist-OR1OnN-y.js → dist-D3x9__Fu.js} +46 -46
- package/dist/{dist-BMQf5zIS.js → dist-D7mrh5sO.js} +36 -36
- package/dist/{dist-CSJ0MDRw.js → dist-D9Q3xjiP.js} +1 -1
- package/dist/{dist-BuaRHxOc.js → dist-DP60Ubh8.js} +2 -2
- package/dist/{dist-CSbh1PNP.js → dist-DTv9KkpW.js} +12 -12
- package/dist/{dist-D-wwqlzJ.js → dist-DVVwOfrD.js} +109 -109
- package/dist/{dist-C8fAKSH1.js → dist-DYXM73-k.js} +36 -36
- package/dist/{dist-DBtSl3sf.js → dist-DjeybPOb.js} +1 -1
- package/dist/{dist-CrSP_H1M.js → dist-DtGn9N4h.js} +197 -197
- package/dist/{dist-CLdpGQVr.js → dist-KN80qWCP.js} +2 -2
- package/dist/{dist-Cg7gzw-a.js → dist-O0qFpEJh.js} +56 -56
- package/dist/{dist-CkTTIdBe.js → dist-OUle2RT7.js} +207 -207
- package/dist/{dist-BK4Oj99o.js → dist-T5rh6JvL.js} +1 -1
- package/dist/{dropdown-menu-B6ftyzOg.js → dropdown-menu-DCMbbQ35.js} +691 -691
- package/dist/{ebnfDiagram-PWID7BFC-B1QRM58v.js → ebnfDiagram-PWID7BFC-P7e4bryK.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-DJK_FqvW.js → erDiagram-RLTQ6QDP-CUHZcmRj.js} +1 -1
- package/dist/{error-banner-D40pmfQQ.js → error-banner-DxJ3s8YO.js} +57 -57
- package/dist/{error-entries-DgK3wUJR.js → error-entries-mpoD5t79.js} +4985 -5006
- package/dist/{esm-D2gTsXEV.js → esm-Bbw_Njjx.js} +575 -575
- package/dist/{esm-AMFssoNp.js → esm-mDQNEFe_.js} +354 -354
- package/dist/{feedback-button-8a6SETmT.js → feedback-button-DL0DJ-LB.js} +30 -30
- package/dist/{flowDiagram-HODETNUW-Uxc25XSJ.js → flowDiagram-HODETNUW-BGZ95AzI.js} +2 -2
- package/dist/{formats-DQCyPd5Z.js → formats-DI7HEVv7.js} +1 -1
- package/dist/{glide-data-editor-B70oke_v.js → glide-data-editor-n4wnx19S.js} +10 -10
- package/dist/{glide-utils-Dz_F4pAY.js → glide-utils-D98laidb.js} +2 -2
- package/dist/{globals-Cxd5hNlI.js → globals-NCsYyjpB.js} +3 -3
- package/dist/{html-to-image-D4yG5Ru0.js → html-to-image-BoZthB4P.js} +467 -458
- package/dist/{infoDiagram-27XIBGKW-DmjxqwL0.js → infoDiagram-27XIBGKW-BF0YX70D.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-NgCLHqQi.js → ishikawaDiagram-5VMMS53U-_itsAAn-.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-CZaG-iam.js → kanban-definition-UXKFOSKX-VNW2Beqh.js} +1 -1
- package/dist/{label-D9_-zSg-.js → label-Qvw1E97W.js} +1 -1
- package/dist/main.js +8257 -6606
- package/dist/{mermaid-CSvw7c71.js → mermaid-CZ6FrClS.js} +35 -35
- package/dist/{mindmap-definition-YA3MSWOX-DJYQBDH_.js → mindmap-definition-YA3MSWOX-DR4ripvd.js} +1 -1
- package/dist/{number-overlay-editor-ChK-SKUk.js → number-overlay-editor-rlvo4mo3.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-CHKO_dAe.js → pegDiagram-XKGWAZYB-CFr3XlGl.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-DVevbMAo.js → pieDiagram-E7YTZNPT-j91XYSLY.js} +1 -1
- package/dist/{process-output-DxvBAeL3.js → process-output-DLS4Mqg_.js} +4 -4
- package/dist/{railroadDiagram-O6MQD6OU-Detj1kcB.js → railroadDiagram-O6MQD6OU-Cd47ZV9E.js} +2 -2
- package/dist/{requirementDiagram-BXWQKSXE-BLFD0T_Z.js → requirementDiagram-BXWQKSXE-eJH6gLtX.js} +1 -1
- package/dist/{reveal-component-CXMXeDZD.js → reveal-component-BJfmRUzb.js} +9 -9
- package/dist/{select-CkF_GBxO.js → select-2KOiReNY.js} +324 -324
- package/dist/{sequenceDiagram-WJ2MYXX4-BZBgatQV.js → sequenceDiagram-WJ2MYXX4-DdfFEIrm.js} +1 -1
- package/dist/{spec-Mnkn3XEr.js → spec-h69nC3SI.js} +4 -4
- package/dist/{stateDiagram-D77RDMKH-4BZW9-6_.js → stateDiagram-D77RDMKH-DkjDvip8.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-C4sKC8Iq.js → stateDiagram-v2-MP3YSRHH-DBHACnOo.js} +2 -2
- package/dist/{swimlanes-42K2YHIH-SL5yeGe2.js → swimlanes-42K2YHIH-ogImlOmp.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-DqPmAYUv.js → swimlanesDiagram-VR7AAH4N-D6x-zsci.js} +2 -2
- package/dist/{timeline-definition-24CTP7MA-BfXUMWkq.js → timeline-definition-24CTP7MA-DQpLtsHD.js} +1 -1
- package/dist/{toDate-TMubKIVL.js → toDate-CDzoofJo.js} +2 -2
- package/dist/{toast-Btbve3Lm.js → toast-B5t9o6s_.js} +47 -47
- package/dist/{tooltip-CJ4Rqasp.js → tooltip-s4zZxwKe.js} +67 -67
- package/dist/{use-restore-focus-CmGwRNId.js → use-restore-focus-BgDTd2tc.js} +1 -1
- package/dist/{useAsyncData-DjMGFzFy.js → useAsyncData-Bn8SxUqM.js} +1 -1
- package/dist/{useDateFormatter-eCL_SdeG.js → useDateFormatter-D3Tkfzej.js} +2 -2
- package/dist/{useDeepCompareMemoize-BQR5TJot.js → useDeepCompareMemoize-CC2tnPCk.js} +1 -1
- package/dist/{useLifecycle-C_GvKWbQ.js → useLifecycle-BJlxHqWa.js} +2 -2
- package/dist/{useTheme-Bns2gJZ6.js → useTheme-DMfQYmlG.js} +85 -85
- package/dist/{vega-component-BsVptuhz.js → vega-component-CovWHi60.js} +7 -7
- package/dist/{vennDiagram-4TSXK5OY-CH65znGa.js → vennDiagram-4TSXK5OY-BD-SL_vq.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-z9pWKb2_.js → wardleyDiagram-VM6X3IG4-BDgJV4ah.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-MxyaWjjq.js → xychartDiagram-S5SC5T6Z-1hIHN6Rl.js} +1 -1
- package/package.json +1 -1
- package/src/__mocks__/document.tsx +54 -0
- package/src/__mocks__/notebook.ts +2 -1
- package/src/__mocks__/requests.ts +0 -2
- package/src/components/chat/chat-panel.tsx +3 -3
- package/src/components/datasources/__tests__/column-preview.test.tsx +6 -8
- package/src/components/datasources/column-preview.tsx +4 -8
- package/src/components/datasources/datasources.tsx +4 -3
- package/src/components/dependency-graph/minimap-content.tsx +2 -6
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/editor/__tests__/Output.test.tsx +50 -32
- package/src/components/editor/__tests__/data-attributes.test.tsx +22 -11
- package/src/components/editor/__tests__/output-persistence.test.tsx +6 -1
- package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/useCellActionButton.tsx +20 -26
- package/src/components/editor/actions/useNotebookActions.tsx +13 -18
- package/src/components/editor/actions/useSetCodeVisibility.ts +10 -11
- package/src/components/editor/actions/useSetOutputsExpanded.ts +13 -18
- package/src/components/editor/cell/CreateCellButton.tsx +5 -9
- package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +3 -1
- package/src/components/editor/cell/code/cell-editor.tsx +13 -20
- 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 +2 -5
- package/src/components/editor/cell/useSplitCell.tsx +2 -1
- package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -11
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +3 -1
- package/src/components/editor/columns/sortable-column.tsx +1 -1
- package/src/components/editor/connections/components.tsx +4 -9
- package/src/components/editor/controls/Controls.tsx +1 -1
- package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +9 -3
- package/src/components/editor/documentation.css +34 -11
- package/src/components/editor/errors/auto-fix.tsx +4 -8
- package/src/components/editor/file-tree/file-explorer.tsx +3 -7
- package/src/components/editor/links/__tests__/cell-link.test.tsx +3 -1
- package/src/components/editor/links/cell-link.tsx +2 -1
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
- package/src/components/editor/navigation/__tests__/navigation.test.ts +73 -64
- package/src/components/editor/navigation/clipboard.ts +12 -11
- package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +11 -20
- package/src/components/editor/navigation/navigation.ts +20 -28
- package/src/components/editor/notebook-cell.tsx +7 -10
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
- package/src/components/editor/renderers/cell-array.tsx +10 -17
- package/src/components/markdown/markdown-renderer.tsx +4 -8
- package/src/components/pages/edit-page.tsx +32 -17
- package/src/components/scratchpad/scratchpad.test.tsx +3 -1
- package/src/components/scratchpad/scratchpad.tsx +4 -7
- package/src/components/slides/__tests__/minimap-actions.test.tsx +9 -25
- package/src/components/slides/minimap.tsx +7 -3
- package/src/components/slides/slide-cell-view.tsx +3 -3
- package/src/components/sort/SortableCellsProvider.tsx +2 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +18 -20
- package/src/core/ai/staged-cells.ts +8 -16
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +2 -2
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +2 -2
- package/src/core/ai/tools/base.ts +2 -2
- package/src/core/ai/tools/edit-notebook-tool.ts +13 -21
- package/src/core/cells/__tests__/actions.test.ts +474 -34
- package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
- package/src/core/cells/__tests__/cells.test.ts +251 -861
- package/src/core/cells/__tests__/document.test.ts +42 -38
- package/src/core/cells/__tests__/notebook-outline.test.ts +7 -1
- package/src/core/cells/__tests__/outputs.test.tsx +71 -53
- package/src/core/cells/actions.ts +391 -3
- package/src/core/cells/add-missing-import.ts +46 -42
- package/src/core/cells/cells.ts +73 -444
- package/src/core/cells/document.ts +38 -6
- package/src/core/cells/outputs.ts +12 -28
- package/src/core/codemirror/cells/extensions.ts +6 -6
- package/src/core/codemirror/cells/state.ts +1 -1
- package/src/core/codemirror/keymaps/vim.ts +2 -2
- package/src/core/edit-app.tsx +20 -25
- package/src/core/islands/__tests__/bootstrap.test.ts +56 -0
- package/src/core/islands/__tests__/bridge.test.ts +42 -0
- package/src/core/islands/bootstrap.ts +24 -1
- package/src/core/islands/bridge.ts +46 -5
- package/src/core/kernel/__tests__/handlers.test.ts +7 -153
- package/src/core/kernel/handlers.ts +18 -59
- package/src/core/network/__tests__/requests-lazy.test.ts +1 -3
- package/src/core/network/requests-lazy.ts +0 -2
- package/src/core/network/requests-network.ts +0 -16
- package/src/core/network/requests-static.ts +0 -2
- package/src/core/network/requests-toasting.tsx +0 -2
- package/src/core/network/types.ts +0 -7
- package/src/core/notebook/document/__tests__/codemirror.test.ts +5 -0
- package/src/core/notebook/document/__tests__/draft.test.ts +41 -0
- package/src/core/notebook/document/__tests__/state.test.ts +21 -0
- package/src/core/notebook/document/draft.ts +35 -5
- package/src/core/notebook/document/index.ts +1 -0
- package/src/core/notebook/document/state.ts +6 -2
- package/src/core/run-app.tsx +1 -7
- package/src/core/session/__tests__/useNotebookSession.hook.test.tsx +0 -6
- package/src/core/session/useNotebookSession.tsx +28 -35
- package/src/core/wasm/bridge.ts +0 -16
- package/src/css/globals.css +56 -22
- package/src/stories/runtime-story.tsx +22 -15
|
@@ -4,9 +4,11 @@ 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
10
|
beforeAll,
|
|
11
|
+
afterEach,
|
|
10
12
|
beforeEach,
|
|
11
13
|
describe,
|
|
12
14
|
expect,
|
|
@@ -16,11 +18,12 @@ import {
|
|
|
16
18
|
import { MockNotebook } from "@/__mocks__/notebook";
|
|
17
19
|
import { cellId } from "@/__tests__/branded";
|
|
18
20
|
import type { CellHandle } from "@/components/editor/notebook-cell";
|
|
19
|
-
import { CellId, SCRATCH_CELL_ID
|
|
21
|
+
import { CellId, SCRATCH_CELL_ID } from "@/core/cells/ids";
|
|
20
22
|
import { foldAllBulk, unfoldAllBulk } from "@/core/codemirror/editing/commands";
|
|
21
23
|
import { adaptiveLanguageConfiguration } from "@/core/codemirror/language/extension";
|
|
22
24
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
23
25
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
26
|
+
import type { CellConfig } from "@/core/network/types";
|
|
24
27
|
import {
|
|
25
28
|
type CollapsibleTree,
|
|
26
29
|
MultiColumn,
|
|
@@ -38,7 +41,12 @@ import {
|
|
|
38
41
|
scrollToBottom,
|
|
39
42
|
scrollToTop,
|
|
40
43
|
} from "../scrollCellIntoView";
|
|
41
|
-
import
|
|
44
|
+
import {
|
|
45
|
+
type CellData,
|
|
46
|
+
createCell,
|
|
47
|
+
createCellConfig,
|
|
48
|
+
createCellRuntimeState,
|
|
49
|
+
} from "../types";
|
|
42
50
|
|
|
43
51
|
vi.mock("@/core/codemirror/editing/commands", () => ({
|
|
44
52
|
foldAllBulk: vi.fn(),
|
|
@@ -119,8 +127,7 @@ describe("cell reducer", () => {
|
|
|
119
127
|
let cells: ReturnType<typeof flattenTopLevelNotebookCells>;
|
|
120
128
|
let firstCellId: CellId;
|
|
121
129
|
|
|
122
|
-
const
|
|
123
|
-
state = reducer(state, action);
|
|
130
|
+
const mountEditors = () => {
|
|
124
131
|
for (const [cellIdString, handle] of Object.entries(state.cellHandles)) {
|
|
125
132
|
// @ts-expect-error - Typescript Object.entries doesn't know that keys are CellId
|
|
126
133
|
const cid: CellId = cellIdString;
|
|
@@ -134,7 +141,76 @@ describe("cell reducer", () => {
|
|
|
134
141
|
}
|
|
135
142
|
}
|
|
136
143
|
cells = flattenTopLevelNotebookCells(state);
|
|
137
|
-
}
|
|
144
|
+
};
|
|
145
|
+
const actions = createActions((action) => {
|
|
146
|
+
state = reducer(state, action);
|
|
147
|
+
mountEditors();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
/** Put a cell into the notebook the way the document would. */
|
|
151
|
+
function seedCell({
|
|
152
|
+
cellId,
|
|
153
|
+
before,
|
|
154
|
+
code = "",
|
|
155
|
+
name,
|
|
156
|
+
config,
|
|
157
|
+
newCellId,
|
|
158
|
+
hideCode,
|
|
159
|
+
autoFocus = true,
|
|
160
|
+
}: {
|
|
161
|
+
cellId: CellId | "__end__" | { type: "__end__"; columnId: CellColumnId };
|
|
162
|
+
before: boolean;
|
|
163
|
+
code?: string;
|
|
164
|
+
name?: string;
|
|
165
|
+
config?: CellConfig;
|
|
166
|
+
newCellId?: CellId;
|
|
167
|
+
hideCode?: boolean;
|
|
168
|
+
autoFocus?: boolean;
|
|
169
|
+
}): CellId {
|
|
170
|
+
let column: CollapsibleTree<CellId>;
|
|
171
|
+
let cellIndex: number;
|
|
172
|
+
if (cellId === "__end__") {
|
|
173
|
+
column = state.cellIds.atOrThrow(0);
|
|
174
|
+
cellIndex = column.length;
|
|
175
|
+
} else if (typeof cellId === "string") {
|
|
176
|
+
column = state.cellIds.findWithId(cellId);
|
|
177
|
+
cellIndex = column.topLevelIds.indexOf(cellId);
|
|
178
|
+
} else {
|
|
179
|
+
column = state.cellIds.get(cellId.columnId) ?? state.cellIds.atOrThrow(0);
|
|
180
|
+
cellIndex = column.length;
|
|
181
|
+
}
|
|
182
|
+
const id = newCellId ?? CellId.create();
|
|
183
|
+
state = {
|
|
184
|
+
...state,
|
|
185
|
+
cellIds: state.cellIds.insertId(
|
|
186
|
+
id,
|
|
187
|
+
column.id,
|
|
188
|
+
before ? cellIndex : cellIndex + 1,
|
|
189
|
+
),
|
|
190
|
+
cellData: {
|
|
191
|
+
...state.cellData,
|
|
192
|
+
[id]: createCell({
|
|
193
|
+
id,
|
|
194
|
+
code,
|
|
195
|
+
name,
|
|
196
|
+
config: createCellConfig({
|
|
197
|
+
...config,
|
|
198
|
+
...(hideCode != null && { hide_code: hideCode }),
|
|
199
|
+
}),
|
|
200
|
+
edited: Boolean(code),
|
|
201
|
+
}),
|
|
202
|
+
},
|
|
203
|
+
cellRuntime: { ...state.cellRuntime, [id]: createCellRuntimeState() },
|
|
204
|
+
cellHandles: { ...state.cellHandles, [id]: createRef() },
|
|
205
|
+
scrollKey: autoFocus ? id : null,
|
|
206
|
+
untouchedNewCells:
|
|
207
|
+
hideCode && autoFocus
|
|
208
|
+
? new Set([...state.untouchedNewCells, id])
|
|
209
|
+
: state.untouchedNewCells,
|
|
210
|
+
};
|
|
211
|
+
mountEditors();
|
|
212
|
+
return id;
|
|
213
|
+
}
|
|
138
214
|
|
|
139
215
|
let i = 0;
|
|
140
216
|
const originalCreate = CellId.create.bind(CellId);
|
|
@@ -150,7 +226,7 @@ describe("cell reducer", () => {
|
|
|
150
226
|
|
|
151
227
|
state = initialNotebookState();
|
|
152
228
|
state.cellIds = MultiColumn.from([]);
|
|
153
|
-
|
|
229
|
+
seedCell({ cellId: "__end__", before: false });
|
|
154
230
|
firstCellId = state.cellIds.inOrderIds[0];
|
|
155
231
|
});
|
|
156
232
|
|
|
@@ -158,181 +234,6 @@ describe("cell reducer", () => {
|
|
|
158
234
|
CellId.create = originalCreate;
|
|
159
235
|
});
|
|
160
236
|
|
|
161
|
-
it("can add a cell after another cell", () => {
|
|
162
|
-
actions.createNewCell({
|
|
163
|
-
cellId: firstCellId,
|
|
164
|
-
before: false,
|
|
165
|
-
});
|
|
166
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
167
|
-
"
|
|
168
|
-
[0] ''
|
|
169
|
-
|
|
170
|
-
[1] ''
|
|
171
|
-
"
|
|
172
|
-
`);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it("can add a cell to the end with code", () => {
|
|
176
|
-
actions.createNewCell({
|
|
177
|
-
cellId: "__end__",
|
|
178
|
-
code: "import numpy as np",
|
|
179
|
-
before: false,
|
|
180
|
-
});
|
|
181
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
182
|
-
"
|
|
183
|
-
[0] ''
|
|
184
|
-
|
|
185
|
-
[1] 'import numpy as np'
|
|
186
|
-
"
|
|
187
|
-
`);
|
|
188
|
-
|
|
189
|
-
// Cell should be added to the end and edited
|
|
190
|
-
expect(cells[1].code).toBe("import numpy as np");
|
|
191
|
-
expect(cells[1].edited).toBe(true);
|
|
192
|
-
expect(cells[1].lastCodeRun).toBe(null);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("can add a cell before another cell", () => {
|
|
196
|
-
actions.createNewCell({
|
|
197
|
-
cellId: firstCellId,
|
|
198
|
-
before: true,
|
|
199
|
-
});
|
|
200
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
201
|
-
"
|
|
202
|
-
[1] ''
|
|
203
|
-
|
|
204
|
-
[0] ''
|
|
205
|
-
"
|
|
206
|
-
`);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it("can add a cell with name and config", () => {
|
|
210
|
-
actions.createNewCell({
|
|
211
|
-
cellId: firstCellId,
|
|
212
|
-
before: false,
|
|
213
|
-
code: "x = 1",
|
|
214
|
-
name: "My Cell",
|
|
215
|
-
config: { hide_code: true, disabled: false },
|
|
216
|
-
});
|
|
217
|
-
const newCellId = state.cellIds.inOrderIds[1];
|
|
218
|
-
expect(state.cellData[newCellId].name).toBe("My Cell");
|
|
219
|
-
expect(state.cellData[newCellId].config.hide_code).toBe(true);
|
|
220
|
-
expect(state.cellData[newCellId].config.disabled).toBe(false);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it("can delete a Python cell and undo delete", () => {
|
|
224
|
-
actions.createNewCell({
|
|
225
|
-
cellId: firstCellId,
|
|
226
|
-
before: false,
|
|
227
|
-
});
|
|
228
|
-
actions.deleteCell({
|
|
229
|
-
cellId: firstCellId,
|
|
230
|
-
});
|
|
231
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
232
|
-
"
|
|
233
|
-
[1] ''
|
|
234
|
-
"
|
|
235
|
-
`);
|
|
236
|
-
|
|
237
|
-
// undo
|
|
238
|
-
actions.undoDeleteCell();
|
|
239
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
240
|
-
"
|
|
241
|
-
[2] ''
|
|
242
|
-
|
|
243
|
-
[1] ''
|
|
244
|
-
"
|
|
245
|
-
`);
|
|
246
|
-
|
|
247
|
-
// Verify scrollKey is set to the restored cell
|
|
248
|
-
expect(state.scrollKey).toBe("2");
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it("can delete a SQL cell and undo delete", () => {
|
|
252
|
-
actions.createNewCell({
|
|
253
|
-
cellId: firstCellId,
|
|
254
|
-
before: false,
|
|
255
|
-
code: `df = mo.sql("""SELECT * FROM table""")`,
|
|
256
|
-
});
|
|
257
|
-
const newCellId = state.cellIds.getColumns()[0].atOrThrow(1);
|
|
258
|
-
actions.deleteCell({
|
|
259
|
-
cellId: newCellId,
|
|
260
|
-
});
|
|
261
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
262
|
-
"
|
|
263
|
-
[0] ''
|
|
264
|
-
"
|
|
265
|
-
`);
|
|
266
|
-
|
|
267
|
-
// undo
|
|
268
|
-
actions.undoDeleteCell();
|
|
269
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
270
|
-
"
|
|
271
|
-
[0] ''
|
|
272
|
-
|
|
273
|
-
[2] 'df = mo.sql("""SELECT * FROM table""")'
|
|
274
|
-
"
|
|
275
|
-
`);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it("can delete a Markdown cell and undo delete", () => {
|
|
279
|
-
const text = "The quick brown fox jumps over the lazy dog.";
|
|
280
|
-
actions.createNewCell({
|
|
281
|
-
cellId: firstCellId,
|
|
282
|
-
before: false,
|
|
283
|
-
code: `mo.md(r"""${text}""")`,
|
|
284
|
-
});
|
|
285
|
-
const newCellId = state.cellIds.getColumns()[0].atOrThrow(1);
|
|
286
|
-
actions.deleteCell({
|
|
287
|
-
cellId: newCellId,
|
|
288
|
-
});
|
|
289
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
290
|
-
"
|
|
291
|
-
[0] ''
|
|
292
|
-
"
|
|
293
|
-
`);
|
|
294
|
-
|
|
295
|
-
// undo
|
|
296
|
-
actions.undoDeleteCell();
|
|
297
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
298
|
-
"
|
|
299
|
-
[0] ''
|
|
300
|
-
|
|
301
|
-
[2] 'mo.md(r"""The quick brown fox jumps over the lazy dog.""")'
|
|
302
|
-
"
|
|
303
|
-
`);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it("undo delete restores cell config (hide_code, disabled)", () => {
|
|
307
|
-
actions.createNewCell({
|
|
308
|
-
cellId: firstCellId,
|
|
309
|
-
before: false,
|
|
310
|
-
code: "x = 1",
|
|
311
|
-
});
|
|
312
|
-
const newCellId = state.cellIds.getColumns()[0].atOrThrow(1);
|
|
313
|
-
|
|
314
|
-
// Set config to hidden and disabled
|
|
315
|
-
actions.updateCellConfig({
|
|
316
|
-
cellId: newCellId,
|
|
317
|
-
config: { hide_code: true, disabled: true },
|
|
318
|
-
});
|
|
319
|
-
expect(state.cellData[newCellId].config.hide_code).toBe(true);
|
|
320
|
-
expect(state.cellData[newCellId].config.disabled).toBe(true);
|
|
321
|
-
|
|
322
|
-
// Delete the cell
|
|
323
|
-
actions.deleteCell({ cellId: newCellId });
|
|
324
|
-
expect(state.cellIds.inOrderIds).not.toContain(newCellId);
|
|
325
|
-
|
|
326
|
-
// Undo delete
|
|
327
|
-
actions.undoDeleteCell();
|
|
328
|
-
const restoredCellId =
|
|
329
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
330
|
-
|
|
331
|
-
// Config should be preserved
|
|
332
|
-
expect(state.cellData[restoredCellId].config.hide_code).toBe(true);
|
|
333
|
-
expect(state.cellData[restoredCellId].config.disabled).toBe(true);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
237
|
it("can update a cell", () => {
|
|
337
238
|
actions.updateCellCode({
|
|
338
239
|
cellId: firstCellId,
|
|
@@ -347,7 +248,7 @@ describe("cell reducer", () => {
|
|
|
347
248
|
});
|
|
348
249
|
|
|
349
250
|
it("can move a cell", () => {
|
|
350
|
-
|
|
251
|
+
seedCell({
|
|
351
252
|
cellId: firstCellId,
|
|
352
253
|
before: false,
|
|
353
254
|
});
|
|
@@ -461,11 +362,11 @@ describe("cell reducer", () => {
|
|
|
461
362
|
});
|
|
462
363
|
|
|
463
364
|
it("can drag and drop a cell", () => {
|
|
464
|
-
|
|
365
|
+
seedCell({
|
|
465
366
|
cellId: firstCellId,
|
|
466
367
|
before: false,
|
|
467
368
|
});
|
|
468
|
-
|
|
369
|
+
seedCell({
|
|
469
370
|
cellId: cellId("1"),
|
|
470
371
|
before: false,
|
|
471
372
|
});
|
|
@@ -511,11 +412,11 @@ describe("cell reducer", () => {
|
|
|
511
412
|
});
|
|
512
413
|
|
|
513
414
|
it("can move a cell to an exact index within a column", () => {
|
|
514
|
-
|
|
415
|
+
seedCell({
|
|
515
416
|
cellId: firstCellId,
|
|
516
417
|
before: false,
|
|
517
418
|
});
|
|
518
|
-
|
|
419
|
+
seedCell({
|
|
519
420
|
cellId: cellId("1"),
|
|
520
421
|
before: false,
|
|
521
422
|
});
|
|
@@ -539,11 +440,11 @@ describe("cell reducer", () => {
|
|
|
539
440
|
});
|
|
540
441
|
|
|
541
442
|
it("can move a cell to an exact index across columns", () => {
|
|
542
|
-
|
|
443
|
+
seedCell({
|
|
543
444
|
cellId: firstCellId,
|
|
544
445
|
before: false,
|
|
545
446
|
});
|
|
546
|
-
|
|
447
|
+
seedCell({
|
|
547
448
|
cellId: cellId("1"),
|
|
548
449
|
before: false,
|
|
549
450
|
});
|
|
@@ -572,11 +473,11 @@ describe("cell reducer", () => {
|
|
|
572
473
|
});
|
|
573
474
|
|
|
574
475
|
it("moveCellToIndex is a no-op when moving to the same position", () => {
|
|
575
|
-
|
|
476
|
+
seedCell({
|
|
576
477
|
cellId: firstCellId,
|
|
577
478
|
before: false,
|
|
578
479
|
});
|
|
579
|
-
|
|
480
|
+
seedCell({
|
|
580
481
|
cellId: cellId("1"),
|
|
581
482
|
before: false,
|
|
582
483
|
});
|
|
@@ -594,7 +495,7 @@ describe("cell reducer", () => {
|
|
|
594
495
|
});
|
|
595
496
|
|
|
596
497
|
it("moveCellToIndex is a no-op for an invalid columnId", () => {
|
|
597
|
-
|
|
498
|
+
seedCell({
|
|
598
499
|
cellId: firstCellId,
|
|
599
500
|
before: false,
|
|
600
501
|
});
|
|
@@ -611,11 +512,11 @@ describe("cell reducer", () => {
|
|
|
611
512
|
});
|
|
612
513
|
|
|
613
514
|
it("can move multiple cells relative to target", () => {
|
|
614
|
-
|
|
515
|
+
seedCell({
|
|
615
516
|
cellId: firstCellId,
|
|
616
517
|
before: false,
|
|
617
518
|
});
|
|
618
|
-
|
|
519
|
+
seedCell({
|
|
619
520
|
cellId: cellId("1"),
|
|
620
521
|
before: false,
|
|
621
522
|
});
|
|
@@ -646,143 +547,6 @@ describe("cell reducer", () => {
|
|
|
646
547
|
`);
|
|
647
548
|
});
|
|
648
549
|
|
|
649
|
-
it("can undo cut-paste (move with previousPlacements)", () => {
|
|
650
|
-
actions.createNewCell({
|
|
651
|
-
cellId: firstCellId,
|
|
652
|
-
before: false,
|
|
653
|
-
});
|
|
654
|
-
actions.createNewCell({
|
|
655
|
-
cellId: cellId("1"),
|
|
656
|
-
before: false,
|
|
657
|
-
});
|
|
658
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
659
|
-
"
|
|
660
|
-
[0] ''
|
|
661
|
-
|
|
662
|
-
[1] ''
|
|
663
|
-
|
|
664
|
-
[2] ''
|
|
665
|
-
"
|
|
666
|
-
`);
|
|
667
|
-
|
|
668
|
-
const col = state.cellIds.findWithId(firstCellId);
|
|
669
|
-
const previousPlacements = [
|
|
670
|
-
{
|
|
671
|
-
columnId: col.id,
|
|
672
|
-
index: col.indexOfOrThrow(
|
|
673
|
-
firstCellId,
|
|
674
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
675
|
-
},
|
|
676
|
-
{
|
|
677
|
-
columnId: col.id,
|
|
678
|
-
index: col.indexOfOrThrow(
|
|
679
|
-
cellId("1"),
|
|
680
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
681
|
-
},
|
|
682
|
-
];
|
|
683
|
-
|
|
684
|
-
actions.moveCellsRelativeTo({
|
|
685
|
-
cellIds: [firstCellId, cellId("1")],
|
|
686
|
-
targetCellId: cellId("2"),
|
|
687
|
-
position: "after",
|
|
688
|
-
previousPlacements,
|
|
689
|
-
});
|
|
690
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
691
|
-
"
|
|
692
|
-
[2] ''
|
|
693
|
-
|
|
694
|
-
[0] ''
|
|
695
|
-
|
|
696
|
-
[1] ''
|
|
697
|
-
"
|
|
698
|
-
`);
|
|
699
|
-
|
|
700
|
-
actions.undoDeleteCell();
|
|
701
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
702
|
-
"
|
|
703
|
-
[0] ''
|
|
704
|
-
|
|
705
|
-
[1] ''
|
|
706
|
-
|
|
707
|
-
[2] ''
|
|
708
|
-
"
|
|
709
|
-
`);
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
it("undo order: cut-paste then delete — first undo restores delete, second undo undoes move", () => {
|
|
713
|
-
actions.createNewCell({
|
|
714
|
-
cellId: firstCellId,
|
|
715
|
-
before: false,
|
|
716
|
-
});
|
|
717
|
-
actions.createNewCell({
|
|
718
|
-
cellId: cellId("1"),
|
|
719
|
-
before: false,
|
|
720
|
-
});
|
|
721
|
-
|
|
722
|
-
const col = state.cellIds.findWithId(firstCellId);
|
|
723
|
-
const previousPlacements = [
|
|
724
|
-
{
|
|
725
|
-
columnId: col.id,
|
|
726
|
-
index: col.indexOfOrThrow(
|
|
727
|
-
firstCellId,
|
|
728
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
729
|
-
},
|
|
730
|
-
{
|
|
731
|
-
columnId: col.id,
|
|
732
|
-
index: col.indexOfOrThrow(
|
|
733
|
-
cellId("1"),
|
|
734
|
-
) as import("@/utils/id-tree").CellIndex,
|
|
735
|
-
},
|
|
736
|
-
];
|
|
737
|
-
|
|
738
|
-
actions.moveCellsRelativeTo({
|
|
739
|
-
cellIds: [firstCellId, cellId("1")],
|
|
740
|
-
targetCellId: cellId("2"),
|
|
741
|
-
position: "after",
|
|
742
|
-
previousPlacements,
|
|
743
|
-
});
|
|
744
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
745
|
-
"
|
|
746
|
-
[2] ''
|
|
747
|
-
|
|
748
|
-
[0] ''
|
|
749
|
-
|
|
750
|
-
[1] ''
|
|
751
|
-
"
|
|
752
|
-
`);
|
|
753
|
-
|
|
754
|
-
actions.deleteCell({ cellId: cellId("2") });
|
|
755
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
756
|
-
"
|
|
757
|
-
[0] ''
|
|
758
|
-
|
|
759
|
-
[1] ''
|
|
760
|
-
"
|
|
761
|
-
`);
|
|
762
|
-
|
|
763
|
-
actions.undoDeleteCell();
|
|
764
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
765
|
-
"
|
|
766
|
-
[3] ''
|
|
767
|
-
|
|
768
|
-
[0] ''
|
|
769
|
-
|
|
770
|
-
[1] ''
|
|
771
|
-
"
|
|
772
|
-
`);
|
|
773
|
-
|
|
774
|
-
actions.undoDeleteCell();
|
|
775
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
776
|
-
"
|
|
777
|
-
[0] ''
|
|
778
|
-
|
|
779
|
-
[1] ''
|
|
780
|
-
|
|
781
|
-
[3] ''
|
|
782
|
-
"
|
|
783
|
-
`);
|
|
784
|
-
});
|
|
785
|
-
|
|
786
550
|
it("keeps error evidence after an edit and a new queued run", () => {
|
|
787
551
|
const code = "raise ValueError('old failure')";
|
|
788
552
|
const output: OutputMessage = {
|
|
@@ -1166,7 +930,7 @@ describe("cell reducer", () => {
|
|
|
1166
930
|
formattingChange: false,
|
|
1167
931
|
});
|
|
1168
932
|
// Add cell
|
|
1169
|
-
|
|
933
|
+
seedCell({
|
|
1170
934
|
cellId: firstCellId,
|
|
1171
935
|
before: false,
|
|
1172
936
|
});
|
|
@@ -1271,33 +1035,6 @@ describe("cell reducer", () => {
|
|
|
1271
1035
|
expect(cell.edited).toBe(false);
|
|
1272
1036
|
});
|
|
1273
1037
|
|
|
1274
|
-
it("can update a cells config", () => {
|
|
1275
|
-
const firstCellId = cells[0].id;
|
|
1276
|
-
let cell = cells[0];
|
|
1277
|
-
// Starts empty
|
|
1278
|
-
expect(cell.config).toEqual({
|
|
1279
|
-
disabled: false,
|
|
1280
|
-
hide_code: false,
|
|
1281
|
-
column: null,
|
|
1282
|
-
expand_output: false,
|
|
1283
|
-
});
|
|
1284
|
-
|
|
1285
|
-
actions.updateCellConfig({
|
|
1286
|
-
cellId: firstCellId,
|
|
1287
|
-
config: { disabled: true },
|
|
1288
|
-
});
|
|
1289
|
-
cell = cells[0];
|
|
1290
|
-
expect(cell.config.disabled).toBe(true);
|
|
1291
|
-
|
|
1292
|
-
// Revert
|
|
1293
|
-
actions.updateCellConfig({
|
|
1294
|
-
cellId: firstCellId,
|
|
1295
|
-
config: { disabled: false },
|
|
1296
|
-
});
|
|
1297
|
-
cell = cells[0];
|
|
1298
|
-
expect(cell.config.disabled).toBe(false);
|
|
1299
|
-
});
|
|
1300
|
-
|
|
1301
1038
|
it("can run a stopped cell", () => {
|
|
1302
1039
|
// Update code of first cell
|
|
1303
1040
|
actions.updateCellCode({
|
|
@@ -1703,8 +1440,8 @@ describe("cell reducer", () => {
|
|
|
1703
1440
|
});
|
|
1704
1441
|
|
|
1705
1442
|
it("can send a cell to the top", () => {
|
|
1706
|
-
|
|
1707
|
-
|
|
1443
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1444
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
1708
1445
|
actions.sendToTop({ cellId: cellId("2") });
|
|
1709
1446
|
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
1710
1447
|
"
|
|
@@ -1718,8 +1455,8 @@ describe("cell reducer", () => {
|
|
|
1718
1455
|
});
|
|
1719
1456
|
|
|
1720
1457
|
it("can send a cell to the bottom", () => {
|
|
1721
|
-
|
|
1722
|
-
|
|
1458
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1459
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
1723
1460
|
actions.sendToBottom({ cellId: firstCellId });
|
|
1724
1461
|
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
1725
1462
|
"
|
|
@@ -1733,8 +1470,8 @@ describe("cell reducer", () => {
|
|
|
1733
1470
|
});
|
|
1734
1471
|
|
|
1735
1472
|
it("can focus cells", () => {
|
|
1736
|
-
|
|
1737
|
-
|
|
1473
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1474
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
1738
1475
|
|
|
1739
1476
|
actions.focusCell({ cellId: cellId("1"), where: "before" });
|
|
1740
1477
|
expect(focusAndScrollCellIntoView).toHaveBeenCalledWith(
|
|
@@ -1750,11 +1487,6 @@ describe("cell reducer", () => {
|
|
|
1750
1487
|
expect(scrollToBottom).toHaveBeenCalled();
|
|
1751
1488
|
});
|
|
1752
1489
|
|
|
1753
|
-
it("can update cell name", () => {
|
|
1754
|
-
actions.updateCellName({ cellId: firstCellId, name: "Test Cell" });
|
|
1755
|
-
expect(state.cellData[firstCellId].name).toBe("Test Cell");
|
|
1756
|
-
});
|
|
1757
|
-
|
|
1758
1490
|
it("can fold and unfold all cells", () => {
|
|
1759
1491
|
actions.foldAll();
|
|
1760
1492
|
expect(foldAllBulk).toHaveBeenCalled();
|
|
@@ -1783,13 +1515,13 @@ describe("cell reducer", () => {
|
|
|
1783
1515
|
});
|
|
1784
1516
|
|
|
1785
1517
|
it("can collapse and expand cells", () => {
|
|
1786
|
-
|
|
1787
|
-
|
|
1518
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1519
|
+
seedCell({
|
|
1788
1520
|
cellId: cellId("1"),
|
|
1789
1521
|
before: false,
|
|
1790
1522
|
code: "# Header",
|
|
1791
1523
|
});
|
|
1792
|
-
|
|
1524
|
+
seedCell({
|
|
1793
1525
|
cellId: cellId("2"),
|
|
1794
1526
|
before: false,
|
|
1795
1527
|
code: "## Subheader",
|
|
@@ -1811,13 +1543,13 @@ describe("cell reducer", () => {
|
|
|
1811
1543
|
});
|
|
1812
1544
|
|
|
1813
1545
|
it("can collapse and expand all cells in multiple columns", () => {
|
|
1814
|
-
|
|
1815
|
-
|
|
1546
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1547
|
+
seedCell({
|
|
1816
1548
|
cellId: cellId("1"),
|
|
1817
1549
|
before: false,
|
|
1818
1550
|
code: "# First Column Header",
|
|
1819
1551
|
});
|
|
1820
|
-
|
|
1552
|
+
seedCell({
|
|
1821
1553
|
cellId: cellId("2"),
|
|
1822
1554
|
before: false,
|
|
1823
1555
|
code: "## First Column Subheader",
|
|
@@ -1825,12 +1557,12 @@ describe("cell reducer", () => {
|
|
|
1825
1557
|
|
|
1826
1558
|
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
1827
1559
|
|
|
1828
|
-
|
|
1560
|
+
seedCell({
|
|
1829
1561
|
cellId: cellId("3"),
|
|
1830
1562
|
before: false,
|
|
1831
1563
|
code: "# Second Column Header",
|
|
1832
1564
|
});
|
|
1833
|
-
|
|
1565
|
+
seedCell({
|
|
1834
1566
|
cellId: cellId("4"),
|
|
1835
1567
|
before: false,
|
|
1836
1568
|
code: "## Second Column Subheader",
|
|
@@ -1878,18 +1610,18 @@ describe("cell reducer", () => {
|
|
|
1878
1610
|
});
|
|
1879
1611
|
|
|
1880
1612
|
it("can collapse and expand nested cells in one call", () => {
|
|
1881
|
-
|
|
1882
|
-
|
|
1613
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1614
|
+
seedCell({
|
|
1883
1615
|
cellId: cellId("1"),
|
|
1884
1616
|
before: false,
|
|
1885
1617
|
code: "# Header",
|
|
1886
1618
|
});
|
|
1887
|
-
|
|
1619
|
+
seedCell({
|
|
1888
1620
|
cellId: cellId("2"),
|
|
1889
1621
|
before: false,
|
|
1890
1622
|
code: "## Subheader",
|
|
1891
1623
|
});
|
|
1892
|
-
|
|
1624
|
+
seedCell({
|
|
1893
1625
|
cellId: cellId("3"),
|
|
1894
1626
|
before: false,
|
|
1895
1627
|
code: "### Subsubheader",
|
|
@@ -1933,18 +1665,18 @@ describe("cell reducer", () => {
|
|
|
1933
1665
|
});
|
|
1934
1666
|
|
|
1935
1667
|
it("can collapse all cells when nested heading ranges end at the same cell", () => {
|
|
1936
|
-
|
|
1937
|
-
|
|
1668
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1669
|
+
seedCell({
|
|
1938
1670
|
cellId: cellId("1"),
|
|
1939
1671
|
before: false,
|
|
1940
1672
|
code: "# Header",
|
|
1941
1673
|
});
|
|
1942
|
-
|
|
1674
|
+
seedCell({
|
|
1943
1675
|
cellId: cellId("2"),
|
|
1944
1676
|
before: false,
|
|
1945
1677
|
code: "## Subheader",
|
|
1946
1678
|
});
|
|
1947
|
-
|
|
1679
|
+
seedCell({
|
|
1948
1680
|
cellId: cellId("3"),
|
|
1949
1681
|
before: false,
|
|
1950
1682
|
code: "### Subsubheader",
|
|
@@ -1998,23 +1730,23 @@ describe("cell reducer", () => {
|
|
|
1998
1730
|
});
|
|
1999
1731
|
|
|
2000
1732
|
it("can collapse all cells when a deep chain is followed by a later section", () => {
|
|
2001
|
-
|
|
2002
|
-
|
|
1733
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1734
|
+
seedCell({
|
|
2003
1735
|
cellId: cellId("1"),
|
|
2004
1736
|
before: false,
|
|
2005
1737
|
code: "# Header",
|
|
2006
1738
|
});
|
|
2007
|
-
|
|
1739
|
+
seedCell({
|
|
2008
1740
|
cellId: cellId("2"),
|
|
2009
1741
|
before: false,
|
|
2010
1742
|
code: "## Section A",
|
|
2011
1743
|
});
|
|
2012
|
-
|
|
1744
|
+
seedCell({
|
|
2013
1745
|
cellId: cellId("3"),
|
|
2014
1746
|
before: false,
|
|
2015
1747
|
code: "### Sub of A",
|
|
2016
1748
|
});
|
|
2017
|
-
|
|
1749
|
+
seedCell({
|
|
2018
1750
|
cellId: cellId("4"),
|
|
2019
1751
|
before: false,
|
|
2020
1752
|
code: "## Section B",
|
|
@@ -2077,8 +1809,8 @@ describe("cell reducer", () => {
|
|
|
2077
1809
|
});
|
|
2078
1810
|
|
|
2079
1811
|
it("can show hidden cells", () => {
|
|
2080
|
-
|
|
2081
|
-
|
|
1812
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1813
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2082
1814
|
actions.collapseCell({ cellId: firstCellId });
|
|
2083
1815
|
|
|
2084
1816
|
actions.showCellIfHidden({ cellId: cellId("1") });
|
|
@@ -2088,7 +1820,7 @@ describe("cell reducer", () => {
|
|
|
2088
1820
|
});
|
|
2089
1821
|
|
|
2090
1822
|
it("can split and undo split cells", () => {
|
|
2091
|
-
|
|
1823
|
+
seedCell({
|
|
2092
1824
|
cellId: firstCellId,
|
|
2093
1825
|
before: false,
|
|
2094
1826
|
code: "line1\nline2",
|
|
@@ -2155,9 +1887,9 @@ describe("cell reducer", () => {
|
|
|
2155
1887
|
});
|
|
2156
1888
|
|
|
2157
1889
|
it("can add a column breakpoint", () => {
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
1890
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1891
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
1892
|
+
seedCell({ cellId: cellId("2"), before: false });
|
|
2161
1893
|
|
|
2162
1894
|
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2163
1895
|
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
@@ -2202,16 +1934,16 @@ describe("cell reducer", () => {
|
|
|
2202
1934
|
|
|
2203
1935
|
it("cannot add a column breakpoint before the first cell", () => {
|
|
2204
1936
|
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2205
|
-
|
|
2206
|
-
|
|
1937
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1938
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2207
1939
|
actions.addColumnBreakpoint({ cellId: firstCellId });
|
|
2208
1940
|
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2209
1941
|
});
|
|
2210
1942
|
|
|
2211
1943
|
it("can delete a column", () => {
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
1944
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1945
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
1946
|
+
seedCell({ cellId: cellId("2"), before: false });
|
|
2215
1947
|
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2216
1948
|
|
|
2217
1949
|
expect(state.cellIds.getColumns().length).toBe(2);
|
|
@@ -2255,8 +1987,8 @@ describe("cell reducer", () => {
|
|
|
2255
1987
|
});
|
|
2256
1988
|
|
|
2257
1989
|
it("deleting the last column does nothing", () => {
|
|
2258
|
-
|
|
2259
|
-
|
|
1990
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
1991
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2260
1992
|
|
|
2261
1993
|
const initialState = { ...state };
|
|
2262
1994
|
|
|
@@ -2267,9 +1999,9 @@ describe("cell reducer", () => {
|
|
|
2267
1999
|
});
|
|
2268
2000
|
|
|
2269
2001
|
it("can drop a cell over another cell", () => {
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2002
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
2003
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2004
|
+
seedCell({ cellId: cellId("2"), before: false });
|
|
2273
2005
|
|
|
2274
2006
|
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2275
2007
|
"
|
|
@@ -2302,8 +2034,8 @@ describe("cell reducer", () => {
|
|
|
2302
2034
|
});
|
|
2303
2035
|
|
|
2304
2036
|
it("can drop a cell over a new column", () => {
|
|
2305
|
-
|
|
2306
|
-
|
|
2037
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
2038
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2307
2039
|
|
|
2308
2040
|
expect(state.cellIds.getColumns().length).toBe(1);
|
|
2309
2041
|
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
@@ -2340,9 +2072,9 @@ describe("cell reducer", () => {
|
|
|
2340
2072
|
});
|
|
2341
2073
|
|
|
2342
2074
|
it("can drop a column over another column", () => {
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2075
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
2076
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2077
|
+
seedCell({ cellId: cellId("2"), before: false });
|
|
2346
2078
|
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2347
2079
|
|
|
2348
2080
|
expect(state.cellIds.getColumns().length).toBe(2);
|
|
@@ -2393,8 +2125,8 @@ describe("cell reducer", () => {
|
|
|
2393
2125
|
|
|
2394
2126
|
it("can compact columns", () => {
|
|
2395
2127
|
// Create initial state with 3 columns, including an empty one
|
|
2396
|
-
|
|
2397
|
-
|
|
2128
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
2129
|
+
seedCell({ cellId: cellId("1"), before: false });
|
|
2398
2130
|
actions.addColumnBreakpoint({ cellId: cellId("1") });
|
|
2399
2131
|
actions.addColumnBreakpoint({ cellId: cellId("2") });
|
|
2400
2132
|
actions.dropOverNewColumn({ cellId: cellId("2") });
|
|
@@ -2533,7 +2265,7 @@ describe("cell reducer", () => {
|
|
|
2533
2265
|
|
|
2534
2266
|
it("can clear output of all cells", () => {
|
|
2535
2267
|
// Create multiple cells with output
|
|
2536
|
-
|
|
2268
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
2537
2269
|
const secondCellId = state.cellIds.atOrThrow(FIRST_COLUMN).atOrThrow(1);
|
|
2538
2270
|
|
|
2539
2271
|
// Add output to both cells
|
|
@@ -2580,121 +2312,9 @@ describe("cell reducer", () => {
|
|
|
2580
2312
|
expect(state.cellRuntime[secondCellId].consoleOutputs).toEqual([]);
|
|
2581
2313
|
});
|
|
2582
2314
|
|
|
2583
|
-
it("skips creating new cell if code exists and skipIfCodeExists is true", () => {
|
|
2584
|
-
// Add initial cell with code
|
|
2585
|
-
actions.updateCellCode({
|
|
2586
|
-
cellId: firstCellId,
|
|
2587
|
-
code: "import numpy as np",
|
|
2588
|
-
formattingChange: false,
|
|
2589
|
-
});
|
|
2590
|
-
|
|
2591
|
-
// Try to create new cell with same code and skipIfCodeExists
|
|
2592
|
-
actions.createNewCell({
|
|
2593
|
-
cellId: "__end__",
|
|
2594
|
-
code: "import numpy as np",
|
|
2595
|
-
before: false,
|
|
2596
|
-
skipIfCodeExists: true,
|
|
2597
|
-
});
|
|
2598
|
-
|
|
2599
|
-
// Should still only have one cell
|
|
2600
|
-
expect(state.cellIds.inOrderIds.length).toBe(1);
|
|
2601
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2602
|
-
"
|
|
2603
|
-
[0] 'import numpy as np'
|
|
2604
|
-
"
|
|
2605
|
-
`);
|
|
2606
|
-
|
|
2607
|
-
// Verify we can still add cell with different code
|
|
2608
|
-
actions.createNewCell({
|
|
2609
|
-
cellId: "__end__",
|
|
2610
|
-
code: "import pandas as pd",
|
|
2611
|
-
before: false,
|
|
2612
|
-
skipIfCodeExists: true,
|
|
2613
|
-
});
|
|
2614
|
-
|
|
2615
|
-
expect(state.cellIds.inOrderIds.length).toBe(2);
|
|
2616
|
-
expect(formatCells(state)).toMatchInlineSnapshot(`
|
|
2617
|
-
"
|
|
2618
|
-
[0] 'import numpy as np'
|
|
2619
|
-
|
|
2620
|
-
[1] 'import pandas as pd'
|
|
2621
|
-
"
|
|
2622
|
-
`);
|
|
2623
|
-
});
|
|
2624
|
-
|
|
2625
|
-
it("can create and noop-update a setup cell", () => {
|
|
2626
|
-
// Create the setup cell
|
|
2627
|
-
actions.addSetupCellIfDoesntExist({ code: "# Setup code" });
|
|
2628
|
-
|
|
2629
|
-
// Check that setup cell was created
|
|
2630
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2631
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2632
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2633
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2634
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2635
|
-
|
|
2636
|
-
// Update the setup cell
|
|
2637
|
-
actions.addSetupCellIfDoesntExist({ code: "# Updated setup code" });
|
|
2638
|
-
|
|
2639
|
-
// Check that the setup cell did not change, since it already exists
|
|
2640
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2641
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2642
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2643
|
-
});
|
|
2644
|
-
|
|
2645
|
-
it("can delete and undelete the setup cell", () => {
|
|
2646
|
-
// Create the setup cell
|
|
2647
|
-
actions.addSetupCellIfDoesntExist({ code: "# Setup code" });
|
|
2648
|
-
|
|
2649
|
-
// Check that setup cell was created
|
|
2650
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2651
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2652
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2653
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2654
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2655
|
-
|
|
2656
|
-
// Delete the setup cell
|
|
2657
|
-
actions.deleteCell({ cellId: SETUP_CELL_ID });
|
|
2658
|
-
|
|
2659
|
-
// Check that setup cell was deleted
|
|
2660
|
-
expect(state.cellData[SETUP_CELL_ID]).toBeDefined(); // we keep old state
|
|
2661
|
-
expect(state.cellIds.inOrderIds).not.toContain(SETUP_CELL_ID);
|
|
2662
|
-
|
|
2663
|
-
// Undo delete the setup cell
|
|
2664
|
-
actions.undoDeleteCell();
|
|
2665
|
-
|
|
2666
|
-
// Check that setup cell was restored
|
|
2667
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2668
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2669
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# Setup code");
|
|
2670
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2671
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2672
|
-
|
|
2673
|
-
// Verify scrollKey is set to the restored setup cell
|
|
2674
|
-
expect(state.scrollKey).toBe(SETUP_CELL_ID);
|
|
2675
|
-
});
|
|
2676
|
-
|
|
2677
|
-
it("can delete and then create a new setup cell", () => {
|
|
2678
|
-
// Create the setup cell
|
|
2679
|
-
actions.addSetupCellIfDoesntExist({ code: "# Setup code" });
|
|
2680
|
-
|
|
2681
|
-
// Delete the setup cell
|
|
2682
|
-
actions.deleteCell({ cellId: SETUP_CELL_ID });
|
|
2683
|
-
|
|
2684
|
-
// Create a new setup cell
|
|
2685
|
-
actions.addSetupCellIfDoesntExist({ code: "# New code" });
|
|
2686
|
-
|
|
2687
|
-
// Check that the new setup cell was created
|
|
2688
|
-
expect(state.cellData[SETUP_CELL_ID].id).toBe(SETUP_CELL_ID);
|
|
2689
|
-
expect(state.cellData[SETUP_CELL_ID].name).toBe("setup");
|
|
2690
|
-
expect(state.cellData[SETUP_CELL_ID].code).toBe("# New code");
|
|
2691
|
-
expect(state.cellData[SETUP_CELL_ID].edited).toBe(true);
|
|
2692
|
-
expect(state.cellIds.inOrderIds).toContain(SETUP_CELL_ID);
|
|
2693
|
-
});
|
|
2694
|
-
|
|
2695
2315
|
it("can clear all outputs", () => {
|
|
2696
2316
|
// Add a cell and give it output
|
|
2697
|
-
|
|
2317
|
+
seedCell({
|
|
2698
2318
|
cellId: firstCellId,
|
|
2699
2319
|
before: false,
|
|
2700
2320
|
});
|
|
@@ -2722,202 +2342,14 @@ describe("cell reducer", () => {
|
|
|
2722
2342
|
expect(state.cellRuntime[cell2Id].output).toBeNull();
|
|
2723
2343
|
});
|
|
2724
2344
|
|
|
2725
|
-
describe("moveToNextCell", () => {
|
|
2726
|
-
let cell1Id: CellId;
|
|
2727
|
-
let cell2Id: CellId;
|
|
2728
|
-
let cell3Id: CellId;
|
|
2729
|
-
|
|
2730
|
-
beforeEach(() => {
|
|
2731
|
-
// Create a few cells to work with
|
|
2732
|
-
actions.createNewCell({ cellId: "__end__", before: false });
|
|
2733
|
-
actions.createNewCell({ cellId: "__end__", before: false });
|
|
2734
|
-
|
|
2735
|
-
cell1Id = state.cellIds.inOrderIds[0];
|
|
2736
|
-
cell2Id = state.cellIds.inOrderIds[1];
|
|
2737
|
-
cell3Id = state.cellIds.inOrderIds[2];
|
|
2738
|
-
});
|
|
2739
|
-
|
|
2740
|
-
it("creates new cell when moving after last cell with noCreate=false", () => {
|
|
2741
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2742
|
-
|
|
2743
|
-
actions.moveToNextCell({
|
|
2744
|
-
cellId: cell3Id,
|
|
2745
|
-
before: false,
|
|
2746
|
-
noCreate: false,
|
|
2747
|
-
});
|
|
2748
|
-
|
|
2749
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount + 1);
|
|
2750
|
-
});
|
|
2751
|
-
|
|
2752
|
-
it("creates new cell when moving before first cell with noCreate=false", () => {
|
|
2753
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2754
|
-
|
|
2755
|
-
actions.moveToNextCell({
|
|
2756
|
-
cellId: cell1Id,
|
|
2757
|
-
before: true,
|
|
2758
|
-
noCreate: false,
|
|
2759
|
-
});
|
|
2760
|
-
|
|
2761
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount + 1);
|
|
2762
|
-
});
|
|
2763
|
-
|
|
2764
|
-
it("does not create new cell when moving after last cell with noCreate=true", () => {
|
|
2765
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2766
|
-
const initialState = { ...state };
|
|
2767
|
-
|
|
2768
|
-
actions.moveToNextCell({
|
|
2769
|
-
cellId: cell3Id,
|
|
2770
|
-
before: false,
|
|
2771
|
-
noCreate: true,
|
|
2772
|
-
});
|
|
2773
|
-
|
|
2774
|
-
// Should not create a new cell
|
|
2775
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount);
|
|
2776
|
-
// Should not crash or throw an error
|
|
2777
|
-
expect(state.cellIds.inOrderIds).toEqual(initialState.cellIds.inOrderIds);
|
|
2778
|
-
});
|
|
2779
|
-
|
|
2780
|
-
it("does not create new cell when moving before first cell with noCreate=true", () => {
|
|
2781
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2782
|
-
const initialState = { ...state };
|
|
2783
|
-
|
|
2784
|
-
actions.moveToNextCell({ cellId: cell1Id, before: true, noCreate: true });
|
|
2785
|
-
|
|
2786
|
-
// Should not create a new cell
|
|
2787
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount);
|
|
2788
|
-
// Should not crash or throw an error
|
|
2789
|
-
expect(state.cellIds.inOrderIds).toEqual(initialState.cellIds.inOrderIds);
|
|
2790
|
-
});
|
|
2791
|
-
|
|
2792
|
-
it("focuses next cell when moving within bounds", () => {
|
|
2793
|
-
const focusSpy = vi.mocked(focusAndScrollCellIntoView);
|
|
2794
|
-
focusSpy.mockClear();
|
|
2795
|
-
|
|
2796
|
-
actions.moveToNextCell({
|
|
2797
|
-
cellId: cell1Id,
|
|
2798
|
-
before: false,
|
|
2799
|
-
noCreate: true,
|
|
2800
|
-
});
|
|
2801
|
-
|
|
2802
|
-
expect(focusSpy).toHaveBeenCalledWith({
|
|
2803
|
-
cellId: cell2Id,
|
|
2804
|
-
cell: state.cellHandles[cell2Id],
|
|
2805
|
-
isCodeHidden: false,
|
|
2806
|
-
codeFocus: "top",
|
|
2807
|
-
variableName: undefined,
|
|
2808
|
-
});
|
|
2809
|
-
});
|
|
2810
|
-
|
|
2811
|
-
it("focuses previous cell when moving backward within bounds", () => {
|
|
2812
|
-
const focusSpy = vi.mocked(focusAndScrollCellIntoView);
|
|
2813
|
-
focusSpy.mockClear();
|
|
2814
|
-
|
|
2815
|
-
actions.moveToNextCell({ cellId: cell2Id, before: true, noCreate: true });
|
|
2816
|
-
|
|
2817
|
-
expect(focusSpy).toHaveBeenCalledWith({
|
|
2818
|
-
cellId: cell1Id,
|
|
2819
|
-
cell: state.cellHandles[cell1Id],
|
|
2820
|
-
isCodeHidden: false,
|
|
2821
|
-
codeFocus: "bottom",
|
|
2822
|
-
variableName: undefined,
|
|
2823
|
-
});
|
|
2824
|
-
});
|
|
2825
|
-
|
|
2826
|
-
it("does not move focus from scratch cell", () => {
|
|
2827
|
-
const focusSpy = vi.mocked(focusAndScrollCellIntoView);
|
|
2828
|
-
focusSpy.mockClear();
|
|
2829
|
-
const initialState = { ...state };
|
|
2830
|
-
|
|
2831
|
-
actions.moveToNextCell({
|
|
2832
|
-
cellId: SCRATCH_CELL_ID,
|
|
2833
|
-
before: false,
|
|
2834
|
-
noCreate: false,
|
|
2835
|
-
});
|
|
2836
|
-
|
|
2837
|
-
expect(focusSpy).not.toHaveBeenCalled();
|
|
2838
|
-
expect(state.cellIds.inOrderIds).toEqual(initialState.cellIds.inOrderIds);
|
|
2839
|
-
});
|
|
2840
|
-
});
|
|
2841
|
-
|
|
2842
2345
|
describe("untouched cells functionality", () => {
|
|
2843
2346
|
it("starts with empty untouchedNewCells set", () => {
|
|
2844
2347
|
expect(state.untouchedNewCells).toEqual(new Set());
|
|
2845
2348
|
});
|
|
2846
2349
|
|
|
2847
|
-
it("can create a new cell with hideCode option", () => {
|
|
2848
|
-
const initialCellCount = state.cellIds.inOrderIds.length;
|
|
2849
|
-
|
|
2850
|
-
actions.createNewCell({
|
|
2851
|
-
cellId: "__end__",
|
|
2852
|
-
before: false,
|
|
2853
|
-
hideCode: true,
|
|
2854
|
-
});
|
|
2855
|
-
|
|
2856
|
-
expect(state.cellIds.inOrderIds.length).toBe(initialCellCount + 1);
|
|
2857
|
-
const newCellId =
|
|
2858
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
2859
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
2860
|
-
});
|
|
2861
|
-
|
|
2862
|
-
it("adds interactively-created hidden cell with boilerplate code to untouchedNewCells", () => {
|
|
2863
|
-
// Markdown cells are created with hideCode and non-empty default code
|
|
2864
|
-
// (e.g. `mo.md(r"""\n""")`). They are user-initiated, so their editor
|
|
2865
|
-
// should be shown until first blur.
|
|
2866
|
-
actions.createNewCell({
|
|
2867
|
-
cellId: "__end__",
|
|
2868
|
-
before: false,
|
|
2869
|
-
code: 'mo.md(r"""\n""")',
|
|
2870
|
-
hideCode: true,
|
|
2871
|
-
autoFocus: true,
|
|
2872
|
-
});
|
|
2873
|
-
|
|
2874
|
-
const newCellId =
|
|
2875
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
2876
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
2877
|
-
});
|
|
2878
|
-
|
|
2879
|
-
it("does not add programmatically-created hidden cell with code to untouchedNewCells", () => {
|
|
2880
|
-
// Cells created by the kernel (e.g. via code_mode) carry code and
|
|
2881
|
-
// autoFocus=false; their hide_code must take effect immediately.
|
|
2882
|
-
actions.createNewCell({
|
|
2883
|
-
cellId: "__end__",
|
|
2884
|
-
before: false,
|
|
2885
|
-
code: "x = 1",
|
|
2886
|
-
hideCode: true,
|
|
2887
|
-
autoFocus: false,
|
|
2888
|
-
});
|
|
2889
|
-
|
|
2890
|
-
const newCellId =
|
|
2891
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
2892
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
2893
|
-
});
|
|
2894
|
-
|
|
2895
|
-
it("does not add cell to untouchedNewCells when hideCode is false", () => {
|
|
2896
|
-
actions.createNewCell({
|
|
2897
|
-
cellId: "__end__",
|
|
2898
|
-
before: false,
|
|
2899
|
-
hideCode: false,
|
|
2900
|
-
});
|
|
2901
|
-
|
|
2902
|
-
const newCellId =
|
|
2903
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
2904
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
2905
|
-
});
|
|
2906
|
-
|
|
2907
|
-
it("does not add cell to untouchedNewCells when hideCode is undefined", () => {
|
|
2908
|
-
actions.createNewCell({
|
|
2909
|
-
cellId: "__end__",
|
|
2910
|
-
before: false,
|
|
2911
|
-
});
|
|
2912
|
-
|
|
2913
|
-
const newCellId =
|
|
2914
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
2915
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(false);
|
|
2916
|
-
});
|
|
2917
|
-
|
|
2918
2350
|
it("can mark a cell as touched", () => {
|
|
2919
2351
|
// Create a cell with hideCode
|
|
2920
|
-
|
|
2352
|
+
seedCell({
|
|
2921
2353
|
cellId: "__end__",
|
|
2922
2354
|
before: false,
|
|
2923
2355
|
hideCode: true,
|
|
@@ -2935,7 +2367,7 @@ describe("cell reducer", () => {
|
|
|
2935
2367
|
|
|
2936
2368
|
it("markTouched is idempotent", () => {
|
|
2937
2369
|
// Create a cell with hideCode
|
|
2938
|
-
|
|
2370
|
+
seedCell({
|
|
2939
2371
|
cellId: "__end__",
|
|
2940
2372
|
before: false,
|
|
2941
2373
|
hideCode: true,
|
|
@@ -2965,17 +2397,17 @@ describe("cell reducer", () => {
|
|
|
2965
2397
|
|
|
2966
2398
|
it("can handle multiple untouched cells", () => {
|
|
2967
2399
|
// Create multiple cells with hideCode
|
|
2968
|
-
|
|
2400
|
+
seedCell({
|
|
2969
2401
|
cellId: "__end__",
|
|
2970
2402
|
before: false,
|
|
2971
2403
|
hideCode: true,
|
|
2972
2404
|
});
|
|
2973
|
-
|
|
2405
|
+
seedCell({
|
|
2974
2406
|
cellId: "__end__",
|
|
2975
2407
|
before: false,
|
|
2976
2408
|
hideCode: true,
|
|
2977
2409
|
});
|
|
2978
|
-
|
|
2410
|
+
seedCell({
|
|
2979
2411
|
cellId: "__end__",
|
|
2980
2412
|
before: false,
|
|
2981
2413
|
hideCode: false,
|
|
@@ -3000,12 +2432,12 @@ describe("cell reducer", () => {
|
|
|
3000
2432
|
|
|
3001
2433
|
it("preserves untouched state when cells are moved", () => {
|
|
3002
2434
|
// Create cells with hideCode
|
|
3003
|
-
|
|
2435
|
+
seedCell({
|
|
3004
2436
|
cellId: "__end__",
|
|
3005
2437
|
before: false,
|
|
3006
2438
|
hideCode: true,
|
|
3007
2439
|
});
|
|
3008
|
-
|
|
2440
|
+
seedCell({
|
|
3009
2441
|
cellId: "__end__",
|
|
3010
2442
|
before: false,
|
|
3011
2443
|
hideCode: true,
|
|
@@ -3029,58 +2461,9 @@ describe("cell reducer", () => {
|
|
|
3029
2461
|
expect(state.untouchedNewCells.has(cell2Id)).toBe(true);
|
|
3030
2462
|
});
|
|
3031
2463
|
|
|
3032
|
-
it("does not remove untouched state when cell is deleted", () => {
|
|
3033
|
-
// We could implement this, but it doesn't actually affect downstream behavior.
|
|
3034
|
-
// It is easier to leave it, so `undo` works as expected.
|
|
3035
|
-
|
|
3036
|
-
// Create a cell with hideCode
|
|
3037
|
-
actions.createNewCell({
|
|
3038
|
-
cellId: "__end__",
|
|
3039
|
-
before: false,
|
|
3040
|
-
hideCode: true,
|
|
3041
|
-
});
|
|
3042
|
-
|
|
3043
|
-
const newCellId =
|
|
3044
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3045
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3046
|
-
|
|
3047
|
-
// Delete the cell
|
|
3048
|
-
actions.deleteCell({ cellId: newCellId });
|
|
3049
|
-
|
|
3050
|
-
// Does not actually remove untouched state
|
|
3051
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3052
|
-
});
|
|
3053
|
-
|
|
3054
|
-
it("restores untouched state when cell deletion is undone", () => {
|
|
3055
|
-
// Create a cell with hideCode
|
|
3056
|
-
actions.createNewCell({
|
|
3057
|
-
cellId: "__end__",
|
|
3058
|
-
before: false,
|
|
3059
|
-
hideCode: true,
|
|
3060
|
-
});
|
|
3061
|
-
|
|
3062
|
-
const newCellId =
|
|
3063
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3064
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3065
|
-
|
|
3066
|
-
// Delete the cell
|
|
3067
|
-
actions.deleteCell({ cellId: newCellId });
|
|
3068
|
-
// Still exists in untouchedNewCells
|
|
3069
|
-
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
3070
|
-
|
|
3071
|
-
// Undo the deletion
|
|
3072
|
-
actions.undoDeleteCell();
|
|
3073
|
-
|
|
3074
|
-
// The cell should be restored but no longer untouched
|
|
3075
|
-
// (this is expected behavior - undoing doesn't restore untouched state)
|
|
3076
|
-
const restoredCellId =
|
|
3077
|
-
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3078
|
-
expect(state.untouchedNewCells.has(restoredCellId)).toBe(false);
|
|
3079
|
-
});
|
|
3080
|
-
|
|
3081
2464
|
it("untouched cell behavior with hide_code config", () => {
|
|
3082
2465
|
// Create a cell with hideCode and hide_code config
|
|
3083
|
-
|
|
2466
|
+
seedCell({
|
|
3084
2467
|
cellId: "__end__",
|
|
3085
2468
|
before: false,
|
|
3086
2469
|
hideCode: true,
|
|
@@ -3089,11 +2472,11 @@ describe("cell reducer", () => {
|
|
|
3089
2472
|
const newCellId =
|
|
3090
2473
|
state.cellIds.inOrderIds[state.cellIds.inOrderIds.length - 1];
|
|
3091
2474
|
|
|
3092
|
-
//
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
config: { hide_code: true },
|
|
3096
|
-
}
|
|
2475
|
+
// The document hides the cell's code
|
|
2476
|
+
state.cellData[newCellId] = {
|
|
2477
|
+
...state.cellData[newCellId],
|
|
2478
|
+
config: { ...state.cellData[newCellId].config, hide_code: true },
|
|
2479
|
+
};
|
|
3097
2480
|
|
|
3098
2481
|
// Cell should be untouched and have hide_code config
|
|
3099
2482
|
expect(state.untouchedNewCells.has(newCellId)).toBe(true);
|
|
@@ -3112,7 +2495,7 @@ describe("cell reducer", () => {
|
|
|
3112
2495
|
|
|
3113
2496
|
it("can mark an existing cell as untouched", () => {
|
|
3114
2497
|
// Create a cell without hideCode (not in untouchedNewCells)
|
|
3115
|
-
|
|
2498
|
+
seedCell({
|
|
3116
2499
|
cellId: "__end__",
|
|
3117
2500
|
before: false,
|
|
3118
2501
|
hideCode: false,
|
|
@@ -3130,7 +2513,7 @@ describe("cell reducer", () => {
|
|
|
3130
2513
|
|
|
3131
2514
|
it("markUntouched is idempotent", () => {
|
|
3132
2515
|
// Create a cell without hideCode
|
|
3133
|
-
|
|
2516
|
+
seedCell({
|
|
3134
2517
|
cellId: "__end__",
|
|
3135
2518
|
before: false,
|
|
3136
2519
|
hideCode: false,
|
|
@@ -3150,7 +2533,7 @@ describe("cell reducer", () => {
|
|
|
3150
2533
|
|
|
3151
2534
|
it("markUntouched does not affect already untouched cells", () => {
|
|
3152
2535
|
// Create a cell with hideCode (already in untouchedNewCells)
|
|
3153
|
-
|
|
2536
|
+
seedCell({
|
|
3154
2537
|
cellId: "__end__",
|
|
3155
2538
|
before: false,
|
|
3156
2539
|
hideCode: true,
|
|
@@ -3168,7 +2551,7 @@ describe("cell reducer", () => {
|
|
|
3168
2551
|
|
|
3169
2552
|
it("markTouched and markUntouched can toggle cell state", () => {
|
|
3170
2553
|
// Create a cell without hideCode
|
|
3171
|
-
|
|
2554
|
+
seedCell({
|
|
3172
2555
|
cellId: "__end__",
|
|
3173
2556
|
before: false,
|
|
3174
2557
|
hideCode: false,
|
|
@@ -3196,7 +2579,7 @@ describe("cell reducer", () => {
|
|
|
3196
2579
|
it("markUntouched works for markdown cell conversion scenario", () => {
|
|
3197
2580
|
// Simulates converting a Python cell to Markdown
|
|
3198
2581
|
// 1. Create a regular cell (no hideCode)
|
|
3199
|
-
|
|
2582
|
+
seedCell({
|
|
3200
2583
|
cellId: "__end__",
|
|
3201
2584
|
before: false,
|
|
3202
2585
|
hideCode: false,
|
|
@@ -3210,11 +2593,12 @@ describe("cell reducer", () => {
|
|
|
3210
2593
|
expect(state.untouchedNewCells.has(cellId)).toBe(false);
|
|
3211
2594
|
expect(exportedForTesting.isCellCodeHidden(state, cellId)).toBe(false);
|
|
3212
2595
|
|
|
3213
|
-
// 2. Convert to markdown:
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
2596
|
+
// 2. Convert to markdown: the document hides the code, and the cell
|
|
2597
|
+
// is marked untouched
|
|
2598
|
+
state.cellData[cellId] = {
|
|
2599
|
+
...state.cellData[cellId],
|
|
2600
|
+
config: { ...state.cellData[cellId].config, hide_code: true },
|
|
2601
|
+
};
|
|
3218
2602
|
actions.markUntouched({ cellId });
|
|
3219
2603
|
|
|
3220
2604
|
// Code should NOT be hidden because cell is untouched (user can edit)
|
|
@@ -3236,7 +2620,7 @@ describe("cell reducer", () => {
|
|
|
3236
2620
|
const { cellDataAtom, cellRuntimeAtom, cellHandleAtom } =
|
|
3237
2621
|
exportedForTesting;
|
|
3238
2622
|
|
|
3239
|
-
|
|
2623
|
+
seedCell({ cellId: firstCellId, before: false });
|
|
3240
2624
|
const newCellId = state.cellIds.inOrderIds[1];
|
|
3241
2625
|
|
|
3242
2626
|
const dataAtom1 = cellDataAtom(newCellId);
|
|
@@ -3252,31 +2636,6 @@ describe("cell reducer", () => {
|
|
|
3252
2636
|
expect(runtimeAtom2).toBe(runtimeAtom1);
|
|
3253
2637
|
expect(handleAtom2).toBe(handleAtom1);
|
|
3254
2638
|
});
|
|
3255
|
-
|
|
3256
|
-
it("cleans up atom family cache when cells are deleted", () => {
|
|
3257
|
-
const { cellDataAtom, cellRuntimeAtom, cellHandleAtom } =
|
|
3258
|
-
exportedForTesting;
|
|
3259
|
-
|
|
3260
|
-
actions.createNewCell({ cellId: firstCellId, before: false });
|
|
3261
|
-
const newCellId = state.cellIds.inOrderIds[1];
|
|
3262
|
-
|
|
3263
|
-
// Access to create cache entries
|
|
3264
|
-
const dataAtom1 = cellDataAtom(newCellId);
|
|
3265
|
-
const runtimeAtom1 = cellRuntimeAtom(newCellId);
|
|
3266
|
-
const handleAtom1 = cellHandleAtom(newCellId);
|
|
3267
|
-
|
|
3268
|
-
// Triggers purge
|
|
3269
|
-
actions.deleteCell({ cellId: newCellId });
|
|
3270
|
-
|
|
3271
|
-
// Access again (should be new instances after cleanup)
|
|
3272
|
-
const dataAtom2 = cellDataAtom(newCellId);
|
|
3273
|
-
const runtimeAtom2 = cellRuntimeAtom(newCellId);
|
|
3274
|
-
const handleAtom2 = cellHandleAtom(newCellId);
|
|
3275
|
-
|
|
3276
|
-
expect(dataAtom2).not.toBe(dataAtom1);
|
|
3277
|
-
expect(runtimeAtom2).not.toBe(runtimeAtom1);
|
|
3278
|
-
expect(handleAtom2).not.toBe(handleAtom1);
|
|
3279
|
-
});
|
|
3280
2639
|
});
|
|
3281
2640
|
});
|
|
3282
2641
|
|
|
@@ -3591,31 +2950,9 @@ describe("createTracebackInfoAtom", () => {
|
|
|
3591
2950
|
});
|
|
3592
2951
|
});
|
|
3593
2952
|
|
|
3594
|
-
describe("
|
|
2953
|
+
describe("kernel-ready", () => {
|
|
3595
2954
|
const CELL_A = cellId("A");
|
|
3596
2955
|
const CELL_B = cellId("B");
|
|
3597
|
-
const newCells: CellData[] = [
|
|
3598
|
-
{
|
|
3599
|
-
id: CELL_A,
|
|
3600
|
-
name: "a",
|
|
3601
|
-
code: "1",
|
|
3602
|
-
edited: false,
|
|
3603
|
-
lastCodeRun: null,
|
|
3604
|
-
lastExecutionTime: null,
|
|
3605
|
-
config: { hide_code: false, disabled: false, column: null },
|
|
3606
|
-
serializedEditorState: null,
|
|
3607
|
-
},
|
|
3608
|
-
{
|
|
3609
|
-
id: CELL_B,
|
|
3610
|
-
name: "b",
|
|
3611
|
-
code: "2",
|
|
3612
|
-
edited: false,
|
|
3613
|
-
lastCodeRun: null,
|
|
3614
|
-
lastExecutionTime: null,
|
|
3615
|
-
config: { hide_code: false, disabled: false, column: null },
|
|
3616
|
-
serializedEditorState: null,
|
|
3617
|
-
},
|
|
3618
|
-
];
|
|
3619
2956
|
|
|
3620
2957
|
const hydratedState = () =>
|
|
3621
2958
|
MockNotebook.notebookState({
|
|
@@ -3645,44 +2982,97 @@ describe("setCells snapshot preservation", () => {
|
|
|
3645
2982
|
},
|
|
3646
2983
|
});
|
|
3647
2984
|
|
|
3648
|
-
|
|
3649
|
-
const
|
|
3650
|
-
|
|
2985
|
+
it("setLastRun records what the kernel last ran", () => {
|
|
2986
|
+
const state = hydratedState();
|
|
2987
|
+
const next = exportedForTesting.reducer(state, {
|
|
2988
|
+
type: "setLastRun",
|
|
2989
|
+
payload: {
|
|
2990
|
+
lastCodeRun: { [CELL_A]: "0" },
|
|
2991
|
+
lastExecutionTime: { [CELL_A]: 5 },
|
|
2992
|
+
},
|
|
2993
|
+
});
|
|
2994
|
+
|
|
2995
|
+
expect(next.cellData[CELL_A]).toMatchObject({
|
|
2996
|
+
lastCodeRun: "0",
|
|
2997
|
+
lastExecutionTime: 5,
|
|
2998
|
+
edited: true,
|
|
2999
|
+
});
|
|
3000
|
+
expect(next.cellData[CELL_B]).toMatchObject({
|
|
3001
|
+
lastCodeRun: null,
|
|
3002
|
+
lastExecutionTime: null,
|
|
3003
|
+
edited: false,
|
|
3004
|
+
});
|
|
3005
|
+
expect(next.cellRuntime).toBe(state.cellRuntime);
|
|
3651
3006
|
});
|
|
3652
3007
|
|
|
3653
|
-
it("
|
|
3008
|
+
it("resetCellRuntimes starts every cell's runtime over", () => {
|
|
3654
3009
|
const next = exportedForTesting.reducer(hydratedState(), {
|
|
3655
|
-
type: "
|
|
3656
|
-
payload:
|
|
3010
|
+
type: "resetCellRuntimes",
|
|
3011
|
+
payload: undefined,
|
|
3657
3012
|
});
|
|
3658
3013
|
|
|
3659
|
-
expect(next.cellRuntime[CELL_A].output).
|
|
3660
|
-
|
|
3014
|
+
expect(next.cellRuntime[CELL_A].output).toBeNull();
|
|
3015
|
+
expect(next.cellRuntime[CELL_B].consoleOutputs).toEqual([]);
|
|
3016
|
+
});
|
|
3017
|
+
|
|
3018
|
+
it("resetCellRuntimes starts the scratch cell over too", () => {
|
|
3019
|
+
const state = MockNotebook.notebookState({
|
|
3020
|
+
cellData: { [CELL_A]: { id: CELL_A, code: "1" } },
|
|
3021
|
+
cellRuntime: {
|
|
3022
|
+
[SCRATCH_CELL_ID]: {
|
|
3023
|
+
output: {
|
|
3024
|
+
channel: "output",
|
|
3025
|
+
mimetype: "text/plain",
|
|
3026
|
+
data: "scratch",
|
|
3027
|
+
timestamp: 0,
|
|
3028
|
+
},
|
|
3029
|
+
},
|
|
3030
|
+
},
|
|
3661
3031
|
});
|
|
3032
|
+
const next = exportedForTesting.reducer(state, {
|
|
3033
|
+
type: "resetCellRuntimes",
|
|
3034
|
+
payload: undefined,
|
|
3035
|
+
});
|
|
3036
|
+
|
|
3037
|
+
expect(next.cellRuntime[SCRATCH_CELL_ID].output).toBeNull();
|
|
3662
3038
|
});
|
|
3663
3039
|
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3040
|
+
describe("resetCellRuntimes in WASM", () => {
|
|
3041
|
+
beforeEach(async () => {
|
|
3042
|
+
const { isWasm } = await import("@/core/wasm/utils");
|
|
3043
|
+
vi.mocked(isWasm).mockReturnValue(true);
|
|
3668
3044
|
});
|
|
3669
3045
|
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3046
|
+
afterEach(async () => {
|
|
3047
|
+
const { isWasm } = await import("@/core/wasm/utils");
|
|
3048
|
+
vi.mocked(isWasm).mockReturnValue(false);
|
|
3673
3049
|
});
|
|
3674
|
-
});
|
|
3675
3050
|
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3051
|
+
it("keeps hydrated outputs and console", () => {
|
|
3052
|
+
const next = exportedForTesting.reducer(hydratedState(), {
|
|
3053
|
+
type: "resetCellRuntimes",
|
|
3054
|
+
payload: undefined,
|
|
3055
|
+
});
|
|
3056
|
+
|
|
3057
|
+
expect(next.cellRuntime[CELL_A].output).toMatchObject({
|
|
3058
|
+
data: "hydrated-A",
|
|
3059
|
+
});
|
|
3060
|
+
expect(next.cellRuntime[CELL_B].consoleOutputs[0]).toMatchObject({
|
|
3061
|
+
data: "hydrated-B-stdout",
|
|
3062
|
+
});
|
|
3681
3063
|
});
|
|
3682
3064
|
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3065
|
+
it("starts cells with no prior runtime over", () => {
|
|
3066
|
+
const state = MockNotebook.notebookState({
|
|
3067
|
+
cellData: { [CELL_A]: { id: CELL_A, code: "1" } },
|
|
3068
|
+
});
|
|
3069
|
+
const next = exportedForTesting.reducer(state, {
|
|
3070
|
+
type: "resetCellRuntimes",
|
|
3071
|
+
payload: undefined,
|
|
3072
|
+
});
|
|
3073
|
+
|
|
3074
|
+
expect(next.cellRuntime[CELL_A].output).toBeNull();
|
|
3075
|
+
expect(next.cellRuntime[CELL_A].consoleOutputs).toEqual([]);
|
|
3076
|
+
});
|
|
3687
3077
|
});
|
|
3688
3078
|
});
|