ai-test-guardrails 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -2
- package/package.json +1 -1
- package/.cursor/mcp.json +0 -8
- package/.prettierrc +0 -8
- package/eslint.config.js +0 -25
- package/examples/playwright/.auth/care-admin-api-rest-dev-0.json +0 -1
- package/examples/playwright/.auth/care-admin-api-rest-stage-0.json +0 -1
- package/examples/playwright/.auth/care-admin-api-soap-dev-0.json +0 -1
- package/examples/playwright/.auth/care-admin-api-soap-stage-0.json +0 -1
- package/examples/playwright/.auth/care-admin-dev-0.json +0 -1
- package/examples/playwright/.auth/care-admin-stage-0-data.json +0 -1
- package/examples/playwright/.auth/care-admin-stage-0.json +0 -1
- package/examples/playwright/.auth/care-admin-stage-1.json +0 -1
- package/examples/playwright/.auth/care-admin-stage-2.json +0 -1
- package/examples/playwright/.auth/care-community-dev-0-data.json +0 -3
- package/examples/playwright/.auth/care-community-dev-0.json +0 -15
- package/examples/playwright/.auth/care-community-stage-0.json +0 -1
- package/examples/playwright/care-admin-base.ts +0 -66
- package/examples/playwright/care-community-base.ts +0 -65
- package/examples/playwright/constants.ts +0 -3
- package/examples/playwright/pages/better-care/better-care-button.page.ts +0 -15
- package/examples/playwright/pages/better-care/menu.page.ts +0 -14
- package/examples/playwright/pages/care-admin/main.frame.ts +0 -17
- package/examples/playwright/pages/care-admin/nav.frame.ts +0 -9
- package/examples/playwright/pages/care-admin/setup.page.ts +0 -131
- package/examples/playwright/pages/care-admin/study-program.types.ts +0 -339
- package/examples/playwright/pages/care-admin/study-programs.page.ts +0 -213
- package/examples/playwright/pages/care-admin/toolbar.frame.ts +0 -42
- package/examples/playwright/pages/care-community/course-registration.page.ts +0 -43
- package/examples/playwright/pages/care-community/documents.page.ts +0 -82
- package/examples/playwright/pages/care-community/examination-results.page.ts +0 -58
- package/examples/playwright/pages/care-community/nav-bar.page.ts +0 -177
- package/examples/playwright/pages/language.page.ts +0 -111
- package/examples/playwright/pages/language.types.ts +0 -13
- package/examples/playwright/snapshots/care-admin/study-program-search-results.yml +0 -5
- package/examples/playwright.config.ts +0 -180
- package/src/config/defaultRules.ts +0 -53
- package/src/server.ts +0 -274
- package/src/types/guardrail.types.ts +0 -121
- package/src/utils/astParser.ts +0 -167
- package/src/utils/enforcement.ts +0 -123
- package/src/utils/frameworkDetector.ts +0 -52
- package/src/utils/projectScanner.ts +0 -211
- package/src/validators/architecture.ts +0 -131
- package/src/validators/determinism.ts +0 -205
- package/src/validators/flakeRisk.ts +0 -118
- package/tsconfig.json +0 -26
- package/vitest.config.ts +0 -8
package/README.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# ai-test-guardrails
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/ai-test-guardrails)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
3
6
|
An MCP (Model Context Protocol) server that provides deterministic guardrails for AI-generated and existing test automation. It validates Playwright and Cypress test proposals using AST-based analysis — detecting flake-prone patterns, enforcing architecture rules, scoring risk, and scanning entire projects in a single call.
|
|
4
7
|
|
|
5
8
|
## What It Does
|
|
6
9
|
|
|
7
|
-
- **Validates** AI-generated test code for determinism, flake risk, and architecture compliance
|
|
10
|
+
- **Validates** AI-generated test/ existing test code for determinism, flake risk, and architecture compliance
|
|
8
11
|
- **Classifies** violations as `critical`, `major`, or `minor` for prioritised remediation
|
|
9
12
|
- **Scans** entire project directories, validating every test file in one pass with severity breakdown
|
|
10
13
|
- **Detects** flake-prone constructs: hard sleeps, unbounded retries, unmocked network calls, dynamic selectors
|
|
@@ -422,10 +425,66 @@ tests/
|
|
|
422
425
|
└── severity.test.ts
|
|
423
426
|
```
|
|
424
427
|
|
|
428
|
+
## Contributing
|
|
429
|
+
|
|
430
|
+
Contributions, bug reports, and feature suggestions are welcome. This is an open source project and community input directly shapes the roadmap.
|
|
431
|
+
|
|
432
|
+
### Reporting Issues
|
|
433
|
+
|
|
434
|
+
If you find a bug or unexpected behaviour, please [open an issue](https://github.com/jch1887/ai-test-guardrails/issues) and include:
|
|
435
|
+
|
|
436
|
+
- A minimal code snippet that reproduces the problem
|
|
437
|
+
- The framework (`playwright` or `cypress`) and enforcement mode you were using
|
|
438
|
+
- The full tool output (JSON response)
|
|
439
|
+
- Your Node.js version (`node --version`)
|
|
440
|
+
|
|
441
|
+
### Suggesting Features or New Rules
|
|
442
|
+
|
|
443
|
+
Have an idea for a new validation rule, flake risk factor, or tool feature? [Open an issue](https://github.com/jch1887/ai-test-guardrails/issues) with the label **`enhancement`** and describe:
|
|
444
|
+
|
|
445
|
+
- The problem or pattern you want to catch
|
|
446
|
+
- Why it matters for test reliability or architecture
|
|
447
|
+
- Any example code that should trigger (or not trigger) the rule
|
|
448
|
+
|
|
449
|
+
### Submitting a Pull Request
|
|
450
|
+
|
|
451
|
+
1. Fork the repository and create a branch from `main`
|
|
452
|
+
2. Install dependencies: `npm install`
|
|
453
|
+
3. Make your changes — new rules live in `src/validators/`, new flake factors in `src/validators/flakeRisk.ts`
|
|
454
|
+
4. Add or update tests in `tests/` to cover your change
|
|
455
|
+
5. Ensure all checks pass:
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
npm test # all tests must pass
|
|
459
|
+
npm run lint # no lint errors
|
|
460
|
+
npm run typecheck # no type errors
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
6. Open a pull request against `main` with a clear description of what changed and why
|
|
464
|
+
|
|
465
|
+
### Development Setup
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
git clone https://github.com/jch1887/ai-test-guardrails.git
|
|
469
|
+
cd ai-test-guardrails
|
|
470
|
+
npm install
|
|
471
|
+
npm run build
|
|
472
|
+
npm test
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Code Style
|
|
476
|
+
|
|
477
|
+
- TypeScript strict mode is enabled — avoid `any`
|
|
478
|
+
- Prettier and ESLint configs are included; run `npm run format` before committing
|
|
479
|
+
- Keep rule logic self-contained and unit-testable
|
|
480
|
+
- Violation messages should be actionable: say what to do, not just what went wrong
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
425
484
|
## Roadmap
|
|
426
485
|
|
|
427
486
|
- [x] **v0.1** — Core validation engine, three enforcement modes, project scanning
|
|
428
|
-
- [x] **v0.2** — Violation severity tiers (critical / major / minor),
|
|
487
|
+
- [x] **v0.2** — Violation severity tiers (critical / major / minor), severity breakdown in scan summary, two-pass `.js`/`.ts` file discovery
|
|
429
488
|
- [ ] **v0.3** — Auto-fix suggestions in violation messages
|
|
430
489
|
- [ ] **v0.3** — Cypress-specific selector pattern detection
|
|
431
490
|
- [ ] **v0.4** — Support for custom rule plugins
|
package/package.json
CHANGED
package/.cursor/mcp.json
DELETED
package/.prettierrc
DELETED
package/eslint.config.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import tseslint from "typescript-eslint";
|
|
2
|
-
|
|
3
|
-
export default tseslint.config(
|
|
4
|
-
{
|
|
5
|
-
ignores: ["dist/", "node_modules/", "*.config.*"],
|
|
6
|
-
},
|
|
7
|
-
...tseslint.configs.strictTypeChecked,
|
|
8
|
-
{
|
|
9
|
-
languageOptions: {
|
|
10
|
-
parserOptions: {
|
|
11
|
-
projectService: true,
|
|
12
|
-
tsconfigRootDir: import.meta.dirname,
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
rules: {
|
|
16
|
-
"@typescript-eslint/no-unused-vars": [
|
|
17
|
-
"error",
|
|
18
|
-
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
|
19
|
-
],
|
|
20
|
-
"@typescript-eslint/explicit-function-return-type": "error",
|
|
21
|
-
"@typescript-eslint/no-explicit-any": "error",
|
|
22
|
-
"@typescript-eslint/strict-boolean-expressions": "off",
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cookies": [
|
|
3
|
-
{
|
|
4
|
-
"name": "PHPSESSID",
|
|
5
|
-
"value": "3qoqnrnr3rj3fola066u63pgm2",
|
|
6
|
-
"domain": "fs.care.idss-dev.iu-aws.de",
|
|
7
|
-
"path": "/",
|
|
8
|
-
"expires": -1,
|
|
9
|
-
"httpOnly": true,
|
|
10
|
-
"secure": false,
|
|
11
|
-
"sameSite": "Lax"
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"origins": []
|
|
15
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { createTest, expect } from "@iu/playwright-test-utils/care-admin/base";
|
|
2
|
-
import type { Page } from "@playwright/test";
|
|
3
|
-
import { BetterCareButtonPage } from "./pages/better-care/better-care-button.page";
|
|
4
|
-
import { MenuPage } from "./pages/better-care/menu.page";
|
|
5
|
-
import { Main } from "./pages/care-admin/main.frame";
|
|
6
|
-
import { Nav } from "./pages/care-admin/nav.frame";
|
|
7
|
-
import { SetupPage } from "./pages/care-admin/setup.page";
|
|
8
|
-
import { StudyProgramsPage } from "./pages/care-admin/study-programs.page";
|
|
9
|
-
import { Toolbar } from "./pages/care-admin/toolbar.frame";
|
|
10
|
-
|
|
11
|
-
/*
|
|
12
|
-
This file allows us to inherit any fixtures from the utils library as well as add our own.
|
|
13
|
-
|
|
14
|
-
See https://playwright.dev/docs/test-fixtures for more details or the Care Community base file for a more comprehensive example.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
type TestFixtures = {
|
|
18
|
-
page: Page;
|
|
19
|
-
setup: SetupPage;
|
|
20
|
-
studyPrograms: StudyProgramsPage;
|
|
21
|
-
toolbar: Toolbar;
|
|
22
|
-
main: Main;
|
|
23
|
-
nav: Nav;
|
|
24
|
-
// Better Care
|
|
25
|
-
menu: MenuPage;
|
|
26
|
-
betterCareButton: BetterCareButtonPage;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const base = createTest();
|
|
30
|
-
|
|
31
|
-
const test = base.extend<TestFixtures>({
|
|
32
|
-
async page({ page }, use) {
|
|
33
|
-
await use(page);
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
async setup({ page }, use) {
|
|
37
|
-
await use(new SetupPage(page));
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
async toolbar({ page }, use) {
|
|
41
|
-
await use(new Toolbar(page));
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
async nav({ page }, use) {
|
|
45
|
-
await use(new Nav(page));
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
async main({ page }, use) {
|
|
49
|
-
await use(new Main(page));
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
async studyPrograms({ page, setup, toolbar, main }, use) {
|
|
53
|
-
await use(new StudyProgramsPage(page, setup, toolbar, main));
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
// Better Care
|
|
57
|
-
async menu({ nav }, use) {
|
|
58
|
-
await use(new MenuPage(nav));
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
async betterCareButton({ page }, use) {
|
|
62
|
-
await use(new BetterCareButtonPage(page));
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
export { test, expect };
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createTest,
|
|
3
|
-
expect,
|
|
4
|
-
} from "@iu/playwright-test-utils/care-community/base";
|
|
5
|
-
import type { Page } from "@playwright/test";
|
|
6
|
-
import { CourseRegistrationPage } from "./pages/care-community/course-registration.page";
|
|
7
|
-
import { DocumentsPage } from "./pages/care-community/documents.page";
|
|
8
|
-
import { ExaminationResultsPage } from "./pages/care-community/examination-results.page";
|
|
9
|
-
import { NavBar } from "./pages/care-community/nav-bar.page";
|
|
10
|
-
import { Language } from "./pages/language.page";
|
|
11
|
-
|
|
12
|
-
const base = createTest();
|
|
13
|
-
|
|
14
|
-
type TestFixtures = {
|
|
15
|
-
page: Page;
|
|
16
|
-
navBar: NavBar;
|
|
17
|
-
courseRegistrationPage: CourseRegistrationPage;
|
|
18
|
-
documentsPage: DocumentsPage;
|
|
19
|
-
examinationResultsPage: ExaminationResultsPage;
|
|
20
|
-
language: Language;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
This file allows us to inherit any fixtures from the utils library as well as add our own.
|
|
25
|
-
|
|
26
|
-
In this example we are inheriting the fixtures provided from the utils library and adding our own additional fixtures.
|
|
27
|
-
|
|
28
|
-
For example we have added `language` and `navBar` which means they can be imported into all our spec files without manual imports.
|
|
29
|
-
|
|
30
|
-
See https://playwright.dev/docs/test-fixtures for more details.
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
const test = base.extend<TestFixtures>({
|
|
34
|
-
async page({ page }, use) {
|
|
35
|
-
await use(page);
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
async language({ page }, use, testInfo) {
|
|
39
|
-
const language = new Language(page, testInfo);
|
|
40
|
-
|
|
41
|
-
await use(language);
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
async navBar({ page, language }, use) {
|
|
45
|
-
const navBar = new NavBar(page, language);
|
|
46
|
-
await use(navBar);
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
async documentsPage({ page, language }, use) {
|
|
50
|
-
const documentsPage = new DocumentsPage(page, language);
|
|
51
|
-
await use(documentsPage);
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
async examinationResultsPage({ page }, use) {
|
|
55
|
-
const examinationResultsPage = new ExaminationResultsPage(page);
|
|
56
|
-
await use(examinationResultsPage);
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
async courseRegistrationPage({ page }, use) {
|
|
60
|
-
const courseRegistrationPage = new CourseRegistrationPage(page);
|
|
61
|
-
await use(courseRegistrationPage);
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
export { test, expect };
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export const PROFILE_ID = "10608473"; // Academy5Id/AC5ID - QI Esmeralda
|
|
2
|
-
export const BOOKING_ID = "10958750"; // Default booking for "QI Esmeralda FS Study Tester"
|
|
3
|
-
export const COURSE_ID = "10050031"; // Course ID for "Einführung in die Soziale Arbeit (DLBSAESA01-QI)" in FS BA QIBA test study programme
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { Locator, Page } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
export class BetterCareButtonPage {
|
|
4
|
-
readonly bubble: Locator;
|
|
5
|
-
readonly infoPanel: Locator;
|
|
6
|
-
readonly debugModeToggle: Locator;
|
|
7
|
-
|
|
8
|
-
constructor(private readonly page: Page) {
|
|
9
|
-
this.bubble = this.page
|
|
10
|
-
.getByTestId("bcv2-global-module-container")
|
|
11
|
-
.filter({ hasText: "Better Care" });
|
|
12
|
-
this.infoPanel = this.page.getByTestId("bcv2-info-panel");
|
|
13
|
-
this.debugModeToggle = this.infoPanel.getByTestId("debug-mode-toggle");
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Locator } from "@playwright/test";
|
|
2
|
-
import type { Nav } from "../care-admin/nav.frame";
|
|
3
|
-
|
|
4
|
-
export class MenuPage {
|
|
5
|
-
readonly peopleSearch: Locator;
|
|
6
|
-
readonly studyPrograms: Locator;
|
|
7
|
-
readonly showFullMenu: Locator;
|
|
8
|
-
|
|
9
|
-
constructor(private readonly nav: Nav) {
|
|
10
|
-
this.peopleSearch = this.nav.frame.getByTestId("menu-people-search");
|
|
11
|
-
this.studyPrograms = this.nav.frame.getByTestId("menu-study-programs");
|
|
12
|
-
this.showFullMenu = this.nav.frame.getByTestId("menu-show-full-menu");
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { FrameLocator, Locator, Page } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
type MenuItems = {
|
|
4
|
-
edit: Locator;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export class Main {
|
|
8
|
-
readonly frame: FrameLocator;
|
|
9
|
-
readonly menuItems: MenuItems;
|
|
10
|
-
|
|
11
|
-
constructor(private readonly page: Page) {
|
|
12
|
-
this.frame = this.page.frameLocator("#main");
|
|
13
|
-
this.menuItems = {
|
|
14
|
-
edit: this.frame.locator(".menuitems").filter({ hasText: "Bearbeiten" }),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import type { Frame, FrameLocator, Locator, Page } from "@playwright/test";
|
|
2
|
-
import { expect } from "playwright/care-admin-base";
|
|
3
|
-
|
|
4
|
-
export class SetupPage {
|
|
5
|
-
readonly sideBySideFrame: FrameLocator;
|
|
6
|
-
readonly navBar: Locator;
|
|
7
|
-
readonly reminder: Locator;
|
|
8
|
-
readonly reminderClose: Locator;
|
|
9
|
-
|
|
10
|
-
constructor(private readonly page: Page) {
|
|
11
|
-
this.sideBySideFrame = this.page.frameLocator("#side-by-side-iframe");
|
|
12
|
-
this.navBar = this.page.locator("#navbar-academy-five");
|
|
13
|
-
this.reminder = this.page.locator(".p-reminder");
|
|
14
|
-
this.reminderClose = this.page.locator(".p-reminder-close");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private async waitForHomeUrl() {
|
|
18
|
-
// wait till the url changed to /home (note that Firefox loads home#)
|
|
19
|
-
await this.page.waitForURL("/home**");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
private async setupAuthenticatedPage() {
|
|
23
|
-
// Navigate to login page
|
|
24
|
-
await this.page.goto("/");
|
|
25
|
-
|
|
26
|
-
await this.waitForHomeUrl();
|
|
27
|
-
|
|
28
|
-
// wait till #navbar-academy-five exists and is visible
|
|
29
|
-
await expect(this.navBar).toBeVisible({ timeout: 20000 });
|
|
30
|
-
|
|
31
|
-
// wait till everything is loaded
|
|
32
|
-
await this.page.waitForLoadState("domcontentloaded");
|
|
33
|
-
|
|
34
|
-
// wait till frame elements exist on page
|
|
35
|
-
await this.page.waitForSelector("#nav", { state: "visible" });
|
|
36
|
-
await this.page.waitForSelector("#main", { state: "visible" });
|
|
37
|
-
|
|
38
|
-
// Debug: Log all available frames
|
|
39
|
-
const allFrames: Record<string, Frame> = {};
|
|
40
|
-
for (const f of this.page.frames()) {
|
|
41
|
-
if (f.isDetached()) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
allFrames[
|
|
45
|
-
f.name() ||
|
|
46
|
-
(await f
|
|
47
|
-
.frameElement()
|
|
48
|
-
.then((el) => el?.getAttribute("id"))
|
|
49
|
-
.catch(() => null)) ||
|
|
50
|
-
""
|
|
51
|
-
] = f;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// get frame accessors
|
|
55
|
-
const navFrame = allFrames.nav;
|
|
56
|
-
const mainFrame = allFrames.main;
|
|
57
|
-
const toolbarFrame = allFrames.toolbar;
|
|
58
|
-
const sideBySideFrame = allFrames["side-by-side-iframe"];
|
|
59
|
-
|
|
60
|
-
// check if all frames exist
|
|
61
|
-
if (!navFrame) {
|
|
62
|
-
console.error("Failed to get navigation frame [name=nav]", navFrame);
|
|
63
|
-
throw new Error("Failed to get navigation frame [name=nav]");
|
|
64
|
-
}
|
|
65
|
-
if (!mainFrame) {
|
|
66
|
-
console.error("Failed to get main frame [name=main]", mainFrame);
|
|
67
|
-
throw new Error("Failed to get main frame [name=main]");
|
|
68
|
-
}
|
|
69
|
-
if (!toolbarFrame) {
|
|
70
|
-
console.error("Failed to get toolbar frame [name=toolbar]", toolbarFrame);
|
|
71
|
-
throw new Error("Failed to get toolbar frame [name=toolbar]");
|
|
72
|
-
}
|
|
73
|
-
if (!sideBySideFrame) {
|
|
74
|
-
throw new Error(
|
|
75
|
-
"Failed to get side-by-side-iframe [name=side-by-side-iframe]",
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// wait for all frames to be loaded
|
|
80
|
-
await Promise.all([
|
|
81
|
-
navFrame.waitForLoadState("domcontentloaded"),
|
|
82
|
-
mainFrame.waitForLoadState("domcontentloaded"),
|
|
83
|
-
toolbarFrame.waitForLoadState("domcontentloaded"),
|
|
84
|
-
]);
|
|
85
|
-
|
|
86
|
-
// wait untl mainFrame has url "/dashboard"
|
|
87
|
-
await mainFrame.waitForURL("/dashboard");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
public async frameGoto(url: string, timeout?: number) {
|
|
91
|
-
await this.page.evaluate((url) => {
|
|
92
|
-
const iFrame = document.querySelector<HTMLIFrameElement>(
|
|
93
|
-
'iframe[name="main"]',
|
|
94
|
-
);
|
|
95
|
-
if (iFrame) {
|
|
96
|
-
iFrame.src = url;
|
|
97
|
-
}
|
|
98
|
-
}, url);
|
|
99
|
-
|
|
100
|
-
// Wait for frame to be fully loaded
|
|
101
|
-
await this.page.waitForLoadState("domcontentloaded");
|
|
102
|
-
await this.page.waitForLoadState("networkidle", { timeout });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
public async loadPage(caseName?: string) {
|
|
106
|
-
await this.page.route("**/*", (route) => {
|
|
107
|
-
const headers = {
|
|
108
|
-
...route.request().headers(),
|
|
109
|
-
"X-Test-Context": caseName || "default",
|
|
110
|
-
};
|
|
111
|
-
route.continue({ headers });
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
await this.setupAuthenticatedPage();
|
|
115
|
-
await this.waitForHomeUrl();
|
|
116
|
-
|
|
117
|
-
if (await this.reminder.isVisible()) {
|
|
118
|
-
await this.reminderClose.click();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
registerApiMock: async (
|
|
123
|
-
url: string,
|
|
124
|
-
response: {
|
|
125
|
-
statusCode: number;
|
|
126
|
-
body: string;
|
|
127
|
-
},
|
|
128
|
-
) => {},
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
}
|