@sun-asterisk/sungen 3.2.0-beta.141 → 3.2.0-beta.143

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 (242) hide show
  1. package/dist/capabilities/context-router.d.ts +11 -2
  2. package/dist/capabilities/context-router.d.ts.map +1 -1
  3. package/dist/capabilities/context-router.js +10 -3
  4. package/dist/capabilities/context-router.js.map +1 -1
  5. package/dist/capabilities/discover.js +1 -1
  6. package/dist/capabilities/discover.js.map +1 -1
  7. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts +54 -0
  8. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts.map +1 -0
  9. package/dist/generators/test-generator/adapters/appium/appium-adapter.js +52 -0
  10. package/dist/generators/test-generator/adapters/appium/appium-adapter.js.map +1 -0
  11. package/dist/generators/test-generator/adapters/appium/templates/after-all.hbs +8 -0
  12. package/dist/generators/test-generator/adapters/appium/templates/after-each.hbs +8 -0
  13. package/dist/generators/test-generator/adapters/appium/templates/before-all.hbs +8 -0
  14. package/dist/generators/test-generator/adapters/appium/templates/before-each.hbs +8 -0
  15. package/dist/generators/test-generator/adapters/appium/templates/imports.hbs +8 -0
  16. package/dist/generators/test-generator/adapters/appium/templates/scenario.hbs +8 -0
  17. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/alert-accept-action.hbs +4 -0
  18. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/alert-dismiss-action.hbs +2 -0
  19. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs +2 -0
  20. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/check-action.hbs +10 -0
  21. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/clear-action.hbs +1 -0
  22. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-action.hbs +1 -0
  23. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +2 -0
  24. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-select-action.hbs +4 -0
  25. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/dismiss-action.hbs +3 -0
  26. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +6 -0
  27. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/drag-action.hbs +2 -0
  28. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/expand-action.hbs +2 -0
  29. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/fill-action.hbs +14 -0
  30. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/fill-editor-action.hbs +12 -0
  31. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +6 -0
  32. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/frame-exit-action.hbs +2 -0
  33. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hide-keyboard-action.hbs +4 -0
  34. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs +2 -0
  35. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/keyboard-global-action.hbs +2 -0
  36. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/press-action.hbs +4 -0
  37. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/radio-select-action.hbs +4 -0
  38. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/scroll-action.hbs +19 -0
  39. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/select-action.hbs +5 -0
  40. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/table-action-in-row.hbs +2 -0
  41. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/toggle-action.hbs +3 -0
  42. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/uncheck-action.hbs +8 -0
  43. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/unknown-element-action.hbs +2 -0
  44. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/upload-action.hbs +3 -0
  45. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/wait-for-page.hbs +3 -0
  46. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/wait-for-role-with-data.hbs +2 -0
  47. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/wait-for-role.hbs +3 -0
  48. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/alert-text-assertion.hbs +2 -0
  49. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/attribute-assertion.hbs +1 -0
  50. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/checked-assertion.hbs +1 -0
  51. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/clipboard-text-assertion.hbs +2 -0
  52. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/column-cell-assertion.hbs +2 -0
  53. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/contain-text-assertion.hbs +14 -0
  54. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/count-assertion.hbs +1 -0
  55. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/disabled-assertion.hbs +1 -0
  56. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/empty-assertion.hbs +1 -0
  57. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/enabled-assertion.hbs +1 -0
  58. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/focused-assertion.hbs +1 -0
  59. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/have-text-assertion.hbs +15 -0
  60. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +1 -0
  61. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/is-hidden-assertion.hbs +1 -0
  62. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +12 -0
  63. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/list-item-count-assertion.hbs +2 -0
  64. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/loading-assertion.hbs +2 -0
  65. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/not-checked-assertion.hbs +1 -0
  66. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/page-assertion.hbs +1 -0
  67. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/route-assertion.hbs +2 -0
  68. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/selected-assertion.hbs +1 -0
  69. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/sorted-assertion.hbs +2 -0
  70. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/table-column-exists.hbs +2 -0
  71. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/table-empty.hbs +2 -0
  72. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/table-match-data.hbs +2 -0
  73. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/table-row-count.hbs +2 -0
  74. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/table-row-exists.hbs +2 -0
  75. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/table-row-not-exists.hbs +2 -0
  76. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -0
  77. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/background-action.hbs +1 -0
  78. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/grant-permission-action.hbs +11 -0
  79. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +5 -0
  80. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/open-notifications-action.hbs +3 -0
  81. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +5 -0
  82. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/pull-to-refresh-action.hbs +5 -0
  83. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/rotate-action.hbs +1 -0
  84. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/set-clipboard-action.hbs +2 -0
  85. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/set-geolocation-action.hbs +2 -0
  86. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/swipe-action.hbs +5 -0
  87. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/tap-top-action.hbs +24 -0
  88. package/dist/generators/test-generator/adapters/appium/templates/steps/navigation/navigation.hbs +1 -0
  89. package/dist/generators/test-generator/adapters/appium/templates/steps/navigation/wait-for-element-with-text.hbs +1 -0
  90. package/dist/generators/test-generator/adapters/appium/templates/steps/navigation/wait-for-element.hbs +1 -0
  91. package/dist/generators/test-generator/adapters/appium/templates/steps/navigation/wait-timeout.hbs +1 -0
  92. package/dist/generators/test-generator/adapters/appium/templates/steps/partials/appium-selector-expr.hbs +8 -0
  93. package/dist/generators/test-generator/adapters/appium/templates/steps/partials/appium-selector.hbs +15 -0
  94. package/dist/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +8 -0
  95. package/dist/generators/test-generator/adapters/appium/templates/steps/setup/application-running.hbs +1 -0
  96. package/dist/generators/test-generator/adapters/appium/templates/steps/setup/clear-auth.hbs +2 -0
  97. package/dist/generators/test-generator/adapters/appium/templates/steps/setup/clear-browser-state.hbs +1 -0
  98. package/dist/generators/test-generator/adapters/appium/templates/steps/setup/clear-database.hbs +1 -0
  99. package/dist/generators/test-generator/adapters/appium/templates/steps/setup/user-login-todo.hbs +2 -0
  100. package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +226 -0
  101. package/dist/generators/test-generator/adapters/index.d.ts +1 -0
  102. package/dist/generators/test-generator/adapters/index.d.ts.map +1 -1
  103. package/dist/generators/test-generator/adapters/index.js +9 -1
  104. package/dist/generators/test-generator/adapters/index.js.map +1 -1
  105. package/dist/generators/test-generator/step-mapper.d.ts +1 -0
  106. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  107. package/dist/generators/test-generator/step-mapper.js +7 -37
  108. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  109. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  110. package/dist/generators/test-generator/template-engine.js +13 -1
  111. package/dist/generators/test-generator/template-engine.js.map +1 -1
  112. package/dist/harness/audit.d.ts +1 -1
  113. package/dist/harness/audit.d.ts.map +1 -1
  114. package/dist/harness/audit.js +14 -4
  115. package/dist/harness/audit.js.map +1 -1
  116. package/dist/harness/catalog/drivers.yaml +1 -1
  117. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  118. package/dist/orchestrator/ai-rules-updater.js +8 -0
  119. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  120. package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-mobile.md +184 -0
  121. package/dist/orchestrator/templates/ai-instructions/claude-skill-mobile-gestures.md +109 -0
  122. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix-mobile.md +316 -0
  123. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mobile.md +184 -0
  124. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-mobile-gestures.md +109 -0
  125. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix-mobile.md +316 -0
  126. package/dist/orchestrator/templates/env.appium.example +25 -0
  127. package/dist/orchestrator/templates/specs-pw-shape-reporter.ts +92 -0
  128. package/dist/orchestrator/templates/wdio.conf.ts +295 -0
  129. package/dist/utils/selector-types.d.ts +1 -1
  130. package/dist/utils/selector-types.d.ts.map +1 -1
  131. package/dist/utils/selector-types.js +5 -0
  132. package/dist/utils/selector-types.js.map +1 -1
  133. package/package.json +3 -3
  134. package/src/capabilities/context-router.ts +15 -3
  135. package/src/capabilities/discover.ts +1 -1
  136. package/src/generators/test-generator/adapters/appium/appium-adapter.ts +57 -0
  137. package/src/generators/test-generator/adapters/appium/templates/after-all.hbs +8 -0
  138. package/src/generators/test-generator/adapters/appium/templates/after-each.hbs +8 -0
  139. package/src/generators/test-generator/adapters/appium/templates/before-all.hbs +8 -0
  140. package/src/generators/test-generator/adapters/appium/templates/before-each.hbs +8 -0
  141. package/src/generators/test-generator/adapters/appium/templates/imports.hbs +8 -0
  142. package/src/generators/test-generator/adapters/appium/templates/scenario.hbs +8 -0
  143. package/src/generators/test-generator/adapters/appium/templates/steps/actions/alert-accept-action.hbs +4 -0
  144. package/src/generators/test-generator/adapters/appium/templates/steps/actions/alert-dismiss-action.hbs +2 -0
  145. package/src/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs +2 -0
  146. package/src/generators/test-generator/adapters/appium/templates/steps/actions/check-action.hbs +10 -0
  147. package/src/generators/test-generator/adapters/appium/templates/steps/actions/clear-action.hbs +1 -0
  148. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-action.hbs +1 -0
  149. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +2 -0
  150. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-select-action.hbs +4 -0
  151. package/src/generators/test-generator/adapters/appium/templates/steps/actions/dismiss-action.hbs +3 -0
  152. package/src/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +6 -0
  153. package/src/generators/test-generator/adapters/appium/templates/steps/actions/drag-action.hbs +2 -0
  154. package/src/generators/test-generator/adapters/appium/templates/steps/actions/expand-action.hbs +2 -0
  155. package/src/generators/test-generator/adapters/appium/templates/steps/actions/fill-action.hbs +14 -0
  156. package/src/generators/test-generator/adapters/appium/templates/steps/actions/fill-editor-action.hbs +12 -0
  157. package/src/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +6 -0
  158. package/src/generators/test-generator/adapters/appium/templates/steps/actions/frame-exit-action.hbs +2 -0
  159. package/src/generators/test-generator/adapters/appium/templates/steps/actions/hide-keyboard-action.hbs +4 -0
  160. package/src/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs +2 -0
  161. package/src/generators/test-generator/adapters/appium/templates/steps/actions/keyboard-global-action.hbs +2 -0
  162. package/src/generators/test-generator/adapters/appium/templates/steps/actions/press-action.hbs +4 -0
  163. package/src/generators/test-generator/adapters/appium/templates/steps/actions/radio-select-action.hbs +4 -0
  164. package/src/generators/test-generator/adapters/appium/templates/steps/actions/scroll-action.hbs +19 -0
  165. package/src/generators/test-generator/adapters/appium/templates/steps/actions/select-action.hbs +5 -0
  166. package/src/generators/test-generator/adapters/appium/templates/steps/actions/table-action-in-row.hbs +2 -0
  167. package/src/generators/test-generator/adapters/appium/templates/steps/actions/toggle-action.hbs +3 -0
  168. package/src/generators/test-generator/adapters/appium/templates/steps/actions/uncheck-action.hbs +8 -0
  169. package/src/generators/test-generator/adapters/appium/templates/steps/actions/unknown-element-action.hbs +2 -0
  170. package/src/generators/test-generator/adapters/appium/templates/steps/actions/upload-action.hbs +3 -0
  171. package/src/generators/test-generator/adapters/appium/templates/steps/actions/wait-for-page.hbs +3 -0
  172. package/src/generators/test-generator/adapters/appium/templates/steps/actions/wait-for-role-with-data.hbs +2 -0
  173. package/src/generators/test-generator/adapters/appium/templates/steps/actions/wait-for-role.hbs +3 -0
  174. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/alert-text-assertion.hbs +2 -0
  175. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/attribute-assertion.hbs +1 -0
  176. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/checked-assertion.hbs +1 -0
  177. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/clipboard-text-assertion.hbs +2 -0
  178. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/column-cell-assertion.hbs +2 -0
  179. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/contain-text-assertion.hbs +14 -0
  180. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/count-assertion.hbs +1 -0
  181. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/disabled-assertion.hbs +1 -0
  182. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/empty-assertion.hbs +1 -0
  183. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/enabled-assertion.hbs +1 -0
  184. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/focused-assertion.hbs +1 -0
  185. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/have-text-assertion.hbs +15 -0
  186. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +1 -0
  187. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/is-hidden-assertion.hbs +1 -0
  188. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +12 -0
  189. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/list-item-count-assertion.hbs +2 -0
  190. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/loading-assertion.hbs +2 -0
  191. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/not-checked-assertion.hbs +1 -0
  192. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/page-assertion.hbs +1 -0
  193. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/route-assertion.hbs +2 -0
  194. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/selected-assertion.hbs +1 -0
  195. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/sorted-assertion.hbs +2 -0
  196. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/table-column-exists.hbs +2 -0
  197. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/table-empty.hbs +2 -0
  198. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/table-match-data.hbs +2 -0
  199. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/table-row-count.hbs +2 -0
  200. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/table-row-exists.hbs +2 -0
  201. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/table-row-not-exists.hbs +2 -0
  202. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -0
  203. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/background-action.hbs +1 -0
  204. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/grant-permission-action.hbs +11 -0
  205. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +5 -0
  206. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/open-notifications-action.hbs +3 -0
  207. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +5 -0
  208. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/pull-to-refresh-action.hbs +5 -0
  209. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/rotate-action.hbs +1 -0
  210. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/set-clipboard-action.hbs +2 -0
  211. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/set-geolocation-action.hbs +2 -0
  212. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/swipe-action.hbs +5 -0
  213. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/tap-top-action.hbs +24 -0
  214. package/src/generators/test-generator/adapters/appium/templates/steps/navigation/navigation.hbs +1 -0
  215. package/src/generators/test-generator/adapters/appium/templates/steps/navigation/wait-for-element-with-text.hbs +1 -0
  216. package/src/generators/test-generator/adapters/appium/templates/steps/navigation/wait-for-element.hbs +1 -0
  217. package/src/generators/test-generator/adapters/appium/templates/steps/navigation/wait-timeout.hbs +1 -0
  218. package/src/generators/test-generator/adapters/appium/templates/steps/partials/appium-selector-expr.hbs +8 -0
  219. package/src/generators/test-generator/adapters/appium/templates/steps/partials/appium-selector.hbs +15 -0
  220. package/src/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +8 -0
  221. package/src/generators/test-generator/adapters/appium/templates/steps/setup/application-running.hbs +1 -0
  222. package/src/generators/test-generator/adapters/appium/templates/steps/setup/clear-auth.hbs +2 -0
  223. package/src/generators/test-generator/adapters/appium/templates/steps/setup/clear-browser-state.hbs +1 -0
  224. package/src/generators/test-generator/adapters/appium/templates/steps/setup/clear-database.hbs +1 -0
  225. package/src/generators/test-generator/adapters/appium/templates/steps/setup/user-login-todo.hbs +2 -0
  226. package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +226 -0
  227. package/src/generators/test-generator/adapters/index.ts +7 -0
  228. package/src/generators/test-generator/step-mapper.ts +8 -5
  229. package/src/generators/test-generator/template-engine.ts +13 -1
  230. package/src/harness/audit.ts +12 -4
  231. package/src/harness/catalog/drivers.yaml +1 -1
  232. package/src/orchestrator/ai-rules-updater.ts +8 -0
  233. package/src/orchestrator/templates/ai-instructions/claude-skill-capture-mobile.md +184 -0
  234. package/src/orchestrator/templates/ai-instructions/claude-skill-mobile-gestures.md +109 -0
  235. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix-mobile.md +316 -0
  236. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-mobile.md +184 -0
  237. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-mobile-gestures.md +109 -0
  238. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix-mobile.md +316 -0
  239. package/src/orchestrator/templates/env.appium.example +25 -0
  240. package/src/orchestrator/templates/specs-pw-shape-reporter.ts +92 -0
  241. package/src/orchestrator/templates/wdio.conf.ts +295 -0
  242. package/src/utils/selector-types.ts +5 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * WebdriverIO runner config for sungen mobile (Appium) tests.
3
+ * Mobile equivalent of playwright.config.ts. Run with: npm run test:mobile
4
+ *
5
+ * Capabilities default to the app configured at `sungen init --mobile`, but every value can be
6
+ * overridden at runtime via env vars — no need to edit this file to target another app/device:
7
+ * APP_PACKAGE=com.other.app ANDROID_UDID=emulator-5556 npm run test:mobile
8
+ * (the launch activity is auto-detected from APP_PACKAGE; set APP_ACTIVITY only to pin a non-standard one)
9
+ * APP_APK=/path/to/app.apk npm run test:mobile # install + run from an .apk (Appium derives pkg/activity)
10
+ *
11
+ * iOS Simulator (opt in with MOBILE_PLATFORM=ios; needs Xcode + the xcuitest driver):
12
+ * MOBILE_PLATFORM=ios IOS_BUNDLE_ID=com.example.app npm run test:mobile # app already installed on the sim
13
+ * MOBILE_PLATFORM=ios IOS_APP=/path/MyApp.app npm run test:mobile # Appium installs a Simulator build
14
+ * (+ optional IOS_DEVICE='iPhone 16' IOS_VERSION='18.0' IOS_UDID=<sim-udid>)
15
+ *
16
+ * The @wdio/appium-service auto-starts a local Appium server (auto-detecting the uiautomator2 / xcuitest driver).
17
+ */
18
+ /// <reference types="node" />
19
+ /// <reference types="@wdio/globals/types" />
20
+ // Load .env.appium (if present) into process.env FIRST — so every override below (ANDROID_HOME / JAVA_HOME /
21
+ // ANDROID_UDID / APP_PACKAGE / IOS_BUNDLE_ID / MOBILE_PLATFORM / SUNGEN_ENV …) can come from a dedicated
22
+ // .env.appium file instead of shell exports. A separate file (not the generic .env) keeps Appium config from
23
+ // clashing with other .env vars (e.g. FIGMA_PAT). dotenv is a dependency; a missing .env.appium is a no-op.
24
+ import dotenv from 'dotenv';
25
+ dotenv.config({ path: '.env.appium' });
26
+ import * as fs from 'node:fs';
27
+ import * as path from 'node:path';
28
+ import PwShapeReporter from './specs/reporters/pw-shape-reporter';
29
+
30
+ /**
31
+ * Auto-select MOBILE specs and classify each by its target OS (dual-target routing).
32
+ *
33
+ * sungen emits one spec per feature; the test runner differs by platform:
34
+ * - mobile/appium specs import from '@wdio/globals' ← run these with wdio
35
+ * - web/playwright specs import from '@playwright/test' ← run those with `playwright test`
36
+ * The '@wdio/globals' import is the machine-readable "platform = mobile" marker, so we keep
37
+ * only those files and never feed Playwright specs into the (incompatible) mocha runner.
38
+ *
39
+ * Each mobile spec also carries a `// sungen:platform=<mobile|android|ios>` marker (emitted from the
40
+ * feature's @platform:* tag). It routes the spec per OS:
41
+ * - mobile → cross-platform: runs on BOTH the Android and iOS capability sets
42
+ * - android → Android cap only
43
+ * - ios → iOS cap only
44
+ * A spec with no marker (older codegen) defaults to `mobile` (runs on both) so nothing is dropped.
45
+ *
46
+ * Override with SUNGEN_SPECS=<glob-or-path> for a single spec (still classified by its marker).
47
+ */
48
+ function readPlatformMarker(file: string): 'mobile' | 'android' | 'ios' {
49
+ try {
50
+ const m = /sungen:platform=(mobile|android|ios)/.exec(fs.readFileSync(file, 'utf-8'));
51
+ return (m?.[1] as 'mobile' | 'android' | 'ios') || 'mobile';
52
+ } catch {
53
+ return 'mobile';
54
+ }
55
+ }
56
+ function classifyMobileSpecs(root: string): Array<{ file: string; platform: string }> {
57
+ if (!fs.existsSync(root)) return [];
58
+ return (fs.readdirSync(root, { recursive: true }) as string[])
59
+ .filter((rel) => rel.endsWith('.spec.ts'))
60
+ .map((rel) => path.join(root, rel))
61
+ .filter((full) => {
62
+ try {
63
+ return fs.readFileSync(full, 'utf-8').includes('@wdio/globals');
64
+ } catch {
65
+ return false;
66
+ }
67
+ })
68
+ .map((file) => ({ file, platform: readPlatformMarker(file) }));
69
+ }
70
+
71
+ const specEntries = process.env.SUNGEN_SPECS
72
+ ? [process.env.SUNGEN_SPECS].map((file) => ({ file, platform: readPlatformMarker(file) }))
73
+ : classifyMobileSpecs(path.join(process.cwd(), 'specs', 'generated'));
74
+
75
+ // Android cap runs android + mobile (everything except ios-only); iOS cap runs ios + mobile.
76
+ const androidSpecs = specEntries.filter((e) => e.platform !== 'ios').map((e) => e.file);
77
+ const iosSpecs = specEntries.filter((e) => e.platform !== 'android').map((e) => e.file);
78
+ const mobileSpecs = specEntries.map((e) => e.file); // union — top-level fallback
79
+
80
+ // App under test — env overrides the init-configured defaults.
81
+ const APP_PACKAGE = process.env.APP_PACKAGE || '__APP_PACKAGE__';
82
+ const APP_ACTIVITY = process.env.APP_ACTIVITY || '__APP_ACTIVITY__';
83
+ const APP_APK = process.env.APP_APK; // optional: install + launch from an .apk file
84
+ // appActivity is OPTIONAL: UiAutomator2 auto-resolves the package's launcher activity when it's
85
+ // omitted, and the per-scenario relaunch uses activateApp(package) (no activity). So Android needs
86
+ // only APP_PACKAGE — set APP_ACTIVITY only to pin a non-standard launcher. iOS has no activity
87
+ // concept at all (bundleId only). Only pass the cap when APP_ACTIVITY is a real value (not the
88
+ // unfilled scaffold placeholder / empty), so a package-only setup launches cleanly.
89
+ const HAS_REAL_APP_ACTIVITY = !!APP_ACTIVITY && APP_ACTIVITY !== '__APP_ACTIVITY__';
90
+
91
+ // ── iOS (Simulator) — opt in with MOBILE_PLATFORM=ios; every value is env-overridable ──────────
92
+ // MOBILE_PLATFORM=ios IOS_BUNDLE_ID=com.example.app npm run test:mobile
93
+ // - IOS_APP=/path/MyApp.app → Appium installs a SIMULATOR build (.app or zipped .app) first.
94
+ // (A device .ipa won't run on a Simulator — wrong binary/platform.)
95
+ // - IOS_BUNDLE_ID=com.x → attach to an app already installed on the sim (simctl install first).
96
+ // - IOS_DEVICE / IOS_VERSION → pick the simulator; IOS_UDID targets a specific one.
97
+ //
98
+ // MOBILE_PLATFORM selects which capability set(s) run:
99
+ // android (default) → Android cap only (runs @platform:android + @platform:mobile specs)
100
+ // ios → iOS cap only (runs @platform:ios + @platform:mobile specs)
101
+ // both → BOTH caps in one run (a @platform:mobile spec executes on each — write once, run both)
102
+ const MOBILE_PLATFORM = (process.env.MOBILE_PLATFORM || 'android').toLowerCase();
103
+ const RUN_ANDROID = MOBILE_PLATFORM === 'android' || MOBILE_PLATFORM === 'both';
104
+ const RUN_IOS = MOBILE_PLATFORM === 'ios' || MOBILE_PLATFORM === 'both';
105
+ const IOS_APP = process.env.IOS_APP;
106
+ const IOS_BUNDLE_ID = process.env.IOS_BUNDLE_ID || '__IOS_BUNDLE_ID__';
107
+ const IOS_DEVICE = process.env.IOS_DEVICE || '__IOS_DEVICE__';
108
+ const IOS_VERSION = process.env.IOS_VERSION || '__IOS_VERSION__';
109
+ // platformVersion is OPTIONAL on a real device: with IOS_UDID set, XCUITest reads the iOS version off
110
+ // the connected device. Only pass the cap when IOS_VERSION is a real value (not the unfilled scaffold
111
+ // placeholder). On a Simulator set it (or IOS_DEVICE) so Appium picks a matching runtime.
112
+ const HAS_REAL_IOS_VERSION = !!IOS_VERSION && IOS_VERSION !== '__IOS_VERSION__';
113
+ const IOS_UDID = process.env.IOS_UDID;
114
+ // Real iPhone (device) — WebDriverAgent must be code-signed onto it. Set IOS_TEAM_ID (your Apple
115
+ // Team ID) to switch the iOS cap into real-device mode; the Simulator ignores these (they're only
116
+ // emitted when IOS_TEAM_ID is present, so Simulator runs are unchanged). For a real device also set
117
+ // IOS_UDID (the device udid, NOT a sim) and the REAL IOS_BUNDLE_ID (Android package ≠ iOS bundle id).
118
+ const IOS_TEAM_ID = process.env.IOS_TEAM_ID; // → appium:xcodeOrgId
119
+ const IOS_SIGNING_ID = process.env.IOS_SIGNING_ID || 'Apple Development'; // → appium:xcodeSigningId
120
+ const IOS_WDA_BUNDLE_ID = process.env.IOS_WDA_BUNDLE_ID || 'com.sungen.wda'; // → appium:updatedWDABundleId; default gives WDA a unique id (required for free teams) so you needn't set it
121
+
122
+ // ── i18n (device locale) ────────────────────────────────────────────────────
123
+ // SUNGEN_ENV doubles as the locale selector (the same var that swaps the test-data overlay).
124
+ // When its value looks like a locale code ("vi", "ja", "vi-VN"), drive the DEVICE locale via
125
+ // appium:language/appium:locale so an app that localizes from device locale on first launch picks
126
+ // it up, and force a data reset (noReset:false) so that first-launch path actually re-runs (clears
127
+ // any persisted in-app language override). Non-locale envs ("staging", "production") are left
128
+ // untouched, so existing suites are unaffected. SUNGEN_LOCALE overrides explicitly when the device
129
+ // locale must differ from the overlay name. Country defaults are used only when the code omits a region.
130
+ const LOCALE_COUNTRY: Record<string, string> = {
131
+ vi: 'VN',
132
+ ja: 'JP',
133
+ en: 'US',
134
+ ko: 'KR',
135
+ zh: 'CN',
136
+ th: 'TH',
137
+ id: 'ID',
138
+ fr: 'FR',
139
+ de: 'DE',
140
+ es: 'ES',
141
+ pt: 'BR',
142
+ ru: 'RU',
143
+ };
144
+ function resolveLocaleCaps(): Record<string, unknown> {
145
+ const raw = process.env.SUNGEN_LOCALE || process.env.SUNGEN_ENV;
146
+ if (!raw) return {};
147
+ const m = /^([a-z]{2})(?:[-_]([A-Za-z]{2}))?$/.exec(raw.trim());
148
+ if (!m) return {}; // not a locale code (e.g. "staging") → don't touch the device locale
149
+ const language = m[1];
150
+ const country = (m[2] || LOCALE_COUNTRY[language] || language).toUpperCase();
151
+ return {
152
+ 'appium:language': language,
153
+ 'appium:locale': country,
154
+ 'appium:noReset': false,
155
+ };
156
+ }
157
+ const localeCaps = resolveLocaleCaps();
158
+
159
+ export const config: WebdriverIO.Config = {
160
+ runner: 'local',
161
+ tsConfigPath: './tsconfig.json',
162
+
163
+ specs: mobileSpecs,
164
+ // SUNGEN_MAX_INSTANCES=2 lets a MOBILE_PLATFORM=both run execute the Android and iOS capability
165
+ // in PARALLEL (separate devices; uiautomator2/XCUITest do not share ports; the reporter writes
166
+ // per-platform files so results cannot collide). Default stays 1 — serial is the safe choice on
167
+ // a laptop driving an emulator + a simulator at once.
168
+ maxInstances: Number(process.env.SUNGEN_MAX_INSTANCES || 1),
169
+
170
+ // Global auto-wait for $/$$ matchers (toBeDisplayed, click, …). Default is 3s, too short for a
171
+ // heavy app's cold (re)launch — each scenario terminates+activates its app, so the first
172
+ // find/click must wait out the splash/first-frame. 20s keeps slow native/Flutter apps green.
173
+ waitforTimeout: 20000,
174
+
175
+ // Capability set(s) selected by MOBILE_PLATFORM (android | ios | both). Each cap carries its OWN
176
+ // `specs` (per-OS routing): the Android cap runs android + mobile specs, the iOS cap runs ios +
177
+ // mobile specs, so MOBILE_PLATFORM=both executes a @platform:mobile spec on each in a single run.
178
+ // i18n localeCaps (appium:language/locale + noReset:false) apply to both when SUNGEN_ENV is a locale.
179
+ capabilities: [
180
+ ...(RUN_ANDROID
181
+ ? [
182
+ {
183
+ platformName: 'Android',
184
+ 'appium:automationName': 'UiAutomator2',
185
+ 'appium:udid': process.env.ANDROID_UDID || '__ANDROID_UDID__',
186
+ // APP_APK installs from a file (Appium reads pkg/activity from the manifest);
187
+ // otherwise target an already-installed app by package + activity.
188
+ ...(APP_APK
189
+ ? { 'appium:app': APP_APK }
190
+ : {
191
+ 'appium:appPackage': APP_PACKAGE,
192
+ // Omit when unset → UiAutomator2 launches the package's default launcher activity.
193
+ ...(HAS_REAL_APP_ACTIVITY ? { 'appium:appActivity': APP_ACTIVITY } : {}),
194
+ }),
195
+ 'appium:noReset': true,
196
+ 'appium:autoGrantPermissions': true,
197
+ 'appium:newCommandTimeout': 300,
198
+ // i18n: when SUNGEN_ENV/SUNGEN_LOCALE is a locale code, this overrides noReset→false and
199
+ // adds appium:language/appium:locale so the app boots in that locale. Empty otherwise.
200
+ ...localeCaps,
201
+ // Per-capability spec routing (supported by WDIO at runtime; not in the TS cap type → cast).
202
+ specs: androidSpecs,
203
+ } as any,
204
+ ]
205
+ : []),
206
+ ...(RUN_IOS
207
+ ? [
208
+ {
209
+ platformName: 'iOS',
210
+ 'appium:automationName': 'XCUITest',
211
+ 'appium:deviceName': IOS_DEVICE,
212
+ // Omit when unknown (real device, no IOS_VERSION) → XCUITest reads it from the device by udid.
213
+ ...(HAS_REAL_IOS_VERSION ? { 'appium:platformVersion': IOS_VERSION } : {}),
214
+ // target a specific simulator if given (else Appium uses the matching device/version)
215
+ ...(IOS_UDID ? { 'appium:udid': IOS_UDID } : {}),
216
+ // IOS_APP installs a Simulator build (.app/.zip); otherwise attach to an installed bundleId.
217
+ ...(IOS_APP
218
+ ? { 'appium:app': IOS_APP }
219
+ : IOS_BUNDLE_ID
220
+ ? { 'appium:bundleId': IOS_BUNDLE_ID }
221
+ : {}),
222
+ // Real-device WDA signing — emitted only when IOS_TEAM_ID is set (Simulator: omitted → unchanged).
223
+ ...(IOS_TEAM_ID
224
+ ? {
225
+ 'appium:xcodeOrgId': IOS_TEAM_ID,
226
+ 'appium:xcodeSigningId': IOS_SIGNING_ID,
227
+ // Pass -allowProvisioningUpdates -allowProvisioningDeviceRegistration to xcodebuild so it
228
+ // auto-creates/refreshes the WDA profile + registers the device (needed for automatic
229
+ // signing on a real device; without it WDA build fails fast with "xcodebuild code 65").
230
+ 'appium:allowProvisioningDeviceRegistration': true,
231
+ ...(IOS_WDA_BUNDLE_ID ? { 'appium:updatedWDABundleId': IOS_WDA_BUNDLE_ID } : {}),
232
+ }
233
+ : {}),
234
+ 'appium:noReset': true,
235
+ 'appium:newCommandTimeout': 300,
236
+ ...localeCaps,
237
+ specs: iosSpecs,
238
+ } as any,
239
+ ]
240
+ : []),
241
+ ],
242
+
243
+ logLevel: 'warn',
244
+ framework: 'mocha',
245
+ // 'spec' for console + PwShapeReporter for a Playwright-shaped JSON the delivery/dashboard reuse.
246
+ reporters: ['spec', [PwShapeReporter, {}]],
247
+
248
+ // Auto-start a local Appium server on :4723 (base path '/')
249
+ services: ['appium'],
250
+ port: 4723,
251
+ path: '/',
252
+
253
+ mochaOpts: {
254
+ ui: 'bdd',
255
+ timeout: 120000,
256
+ },
257
+
258
+ // iOS + locale: XCUITest's `noReset:false` does NOT actually clear the app's data container
259
+ // (verified live 2026-06-11) — a Flutter app that persisted its language on a previous launch keeps
260
+ // it and ignores the new device locale, so the i18n run asserts the wrong language. Wipe the app
261
+ // data via simctl BEFORE the session so first-launch locale detection re-runs. Android needs no
262
+ // hook (its noReset:false reset works natively).
263
+ beforeSession: async (_config, capabilities) => {
264
+ if (Object.keys(localeCaps).length === 0) return; // not a locale run
265
+ const caps = capabilities as Record<string, unknown>;
266
+ if (String(caps['platformName'] || '').toLowerCase() !== 'ios') return;
267
+ const { execSync } = await import('node:child_process');
268
+ const fsm = await import('node:fs');
269
+ const udid = (caps['appium:udid'] as string) || 'booted';
270
+ // Wipe the session-default app AND every per-feature dual-id bundle the worker's specs declare
271
+ // (__IOS_BUNDLE__ markers) — a multi-app iOS locale run must reset each app, not just the first.
272
+ const bundleIds = new Set<string>();
273
+ if (typeof caps['appium:bundleId'] === 'string') bundleIds.add(caps['appium:bundleId'] as string);
274
+ for (const spec of specs || []) {
275
+ try {
276
+ const src = fsm.readFileSync(String(spec).replace('file://', ''), 'utf-8');
277
+ const m = /__IOS_BUNDLE__ = '([^']+)'/.exec(src);
278
+ if (m) bundleIds.add(m[1]);
279
+ } catch { /* unreadable spec — skip */ }
280
+ }
281
+ for (const bundleId of bundleIds) {
282
+ try { execSync(`xcrun simctl terminate ${udid} ${bundleId}`, { stdio: 'ignore' }); } catch { /* not running */ }
283
+ try {
284
+ const dataDir = execSync(`xcrun simctl get_app_container ${udid} ${bundleId} data`).toString().trim();
285
+ if (dataDir) execSync(`rm -rf "${dataDir}/Library" "${dataDir}/Documents"`);
286
+ console.log(`[sungen] iOS locale run: wiped app data for ${bundleId} (first-launch locale re-detect)`);
287
+ } catch { /* app not installed yet */ }
288
+ }
289
+ },
290
+
291
+ // Per-scenario app reset lives in each generated spec's `beforeEach` (terminate+activate the app
292
+ // from that feature's `Path:`). One run can therefore host screens from different apps — each spec
293
+ // launches its own — so there's no single-app reset hook here. The capabilities above only bootstrap
294
+ // the session (default app / device); the real app per scenario comes from the spec.
295
+ };
@@ -15,6 +15,11 @@ export const VALID_SELECTOR_TYPES = [
15
15
  'upload',
16
16
  'frame',
17
17
  'table',
18
+ // === Mobile (Appium) strategies — resolved by the appium adapter (MOB-3) ===
19
+ 'accessibility-id', // cross-platform — Android content-desc / iOS accessibilityIdentifier
20
+ 'xpath', // cross-platform, last resort
21
+ 'android-uiautomator', // Android only — UiSelector expressions
22
+ 'ios-predicate', // iOS only — NSPredicate strings
18
23
  ] as const;
19
24
 
20
25
  export type SelectorType = (typeof VALID_SELECTOR_TYPES)[number];