@nouhouari/conductor-e2e 0.0.0-stage → 0.1.8

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 (101) hide show
  1. package/CHANGELOG.md +228 -0
  2. package/LICENSE +21 -0
  3. package/README.md +138 -2
  4. package/config/environments/default.ts +41 -0
  5. package/config/environments/dev.ts +16 -0
  6. package/config/environments/staging.ts +15 -0
  7. package/config/index.ts +70 -0
  8. package/config/types.ts +94 -0
  9. package/dist/config/environments/default.d.ts +3 -0
  10. package/dist/config/environments/default.d.ts.map +1 -0
  11. package/dist/config/environments/default.js +40 -0
  12. package/dist/config/environments/default.js.map +1 -0
  13. package/dist/config/environments/dev.d.ts +3 -0
  14. package/dist/config/environments/dev.d.ts.map +1 -0
  15. package/dist/config/environments/dev.js +18 -0
  16. package/dist/config/environments/dev.js.map +1 -0
  17. package/dist/config/environments/staging.d.ts +3 -0
  18. package/dist/config/environments/staging.d.ts.map +1 -0
  19. package/dist/config/environments/staging.js +17 -0
  20. package/dist/config/environments/staging.js.map +1 -0
  21. package/dist/config/index.d.ts +7 -0
  22. package/dist/config/index.d.ts.map +1 -0
  23. package/dist/config/index.js +81 -0
  24. package/dist/config/index.js.map +1 -0
  25. package/dist/config/types.d.ts +93 -0
  26. package/dist/config/types.d.ts.map +1 -0
  27. package/dist/config/types.js +3 -0
  28. package/dist/config/types.js.map +1 -0
  29. package/dist/src/drivers/ApiDriver.d.ts +16 -0
  30. package/dist/src/drivers/ApiDriver.d.ts.map +1 -0
  31. package/dist/src/drivers/ApiDriver.js +48 -0
  32. package/dist/src/drivers/ApiDriver.js.map +1 -0
  33. package/dist/src/drivers/DatabaseDriver.d.ts +12 -0
  34. package/dist/src/drivers/DatabaseDriver.d.ts.map +1 -0
  35. package/dist/src/drivers/DatabaseDriver.js +15 -0
  36. package/dist/src/drivers/DatabaseDriver.js.map +1 -0
  37. package/dist/src/drivers/FlutterDesktopDriver.d.ts +139 -0
  38. package/dist/src/drivers/FlutterDesktopDriver.d.ts.map +1 -0
  39. package/dist/src/drivers/FlutterDesktopDriver.js +445 -0
  40. package/dist/src/drivers/FlutterDesktopDriver.js.map +1 -0
  41. package/dist/src/drivers/MaestroDriver.d.ts +19 -0
  42. package/dist/src/drivers/MaestroDriver.d.ts.map +1 -0
  43. package/dist/src/drivers/MaestroDriver.js +144 -0
  44. package/dist/src/drivers/MaestroDriver.js.map +1 -0
  45. package/dist/src/drivers/WebDriver.d.ts +21 -0
  46. package/dist/src/drivers/WebDriver.d.ts.map +1 -0
  47. package/dist/src/drivers/WebDriver.js +57 -0
  48. package/dist/src/drivers/WebDriver.js.map +1 -0
  49. package/dist/src/hooks/browser.hooks.d.ts +2 -0
  50. package/dist/src/hooks/browser.hooks.d.ts.map +1 -0
  51. package/dist/src/hooks/browser.hooks.js +15 -0
  52. package/dist/src/hooks/browser.hooks.js.map +1 -0
  53. package/dist/src/hooks/database.hooks.d.ts +2 -0
  54. package/dist/src/hooks/database.hooks.d.ts.map +1 -0
  55. package/dist/src/hooks/database.hooks.js +11 -0
  56. package/dist/src/hooks/database.hooks.js.map +1 -0
  57. package/dist/src/hooks/desktop.hooks.d.ts +2 -0
  58. package/dist/src/hooks/desktop.hooks.d.ts.map +1 -0
  59. package/dist/src/hooks/desktop.hooks.js +15 -0
  60. package/dist/src/hooks/desktop.hooks.js.map +1 -0
  61. package/dist/src/hooks/flutterDesktop.hooks.d.ts +2 -0
  62. package/dist/src/hooks/flutterDesktop.hooks.d.ts.map +1 -0
  63. package/dist/src/hooks/flutterDesktop.hooks.js +26 -0
  64. package/dist/src/hooks/flutterDesktop.hooks.js.map +1 -0
  65. package/dist/src/hooks/index.d.ts +6 -0
  66. package/dist/src/hooks/index.d.ts.map +1 -0
  67. package/dist/src/hooks/index.js +25 -0
  68. package/dist/src/hooks/index.js.map +1 -0
  69. package/dist/src/hooks/maestro.hooks.d.ts +2 -0
  70. package/dist/src/hooks/maestro.hooks.d.ts.map +1 -0
  71. package/dist/src/hooks/maestro.hooks.js +8 -0
  72. package/dist/src/hooks/maestro.hooks.js.map +1 -0
  73. package/dist/src/index.d.ts +21 -0
  74. package/dist/src/index.d.ts.map +1 -0
  75. package/dist/src/index.js +30 -0
  76. package/dist/src/index.js.map +1 -0
  77. package/dist/src/pages/BasePage.d.ts +11 -0
  78. package/dist/src/pages/BasePage.d.ts.map +1 -0
  79. package/dist/src/pages/BasePage.js +22 -0
  80. package/dist/src/pages/BasePage.js.map +1 -0
  81. package/dist/src/scenarios/RemoteScenarioFetcher.d.ts +51 -0
  82. package/dist/src/scenarios/RemoteScenarioFetcher.d.ts.map +1 -0
  83. package/dist/src/scenarios/RemoteScenarioFetcher.js +162 -0
  84. package/dist/src/scenarios/RemoteScenarioFetcher.js.map +1 -0
  85. package/dist/src/scenarios/cli.d.ts +3 -0
  86. package/dist/src/scenarios/cli.d.ts.map +1 -0
  87. package/dist/src/scenarios/cli.js +26 -0
  88. package/dist/src/scenarios/cli.js.map +1 -0
  89. package/dist/src/support/logger.d.ts +3 -0
  90. package/dist/src/support/logger.d.ts.map +1 -0
  91. package/dist/src/support/logger.js +16 -0
  92. package/dist/src/support/logger.js.map +1 -0
  93. package/dist/src/support/retry.d.ts +7 -0
  94. package/dist/src/support/retry.d.ts.map +1 -0
  95. package/dist/src/support/retry.js +21 -0
  96. package/dist/src/support/retry.js.map +1 -0
  97. package/dist/src/world/ConductorWorld.d.ts +39 -0
  98. package/dist/src/world/ConductorWorld.d.ts.map +1 -0
  99. package/dist/src/world/ConductorWorld.js +112 -0
  100. package/dist/src/world/ConductorWorld.js.map +1 -0
  101. package/package.json +81 -4
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultConfig = void 0;
4
+ exports.defaultConfig = {
5
+ name: 'default',
6
+ web: {
7
+ baseUrl: 'http://localhost:3000',
8
+ headless: true,
9
+ browserName: 'chromium'
10
+ },
11
+ api: {
12
+ baseUrl: 'http://localhost:3000',
13
+ defaultCredentials: { username: 'test@example.com', password: 'password' },
14
+ timeoutMs: 30000
15
+ },
16
+ mobile: {
17
+ flowsDir: 'flows/mobile',
18
+ timeoutMs: 120000
19
+ },
20
+ database: {
21
+ enabled: false
22
+ },
23
+ desktop: {
24
+ agentJar: require('path').resolve(__dirname, '../../apps/desktop/agent/fxagent.jar'),
25
+ defaultTimeoutMs: 10000,
26
+ screenshotDir: 'reports/screenshots'
27
+ },
28
+ flutterDesktop: {
29
+ appPath: require('path').resolve(__dirname, '../../apps/mobile/build/macos/Build/Products/Profile/todoapp.app/Contents/MacOS/todoapp'),
30
+ defaultTimeoutMs: 10000,
31
+ launchTimeoutMs: 30000,
32
+ screenshotDir: 'reports/screenshots'
33
+ },
34
+ remoteScenarios: {
35
+ baseUrl: 'http://localhost:8788/api',
36
+ outputDir: '.remote-features',
37
+ filters: {}
38
+ }
39
+ };
40
+ //# sourceMappingURL=default.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default.js","sourceRoot":"","sources":["../../../config/environments/default.ts"],"names":[],"mappings":";;;AAEa,QAAA,aAAa,GAAsB;IAC9C,IAAI,EAAE,SAAS;IACf,GAAG,EAAE;QACH,OAAO,EAAE,uBAAuB;QAChC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,UAAU;KACxB;IACD,GAAG,EAAE;QACH,OAAO,EAAE,uBAAuB;QAChC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,EAAE,UAAU,EAAE;QAC1E,SAAS,EAAE,KAAK;KACjB;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,cAAc;QACxB,SAAS,EAAE,MAAM;KAClB;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,KAAK;KACf;IACD,OAAO,EAAE;QACP,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,sCAAsC,CAAC;QACpF,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,qBAAqB;KACrC;IACD,cAAc,EAAE;QACd,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAC9B,SAAS,EACT,yFAAyF,CAC1F;QACD,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,qBAAqB;KACrC;IACD,eAAe,EAAE;QACf,OAAO,EAAE,2BAA2B;QACpC,SAAS,EAAE,kBAAkB;QAC7B,OAAO,EAAE,EAAE;KACZ;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { EnvironmentConfig } from '../types';
2
+ export declare const devConfig: Partial<EnvironmentConfig>;
3
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../config/environments/dev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAahD,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.devConfig = void 0;
4
+ exports.devConfig = {
5
+ name: 'dev',
6
+ web: {
7
+ baseUrl: 'http://localhost:3000',
8
+ headless: false,
9
+ browserName: 'chromium',
10
+ slowMo: 100
11
+ },
12
+ api: {
13
+ baseUrl: 'http://localhost:3000/api',
14
+ defaultCredentials: { username: 'dev@example.com', password: 'devpassword' },
15
+ timeoutMs: 60000
16
+ }
17
+ };
18
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../config/environments/dev.ts"],"names":[],"mappings":";;;AAEa,QAAA,SAAS,GAA+B;IACnD,IAAI,EAAE,KAAK;IACX,GAAG,EAAE;QACH,OAAO,EAAE,uBAAuB;QAChC,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,UAAU;QACvB,MAAM,EAAE,GAAG;KACZ;IACD,GAAG,EAAE;QACH,OAAO,EAAE,2BAA2B;QACpC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE;QAC5E,SAAS,EAAE,KAAK;KACjB;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { EnvironmentConfig } from '../types';
2
+ export declare const stagingConfig: Partial<EnvironmentConfig>;
3
+ //# sourceMappingURL=staging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../../../config/environments/staging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,iBAAiB,CAYpD,CAAC"}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stagingConfig = void 0;
4
+ exports.stagingConfig = {
5
+ name: 'staging',
6
+ web: {
7
+ baseUrl: 'https://staging.example.com',
8
+ headless: true,
9
+ browserName: 'chromium'
10
+ },
11
+ api: {
12
+ baseUrl: 'https://staging.example.com/api',
13
+ defaultCredentials: { username: 'staging@example.com', password: 'stagingpassword' },
14
+ timeoutMs: 45000
15
+ }
16
+ };
17
+ //# sourceMappingURL=staging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging.js","sourceRoot":"","sources":["../../../config/environments/staging.ts"],"names":[],"mappings":";;;AAEa,QAAA,aAAa,GAA+B;IACvD,IAAI,EAAE,SAAS;IACf,GAAG,EAAE;QACH,OAAO,EAAE,6BAA6B;QACtC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,UAAU;KACxB;IACD,GAAG,EAAE;QACH,OAAO,EAAE,iCAAiC;QAC1C,kBAAkB,EAAE,EAAE,QAAQ,EAAE,qBAAqB,EAAE,QAAQ,EAAE,iBAAiB,EAAE;QACpF,SAAS,EAAE,KAAK;KACjB;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import 'dotenv/config';
2
+ import type { EnvironmentConfig } from './types';
3
+ declare function loadConfig(): EnvironmentConfig;
4
+ export declare const config: EnvironmentConfig;
5
+ export { loadConfig };
6
+ export type { EnvironmentConfig };
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../config/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,iBAAS,UAAU,IAAI,iBAAiB,CA+CvC;AAeD,eAAO,MAAM,MAAM,mBAAe,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,CAAC;AACtB,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.config = void 0;
4
+ exports.loadConfig = loadConfig;
5
+ require("dotenv/config");
6
+ const default_1 = require("./environments/default");
7
+ function loadConfig() {
8
+ const env = process.env.TEST_ENV ?? 'default';
9
+ let base = default_1.defaultConfig;
10
+ if (env !== 'default') {
11
+ try {
12
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
13
+ const envModule = require(`./environments/${env}`);
14
+ const envConfig = envModule[`${env}Config`];
15
+ base = deepMerge(base, envConfig);
16
+ }
17
+ catch {
18
+ // fall back to default
19
+ }
20
+ }
21
+ // env-var overrides
22
+ if (process.env.WEB_BASE_URL)
23
+ base.web.baseUrl = process.env.WEB_BASE_URL;
24
+ if (process.env.API_BASE_URL)
25
+ base.api.baseUrl = process.env.API_BASE_URL;
26
+ if (process.env.HEADLESS)
27
+ base.web.headless = process.env.HEADLESS !== 'false';
28
+ if (process.env.BROWSER)
29
+ base.web.browserName = process.env.BROWSER;
30
+ if (process.env.MAESTRO_DEVICE)
31
+ base.mobile.deviceId = process.env.MAESTRO_DEVICE;
32
+ if (process.env.FLUTTER_DESKTOP_APP_PATH && base.flutterDesktop) {
33
+ base.flutterDesktop.appPath = process.env.FLUTTER_DESKTOP_APP_PATH;
34
+ }
35
+ if (process.env.FLUTTER_DESKTOP_VM_PORT && base.flutterDesktop) {
36
+ base.flutterDesktop.vmServicePort = Number(process.env.FLUTTER_DESKTOP_VM_PORT);
37
+ }
38
+ if (base.remoteScenarios) {
39
+ const rs = base.remoteScenarios;
40
+ if (process.env.REMOTE_SCENARIOS_URL)
41
+ rs.baseUrl = process.env.REMOTE_SCENARIOS_URL;
42
+ if (process.env.REMOTE_SCENARIOS_PROJECT)
43
+ rs.project = process.env.REMOTE_SCENARIOS_PROJECT;
44
+ if (process.env.REMOTE_SCENARIOS_OUTPUT_DIR)
45
+ rs.outputDir = process.env.REMOTE_SCENARIOS_OUTPUT_DIR;
46
+ rs.filters = rs.filters ?? {};
47
+ if (process.env.REMOTE_SCENARIOS_STORY)
48
+ rs.filters.story = process.env.REMOTE_SCENARIOS_STORY;
49
+ if (process.env.REMOTE_SCENARIOS_REQUIREMENT)
50
+ rs.filters.requirement = process.env.REMOTE_SCENARIOS_REQUIREMENT;
51
+ if (process.env.REMOTE_SCENARIOS_PHASE)
52
+ rs.filters.phase = process.env.REMOTE_SCENARIOS_PHASE;
53
+ if (process.env.REMOTE_SCENARIOS_MODE) {
54
+ rs.filters.mode = process.env.REMOTE_SCENARIOS_MODE;
55
+ }
56
+ if (process.env.REMOTE_SCENARIOS_TAGS)
57
+ rs.filters.tags = process.env.REMOTE_SCENARIOS_TAGS;
58
+ if (process.env.REMOTE_SCENARIOS_FEATURE)
59
+ rs.filters.feature = process.env.REMOTE_SCENARIOS_FEATURE;
60
+ if (process.env.REMOTE_SCENARIOS_Q)
61
+ rs.filters.q = process.env.REMOTE_SCENARIOS_Q;
62
+ if (process.env.REMOTE_SCENARIOS_VALID)
63
+ rs.filters.valid = process.env.REMOTE_SCENARIOS_VALID === 'true';
64
+ }
65
+ return base;
66
+ }
67
+ function deepMerge(base, override) {
68
+ const result = { ...base };
69
+ for (const key of Object.keys(override ?? {})) {
70
+ const ov = override[key];
71
+ if (ov !== null && typeof ov === 'object' && !Array.isArray(ov)) {
72
+ result[key] = deepMerge(result[key], ov);
73
+ }
74
+ else if (ov !== undefined) {
75
+ result[key] = ov;
76
+ }
77
+ }
78
+ return result;
79
+ }
80
+ exports.config = loadConfig();
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../config/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ export interface WebConfig {
2
+ baseUrl: string;
3
+ headless: boolean;
4
+ browserName: 'chromium' | 'firefox' | 'webkit';
5
+ slowMo?: number;
6
+ viewport?: {
7
+ width: number;
8
+ height: number;
9
+ };
10
+ }
11
+ export interface ApiConfig {
12
+ baseUrl: string;
13
+ defaultCredentials: {
14
+ username: string;
15
+ password: string;
16
+ };
17
+ timeoutMs?: number;
18
+ }
19
+ export interface MobileConfig {
20
+ deviceId?: string;
21
+ flowsDir: string;
22
+ timeoutMs: number;
23
+ maestroBin?: string;
24
+ }
25
+ export interface DatabaseConfig {
26
+ enabled: boolean;
27
+ }
28
+ export interface DesktopConfig {
29
+ agentJar: string;
30
+ javaBin?: string;
31
+ agentPort?: number;
32
+ agentHost?: string;
33
+ defaultTimeoutMs?: number;
34
+ pollIntervalMs?: number;
35
+ screenshotDir?: string;
36
+ jvmArgs?: string[];
37
+ }
38
+ export interface FlutterDesktopConfig {
39
+ /** Absolute path to the built executable (.app bundle on macOS, .exe on Windows). */
40
+ appPath: string;
41
+ /** Per-action timeout, ms. Default 10_000. */
42
+ defaultTimeoutMs?: number;
43
+ /** How long to wait for the VM service URL to appear on stdout. Default 30_000. */
44
+ launchTimeoutMs?: number;
45
+ /** Optional fixed VM service port (passed via --vm-service-port=). Default: ephemeral. */
46
+ vmServicePort?: number;
47
+ /** Extra CLI args appended after the executable. */
48
+ extraArgs?: string[];
49
+ /** Environment variables added to the spawned process. */
50
+ env?: Record<string, string>;
51
+ /** Where failure screenshots are written. Default 'reports/screenshots'. */
52
+ screenshotDir?: string;
53
+ }
54
+ export interface RemoteScenariosFilters {
55
+ /** Story id or comma-separated ids (match any), e.g. "US-007". */
56
+ story?: string;
57
+ /** Requirement id or comma-separated ids; resolved via its stories, e.g. "REQ-001". */
58
+ requirement?: string;
59
+ /** Phase id; restricts to in-scope scenarios, e.g. "P1". */
60
+ phase?: string;
61
+ /** Phase resolution mode. Default 'cumulative'. */
62
+ mode?: 'cumulative' | 'strict';
63
+ /** Cucumber tag expression, e.g. "@smoke and not @wip". */
64
+ tags?: string;
65
+ /** Exact feature name. */
66
+ feature?: string;
67
+ /** Case-insensitive substring over name/feature/content. */
68
+ q?: string;
69
+ /** Filter by gherkin validity. */
70
+ valid?: boolean;
71
+ }
72
+ export interface RemoteScenariosConfig {
73
+ /** Base URL of the requ scenario API, e.g. "http://localhost:8788/api". */
74
+ baseUrl: string;
75
+ /** Project slug (required when the API has >1 project loaded). */
76
+ project?: string;
77
+ /** Server-side filters passed to GET /api/scenarios. */
78
+ filters?: RemoteScenariosFilters;
79
+ /** Directory where reconstructed .feature files are written. Default '.remote-features'. */
80
+ outputDir: string;
81
+ }
82
+ export interface EnvironmentConfig {
83
+ name: string;
84
+ web: WebConfig;
85
+ api: ApiConfig;
86
+ mobile: MobileConfig;
87
+ database: DatabaseConfig;
88
+ desktop?: DesktopConfig;
89
+ flutterDesktop?: FlutterDesktopConfig;
90
+ /** Optional: source cucumber scenarios from the requ scenario API instead of local files. */
91
+ remoteScenarios?: RemoteScenariosConfig;
92
+ }
93
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../config/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../config/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { APIRequestContext, APIResponse, BrowserContext } from 'playwright';
2
+ import type { EnvironmentConfig } from '../../config/types';
3
+ export declare class ApiDriver {
4
+ private config;
5
+ private _client;
6
+ constructor(config: EnvironmentConfig);
7
+ init(context?: BrowserContext): Promise<void>;
8
+ get client(): APIRequestContext;
9
+ get isInitialized(): boolean;
10
+ get(url: string, options?: Record<string, unknown>): Promise<APIResponse>;
11
+ post(url: string, data?: unknown, options?: Record<string, unknown>): Promise<APIResponse>;
12
+ put(url: string, data?: unknown, options?: Record<string, unknown>): Promise<APIResponse>;
13
+ delete(url: string, options?: Record<string, unknown>): Promise<APIResponse>;
14
+ dispose(): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=ApiDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiDriver.d.ts","sourceRoot":"","sources":["../../../src/drivers/ApiDriver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,cAAc,EAAgC,MAAM,YAAY,CAAC;AAC1G,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,qBAAa,SAAS;IAGR,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,OAAO,CAAkC;gBAE7B,MAAM,EAAE,iBAAiB;IAEvC,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnD,IAAI,MAAM,IAAI,iBAAiB,CAG9B;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;IAEK,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAI1F,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAIzF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAI5E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAI/B"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApiDriver = void 0;
4
+ const playwright_1 = require("playwright");
5
+ class ApiDriver {
6
+ config;
7
+ _client = null;
8
+ constructor(config) {
9
+ this.config = config;
10
+ }
11
+ async init(context) {
12
+ if (context) {
13
+ this._client = context.request;
14
+ }
15
+ else {
16
+ this._client = await playwright_1.request.newContext({
17
+ baseURL: this.config.api.baseUrl,
18
+ extraHTTPHeaders: { 'Content-Type': 'application/json' }
19
+ });
20
+ }
21
+ }
22
+ get client() {
23
+ if (!this._client)
24
+ throw new Error('ApiDriver not initialized. Call init() first.');
25
+ return this._client;
26
+ }
27
+ get isInitialized() {
28
+ return this._client !== null;
29
+ }
30
+ async get(url, options) {
31
+ return this.client.get(url, options);
32
+ }
33
+ async post(url, data, options) {
34
+ return this.client.post(url, { data, ...options });
35
+ }
36
+ async put(url, data, options) {
37
+ return this.client.put(url, { data, ...options });
38
+ }
39
+ async delete(url, options) {
40
+ return this.client.delete(url, options);
41
+ }
42
+ async dispose() {
43
+ await this._client?.dispose();
44
+ this._client = null;
45
+ }
46
+ }
47
+ exports.ApiDriver = ApiDriver;
48
+ //# sourceMappingURL=ApiDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiDriver.js","sourceRoot":"","sources":["../../../src/drivers/ApiDriver.ts"],"names":[],"mappings":";;;AAAA,2CAA0G;AAG1G,MAAa,SAAS;IAGA;IAFZ,OAAO,GAA6B,IAAI,CAAC;IAEjD,YAAoB,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;IAAG,CAAC;IAEjD,KAAK,CAAC,IAAI,CAAC,OAAwB;QACjC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,GAAG,MAAM,oBAAiB,CAAC,UAAU,CAAC;gBAChD,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO;gBAChC,gBAAgB,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aACzD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM;QACR,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACpF,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,OAAiC;QACtD,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,IAAc,EAAE,OAAiC;QACvE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,IAAc,EAAE,OAAiC;QACtE,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,OAAiC;QACzD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;CACF;AA7CD,8BA6CC"}
@@ -0,0 +1,12 @@
1
+ export interface QueryResult<T> {
2
+ rows: T[];
3
+ rowCount: number;
4
+ }
5
+ export declare abstract class DatabaseDriver {
6
+ abstract connect(): Promise<void>;
7
+ abstract disconnect(): Promise<void>;
8
+ abstract query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
9
+ queryOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T | null>;
10
+ execute(sql: string, params?: unknown[]): Promise<number>;
11
+ }
12
+ //# sourceMappingURL=DatabaseDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseDriver.d.ts","sourceRoot":"","sources":["../../../src/drivers/DatabaseDriver.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8BAAsB,cAAc;IAClC,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAE/F,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKzF,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAIhE"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseDriver = void 0;
4
+ class DatabaseDriver {
5
+ async queryOne(sql, params) {
6
+ const result = await this.query(sql, params);
7
+ return result.rows[0] ?? null;
8
+ }
9
+ async execute(sql, params) {
10
+ const result = await this.query(sql, params);
11
+ return result.rowCount;
12
+ }
13
+ }
14
+ exports.DatabaseDriver = DatabaseDriver;
15
+ //# sourceMappingURL=DatabaseDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseDriver.js","sourceRoot":"","sources":["../../../src/drivers/DatabaseDriver.ts"],"names":[],"mappings":";;;AAKA,MAAsB,cAAc;IAKlC,KAAK,CAAC,QAAQ,CAA8B,GAAW,EAAE,MAAkB;QACzE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAI,GAAG,EAAE,MAAM,CAAC,CAAC;QAChD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,MAAkB;QAC3C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC;CACF;AAdD,wCAcC"}
@@ -0,0 +1,139 @@
1
+ import type { EnvironmentConfig } from '../../config/types';
2
+ /**
3
+ * FlutterDesktopDriver
4
+ *
5
+ * Drives a Flutter desktop app (built with `lib/main_test.dart` calling
6
+ * `enableFlutterDriverExtension()`) by:
7
+ * 1. Spawning the executable.
8
+ * 2. Reading the Dart VM service URL printed on stdout.
9
+ * 3. Opening a WebSocket to the VM service.
10
+ * 4. Calling the `ext.flutter.driver` service extension via JSON-RPC.
11
+ *
12
+ * No Dart side process is involved — this is a pure TypeScript client.
13
+ */
14
+ export type FinderType = 'ByValueKey' | 'ByText' | 'ByType' | 'ByTooltipMessage';
15
+ export interface Finder {
16
+ type: FinderType;
17
+ value: string;
18
+ }
19
+ export type OffsetType = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'center';
20
+ export interface Offset {
21
+ dx: number;
22
+ dy: number;
23
+ }
24
+ export type WaitCondition = 'NoPendingFrames' | 'NoTransientCallbacks' | 'FirstFrameRasterized';
25
+ export declare class FlutterDesktopDriver {
26
+ private readonly cfg;
27
+ private proc;
28
+ private ws;
29
+ private isolateId;
30
+ private nextRpcId;
31
+ private pending;
32
+ private textEntryEmulationEnabled;
33
+ constructor(env: EnvironmentConfig);
34
+ get isLaunched(): boolean;
35
+ launch(): Promise<void>;
36
+ /**
37
+ * Connect to an already-running Flutter app via its Dart VM service URL.
38
+ * Use instead of `launch()` when the app is already running — e.g.:
39
+ * - **Android**: `adb forward tcp:PORT tcp:PORT`, then connect to `ws://localhost:PORT/TOKEN/ws`
40
+ * - **iOS**: `iproxy PORT PORT DEVICE_UDID`, then connect
41
+ * - **Windows / Linux desktop**: manage the process yourself and pass the URL
42
+ *
43
+ * Accepts either the HTTP form printed by the app (`http://localhost:PORT/TOKEN/`)
44
+ * or the WebSocket form directly (`ws://localhost:PORT/TOKEN/ws`).
45
+ */
46
+ connect(vmServiceUrl: string, timeoutMs?: number): Promise<void>;
47
+ close(): Promise<void>;
48
+ /** Tap a widget identified by `finder`. */
49
+ tap(finder: Finder, timeoutMs?: number): Promise<void>;
50
+ /** Type `text` into the currently focused text field.
51
+ * Emulation must be enabled BEFORE tapping so that `TextInput.setClient`
52
+ * is captured by the mock — otherwise the mock's _client stays null and
53
+ * enter_text is silently ignored. */
54
+ enterText(finder: Finder, text: string, timeoutMs?: number): Promise<void>;
55
+ /**
56
+ * Send a message to the app's `enableFlutterDriverExtension` data handler
57
+ * and return the response string. Use this to invoke app-side actions that
58
+ * cannot be driven through the gesture system (e.g. tapping widgets inside
59
+ * a scrollable that blocks flutter_driver's hitTestable() check).
60
+ */
61
+ requestData(message: string, timeoutMs?: number): Promise<string>;
62
+ /** Read the text of a Text widget at `finder`. */
63
+ getText(finder: Finder, timeoutMs?: number): Promise<string>;
64
+ /** Wait for `finder` to resolve to an existing widget. */
65
+ waitFor(finder: Finder, timeoutMs?: number): Promise<void>;
66
+ /** Wait until `finder` no longer resolves to any widget. */
67
+ waitForAbsent(finder: Finder, timeoutMs?: number): Promise<void>;
68
+ /**
69
+ * Take a screenshot of the Flutter app's render surface via the
70
+ * `ext.flutter.driver` `screenshot` command. Returns a PNG path.
71
+ *
72
+ * This goes over the same WebSocket as the rest of the driver — no OS-level
73
+ * screen-recording permissions are required, and only the app surface is
74
+ * captured (not the whole desktop).
75
+ */
76
+ takeScreenshot(name: string): Promise<string>;
77
+ /** Double-tap a widget identified by `finder`. */
78
+ doubleTap(finder: Finder, timeoutMs?: number): Promise<void>;
79
+ /** Long-press a widget identified by `finder`. */
80
+ longPress(finder: Finder, timeoutMs?: number): Promise<void>;
81
+ /**
82
+ * Scroll a Scrollable widget identified by `finder` by (`dx`, `dy`) pixels
83
+ * over `durationMs` milliseconds at `frequency` Hz.
84
+ */
85
+ scroll(finder: Finder, dx: number, dy: number, durationMs?: number, frequency?: number, timeoutMs?: number): Promise<void>;
86
+ /**
87
+ * Scroll until `finder` is visible.
88
+ * `alignment` controls where the widget lands: 0.0 = top edge, 0.5 = center, 1.0 = bottom edge.
89
+ */
90
+ scrollIntoView(finder: Finder, alignment?: number, timeoutMs?: number): Promise<void>;
91
+ /**
92
+ * Clear the text field at `finder` by enabling text-entry emulation,
93
+ * tapping to focus, then setting its value to an empty string.
94
+ */
95
+ clearText(finder: Finder, timeoutMs?: number): Promise<void>;
96
+ /**
97
+ * Non-throwing visibility probe: returns `true` if `finder` resolves within
98
+ * `timeoutMs` (default 500 ms), `false` otherwise. Use for conditional
99
+ * assertions instead of `waitFor` when absence is acceptable.
100
+ */
101
+ isVisible(finder: Finder, timeoutMs?: number): Promise<boolean>;
102
+ /**
103
+ * Return the screen coordinates of a point on the widget at `finder`.
104
+ * `offsetType` defaults to `'center'`.
105
+ */
106
+ getOffset(finder: Finder, offsetType?: OffsetType, timeoutMs?: number): Promise<Offset>;
107
+ /**
108
+ * Wait until a predefined Flutter condition is satisfied — the app-level
109
+ * equivalent of Playwright's `page.waitForLoadState()`.
110
+ *
111
+ * `'NoPendingFrames'` — no animation frames scheduled (app is idle)
112
+ * `'NoTransientCallbacks'` — no pending transient callbacks
113
+ * `'FirstFrameRasterized'` — first frame has been rendered
114
+ */
115
+ waitForCondition(condition: WaitCondition, timeoutMs?: number): Promise<void>;
116
+ /**
117
+ * Enable or disable Flutter's frame-sync during driver commands. Set to
118
+ * `false` before triggering heavy animations so the driver does not stall
119
+ * waiting for each frame to settle; restore with `setFrameSync(true)` when
120
+ * done. Mirrors disabling CSS transitions in web tests.
121
+ */
122
+ setFrameSync(enabled: boolean, timeoutMs?: number): Promise<void>;
123
+ /**
124
+ * NOTE: `isEnabled` (checking whether a widget is interactive) is not part
125
+ * of the `ext.flutter.driver` protocol. Use `requestData()` with an app-side
126
+ * handler that inspects widget state and returns the result as a string.
127
+ */
128
+ private serializeFinder;
129
+ /** Read stdout/stderr until we see a VM service URL or hit the timeout. */
130
+ private waitForVmServiceUrl;
131
+ private connectWebSocket;
132
+ private onMessage;
133
+ /** Send a JSON-RPC method to the VM service and await the response. */
134
+ private rpc;
135
+ /** Send an `ext.flutter.driver` command on the resolved isolate. */
136
+ private driverCommand;
137
+ private resolveIsolateAndDriverExtension;
138
+ }
139
+ //# sourceMappingURL=FlutterDesktopDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlutterDesktopDriver.d.ts","sourceRoot":"","sources":["../../../src/drivers/FlutterDesktopDriver.ts"],"names":[],"mappings":"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"}