@tyndall/test-playwright 0.0.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.
Files changed (77) hide show
  1. package/README.md +30 -0
  2. package/dist/app/AppInstance.d.ts +24 -0
  3. package/dist/app/AppInstance.d.ts.map +1 -0
  4. package/dist/app/AppInstance.js +30 -0
  5. package/dist/app/AppLauncher.d.ts +32 -0
  6. package/dist/app/AppLauncher.d.ts.map +1 -0
  7. package/dist/app/AppLauncher.js +147 -0
  8. package/dist/dynamic/ManifestObserver.d.ts +24 -0
  9. package/dist/dynamic/ManifestObserver.d.ts.map +1 -0
  10. package/dist/dynamic/ManifestObserver.js +71 -0
  11. package/dist/errors.d.ts +17 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +19 -0
  14. package/dist/extensibility/EnvironmentScriptProvider.d.ts +21 -0
  15. package/dist/extensibility/EnvironmentScriptProvider.d.ts.map +1 -0
  16. package/dist/extensibility/EnvironmentScriptProvider.js +20 -0
  17. package/dist/extensibility/ExpectRegistry.d.ts +11 -0
  18. package/dist/extensibility/ExpectRegistry.d.ts.map +1 -0
  19. package/dist/extensibility/ExpectRegistry.js +18 -0
  20. package/dist/extensibility/StepRegistry.d.ts +14 -0
  21. package/dist/extensibility/StepRegistry.d.ts.map +1 -0
  22. package/dist/extensibility/StepRegistry.js +29 -0
  23. package/dist/index.d.ts +21 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +15 -0
  26. package/dist/reporter/ConsoleReporter.d.ts +6 -0
  27. package/dist/reporter/ConsoleReporter.d.ts.map +1 -0
  28. package/dist/reporter/ConsoleReporter.js +13 -0
  29. package/dist/reporter/HtmlReporter.d.ts +11 -0
  30. package/dist/reporter/HtmlReporter.d.ts.map +1 -0
  31. package/dist/reporter/HtmlReporter.js +36 -0
  32. package/dist/reporter/JsonReporter.d.ts +11 -0
  33. package/dist/reporter/JsonReporter.d.ts.map +1 -0
  34. package/dist/reporter/JsonReporter.js +12 -0
  35. package/dist/reporter/Reporter.d.ts +5 -0
  36. package/dist/reporter/Reporter.d.ts.map +1 -0
  37. package/dist/reporter/Reporter.js +1 -0
  38. package/dist/reporter/ResultCollector.d.ts +7 -0
  39. package/dist/reporter/ResultCollector.d.ts.map +1 -0
  40. package/dist/reporter/ResultCollector.js +26 -0
  41. package/dist/runner/PlaywrightRunner.d.ts +38 -0
  42. package/dist/runner/PlaywrightRunner.d.ts.map +1 -0
  43. package/dist/runner/PlaywrightRunner.js +77 -0
  44. package/dist/runner/StepExecutor.d.ts +16 -0
  45. package/dist/runner/StepExecutor.d.ts.map +1 -0
  46. package/dist/runner/StepExecutor.js +53 -0
  47. package/dist/scenario/ScenarioLoader.d.ts +4 -0
  48. package/dist/scenario/ScenarioLoader.d.ts.map +1 -0
  49. package/dist/scenario/ScenarioLoader.js +23 -0
  50. package/dist/scenario/ScenarioValidator.d.ts +15 -0
  51. package/dist/scenario/ScenarioValidator.d.ts.map +1 -0
  52. package/dist/scenario/ScenarioValidator.js +207 -0
  53. package/dist/scenario/types.d.ts +2 -0
  54. package/dist/scenario/types.d.ts.map +1 -0
  55. package/dist/scenario/types.js +1 -0
  56. package/dist/steps/click.d.ts +6 -0
  57. package/dist/steps/click.d.ts.map +1 -0
  58. package/dist/steps/click.js +3 -0
  59. package/dist/steps/expect.d.ts +7 -0
  60. package/dist/steps/expect.d.ts.map +1 -0
  61. package/dist/steps/expect.js +71 -0
  62. package/dist/steps/goto.d.ts +6 -0
  63. package/dist/steps/goto.d.ts.map +1 -0
  64. package/dist/steps/goto.js +6 -0
  65. package/dist/steps/index.d.ts +16 -0
  66. package/dist/steps/index.d.ts.map +1 -0
  67. package/dist/steps/index.js +8 -0
  68. package/dist/steps/types.d.ts +17 -0
  69. package/dist/steps/types.d.ts.map +1 -0
  70. package/dist/steps/types.js +1 -0
  71. package/dist/types/result.d.ts +25 -0
  72. package/dist/types/result.d.ts.map +1 -0
  73. package/dist/types/result.js +1 -0
  74. package/dist/types/scenario.d.ts +44 -0
  75. package/dist/types/scenario.d.ts.map +1 -0
  76. package/dist/types/scenario.js +1 -0
  77. package/package.json +28 -0
@@ -0,0 +1,71 @@
1
+ import { AssertionError } from "../errors.js";
2
+ import { defaultExpectRegistry } from "../extensibility/ExpectRegistry.js";
3
+ const EXPECT_TIMEOUT_MS = 2000;
4
+ const EXPECT_POLL_INTERVAL_MS = 50;
5
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
6
+ const buildSelectorExpectationError = (selector, expect) => {
7
+ if (expect.exists === true) {
8
+ return new AssertionError(`Expected selector ${selector} to exist`);
9
+ }
10
+ if (expect.exists === false) {
11
+ return new AssertionError(`Expected selector ${selector} to not exist`);
12
+ }
13
+ if (typeof expect.text === "string") {
14
+ return new AssertionError(`Expected ${selector} text to be "${expect.text}"`);
15
+ }
16
+ if (typeof expect.contains === "string") {
17
+ return new AssertionError(`Expected ${selector} text to include "${expect.contains}"`);
18
+ }
19
+ return new AssertionError(`Expectation failed for selector ${selector}`);
20
+ };
21
+ const matchesSelectorExpectation = (textContent, expect) => {
22
+ if (expect.exists === true && textContent === null) {
23
+ return false;
24
+ }
25
+ if (expect.exists === false && textContent !== null) {
26
+ return false;
27
+ }
28
+ if (typeof expect.text === "string" && textContent !== expect.text) {
29
+ return false;
30
+ }
31
+ if (typeof expect.contains === "string" && !textContent?.includes(expect.contains)) {
32
+ return false;
33
+ }
34
+ return true;
35
+ };
36
+ const waitForSelectorExpectation = async (selector, expect, context) => {
37
+ const deadline = Date.now() + EXPECT_TIMEOUT_MS;
38
+ while (Date.now() <= deadline) {
39
+ const textContent = await context.page.textContent(selector);
40
+ if (matchesSelectorExpectation(textContent, expect)) {
41
+ return;
42
+ }
43
+ await sleep(EXPECT_POLL_INTERVAL_MS);
44
+ }
45
+ throw buildSelectorExpectationError(selector, expect);
46
+ };
47
+ export const runExpectStep = async (step, context) => {
48
+ const { expect } = step;
49
+ if (expect.selector) {
50
+ await waitForSelectorExpectation(expect.selector, expect, context);
51
+ }
52
+ if (expect.network) {
53
+ throw new AssertionError("Network expectations are not implemented yet");
54
+ }
55
+ if (expect.dynamicManifest) {
56
+ if (!context.manifestObserver) {
57
+ throw new AssertionError("Dynamic manifest observer is not configured");
58
+ }
59
+ context.manifestObserver.assert(expect.dynamicManifest);
60
+ }
61
+ if (expect.custom) {
62
+ const registry = context.expectRegistry ?? defaultExpectRegistry;
63
+ for (const [name, value] of Object.entries(expect.custom)) {
64
+ const handler = registry.get(name);
65
+ if (!handler) {
66
+ throw new AssertionError(`Unknown expectation: ${name}`);
67
+ }
68
+ await handler(value, context);
69
+ }
70
+ }
71
+ };
@@ -0,0 +1,6 @@
1
+ import type { StepContext } from "./types.js";
2
+ export interface GotoStep {
3
+ goto: string;
4
+ }
5
+ export declare const runGotoStep: (step: GotoStep, context: StepContext) => Promise<void>;
6
+ //# sourceMappingURL=goto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goto.d.ts","sourceRoot":"","sources":["../../src/steps/goto.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,WAAW,GAAU,MAAM,QAAQ,EAAE,SAAS,WAAW,kBAKrE,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const runGotoStep = async (step, context) => {
2
+ const target = step.goto.startsWith("http")
3
+ ? step.goto
4
+ : `${context.baseUrl}${step.goto}`;
5
+ await context.page.goto(target);
6
+ };
@@ -0,0 +1,16 @@
1
+ import type { StepContext } from "./types.js";
2
+ import type { ExpectSpec } from "../types/scenario.js";
3
+ export interface StepHandlerMap {
4
+ goto: (step: {
5
+ goto: string;
6
+ }, context: StepContext) => Promise<void>;
7
+ click: (step: {
8
+ click: string;
9
+ }, context: StepContext) => Promise<void>;
10
+ expect: (step: {
11
+ expect: ExpectSpec;
12
+ }, context: StepContext) => Promise<void>;
13
+ }
14
+ export declare const defaultStepHandlers: StepHandlerMap;
15
+ export type { StepContext } from "./types.js";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,KAAK,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,UAAU,CAAA;KAAE,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E;AAED,eAAO,MAAM,mBAAmB,EAAE,cAIjC,CAAC;AAEF,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { runGotoStep } from "./goto.js";
2
+ import { runClickStep } from "./click.js";
3
+ import { runExpectStep } from "./expect.js";
4
+ export const defaultStepHandlers = {
5
+ goto: runGotoStep,
6
+ click: runClickStep,
7
+ expect: runExpectStep,
8
+ };
@@ -0,0 +1,17 @@
1
+ export interface PageLike {
2
+ goto(url: string): Promise<unknown>;
3
+ click(selector: string): Promise<unknown>;
4
+ textContent(selector: string): Promise<string | null>;
5
+ addInitScript?: (options: {
6
+ path: string;
7
+ }) => Promise<unknown>;
8
+ }
9
+ import type { ManifestObserver } from "../dynamic/ManifestObserver.js";
10
+ import type { ExpectRegistry } from "../extensibility/ExpectRegistry.js";
11
+ export interface StepContext {
12
+ page: PageLike;
13
+ baseUrl: string;
14
+ manifestObserver?: ManifestObserver;
15
+ expectRegistry?: ExpectRegistry;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/steps/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACjE;AAED,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,25 @@
1
+ import type { ScenarioCase } from "./scenario.js";
2
+ export type StepStatus = "passed" | "failed" | "skipped";
3
+ export interface StepResult {
4
+ status: StepStatus;
5
+ startedAt: number;
6
+ finishedAt: number;
7
+ error?: string;
8
+ errorType?: string;
9
+ screenshotPath?: string;
10
+ }
11
+ export interface ScenarioResult {
12
+ scenario: ScenarioCase;
13
+ steps: StepResult[];
14
+ status: StepStatus;
15
+ startedAt: number;
16
+ finishedAt: number;
17
+ }
18
+ export interface AggregatedResult {
19
+ name: string;
20
+ scenarios: ScenarioResult[];
21
+ status: StepStatus;
22
+ startedAt: number;
23
+ finishedAt: number;
24
+ }
25
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/types/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ export type ScenarioMode = "dev" | "ssg" | "ssr";
2
+ export interface ScenarioSetup {
3
+ env?: Record<string, string>;
4
+ }
5
+ export interface DynamicManifestExpectation {
6
+ mode?: "meta" | "program";
7
+ pageId?: string;
8
+ version?: string;
9
+ }
10
+ export interface NetworkExpectation {
11
+ url?: string;
12
+ method?: string;
13
+ status?: number;
14
+ count?: number;
15
+ }
16
+ export interface ExpectSpec {
17
+ selector?: string;
18
+ text?: string;
19
+ contains?: string;
20
+ exists?: boolean;
21
+ network?: NetworkExpectation;
22
+ dynamicManifest?: DynamicManifestExpectation;
23
+ custom?: Record<string, unknown>;
24
+ }
25
+ export type Step = {
26
+ goto: string;
27
+ } | {
28
+ click: string;
29
+ } | {
30
+ expect: ExpectSpec;
31
+ } | Record<string, unknown>;
32
+ export interface ScenarioCase {
33
+ id: string;
34
+ name?: string;
35
+ steps: Step[];
36
+ }
37
+ export interface ScenarioDocument {
38
+ name: string;
39
+ mode?: ScenarioMode;
40
+ baseUrl?: string;
41
+ setup?: ScenarioSetup;
42
+ scenarios: ScenarioCase[];
43
+ }
44
+ //# sourceMappingURL=scenario.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../../src/types/scenario.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,eAAe,CAAC,EAAE,0BAA0B,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,IAAI,GACZ;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GACjB;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5B,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@tyndall/test-playwright",
3
+ "version": "0.0.1",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "bun": "./src/index.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json"
22
+ },
23
+ "dependencies": {
24
+ "@tyndall/core": "workspace:*",
25
+ "playwright": "^1.44.0",
26
+ "yaml": "^2.4.5"
27
+ }
28
+ }