Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions examples/ag-ui/angular/e2e/aimock-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,14 @@ function loadFixtureEntries(fixturePath: string): FixtureFileEntry[] {
return out;
}

export async function startAimock(opts: AimockStartOptions): Promise<AimockHandle> {
export async function startAimock(
opts: AimockStartOptions
): Promise<AimockHandle> {
const entries = loadFixtureEntries(opts.fixturePath);

// Use a large chunkSize so each response arrives in 1-2 SSE deltas. This
// intentionally turns off the partial-markdown streaming path for harness
// tests: structural assertions (code fence, list) measure the FINAL rendered
// DOM, not the progressive render. With aggressive default chunking, the
// partial-markdown parser sometimes can't recover a triple-backtick fence
// that gets split mid-token, and the final state ends up as inline <code>
// instead of <pre><code>. Streaming-progressive behavior is covered by the
// Phase 1 unit-variance tables; the e2e harness is for final-state
// invariants and cross-stack integration.
// Keep ordinary fixtures fast with a large default chunk. Progressive
// rendering regressions opt into deterministic chunk sizes and latency on
// the individual fixture so they exercise the complete AG-UI transport.
const mock = new LLMock({ port: 0, chunkSize: 4096 });
if (entries.length > 0) {
mock.addFixturesFromJSON(entries as never);
Expand Down
60 changes: 57 additions & 3 deletions examples/ag-ui/angular/e2e/fixtures/markdown.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,75 @@
"fixtures": [
{
"match": { "userMessage": "respond with a heading" },
"response": { "content": "# Heading One\n\nA short paragraph below the heading." }
"response": {
"content": "# Heading One\n\nA short paragraph below the heading."
}
},
{
"match": { "userMessage": "respond with a code fence" },
"response": { "content": "Here's the snippet:\n\n```typescript\nconst answer = 42;\n```\n\nThat's it." }
"response": {
"content": "Here's the snippet:\n\n```typescript\nconst answer = 42;\n```\n\nThat's it."
}
},
{
"match": { "userMessage": "respond with a bullet list" },
"response": { "content": "Three things:\n\n- alpha\n- beta\n- gamma" }
},
{
"match": { "userMessage": "respond with the markdown checklist kitchen sink" },
"match": {
"userMessage": "respond with the markdown checklist kitchen sink"
},
"response": {
"content": "# Heading One\n\n## Heading Two\n\n### Heading Three\n\nA paragraph with **bold text**, *italic text*, and `inline code`.\n\n- parent item\n - nested child\n- second parent\n\n1. first ordered\n2. second ordered\n\n- [ ] unchecked task\n- [x] checked task\n\n```typescript\nconst answer = 42;\n```\n\n| Name | Mental model | When to use |\n| --- | --- | --- |\n| Signals | value graph | local state |\n| RxJS | event stream | async events |\n\n> This is a blockquote.\n\n[Angular](https://angular.dev)\n\n---\n\n<script>alert('xss')</script>"
}
},
{
"match": {
"userMessage": "stream an AG-UI markdown comparison table regression"
},
"response": {
"content": "Here is the comparison:\n\n| Name | Mental model | When to use |\n| --- | --- | --- |\n| Angular Signals | Synchronous value graph | Local component state |\n| RxJS | Event stream | Async flows and cancellation |\n| zone.js | Async task patching | Zone-based change detection |\n\nDone."
},
"chunkSize": 4,
"latency": 75
},
{
"match": {
"userMessage": "stream an AG-UI blockquote then table regression"
},
"response": {
"content": "> First line of the quote.\n> Second line of the quote.\n\n| Issue | Expected behavior | Verification |\n| --- | --- | --- |\n| Button click does not update UI | UI reflects new state immediately | Click button and observe state |\n| Slow initial render | Main content appears within target | Measure first meaningful paint |"
},
"chunkSize": 6,
"latency": 25
},
{
"match": {
"userMessage": "stream an AG-UI markdown table with a long header pause"
},
"response": {
"content": "Long pause table:\n\n| Name | Value |\n| --- | --- |\n| alpha | one |\n| beta | two |\n"
},
"chunkSize": 36,
"latency": 750
},
{
"match": {
"userMessage": "stream an AG-UI TypeScript code fence regression"
},
"response": {
"content": "Here is the snippet:\n\n```typescript\nconst answer = 42;\n```\n\nThe constant is available for later use."
},
"chunkSize": 3,
"latency": 35
},
{
"match": { "userMessage": "stream an AG-UI thematic break regression" },
"response": {
"content": "Before the break.\n\n---\n\nAfter the break."
},
"chunkSize": 8,
"latency": 200
}
]
}
Loading
Loading