feat(playground): stdinQueue di store — enqueue/consume/clear atomik

This commit is contained in:
a2nr 2026-08-01 22:34:32 +00:00
parent dbed014474
commit 1aef334d59
2 changed files with 76 additions and 0 deletions

View File

@ -0,0 +1,55 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { get } from 'svelte/store';
import { playgroundStore } from './playground';
describe('playgroundStore stdinQueue', () => {
beforeEach(() => {
playgroundStore.reset();
playgroundStore.clearConsole();
});
it('enqueueStdin menambah baris ke antrean', () => {
playgroundStore.enqueueStdin('Budi');
playgroundStore.enqueueStdin('17');
const state = get(playgroundStore);
expect(state.stdinQueue).toEqual(['Budi', '17']);
});
it('enqueueStdin mengabaikan baris kosong', () => {
playgroundStore.enqueueStdin('');
playgroundStore.enqueueStdin(' ');
const state = get(playgroundStore);
expect(state.stdinQueue).toEqual([]);
});
it('consumeStdin mengembalikan seluruh antrean + draft, digabung dengan newline, lalu mengosongkan', () => {
playgroundStore.enqueueStdin('Budi');
playgroundStore.enqueueStdin('17');
playgroundStore.setConsoleInput('draft yang belum dikirim');
const stdin = playgroundStore.consumeStdin();
expect(stdin).toBe('Budi\n17\ndraft yang belum dikirim');
const state = get(playgroundStore);
expect(state.stdinQueue).toEqual([]);
expect(state.consoleInput).toBe('');
});
it('consumeStdin mengembalikan string kosong jika tidak ada baris maupun draft', () => {
const stdin = playgroundStore.consumeStdin();
expect(stdin).toBe('');
});
it('consumeStdin menambah baris baru di akhir masing-masing baris', () => {
playgroundStore.enqueueStdin('Budi');
const stdin = playgroundStore.consumeStdin();
expect(stdin).toBe('Budi\n');
});
it('clearStdinQueue mengosongkan antrean tanpa menyentuh consoleInput', () => {
playgroundStore.enqueueStdin('Budi');
playgroundStore.setConsoleInput('draft');
playgroundStore.clearStdinQueue();
const state = get(playgroundStore);
expect(state.stdinQueue).toEqual([]);
expect(state.consoleInput).toBe('draft');
});
});

View File

@ -29,6 +29,7 @@ interface PlaygroundState {
activeFileId: string; activeFileId: string;
consoleHistory: ConsoleLine[]; consoleHistory: ConsoleLine[];
consoleInput: string; consoleInput: string;
stdinQueue: string[];
consoleVisible: boolean; consoleVisible: boolean;
running: boolean; running: boolean;
} }
@ -86,6 +87,7 @@ function initialState(): PlaygroundState {
activeFileId: files[0]?.id ?? '', activeFileId: files[0]?.id ?? '',
consoleHistory: [], consoleHistory: [],
consoleInput: '', consoleInput: '',
stdinQueue: [],
consoleVisible: true, consoleVisible: true,
running: false running: false
}; };
@ -169,6 +171,25 @@ function createPlaygroundStore() {
update((s) => ({ ...s, consoleInput: text })); update((s) => ({ ...s, consoleInput: text }));
}, },
enqueueStdin: (text: string) => {
const trimmed = text.trim();
if (!trimmed) return;
update((s) => ({ ...s, stdinQueue: [...s.stdinQueue, trimmed] }));
},
consumeStdin: (): string => {
let stdin = '';
update((s) => {
stdin = s.stdinQueue.map((line) => line + '\n').join('') + s.consoleInput;
return { ...s, stdinQueue: [], consoleInput: '' };
});
return stdin;
},
clearStdinQueue: () => {
update((s) => ({ ...s, stdinQueue: [] }));
},
toggleConsole: () => { toggleConsole: () => {
update((s) => ({ ...s, consoleVisible: !s.consoleVisible })); update((s) => ({ ...s, consoleVisible: !s.consoleVisible }));
}, },