@testspectra/cli 1.1.7 → 1.1.8-rc.2

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 (261) hide show
  1. package/bin/.testspectra-runner.hash +1 -1
  2. package/bin/spectra.js +0 -0
  3. package/bin/testspectra-runner.exe +0 -0
  4. package/demo-app/assets/index-BhlW-eXG.css +1 -0
  5. package/demo-app/assets/index-DOtRypCa.js +154 -0
  6. package/demo-app/index.html +2 -2
  7. package/dist/.tsbuildinfo +1 -1
  8. package/dist/commands/__tests__/run-e2e.test.js +270 -29
  9. package/dist/commands/__tests__/run.test.js +92 -16
  10. package/dist/commands/demo.js +17 -7
  11. package/dist/commands/init.d.ts +1 -1
  12. package/dist/commands/init.js +154 -149
  13. package/dist/commands/lint.d.ts +5 -0
  14. package/dist/commands/lint.js +55 -0
  15. package/dist/commands/refactor.d.ts +2 -1
  16. package/dist/commands/refactor.js +129 -35
  17. package/dist/commands/run.d.ts +2 -3
  18. package/dist/commands/run.js +93 -28
  19. package/dist/commands/skills.d.ts +9 -0
  20. package/dist/commands/skills.js +28 -0
  21. package/dist/commands/sync-types.js +1 -0
  22. package/dist/commands/test.d.ts +17 -0
  23. package/dist/commands/test.js +104 -0
  24. package/dist/commands/watch.js +9 -3
  25. package/dist/config/loader.js +1 -1
  26. package/dist/config/schema.d.ts +5 -114
  27. package/dist/config/schema.js +1 -17
  28. package/dist/generator/__tests__/tsconfig-isolation.test.js +6 -2
  29. package/dist/generator/__tests__/type-generator.test.js +1 -1
  30. package/dist/generator/tsconfig-generator.js +44 -16
  31. package/dist/generator/type-generator.d.ts +24 -1
  32. package/dist/generator/type-generator.js +104 -8
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +76 -40
  35. package/dist/linter/__tests__/anonymous-export.test.js +184 -0
  36. package/dist/linter/__tests__/component-test-imports.test.d.ts +1 -0
  37. package/dist/linter/__tests__/component-test-imports.test.js +115 -0
  38. package/dist/linter/__tests__/shared-lib-boundary.test.d.ts +1 -0
  39. package/dist/linter/__tests__/shared-lib-boundary.test.js +270 -0
  40. package/dist/linter/__tests__/spec-schema.test.d.ts +1 -0
  41. package/dist/linter/__tests__/spec-schema.test.js +369 -0
  42. package/dist/linter/__tests__/step-parity.test.d.ts +1 -0
  43. package/dist/linter/__tests__/step-parity.test.js +372 -0
  44. package/dist/linter/discovery.d.ts +30 -0
  45. package/dist/linter/discovery.js +249 -0
  46. package/dist/linter/extractor.d.ts +67 -0
  47. package/dist/linter/extractor.js +245 -0
  48. package/dist/linter/index.d.ts +7 -0
  49. package/dist/linter/index.js +7 -0
  50. package/dist/linter/parser.d.ts +24 -0
  51. package/dist/linter/parser.js +219 -0
  52. package/dist/linter/schemas/spec.schema.d.ts +83 -0
  53. package/dist/linter/schemas/spec.schema.js +150 -0
  54. package/dist/linter/schemas/suite.schema.d.ts +59 -0
  55. package/dist/linter/schemas/suite.schema.js +83 -0
  56. package/dist/linter/spec-linter.d.ts +23 -0
  57. package/dist/linter/spec-linter.js +630 -0
  58. package/dist/linter/types.d.ts +28 -0
  59. package/dist/linter/types.js +1 -0
  60. package/dist/refactor/__tests__/refactor-engine.test.js +698 -0
  61. package/dist/refactor/refactor-engine.d.ts +25 -0
  62. package/dist/refactor/refactor-engine.js +374 -42
  63. package/dist/reporter/semantic-formatter.js +22 -2
  64. package/dist/reporter/types.d.ts +1 -1
  65. package/dist/runner/bridge.d.ts +1 -1
  66. package/dist/runner/bridge.js +34 -21
  67. package/dist/runner/reporter.d.ts +2 -0
  68. package/dist/runner/reporter.js +11 -3
  69. package/dist/utils/__tests__/api-server.test.d.ts +1 -0
  70. package/dist/utils/__tests__/api-server.test.js +62 -0
  71. package/dist/utils/__tests__/demo-server.test.d.ts +1 -0
  72. package/dist/utils/__tests__/demo-server.test.js +35 -0
  73. package/dist/utils/api-server.d.ts +19 -0
  74. package/dist/utils/api-server.js +179 -0
  75. package/dist/utils/demo-server.d.ts +5 -0
  76. package/dist/utils/demo-server.js +8 -1
  77. package/package.json +29 -25
  78. package/templates/default/CLAUDE.md +16 -11
  79. package/templates/default/global-hooks/after/mobile.hook.ts +3 -3
  80. package/templates/default/global-hooks/after/web.hook.ts +3 -3
  81. package/templates/default/global-hooks/before/mobile.hook.ts +3 -3
  82. package/templates/default/global-hooks/before/web.hook.ts +3 -3
  83. package/templates/default/package.json +3 -3
  84. package/templates/default/page-objects/AuthPage/mobile.ts +5 -0
  85. package/templates/default/page-objects/AuthPage/web.ts +10 -0
  86. package/templates/default/page-objects/MatchersPage/mobile.ts +70 -46
  87. package/templates/default/page-objects/MatchersPage/web.ts +43 -37
  88. package/templates/default/page-objects/NavigationPage/mobile.ts +14 -14
  89. package/templates/default/page-objects/NavigationPage/web.ts +8 -8
  90. package/templates/default/page-objects/PlaygroundPage/mobile.ts +42 -36
  91. package/templates/default/page-objects/PlaygroundPage/web.ts +31 -31
  92. package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +53 -11
  93. package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/spec.md +19 -12
  94. package/templates/default/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +31 -27
  95. package/templates/default/specs/ApiInterception/TC-0009-post-mocking/android.test.ts +3 -0
  96. package/templates/default/specs/ApiInterception/TC-0009-post-mocking/common.test.ts +3 -0
  97. package/templates/default/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +27 -16
  98. package/templates/default/specs/ApiInterception/TC-0009-post-mocking/spec.md +19 -12
  99. package/templates/default/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +26 -24
  100. package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/common.test.ts +30 -0
  101. package/templates/default/specs/ApiInterception/TC-0012-direct-and-late-response/spec.md +22 -0
  102. package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/common.test.ts +27 -0
  103. package/templates/default/specs/ApiInterception/TC-0013-real-network-call-recorded/spec.md +20 -0
  104. package/templates/default/specs/ApiInterception/TC-0015-mock-server-sent-events/spec.md +24 -0
  105. package/templates/default/specs/ApiInterception/TC-0015-mock-server-sent-events/web.test.ts +26 -0
  106. package/templates/default/specs/ApiInterception/TC-0016-bypass-websocket-with-app-level-mock/spec.md +37 -0
  107. package/templates/default/specs/ApiInterception/TC-0016-bypass-websocket-with-app-level-mock/web.test.ts +21 -0
  108. package/templates/default/specs/ApiInterception/TC-0017-bypass-captcha-with-test-mode-flag/spec.md +29 -0
  109. package/templates/default/specs/ApiInterception/TC-0017-bypass-captcha-with-test-mode-flag/web.test.ts +16 -0
  110. package/templates/default/specs/ApiInterception/suite.md +10 -9
  111. package/templates/default/specs/ApiSeeding/TC-0014-seed-and-cleanup-via-hooks/common.test.ts +30 -0
  112. package/templates/default/specs/ApiSeeding/TC-0014-seed-and-cleanup-via-hooks/spec.md +23 -0
  113. package/templates/default/specs/ApiSeeding/hooks/after/common.hook.ts +16 -0
  114. package/templates/default/specs/ApiSeeding/hooks/before/common.hook.ts +28 -0
  115. package/templates/default/specs/ApiSeeding/suite.md +9 -0
  116. package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/mobile.test.ts +7 -0
  117. package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/spec.md +19 -0
  118. package/templates/default/specs/Authentication/TC-0021-seed-authenticated-session/web.test.ts +9 -0
  119. package/templates/default/specs/Authentication/suite.md +9 -0
  120. package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +9 -9
  121. package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/spec.md +17 -12
  122. package/templates/default/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +19 -19
  123. package/templates/default/specs/BrowserContext/TC-0022-history-navigation/mobile.test.ts +17 -0
  124. package/templates/default/specs/BrowserContext/TC-0022-history-navigation/spec.md +28 -0
  125. package/templates/default/specs/BrowserContext/TC-0022-history-navigation/web.test.ts +26 -0
  126. package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/common.test.ts +26 -0
  127. package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/spec.md +19 -12
  128. package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +11 -11
  129. package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/spec.md +17 -12
  130. package/templates/default/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +11 -11
  131. package/templates/default/specs/ContentMatchers/TC-0020-scoped-element-access/common.test.ts +14 -0
  132. package/templates/default/specs/ContentMatchers/TC-0020-scoped-element-access/spec.md +21 -0
  133. package/templates/default/specs/DeepLink/TC-0018-navigate-via-deep-link/mobile.test.ts +28 -0
  134. package/templates/default/specs/DeepLink/TC-0018-navigate-via-deep-link/spec.md +29 -0
  135. package/templates/default/specs/DeepLink/suite.md +9 -0
  136. package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +11 -11
  137. package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/spec.md +17 -12
  138. package/templates/default/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +11 -11
  139. package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +29 -29
  140. package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/spec.md +19 -12
  141. package/templates/default/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +29 -29
  142. package/templates/default/specs/ElementMatchers/suite.md +10 -9
  143. package/templates/default/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/common.test.ts +5 -0
  144. package/templates/default/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/spec.md +16 -0
  145. package/templates/default/specs/EnvironmentConfig/suite.md +9 -0
  146. package/templates/default/specs/PermissionRationale/TC-0010-camera-permission-allow/mobile.test.ts +26 -0
  147. package/templates/default/specs/PermissionRationale/TC-0010-camera-permission-allow/spec.md +22 -0
  148. package/templates/default/specs/PermissionRationale/TC-0011-camera-permission-deny/mobile.test.ts +13 -0
  149. package/templates/default/specs/PermissionRationale/TC-0011-camera-permission-deny/spec.md +20 -0
  150. package/templates/default/specs/PermissionRationale/suite.md +9 -0
  151. package/templates/default/specs/Playground/TC-0001-form-controls/mobile.test.ts +6 -6
  152. package/templates/default/specs/Playground/TC-0001-form-controls/spec.md +18 -12
  153. package/templates/default/specs/Playground/TC-0001-form-controls/web.test.ts +6 -6
  154. package/templates/default/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +6 -6
  155. package/templates/default/specs/Playground/TC-0002-toggle-elements/spec.md +18 -12
  156. package/templates/default/specs/Playground/TC-0002-toggle-elements/web.test.ts +6 -6
  157. package/templates/default/spectra.config.ts +52 -68
  158. package/templates/default/support/actions/fillCredentials/mobile.action.ts +4 -4
  159. package/templates/default/support/actions/fillCredentials/web.action.ts +4 -4
  160. package/templates/default/support/actions/seedSession/mobile.action.ts +9 -0
  161. package/templates/default/support/actions/seedSession/web.action.ts +13 -0
  162. package/templates/default/support/steps/togglePlaygroundStates/mobile.step.ts +5 -5
  163. package/templates/default/support/steps/togglePlaygroundStates/web.step.ts +5 -5
  164. package/templates/default/support/steps/verifyPlaygroundState/mobile.step.ts +6 -6
  165. package/templates/default/support/steps/verifyPlaygroundState/web.step.ts +6 -6
  166. package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db +0 -0
  167. package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db-shm +0 -0
  168. package/templates/nx/.nx/workspace-data/59842386-c7c4-44ca-b2c2-20e1700bd13d.db-wal +0 -0
  169. package/templates/nx/.nx/workspace-data/d/daemon.log +1577 -168
  170. package/templates/nx/.nx/workspace-data/d/server-process.json +3 -0
  171. package/templates/nx/.nx/workspace-data/file-map.json +464 -0
  172. package/templates/nx/.nx/workspace-data/lockfile.hash +1 -0
  173. package/templates/nx/.nx/workspace-data/nx_files.nxt +0 -0
  174. package/templates/nx/.nx/workspace-data/parsed-lock-file.json +13485 -0
  175. package/templates/nx/.nx/workspace-data/project-graph.json +14389 -0
  176. package/templates/nx/CLAUDE.md +10 -10
  177. package/templates/nx/package.json +3 -3
  178. package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/mobile.test.ts +27 -3
  179. package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0008-fetch-mocking/web.test.ts +27 -27
  180. package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/mobile.test.ts +24 -3
  181. package/templates/nx/packages/matchers/e2e/specs/ApiInterception/TC-0009-post-mocking/web.test.ts +24 -24
  182. package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/mobile.test.ts +3 -3
  183. package/templates/nx/packages/matchers/e2e/specs/BrowserContext/TC-0007-title-and-navigation/web.test.ts +19 -19
  184. package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/mobile.test.ts +3 -3
  185. package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0005-text-and-values/web.test.ts +17 -17
  186. package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/mobile.test.ts +3 -3
  187. package/templates/nx/packages/matchers/e2e/specs/ContentMatchers/TC-0006-collections-and-empty/web.test.ts +11 -11
  188. package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/mobile.test.ts +3 -3
  189. package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0003-visibility-and-dom/web.test.ts +11 -11
  190. package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/mobile.test.ts +3 -3
  191. package/templates/nx/packages/matchers/e2e/specs/ElementMatchers/TC-0004-states-and-attributes/web.test.ts +29 -29
  192. package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/common.test.ts +5 -0
  193. package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/TC-0019-read-custom-environment-variable/spec.md +16 -0
  194. package/templates/nx/packages/matchers/e2e/specs/EnvironmentConfig/suite.md +9 -0
  195. package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/mobile.test.ts +3 -3
  196. package/templates/nx/packages/playground/e2e/specs/Playground/TC-0001-form-controls/web.test.ts +6 -6
  197. package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/mobile.test.ts +3 -3
  198. package/templates/nx/packages/playground/e2e/specs/Playground/TC-0002-toggle-elements/web.test.ts +6 -6
  199. package/templates/nx/pnpm-lock.yaml +6663 -6663
  200. package/templates/nx/pnpm-workspace.yaml +9 -9
  201. package/templates/nx/shared/testing/page-objects/MatchersPage/mobile.ts +33 -33
  202. package/templates/nx/shared/testing/page-objects/MatchersPage/web.ts +91 -37
  203. package/templates/nx/shared/testing/page-objects/NavigationPage/mobile.ts +5 -5
  204. package/templates/nx/shared/testing/page-objects/NavigationPage/web.ts +8 -8
  205. package/templates/nx/shared/testing/page-objects/PlaygroundPage/mobile.ts +26 -26
  206. package/templates/nx/shared/testing/page-objects/PlaygroundPage/web.ts +31 -31
  207. package/templates/nx/shared/testing/project.json +19 -19
  208. package/templates/nx/shared/testing/support/actions/fillCredentials/mobile.action.ts +4 -4
  209. package/templates/nx/shared/testing/support/actions/fillCredentials/web.action.ts +4 -4
  210. package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/mobile.step.ts +3 -3
  211. package/templates/nx/shared/testing/support/steps/togglePlaygroundStates/web.step.ts +5 -5
  212. package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/mobile.step.ts +4 -4
  213. package/templates/nx/shared/testing/support/steps/verifyPlaygroundState/web.step.ts +6 -6
  214. package/templates/nx/spectra.config.ts +52 -68
  215. package/templates/react-component/.cursorrules +17 -0
  216. package/templates/react-component/.vscode/extensions.json +5 -0
  217. package/templates/react-component/CLAUDE.md +14 -0
  218. package/templates/react-component/README.md +69 -0
  219. package/templates/react-component/fixtures/component-mock.json +12 -0
  220. package/templates/react-component/global-hooks/after/web.hook.ts +3 -0
  221. package/templates/react-component/global-hooks/before/web.hook.ts +3 -0
  222. package/templates/react-component/package.json +27 -0
  223. package/templates/react-component/page-objects/BadgeComponent/web.ts +23 -0
  224. package/templates/react-component/page-objects/ButtonComponent/web.ts +23 -0
  225. package/templates/react-component/page-objects/InputComponent/web.ts +13 -0
  226. package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/spec.md +18 -0
  227. package/templates/react-component/specs/BadgeComponent/TC-0002-badge-severities-and-dot/web.test.tsx +11 -0
  228. package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/spec.md +18 -0
  229. package/templates/react-component/specs/BadgeComponent/TC-0006-badge-success-with-dot/web.test.tsx +10 -0
  230. package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/spec.md +18 -0
  231. package/templates/react-component/specs/BadgeComponent/TC-0007-badge-by-severity-lookup/web.test.tsx +16 -0
  232. package/templates/react-component/specs/BadgeComponent/suite.md +12 -0
  233. package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/spec.md +19 -0
  234. package/templates/react-component/specs/ButtonComponent/TC-0001-button-rendering-and-click/web.test.tsx +28 -0
  235. package/templates/react-component/specs/ButtonComponent/TC-0004-disabled-button-not-clickable/spec.md +19 -0
  236. package/templates/react-component/specs/ButtonComponent/TC-0004-disabled-button-not-clickable/web.test.tsx +22 -0
  237. package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/spec.md +18 -0
  238. package/templates/react-component/specs/ButtonComponent/TC-0005-button-renders-icon/web.test.tsx +8 -0
  239. package/templates/react-component/specs/ButtonComponent/suite.md +12 -0
  240. package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/spec.md +20 -0
  241. package/templates/react-component/specs/InputComponent/TC-0003-input-typing-and-clear/web.test.tsx +28 -0
  242. package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/spec.md +18 -0
  243. package/templates/react-component/specs/InputComponent/TC-0008-disabled-input-not-editable/web.test.tsx +9 -0
  244. package/templates/react-component/specs/InputComponent/suite.md +12 -0
  245. package/templates/react-component/spectra.config.ts +27 -0
  246. package/templates/react-component/src/components/Badge/Badge.tsx +60 -0
  247. package/templates/react-component/src/components/Button/Button.tsx +57 -0
  248. package/templates/react-component/src/components/Input/Input.tsx +41 -0
  249. package/templates/react-component/src/test-utils.tsx +23 -0
  250. package/templates/react-component/support/actions/fillInputField/web.action.ts +9 -0
  251. package/templates/react-component/support/steps/verifyButtonState/web.step.ts +12 -0
  252. package/templates/react-component/tsconfig.json +8 -0
  253. package/bin/testspectra-runner +0 -0
  254. package/demo-app/assets/index-DPfv5_EF.js +0 -116
  255. package/demo-app/assets/index-gIwu2EMV.css +0 -1
  256. package/dist/commands/__tests__/cloud-run.test.js +0 -93
  257. package/dist/commands/cloud-run.d.ts +0 -13
  258. package/dist/commands/cloud-run.js +0 -120
  259. package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/mobile.test.ts +0 -17
  260. package/templates/default/specs/ContentMatchers/TC-0005-text-and-values/web.test.ts +0 -17
  261. /package/dist/{commands/__tests__/cloud-run.test.d.ts → linter/__tests__/anonymous-export.test.d.ts} +0 -0
@@ -0,0 +1,22 @@
1
+ ---
2
+ id: TC-0010-camera-permission-allow
3
+ title: Confirm custom rationale dialog Allow triggers real permission request and grants camera access
4
+ priority: High
5
+ caseType: Positive
6
+ status: ready-for-automation
7
+ coverage:
8
+ web: unsupported
9
+ mobile: automated
10
+ ---
11
+
12
+ # Confirm custom rationale dialog Allow triggers real permission request and grants camera access
13
+
14
+ ## Test Steps
15
+ 1. Navigate to the permission rationale demo route
16
+ 2. Assert the initial status is "Not requested"
17
+ 3. Click the request camera permission button
18
+ 4. Assert the custom rationale dialog appears
19
+ 5. Click Allow
20
+ 6. Grant the real camera permission on demand
21
+ 7. Assert the status becomes "Granted"
22
+ 8. Return to the home screen
@@ -0,0 +1,13 @@
1
+ it("Confirm custom rationale dialog Deny never triggers the real permission request", async () => {
2
+ await Spectra.get("~nav-to-permission-demo").click();
3
+
4
+ await Spectra.get("~request-camera-permission-btn").click();
5
+ await Spectra.get("~rationale-deny-btn").shouldBeVisible();
6
+ await Spectra.get("~rationale-deny-btn").click();
7
+
8
+ // Deliberately never calls the real permission API — the status must reflect the custom
9
+ // dialog's own decision, not any OS-level request.
10
+ await Spectra.get("~permission-status-text").shouldHaveText("Declined in rationale dialog");
11
+
12
+ await Spectra.get("~back-to-home-btn").click();
13
+ });
@@ -0,0 +1,20 @@
1
+ ---
2
+ id: TC-0011-camera-permission-deny
3
+ title: Confirm custom rationale dialog Deny never triggers the real permission request
4
+ priority: High
5
+ caseType: Negative
6
+ status: ready-for-automation
7
+ coverage:
8
+ web: unsupported
9
+ mobile: automated
10
+ ---
11
+
12
+ # Confirm custom rationale dialog Deny never triggers the real permission request
13
+
14
+ ## Test Steps
15
+ 1. Navigate to the permission rationale demo route
16
+ 2. Click the request camera permission button
17
+ 3. Assert the custom rationale dialog appears
18
+ 4. Click Deny
19
+ 5. Assert the status reflects the dialog's own decision without any real permission request
20
+ 6. Return to the home screen
@@ -0,0 +1,9 @@
1
+ ---
2
+ id: suite-permission-rationale
3
+ name: PermissionRationale
4
+ description: Android runtime permission rationale dialog and on-demand Spectra.grantPermission()
5
+ executionOrder: 2.0
6
+ parallel: true
7
+ ---
8
+
9
+ # Suite: PermissionRationale
@@ -1,6 +1,6 @@
1
- it("should verify live playground form inputs and default states (Mobile)", async () => {
2
- await Step.verifyPlaygroundState();
3
- await PlaygroundPage.emailInput.shouldHaveValue(Fixture.playgroundData.defaultEmail);
4
- await PlaygroundPage.tokenInput.shouldContainValue("JWT_");
5
- await PlaygroundPage.exactText.shouldHaveText(Fixture.playgroundData.welcomeText);
6
- });
1
+ it("Verify playground form inputs and default states", async () => {
2
+ await Step.verifyPlaygroundState();
3
+ await PlaygroundPage.emailInput.shouldHaveValue(Fixture.playgroundData.defaultEmail);
4
+ await PlaygroundPage.tokenInput.shouldContainValue("JWT_");
5
+ await PlaygroundPage.exactText.shouldHaveText(Fixture.playgroundData.welcomeText);
6
+ });
@@ -1,12 +1,18 @@
1
- ---
2
- id: TC-0001-form-controls
3
- title: Verify playground form inputs and default states
4
- priority: High
5
- caseType: Positive
6
- status: ready-for-automation
7
- coverage:
8
- web: automated
9
- mobile: automated
10
- ---
11
-
12
- # Verify playground form inputs and default states
1
+ ---
2
+ id: TC-0001-form-controls
3
+ title: Verify playground form inputs and default states
4
+ priority: High
5
+ caseType: Positive
6
+ status: ready-for-automation
7
+ coverage:
8
+ web: automated
9
+ mobile: automated
10
+ ---
11
+
12
+ # Verify playground form inputs and default states
13
+
14
+ ## Test Steps
15
+ 1. @step:verifyPlaygroundState
16
+ 2. Verify playground email input has default email
17
+ 3. Verify token input contains JWT token
18
+ 4. Verify exact welcome text matches playground data
@@ -1,6 +1,6 @@
1
- it("should verify live playground form inputs and default states (Web)", async () => {
2
- await Step.verifyPlaygroundState();
3
- await PlaygroundPage.emailInput.shouldHaveValue(Fixture.playgroundData.defaultEmail);
4
- await PlaygroundPage.tokenInput.shouldContainValue("JWT_");
5
- await PlaygroundPage.exactText.shouldHaveText(Fixture.playgroundData.welcomeText);
6
- });
1
+ it("Verify playground form inputs and default states", async () => {
2
+ await Step.verifyPlaygroundState();
3
+ await PlaygroundPage.emailInput.shouldHaveValue(Fixture.playgroundData.defaultEmail);
4
+ await PlaygroundPage.tokenInput.shouldContainValue("JWT_");
5
+ await PlaygroundPage.exactText.shouldHaveText(Fixture.playgroundData.welcomeText);
6
+ });
@@ -1,6 +1,6 @@
1
- it("should update input values and verify updated state (Mobile)", async () => {
2
- await PlaygroundPage.open();
3
- await PlaygroundPage.fillCredentials("qa.expert@testspectra.dev", "JWT_custom_session_token");
4
- await PlaygroundPage.emailInput.shouldHaveValue("qa.expert@testspectra.dev");
5
- await PlaygroundPage.tokenInput.shouldContainValue("JWT_custom_session_token");
6
- });
1
+ it("Verify typing credentials and updating playground inputs", async () => {
2
+ await PlaygroundPage.open();
3
+ await PlaygroundPage.fillCredentials("qa.expert@testspectra.dev", "JWT_custom_session_token");
4
+ await PlaygroundPage.emailInput.shouldHaveValue("qa.expert@testspectra.dev");
5
+ await PlaygroundPage.tokenInput.shouldContainValue("JWT_custom_session_token");
6
+ });
@@ -1,12 +1,18 @@
1
- ---
2
- id: TC-0002-toggle-elements
3
- title: Verify typing credentials and updating playground inputs
4
- priority: High
5
- caseType: Positive
6
- status: ready-for-automation
7
- coverage:
8
- web: automated
9
- mobile: automated
10
- ---
11
-
12
- # Verify typing credentials and updating playground inputs
1
+ ---
2
+ id: TC-0002-toggle-elements
3
+ title: Verify typing credentials and updating playground inputs
4
+ priority: High
5
+ caseType: Positive
6
+ status: ready-for-automation
7
+ coverage:
8
+ web: automated
9
+ mobile: automated
10
+ ---
11
+
12
+ # Verify typing credentials and updating playground inputs
13
+
14
+ ## Test Steps
15
+ 1. Open playground page
16
+ 2. Fill credentials into email and token input fields
17
+ 3. Verify email input contains updated email
18
+ 4. Verify token input contains updated session token
@@ -1,6 +1,6 @@
1
- it("should update input values and verify updated state (Web)", async () => {
2
- await PlaygroundPage.open();
3
- await PlaygroundPage.fillCredentials("qa.expert@testspectra.dev", "JWT_custom_session_token");
4
- await PlaygroundPage.emailInput.shouldHaveValue("qa.expert@testspectra.dev");
5
- await PlaygroundPage.tokenInput.shouldContainValue("JWT_custom_session_token");
6
- });
1
+ it("Verify typing credentials and updating playground inputs", async () => {
2
+ await PlaygroundPage.open();
3
+ await PlaygroundPage.fillCredentials("qa.expert@testspectra.dev", "JWT_custom_session_token");
4
+ await PlaygroundPage.emailInput.shouldHaveValue("qa.expert@testspectra.dev");
5
+ await PlaygroundPage.tokenInput.shouldContainValue("JWT_custom_session_token");
6
+ });
@@ -1,68 +1,52 @@
1
- import { defineConfig } from "@testspectra/cli";
2
-
3
- export default defineConfig({
4
- webConfig: {
5
- baseUrl: "http://localhost:5173",
6
- maxConcurrentSessions: "1",
7
- headless: true,
8
- implicitWait: "5000",
9
- pageLoadTimeout: "30000",
10
- scriptTimeout: "30000",
11
- parallelizationMode: "testcase",
12
- },
13
- browsers: [
14
- {
15
- id: "chrome-desktop",
16
- type: "chrome",
17
- mobileEmulation: false,
18
- },
19
- ],
20
- androidConfig: {
21
- driverServer: "tcp://127.0.0.1:8200",
22
- appPackage: "dev.testspectra.demoapp",
23
- appActivity: "dev.testspectra.demoapp.MainActivity",
24
- autoGrantPermissions: true,
25
- noReset: false,
26
- implicitWait: "10000",
27
- parallelizationMode: "suite",
28
- devices: [
29
- {
30
- id: "emulator-5554",
31
- name: "Pixel 8a Emulator",
32
- version: "14.0",
33
- systemPort: 8200,
34
- },
35
- ],
36
- },
37
- iosConfig: {
38
- appiumServer: "http://127.0.0.1:4723",
39
- automationName: "XCUITest",
40
- bundleId: "",
41
- autoAcceptAlerts: true,
42
- noReset: false,
43
- implicitWait: "10000",
44
- parallelizationMode: "suite",
45
- devices: [
46
- {
47
- id: "iphone-15-pro",
48
- name: "iPhone 15 Pro Simulator",
49
- version: "17.0",
50
- udid: "auto",
51
- wdaLocalPort: 8100,
52
- },
53
- ],
54
- },
55
- loadConfig: {
56
- virtualUsers: "10",
57
- duration: "1m",
58
- },
59
- loadStages: [],
60
- thresholds: [],
61
- executionConfig: {
62
- networkMonitoringEnabled: true,
63
- fastResponseTime: "200",
64
- normalResponseTime: "1000",
65
- monitoredDomains: [],
66
- environmentVariables: [],
67
- },
68
- });
1
+ import { defineConfig } from "@testspectra/cli";
2
+
3
+ export default defineConfig({
4
+ webConfig: {
5
+ baseUrl: "http://localhost:5173",
6
+ maxConcurrentSessions: "1",
7
+ headless: true,
8
+ implicitWait: "5000",
9
+ parallelizationMode: "testcase",
10
+ },
11
+ androidConfig: {
12
+ driverServer: "tcp://127.0.0.1:8200",
13
+ appPackage: "dev.testspectra.demoapp",
14
+ appActivity: "dev.testspectra.demoapp.MainActivity",
15
+ noReset: false,
16
+ implicitWait: "10000",
17
+ parallelizationMode: "suite",
18
+ devices: [
19
+ {
20
+ id: "emulator-5554",
21
+ name: "Pixel 8a Emulator",
22
+ version: "14.0",
23
+ systemPort: 8200,
24
+ },
25
+ ],
26
+ },
27
+ iosConfig: {
28
+ appiumServer: "http://127.0.0.1:4723",
29
+ automationName: "XCUITest",
30
+ bundleId: "",
31
+ autoAcceptAlerts: true,
32
+ noReset: false,
33
+ implicitWait: "10000",
34
+ parallelizationMode: "suite",
35
+ devices: [
36
+ {
37
+ id: "iphone-15-pro",
38
+ name: "iPhone 15 Pro Simulator",
39
+ version: "17.0",
40
+ udid: "auto",
41
+ wdaLocalPort: 8100,
42
+ },
43
+ ],
44
+ },
45
+ executionConfig: {
46
+ networkMonitoringEnabled: true,
47
+ fastResponseTime: "200",
48
+ normalResponseTime: "1000",
49
+ monitoredDomains: [],
50
+ environmentVariables: { DEMO_API_MODE: "sandbox" },
51
+ },
52
+ });
@@ -1,4 +1,4 @@
1
- export default async function fillCredentials(this: any, email: string, token: string) {
2
- await this.get("~email-input").type(email);
3
- await this.get("~token-input").type(token);
4
- }
1
+ export default async function (this: any, email: string, token: string) {
2
+ await this.get("~pg-email-input").type(email);
3
+ await this.get("~pg-token-input").type(token);
4
+ }
@@ -1,4 +1,4 @@
1
- export default async function fillCredentials(this: any, email: string, token: string) {
2
- await this.get("#demo-email-input-pg").type(email);
3
- await this.get("#demo-token-input-pg").type(token);
4
- }
1
+ export default async function (this: any, email: string, token: string) {
2
+ await this.get("#demo-email-input-pg").type(email);
3
+ await this.get("#demo-token-input-pg").type(token);
4
+ }
@@ -0,0 +1,9 @@
1
+ export default async function (this: any) {
2
+ // Android has no cookie jar to write into — the deep link asks the app to log itself in
3
+ // (a known, sanctioned test account, server-side) and persist the result through its own
4
+ // secure storage (e.g. react-native-keychain), the same way a real login would. See
5
+ // docs/v2/features/authentication-and-session-seeding.md for why this doesn't accept an
6
+ // externally-supplied session value the way the web action does.
7
+ await this.navigate("testspectra-demo://seed-session");
8
+ await this.get("~auth-status-badge").waitForElement(10000);
9
+ }
@@ -0,0 +1,13 @@
1
+ export default async function (this: any) {
2
+ // Host-side (Bun) fetch — not the browser's — so there's no CORS/credentials restriction on
3
+ // reading the raw Set-Cookie header, HttpOnly included.
4
+ const res = await fetch("http://localhost:5200/api/login", {
5
+ method: "POST",
6
+ headers: { "content-type": "application/json" },
7
+ body: JSON.stringify({ email: "demo@testspectra.dev", password: "demo-password" }),
8
+ });
9
+ if (!res.ok) {
10
+ throw new Error(`seedSession: login failed (${res.status})`);
11
+ }
12
+ await this.browser.setCookies(res.headers.getSetCookie(), res.url);
13
+ }
@@ -1,5 +1,5 @@
1
- export default async function togglePlaygroundStates() {
2
- await PlaygroundPage.open();
3
- await PlaygroundPage.hiddenElement.shouldBeVisible();
4
- await PlaygroundPage.existingElement.shouldExist();
5
- }
1
+ export default async function () {
2
+ await PlaygroundPage.open();
3
+ await PlaygroundPage.hiddenElement.shouldBeVisible();
4
+ await PlaygroundPage.existingElement.shouldExist();
5
+ }
@@ -1,5 +1,5 @@
1
- export default async function togglePlaygroundStates() {
2
- await PlaygroundPage.open();
3
- await PlaygroundPage.hiddenElement.shouldBeVisible();
4
- await PlaygroundPage.existingElement.shouldExist();
5
- }
1
+ export default async function () {
2
+ await PlaygroundPage.open();
3
+ await PlaygroundPage.hiddenElement.shouldBeVisible();
4
+ await PlaygroundPage.existingElement.shouldExist();
5
+ }
@@ -1,6 +1,6 @@
1
- export default async function verifyPlaygroundState() {
2
- await PlaygroundPage.open();
3
- await PlaygroundPage.visibleElement.shouldBeVisible();
4
- await PlaygroundPage.enabledButton.shouldBeEnabled();
5
- await PlaygroundPage.termsCheckbox.shouldBeChecked();
6
- }
1
+ export default async function () {
2
+ await PlaygroundPage.open();
3
+ await PlaygroundPage.visibleElement.shouldBeVisible();
4
+ await PlaygroundPage.enabledButton.shouldBeEnabled();
5
+ await PlaygroundPage.termsCheckbox.shouldBeChecked();
6
+ }
@@ -1,6 +1,6 @@
1
- export default async function verifyPlaygroundState() {
2
- await PlaygroundPage.open();
3
- await PlaygroundPage.visibleElement.shouldBeVisible();
4
- await PlaygroundPage.enabledButton.shouldBeEnabled();
5
- await PlaygroundPage.termsCheckbox.shouldBeChecked();
6
- }
1
+ export default async function () {
2
+ await PlaygroundPage.open();
3
+ await PlaygroundPage.visibleElement.shouldBeVisible();
4
+ await PlaygroundPage.enabledButton.shouldBeEnabled();
5
+ await PlaygroundPage.termsCheckbox.shouldBeChecked();
6
+ }