@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,385 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Running &amp; debugging tests · taqwright</title>
7
+ <meta name="description" content="Tracing, screen recording, the output directory, and reporters — debug taqwright runs after the fact and ship results to CI.">
8
+ <link rel="stylesheet" href="styles.css">
9
+ <script>try{var t=localStorage.getItem('tw-theme');if(t==='light'||(!t&&typeof matchMedia==='function'&&matchMedia('(prefers-color-scheme: light)').matches))document.documentElement.setAttribute('data-theme','light');}catch(e){}</script>
10
+ </head>
11
+ <body>
12
+
13
+ <header class="topbar">
14
+ <button class="menu-toggle" id="menu-toggle" aria-label="Toggle navigation">☰</button>
15
+ <a class="brand" href="installation.html"><span class="accent">taq</span>wright</a>
16
+ <nav class="primary">
17
+ <a href="installation.html" class="current">Docs</a>
18
+ <a href="generating-tests.html">Inspector</a>
19
+ <a href="writing-tests.html#actions">API</a>
20
+ </nav>
21
+ <span class="spacer"></span>
22
+ <div class="search" title="Search (placeholder)">
23
+ <span>Search docs…</span>
24
+ <span class="kbd">⌘K</span>
25
+ </div>
26
+ <button class="theme-toggle" id="theme-toggle" aria-label="Switch to light theme" title="Switch to light theme"></button>
27
+ <a class="gh-link" href="https://github.com/taqelah/taqwright" title="GitHub">
28
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 .5a11.5 11.5 0 0 0-3.64 22.42c.58.1.79-.25.79-.55v-2.02c-3.2.7-3.88-1.36-3.88-1.36-.52-1.33-1.28-1.68-1.28-1.68-1.05-.71.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.7 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.47.11-3.06 0 0 .97-.31 3.18 1.18a11 11 0 0 1 5.79 0c2.21-1.49 3.18-1.18 3.18-1.18.63 1.59.23 2.77.11 3.06.74.81 1.18 1.84 1.18 3.1 0 4.43-2.7 5.4-5.27 5.69.41.36.78 1.06.78 2.14v3.17c0 .31.21.66.8.55A11.5 11.5 0 0 0 12 .5Z"/></svg>
29
+ </a>
30
+ </header>
31
+
32
+ <div class="shell">
33
+
34
+ <aside class="sidebar" id="sidebar">
35
+ <h3>Getting started</h3>
36
+ <ul>
37
+ <li><a href="installation.html">Installation</a></li>
38
+ <li><a href="writing-tests.html">Writing tests</a></li>
39
+ <li><a href="generating-tests.html">Generating tests</a></li>
40
+ <li><a href="running-tests.html" class="current">Running &amp; debugging</a></li>
41
+ <li class="sub"><a href="running-tests.html#tracing">Tracing</a></li>
42
+ <li class="sub"><a href="running-tests.html#video">Screen recording</a></li>
43
+ <li class="sub"><a href="running-tests.html#output-dir">Output &amp; artifacts</a></li>
44
+ <li class="sub"><a href="running-tests.html#reports">Reports</a></li>
45
+ <li><a href="custom-reporters.html">Custom reporters</a></li>
46
+ <li><a href="parallel.html">Parallel runs</a></li>
47
+ <li><a href="docker.html">Run in Docker</a></li>
48
+ </ul>
49
+
50
+ <h3>Taqwright Test</h3>
51
+ <ul>
52
+ <li><a href="configuration.html">Configuration</a></li>
53
+ </ul>
54
+
55
+ <h3>Reference</h3>
56
+ <ul>
57
+ <li><a href="https://playwright.dev/docs/intro">Playwright runner ↗</a></li>
58
+ <li><a href="https://appium.io/docs/en/latest/">Appium 3 ↗</a></li>
59
+ </ul>
60
+ </aside>
61
+
62
+ <main>
63
+
64
+ <div class="breadcrumb">
65
+ <a href="installation.html">Docs</a> / Getting started / Running &amp; debugging tests
66
+ </div>
67
+
68
+ <h1>Running &amp; debugging tests</h1>
69
+ <p class="lede">
70
+ When a test fails on a device you can't see, you need a record of what happened. Taqwright captures two kinds — a per-action <strong>trace</strong> and a full-run <strong>video</strong> — writes them under the <strong>output directory</strong>, and hands everything to Playwright's <strong>reporters</strong>.
71
+ </p>
72
+
73
+ <h2 id="tracing">Tracing — post-mortem debugging</h2>
74
+ <p>
75
+ Set <code>trace</code> in a project's <code>use</code> block to capture a per-action screenshot + page-source timeline of every test run. The result is a self-contained <code>trace.html</code> file under the test's output directory, attached to the Playwright HTML report as <code>taqwright-trace</code>.
76
+ </p>
77
+ <div class="callout">
78
+ <strong>Open it directly.</strong> It's a standalone HTML page — in the Playwright report, click the <code>taqwright-trace</code> attachment to open it in a new tab. It is <em>not</em> a Playwright <code>.zip</code> trace, so don't load it in the Playwright Trace Viewer (that viewer reports <em>"Could not load trace"</em> for it).
79
+ </div>
80
+
81
+ <table class="api">
82
+ <thead><tr><th>Value</th><th>Behaviour</th></tr></thead>
83
+ <tbody>
84
+ <tr><td><code>'off'</code> (default)</td><td>No overhead — Tracer never instantiated.</td></tr>
85
+ <tr><td><code>'on'</code></td><td>Trace every test; HTML always written.</td></tr>
86
+ <tr><td><code>'on-failure'</code></td><td>Trace every test; HTML written only when the test fails. <strong>Recommended for CI.</strong></td></tr>
87
+ <tr><td><code>'retain-on-failure'</code></td><td>Alias of <code>'on-failure'</code> on mobile.</td></tr>
88
+ </tbody>
89
+ </table>
90
+
91
+ <div class="codeblock">
92
+ <div class="filename">taqwright.config.ts</div>
93
+ <pre class="code"><button class="copy">Copy</button><code>{
94
+ name: 'android',
95
+ use: {
96
+ // ... rest of your use options
97
+ trace: 'on-failure',
98
+ },
99
+ }</code></pre>
100
+ </div>
101
+
102
+ <p>What ends up in <code>trace.html</code>:</p>
103
+ <ul>
104
+ <li><strong>Per-action timeline</strong> — each <code>click</code> / <code>fill</code> / <code>assertVisible</code> / etc. gets a row, in execution order.</li>
105
+ <li><strong>Post-state screenshot</strong> for every step (click thumbnail to zoom).</li>
106
+ <li><strong>Page-source XML</strong> snapshot at that moment.</li>
107
+ <li><strong>Per-step timing</strong> + error message highlighted on the failing step.</li>
108
+ </ul>
109
+
110
+ <div class="callout">
111
+ <strong>Cost:</strong>
112
+ each traced action adds one <code>takeScreenshot</code> + one <code>getPageSource</code> round-trip (~100–300 ms on a local emulator, more over USB / cloud). A 30-action test on <code>trace: 'on'</code> typically goes from ~5 s to ~15 s. That's why <code>'on-failure'</code> is the sweet spot for CI.
113
+ </div>
114
+
115
+ <p><strong>How it works under the hood:</strong> the <code>mobile</code> fixture wraps the Mobile + Locator instances in a Proxy when <code>trace !== 'off'</code>. Chain methods (<code>filter</code> / <code>first</code> / <code>nth</code> / <code>locator</code> / <code>and</code> / <code>or</code>) pass through untraced — only the terminal action (<code>click</code>, <code>fill</code>, etc.) records an entry. So <code>mobile.getByType('Cell').nth(2).click()</code> produces one row in the trace, not three.</p>
116
+
117
+ <p>For <strong>interactive</strong> debugging during development (instead of post-mortem), drop <code>await mobile.pause()</code> in a test — it hands the in-flight WebDriver session off to the inspector in your browser. See <a href="generating-tests.html#pause">Generating tests → Debug a live test</a>.</p>
118
+
119
+ <h2 id="video">Screen recording — full-run video</h2>
120
+ <p>
121
+ Set <code>video</code> in a project's <code>use</code> block to capture an Appium on-device screen recording of every test run. The result is a <code>screen.mp4</code> under the test's output directory, attached to the Playwright HTML report as <code>taqwright-video</code>.
122
+ </p>
123
+ <div class="callout">
124
+ <strong>It's a plain video.</strong> In the Playwright report, click the <code>taqwright-video</code> attachment to play the <code>.mp4</code>. It is <em>not</em> a Playwright Trace Viewer trace, and it's deliberately named <code>taqwright-video</code> (not <code>video</code>) so the report doesn't confuse it with its own browser recordings.
125
+ </div>
126
+
127
+ <div class="callout">
128
+ <strong>iOS simulators require <code>ffmpeg</code> on <code>PATH</code>.</strong>
129
+ XCUITest records the iOS <em>simulator</em> by piping frames through host
130
+ <code>ffmpeg</code>. If it isn't installed, Appium's
131
+ <code>startRecordingScreen</code> throws at session start and
132
+ <strong>every iOS test in that project fails in fixture setup</strong> with
133
+ <code>WebDriverError: 'ffmpeg' binary is not found in PATH</code> — this is
134
+ by design (the fixture surfaces the error loudly rather than producing an
135
+ empty <code>.mp4</code>). Install it once:
136
+ <code>brew install ffmpeg</code> (macOS) /
137
+ <code>sudo apt-get install ffmpeg</code> (Linux), then verify with
138
+ <code>ffmpeg -version</code>. Android emulators/devices and <em>real</em>
139
+ iOS devices record on-device and need <strong>no</strong> host
140
+ <code>ffmpeg</code>. Note this affects every non-<code>'off'</code> mode:
141
+ <code>'on-failure'</code> still starts the recorder at session start, so it
142
+ fails the same way without <code>ffmpeg</code> — set
143
+ <code>video: 'off'</code> for the iOS project if you can't install it.
144
+ </div>
145
+
146
+ <table class="api">
147
+ <thead><tr><th>Value</th><th>Behaviour</th></tr></thead>
148
+ <tbody>
149
+ <tr><td><code>'off'</code> (default)</td><td>No recording — recorder never started.</td></tr>
150
+ <tr><td><code>'on'</code></td><td>Record every test; <code>.mp4</code> always kept.</td></tr>
151
+ <tr><td><code>'on-failure'</code></td><td>Record every test; <code>.mp4</code> kept only when the test fails. <strong>Recommended for CI.</strong></td></tr>
152
+ <tr><td><code>'retain-on-failure'</code></td><td>Alias of <code>'on-failure'</code> on mobile.</td></tr>
153
+ </tbody>
154
+ </table>
155
+
156
+ <div class="codeblock">
157
+ <div class="filename">taqwright.config.ts</div>
158
+ <pre class="code"><button class="copy">Copy</button><code>{
159
+ name: 'android',
160
+ use: {
161
+ // ... rest of your use options
162
+ video: 'on-failure',
163
+ },
164
+ }</code></pre>
165
+ </div>
166
+
167
+ <h3 id="video-view">Run &amp; verify</h3>
168
+ <p>
169
+ With <code>video</code> set, just run the project — recording is automatic. The <code>.mp4</code> is written when the test finishes (teardown), so let the run complete.
170
+ </p>
171
+ <div class="codeblock">
172
+ <pre class="code"><button class="copy">Copy</button><code># run the project (emulator/simulator up; Appium auto-starts if configured)
173
+ npx taqwright test --project=android
174
+
175
+ # open the HTML report, then: pick the test → Attachments → taqwright-video
176
+ npx taqwright show-report</code></pre>
177
+ </div>
178
+ <p>
179
+ In the report, open the test and expand <strong>Attachments</strong> — click <code>taqwright-video</code> to play the recording inline (alongside <code>taqwright-trace</code> if <a href="#tracing">tracing</a> is also on). To skip the report and grab the file directly, it's <code>screen.mp4</code> in the test's output folder:
180
+ </p>
181
+ <div class="codeblock">
182
+ <pre class="code"><button class="copy">Copy</button><code>find test-results -name screen.mp4 -exec open {} \;</code></pre>
183
+ </div>
184
+ <p>
185
+ Expectations: with <code>'on'</code> you get an <code>.mp4</code> every run (pass or fail); with <code>'on-failure'</code> only failing tests keep one. The file lives under <a href="#output-dir"><code>outputDir</code></a> (gitignored by the <code>taqwright init</code> scaffold), so it isn't committed. If you don't see the attachment, confirm the run actually reached teardown and that the project's <code>use.video</code> isn't <code>'off'</code>.
186
+ </p>
187
+
188
+ <div class="callout">
189
+ <strong>Cost &amp; caveats:</strong> recording happens on the device for the whole run, so unlike <a href="#tracing">tracing</a> there is <em>no</em> per-action penalty — but every run pays the device recorder plus a base64 transfer of the <code>.mp4</code> at teardown, even when the buffer is discarded on a pass (<code>'on-failure'</code>/<code>'retain-on-failure'</code>). Expect a few MB per minute. Long tests are capped at 30&nbsp;min (the Appium maximum) so recordings aren't silently truncated. On-device recording support varies by driver — real devices and Android emulators record on-device and work out of the box; the iOS <em>simulator</em> needs host <code>ffmpeg</code> on <code>PATH</code> (see the callout above) and the fixture surfaces a clear error at session start rather than producing an empty file.
190
+ </div>
191
+
192
+ <p><strong>How it works under the hood:</strong> the <code>mobile</code> fixture calls Appium's <code>startRecordingScreen</code> before the test body and always <code>stopRecordingScreen</code> at teardown (so the device recorder can't leak between tests). The base64 payload is written to <code>screen.mp4</code> and attached only when the run's outcome matches the selected mode. <code>video</code> and <code>trace</code> are independent — enable both and you get a <code>taqwright-video</code> MP4 plus a <code>taqwright-trace</code> HTML timeline for the same run.</p>
193
+
194
+ <h2 id="output-dir">Output directory &amp; artifacts</h2>
195
+ <p>
196
+ <code>outputDir</code> is the root directory for everything a test run produces on disk — the <code>trace.html</code> from <a href="#tracing">tracing</a>, any <code>testInfo.attach(...)</code> files, and anything a test writes via <code>testInfo.outputPath(...)</code>. It's a top-level <code>defineConfig</code> option, overridable per project.
197
+ </p>
198
+
199
+ <div class="codeblock">
200
+ <div class="filename">taqwright.config.ts</div>
201
+ <pre class="code"><button class="copy">Copy</button><code>export default defineConfig({
202
+ testDir: './tests',
203
+ outputDir: './test-results', // top-level default for every project
204
+
205
+ projects: [
206
+ {
207
+ name: 'android',
208
+ outputDir: './test-results/android', // optional per-project override
209
+ use: { /* ... */ },
210
+ },
211
+ ],
212
+ });</code></pre>
213
+ </div>
214
+
215
+ <ul>
216
+ <li><strong>Per-test subfolder</strong> — each test gets its own directory under <code>outputDir</code>, named <code>&lt;file&gt;-&lt;title&gt;-&lt;project&gt;/</code>. Two tests never clobber each other's artifacts.</li>
217
+ <li><strong>Path resolution</strong> — relative paths are resolved against the <code>taqwright.config.ts</code> location, not the shell's cwd, so the runner works the same whether launched from the project root or a subfolder.</li>
218
+ <li><strong>Default</strong> — if you omit <code>outputDir</code>, it falls back to Playwright's default <code>test-results/</code> in the config directory.</li>
219
+ <li><strong>Reading it from a test</strong> — <code>testInfo</code> is the second argument to the test function: <code>test('name', async ({ mobile }, testInfo) =&gt; { ... })</code>. Use <code>testInfo.outputDir</code> or <code>testInfo.outputPath('file.png')</code> to write your own artifacts into the per-test folder.</li>
220
+ </ul>
221
+
222
+ <div class="callout">
223
+ <strong>Git:</strong> add <code>outputDir</code> (e.g. <code>test-results</code>) to <code>.gitignore</code> — it's regenerated every run, not source. The <code>taqwright init</code> scaffold already ignores <code>test-results/</code> for you.
224
+ </div>
225
+
226
+ <h2 id="reports">Reports</h2>
227
+ <p>
228
+ taqwright forwards the <code>reporter</code> option straight to Playwright. Reporters are <strong>run-level</strong> (there is no per-project reporter), and you stack several at once with the array form. Need a bespoke format? See <a href="custom-reporters.html">Custom reporters</a>.
229
+ </p>
230
+
231
+ <table class="api">
232
+ <thead><tr><th>Reporter</th><th>Writes to</th><th>Use for</th></tr></thead>
233
+ <tbody>
234
+ <tr><td><code>'list'</code> (default)</td><td>console — one line per test</td><td>local / interactive</td></tr>
235
+ <tr><td><code>'line'</code></td><td>console — compact, updating line</td><td>larger suites</td></tr>
236
+ <tr><td><code>'dot'</code></td><td>console — one char per test</td><td>huge suites / CI logs</td></tr>
237
+ <tr><td><code>'html'</code></td><td><code>outputFolder/</code> — browsable site</td><td>debugging, sharing</td></tr>
238
+ <tr><td><code>'json'</code></td><td><code>outputFile</code></td><td>custom tooling</td></tr>
239
+ <tr><td><code>'junit'</code></td><td><code>outputFile</code></td><td>CI (Jenkins/GitLab/Azure)</td></tr>
240
+ <tr><td><code>'blob'</code></td><td><code>outputDir/</code> — shardable</td><td><code>merge-reports</code> across shards</td></tr>
241
+ <tr><td><code>'github'</code></td><td>GitHub Actions annotations</td><td>CI only</td></tr>
242
+ </tbody>
243
+ </table>
244
+
245
+ <div class="codeblock">
246
+ <div class="filename">taqwright.config.ts</div>
247
+ <pre class="code"><button class="copy">Copy</button><code>export default defineConfig({
248
+ reporter: [
249
+ ['list'], // ONE console reporter only
250
+ ['html', { open: 'never', outputFolder: 'reports/html' }],
251
+ ['json', { outputFile: 'reports/results.json' }],
252
+ ['junit', { outputFile: 'reports/results.xml' }],
253
+ ...(process.env.CI ? [['github'] as [string]] : []), // CI-only annotations
254
+ ['blob', { outputDir: 'reports/blob' }],
255
+ ],
256
+ });</code></pre>
257
+ </div>
258
+
259
+ <ul>
260
+ <li><strong>One console reporter.</strong> <code>list</code> / <code>line</code> / <code>dot</code> all write to stdout — stacking two interleaves the output into noise. Pick one; the file reporters coexist cleanly.</li>
261
+ <li><strong>Give <code>json</code> / <code>junit</code> an <code>outputFile</code></strong> — without it they print to stdout and collide with the console reporter.</li>
262
+ <li><strong><code>github</code> is CI-only.</strong> It emits GitHub Actions <code>::notice::</code> / <code>::error::</code> annotations; locally it just prints a hardcoded Playwright summary line. Gate it on <code>process.env.CI</code> as shown.</li>
263
+ </ul>
264
+
265
+ <div class="callout danger">
266
+ <strong>Don't nest the HTML report inside <code>outputDir</code>.</strong> The <code>html</code> reporter <em>wipes</em> its <code>outputFolder</code> before regenerating. If that folder sits inside the test <a href="#output-dir"><code>outputDir</code></a> (e.g. <code>outputFolder: 'test-results/html'</code> with <code>outputDir: 'test-results'</code>), Playwright errors — <em>"HTML reporter output folder clashes with the tests output folder"</em> — and per-test artifacts are destroyed. Keep reports a <strong>sibling</strong> of <code>outputDir</code> (e.g. <code>reports/</code> next to <code>test-results/</code>).
267
+ </div>
268
+
269
+ <h3 id="reports-view">Viewing the HTML report</h3>
270
+ <p>After a run, serve it with:</p>
271
+ <div class="codeblock">
272
+ <pre class="code"><button class="copy">Copy</button><code>npx taqwright show-report reports/html
273
+ # --host &lt;host&gt; (default localhost) · --port &lt;port&gt; (default 9323)</code></pre>
274
+ </div>
275
+ <p>
276
+ taqwright prints this exact (taqwright-branded) command at the end of an interactive run. <code>show-report</code> also serves a blob <code>.zip</code> directly.
277
+ </p>
278
+
279
+ <h3 id="reports-per-project">Per-project report directories</h3>
280
+ <p>
281
+ Because reporters are run-level, one run merges every project into a single report. For an isolated report <em>per</em> project, run once per project and let the config derive reporter paths from an env var — <code>taqwright.config.ts</code> is just TypeScript, so it can read <code>process.env</code>:
282
+ </p>
283
+ <div class="codeblock">
284
+ <div class="filename">taqwright.config.ts</div>
285
+ <pre class="code"><button class="copy">Copy</button><code>const proj = process.env.TW_REPORT_PROJECT;
286
+ const base = proj ? `reports/${proj}` : 'reports/_all';
287
+
288
+ export default defineConfig({
289
+ outputDir: './test-results', // sibling of reports/ — no clash
290
+ reporter: [
291
+ ['list'],
292
+ ['html', { open: 'never', outputFolder: `${base}/html-report` }],
293
+ ['json', { outputFile: `${base}/results.json` }],
294
+ ['junit', { outputFile: `${base}/results.xml` }],
295
+ ['blob', { outputDir: `${base}/blob-report` }],
296
+ ],
297
+ // ...
298
+ });</code></pre>
299
+ </div>
300
+ <div class="codeblock">
301
+ <div class="filename">package.json</div>
302
+ <pre class="code"><button class="copy">Copy</button><code>{
303
+ "scripts": {
304
+ "test:android": "TW_REPORT_PROJECT=android taqwright test --project=android",
305
+ "test:ios": "TW_REPORT_PROJECT=ios taqwright test --project=ios",
306
+ "report:android": "taqwright show-report reports/android/html-report",
307
+ "report:ios": "taqwright show-report reports/ios/html-report"
308
+ }
309
+ }</code></pre>
310
+ </div>
311
+ <p>
312
+ Each invocation writes only under its own <code>reports/&lt;project&gt;/</code> — runs never clobber each other. A plain <code>taqwright test</code> (all projects, one run, env unset) falls back to <code>reports/_all/</code>.
313
+ </p>
314
+
315
+ <div class="pager">
316
+ <a href="generating-tests.html">
317
+ <div class="label">← Previous</div>
318
+ <div class="title">Generating tests</div>
319
+ </a>
320
+ <a class="next" href="custom-reporters.html">
321
+ <div class="label">Next →</div>
322
+ <div class="title">Custom reporters</div>
323
+ </a>
324
+ </div>
325
+
326
+ </main>
327
+
328
+ <aside class="onthispage">
329
+ <h4>On this page</h4>
330
+ <ol>
331
+ <li><a href="#tracing">Tracing</a></li>
332
+ <li><a href="#video">Screen recording</a>
333
+ <ol class="sub">
334
+ <li><a href="#video-view">Run &amp; verify</a></li>
335
+ </ol>
336
+ </li>
337
+ <li><a href="#output-dir">Output &amp; artifacts</a></li>
338
+ <li><a href="#reports">Reports</a>
339
+ <ol class="sub">
340
+ <li><a href="#reports-view">Viewing the report</a></li>
341
+ <li><a href="#reports-per-project">Per-project dirs</a></li>
342
+ </ol>
343
+ </li>
344
+ </ol>
345
+ </aside>
346
+
347
+ </div>
348
+
349
+ <footer class="bot">
350
+ <div class="cols">
351
+ <div>
352
+ <h5>Getting started</h5>
353
+ <ul>
354
+ <li><a href="installation.html">Installation</a></li>
355
+ <li><a href="writing-tests.html">Writing tests</a></li>
356
+ <li><a href="generating-tests.html">Generating tests</a></li>
357
+ <li><a href="running-tests.html">Running &amp; debugging</a></li>
358
+ </ul>
359
+ </div>
360
+ <div>
361
+ <h5>Guides</h5>
362
+ <ul>
363
+ <li><a href="custom-reporters.html">Custom reporters</a></li>
364
+ <li><a href="parallel.html">Parallel runs</a></li>
365
+ <li><a href="docker.html">Run in Docker</a></li>
366
+ <li><a href="writing-tests.html#actions">API surface</a></li>
367
+ </ul>
368
+ </div>
369
+ <div>
370
+ <h5>Built on</h5>
371
+ <ul>
372
+ <li><a href="https://playwright.dev/">Playwright</a></li>
373
+ <li><a href="https://appium.io/">Appium 3</a></li>
374
+ </ul>
375
+ </div>
376
+ </div>
377
+ <div class="copy">
378
+ Apache-2.0 licensed · Built on Playwright + Appium
379
+ </div>
380
+ </footer>
381
+
382
+ <script src="docs.js"></script>
383
+
384
+ </body>
385
+ </html>