Compare commits

..
Author SHA1 Message Date
dayuan.jiang 91b8d781bd ci: six e2e shards
With four, the shard of the long workspace tests took 8 minutes while
the others took 4 to 5.
2026-10-08 18:27:59 +09:00
dayuan.jiang 74a40082f4 ci: run the e2e tests in four shards
One job ran all 300+ tests with one worker, about 20 minutes. Four
jobs at once take a quarter each, still with one worker per job.
2026-10-08 18:11:46 +09:00
4 changed files with 400 additions and 720 deletions
+387 -630
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -33,15 +33,15 @@
"test:e2e": "playwright test"
},
"dependencies": {
"@ai-sdk/amazon-bedrock": "^5.0.0",
"@ai-sdk/anthropic": "^4.0.0",
"@ai-sdk/azure": "^4.0.0",
"@ai-sdk/deepseek": "^3.0.0",
"@ai-sdk/google": "^4.0.0",
"@ai-sdk/google-vertex": "^5.0.0",
"@ai-sdk/openai": "^4.0.0",
"@ai-sdk/openai-compatible": "^3.0.0",
"@ai-sdk/react": "^4.0.0",
"@ai-sdk/amazon-bedrock": "^4.0.191",
"@ai-sdk/anthropic": "^3.0.127",
"@ai-sdk/azure": "^3.0.133",
"@ai-sdk/deepseek": "^2.0.71",
"@ai-sdk/google": "^3.0.130",
"@ai-sdk/google-vertex": "^4.0.210",
"@ai-sdk/openai": "^3.0.124",
"@ai-sdk/openai-compatible": "^2.0.81",
"@ai-sdk/react": "^3.0.303",
"@aihubmix/ai-sdk-provider": "^2.2.1",
"@aws-sdk/client-dynamodb": "^3.957.0",
"@aws-sdk/credential-providers": "^3.943.0",
@@ -52,7 +52,7 @@
"@langfuse/tracing": "^4.4.9",
"@next/third-parties": "^16.0.6",
"@opennextjs/cloudflare": "^1.17.1",
"@openrouter/ai-sdk-provider": "^3.0.0",
"@openrouter/ai-sdk-provider": "^2.10.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.222.0",
"@opentelemetry/sdk-trace-node": "^2.2.0",
@@ -68,7 +68,7 @@
"@radix-ui/react-tooltip": "^1.1.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@xmldom/xmldom": "^0.9.8",
"ai": "^7.0.0",
"ai": "^6.0.300",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
@@ -79,7 +79,7 @@
"nanoid": "^5.0.0",
"negotiator": "^1.0.0",
"next": "^16.0.7",
"ollama-ai-provider-v2": "^4.0.0",
"ollama-ai-provider-v2": "^3.6.0",
"pako": "^2.1.0",
"prism-react-renderer": "^2.4.1",
"react": "^19.1.2",
@@ -145,7 +145,7 @@
},
"overrides": {
"@openrouter/ai-sdk-provider": {
"ai": "^7.0.0"
"ai": "^6.0.1"
}
}
}
@@ -216,20 +216,6 @@ export function applyDiagramOperations(
continue
}
// A cut-off cell (its XML still streaming in a preview) would
// parse in Chrome to a cell without its geometry
const syntaxError = getXmlSyntaxError(
`<wrapper>${op.new_xml}</wrapper>`,
)
if (syntaxError) {
errors.push({
type: "update",
cellId: op.cell_id,
message: `new_xml is not well-formed XML: ${syntaxError}`,
})
continue
}
// Parse the new XML
const newDoc = parser.parseFromString(
`<wrapper>${op.new_xml}</wrapper>`,
@@ -282,20 +268,6 @@ export function applyDiagramOperations(
continue
}
// A cut-off cell (its XML still streaming in a preview) would
// parse in Chrome to a cell without its geometry
const syntaxError = getXmlSyntaxError(
`<wrapper>${op.new_xml}</wrapper>`,
)
if (syntaxError) {
errors.push({
type: "add",
cellId: op.cell_id,
message: `new_xml is not well-formed XML: ${syntaxError}`,
})
continue
}
// Parse the new XML
const newDoc = parser.parseFromString(
`<wrapper>${op.new_xml}</wrapper>`,
@@ -149,52 +149,3 @@ describe("a wrapped mxCell with its wrapper's id", () => {
expect(result).toContain('label="B"')
})
})
describe("cut-off new_xml", () => {
// While edit_diagram streams, the last operation's XML is often
// incomplete. Chrome's DOMParser keeps the partial cell, so it must be
// refused before it reaches the diagram.
const CUT = `<mxCell id="b" value="B2" style="rounded=1;" vertex="1" parent="1">`
it("refuses an update whose XML is cut off", () => {
const { result, errors } = applyDiagramOperations(DOC, [
{ operation: "update", cell_id: "b", new_xml: CUT },
])
expect(errors).toHaveLength(1)
expect(errors[0]).toMatchObject({ type: "update", cellId: "b" })
expect(errors[0].message).toContain("not well-formed")
expect(result).toContain('value="B"')
expect(result).not.toContain("B2")
})
it("refuses an add whose XML is cut off", () => {
const { result, errors } = applyDiagramOperations(DOC, [
{
operation: "add",
cell_id: "n",
new_xml: `<mxCell id="n" value="N" vertex="1" parent="1"><mxGeometry x="1" y="2" width="3"`,
},
])
expect(errors).toHaveLength(1)
expect(errors[0]).toMatchObject({ type: "add", cellId: "n" })
expect(result).not.toContain('id="n"')
})
it("applies the complete operations before a cut-off one", () => {
const { result, errors } = applyDiagramOperations(DOC, [
{
operation: "update",
cell_id: "b",
new_xml: `<mxCell id="b" value="B3" vertex="1" parent="1"><mxGeometry as="geometry"/></mxCell>`,
},
{
operation: "add",
cell_id: "n",
new_xml: `<mxCell id="n" value="N" vertex="1" parent="1">`,
},
])
expect(errors).toHaveLength(1)
expect(result).toContain('value="B3"')
expect(result).not.toContain('id="n"')
})
})