@fluentui-react-native/desktop-driver 0.2.0

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 (235) hide show
  1. package/.cache/tsconfig.tsbuildinfo +1 -0
  2. package/AGENTS.md +68 -0
  3. package/CHANGELOG.md +16 -0
  4. package/PLAN.md +1394 -0
  5. package/README.md +223 -0
  6. package/SPEC.md +105 -0
  7. package/config/cli.cjs +8 -0
  8. package/jest.config.cjs +9 -0
  9. package/lib/agent/DesktopAgent.d.ts +56 -0
  10. package/lib/agent/DesktopAgent.d.ts.map +1 -0
  11. package/lib/agent/DesktopAgent.js +118 -0
  12. package/lib/agent/DesktopAgent.js.map +1 -0
  13. package/lib/agent/DesktopAgent.test.d.ts +2 -0
  14. package/lib/agent/DesktopAgent.test.d.ts.map +1 -0
  15. package/lib/agent/DesktopAgent.test.js +97 -0
  16. package/lib/agent/DesktopAgent.test.js.map +1 -0
  17. package/lib/agent/agent.contract.cjs +66 -0
  18. package/lib/agent/agent.contract.cjs.map +1 -0
  19. package/lib/agent/agent.contract.d.cts +2 -0
  20. package/lib/agent/agent.contract.d.cts.map +1 -0
  21. package/lib/agent/index.d.ts +3 -0
  22. package/lib/agent/index.d.ts.map +1 -0
  23. package/lib/agent/index.js +2 -0
  24. package/lib/agent/index.js.map +1 -0
  25. package/lib/artifacts/ArtifactManager.d.ts +13 -0
  26. package/lib/artifacts/ArtifactManager.d.ts.map +1 -0
  27. package/lib/artifacts/ArtifactManager.js +88 -0
  28. package/lib/artifacts/ArtifactManager.js.map +1 -0
  29. package/lib/artifacts/ArtifactManager.test.d.ts +2 -0
  30. package/lib/artifacts/ArtifactManager.test.d.ts.map +1 -0
  31. package/lib/artifacts/ArtifactManager.test.js +19 -0
  32. package/lib/artifacts/ArtifactManager.test.js.map +1 -0
  33. package/lib/artifacts/index.d.ts +2 -0
  34. package/lib/artifacts/index.d.ts.map +1 -0
  35. package/lib/artifacts/index.js +2 -0
  36. package/lib/artifacts/index.js.map +1 -0
  37. package/lib/authoring/index.d.ts +4 -0
  38. package/lib/authoring/index.d.ts.map +1 -0
  39. package/lib/authoring/index.js +2 -0
  40. package/lib/authoring/index.js.map +1 -0
  41. package/lib/authoring/results.d.ts +43 -0
  42. package/lib/authoring/results.d.ts.map +1 -0
  43. package/lib/authoring/results.js +2 -0
  44. package/lib/authoring/results.js.map +1 -0
  45. package/lib/authoring/storyTests.d.ts +81 -0
  46. package/lib/authoring/storyTests.d.ts.map +1 -0
  47. package/lib/authoring/storyTests.js +272 -0
  48. package/lib/authoring/storyTests.js.map +1 -0
  49. package/lib/authoring/storyTests.test.d.ts +2 -0
  50. package/lib/authoring/storyTests.test.d.ts.map +1 -0
  51. package/lib/authoring/storyTests.test.js +46 -0
  52. package/lib/authoring/storyTests.test.js.map +1 -0
  53. package/lib/cli/DesktopDriverCli.test.d.ts +2 -0
  54. package/lib/cli/DesktopDriverCli.test.d.ts.map +1 -0
  55. package/lib/cli/DesktopDriverCli.test.js +141 -0
  56. package/lib/cli/DesktopDriverCli.test.js.map +1 -0
  57. package/lib/cli/createDesktopDriverCommand.d.ts +8 -0
  58. package/lib/cli/createDesktopDriverCommand.d.ts.map +1 -0
  59. package/lib/cli/createDesktopDriverCommand.js +242 -0
  60. package/lib/cli/createDesktopDriverCommand.js.map +1 -0
  61. package/lib/cli/index.d.ts +3 -0
  62. package/lib/cli/index.d.ts.map +1 -0
  63. package/lib/cli/index.js +2 -0
  64. package/lib/cli/index.js.map +1 -0
  65. package/lib/client/DesktopDriverClient.d.ts +60 -0
  66. package/lib/client/DesktopDriverClient.d.ts.map +1 -0
  67. package/lib/client/DesktopDriverClient.js +155 -0
  68. package/lib/client/DesktopDriverClient.js.map +1 -0
  69. package/lib/client/index.d.ts +3 -0
  70. package/lib/client/index.d.ts.map +1 -0
  71. package/lib/client/index.js +2 -0
  72. package/lib/client/index.js.map +1 -0
  73. package/lib/host/types.d.ts +153 -0
  74. package/lib/host/types.d.ts.map +1 -0
  75. package/lib/host/types.js +2 -0
  76. package/lib/host/types.js.map +1 -0
  77. package/lib/hosts/fake/FakeDesktopHost.d.ts +72 -0
  78. package/lib/hosts/fake/FakeDesktopHost.d.ts.map +1 -0
  79. package/lib/hosts/fake/FakeDesktopHost.js +452 -0
  80. package/lib/hosts/fake/FakeDesktopHost.js.map +1 -0
  81. package/lib/index.d.ts +23 -0
  82. package/lib/index.d.ts.map +1 -0
  83. package/lib/index.js +11 -0
  84. package/lib/index.js.map +1 -0
  85. package/lib/protocol/actions.d.ts +11 -0
  86. package/lib/protocol/actions.d.ts.map +1 -0
  87. package/lib/protocol/actions.js +137 -0
  88. package/lib/protocol/actions.js.map +1 -0
  89. package/lib/protocol/capabilities.d.ts +11 -0
  90. package/lib/protocol/capabilities.d.ts.map +1 -0
  91. package/lib/protocol/capabilities.js +103 -0
  92. package/lib/protocol/capabilities.js.map +1 -0
  93. package/lib/protocol/constants.d.ts +2 -0
  94. package/lib/protocol/constants.d.ts.map +1 -0
  95. package/lib/protocol/constants.js +2 -0
  96. package/lib/protocol/constants.js.map +1 -0
  97. package/lib/protocol/errors.d.ts +37 -0
  98. package/lib/protocol/errors.d.ts.map +1 -0
  99. package/lib/protocol/errors.js +66 -0
  100. package/lib/protocol/errors.js.map +1 -0
  101. package/lib/protocol/timeouts.d.ts +2 -0
  102. package/lib/protocol/timeouts.d.ts.map +1 -0
  103. package/lib/protocol/timeouts.js +23 -0
  104. package/lib/protocol/timeouts.js.map +1 -0
  105. package/lib/protocol/types.d.ts +46 -0
  106. package/lib/protocol/types.d.ts.map +1 -0
  107. package/lib/protocol/types.js +2 -0
  108. package/lib/protocol/types.js.map +1 -0
  109. package/lib/runner/StoryTestRunner.d.ts +38 -0
  110. package/lib/runner/StoryTestRunner.d.ts.map +1 -0
  111. package/lib/runner/StoryTestRunner.js +497 -0
  112. package/lib/runner/StoryTestRunner.js.map +1 -0
  113. package/lib/runner/StoryTestRunner.test.d.ts +2 -0
  114. package/lib/runner/StoryTestRunner.test.d.ts.map +1 -0
  115. package/lib/runner/StoryTestRunner.test.js +349 -0
  116. package/lib/runner/StoryTestRunner.test.js.map +1 -0
  117. package/lib/runner/index.d.ts +3 -0
  118. package/lib/runner/index.d.ts.map +1 -0
  119. package/lib/runner/index.js +2 -0
  120. package/lib/runner/index.js.map +1 -0
  121. package/lib/server/SessionManager.d.ts +52 -0
  122. package/lib/server/SessionManager.d.ts.map +1 -0
  123. package/lib/server/SessionManager.js +208 -0
  124. package/lib/server/SessionManager.js.map +1 -0
  125. package/lib/server/TargetRegistry.d.ts +9 -0
  126. package/lib/server/TargetRegistry.d.ts.map +1 -0
  127. package/lib/server/TargetRegistry.js +24 -0
  128. package/lib/server/TargetRegistry.js.map +1 -0
  129. package/lib/server/createDesktopDriverServer.d.ts +19 -0
  130. package/lib/server/createDesktopDriverServer.d.ts.map +1 -0
  131. package/lib/server/createDesktopDriverServer.js +609 -0
  132. package/lib/server/createDesktopDriverServer.js.map +1 -0
  133. package/lib/server/desktopDriver.test.d.ts +2 -0
  134. package/lib/server/desktopDriver.test.d.ts.map +1 -0
  135. package/lib/server/desktopDriver.test.js +389 -0
  136. package/lib/server/desktopDriver.test.js.map +1 -0
  137. package/lib/server/index.d.ts +6 -0
  138. package/lib/server/index.d.ts.map +1 -0
  139. package/lib/server/index.js +4 -0
  140. package/lib/server/index.js.map +1 -0
  141. package/lib/server/webdriverio.contract.cjs +35 -0
  142. package/lib/server/webdriverio.contract.cjs.map +1 -0
  143. package/lib/server/webdriverio.contract.d.cts +2 -0
  144. package/lib/server/webdriverio.contract.d.cts.map +1 -0
  145. package/lib/server/webdriverio.test.d.ts +2 -0
  146. package/lib/server/webdriverio.test.d.ts.map +1 -0
  147. package/lib/server/webdriverio.test.js +40 -0
  148. package/lib/server/webdriverio.test.js.map +1 -0
  149. package/lib/storybook.d.ts +36 -0
  150. package/lib/storybook.d.ts.map +1 -0
  151. package/lib/storybook.js +2 -0
  152. package/lib/storybook.js.map +1 -0
  153. package/lib/testing/FakeStoryOrchestrator.d.ts +21 -0
  154. package/lib/testing/FakeStoryOrchestrator.d.ts.map +1 -0
  155. package/lib/testing/FakeStoryOrchestrator.js +44 -0
  156. package/lib/testing/FakeStoryOrchestrator.js.map +1 -0
  157. package/lib/testing/fakeStoryElements.d.ts +4 -0
  158. package/lib/testing/fakeStoryElements.d.ts.map +1 -0
  159. package/lib/testing/fakeStoryElements.js +143 -0
  160. package/lib/testing/fakeStoryElements.js.map +1 -0
  161. package/lib/testing/fakeStoryElements.test.d.ts +2 -0
  162. package/lib/testing/fakeStoryElements.test.d.ts.map +1 -0
  163. package/lib/testing/fakeStoryElements.test.js +38 -0
  164. package/lib/testing/fakeStoryElements.test.js.map +1 -0
  165. package/lib/testing/index.d.ts +7 -0
  166. package/lib/testing/index.d.ts.map +1 -0
  167. package/lib/testing/index.js +5 -0
  168. package/lib/testing/index.js.map +1 -0
  169. package/lib/testing/protocolHarness.d.ts +17 -0
  170. package/lib/testing/protocolHarness.d.ts.map +1 -0
  171. package/lib/testing/protocolHarness.js +46 -0
  172. package/lib/testing/protocolHarness.js.map +1 -0
  173. package/lib/wdio/DesktopWebdriver.d.ts +47 -0
  174. package/lib/wdio/DesktopWebdriver.d.ts.map +1 -0
  175. package/lib/wdio/DesktopWebdriver.js +76 -0
  176. package/lib/wdio/DesktopWebdriver.js.map +1 -0
  177. package/lib/wdio/DesktopWebdriver.test.d.ts +2 -0
  178. package/lib/wdio/DesktopWebdriver.test.d.ts.map +1 -0
  179. package/lib/wdio/DesktopWebdriver.test.js +74 -0
  180. package/lib/wdio/DesktopWebdriver.test.js.map +1 -0
  181. package/lib/wdio/index.d.ts +3 -0
  182. package/lib/wdio/index.d.ts.map +1 -0
  183. package/lib/wdio/index.js +2 -0
  184. package/lib/wdio/index.js.map +1 -0
  185. package/lib/wdio/wdioRunner.contract.cjs +64 -0
  186. package/lib/wdio/wdioRunner.contract.cjs.map +1 -0
  187. package/lib/wdio/wdioRunner.contract.d.cts +2 -0
  188. package/lib/wdio/wdioRunner.contract.d.cts.map +1 -0
  189. package/package.json +96 -0
  190. package/src/agent/DesktopAgent.test.ts +102 -0
  191. package/src/agent/DesktopAgent.ts +170 -0
  192. package/src/agent/agent.contract.cjs +32 -0
  193. package/src/agent/index.ts +8 -0
  194. package/src/artifacts/ArtifactManager.test.ts +20 -0
  195. package/src/artifacts/ArtifactManager.ts +105 -0
  196. package/src/artifacts/index.ts +1 -0
  197. package/src/authoring/index.ts +26 -0
  198. package/src/authoring/results.ts +47 -0
  199. package/src/authoring/storyTests.test.ts +58 -0
  200. package/src/authoring/storyTests.ts +345 -0
  201. package/src/cli/DesktopDriverCli.test.ts +150 -0
  202. package/src/cli/createDesktopDriverCommand.ts +290 -0
  203. package/src/cli/index.ts +2 -0
  204. package/src/client/DesktopDriverClient.ts +218 -0
  205. package/src/client/index.ts +2 -0
  206. package/src/host/types.ts +158 -0
  207. package/src/hosts/fake/FakeDesktopHost.ts +558 -0
  208. package/src/index.ts +101 -0
  209. package/src/protocol/actions.ts +163 -0
  210. package/src/protocol/capabilities.ts +129 -0
  211. package/src/protocol/constants.ts +1 -0
  212. package/src/protocol/errors.ts +76 -0
  213. package/src/protocol/timeouts.ts +26 -0
  214. package/src/protocol/types.ts +55 -0
  215. package/src/runner/StoryTestRunner.test.ts +362 -0
  216. package/src/runner/StoryTestRunner.ts +624 -0
  217. package/src/runner/index.ts +9 -0
  218. package/src/server/SessionManager.ts +302 -0
  219. package/src/server/TargetRegistry.ts +29 -0
  220. package/src/server/createDesktopDriverServer.ts +775 -0
  221. package/src/server/desktopDriver.test.ts +421 -0
  222. package/src/server/index.ts +5 -0
  223. package/src/server/webdriverio.contract.cjs +38 -0
  224. package/src/server/webdriverio.test.ts +41 -0
  225. package/src/storybook.ts +40 -0
  226. package/src/testing/FakeStoryOrchestrator.ts +55 -0
  227. package/src/testing/fakeStoryElements.test.ts +40 -0
  228. package/src/testing/fakeStoryElements.ts +167 -0
  229. package/src/testing/index.ts +6 -0
  230. package/src/testing/protocolHarness.ts +66 -0
  231. package/src/wdio/DesktopWebdriver.test.ts +76 -0
  232. package/src/wdio/DesktopWebdriver.ts +130 -0
  233. package/src/wdio/index.ts +2 -0
  234. package/src/wdio/wdioRunner.contract.cjs +30 -0
  235. package/tsconfig.json +15 -0
@@ -0,0 +1,349 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { ArtifactManager } from '../artifacts/ArtifactManager.js';
5
+ import { createDesktopDriverClient } from '../client/DesktopDriverClient.js';
6
+ import { createDesktopDriverStoryHarness } from '../testing/protocolHarness.js';
7
+ import { runDesktopStoryTests, selectDesktopStoryTests } from './StoryTestRunner.js';
8
+ import { findDesktopElements } from './StoryTestRunner.js';
9
+ const passingPlan = {
10
+ version: 1,
11
+ tests: [
12
+ {
13
+ id: 'button-contract',
14
+ requires: ['focus', 'keyboard', 'screenshot', 'wheel'],
15
+ steps: [
16
+ { action: 'wait', target: { testId: 'button-primary' }, timeoutMs: 100 },
17
+ { expect: { state: 'role', target: { testId: 'button-primary' }, value: 'button' } },
18
+ { expect: { state: 'enabled', target: { testId: 'button-primary' }, value: true } },
19
+ { action: 'click', target: { testId: 'button-primary' } },
20
+ { expect: { state: 'focused', target: { testId: 'button-primary' }, value: true } },
21
+ { action: 'type', target: { testId: 'input-name' }, text: 'Ada' },
22
+ { expect: { state: 'value', target: { testId: 'input-name' }, value: 'Ada' } },
23
+ { action: 'keys', value: ['\uE004'] },
24
+ { action: 'scroll', deltaY: 120 },
25
+ { action: 'setArgs', args: { disabled: false } },
26
+ { action: 'screenshot', name: 'button' },
27
+ { action: 'source', name: 'source' },
28
+ ],
29
+ title: 'Button contract',
30
+ },
31
+ ],
32
+ };
33
+ describe('runDesktopStoryTests', () => {
34
+ test('runs a portable plan and writes a stable evidence report', async () => {
35
+ const manifest = makeManifest(passingPlan);
36
+ const harness = await createDesktopDriverStoryHarness(manifest);
37
+ const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'desktop-driver-run-'));
38
+ try {
39
+ const client = createDesktopDriverClient({ url: harness.server.url });
40
+ const session = await client.newSession({
41
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
42
+ });
43
+ const result = await runDesktopStoryTests({
44
+ artifacts: new ArtifactManager(temporaryDirectory),
45
+ endpoint: 'windows',
46
+ manifest,
47
+ platformName: 'windows',
48
+ runId: 'run',
49
+ session,
50
+ targetId: harness.target.id,
51
+ });
52
+ expect(result).toMatchObject({
53
+ status: 'passed',
54
+ tests: [
55
+ {
56
+ status: 'passed',
57
+ steps: expect.arrayContaining([expect.objectContaining({ status: 'passed' })]),
58
+ },
59
+ ],
60
+ });
61
+ expect(result.tests[0].artifacts.map(({ kind }) => kind)).toEqual(['screenshot', 'source']);
62
+ expect(harness.storyOrchestrator?.argUpdates).toEqual([{ args: { disabled: false }, storyId: 'components-button--default' }]);
63
+ expect(JSON.parse(fs.readFileSync(path.join(temporaryDirectory, 'run.json'), 'utf8'))).toMatchObject({
64
+ runId: 'run',
65
+ status: 'passed',
66
+ });
67
+ expect(JSON.parse(fs.readFileSync(path.join(temporaryDirectory, 'host.json'), 'utf8'))).toMatchObject({
68
+ endpoint: 'windows',
69
+ targetId: harness.target.id,
70
+ });
71
+ await session.delete();
72
+ }
73
+ finally {
74
+ await harness.close();
75
+ fs.rmSync(temporaryDirectory, { force: true, recursive: true });
76
+ }
77
+ });
78
+ test('distinguishes assertion failures and captures failure evidence', async () => {
79
+ const manifest = makeManifest({
80
+ version: 1,
81
+ tests: [
82
+ {
83
+ id: 'fails',
84
+ steps: [{ expect: { state: 'role', target: { testId: 'button-primary' }, value: 'checkbox' } }],
85
+ },
86
+ ],
87
+ });
88
+ const harness = await createDesktopDriverStoryHarness(manifest);
89
+ const temporaryDirectory = fs.mkdtempSync(path.join(os.tmpdir(), 'desktop-driver-failure-'));
90
+ try {
91
+ const client = createDesktopDriverClient({ url: harness.server.url });
92
+ const session = await client.newSession({
93
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
94
+ });
95
+ const result = await runDesktopStoryTests({
96
+ artifacts: new ArtifactManager(temporaryDirectory),
97
+ endpoint: 'windows',
98
+ manifest,
99
+ platformName: 'windows',
100
+ session,
101
+ targetId: harness.target.id,
102
+ });
103
+ expect(result.status).toBe('failed');
104
+ expect(result.tests[0]).toMatchObject({
105
+ status: 'failed',
106
+ error: expect.stringContaining('checkbox'),
107
+ });
108
+ expect(result.tests[0].artifacts.map(({ name }) => name)).toEqual(['failure', 'failure-source', 'failure-tree']);
109
+ await session.delete();
110
+ }
111
+ finally {
112
+ await harness.close();
113
+ fs.rmSync(temporaryDirectory, { force: true, recursive: true });
114
+ }
115
+ });
116
+ test('filters and deterministically shards plans', () => {
117
+ const manifest = makeManifest({
118
+ version: 1,
119
+ tests: [
120
+ { id: 'one', steps: [{ action: 'note', message: 'one' }] },
121
+ { id: 'two', steps: [{ action: 'note', message: 'two' }] },
122
+ { id: 'three', steps: [{ action: 'note', message: 'three' }] },
123
+ { id: 'four', steps: [{ action: 'note', message: 'four' }] },
124
+ ],
125
+ });
126
+ const first = selectDesktopStoryTests(manifest, 'windows', { shardCount: 2, shardIndex: 0 });
127
+ const second = selectDesktopStoryTests(manifest, 'windows', { shardCount: 2, shardIndex: 1 });
128
+ expect([...first, ...second].map(({ test }) => test.id).sort()).toEqual(['four', 'one', 'three', 'two']);
129
+ expect(first).toHaveLength(2);
130
+ expect(second).toHaveLength(2);
131
+ });
132
+ test('does not turn an unsupported runtime property into a passing skip', async () => {
133
+ const manifest = makeManifest({
134
+ version: 1,
135
+ tests: [
136
+ {
137
+ id: 'unsupported-checked',
138
+ steps: [{ expect: { state: 'checked', target: { testId: 'button-primary' }, value: true } }],
139
+ },
140
+ ],
141
+ });
142
+ const harness = await createDesktopDriverStoryHarness(manifest);
143
+ harness.host.setElementStateUnsupported('button', 'checked', 'not exposed by this platform');
144
+ try {
145
+ const client = createDesktopDriverClient({ url: harness.server.url });
146
+ const session = await client.newSession({
147
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
148
+ });
149
+ const result = await runDesktopStoryTests({
150
+ endpoint: 'windows',
151
+ manifest,
152
+ platformName: 'windows',
153
+ session,
154
+ targetId: harness.target.id,
155
+ });
156
+ expect(result).toMatchObject({
157
+ status: 'failed',
158
+ tests: [{ status: 'failed', error: expect.stringContaining('not exposed') }],
159
+ });
160
+ await session.delete();
161
+ }
162
+ finally {
163
+ await harness.close();
164
+ }
165
+ });
166
+ test('matches text independently from accessible name', async () => {
167
+ const harness = await createDesktopDriverStoryHarness(makeManifest(passingPlan), {
168
+ windows: [
169
+ {
170
+ id: 'window-1',
171
+ title: 'Text selector',
172
+ elements: [
173
+ {
174
+ id: 'label',
175
+ rect: { height: 20, width: 100, x: 0, y: 0 },
176
+ role: 'text',
177
+ scope: 'preview',
178
+ text: 'Visible text',
179
+ windowId: 'window-1',
180
+ },
181
+ {
182
+ id: 'story-root',
183
+ automationId: 'story-root',
184
+ name: JSON.stringify({ previewGeneration: 0, storyId: 'initial--story' }),
185
+ rect: { height: 100, width: 100, x: 0, y: 0 },
186
+ role: 'group',
187
+ scope: 'preview',
188
+ windowId: 'window-1',
189
+ },
190
+ ],
191
+ },
192
+ ],
193
+ });
194
+ try {
195
+ const client = createDesktopDriverClient({ url: harness.server.url });
196
+ const session = await client.newSession({
197
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
198
+ });
199
+ await expect(findDesktopElements(session, { text: 'Visible' })).resolves.toHaveLength(1);
200
+ await session.delete();
201
+ }
202
+ finally {
203
+ await harness.close();
204
+ }
205
+ });
206
+ test('cancels an in-flight wait and releases input before the next test', async () => {
207
+ const manifest = makeManifest({
208
+ version: 1,
209
+ tests: [
210
+ {
211
+ id: 'cancelled-wait',
212
+ steps: [{ action: 'wait', target: { testId: 'missing' }, timeoutMs: 1000 }],
213
+ },
214
+ ],
215
+ });
216
+ const harness = await createDesktopDriverStoryHarness(manifest);
217
+ const controller = new AbortController();
218
+ try {
219
+ const client = createDesktopDriverClient({ url: harness.server.url });
220
+ const session = await client.newSession({
221
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
222
+ });
223
+ setTimeout(() => controller.abort(), 20);
224
+ const started = Date.now();
225
+ const result = await runDesktopStoryTests({
226
+ endpoint: 'windows',
227
+ manifest,
228
+ platformName: 'windows',
229
+ session,
230
+ signal: controller.signal,
231
+ targetId: harness.target.id,
232
+ });
233
+ expect(Date.now() - started).toBeLessThan(500);
234
+ expect(result).toMatchObject({ status: 'failed', tests: [{ status: 'cancelled' }] });
235
+ expect(harness.host.actions).toContainEqual({ type: 'release-actions' });
236
+ await session.delete();
237
+ }
238
+ finally {
239
+ await harness.close();
240
+ }
241
+ });
242
+ test('skips a declared focus requirement when focused state is unavailable', async () => {
243
+ const manifest = makeManifest({
244
+ version: 1,
245
+ tests: [
246
+ {
247
+ id: 'focus-required',
248
+ requires: ['focus'],
249
+ steps: [{ expect: { state: 'focused', target: { testId: 'button-primary' }, value: true } }],
250
+ },
251
+ ],
252
+ });
253
+ const harness = await createDesktopDriverStoryHarness(manifest, { features: { focus: false } });
254
+ try {
255
+ const client = createDesktopDriverClient({ url: harness.server.url });
256
+ const session = await client.newSession({
257
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
258
+ });
259
+ const result = await runDesktopStoryTests({
260
+ endpoint: 'windows',
261
+ manifest,
262
+ platformName: 'windows',
263
+ session,
264
+ targetId: harness.target.id,
265
+ });
266
+ expect(result).toMatchObject({
267
+ status: 'passed',
268
+ tests: [{ skipReason: 'Unsupported capabilities: focus', status: 'skipped', steps: [] }],
269
+ });
270
+ await session.delete();
271
+ }
272
+ finally {
273
+ await harness.close();
274
+ }
275
+ });
276
+ test('drains an aborted native action before releasing input', async () => {
277
+ const manifest = makeManifest({
278
+ version: 1,
279
+ tests: [
280
+ {
281
+ id: 'cancelled-action',
282
+ steps: [
283
+ {
284
+ action: 'actions',
285
+ sequences: [{ id: 'key', type: 'key', actions: [{ type: 'keyDown', value: 'A' }] }],
286
+ },
287
+ ],
288
+ },
289
+ ],
290
+ });
291
+ const harness = await createDesktopDriverStoryHarness(manifest, { actionDelayMs: 50 });
292
+ const controller = new AbortController();
293
+ try {
294
+ const client = createDesktopDriverClient({ url: harness.server.url });
295
+ const session = await client.newSession({
296
+ alwaysMatch: { platformName: 'windows', 'furn:target': harness.target.id },
297
+ });
298
+ const running = runDesktopStoryTests({
299
+ endpoint: 'windows',
300
+ manifest,
301
+ platformName: 'windows',
302
+ session,
303
+ signal: controller.signal,
304
+ targetId: harness.target.id,
305
+ });
306
+ await waitUntil(() => harness.host.actions.some(({ type }) => type === 'actions-start'));
307
+ controller.abort();
308
+ const result = await running;
309
+ expect(result).toMatchObject({ status: 'failed', tests: [{ status: 'cancelled' }] });
310
+ const completed = harness.host.actions.findIndex(({ type }) => type === 'actions');
311
+ const released = harness.host.actions.findIndex(({ type }) => type === 'release-actions');
312
+ expect(completed).toBeGreaterThan(-1);
313
+ expect(released).toBeGreaterThan(completed);
314
+ await session.delete();
315
+ }
316
+ finally {
317
+ await harness.close();
318
+ }
319
+ });
320
+ });
321
+ function makeManifest(tests) {
322
+ return {
323
+ endpoint: 'windows',
324
+ entries: [
325
+ {
326
+ id: 'components-button--default',
327
+ name: 'Default',
328
+ packageName: '@fluentui-react-native/components',
329
+ sourcePath: 'src/components/button/button.stories.tsx',
330
+ tags: ['e2e', 'story'],
331
+ tests,
332
+ title: 'Components/Button',
333
+ },
334
+ ],
335
+ platformManifestDigest: 'platform-digest',
336
+ portablePlanDigest: 'portable-digest',
337
+ schemaVersion: 1,
338
+ };
339
+ }
340
+ async function waitUntil(predicate, timeoutMs = 1000) {
341
+ const deadline = Date.now() + timeoutMs;
342
+ while (!predicate()) {
343
+ if (Date.now() >= deadline) {
344
+ throw new Error('Timed out waiting for the expected test condition.');
345
+ }
346
+ await new Promise((resolve) => setTimeout(resolve, 1));
347
+ }
348
+ }
349
+ //# sourceMappingURL=StoryTestRunner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StoryTestRunner.test.js","sourceRoot":"","sources":["../../src/runner/StoryTestRunner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { assertDesktopExpectation, DesktopAssertionError, findDesktopElement, findDesktopElements, runDesktopStoryTests, selectDesktopStoryTests, } from './StoryTestRunner.js';
2
+ export type { DesktopStoryTestRunnerOptions, DesktopStoryTestSelection } from './StoryTestRunner.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { assertDesktopExpectation, DesktopAssertionError, findDesktopElement, findDesktopElements, runDesktopStoryTests, selectDesktopStoryTests, } from './StoryTestRunner.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { ApplicationLease, DesktopHostInfo, DesktopTarget, DesktopWindow, NativeElementScope, NativeElementSnapshot } from '../host/types.js';
2
+ import type { WebDriverInputState } from '../protocol/actions.js';
3
+ import type { DesktopClickMode, DesktopTimeouts, WebDriverTimeouts } from '../protocol/types.js';
4
+ export type ElementRecord = {
5
+ id: string;
6
+ nativeId: string;
7
+ previewGeneration: number;
8
+ scope: NativeElementScope;
9
+ };
10
+ export type DesktopSession = {
11
+ clickMode: DesktopClickMode;
12
+ currentWindowId: string;
13
+ desktopTimeouts: DesktopTimeouts;
14
+ elements: Map<string, ElementRecord>;
15
+ elementIdsByNativeId: Map<string, string>;
16
+ hostInfo: DesktopHostInfo;
17
+ id: string;
18
+ inputState: WebDriverInputState;
19
+ issuedElementIds: Set<string>;
20
+ lease: ApplicationLease;
21
+ previewGeneration: number;
22
+ story: {
23
+ previewGeneration: number;
24
+ runId: string;
25
+ storyId: string;
26
+ } | null;
27
+ target: DesktopTarget;
28
+ timeouts: WebDriverTimeouts;
29
+ windows: DesktopWindow[];
30
+ };
31
+ export declare class SessionManager {
32
+ private readonly sessions;
33
+ private readonly sessionsByTarget;
34
+ private readonly reservedTargets;
35
+ private readonly commandQueues;
36
+ private readonly inFlightCreates;
37
+ private inputQueue;
38
+ private closing;
39
+ create(target: DesktopTarget, hostInfo: DesktopHostInfo, clickMode: DesktopClickMode, launchMode: 'attach' | 'launch'): Promise<DesktopSession>;
40
+ beginClose(): void;
41
+ waitForCreates(): Promise<void>;
42
+ private createSession;
43
+ get(id: string): DesktopSession;
44
+ runCommand<T>(sessionId: string, operation: () => Promise<T>): Promise<T>;
45
+ runInputCommand<T>(operation: () => Promise<T>): Promise<T>;
46
+ delete(id: string): Promise<void>;
47
+ deleteAll(): Promise<void>;
48
+ registerElement(session: DesktopSession, snapshot: NativeElementSnapshot): ElementRecord;
49
+ resolveElement(session: DesktopSession, id: string): ElementRecord;
50
+ invalidatePreview(session: DesktopSession): void;
51
+ }
52
+ //# sourceMappingURL=SessionManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionManager.d.ts","sourceRoot":"","sources":["../../src/server/SessionManager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEjG,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,kBAAkB,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,gBAAgB,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,EAAE,eAAe,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,mBAAmB,CAAC;IAChC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,KAAK,EAAE,gBAAgB,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5E,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B,CAAC;AAEF,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA6B;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoC;IAClE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4B;IAC5D,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,OAAO,CAAS;IAExB,MAAM,CACJ,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,eAAe,EACzB,SAAS,EAAE,gBAAgB,EAC3B,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAC9B,OAAO,CAAC,cAAc,CAAC,CAYzB;IAED,UAAU,IAAI,IAAI,CAEjB;IAEK,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpC;YAEa,aAAa;IAmG3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,CAM9B;IAED,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAcxE;IAED,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAO1D;IAEK,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCtC;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAY/B;IAED,eAAe,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,qBAAqB,GAAG,aAAa,CAevF;IAED,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,CAYjE;IAED,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAQ/C;CACF"}
@@ -0,0 +1,208 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { createInputState } from '../protocol/actions.js';
3
+ import { WebDriverError } from '../protocol/errors.js';
4
+ import { withCommandTimeout } from '../protocol/timeouts.js';
5
+ export class SessionManager {
6
+ sessions = new Map();
7
+ sessionsByTarget = new Map();
8
+ reservedTargets = new Set();
9
+ commandQueues = new Map();
10
+ inFlightCreates = new Set();
11
+ inputQueue = Promise.resolve();
12
+ closing = false;
13
+ create(target, hostInfo, clickMode, launchMode) {
14
+ if (this.closing) {
15
+ return Promise.reject(new WebDriverError('session not created', 'Desktop Driver is shutting down.'));
16
+ }
17
+ const result = this.createSession(target, hostInfo, clickMode, launchMode);
18
+ const settled = result.then(() => undefined, () => undefined);
19
+ this.inFlightCreates.add(settled);
20
+ void settled.finally(() => this.inFlightCreates.delete(settled));
21
+ return result;
22
+ }
23
+ beginClose() {
24
+ this.closing = true;
25
+ }
26
+ async waitForCreates() {
27
+ await Promise.all(this.inFlightCreates);
28
+ }
29
+ async createSession(target, hostInfo, clickMode, launchMode) {
30
+ if (this.sessionsByTarget.has(target.id) || this.reservedTargets.has(target.id)) {
31
+ throw new WebDriverError('session not created', `Target "${target.id}" already has an active session.`);
32
+ }
33
+ this.reservedTargets.add(target.id);
34
+ let lease;
35
+ let releaseReservation = true;
36
+ let leasePromise;
37
+ try {
38
+ lease = await withCommandTimeout((signal) => {
39
+ leasePromise = launchMode === 'attach' ? target.host.attach(target, signal) : target.host.launch(target, signal);
40
+ return leasePromise;
41
+ }, 120_000, `${launchMode === 'attach' ? 'Attaching to' : 'Launching'} target "${target.id}"`);
42
+ const activeLease = lease;
43
+ const windows = await withCommandTimeout((signal) => target.host.windows(activeLease, signal), 10_000, `Reading windows for target "${target.id}"`);
44
+ if (windows.length === 0) {
45
+ throw new WebDriverError('session not created', `Target "${target.id}" did not expose any windows.`);
46
+ }
47
+ if (this.closing) {
48
+ throw new WebDriverError('session not created', 'Desktop Driver shut down while the target was starting.');
49
+ }
50
+ const session = {
51
+ clickMode,
52
+ currentWindowId: windows[0].id,
53
+ desktopTimeouts: {
54
+ appLaunch: 120_000,
55
+ nativeCommand: 10_000,
56
+ stableLayout: 1_000,
57
+ storyRender: 30_000,
58
+ },
59
+ elements: new Map(),
60
+ elementIdsByNativeId: new Map(),
61
+ hostInfo,
62
+ id: randomUUID(),
63
+ inputState: createInputState(),
64
+ issuedElementIds: new Set(),
65
+ lease,
66
+ previewGeneration: 0,
67
+ story: null,
68
+ target,
69
+ timeouts: {
70
+ implicit: 0,
71
+ pageLoad: 300_000,
72
+ script: 30_000,
73
+ },
74
+ windows,
75
+ };
76
+ this.sessions.set(session.id, session);
77
+ this.sessionsByTarget.set(target.id, session.id);
78
+ return session;
79
+ }
80
+ catch (error) {
81
+ await this.runInputCommand(() => withCommandTimeout((signal) => target.host.releaseActions(signal), 10_000, `Releasing input for target "${target.id}"`)).catch(() => undefined);
82
+ if (lease) {
83
+ const failedLease = lease;
84
+ await withCommandTimeout((signal) => target.host.closeApplication(failedLease, signal), 10_000, `Closing failed target "${target.id}"`).catch(() => undefined);
85
+ }
86
+ else if (leasePromise) {
87
+ releaseReservation = false;
88
+ void leasePromise
89
+ .then(async (lateLease) => {
90
+ await this.runInputCommand(() => withCommandTimeout((signal) => target.host.releaseActions(signal), 10_000, `Releasing late input for target "${target.id}"`)).catch(() => undefined);
91
+ await withCommandTimeout((signal) => target.host.closeApplication(lateLease, signal), 10_000, `Closing late target "${target.id}"`).catch(() => undefined);
92
+ })
93
+ .catch(() => undefined)
94
+ .finally(() => this.reservedTargets.delete(target.id));
95
+ }
96
+ throw error;
97
+ }
98
+ finally {
99
+ if (releaseReservation) {
100
+ this.reservedTargets.delete(target.id);
101
+ }
102
+ }
103
+ }
104
+ get(id) {
105
+ const session = this.sessions.get(id);
106
+ if (!session) {
107
+ throw new WebDriverError('invalid session id', `Session "${id}" does not exist.`);
108
+ }
109
+ return session;
110
+ }
111
+ runCommand(sessionId, operation) {
112
+ const previous = this.commandQueues.get(sessionId) ?? Promise.resolve();
113
+ const result = previous.catch(() => undefined).then(operation);
114
+ const tail = result.then(() => undefined, () => undefined);
115
+ this.commandQueues.set(sessionId, tail);
116
+ void tail.finally(() => {
117
+ if (this.commandQueues.get(sessionId) === tail) {
118
+ this.commandQueues.delete(sessionId);
119
+ }
120
+ });
121
+ return result;
122
+ }
123
+ runInputCommand(operation) {
124
+ const result = this.inputQueue.catch(() => undefined).then(operation);
125
+ this.inputQueue = result.then(() => undefined, () => undefined);
126
+ return result;
127
+ }
128
+ async delete(id) {
129
+ const session = this.get(id);
130
+ this.reservedTargets.add(session.target.id);
131
+ const failures = [];
132
+ try {
133
+ try {
134
+ await this.runInputCommand(() => withCommandTimeout((signal) => session.target.host.releaseActions(signal), session.desktopTimeouts.nativeCommand, `Releasing input for session "${id}"`));
135
+ }
136
+ catch (error) {
137
+ failures.push(error);
138
+ }
139
+ try {
140
+ await withCommandTimeout((signal) => session.target.host.closeApplication(session.lease, signal), session.desktopTimeouts.nativeCommand, `Closing application for session "${id}"`);
141
+ }
142
+ catch (error) {
143
+ failures.push(error);
144
+ }
145
+ if (failures.length === 1) {
146
+ throw failures[0];
147
+ }
148
+ if (failures.length > 1) {
149
+ throw new AggregateError(failures, `Failed to close session "${id}".`);
150
+ }
151
+ this.sessions.delete(id);
152
+ this.sessionsByTarget.delete(session.target.id);
153
+ }
154
+ finally {
155
+ this.reservedTargets.delete(session.target.id);
156
+ }
157
+ }
158
+ async deleteAll() {
159
+ const failures = [];
160
+ for (const id of Array.from(this.sessions.keys())) {
161
+ try {
162
+ await this.delete(id);
163
+ }
164
+ catch (error) {
165
+ failures.push(error);
166
+ }
167
+ }
168
+ if (failures.length > 0) {
169
+ throw new AggregateError(failures, 'One or more desktop sessions failed to close.');
170
+ }
171
+ }
172
+ registerElement(session, snapshot) {
173
+ const existingId = session.elementIdsByNativeId.get(snapshot.id);
174
+ if (existingId) {
175
+ return session.elements.get(existingId);
176
+ }
177
+ const record = {
178
+ id: randomUUID(),
179
+ nativeId: snapshot.id,
180
+ previewGeneration: session.previewGeneration,
181
+ scope: snapshot.scope,
182
+ };
183
+ session.elements.set(record.id, record);
184
+ session.elementIdsByNativeId.set(record.nativeId, record.id);
185
+ session.issuedElementIds.add(record.id);
186
+ return record;
187
+ }
188
+ resolveElement(session, id) {
189
+ const element = session.elements.get(id);
190
+ if (!element) {
191
+ throw new WebDriverError(session.issuedElementIds.has(id) ? 'stale element reference' : 'no such element', `Element "${id}" is not available in this session.`);
192
+ }
193
+ if (element.scope === 'preview' && element.previewGeneration !== session.previewGeneration) {
194
+ throw new WebDriverError('stale element reference', `Element "${id}" is no longer attached to the current view.`);
195
+ }
196
+ return element;
197
+ }
198
+ invalidatePreview(session) {
199
+ session.previewGeneration += 1;
200
+ for (const [id, element] of session.elements) {
201
+ if (element.scope === 'preview') {
202
+ session.elements.delete(id);
203
+ session.elementIdsByNativeId.delete(element.nativeId);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ //# sourceMappingURL=SessionManager.js.map