|
|
@@ -1,6 +1,7 @@
|
|
|
-import { readFile, readdir, writeFile } from 'node:fs/promises'
|
|
|
+import { mkdtemp, readFile, readdir, rm, writeFile } from 'node:fs/promises'
|
|
|
import { createServer } from 'node:http'
|
|
|
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
|
+import { tmpdir } from 'node:os'
|
|
|
import { join } from 'node:path'
|
|
|
import { fileURLToPath } from 'node:url'
|
|
|
import {
|
|
|
@@ -308,6 +309,59 @@ describe('headless stream-json snapshots', () => {
|
|
|
expect(result.stderr).toContain('omit --session-id to start a new Session')
|
|
|
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
|
|
|
|
|
|
+ it('resumes one persisted Session across two real --session-id wakes', async () => {
|
|
|
+ const firstTask = 'Record the first wake of the resume proof.'
|
|
|
+ const secondTask = 'Continue from the first wake of the resume proof.'
|
|
|
+ const env = {
|
|
|
+ DSH_PERMISSION_MODE: 'danger-full-access',
|
|
|
+ DSH_TELEMETRY_DISABLED: '1',
|
|
|
+ NODE_OPTIONS: [process.env.NODE_OPTIONS, '--disable-warning=ExperimentalWarning'].filter(Boolean).join(' '),
|
|
|
+ }
|
|
|
+ const cwd = await mkdtemp(join(tmpdir(), 'headless-session-resume-'))
|
|
|
+ try {
|
|
|
+ const first = await runLoaderSmoke({
|
|
|
+ label: 'product headless profile resume first wake',
|
|
|
+ tempDirPrefix: 'headless-session-resume-',
|
|
|
+ cwd,
|
|
|
+ binScript: dshBinScript,
|
|
|
+ configPath: headlessOverlayPath,
|
|
|
+ binArgs: ['--profile', 'headless', '--patch', headlessOverlayPath, '--json', firstTask],
|
|
|
+ tsconfigPath,
|
|
|
+ env,
|
|
|
+ })
|
|
|
+ const firstEvents = first.stdout.trim().split('\n').map(line => JSON.parse(line) as JsonObject)
|
|
|
+ expect(firstEvents[0]).toMatchObject({ type: 'session' })
|
|
|
+ const sessionId = firstEvents[0]?.sessionId
|
|
|
+ if (typeof sessionId !== 'string') throw new Error('the first wake reported no Session identity')
|
|
|
+
|
|
|
+ const second = await runLoaderSmoke({
|
|
|
+ label: 'product headless profile resume second wake',
|
|
|
+ tempDirPrefix: 'headless-session-resume-',
|
|
|
+ cwd,
|
|
|
+ binScript: dshBinScript,
|
|
|
+ configPath: headlessOverlayPath,
|
|
|
+ binArgs: [
|
|
|
+ '--profile', 'headless', '--patch', headlessOverlayPath,
|
|
|
+ '--json', '--session-id', sessionId, secondTask,
|
|
|
+ ],
|
|
|
+ tsconfigPath,
|
|
|
+ env,
|
|
|
+ inspect: async (inspected) => {
|
|
|
+ const logs = await persistedLogs(inspected, join(inspected, '.dsh', 'sessions'))
|
|
|
+ expect(logs).toHaveLength(1)
|
|
|
+ const content = logs[0]?.content ?? ''
|
|
|
+ expect(content).toContain(firstTask)
|
|
|
+ expect(content).toContain(secondTask)
|
|
|
+ },
|
|
|
+ })
|
|
|
+ const secondEvents = second.stdout.trim().split('\n').map(line => JSON.parse(line) as JsonObject)
|
|
|
+ expect(secondEvents[0]).toMatchObject({ type: 'session', sessionId })
|
|
|
+ expect(secondEvents.at(-1)).toMatchObject({ type: 'final' })
|
|
|
+ } finally {
|
|
|
+ await rm(cwd, { recursive: true, force: true })
|
|
|
+ }
|
|
|
+ }, LOADER_SMOKE_TEST_TIMEOUT_MS * 2)
|
|
|
+
|
|
|
it('prints a terminal model failure through the product headless profile command', async () => {
|
|
|
const result = await runLoaderSmoke({
|
|
|
label: 'product headless profile model failure snapshot',
|