@flighthq/accessibility 0.4.0-next.1903.50bfa67 → 0.4.0-next.1908.751021c

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/accessibility",
3
- "version": "0.4.0-next.1903.50bfa67",
3
+ "version": "0.4.0-next.1908.751021c",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,7 +38,7 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/types": "0.4.0-next.1903.50bfa67"
41
+ "@flighthq/types": "0.4.0-next.1908.751021c"
42
42
  },
43
43
  "devDependencies": {
44
44
  "typescript": "^5.3.0"
@@ -10,6 +10,10 @@ import {
10
10
  setAccessibilityBackend,
11
11
  setAccessibilityFocus,
12
12
  setAccessibilityNode,
13
+ explainAccessibilityBackend,
14
+ installAccessibilityHostBackend,
15
+ observeAccessibilityHostResult,
16
+ resetAccessibilityBackendForTest,
13
17
  } from './accessibility';
14
18
 
15
19
  afterEach(() => {
@@ -187,6 +191,34 @@ describe('createWebAccessibilityBackend', () => {
187
191
  });
188
192
  });
189
193
 
194
+ describe('explainAccessibilityBackend', () => {
195
+ afterEach(() => resetAccessibilityBackendForTest());
196
+
197
+ it('reports host-not-enabled when no backend is installed', () => {
198
+ resetAccessibilityBackendForTest();
199
+ const explanation = explainAccessibilityBackend();
200
+ expect(explanation.layer).toBe('host-not-enabled');
201
+ expect(explanation.conflict).toBe(false);
202
+ expect(explanation.viability).toBe('unobserved');
203
+ });
204
+
205
+ it('reports custom layer when a custom backend is set', () => {
206
+ setAccessibilityBackend(getAccessibilityBackend());
207
+ expect(explainAccessibilityBackend().layer).toBe('custom');
208
+ });
209
+
210
+ it('reports host layer when a host backend is installed', () => {
211
+ installAccessibilityHostBackend(getAccessibilityBackend());
212
+ expect(explainAccessibilityBackend().layer).toBe('host');
213
+ });
214
+
215
+ it('reports conflict when two different host backends are installed', () => {
216
+ installAccessibilityHostBackend({ ...getAccessibilityBackend() });
217
+ installAccessibilityHostBackend({ ...getAccessibilityBackend() });
218
+ expect(explainAccessibilityBackend().conflict).toBe(true);
219
+ });
220
+ });
221
+
190
222
  describe('getAccessibilityBackend', () => {
191
223
  it('lazily returns a stable web default', () => {
192
224
  const first = getAccessibilityBackend();
@@ -200,50 +232,49 @@ describe('getAccessibilityBackend', () => {
200
232
  });
201
233
  });
202
234
 
203
- describe('removeAccessibilityNode', () => {
204
- it('dispatches the id to the backend', () => {
205
- const mock = createMockAccessibilityBackend();
206
- setAccessibilityBackend(mock.backend);
207
- removeAccessibilityNode('gone');
208
- expect(mock.calls.removeNode).toEqual(['gone']);
209
- });
210
- });
235
+ describe('installAccessibilityHostBackend', () => {
236
+ afterEach(() => resetAccessibilityBackendForTest());
211
237
 
212
- describe('setAccessibilityBackend', () => {
213
- it('installs a backend that later commands dispatch through', () => {
214
- const mock = createMockAccessibilityBackend();
215
- setAccessibilityBackend(mock.backend);
216
- setAccessibilityNode(node('a', 'button', {}));
217
- expect(mock.calls.setNode.length).toBe(1);
238
+ it('installs a host backend that getAccessibilityBackend returns', () => {
239
+ const backend = getAccessibilityBackend();
240
+ installAccessibilityHostBackend(backend);
241
+ expect(getAccessibilityBackend()).toBe(backend);
218
242
  });
219
243
 
220
- it('reverts to the sentinel when passed null', () => {
221
- const sentinel = getAccessibilityBackend();
222
- const mock = createMockAccessibilityBackend();
223
- setAccessibilityBackend(mock.backend);
224
- expect(getAccessibilityBackend()).toBe(mock.backend);
225
- setAccessibilityBackend(null);
226
- expect(getAccessibilityBackend()).toBe(sentinel);
244
+ it('is first-host-wins: a second different backend sets conflict', () => {
245
+ const first = { ...getAccessibilityBackend() };
246
+ const second = { ...getAccessibilityBackend() };
247
+ installAccessibilityHostBackend(first);
248
+ installAccessibilityHostBackend(second);
249
+ expect(getAccessibilityBackend()).toBe(first);
250
+ expect(explainAccessibilityBackend().conflict).toBe(true);
227
251
  });
228
252
  });
229
253
 
230
- describe('setAccessibilityFocus', () => {
231
- it('dispatches the id and returns the backend result', () => {
232
- const mock = createMockAccessibilityBackend();
233
- setAccessibilityBackend(mock.backend);
234
- expect(setAccessibilityFocus('ok')).toBe(true);
235
- expect(setAccessibilityFocus('nope')).toBe(false);
236
- expect(mock.calls.setFocus).toEqual(['ok', 'nope']);
254
+ describe('observeAccessibilityHostResult', () => {
255
+ afterEach(() => resetAccessibilityBackendForTest());
256
+
257
+ it('records a successful observation', () => {
258
+ installAccessibilityHostBackend(getAccessibilityBackend());
259
+ observeAccessibilityHostResult('setNode', true);
260
+ const explanation = explainAccessibilityBackend();
261
+ expect(explanation.operation).toBe('setNode');
262
+ expect(explanation.viability).toBe('available');
263
+ });
264
+
265
+ it('records a failed observation', () => {
266
+ installAccessibilityHostBackend(getAccessibilityBackend());
267
+ observeAccessibilityHostResult('setNode', false);
268
+ expect(explainAccessibilityBackend().viability).toBe('runtime-api-unavailable');
237
269
  });
238
270
  });
239
271
 
240
- describe('setAccessibilityNode', () => {
241
- it('dispatches the node to the backend', () => {
272
+ describe('removeAccessibilityNode', () => {
273
+ it('dispatches the id to the backend', () => {
242
274
  const mock = createMockAccessibilityBackend();
243
275
  setAccessibilityBackend(mock.backend);
244
- const target = node('a', 'button', { label: 'Go' });
245
- setAccessibilityNode(target);
246
- expect(mock.calls.setNode).toEqual([target]);
276
+ removeAccessibilityNode('gone');
277
+ expect(mock.calls.removeNode).toEqual(['gone']);
247
278
  });
248
279
  });
249
280
 
@@ -285,3 +316,53 @@ function createMockAccessibilityBackend(): { backend: AccessibilityBackend; call
285
316
  };
286
317
  return { backend, calls };
287
318
  }
319
+
320
+ describe('resetAccessibilityBackendForTest', () => {
321
+ it('clears all backend slots', () => {
322
+ setAccessibilityBackend(getAccessibilityBackend());
323
+ installAccessibilityHostBackend(getAccessibilityBackend());
324
+ observeAccessibilityHostResult('setNode', true);
325
+ resetAccessibilityBackendForTest();
326
+ expect(explainAccessibilityBackend().layer).toBe('host-not-enabled');
327
+ expect(explainAccessibilityBackend().conflict).toBe(false);
328
+ expect(explainAccessibilityBackend().viability).toBe('unobserved');
329
+ });
330
+ });
331
+
332
+ describe('setAccessibilityBackend', () => {
333
+ it('installs a backend that later commands dispatch through', () => {
334
+ const mock = createMockAccessibilityBackend();
335
+ setAccessibilityBackend(mock.backend);
336
+ setAccessibilityNode(node('a', 'button', {}));
337
+ expect(mock.calls.setNode.length).toBe(1);
338
+ });
339
+
340
+ it('reverts to the sentinel when passed null', () => {
341
+ const sentinel = getAccessibilityBackend();
342
+ const mock = createMockAccessibilityBackend();
343
+ setAccessibilityBackend(mock.backend);
344
+ expect(getAccessibilityBackend()).toBe(mock.backend);
345
+ setAccessibilityBackend(null);
346
+ expect(getAccessibilityBackend()).toBe(sentinel);
347
+ });
348
+ });
349
+
350
+ describe('setAccessibilityFocus', () => {
351
+ it('dispatches the id and returns the backend result', () => {
352
+ const mock = createMockAccessibilityBackend();
353
+ setAccessibilityBackend(mock.backend);
354
+ expect(setAccessibilityFocus('ok')).toBe(true);
355
+ expect(setAccessibilityFocus('nope')).toBe(false);
356
+ expect(mock.calls.setFocus).toEqual(['ok', 'nope']);
357
+ });
358
+ });
359
+
360
+ describe('setAccessibilityNode', () => {
361
+ it('dispatches the node to the backend', () => {
362
+ const mock = createMockAccessibilityBackend();
363
+ setAccessibilityBackend(mock.backend);
364
+ const target = node('a', 'button', { label: 'Go' });
365
+ setAccessibilityNode(target);
366
+ expect(mock.calls.setNode).toEqual([target]);
367
+ });
368
+ });