@taqwright/taqwright 0.0.24

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 (132) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +108 -0
  3. package/dist/auto-appium.d.ts +12 -0
  4. package/dist/auto-appium.js +77 -0
  5. package/dist/bin/branding.d.ts +6 -0
  6. package/dist/bin/branding.js +22 -0
  7. package/dist/bin/index.d.ts +2 -0
  8. package/dist/bin/index.js +321 -0
  9. package/dist/bin/init.d.ts +26 -0
  10. package/dist/bin/init.js +902 -0
  11. package/dist/bin/inspect.d.ts +9 -0
  12. package/dist/bin/inspect.js +91 -0
  13. package/dist/bin/report-branding.d.ts +2 -0
  14. package/dist/bin/report-branding.js +42 -0
  15. package/dist/branding-assets.d.ts +1 -0
  16. package/dist/branding-assets.js +1 -0
  17. package/dist/capabilities-helpers.d.ts +7 -0
  18. package/dist/capabilities-helpers.js +14 -0
  19. package/dist/capabilities.d.ts +6 -0
  20. package/dist/capabilities.js +86 -0
  21. package/dist/config.d.ts +17 -0
  22. package/dist/config.js +235 -0
  23. package/dist/discovery-setup.d.ts +1 -0
  24. package/dist/discovery-setup.js +61 -0
  25. package/dist/discovery.d.ts +17 -0
  26. package/dist/discovery.js +55 -0
  27. package/dist/docs/configuration.html +376 -0
  28. package/dist/docs/custom-reporters.html +265 -0
  29. package/dist/docs/docker.html +339 -0
  30. package/dist/docs/docs.js +173 -0
  31. package/dist/docs/generating-tests.html +161 -0
  32. package/dist/docs/images/taqwright-html-report.png +0 -0
  33. package/dist/docs/index.html +13 -0
  34. package/dist/docs/installation.html +686 -0
  35. package/dist/docs/parallel.html +271 -0
  36. package/dist/docs/running-tests.html +385 -0
  37. package/dist/docs/styles.css +460 -0
  38. package/dist/docs/writing-tests.html +565 -0
  39. package/dist/doctor.d.ts +33 -0
  40. package/dist/doctor.js +508 -0
  41. package/dist/expect.d.ts +38 -0
  42. package/dist/expect.js +96 -0
  43. package/dist/fixture/artifact-mode.d.ts +2 -0
  44. package/dist/fixture/artifact-mode.js +7 -0
  45. package/dist/fixture/index.d.ts +15 -0
  46. package/dist/fixture/index.js +324 -0
  47. package/dist/images/taqwright-html-report.png +0 -0
  48. package/dist/images/taqwright_favicon.png +0 -0
  49. package/dist/images/taqwright_logo.png +0 -0
  50. package/dist/index.d.ts +9 -0
  51. package/dist/index.js +7 -0
  52. package/dist/inspector/codegen-appium.d.ts +3 -0
  53. package/dist/inspector/codegen-appium.js +228 -0
  54. package/dist/inspector/devices.d.ts +41 -0
  55. package/dist/inspector/devices.js +422 -0
  56. package/dist/inspector/locator-suggester.d.ts +23 -0
  57. package/dist/inspector/locator-suggester.js +539 -0
  58. package/dist/inspector/recorder.d.ts +128 -0
  59. package/dist/inspector/recorder.js +162 -0
  60. package/dist/inspector/server.d.ts +39 -0
  61. package/dist/inspector/server.js +1210 -0
  62. package/dist/inspector/session.d.ts +84 -0
  63. package/dist/inspector/session.js +262 -0
  64. package/dist/inspector/ui.d.ts +1 -0
  65. package/dist/inspector/ui.js +5508 -0
  66. package/dist/keys.d.ts +3 -0
  67. package/dist/keys.js +28 -0
  68. package/dist/locator/index.d.ts +206 -0
  69. package/dist/locator/index.js +1506 -0
  70. package/dist/logger.d.ts +5 -0
  71. package/dist/logger.js +5 -0
  72. package/dist/mobile/index.d.ts +130 -0
  73. package/dist/mobile/index.js +762 -0
  74. package/dist/network/android.d.ts +5 -0
  75. package/dist/network/android.js +87 -0
  76. package/dist/network/ca.d.ts +10 -0
  77. package/dist/network/ca.js +136 -0
  78. package/dist/network/har.d.ts +90 -0
  79. package/dist/network/har.js +101 -0
  80. package/dist/network/host-proxy.d.ts +16 -0
  81. package/dist/network/host-proxy.js +134 -0
  82. package/dist/network/index.d.ts +26 -0
  83. package/dist/network/index.js +105 -0
  84. package/dist/network/ios-sim.d.ts +3 -0
  85. package/dist/network/ios-sim.js +29 -0
  86. package/dist/network/proxy.d.ts +13 -0
  87. package/dist/network/proxy.js +310 -0
  88. package/dist/providers/appium.d.ts +23 -0
  89. package/dist/providers/appium.js +288 -0
  90. package/dist/providers/browserstack/index.d.ts +5 -0
  91. package/dist/providers/browserstack/index.js +77 -0
  92. package/dist/providers/browserstack/utils.d.ts +1 -0
  93. package/dist/providers/browserstack/utils.js +6 -0
  94. package/dist/providers/cloud.d.ts +53 -0
  95. package/dist/providers/cloud.js +117 -0
  96. package/dist/providers/emulator/index.d.ts +8 -0
  97. package/dist/providers/emulator/index.js +47 -0
  98. package/dist/providers/index.d.ts +10 -0
  99. package/dist/providers/index.js +33 -0
  100. package/dist/providers/lambdatest/index.d.ts +28 -0
  101. package/dist/providers/lambdatest/index.js +99 -0
  102. package/dist/providers/lambdatest/utils.d.ts +1 -0
  103. package/dist/providers/lambdatest/utils.js +6 -0
  104. package/dist/providers/local/index.d.ts +9 -0
  105. package/dist/providers/local/index.js +53 -0
  106. package/dist/providers/local-session.d.ts +16 -0
  107. package/dist/providers/local-session.js +55 -0
  108. package/dist/setup/archive.d.ts +2 -0
  109. package/dist/setup/archive.js +43 -0
  110. package/dist/setup/avd.d.ts +12 -0
  111. package/dist/setup/avd.js +103 -0
  112. package/dist/setup/index.d.ts +6 -0
  113. package/dist/setup/index.js +55 -0
  114. package/dist/setup/install-android.d.ts +2 -0
  115. package/dist/setup/install-android.js +70 -0
  116. package/dist/setup/install-appium.d.ts +1 -0
  117. package/dist/setup/install-appium.js +64 -0
  118. package/dist/setup/install-jdk.d.ts +1 -0
  119. package/dist/setup/install-jdk.js +58 -0
  120. package/dist/setup/paths.d.ts +16 -0
  121. package/dist/setup/paths.js +88 -0
  122. package/dist/setup/spawn-tool.d.ts +3 -0
  123. package/dist/setup/spawn-tool.js +11 -0
  124. package/dist/tracer/index.d.ts +34 -0
  125. package/dist/tracer/index.js +687 -0
  126. package/dist/tracer/proxy.d.ts +3 -0
  127. package/dist/tracer/proxy.js +60 -0
  128. package/dist/types/index.d.ts +189 -0
  129. package/dist/types/index.js +6 -0
  130. package/dist/utils.d.ts +2 -0
  131. package/dist/utils.js +37 -0
  132. package/package.json +79 -0
@@ -0,0 +1,321 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'node:child_process';
3
+ import { createRequire } from 'node:module';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { Command } from 'commander';
6
+ import { findConfigFile, loadTaqwrightConfig, resolveCliWorkers } from '../config.js';
7
+ import { maybeAutoStartAppium } from '../auto-appium.js';
8
+ import { runDoctorChecks } from '../doctor.js';
9
+ import { listDevices } from '../inspector/devices.js';
10
+ import { runSetup } from '../setup/index.js';
11
+ import { applyManagedEnv } from '../setup/paths.js';
12
+ import { BrandingBuffer } from './branding.js';
13
+ import { brandReportDir } from './report-branding.js';
14
+ const _require = createRequire(import.meta.url);
15
+ function getVersion() {
16
+ try {
17
+ const pkg = _require('../../package.json');
18
+ return pkg.version;
19
+ }
20
+ catch {
21
+ return '0.0.0';
22
+ }
23
+ }
24
+ function locatePlaywrightCli() {
25
+ for (const pkgName of ['@playwright/test', 'playwright']) {
26
+ try {
27
+ const pkgPath = _require.resolve(`${pkgName}/package.json`);
28
+ const pkg = _require(pkgPath);
29
+ const binRel = typeof pkg.bin === 'string'
30
+ ? pkg.bin
31
+ : (pkg.bin?.playwright ?? pkg.bin?.['@playwright/test']);
32
+ if (!binRel)
33
+ continue;
34
+ return join(dirname(pkgPath), binRel);
35
+ }
36
+ catch {
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ async function runPlaywright(args) {
42
+ const cliPath = locatePlaywrightCli();
43
+ if (!cliPath) {
44
+ console.error('error: could not locate Playwright CLI in node_modules');
45
+ return 1;
46
+ }
47
+ const env = { ...process.env };
48
+ if (process.stdout.isTTY && env.FORCE_COLOR === undefined) {
49
+ env.FORCE_COLOR = '1';
50
+ }
51
+ return new Promise((resolve) => {
52
+ const child = spawn(process.execPath, [cliPath, ...args], {
53
+ stdio: ['inherit', 'pipe', 'pipe'],
54
+ env,
55
+ });
56
+ const branding = new BrandingBuffer();
57
+ child.stdout?.setEncoding('utf8');
58
+ child.stdout?.on('data', (chunk) => {
59
+ const out = branding.push(chunk);
60
+ if (out)
61
+ process.stdout.write(out);
62
+ });
63
+ child.stderr?.on('data', (chunk) => process.stderr.write(chunk));
64
+ child.on('close', (code, signal) => {
65
+ const tail = branding.flush();
66
+ if (tail)
67
+ process.stdout.write(tail);
68
+ if (signal)
69
+ resolve(128);
70
+ else
71
+ resolve(code ?? 0);
72
+ });
73
+ });
74
+ }
75
+ const program = new Command();
76
+ program.name('taqwright').version(getVersion());
77
+ applyManagedEnv();
78
+ program
79
+ .command('test [test-filter...]')
80
+ .description('run tests')
81
+ .option('-c, --config <file>', 'configuration file (default: taqwright.config.{ts,mts,js,mjs})')
82
+ .option('--reporter <reporter>', 'reporter to use (e.g. list, html, json, junit)')
83
+ .option('--grep <grep>', 'only run tests matching this regex')
84
+ .option('--grep-invert <grep>', 'only run tests NOT matching this regex')
85
+ .option('--project <name...>', 'only run tests from specified projects')
86
+ .option('--retries <n>', 'maximum retry count for flaky tests')
87
+ .option('--timeout <ms>', 'test timeout in milliseconds')
88
+ .option('--shard <x/n>', 'shard to run, e.g. 1/3')
89
+ .option('--workers <n>', "number of parallel workers (default: the run's project workers)")
90
+ .option('--list', 'list all tests without running them')
91
+ .option('--pass-with-no-tests', 'exit with code 0 when no tests found')
92
+ .allowUnknownOption(true)
93
+ .action(async (filters, opts) => {
94
+ const configPath = opts.config ?? (await findConfigFile());
95
+ if (!configPath) {
96
+ console.error('error: no taqwright config found. Create taqwright.config.ts or pass --config <file>.');
97
+ process.exit(1);
98
+ }
99
+ const args = ['test', '--config', configPath, ...filters];
100
+ for (const flag of [
101
+ 'reporter',
102
+ 'grep',
103
+ 'grepInvert',
104
+ 'project',
105
+ 'retries',
106
+ 'timeout',
107
+ 'shard',
108
+ ]) {
109
+ const v = opts[flag];
110
+ if (v === undefined)
111
+ continue;
112
+ const cliFlag = flag === 'grepInvert' ? '--grep-invert' : `--${flag}`;
113
+ if (Array.isArray(v)) {
114
+ for (const item of v)
115
+ args.push(cliFlag, String(item));
116
+ }
117
+ else {
118
+ args.push(cliFlag, String(v));
119
+ }
120
+ }
121
+ if (opts.list)
122
+ args.push('--list');
123
+ if (opts.passWithNoTests)
124
+ args.push('--pass-with-no-tests');
125
+ const projectFilter = Array.isArray(opts.project) ? opts.project : [];
126
+ const cfg = await loadTaqwrightConfig(dirname(configPath));
127
+ const workers = cfg
128
+ ? resolveCliWorkers(cfg, projectFilter, opts.workers)
129
+ : opts.workers !== undefined
130
+ ? Number.parseInt(String(opts.workers), 10)
131
+ : undefined;
132
+ if (workers !== undefined && Number.isFinite(workers)) {
133
+ args.push('--workers', String(workers));
134
+ }
135
+ const appiumProcs = await maybeAutoStartAppium(configPath, projectFilter);
136
+ const code = await runPlaywright(args);
137
+ for (const proc of appiumProcs) {
138
+ if (!proc.killed)
139
+ proc.kill();
140
+ }
141
+ try {
142
+ brandReportDir(resolve(process.cwd(), 'playwright-report'));
143
+ }
144
+ catch {
145
+ }
146
+ process.exit(code);
147
+ });
148
+ program
149
+ .command('init [dir]')
150
+ .description('scaffold a new taqwright project (interactive)')
151
+ .option('--test-dir <name>', 'test folder name (default: tests)')
152
+ .option('--platform <p>', 'android | ios | both (default: android)')
153
+ .option('--install', 'run npm install after scaffolding')
154
+ .option('--no-install', 'skip running npm install after scaffolding')
155
+ .option('-y, --yes', 'overwrite an existing non-empty directory without prompting')
156
+ .option('--install-toolchain', 'auto-install the Android toolchain after scaffolding (skips the prompt)')
157
+ .option('--no-install-toolchain', 'skip the Android-toolchain prompt entirely')
158
+ .option('--with-avd', 'also create an Android emulator (system image + AVD) when installing the toolchain')
159
+ .option('--no-with-avd', 'skip the emulator prompt')
160
+ .option('--demo-app', 'download the demo APK so the example test runs out of the box')
161
+ .option('--no-demo-app', 'skip the demo-app prompt entirely')
162
+ .action(async (dir, opts) => {
163
+ const platform = opts.platform?.toLowerCase();
164
+ if (platform && !['android', 'ios', 'both'].includes(platform)) {
165
+ console.error(`error: --platform must be android, ios, or both (got "${opts.platform}")`);
166
+ process.exit(1);
167
+ }
168
+ const { runInit } = await import('./init.js');
169
+ await runInit(dir, {
170
+ testDir: opts.testDir,
171
+ platform: platform,
172
+ install: opts.install,
173
+ yes: opts.yes,
174
+ installToolchain: opts.installToolchain,
175
+ withAvd: opts.withAvd,
176
+ demoApp: opts.demoApp,
177
+ });
178
+ });
179
+ program
180
+ .command('inspect')
181
+ .description('open the taqwright inspector (web UI) against a device')
182
+ .option('-c, --config <file>', 'configuration file (default: taqwright.config.{ts,mts,js,mjs})')
183
+ .option('--project <name>', 'project to inspect (default: first project in config)')
184
+ .option('--port <n>', 'preferred local port for the inspector UI', '4280')
185
+ .option('--host <host>', 'host to bind the inspector UI', 'localhost')
186
+ .option('--no-open', 'do not automatically open the browser')
187
+ .option('--record', 'auto-start recording the moment Connect succeeds')
188
+ .action(async (opts) => {
189
+ const { runInspect } = await import('./inspect.js');
190
+ await runInspect(opts);
191
+ });
192
+ program
193
+ .command('codegen')
194
+ .description('open the inspector and auto-start recording on Connect (alias of `inspect --record`)')
195
+ .option('-c, --config <file>', 'configuration file (default: taqwright.config.{ts,mts,js,mjs})')
196
+ .option('--project <name>', 'project to record against (default: first project in config)')
197
+ .option('--port <n>', 'preferred local port for the inspector UI', '4280')
198
+ .option('--host <host>', 'host to bind the inspector UI', 'localhost')
199
+ .option('--no-open', 'do not automatically open the browser')
200
+ .action(async (opts) => {
201
+ const { runInspect } = await import('./inspect.js');
202
+ await runInspect({ ...opts, record: true });
203
+ });
204
+ program
205
+ .command('devices')
206
+ .description('list connected devices, simulators, and emulators')
207
+ .action(async () => {
208
+ const { android, ios, toolsMissing } = await listDevices();
209
+ const stateRank = (s) => (s === 'booted' ? 0 : s === 'booting' ? 1 : 2);
210
+ const bySort = (a, b) => stateRank(a.state) - stateRank(b.state) || a.name.localeCompare(b.name);
211
+ const fmt = (d, osLabel) => {
212
+ const os = d.osVersion ? `, ${osLabel} ${d.osVersion}` : '';
213
+ return ` ${d.name} ${d.udid} (${d.state}${os})`;
214
+ };
215
+ console.log('Android (adb + emulator):');
216
+ if (toolsMissing.adb && toolsMissing.emulator) {
217
+ console.log(' (adb and emulator not on PATH — install Android SDK)');
218
+ }
219
+ else if (android.length === 0) {
220
+ console.log(' (no Android emulators or devices found)');
221
+ }
222
+ else {
223
+ [...android].sort(bySort).forEach((d) => console.log(fmt(d, 'Android')));
224
+ if (toolsMissing.emulator) {
225
+ console.log(' (emulator not on PATH — shutdown AVDs not listed)');
226
+ }
227
+ }
228
+ if (process.platform === 'darwin') {
229
+ console.log('\niOS Simulators (xcrun simctl):');
230
+ if (toolsMissing.xcrun) {
231
+ console.log(' (xcrun not on PATH — install Xcode command-line tools)');
232
+ }
233
+ else if (ios.length === 0) {
234
+ console.log(' (no iOS simulators found)');
235
+ }
236
+ else {
237
+ [...ios].sort(bySort).forEach((d) => console.log(fmt(d, 'iOS')));
238
+ }
239
+ }
240
+ const noTooling = !!toolsMissing.adb &&
241
+ !!toolsMissing.emulator &&
242
+ (process.platform !== 'darwin' || !!toolsMissing.xcrun);
243
+ if (noTooling) {
244
+ console.error('error: neither `adb`/`emulator` nor `xcrun` is on PATH. ' +
245
+ 'Install Android SDK and/or Xcode and try again.');
246
+ process.exit(1);
247
+ }
248
+ });
249
+ program
250
+ .command('doctor')
251
+ .description('check your environment for mobile-development readiness')
252
+ .option('--json', 'output as JSON')
253
+ .action(async (opts) => {
254
+ const checks = await runDoctorChecks();
255
+ if (opts.json) {
256
+ console.log(JSON.stringify({ version: getVersion(), checks }, null, 2));
257
+ }
258
+ else {
259
+ const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
260
+ const paint = (code, s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : s);
261
+ const green = (s) => paint('32', s);
262
+ const yellow = (s) => paint('33', s);
263
+ const red = (s) => paint('31', s);
264
+ console.log(`taqwright doctor (v${getVersion()})`);
265
+ for (const c of checks) {
266
+ const mark = c.status === 'ok' ? green('[ok]') : c.status === 'warn' ? yellow('[--]') : red('[!!]');
267
+ console.log(` ${mark} ${c.name}${c.detail ? ' — ' + c.detail : ''}`);
268
+ }
269
+ }
270
+ if (checks.some((c) => c.status === 'error'))
271
+ process.exit(1);
272
+ });
273
+ program
274
+ .command('install')
275
+ .description('auto-install the Android toolchain (JDK + SDK + Appium) — zero-touch')
276
+ .option('--force', 'reinstall even if already provisioned')
277
+ .option('--with-avd', 'also create a system image + Android emulator (~1 GB)')
278
+ .option('--print-env', 'also print export lines for using the toolchain from your shell')
279
+ .action(async (opts) => {
280
+ try {
281
+ await runSetup({ force: opts.force, withAvd: opts.withAvd, printEnv: opts.printEnv });
282
+ }
283
+ catch (err) {
284
+ console.error(`\ntaqwright install failed: ${err.message}`);
285
+ process.exit(1);
286
+ }
287
+ });
288
+ program
289
+ .command('merge-reports <directory>')
290
+ .description('merge blob reports into a unified report')
291
+ .option('--reporter <reporter>', 'reporter to use (e.g. html, list, json, junit)')
292
+ .option('-c, --config <file>', 'configuration file')
293
+ .action(async (directory, opts) => {
294
+ const args = ['merge-reports', directory];
295
+ if (opts.reporter)
296
+ args.push('--reporter', opts.reporter);
297
+ if (opts.config)
298
+ args.push('--config', opts.config);
299
+ process.exit(await runPlaywright(args));
300
+ });
301
+ program
302
+ .command('show-report [report]')
303
+ .description('show HTML report')
304
+ .option('--host <host>', 'host to serve report on', 'localhost')
305
+ .option('--port <port>', 'port to serve report on', '9323')
306
+ .action(async (report, opts) => {
307
+ const args = ['show-report'];
308
+ if (report)
309
+ args.push(report);
310
+ args.push('--host', opts.host, '--port', opts.port);
311
+ try {
312
+ brandReportDir(resolve(process.cwd(), report ?? 'playwright-report'));
313
+ }
314
+ catch {
315
+ }
316
+ process.exit(await runPlaywright(args));
317
+ });
318
+ program.parseAsync(process.argv).catch((err) => {
319
+ console.error(err.message);
320
+ process.exit(1);
321
+ });
@@ -0,0 +1,26 @@
1
+ type Platform = 'android' | 'ios';
2
+ export interface InitOptions {
3
+ testDir?: string;
4
+ platform?: 'android' | 'ios' | 'both';
5
+ install?: boolean;
6
+ yes?: boolean;
7
+ installToolchain?: boolean;
8
+ withAvd?: boolean;
9
+ demoApp?: boolean;
10
+ }
11
+ export declare function runInit(argDir: string | undefined, opts?: InitOptions): Promise<void>;
12
+ export declare function isReservedDirName(name: string): boolean;
13
+ export declare function platformChoices(isMac: boolean): string[];
14
+ export declare function platformSupportError(isMac: boolean, platforms: Platform[]): string | null;
15
+ export declare function isValidTestDir(name: string): boolean;
16
+ export declare function projectTargetError(exists: boolean, isDirectory: boolean): string | null;
17
+ export declare function toPackageName(raw: string): string;
18
+ export interface ConfigTemplateOpts {
19
+ demoApp: boolean;
20
+ demoAvd: boolean;
21
+ scoped: boolean;
22
+ deviceName?: string;
23
+ }
24
+ export declare function configTemplate(platforms: Platform[], testDir: string, opts: ConfigTemplateOpts): string;
25
+ export declare function exampleTestTemplate(demoApp: boolean): string;
26
+ export {};