Stabilize tests: Mocking real network in demo e2e tests - #34606
Conversation
There was a problem hiding this comment.
Pull request overview
Adds additional TestCafe RequestMock coverage for Widgets Gallery demos by routing more demo service endpoints to local fixtures, and updates the shared mock response headers to support credentialed CORS requests (Diagram demo).
Changes:
- Replace the static CORS header set with
getCrossOriginHeaders()that echoesOriginand enables credentials when applicable. - Add new endpoint handlers for Diagram employees, TemperatureData, ListData, and TreeView plain data.
- Add recorded JSON fixtures for the new handlers.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| apps/demos/testing/apiMocks/widgetsGalleryServiceMock.ts | Adds new handlers and updates CORS header behavior for credentialed requests. |
| apps/demos/testing/apiMocks/handlers/treeViewPlainData.ts | Implements virtual-mode TreeView paging over a flat fixture via filter. |
| apps/demos/testing/apiMocks/handlers/temperatureData.ts | Filters the temperature fixture by requested visible date range. |
| apps/demos/testing/apiMocks/handlers/listData.ts | Pages over pre-recorded grouped list data fixture. |
| apps/demos/testing/apiMocks/handlers/diagramEmployees.ts | Serves Diagram employees data from a fixture. |
| apps/demos/testing/apiMocks/fixtures/treeViewPlainData.json | Flat TreeView fixture used for virtual loading. |
| apps/demos/testing/apiMocks/fixtures/temperatureData.json | Temperature time-series fixture used by chart demos. |
| apps/demos/testing/apiMocks/fixtures/listData.json | Grouped list fixture used for list WebAPI demo. |
| apps/demos/testing/apiMocks/fixtures/diagramEmployees.json | Diagram employee hierarchy fixture. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Suppressed comments (3)
apps/demos/testing/apiMocks/handlers/temperatureData.ts:13
new Date(decodeURIComponent(...))relies on implementation-dependent parsing for non-ISO strings likeM/DD/YYYY(as noted in the comment). This can behave differently across environments or even returnInvalid Date, making the mock flaky. Parse the expectedM/DD/YYYYformat explicitly and only then construct aDate.
const parsed = new Date(decodeURIComponent(match[1]));
return Number.isNaN(parsed.getTime()) ? null : parsed;
apps/demos/testing/apiMocks/widgetsGalleryServiceMock.ts:25
- For credentialed cross-origin requests (withCredentials),
access-control-allow-headers: '*'is not accepted by all browsers and can still cause the preflight to be rejected. Since this mock is explicitly trying to support credentialed Diagram requests, it should echo the requested header list (fromaccess-control-request-headers) when present instead of always using*(and ideally addVary: Originwhen echoing the origin).
'access-control-allow-origin': origin ?? '*',
'access-control-allow-methods': 'GET, POST, OPTIONS',
'access-control-allow-headers': '*',
...(origin ? { 'access-control-allow-credentials': 'true' } : {}),
};
apps/demos/testing/apiMocks/handlers/treeViewPlainData.ts:14
requestedCategoryIdcan throw if thefilterquery param is missing, malformed, or not valid JSON (e.g., unexpected encoding). An exception here would break the whole RequestMock chain and make unrelated requests fail; it’s safer for a mock to treat parse errors as “no parent requested” and returnnull.
const [, categoryId] = JSON.parse(decodeURIComponent(match[1]));
return categoryId;
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 14 changed files in this pull request and generated no new comments.
Suppressed comments (1)
apps/demos/testing/apiMocks/fixtures/fileManagerDb.json:637
- The fixture contains a filename with an embedded CRLF sequence ("\r\n"), which will render as a line break in the UI and can cause unexpected layout / screenshot differences. This looks accidental data corruption during recording; it should be a normal single-line filename.
"name": "Rock Your WinForms Apps with DevExpress MVVM\r\n.mp4",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated no new comments.
Suppressed comments (2)
apps/demos/testing/apiMocks/handlers/treeViewPlainData.ts:15
requestedCategoryIdusesJSON.parse(decodeURIComponent(...))without any error handling. If thefilterquery param is missing/empty or not valid JSON, this will throw and abort the request mock, making screenshot tests fail in a hard-to-debug way. Consider parsing defensively and falling back tonullwhen parsing fails or when the decoded value isn't an array.
}
const [, categoryId] = JSON.parse(decodeURIComponent(match[1]));
return categoryId;
};
apps/demos/testing/apiMocks/handlers/fileManager.ts:21
requestedPathassumes theargumentsquery param always contains valid JSON with apathInfoarray. If the param is missing, malformed, or has an unexpected shape,JSON.parse/pathInfo.mapwill throw and break the mock. Parsing defensively (and ignoring emptynamesegments) makes the mock more robust to minor URL shape changes.
const { pathInfo } = JSON.parse(decodeURIComponent(match[1]));
return pathInfo.map(({ name }: { name: string }) => name).join('/');
};
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
apps/demos/testing/apiMocks/handlers/temperatureData.ts:14
new Date(<locale date string>)relies on implementation-dependent parsing (non-ISO input), which can behave differently across browsers/environments and make this mock flaky. Since the demos sendtoLocaleDateString('en-US'), parse the expectedM/D/YYYYformat explicitly.
const dateParam = (url: string, name: string): Date | null => {
const match = url.match(new RegExp(`[?&]${name}=([^&]*)`));
if (!match) {
return null;
}
const parsed = new Date(decodeURIComponent(match[1]));
return Number.isNaN(parsed.getTime()) ? null : parsed;
};
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (3)
apps/demos/testing/apiMocks/handlers/temperatureData.ts:18
new Date(decodeURIComponent(match[1]))parsesM/D/YYYYin an implementation-dependent way (non‑ISO), which can make the mock return different ranges across runtimes/timezones. It’s safer to parse theen-USdate format explicitly and shift days viasetDate(avoids DST/MS arithmetic pitfalls).
const parsed = new Date(decodeURIComponent(match[1]));
apps/demos/testing/apiMocks/handlers/treeViewPlainData.ts:15
requestedCategoryIdassumes thefilterquery param deserializes to a 2-item array and picks the second element. DevExtreme remote filtering typically sendsfilter=["CategoryId","=",<value>], so the current code returns the operator ("=") instead of the parent id and the handler will respond with an emptydataarray.
// GET /api/TreeViewPlainData?filter=["CategoryId",<parent id or null>]
// The TreeView loads one level per request, so the handler returns the children
// of the requested parent out of the flat fixture.
const requestedCategoryId = (url: string): string | null => {
apps/demos/testing/apiMocks/fixtures/fileManagerDb.json:637
- This filename includes an embedded CRLF ("\r\n"), which will surface as a line break in the UI and can make FileManager screenshots/platform behavior inconsistent. If this wasn’t intentional test coverage for unusual names, it should be removed.
"name": "Rock Your WinForms Apps with DevExpress MVVM\r\n.mp4",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (2)
apps/demos/testing/apiMocks/fixtures/fileManagerDb.json:637
- This fixture entry has an embedded CRLF (
\r\n) in the file name, which will render as a newline in the UI and can cause unstable screenshots / unexpected sorting. It looks like an accidental line-break and should be removed.
"name": "Rock Your WinForms Apps with DevExpress MVVM\r\n.mp4",
apps/demos/testing/apiMocks/handlers/temperatureData.ts:33
shiftDaysadds days viagetTime() + days * 24h, which can shift the local time across DST boundaries and skew the requested range filtering. Use calendar-day shifting (setDate) and drop the now-unneeded millisecond constant.
};
const shiftDays = (date: Date, days: number): Date => new Date(date.getTime() + days * MS_PER_DAY);
No description provided.