@marimo-team/islands 0.20.3-dev89 → 0.20.3-dev91
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/main.js
CHANGED
|
@@ -70351,7 +70351,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
|
|
|
70351
70351
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
70352
70352
|
}
|
|
70353
70353
|
}
|
|
70354
|
-
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.3-
|
|
70354
|
+
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.3-dev91"), showCodeInRunModeAtom = atom(true);
|
|
70355
70355
|
atom(null);
|
|
70356
70356
|
var import_compiler_runtime$88 = require_compiler_runtime();
|
|
70357
70357
|
function useKeydownOnElement(e, r) {
|
|
@@ -99666,26 +99666,31 @@ ${c}
|
|
|
99666
99666
|
}), r[0] = e, r[1] = c), c;
|
|
99667
99667
|
};
|
|
99668
99668
|
var ConsoleOutputInternal = (e) => {
|
|
99669
|
-
let r = (0, import_compiler_runtime$4.c)(
|
|
99670
|
-
|
|
99669
|
+
let r = (0, import_compiler_runtime$4.c)(62), c = import_react.useRef(null), { wrapText: d, setWrapText: f } = useWrapText(), [_, v] = useExpandedConsoleOutput(e.cellId), [y, S] = import_react.useState(""), w;
|
|
99670
|
+
r[0] === y ? w = r[1] : (w = {
|
|
99671
|
+
value: y,
|
|
99672
|
+
setValue: S
|
|
99673
|
+
}, r[0] = y, r[1] = w);
|
|
99674
|
+
let E = useInputHistory(w), { consoleOutputs: O, stale: M, cellName: I, cellId: z, onSubmitDebugger: G, onClear: q, onRefactorWithAI: IY, className: LY } = e, RY = O.length > 0, zY = useSelectAllContent(RY), BY = useOverflowDetection(c, RY), VY;
|
|
99675
|
+
if (r[2] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (VY = () => {
|
|
99671
99676
|
let e2 = c.current;
|
|
99672
99677
|
if (!e2) return;
|
|
99673
99678
|
let r2 = e2.scrollHeight - e2.clientHeight;
|
|
99674
99679
|
r2 - e2.scrollTop < 120 && (e2.scrollTop = r2);
|
|
99675
|
-
}, r[
|
|
99676
|
-
let
|
|
99677
|
-
if (r[
|
|
99680
|
+
}, r[2] = VY) : VY = r[2], (0, import_react.useLayoutEffect)(VY), !RY && isInternalCellName(I)) return null;
|
|
99681
|
+
let HY, UY, WY, GY, KY, qY, JY, YY, XY, ZY;
|
|
99682
|
+
if (r[3] !== z || r[4] !== LY || r[5] !== O || r[6] !== RY || r[7] !== E || r[8] !== _ || r[9] !== BY || r[10] !== q || r[11] !== IY || r[12] !== G || r[13] !== zY || r[14] !== v || r[15] !== f || r[16] !== M || r[17] !== y || r[18] !== d) {
|
|
99678
99683
|
let e2 = [
|
|
99679
|
-
...
|
|
99680
|
-
].reverse(), w2 = e2.some(_temp$2),
|
|
99681
|
-
r[
|
|
99682
|
-
let
|
|
99683
|
-
|
|
99684
|
+
...O
|
|
99685
|
+
].reverse(), w2 = e2.some(_temp$2), I2 = e2.findIndex(_temp2$2), VY2;
|
|
99686
|
+
r[29] === O ? VY2 = r[30] : (VY2 = () => O.filter(_temp3$1).map(_temp4$1).join("\n"), r[29] = O, r[30] = VY2);
|
|
99687
|
+
let QY2 = VY2;
|
|
99688
|
+
HY = "relative group", r[31] !== QY2 || r[32] !== RY || r[33] !== _ || r[34] !== BY || r[35] !== v || r[36] !== f || r[37] !== d ? (UY = RY && (0, import_jsx_runtime.jsxs)("div", {
|
|
99684
99689
|
className: "absolute top-1 right-4 z-10 opacity-0 group-hover:opacity-100 flex items-center gap-1 print:hidden",
|
|
99685
99690
|
children: [
|
|
99686
99691
|
(0, import_jsx_runtime.jsx)(CopyClipboardIcon, {
|
|
99687
99692
|
tooltip: "Copy console output",
|
|
99688
|
-
value:
|
|
99693
|
+
value: QY2,
|
|
99689
99694
|
className: "h-4 w-4"
|
|
99690
99695
|
}),
|
|
99691
99696
|
(0, import_jsx_runtime.jsx)(Tooltip, {
|
|
@@ -99702,7 +99707,7 @@ ${c}
|
|
|
99702
99707
|
})
|
|
99703
99708
|
})
|
|
99704
99709
|
}),
|
|
99705
|
-
(
|
|
99710
|
+
(BY || _) && (0, import_jsx_runtime.jsx)(Button, {
|
|
99706
99711
|
"aria-label": _ ? "Collapse output" : "Expand output",
|
|
99707
99712
|
className: "p-0 mb-px",
|
|
99708
99713
|
onClick: () => v(!_),
|
|
@@ -99721,21 +99726,24 @@ ${c}
|
|
|
99721
99726
|
})
|
|
99722
99727
|
})
|
|
99723
99728
|
]
|
|
99724
|
-
}), r[
|
|
99725
|
-
let
|
|
99726
|
-
r[
|
|
99729
|
+
}), r[31] = QY2, r[32] = RY, r[33] = _, r[34] = BY, r[35] = v, r[36] = f, r[37] = d, r[38] = UY) : UY = r[38], WY = M ? "This console output is stale" : void 0, GY = "console-output-area", KY = c, qY = zY, JY = 0;
|
|
99730
|
+
let $Y2 = M && "marimo-output-stale", eX2 = RY ? "p-5" : "p-3";
|
|
99731
|
+
r[39] !== LY || r[40] !== $Y2 || r[41] !== eX2 ? (YY = cn("console-output-area overflow-hidden rounded-b-lg flex flex-col-reverse w-full gap-1 focus:outline-hidden", $Y2, eX2, LY), r[39] = LY, r[40] = $Y2, r[41] = eX2, r[42] = YY) : YY = r[42], r[43] === _ ? XY = r[44] : (XY = _ ? {
|
|
99727
99732
|
maxHeight: "none"
|
|
99728
|
-
} : void 0, r[
|
|
99733
|
+
} : void 0, r[43] = _, r[44] = XY), ZY = e2.map((e3, r2) => {
|
|
99729
99734
|
if (e3.channel === "pdb") return null;
|
|
99730
99735
|
if (e3.channel === "stdin") {
|
|
99731
99736
|
invariant(typeof e3.data == "string", "Expected data to be a string");
|
|
99732
|
-
let c2 =
|
|
99733
|
-
return e3.response == null &&
|
|
99737
|
+
let c2 = O.length - r2 - 1, d2 = e3.mimetype === "text/password";
|
|
99738
|
+
return e3.response == null && I2 === r2 ? (0, import_jsx_runtime.jsx)(StdInput, {
|
|
99734
99739
|
output: e3.data,
|
|
99735
99740
|
isPdb: w2,
|
|
99736
99741
|
isPassword: d2,
|
|
99737
|
-
onSubmit: (e4) =>
|
|
99738
|
-
onClear:
|
|
99742
|
+
onSubmit: (e4) => G(e4, c2),
|
|
99743
|
+
onClear: q,
|
|
99744
|
+
value: y,
|
|
99745
|
+
setValue: S,
|
|
99746
|
+
inputHistory: E
|
|
99739
99747
|
}, r2) : (0, import_jsx_runtime.jsx)(StdInputWithResponse, {
|
|
99740
99748
|
output: e3.data,
|
|
99741
99749
|
response: e3.response,
|
|
@@ -99744,94 +99752,91 @@ ${c}
|
|
|
99744
99752
|
}
|
|
99745
99753
|
return (0, import_jsx_runtime.jsx)(import_react.Fragment, {
|
|
99746
99754
|
children: (0, import_jsx_runtime.jsx)(OutputRenderer, {
|
|
99747
|
-
cellId:
|
|
99748
|
-
onRefactorWithAI:
|
|
99755
|
+
cellId: z,
|
|
99756
|
+
onRefactorWithAI: IY,
|
|
99749
99757
|
message: e3,
|
|
99750
99758
|
wrapText: d
|
|
99751
99759
|
})
|
|
99752
99760
|
}, r2);
|
|
99753
|
-
}), r[
|
|
99754
|
-
} else
|
|
99755
|
-
let
|
|
99756
|
-
r[
|
|
99757
|
-
value:
|
|
99758
|
-
cellId:
|
|
99761
|
+
}), r[3] = z, r[4] = LY, r[5] = O, r[6] = RY, r[7] = E, r[8] = _, r[9] = BY, r[10] = q, r[11] = IY, r[12] = G, r[13] = zY, r[14] = v, r[15] = f, r[16] = M, r[17] = y, r[18] = d, r[19] = HY, r[20] = UY, r[21] = WY, r[22] = GY, r[23] = KY, r[24] = qY, r[25] = JY, r[26] = YY, r[27] = XY, r[28] = ZY;
|
|
99762
|
+
} else HY = r[19], UY = r[20], WY = r[21], GY = r[22], KY = r[23], qY = r[24], JY = r[25], YY = r[26], XY = r[27], ZY = r[28];
|
|
99763
|
+
let QY;
|
|
99764
|
+
r[45] !== z || r[46] !== I ? (QY = (0, import_jsx_runtime.jsx)(NameCellContentEditable, {
|
|
99765
|
+
value: I,
|
|
99766
|
+
cellId: z,
|
|
99759
99767
|
className: "bg-(--slate-4) border-(--slate-4) hover:bg-(--slate-5) dark:border-(--sky-5) dark:bg-(--sky-6) dark:text-(--sky-12) text-(--slate-12) rounded-l rounded-br-lg absolute right-0 bottom-0 text-xs px-1.5 py-0.5 font-mono max-w-[75%] whitespace-nowrap overflow-hidden"
|
|
99760
|
-
}), r[
|
|
99761
|
-
let
|
|
99762
|
-
r[
|
|
99763
|
-
title:
|
|
99764
|
-
"data-testid":
|
|
99765
|
-
ref:
|
|
99766
|
-
...
|
|
99767
|
-
tabIndex:
|
|
99768
|
-
className:
|
|
99769
|
-
style:
|
|
99768
|
+
}), r[45] = z, r[46] = I, r[47] = QY) : QY = r[47];
|
|
99769
|
+
let $Y;
|
|
99770
|
+
r[48] !== QY || r[49] !== WY || r[50] !== GY || r[51] !== KY || r[52] !== qY || r[53] !== JY || r[54] !== YY || r[55] !== XY || r[56] !== ZY ? ($Y = (0, import_jsx_runtime.jsxs)("div", {
|
|
99771
|
+
title: WY,
|
|
99772
|
+
"data-testid": GY,
|
|
99773
|
+
ref: KY,
|
|
99774
|
+
...qY,
|
|
99775
|
+
tabIndex: JY,
|
|
99776
|
+
className: YY,
|
|
99777
|
+
style: XY,
|
|
99770
99778
|
children: [
|
|
99771
|
-
|
|
99772
|
-
|
|
99779
|
+
ZY,
|
|
99780
|
+
QY
|
|
99773
99781
|
]
|
|
99774
|
-
}), r[
|
|
99775
|
-
let
|
|
99776
|
-
return r[
|
|
99777
|
-
className:
|
|
99782
|
+
}), r[48] = QY, r[49] = WY, r[50] = GY, r[51] = KY, r[52] = qY, r[53] = JY, r[54] = YY, r[55] = XY, r[56] = ZY, r[57] = $Y) : $Y = r[57];
|
|
99783
|
+
let eX;
|
|
99784
|
+
return r[58] !== HY || r[59] !== UY || r[60] !== $Y ? (eX = (0, import_jsx_runtime.jsxs)("div", {
|
|
99785
|
+
className: HY,
|
|
99778
99786
|
children: [
|
|
99779
|
-
|
|
99780
|
-
|
|
99787
|
+
UY,
|
|
99788
|
+
$Y
|
|
99781
99789
|
]
|
|
99782
|
-
}), r[
|
|
99790
|
+
}), r[58] = HY, r[59] = UY, r[60] = $Y, r[61] = eX) : eX = r[61], eX;
|
|
99783
99791
|
}, StdInput = (e) => {
|
|
99784
|
-
let r = (0, import_compiler_runtime$4.c)(
|
|
99785
|
-
r[0] ===
|
|
99786
|
-
|
|
99787
|
-
|
|
99788
|
-
|
|
99789
|
-
|
|
99790
|
-
r[2] === e.output ? S = r[3] : (S = renderText(e.output), r[2] = e.output, r[3] = S);
|
|
99791
|
-
let w = e.isPassword ? "password" : "text", E, O;
|
|
99792
|
-
r[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (E = (e2) => d(e2.target.value), O = (0, import_jsx_runtime.jsx)(ChevronRight, {
|
|
99792
|
+
let r = (0, import_compiler_runtime$4.c)(25), { value: c, setValue: d, inputHistory: f, output: _, isPassword: v, isPdb: y, onSubmit: S, onClear: w } = e, { navigateUp: E, navigateDown: O, addToHistory: M } = f, I;
|
|
99793
|
+
r[0] === _ ? I = r[1] : (I = renderText(_), r[0] = _, r[1] = I);
|
|
99794
|
+
let z = v ? "password" : "text", G;
|
|
99795
|
+
r[2] === d ? G = r[3] : (G = (e2) => d(e2.target.value), r[2] = d, r[3] = G);
|
|
99796
|
+
let q;
|
|
99797
|
+
r[4] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (q = (0, import_jsx_runtime.jsx)(ChevronRight, {
|
|
99793
99798
|
className: "w-5 h-5"
|
|
99794
|
-
}), r[4] =
|
|
99795
|
-
let
|
|
99796
|
-
r[6] !==
|
|
99797
|
-
if (
|
|
99798
|
-
|
|
99799
|
+
}), r[4] = q) : q = r[4];
|
|
99800
|
+
let IY;
|
|
99801
|
+
r[5] !== M || r[6] !== O || r[7] !== E || r[8] !== S || r[9] !== d || r[10] !== c ? (IY = (e2) => {
|
|
99802
|
+
if (e2.key === "ArrowUp") {
|
|
99803
|
+
E(), e2.preventDefault();
|
|
99799
99804
|
return;
|
|
99800
99805
|
}
|
|
99801
|
-
if (
|
|
99802
|
-
|
|
99806
|
+
if (e2.key === "ArrowDown") {
|
|
99807
|
+
O(), e2.preventDefault();
|
|
99803
99808
|
return;
|
|
99804
99809
|
}
|
|
99805
|
-
|
|
99806
|
-
}, r[6] =
|
|
99807
|
-
let
|
|
99808
|
-
r[12] !==
|
|
99810
|
+
e2.key === "Enter" && !e2.shiftKey && (c && (M(c), S(c), d("")), e2.preventDefault(), e2.stopPropagation()), e2.key === "Enter" && e2.metaKey && (e2.preventDefault(), e2.stopPropagation());
|
|
99811
|
+
}, r[5] = M, r[6] = O, r[7] = E, r[8] = S, r[9] = d, r[10] = c, r[11] = IY) : IY = r[11];
|
|
99812
|
+
let LY;
|
|
99813
|
+
r[12] !== z || r[13] !== G || r[14] !== IY || r[15] !== c ? (LY = (0, import_jsx_runtime.jsx)(Input, {
|
|
99809
99814
|
"data-testid": "console-input",
|
|
99810
99815
|
"data-stdin-blocking": true,
|
|
99811
|
-
type:
|
|
99816
|
+
type: z,
|
|
99812
99817
|
autoComplete: "off",
|
|
99813
99818
|
autoFocus: true,
|
|
99814
99819
|
value: c,
|
|
99815
|
-
onChange:
|
|
99816
|
-
icon:
|
|
99820
|
+
onChange: G,
|
|
99821
|
+
icon: q,
|
|
99817
99822
|
className: "m-0 h-8 focus-visible:shadow-xs-solid",
|
|
99818
99823
|
placeholder: "stdin",
|
|
99819
|
-
onKeyDownCapture:
|
|
99820
|
-
}), r[12] =
|
|
99821
|
-
let
|
|
99822
|
-
r[
|
|
99823
|
-
onSubmit:
|
|
99824
|
-
onClear:
|
|
99825
|
-
}), r[
|
|
99826
|
-
let
|
|
99827
|
-
return r[
|
|
99824
|
+
onKeyDownCapture: IY
|
|
99825
|
+
}), r[12] = z, r[13] = G, r[14] = IY, r[15] = c, r[16] = LY) : LY = r[16];
|
|
99826
|
+
let RY;
|
|
99827
|
+
r[17] !== y || r[18] !== w || r[19] !== S ? (RY = y && (0, import_jsx_runtime.jsx)(DebuggerControls, {
|
|
99828
|
+
onSubmit: S,
|
|
99829
|
+
onClear: w
|
|
99830
|
+
}), r[17] = y, r[18] = w, r[19] = S, r[20] = RY) : RY = r[20];
|
|
99831
|
+
let zY;
|
|
99832
|
+
return r[21] !== I || r[22] !== LY || r[23] !== RY ? (zY = (0, import_jsx_runtime.jsxs)("div", {
|
|
99828
99833
|
className: "flex gap-2 items-center pt-2",
|
|
99829
99834
|
children: [
|
|
99830
|
-
S,
|
|
99831
99835
|
I,
|
|
99832
|
-
|
|
99836
|
+
LY,
|
|
99837
|
+
RY
|
|
99833
99838
|
]
|
|
99834
|
-
}), r[
|
|
99839
|
+
}), r[21] = I, r[22] = LY, r[23] = RY, r[24] = zY) : zY = r[24], zY;
|
|
99835
99840
|
}, StdInputWithResponse = (e) => {
|
|
99836
99841
|
let r = (0, import_compiler_runtime$4.c)(8), c;
|
|
99837
99842
|
r[0] === e.output ? c = r[1] : (c = renderText(e.output), r[0] = e.output, r[1] = c);
|
package/package.json
CHANGED
|
@@ -18,7 +18,10 @@ import { isInternalCellName } from "@/core/cells/names";
|
|
|
18
18
|
import { useExpandedConsoleOutput } from "@/core/cells/outputs";
|
|
19
19
|
import type { WithResponse } from "@/core/cells/types";
|
|
20
20
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
type UseInputHistoryReturn,
|
|
23
|
+
useInputHistory,
|
|
24
|
+
} from "@/hooks/useInputHistory";
|
|
22
25
|
import { useOverflowDetection } from "@/hooks/useOverflowDetection";
|
|
23
26
|
import { useSelectAllContent } from "@/hooks/useSelectAllContent";
|
|
24
27
|
import { cn } from "@/utils/cn";
|
|
@@ -54,6 +57,11 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
|
|
|
54
57
|
const ref = React.useRef<HTMLDivElement>(null);
|
|
55
58
|
const { wrapText, setWrapText } = useWrapText();
|
|
56
59
|
const [isExpanded, setIsExpanded] = useExpandedConsoleOutput(props.cellId);
|
|
60
|
+
const [stdinValue, setStdinValue] = React.useState("");
|
|
61
|
+
const inputHistory = useInputHistory({
|
|
62
|
+
value: stdinValue,
|
|
63
|
+
setValue: setStdinValue,
|
|
64
|
+
});
|
|
57
65
|
const {
|
|
58
66
|
consoleOutputs,
|
|
59
67
|
stale,
|
|
@@ -210,6 +218,9 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
|
|
|
210
218
|
isPassword={isPassword}
|
|
211
219
|
onSubmit={(text) => onSubmitDebugger(text, originalIdx)}
|
|
212
220
|
onClear={onClear}
|
|
221
|
+
value={stdinValue}
|
|
222
|
+
setValue={setStdinValue}
|
|
223
|
+
inputHistory={inputHistory}
|
|
213
224
|
/>
|
|
214
225
|
);
|
|
215
226
|
}
|
|
@@ -249,25 +260,32 @@ const StdInput = (props: {
|
|
|
249
260
|
onSubmit: (text: string) => void;
|
|
250
261
|
onClear?: () => void;
|
|
251
262
|
output: string;
|
|
252
|
-
response?: string;
|
|
253
263
|
isPdb: boolean;
|
|
254
264
|
isPassword?: boolean;
|
|
265
|
+
value: string;
|
|
266
|
+
setValue: (value: string) => void;
|
|
267
|
+
inputHistory: UseInputHistoryReturn;
|
|
255
268
|
}) => {
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
const { navigateUp, navigateDown, addToHistory } = useInputHistory({
|
|
269
|
+
const {
|
|
259
270
|
value,
|
|
260
271
|
setValue,
|
|
261
|
-
|
|
272
|
+
inputHistory,
|
|
273
|
+
output,
|
|
274
|
+
isPassword,
|
|
275
|
+
isPdb,
|
|
276
|
+
onSubmit,
|
|
277
|
+
onClear,
|
|
278
|
+
} = props;
|
|
279
|
+
const { navigateUp, navigateDown, addToHistory } = inputHistory;
|
|
262
280
|
|
|
263
281
|
return (
|
|
264
282
|
<div className="flex gap-2 items-center pt-2">
|
|
265
|
-
{renderText(
|
|
283
|
+
{renderText(output)}
|
|
266
284
|
<Input
|
|
267
285
|
data-testid="console-input"
|
|
268
286
|
// This is used in <StdinBlockingAlert> to find the input
|
|
269
287
|
data-stdin-blocking={true}
|
|
270
|
-
type={
|
|
288
|
+
type={isPassword ? "password" : "text"}
|
|
271
289
|
autoComplete="off"
|
|
272
290
|
autoFocus={true}
|
|
273
291
|
value={value}
|
|
@@ -292,7 +310,7 @@ const StdInput = (props: {
|
|
|
292
310
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
293
311
|
if (value) {
|
|
294
312
|
addToHistory(value);
|
|
295
|
-
|
|
313
|
+
onSubmit(value);
|
|
296
314
|
setValue("");
|
|
297
315
|
}
|
|
298
316
|
e.preventDefault();
|
|
@@ -306,9 +324,7 @@ const StdInput = (props: {
|
|
|
306
324
|
}
|
|
307
325
|
}}
|
|
308
326
|
/>
|
|
309
|
-
{
|
|
310
|
-
<DebuggerControls onSubmit={props.onSubmit} onClear={props.onClear} />
|
|
311
|
-
)}
|
|
327
|
+
{isPdb && <DebuggerControls onSubmit={onSubmit} onClear={onClear} />}
|
|
312
328
|
</div>
|
|
313
329
|
);
|
|
314
330
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { render, screen } from "@testing-library/react";
|
|
4
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
5
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
6
6
|
import type { CellId } from "@/core/cells/ids";
|
|
7
|
+
import type { WithResponse } from "@/core/cells/types";
|
|
7
8
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
8
9
|
import { ConsoleOutput } from "../ConsoleOutput";
|
|
9
10
|
|
|
@@ -20,6 +21,10 @@ global.ResizeObserver = class ResizeObserver {
|
|
|
20
21
|
}
|
|
21
22
|
};
|
|
22
23
|
|
|
24
|
+
const renderWithProvider = (ui: React.ReactElement) => {
|
|
25
|
+
return render(<TooltipProvider>{ui}</TooltipProvider>);
|
|
26
|
+
};
|
|
27
|
+
|
|
23
28
|
describe("ConsoleOutput integration", () => {
|
|
24
29
|
const createOutput = (data: string, channel = "stdout"): OutputMessage => ({
|
|
25
30
|
channel: channel as "stdout" | "stderr",
|
|
@@ -31,7 +36,7 @@ describe("ConsoleOutput integration", () => {
|
|
|
31
36
|
const defaultProps = {
|
|
32
37
|
cellId: "cell-1" as CellId,
|
|
33
38
|
cellName: "test_cell",
|
|
34
|
-
consoleOutputs: [],
|
|
39
|
+
consoleOutputs: [] as WithResponse<OutputMessage>[],
|
|
35
40
|
stale: false,
|
|
36
41
|
debuggerActive: false,
|
|
37
42
|
onSubmitDebugger: () => {
|
|
@@ -50,14 +55,151 @@ describe("ConsoleOutput integration", () => {
|
|
|
50
55
|
],
|
|
51
56
|
};
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
<TooltipProvider>
|
|
55
|
-
<ConsoleOutput {...props} />
|
|
56
|
-
</TooltipProvider>,
|
|
57
|
-
);
|
|
58
|
+
renderWithProvider(<ConsoleOutput {...props} />);
|
|
58
59
|
|
|
59
60
|
const link = screen.getByRole("link", { name: "https://marimo.io" });
|
|
60
61
|
expect(link).toBeInTheDocument();
|
|
61
62
|
expect(link).toHaveAttribute("href", "https://marimo.io");
|
|
62
63
|
});
|
|
63
64
|
});
|
|
65
|
+
|
|
66
|
+
describe("ConsoleOutput pdb history", () => {
|
|
67
|
+
const defaultProps = {
|
|
68
|
+
cellId: "cell-1" as CellId,
|
|
69
|
+
cellName: "test_cell",
|
|
70
|
+
consoleOutputs: [] as WithResponse<OutputMessage>[],
|
|
71
|
+
stale: false,
|
|
72
|
+
debuggerActive: false,
|
|
73
|
+
onSubmitDebugger: vi.fn(),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const stdinPrompt = (
|
|
77
|
+
data: string,
|
|
78
|
+
response?: string,
|
|
79
|
+
): WithResponse<OutputMessage> => ({
|
|
80
|
+
channel: "stdin" as const,
|
|
81
|
+
mimetype: "text/plain",
|
|
82
|
+
data,
|
|
83
|
+
timestamp: 0,
|
|
84
|
+
response,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should persist command history across StdInput remounts", () => {
|
|
88
|
+
// Initial state: pdb prompt waiting for input
|
|
89
|
+
const outputs1: WithResponse<OutputMessage>[] = [stdinPrompt("(Pdb) ")];
|
|
90
|
+
|
|
91
|
+
const onSubmitDebugger = vi.fn();
|
|
92
|
+
const { rerender } = renderWithProvider(
|
|
93
|
+
<ConsoleOutput
|
|
94
|
+
{...defaultProps}
|
|
95
|
+
consoleOutputs={outputs1}
|
|
96
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
97
|
+
/>,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const input = screen.getByTestId("console-input");
|
|
101
|
+
|
|
102
|
+
// Type "next" and submit
|
|
103
|
+
fireEvent.change(input, { target: { value: "next" } });
|
|
104
|
+
fireEvent.keyDown(input, { key: "Enter" });
|
|
105
|
+
|
|
106
|
+
expect(onSubmitDebugger).toHaveBeenCalledWith("next", 0);
|
|
107
|
+
|
|
108
|
+
// Simulate server response: old stdin gets a response, new stdin prompt appears
|
|
109
|
+
const outputs2: WithResponse<OutputMessage>[] = [
|
|
110
|
+
stdinPrompt("(Pdb) ", "next"),
|
|
111
|
+
stdinPrompt("(Pdb) "),
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
rerender(
|
|
115
|
+
<TooltipProvider>
|
|
116
|
+
<ConsoleOutput
|
|
117
|
+
{...defaultProps}
|
|
118
|
+
consoleOutputs={outputs2}
|
|
119
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
120
|
+
/>
|
|
121
|
+
</TooltipProvider>,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// New StdInput mounted — press ArrowUp to recall previous command
|
|
125
|
+
const newInput = screen.getByTestId("console-input");
|
|
126
|
+
fireEvent.keyDown(newInput, { key: "ArrowUp" });
|
|
127
|
+
|
|
128
|
+
expect(newInput).toHaveValue("next");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("should navigate through multiple history entries across remounts", () => {
|
|
132
|
+
const onSubmitDebugger = vi.fn();
|
|
133
|
+
|
|
134
|
+
// First prompt
|
|
135
|
+
const outputs1: WithResponse<OutputMessage>[] = [stdinPrompt("(Pdb) ")];
|
|
136
|
+
|
|
137
|
+
const { rerender } = renderWithProvider(
|
|
138
|
+
<ConsoleOutput
|
|
139
|
+
{...defaultProps}
|
|
140
|
+
consoleOutputs={outputs1}
|
|
141
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
142
|
+
/>,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Submit "step"
|
|
146
|
+
let input = screen.getByTestId("console-input");
|
|
147
|
+
fireEvent.change(input, { target: { value: "step" } });
|
|
148
|
+
fireEvent.keyDown(input, { key: "Enter" });
|
|
149
|
+
|
|
150
|
+
// Second prompt
|
|
151
|
+
const outputs2: WithResponse<OutputMessage>[] = [
|
|
152
|
+
stdinPrompt("(Pdb) ", "step"),
|
|
153
|
+
stdinPrompt("(Pdb) "),
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
rerender(
|
|
157
|
+
<TooltipProvider>
|
|
158
|
+
<ConsoleOutput
|
|
159
|
+
{...defaultProps}
|
|
160
|
+
consoleOutputs={outputs2}
|
|
161
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
162
|
+
/>
|
|
163
|
+
</TooltipProvider>,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// Submit "print(x)"
|
|
167
|
+
input = screen.getByTestId("console-input");
|
|
168
|
+
fireEvent.change(input, { target: { value: "print(x)" } });
|
|
169
|
+
fireEvent.keyDown(input, { key: "Enter" });
|
|
170
|
+
|
|
171
|
+
// Third prompt
|
|
172
|
+
const outputs3: WithResponse<OutputMessage>[] = [
|
|
173
|
+
stdinPrompt("(Pdb) ", "step"),
|
|
174
|
+
stdinPrompt("(Pdb) ", "print(x)"),
|
|
175
|
+
stdinPrompt("(Pdb) "),
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
rerender(
|
|
179
|
+
<TooltipProvider>
|
|
180
|
+
<ConsoleOutput
|
|
181
|
+
{...defaultProps}
|
|
182
|
+
consoleOutputs={outputs3}
|
|
183
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
184
|
+
/>
|
|
185
|
+
</TooltipProvider>,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// ArrowUp should show most recent command first
|
|
189
|
+
input = screen.getByTestId("console-input");
|
|
190
|
+
fireEvent.keyDown(input, { key: "ArrowUp" });
|
|
191
|
+
expect(input).toHaveValue("print(x)");
|
|
192
|
+
|
|
193
|
+
// ArrowUp again should show older command
|
|
194
|
+
fireEvent.keyDown(input, { key: "ArrowUp" });
|
|
195
|
+
expect(input).toHaveValue("step");
|
|
196
|
+
|
|
197
|
+
// ArrowDown should go back to "print(x)"
|
|
198
|
+
fireEvent.keyDown(input, { key: "ArrowDown" });
|
|
199
|
+
expect(input).toHaveValue("print(x)");
|
|
200
|
+
|
|
201
|
+
// ArrowDown again should return to empty input
|
|
202
|
+
fireEvent.keyDown(input, { key: "ArrowDown" });
|
|
203
|
+
expect(input).toHaveValue("");
|
|
204
|
+
});
|
|
205
|
+
});
|