test(cli): remove unsafe test assertions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -13,12 +13,12 @@ describe("fetchNpmDistTags", () => {
|
|||||||
|
|
||||||
test("returns dist-tags on success", async () => {
|
test("returns dist-tags on success", async () => {
|
||||||
//#given
|
//#given
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: true,
|
ok: true,
|
||||||
json: () => Promise.resolve({ latest: "3.13.1", beta: "3.14.0-beta.1" }),
|
json: () => Promise.resolve({ latest: "3.13.1", beta: "3.14.0-beta.1" }),
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
const result = await fetchNpmDistTags("oh-my-openagent")
|
const result = await fetchNpmDistTags("oh-my-openagent")
|
||||||
@@ -29,7 +29,7 @@ describe("fetchNpmDistTags", () => {
|
|||||||
|
|
||||||
test("returns null on network failure", async () => {
|
test("returns null on network failure", async () => {
|
||||||
//#given
|
//#given
|
||||||
globalThis.fetch = mock(() => Promise.reject(new Error("Network error"))) as unknown as typeof fetch
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() => Promise.reject(new Error("Network error"))))
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
const result = await fetchNpmDistTags("oh-my-openagent")
|
const result = await fetchNpmDistTags("oh-my-openagent")
|
||||||
@@ -40,12 +40,12 @@ describe("fetchNpmDistTags", () => {
|
|||||||
|
|
||||||
test("returns null on non-ok response", async () => {
|
test("returns null on non-ok response", async () => {
|
||||||
//#given
|
//#given
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: false,
|
ok: false,
|
||||||
status: 404,
|
status: 404,
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
const result = await fetchNpmDistTags("oh-my-openagent")
|
const result = await fetchNpmDistTags("oh-my-openagent")
|
||||||
|
|||||||
@@ -92,12 +92,12 @@ describe("getOpenCodeVersion (installer)", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const immediateSetTimeout = ((handler: TimerHandler) => {
|
const immediateSetTimeout = testCoerce<typeof globalThis.setTimeout>(((handler: TimerHandler) => {
|
||||||
if (typeof handler === "function") {
|
if (typeof handler === "function") {
|
||||||
handler()
|
handler()
|
||||||
}
|
}
|
||||||
return 1 as unknown as ReturnType<typeof setTimeout>
|
return testCoerce<ReturnType<typeof setTimeout>>(1)
|
||||||
}) as unknown as typeof globalThis.setTimeout
|
}))
|
||||||
const setTimeoutSpy = spyOn(globalThis, "setTimeout").mockImplementation(immediateSetTimeout)
|
const setTimeoutSpy = spyOn(globalThis, "setTimeout").mockImplementation(immediateSetTimeout)
|
||||||
|
|
||||||
const result = await getOpenCodeVersion()
|
const result = await getOpenCodeVersion()
|
||||||
@@ -124,12 +124,12 @@ describe("getOpenCodeVersion (installer)", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const immediateSetTimeout = ((handler: TimerHandler) => {
|
const immediateSetTimeout = testCoerce<typeof globalThis.setTimeout>(((handler: TimerHandler) => {
|
||||||
if (typeof handler === "function") {
|
if (typeof handler === "function") {
|
||||||
handler()
|
handler()
|
||||||
}
|
}
|
||||||
return 1 as unknown as ReturnType<typeof setTimeout>
|
return testCoerce<ReturnType<typeof setTimeout>>(1)
|
||||||
}) as unknown as typeof globalThis.setTimeout
|
}))
|
||||||
const setTimeoutSpy = spyOn(globalThis, "setTimeout").mockImplementation(immediateSetTimeout)
|
const setTimeoutSpy = spyOn(globalThis, "setTimeout").mockImplementation(immediateSetTimeout)
|
||||||
|
|
||||||
const result = await getOpenCodeVersion()
|
const result = await getOpenCodeVersion()
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ describe("getPluginNameWithVersion", () => {
|
|||||||
|
|
||||||
test("returns the canonical latest tag when current version matches latest", async () => {
|
test("returns the canonical latest tag when current version matches latest", async () => {
|
||||||
//#given
|
//#given
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: true,
|
ok: true,
|
||||||
json: () => Promise.resolve({ latest: "3.13.1", beta: "3.14.0-beta.1" }),
|
json: () => Promise.resolve({ latest: "3.13.1", beta: "3.14.0-beta.1" }),
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
const result = await getPluginNameWithVersion("3.13.1")
|
const result = await getPluginNameWithVersion("3.13.1")
|
||||||
@@ -29,7 +29,7 @@ describe("getPluginNameWithVersion", () => {
|
|||||||
|
|
||||||
test("preserves the canonical prerelease channel when fetch fails", async () => {
|
test("preserves the canonical prerelease channel when fetch fails", async () => {
|
||||||
//#given
|
//#given
|
||||||
globalThis.fetch = mock(() => Promise.reject(new Error("Network error"))) as unknown as typeof fetch
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() => Promise.reject(new Error("Network error"))))
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
const result = await getPluginNameWithVersion("3.14.0-beta.1")
|
const result = await getPluginNameWithVersion("3.14.0-beta.1")
|
||||||
@@ -40,12 +40,12 @@ describe("getPluginNameWithVersion", () => {
|
|||||||
|
|
||||||
test("returns the canonical bare package name for stable fallback", async () => {
|
test("returns the canonical bare package name for stable fallback", async () => {
|
||||||
//#given
|
//#given
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: false,
|
ok: false,
|
||||||
status: 404,
|
status: 404,
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
const result = await getPluginNameWithVersion("3.13.1")
|
const result = await getPluginNameWithVersion("3.13.1")
|
||||||
|
|||||||
@@ -57,12 +57,12 @@ describe("install CLI - binary check behavior", () => {
|
|||||||
getOpenCodeVersionSpy = spyOn(configManager, "getOpenCodeVersion").mockResolvedValue(null)
|
getOpenCodeVersionSpy = spyOn(configManager, "getOpenCodeVersion").mockResolvedValue(null)
|
||||||
|
|
||||||
// given mock npm fetch
|
// given mock npm fetch
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: true,
|
ok: true,
|
||||||
json: () => Promise.resolve({ latest: "3.0.0" }),
|
json: () => Promise.resolve({ latest: "3.0.0" }),
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
const args: InstallArgs = {
|
const args: InstallArgs = {
|
||||||
tui: false,
|
tui: false,
|
||||||
@@ -92,12 +92,12 @@ describe("install CLI - binary check behavior", () => {
|
|||||||
getOpenCodeVersionSpy = spyOn(configManager, "getOpenCodeVersion").mockResolvedValue(null)
|
getOpenCodeVersionSpy = spyOn(configManager, "getOpenCodeVersion").mockResolvedValue(null)
|
||||||
|
|
||||||
// given mock npm fetch
|
// given mock npm fetch
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: true,
|
ok: true,
|
||||||
json: () => Promise.resolve({ latest: "3.0.0" }),
|
json: () => Promise.resolve({ latest: "3.0.0" }),
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
const args: InstallArgs = {
|
const args: InstallArgs = {
|
||||||
tui: false,
|
tui: false,
|
||||||
@@ -131,12 +131,12 @@ describe("install CLI - binary check behavior", () => {
|
|||||||
getOpenCodeVersionSpy = spyOn(configManager, "getOpenCodeVersion").mockResolvedValue("1.4.0")
|
getOpenCodeVersionSpy = spyOn(configManager, "getOpenCodeVersion").mockResolvedValue("1.4.0")
|
||||||
|
|
||||||
// given mock npm fetch
|
// given mock npm fetch
|
||||||
globalThis.fetch = mock(() =>
|
globalThis.fetch = testCoerce<typeof fetch>(mock(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
ok: true,
|
ok: true,
|
||||||
json: () => Promise.resolve({ latest: "3.0.0" }),
|
json: () => Promise.resolve({ latest: "3.0.0" }),
|
||||||
} as Response)
|
} as Response)
|
||||||
) as unknown as typeof fetch
|
))
|
||||||
|
|
||||||
const args: InstallArgs = {
|
const args: InstallArgs = {
|
||||||
tui: false,
|
tui: false,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ function createTempDir(): string {
|
|||||||
|
|
||||||
function createMockContext(directory: string): RunContext {
|
function createMockContext(directory: string): RunContext {
|
||||||
return {
|
return {
|
||||||
client: {
|
client: testCoerce<RunContext["client"]>({
|
||||||
session: {
|
session: {
|
||||||
todo: mock(() => Promise.resolve({ data: [] })),
|
todo: mock(() => Promise.resolve({ data: [] })),
|
||||||
children: mock(() => Promise.resolve({ data: [] })),
|
children: mock(() => Promise.resolve({ data: [] })),
|
||||||
@@ -39,7 +39,7 @@ function createMockContext(directory: string): RunContext {
|
|||||||
})),
|
})),
|
||||||
messages: mock(async () => ({ data: [] })),
|
messages: mock(async () => ({ data: [] })),
|
||||||
},
|
},
|
||||||
} as unknown as RunContext["client"],
|
}),
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
directory,
|
directory,
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@@ -155,17 +155,17 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "child-session"
|
ctx.sessionID = "child-session"
|
||||||
setSessionAgent("child-session", "atlas")
|
setSessionAgent("child-session", "atlas")
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "child-session" ? "root-session" : undefined,
|
parentID: path.id === "child-session" ? "root-session" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "child-session"
|
data: path.id === "child-session"
|
||||||
? [{ info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4" } }]
|
? [{ info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4" } }]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -187,13 +187,13 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "lineage-only-session"
|
ctx.sessionID = "lineage-only-session"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "lineage-only-session" ? "root-session" : undefined,
|
parentID: path.id === "lineage-only-session" ? "root-session" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async () => ({ data: [] })) as unknown as RunContext["client"]["session"]["messages"]
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async () => ({ data: [] })))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -218,17 +218,17 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "mismatch-subagent-session"
|
ctx.sessionID = "mismatch-subagent-session"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "mismatch-subagent-session" ? "root-session" : undefined,
|
parentID: path.id === "mismatch-subagent-session" ? "root-session" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "mismatch-subagent-session"
|
data: path.id === "mismatch-subagent-session"
|
||||||
? [{ info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4" } }]
|
? [{ info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4" } }]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -253,17 +253,17 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "appended-mismatch-session"
|
ctx.sessionID = "appended-mismatch-session"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "appended-mismatch-session" ? "root-session" : undefined,
|
parentID: path.id === "appended-mismatch-session" ? "root-session" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "appended-mismatch-session"
|
data: path.id === "appended-mismatch-session"
|
||||||
? [{ info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4" } }]
|
? [{ info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4" } }]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -288,14 +288,14 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_appended_descendant"
|
ctx.sessionID = "ses_appended_descendant"
|
||||||
ctx.client.session.get = mock(async () => {
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async () => {
|
||||||
throw new Error("session lookup failed")
|
throw new Error("session lookup failed")
|
||||||
}) as unknown as RunContext["client"]["session"]["get"]
|
}))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "ses_appended_descendant"
|
data: path.id === "ses_appended_descendant"
|
||||||
? [{ info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4" } }]
|
? [{ info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4" } }]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -317,12 +317,12 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_direct_child"
|
ctx.sessionID = "ses_direct_child"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "ses_direct_child" ? "ses_parent" : undefined,
|
parentID: path.id === "ses_direct_child" ? "ses_parent" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -347,12 +347,12 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_direct_tracked"
|
ctx.sessionID = "ses_direct_tracked"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: undefined,
|
parentID: undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -374,9 +374,9 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_unknown_child"
|
ctx.sessionID = "ses_unknown_child"
|
||||||
ctx.client.session.get = mock(async () => {
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async () => {
|
||||||
throw new Error("lineage unavailable")
|
throw new Error("lineage unavailable")
|
||||||
}) as unknown as RunContext["client"]["session"]["get"]
|
}))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -401,17 +401,17 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_direct_child"
|
ctx.sessionID = "ses_direct_child"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "ses_direct_child" ? "ses_root_tracked" : undefined,
|
parentID: path.id === "ses_direct_child" ? "ses_root_tracked" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "ses_direct_child"
|
data: path.id === "ses_direct_child"
|
||||||
? [{ info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4" } }]
|
? [{ info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4" } }]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -437,20 +437,20 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_child_after_compaction"
|
ctx.sessionID = "ses_child_after_compaction"
|
||||||
setSessionAgent("ses_child_after_compaction", "atlas")
|
setSessionAgent("ses_child_after_compaction", "atlas")
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "ses_child_after_compaction" ? "root-session" : undefined,
|
parentID: path.id === "ses_child_after_compaction" ? "root-session" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "ses_child_after_compaction"
|
data: path.id === "ses_child_after_compaction"
|
||||||
? [
|
? [
|
||||||
{ info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4" } },
|
{ info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4" } },
|
||||||
{ info: { agent: "compaction", providerID: "openai", modelID: "gpt-5.4" } },
|
{ info: { agent: "compaction", providerID: "openai", modelID: "gpt-5.4" } },
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -472,13 +472,13 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
|
|
||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_sqlite_descendant"
|
ctx.sessionID = "ses_sqlite_descendant"
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "ses_sqlite_descendant" ? "root-session" : undefined,
|
parentID: path.id === "ses_sqlite_descendant" ? "root-session" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: path.id === "ses_sqlite_descendant"
|
data: path.id === "ses_sqlite_descendant"
|
||||||
? [
|
? [
|
||||||
{ id: "msg_0001", info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4", time: { created: 100 } } },
|
{ id: "msg_0001", info: { agent: "atlas", providerID: "openai", modelID: "gpt-5.4", time: { created: 100 } } },
|
||||||
@@ -486,7 +486,7 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
{ id: "msg_0002", info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4", time: { created: 100 } } },
|
{ id: "msg_0002", info: { agent: "sisyphus-junior", providerID: "openai", modelID: "gpt-5.4", time: { created: 100 } } },
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
})) as unknown as RunContext["client"]["session"]["messages"]
|
})))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
@@ -512,13 +512,13 @@ describe("checkCompletionConditions continuation coverage", () => {
|
|||||||
const ctx = createMockContext(directory)
|
const ctx = createMockContext(directory)
|
||||||
ctx.sessionID = "ses_appended_child"
|
ctx.sessionID = "ses_appended_child"
|
||||||
setSessionAgent("ses_appended_child", "atlas")
|
setSessionAgent("ses_appended_child", "atlas")
|
||||||
ctx.client.session.get = mock(async ({ path }: { path: { id: string } }) => ({
|
ctx.client.session.get = testCoerce<RunContext["client"]["session"]["get"]>(mock(async ({ path }: { path: { id: string } }) => ({
|
||||||
data: {
|
data: {
|
||||||
id: path.id,
|
id: path.id,
|
||||||
parentID: path.id === "ses_appended_child" ? "ses_root_tracked" : undefined,
|
parentID: path.id === "ses_appended_child" ? "ses_root_tracked" : undefined,
|
||||||
},
|
},
|
||||||
})) as unknown as RunContext["client"]["session"]["get"]
|
})))
|
||||||
ctx.client.session.messages = mock(async () => ({ data: [] })) as unknown as RunContext["client"]["session"]["messages"]
|
ctx.client.session.messages = testCoerce<RunContext["client"]["session"]["messages"]>(mock(async () => ({ data: [] })))
|
||||||
|
|
||||||
const { checkCompletionConditions } = await import("./completion")
|
const { checkCompletionConditions } = await import("./completion")
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const createMockContext = (overrides: {
|
|||||||
} = overrides
|
} = overrides
|
||||||
|
|
||||||
return {
|
return {
|
||||||
client: {
|
client: testCoerce<RunContext["client"]>({
|
||||||
session: {
|
session: {
|
||||||
todo: mock(() => Promise.resolve({ data: [] })),
|
todo: mock(() => Promise.resolve({ data: [] })),
|
||||||
children: mock((opts: { path: { id: string } }) =>
|
children: mock((opts: { path: { id: string } }) =>
|
||||||
@@ -21,7 +21,7 @@ const createMockContext = (overrides: {
|
|||||||
),
|
),
|
||||||
status: mock(() => Promise.resolve({ data: statuses })),
|
status: mock(() => Promise.resolve({ data: statuses })),
|
||||||
},
|
},
|
||||||
} as unknown as RunContext["client"],
|
}),
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
directory: "/test",
|
directory: "/test",
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const createMockContext = (overrides: {
|
|||||||
} = overrides
|
} = overrides
|
||||||
|
|
||||||
return {
|
return {
|
||||||
client: {
|
client: testCoerce<RunContext["client"]>({
|
||||||
session: {
|
session: {
|
||||||
todo: mock(() => Promise.resolve({ data: todo })),
|
todo: mock(() => Promise.resolve({ data: todo })),
|
||||||
children: mock((opts: { path: { id: string } }) =>
|
children: mock((opts: { path: { id: string } }) =>
|
||||||
@@ -21,7 +21,7 @@ const createMockContext = (overrides: {
|
|||||||
),
|
),
|
||||||
status: mock(() => Promise.resolve({ data: statuses })),
|
status: mock(() => Promise.resolve({ data: statuses })),
|
||||||
},
|
},
|
||||||
} as unknown as RunContext["client"],
|
}),
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
directory: "/test",
|
directory: "/test",
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ describe("handleSessionStatus", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when - handleSessionStatus called with idle status
|
//#when - handleSessionStatus called with idle status
|
||||||
handleSessionStatus(ctx, payload as any, state)
|
handleSessionStatus(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then - state.mainSessionIdle === true
|
//#then - state.mainSessionIdle === true
|
||||||
expect(state.mainSessionIdle).toBe(true)
|
expect(state.mainSessionIdle).toBe(true)
|
||||||
@@ -44,7 +44,7 @@ describe("handleSessionStatus", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when - handleSessionStatus called with busy status
|
//#when - handleSessionStatus called with busy status
|
||||||
handleSessionStatus(ctx, payload as any, state)
|
handleSessionStatus(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then - state.mainSessionIdle === false
|
//#then - state.mainSessionIdle === false
|
||||||
expect(state.mainSessionIdle).toBe(false)
|
expect(state.mainSessionIdle).toBe(false)
|
||||||
@@ -65,7 +65,7 @@ describe("handleSessionStatus", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when - handleSessionStatus called with different session ID
|
//#when - handleSessionStatus called with different session ID
|
||||||
handleSessionStatus(ctx, payload as any, state)
|
handleSessionStatus(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then - state.mainSessionIdle remains unchanged
|
//#then - state.mainSessionIdle remains unchanged
|
||||||
expect(state.mainSessionIdle).toBe(true)
|
expect(state.mainSessionIdle).toBe(true)
|
||||||
@@ -86,7 +86,7 @@ describe("handleSessionStatus", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when - handleSessionStatus called with camelCase sessionId
|
//#when - handleSessionStatus called with camelCase sessionId
|
||||||
handleSessionStatus(ctx, payload as any, state)
|
handleSessionStatus(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then - state.mainSessionIdle === true
|
//#then - state.mainSessionIdle === true
|
||||||
expect(state.mainSessionIdle).toBe(true)
|
expect(state.mainSessionIdle).toBe(true)
|
||||||
@@ -114,7 +114,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleMessagePartUpdated(ctx, payload as any, state)
|
handleMessagePartUpdated(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.hasReceivedMeaningfulWork).toBe(true)
|
expect(state.hasReceivedMeaningfulWork).toBe(true)
|
||||||
@@ -142,7 +142,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleMessagePartUpdated(ctx, payload as any, state)
|
handleMessagePartUpdated(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.hasReceivedMeaningfulWork).toBe(false)
|
expect(state.hasReceivedMeaningfulWork).toBe(false)
|
||||||
@@ -170,7 +170,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleMessagePartUpdated(ctx, payload as any, state)
|
handleMessagePartUpdated(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.currentTool).toBe("read")
|
expect(state.currentTool).toBe("read")
|
||||||
@@ -200,7 +200,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleMessagePartUpdated(ctx, payload as any, state)
|
handleMessagePartUpdated(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.currentTool).toBeNull()
|
expect(state.currentTool).toBeNull()
|
||||||
@@ -225,7 +225,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleMessagePartUpdated(ctx, payload as any, state)
|
handleMessagePartUpdated(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.hasReceivedMeaningfulWork).toBe(true)
|
expect(state.hasReceivedMeaningfulWork).toBe(true)
|
||||||
@@ -243,7 +243,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
|
|
||||||
handleMessageUpdated(
|
handleMessageUpdated(
|
||||||
ctx,
|
ctx,
|
||||||
{
|
testCoerce({
|
||||||
type: "message.updated",
|
type: "message.updated",
|
||||||
properties: {
|
properties: {
|
||||||
info: {
|
info: {
|
||||||
@@ -254,7 +254,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
modelID: "claude-sonnet-4-6",
|
modelID: "claude-sonnet-4-6",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as any,
|
}),
|
||||||
state,
|
state,
|
||||||
)
|
)
|
||||||
state.messageStartedAtById["msg_1"] = 1000
|
state.messageStartedAtById["msg_1"] = 1000
|
||||||
@@ -262,7 +262,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
// when
|
// when
|
||||||
handleMessagePartUpdated(
|
handleMessagePartUpdated(
|
||||||
ctx,
|
ctx,
|
||||||
{
|
testCoerce({
|
||||||
type: "message.part.updated",
|
type: "message.part.updated",
|
||||||
properties: {
|
properties: {
|
||||||
part: {
|
part: {
|
||||||
@@ -274,13 +274,13 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
time: { end: 1 },
|
time: { end: 1 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as any,
|
}),
|
||||||
state,
|
state,
|
||||||
)
|
)
|
||||||
|
|
||||||
handleMessagePartUpdated(
|
handleMessagePartUpdated(
|
||||||
ctx,
|
ctx,
|
||||||
{
|
testCoerce({
|
||||||
type: "message.part.updated",
|
type: "message.part.updated",
|
||||||
properties: {
|
properties: {
|
||||||
part: {
|
part: {
|
||||||
@@ -292,7 +292,7 @@ describe("handleMessagePartUpdated", () => {
|
|||||||
time: { end: 2 },
|
time: { end: 2 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as any,
|
}),
|
||||||
state,
|
state,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ describe("handleTuiToast", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleTuiToast(ctx, payload as any, state)
|
handleTuiToast(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.mainSessionError).toBe(true)
|
expect(state.mainSessionError).toBe(true)
|
||||||
@@ -344,7 +344,7 @@ describe("handleTuiToast", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#when
|
//#when
|
||||||
handleTuiToast(ctx, payload as any, state)
|
handleTuiToast(ctx, testCoerce(payload), state)
|
||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(state.mainSessionError).toBe(false)
|
expect(state.mainSessionError).toBe(false)
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ function createMockWriteStream(): MockWriteStream {
|
|||||||
|
|
||||||
const createMockClient = (
|
const createMockClient = (
|
||||||
getResult?: { error?: unknown; data?: { id: string } }
|
getResult?: { error?: unknown; data?: { id: string } }
|
||||||
): OpencodeClient => ({
|
): OpencodeClient => (testCoerce<OpencodeClient>({
|
||||||
session: {
|
session: {
|
||||||
get: mock((opts: { path: { id: string } }) =>
|
get: mock((opts: { path: { id: string } }) =>
|
||||||
Promise.resolve(getResult ?? { data: { id: opts.path.id } })
|
Promise.resolve(getResult ?? { data: { id: opts.path.id } })
|
||||||
),
|
),
|
||||||
create: mock(() => Promise.resolve({ data: { id: "new-session-id" } })),
|
create: mock(() => Promise.resolve({ data: { id: "new-session-id" } })),
|
||||||
},
|
},
|
||||||
} as unknown as OpencodeClient)
|
}))
|
||||||
|
|
||||||
describe("integration: --json mode", () => {
|
describe("integration: --json mode", () => {
|
||||||
it("emits valid RunResult JSON to stdout", () => {
|
it("emits valid RunResult JSON to stdout", () => {
|
||||||
@@ -78,8 +78,8 @@ describe("integration: --json mode", () => {
|
|||||||
summary: "Test summary",
|
summary: "Test summary",
|
||||||
}
|
}
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -103,8 +103,8 @@ describe("integration: --json mode", () => {
|
|||||||
const mockStdout = createMockWriteStream()
|
const mockStdout = createMockWriteStream()
|
||||||
const mockStderr = createMockWriteStream()
|
const mockStderr = createMockWriteStream()
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
manager.redirectToStderr()
|
manager.redirectToStderr()
|
||||||
|
|
||||||
@@ -272,8 +272,8 @@ describe("integration: option combinations", () => {
|
|||||||
summary: "Test completed",
|
summary: "Test completed",
|
||||||
}
|
}
|
||||||
const jsonManager = createJsonOutputManager({
|
const jsonManager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
jsonManager.redirectToStderr()
|
jsonManager.redirectToStderr()
|
||||||
spawnSpy.mockClear()
|
spawnSpy.mockClear()
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ describe("createJsonOutputManager", () => {
|
|||||||
it("causes stdout writes to go to stderr", () => {
|
it("causes stdout writes to go to stderr", () => {
|
||||||
// given
|
// given
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
manager.redirectToStderr()
|
manager.redirectToStderr()
|
||||||
|
|
||||||
@@ -49,8 +49,8 @@ describe("createJsonOutputManager", () => {
|
|||||||
it("reverses the redirect", () => {
|
it("reverses the redirect", () => {
|
||||||
// given
|
// given
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
manager.redirectToStderr()
|
manager.redirectToStderr()
|
||||||
|
|
||||||
@@ -75,8 +75,8 @@ describe("createJsonOutputManager", () => {
|
|||||||
summary: "Test summary",
|
summary: "Test summary",
|
||||||
}
|
}
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -98,8 +98,8 @@ describe("createJsonOutputManager", () => {
|
|||||||
summary: "Test summary",
|
summary: "Test summary",
|
||||||
}
|
}
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -126,8 +126,8 @@ describe("createJsonOutputManager", () => {
|
|||||||
summary: "Test",
|
summary: "Test",
|
||||||
}
|
}
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
manager.redirectToStderr()
|
manager.redirectToStderr()
|
||||||
|
|
||||||
@@ -148,8 +148,8 @@ describe("createJsonOutputManager", () => {
|
|||||||
it("work correctly", () => {
|
it("work correctly", () => {
|
||||||
// given
|
// given
|
||||||
const manager = createJsonOutputManager({
|
const manager = createJsonOutputManager({
|
||||||
stdout: mockStdout as unknown as NodeJS.WriteStream,
|
stdout: testCoerce<NodeJS.WriteStream>(mockStdout),
|
||||||
stderr: mockStderr as unknown as NodeJS.WriteStream,
|
stderr: testCoerce<NodeJS.WriteStream>(mockStderr),
|
||||||
})
|
})
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const createMockContext = (overrides: {
|
|||||||
} = overrides
|
} = overrides
|
||||||
|
|
||||||
return {
|
return {
|
||||||
client: {
|
client: testCoerce<RunContext["client"]>({
|
||||||
session: {
|
session: {
|
||||||
todo: mock(() => Promise.resolve({ data: todo })),
|
todo: mock(() => Promise.resolve({ data: todo })),
|
||||||
children: mock((opts: { path: { id: string } }) =>
|
children: mock((opts: { path: { id: string } }) =>
|
||||||
@@ -23,7 +23,7 @@ const createMockContext = (overrides: {
|
|||||||
),
|
),
|
||||||
status: mock(() => Promise.resolve({ data: statuses })),
|
status: mock(() => Promise.resolve({ data: statuses })),
|
||||||
},
|
},
|
||||||
} as unknown as RunContext["client"],
|
}),
|
||||||
sessionID: "test-session",
|
sessionID: "test-session",
|
||||||
directory: "/test",
|
directory: "/test",
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@@ -124,7 +124,7 @@ describe("pollForCompletion", () => {
|
|||||||
let todoCallCount = 0
|
let todoCallCount = 0
|
||||||
let busyInserted = false
|
let busyInserted = false
|
||||||
|
|
||||||
;(ctx.client.session as any).todo = mock(async () => {
|
;(testCoerce(ctx.client.session)).todo = mock(async () => {
|
||||||
todoCallCount++
|
todoCallCount++
|
||||||
if (todoCallCount === 1 && !busyInserted) {
|
if (todoCallCount === 1 && !busyInserted) {
|
||||||
busyInserted = true
|
busyInserted = true
|
||||||
@@ -133,10 +133,10 @@ describe("pollForCompletion", () => {
|
|||||||
}
|
}
|
||||||
return { data: [] }
|
return { data: [] }
|
||||||
})
|
})
|
||||||
;(ctx.client.session as any).children = mock(() =>
|
;(testCoerce(ctx.client.session)).children = mock(() =>
|
||||||
Promise.resolve({ data: [] })
|
Promise.resolve({ data: [] })
|
||||||
)
|
)
|
||||||
;(ctx.client.session as any).status = mock(() =>
|
;(testCoerce(ctx.client.session)).status = mock(() =>
|
||||||
Promise.resolve({ data: {} })
|
Promise.resolve({ data: {} })
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -322,17 +322,17 @@ describe("pollForCompletion", () => {
|
|||||||
const abortController = new AbortController()
|
const abortController = new AbortController()
|
||||||
let pollTick = 0
|
let pollTick = 0
|
||||||
|
|
||||||
;(ctx.client.session as any).todo = mock(async () => {
|
;(testCoerce(ctx.client.session)).todo = mock(async () => {
|
||||||
pollTick++
|
pollTick++
|
||||||
if (pollTick === 2) {
|
if (pollTick === 2) {
|
||||||
eventState.currentTool = "task"
|
eventState.currentTool = "task"
|
||||||
}
|
}
|
||||||
return { data: [] }
|
return { data: [] }
|
||||||
})
|
})
|
||||||
;(ctx.client.session as any).children = mock(() =>
|
;(testCoerce(ctx.client.session)).children = mock(() =>
|
||||||
Promise.resolve({ data: [] })
|
Promise.resolve({ data: [] })
|
||||||
)
|
)
|
||||||
;(ctx.client.session as any).status = mock(() =>
|
;(testCoerce(ctx.client.session)).status = mock(() =>
|
||||||
Promise.resolve({ data: {} })
|
Promise.resolve({ data: {} })
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const createMockClient = (overrides: {
|
|||||||
} = {}): OpencodeClient => {
|
} = {}): OpencodeClient => {
|
||||||
const { getResult, createResults = [] } = overrides
|
const { getResult, createResults = [] } = overrides
|
||||||
let createCallIndex = 0
|
let createCallIndex = 0
|
||||||
return {
|
return testCoerce<OpencodeClient>({
|
||||||
session: {
|
session: {
|
||||||
get: mock((opts: { path: { id: string } }) =>
|
get: mock((opts: { path: { id: string } }) =>
|
||||||
Promise.resolve(getResult ?? { data: { id: opts.path.id } })
|
Promise.resolve(getResult ?? { data: { id: opts.path.id } })
|
||||||
@@ -22,7 +22,7 @@ const createMockClient = (overrides: {
|
|||||||
return Promise.resolve(result)
|
return Promise.resolve(result)
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
} as unknown as OpencodeClient
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("resolveSession", () => {
|
describe("resolveSession", () => {
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ describe("createTimestampedStdoutController", () => {
|
|||||||
it("prefixes stdout writes when enabled", () => {
|
it("prefixes stdout writes when enabled", () => {
|
||||||
// given
|
// given
|
||||||
const stdout = createMockWriteStream()
|
const stdout = createMockWriteStream()
|
||||||
const controller = createTimestampedStdoutController(stdout as unknown as NodeJS.WriteStream)
|
const controller = createTimestampedStdoutController(testCoerce<NodeJS.WriteStream>(stdout))
|
||||||
|
|
||||||
// when
|
// when
|
||||||
controller.enable()
|
controller.enable()
|
||||||
@@ -101,7 +101,7 @@ describe("createTimestampedStdoutController", () => {
|
|||||||
it("restores original write function", () => {
|
it("restores original write function", () => {
|
||||||
// given
|
// given
|
||||||
const stdout = createMockWriteStream()
|
const stdout = createMockWriteStream()
|
||||||
const controller = createTimestampedStdoutController(stdout as unknown as NodeJS.WriteStream)
|
const controller = createTimestampedStdoutController(testCoerce<NodeJS.WriteStream>(stdout))
|
||||||
controller.enable()
|
controller.enable()
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -118,7 +118,7 @@ describe("createTimestampedStdoutController", () => {
|
|||||||
it("supports Uint8Array chunks and encoding", () => {
|
it("supports Uint8Array chunks and encoding", () => {
|
||||||
// given
|
// given
|
||||||
const stdout = createMockWriteStream()
|
const stdout = createMockWriteStream()
|
||||||
const controller = createTimestampedStdoutController(stdout as unknown as NodeJS.WriteStream)
|
const controller = createTimestampedStdoutController(testCoerce<NodeJS.WriteStream>(stdout))
|
||||||
|
|
||||||
// when
|
// when
|
||||||
controller.enable()
|
controller.enable()
|
||||||
|
|||||||
Reference in New Issue
Block a user