diff --git a/frontend/src/lib/stores/playground.test.ts b/frontend/src/lib/stores/playground.test.ts new file mode 100644 index 0000000..85279ac --- /dev/null +++ b/frontend/src/lib/stores/playground.test.ts @@ -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'); + }); +}); diff --git a/frontend/src/lib/stores/playground.ts b/frontend/src/lib/stores/playground.ts index 29b1fce..3a83ef0 100644 --- a/frontend/src/lib/stores/playground.ts +++ b/frontend/src/lib/stores/playground.ts @@ -29,6 +29,7 @@ interface PlaygroundState { activeFileId: string; consoleHistory: ConsoleLine[]; consoleInput: string; + stdinQueue: string[]; consoleVisible: boolean; running: boolean; } @@ -86,6 +87,7 @@ function initialState(): PlaygroundState { activeFileId: files[0]?.id ?? '', consoleHistory: [], consoleInput: '', + stdinQueue: [], consoleVisible: true, running: false }; @@ -169,6 +171,25 @@ function createPlaygroundStore() { 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: () => { update((s) => ({ ...s, consoleVisible: !s.consoleVisible })); },