fix: apply editor fix also to script editor

This commit is contained in:
2026-02-27 17:45:43 +01:00
parent 84376cda01
commit e25a0d85a5
2 changed files with 13 additions and 3 deletions

View File

@@ -60,6 +60,9 @@ export const ScriptsView: React.FC<ScriptsViewProps> = ({ scriptId }) => {
const [isCheckingSyntax, setIsCheckingSyntax] = useState(false);
const editorRef = useRef<ScriptMonacoEditor | null>(null);
const monacoRef = useRef<ScriptMonacoRuntime | null>(null);
// Token incremented to signal Monaco to remount with fresh defaultValue.
// Prevents controlled-mode cursor jumps during typing.
const [monacoResetToken, setMonacoResetToken] = useState(0);
const buildCacheKey = (scriptMeta: Pick<ScriptData, 'id' | 'version'>, content: string): string => {
let hash = 0;
@@ -203,6 +206,7 @@ export const ScriptsView: React.FC<ScriptsViewProps> = ({ scriptId }) => {
setAvailableEntrypoints(['main']);
setEnabled(true);
setScriptContent('');
setMonacoResetToken(prev => prev + 1);
setIsSlugManuallyEdited(false);
return;
}
@@ -217,6 +221,7 @@ export const ScriptsView: React.FC<ScriptsViewProps> = ({ scriptId }) => {
setAvailableEntrypoints(['main']);
setEnabled(true);
setScriptContent('');
setMonacoResetToken(prev => prev + 1);
setIsSlugManuallyEdited(false);
return;
}
@@ -228,6 +233,7 @@ export const ScriptsView: React.FC<ScriptsViewProps> = ({ scriptId }) => {
setEntrypoint(item.entrypoint || 'render');
setEnabled(item.enabled ?? true);
setScriptContent(item.content || '');
setMonacoResetToken(prev => prev + 1);
const normalizedExisting = toFunctionSlug(item.slug || item.title || '');
setIsSlugManuallyEdited(normalizedExisting !== toFunctionSlug(item.title || ''));
await refreshEntrypoints(item.content || '', item);
@@ -520,10 +526,11 @@ export const ScriptsView: React.FC<ScriptsViewProps> = ({ scriptId }) => {
<div className="scripts-monaco">
<MonacoEditor
key={monacoResetToken}
height="100%"
language="python"
theme="vs-dark"
value={scriptContent}
defaultValue={scriptContent}
onChange={(value) => setScriptContent(value || '')}
onMount={handleEditorDidMount}
options={{

View File

@@ -13,6 +13,7 @@ const setModelMarkersMock = vi.fn();
vi.mock('@monaco-editor/react', () => ({
default: (props: {
value?: string;
defaultValue?: string;
onChange?: (value?: string) => void;
language?: string;
onMount?: (editor: unknown, monaco: unknown) => void;
@@ -34,7 +35,7 @@ vi.mock('@monaco-editor/react', () => ({
return (
<textarea
aria-label="Script Content"
value={props.value || ''}
defaultValue={props.defaultValue ?? props.value ?? ''}
onChange={(event) => props.onChange?.(event.target.value)}
/>
);
@@ -91,11 +92,13 @@ describe('ScriptsView', () => {
it('loads scripts and allows editing content', async () => {
render(<ScriptsView scriptId="script-1" />);
const textarea = screen.getByLabelText('Script Content') as HTMLTextAreaElement;
// After script loads, Monaco remounts with new key — re-query the textarea
await vi.waitFor(() => {
const textarea = screen.getByLabelText('Script Content') as HTMLTextAreaElement;
expect(textarea.value).toContain('print("hello")');
});
const textarea = screen.getByLabelText('Script Content') as HTMLTextAreaElement;
fireEvent.change(textarea, { target: { value: 'print("updated")' } });
expect(textarea.value).toContain('updated');