@symbiote-native/brightness 0.0.1 → 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 (42) hide show
  1. package/build/angular/index.d.ts +1 -1
  2. package/build/angular/index.js +1 -1
  3. package/build/angular/services/permissions.service/index.d.ts +4 -0
  4. package/build/angular/services/permissions.service/index.js +20 -3
  5. package/build/core/brightness.d.ts +5 -2
  6. package/build/core/brightness.js +5 -2
  7. package/build/react/hooks/use-permissions/index.d.ts +2 -1
  8. package/build/react/hooks/use-permissions/index.js +18 -5
  9. package/build/react/index.d.ts +1 -1
  10. package/build/react/index.js +1 -1
  11. package/build/svelte/index.d.ts +2 -0
  12. package/build/svelte/index.js +6 -0
  13. package/build/svelte/runes/use-permissions.svelte.d.ts +7 -0
  14. package/build/svelte/runes/use-permissions.svelte.js +55 -0
  15. package/build/vue/composables/use-permissions/index.d.ts +1 -0
  16. package/build/vue/composables/use-permissions/index.js +13 -3
  17. package/build/vue/index.d.ts +1 -1
  18. package/build/vue/index.js +1 -1
  19. package/build-ngc/angular/index.d.ts +1 -1
  20. package/build-ngc/angular/index.js +1 -1
  21. package/build-ngc/angular/index.js.map +1 -1
  22. package/build-ngc/angular/services/permissions.service/index.d.ts +4 -0
  23. package/build-ngc/angular/services/permissions.service/index.js +23 -5
  24. package/build-ngc/angular/services/permissions.service/index.js.map +1 -1
  25. package/build-ngc/core/brightness.d.ts +5 -2
  26. package/build-ngc/core/brightness.js +5 -2
  27. package/build-ngc/core/brightness.js.map +1 -1
  28. package/package.json +30 -13
  29. package/src/angular/index.ts +1 -20
  30. package/src/angular/services/permissions.service/index.ts +20 -2
  31. package/src/core/brightness.ts +5 -2
  32. package/src/react/hooks/use-permissions/index.ts +19 -4
  33. package/src/react/index.ts +1 -20
  34. package/src/svelte/index.ts +7 -0
  35. package/src/svelte/runes/use-permissions.svelte.ts +65 -0
  36. package/src/svelte/svelte-ambient.d.ts +6 -0
  37. package/src/vue/composables/use-permissions/index.ts +13 -2
  38. package/src/vue/index.ts +1 -20
  39. package/src/angular/services/permissions.service/permissions.service.test.ts +0 -107
  40. package/src/core/brightness.test.ts +0 -334
  41. package/src/react/hooks/use-permissions/use-permissions.test.tsx +0 -100
  42. package/src/vue/composables/use-permissions/use-permissions.test.ts +0 -99
@@ -1,334 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
2
-
3
- const FAKE_NATIVE_BRIGHTNESS = {
4
- getBrightnessAsync: vi.fn(async () => 0.5),
5
- setBrightnessAsync: vi.fn(async () => undefined),
6
- getSystemBrightnessAsync: vi.fn(async () => 0.6),
7
- setSystemBrightnessAsync: vi.fn(async () => undefined),
8
- restoreSystemBrightnessAsync: vi.fn(async () => undefined),
9
- isUsingSystemBrightnessAsync: vi.fn(async () => true),
10
- getSystemBrightnessModeAsync: vi.fn(async () => 1),
11
- setSystemBrightnessModeAsync: vi.fn(async () => undefined),
12
- getPermissionsAsync: vi.fn(async () => ({ status: 'granted', granted: true })),
13
- requestPermissionsAsync: vi.fn(async () => ({ status: 'granted', granted: true })),
14
- addListener: vi.fn(() => ({ remove: vi.fn() })),
15
- };
16
-
17
- // The real ExpoBrightness native module only exists on device — resolving it via
18
- // requireNativeModule() at import time would throw in this headless test run, so the
19
- // module-lookup file is faked in place of expo-modules-core's runtime resolution, same pattern
20
- // packages/battery/src/core/battery.test.ts and packages/haptics/src/core/haptics.test.ts use.
21
- vi.mock('./native-module', () => ({
22
- expoBrightness: FAKE_NATIVE_BRIGHTNESS,
23
- }));
24
-
25
- // expo-modules-core's real entry transitively imports 'react-native' for Platform/
26
- // TurboModuleRegistry, whose Flow-typed source Vitest's Oxc transform can't parse — same fake
27
- // packages/haptics/src/core/haptics.test.ts uses, since Platform.OS gates every
28
- // system-brightness branch here.
29
- const fakePlatform = { OS: 'ios' as 'ios' | 'android' };
30
-
31
- vi.mock('expo-modules-core', () => ({
32
- Platform: fakePlatform,
33
- PermissionStatus: { GRANTED: 'granted', DENIED: 'denied', UNDETERMINED: 'undetermined' },
34
- UnavailabilityError: class UnavailabilityError extends Error {
35
- constructor(moduleName: string, propertyName: string) {
36
- super(`${propertyName} is not available on ${moduleName}`);
37
- }
38
- },
39
- }));
40
-
41
- const {
42
- isAvailableAsync,
43
- getBrightnessAsync,
44
- setBrightnessAsync,
45
- getSystemBrightnessAsync,
46
- setSystemBrightnessAsync,
47
- restoreSystemBrightnessAsync,
48
- isUsingSystemBrightnessAsync,
49
- getSystemBrightnessModeAsync,
50
- setSystemBrightnessModeAsync,
51
- getPermissionsAsync,
52
- requestPermissionsAsync,
53
- addBrightnessListener,
54
- } = await import('./brightness');
55
- const { BrightnessMode } = await import('./types');
56
-
57
- afterEach(() => {
58
- fakePlatform.OS = 'ios';
59
- vi.clearAllMocks();
60
- });
61
-
62
- describe('isAvailableAsync', () => {
63
- it('resolves true when the native module implements getBrightnessAsync', async () => {
64
- await expect(isAvailableAsync()).resolves.toBe(true);
65
- });
66
-
67
- it('resolves false when the native method is absent', async () => {
68
- const { getBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
69
- // @ts-expect-error -- simulating a platform where the native module has no such method
70
- FAKE_NATIVE_BRIGHTNESS.getBrightnessAsync = undefined;
71
-
72
- await expect(isAvailableAsync()).resolves.toBe(false);
73
-
74
- FAKE_NATIVE_BRIGHTNESS.getBrightnessAsync = native;
75
- });
76
- });
77
-
78
- describe('getBrightnessAsync', () => {
79
- it('delegates to the native module', async () => {
80
- await expect(getBrightnessAsync()).resolves.toBe(0.5);
81
- });
82
-
83
- it('throws an UnavailabilityError-shaped error when the native method is absent', async () => {
84
- const { getBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
85
- // @ts-expect-error -- simulating a platform where the native module has no such method
86
- FAKE_NATIVE_BRIGHTNESS.getBrightnessAsync = undefined;
87
-
88
- await expect(getBrightnessAsync()).rejects.toThrow(
89
- 'getBrightnessAsync is not available on expo-brightness',
90
- );
91
-
92
- FAKE_NATIVE_BRIGHTNESS.getBrightnessAsync = native;
93
- });
94
- });
95
-
96
- describe('setBrightnessAsync', () => {
97
- it('delegates to the native module', async () => {
98
- await setBrightnessAsync(0.4);
99
- expect(FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync).toHaveBeenCalledWith(0.4);
100
- });
101
-
102
- it('clamps a value above 1 down to 1', async () => {
103
- await setBrightnessAsync(1.5);
104
- expect(FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync).toHaveBeenCalledWith(1);
105
- });
106
-
107
- it('clamps a value below 0 up to 0', async () => {
108
- await setBrightnessAsync(-0.5);
109
- expect(FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync).toHaveBeenCalledWith(0);
110
- });
111
-
112
- it('throws a TypeError when the clamped value is NaN', async () => {
113
- await expect(setBrightnessAsync(NaN)).rejects.toThrow(
114
- 'setBrightnessAsync cannot be called with NaN',
115
- );
116
- expect(FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync).not.toHaveBeenCalled();
117
- });
118
-
119
- it('throws an UnavailabilityError-shaped error when the native method is absent', async () => {
120
- const { setBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
121
- // @ts-expect-error -- simulating a platform where the native module has no such method
122
- FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync = undefined;
123
-
124
- await expect(setBrightnessAsync(0.5)).rejects.toThrow(
125
- 'setBrightnessAsync is not available on expo-brightness',
126
- );
127
-
128
- FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync = native;
129
- });
130
- });
131
-
132
- describe('getSystemBrightnessAsync', () => {
133
- it('delegates to getBrightnessAsync on non-Android platforms', async () => {
134
- fakePlatform.OS = 'ios';
135
- await expect(getSystemBrightnessAsync()).resolves.toBe(0.5);
136
- expect(FAKE_NATIVE_BRIGHTNESS.getSystemBrightnessAsync).not.toHaveBeenCalled();
137
- });
138
-
139
- it('delegates to the native module on Android', async () => {
140
- fakePlatform.OS = 'android';
141
- await expect(getSystemBrightnessAsync()).resolves.toBe(0.6);
142
- });
143
-
144
- it('throws an UnavailabilityError-shaped error on Android when the native method is absent', async () => {
145
- fakePlatform.OS = 'android';
146
- const { getSystemBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
147
- // @ts-expect-error -- simulating an Android build missing this native method
148
- FAKE_NATIVE_BRIGHTNESS.getSystemBrightnessAsync = undefined;
149
-
150
- await expect(getSystemBrightnessAsync()).rejects.toThrow(
151
- 'getSystemBrightnessAsync is not available on expo-brightness',
152
- );
153
-
154
- FAKE_NATIVE_BRIGHTNESS.getSystemBrightnessAsync = native;
155
- });
156
- });
157
-
158
- describe('setSystemBrightnessAsync', () => {
159
- it('delegates to setBrightnessAsync on non-Android platforms', async () => {
160
- fakePlatform.OS = 'ios';
161
- await setSystemBrightnessAsync(0.3);
162
- expect(FAKE_NATIVE_BRIGHTNESS.setBrightnessAsync).toHaveBeenCalledWith(0.3);
163
- expect(FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessAsync).not.toHaveBeenCalled();
164
- });
165
-
166
- it('delegates to the native module on Android', async () => {
167
- fakePlatform.OS = 'android';
168
- await setSystemBrightnessAsync(0.3);
169
- expect(FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessAsync).toHaveBeenCalledWith(0.3);
170
- });
171
-
172
- it('clamps out-of-range values before delegating', async () => {
173
- fakePlatform.OS = 'android';
174
- await setSystemBrightnessAsync(2);
175
- expect(FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessAsync).toHaveBeenCalledWith(1);
176
- });
177
-
178
- it('throws a TypeError when the clamped value is NaN', async () => {
179
- await expect(setSystemBrightnessAsync(NaN)).rejects.toThrow(
180
- 'setSystemBrightnessAsync cannot be called with NaN',
181
- );
182
- });
183
-
184
- it('throws an UnavailabilityError-shaped error on Android when the native method is absent', async () => {
185
- fakePlatform.OS = 'android';
186
- const { setSystemBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
187
- // @ts-expect-error -- simulating an Android build missing this native method
188
- FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessAsync = undefined;
189
-
190
- await expect(setSystemBrightnessAsync(0.5)).rejects.toThrow(
191
- 'setSystemBrightnessAsync is not available on expo-brightness',
192
- );
193
-
194
- FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessAsync = native;
195
- });
196
- });
197
-
198
- describe('restoreSystemBrightnessAsync', () => {
199
- it('no-ops on non-Android platforms without calling the native module', async () => {
200
- fakePlatform.OS = 'ios';
201
- await restoreSystemBrightnessAsync();
202
- expect(FAKE_NATIVE_BRIGHTNESS.restoreSystemBrightnessAsync).not.toHaveBeenCalled();
203
- });
204
-
205
- it('delegates to the native module on Android', async () => {
206
- fakePlatform.OS = 'android';
207
- await restoreSystemBrightnessAsync();
208
- expect(FAKE_NATIVE_BRIGHTNESS.restoreSystemBrightnessAsync).toHaveBeenCalledTimes(1);
209
- });
210
-
211
- it('throws an UnavailabilityError-shaped error on Android when the native method is absent', async () => {
212
- fakePlatform.OS = 'android';
213
- const { restoreSystemBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
214
- // @ts-expect-error -- simulating an Android build missing this native method
215
- FAKE_NATIVE_BRIGHTNESS.restoreSystemBrightnessAsync = undefined;
216
-
217
- await expect(restoreSystemBrightnessAsync()).rejects.toThrow(
218
- 'restoreSystemBrightnessAsync is not available on expo-brightness',
219
- );
220
-
221
- FAKE_NATIVE_BRIGHTNESS.restoreSystemBrightnessAsync = native;
222
- });
223
- });
224
-
225
- describe('isUsingSystemBrightnessAsync', () => {
226
- it('resolves false on non-Android platforms without calling the native module', async () => {
227
- fakePlatform.OS = 'ios';
228
- await expect(isUsingSystemBrightnessAsync()).resolves.toBe(false);
229
- expect(FAKE_NATIVE_BRIGHTNESS.isUsingSystemBrightnessAsync).not.toHaveBeenCalled();
230
- });
231
-
232
- it('delegates to the native module on Android', async () => {
233
- fakePlatform.OS = 'android';
234
- await expect(isUsingSystemBrightnessAsync()).resolves.toBe(true);
235
- });
236
-
237
- it('throws an UnavailabilityError-shaped error on Android when the native method is absent', async () => {
238
- fakePlatform.OS = 'android';
239
- const { isUsingSystemBrightnessAsync: native } = FAKE_NATIVE_BRIGHTNESS;
240
- // @ts-expect-error -- simulating an Android build missing this native method
241
- FAKE_NATIVE_BRIGHTNESS.isUsingSystemBrightnessAsync = undefined;
242
-
243
- await expect(isUsingSystemBrightnessAsync()).rejects.toThrow(
244
- 'isUsingSystemBrightnessAsync is not available on expo-brightness',
245
- );
246
-
247
- FAKE_NATIVE_BRIGHTNESS.isUsingSystemBrightnessAsync = native;
248
- });
249
- });
250
-
251
- describe('getSystemBrightnessModeAsync', () => {
252
- it('resolves UNKNOWN on non-Android platforms without calling the native module', async () => {
253
- fakePlatform.OS = 'ios';
254
- await expect(getSystemBrightnessModeAsync()).resolves.toBe(BrightnessMode.UNKNOWN);
255
- expect(FAKE_NATIVE_BRIGHTNESS.getSystemBrightnessModeAsync).not.toHaveBeenCalled();
256
- });
257
-
258
- it('delegates to the native module on Android', async () => {
259
- fakePlatform.OS = 'android';
260
- await expect(getSystemBrightnessModeAsync()).resolves.toBe(1);
261
- });
262
-
263
- it('throws an UnavailabilityError-shaped error on Android when the native method is absent', async () => {
264
- fakePlatform.OS = 'android';
265
- const { getSystemBrightnessModeAsync: native } = FAKE_NATIVE_BRIGHTNESS;
266
- // @ts-expect-error -- simulating an Android build missing this native method
267
- FAKE_NATIVE_BRIGHTNESS.getSystemBrightnessModeAsync = undefined;
268
-
269
- await expect(getSystemBrightnessModeAsync()).rejects.toThrow(
270
- 'getSystemBrightnessModeAsync is not available on expo-brightness',
271
- );
272
-
273
- FAKE_NATIVE_BRIGHTNESS.getSystemBrightnessModeAsync = native;
274
- });
275
- });
276
-
277
- describe('setSystemBrightnessModeAsync', () => {
278
- it('no-ops on non-Android platforms without calling the native module', async () => {
279
- fakePlatform.OS = 'ios';
280
- await setSystemBrightnessModeAsync(BrightnessMode.AUTOMATIC);
281
- expect(FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessModeAsync).not.toHaveBeenCalled();
282
- });
283
-
284
- it('no-ops on Android when passed UNKNOWN', async () => {
285
- fakePlatform.OS = 'android';
286
- await setSystemBrightnessModeAsync(BrightnessMode.UNKNOWN);
287
- expect(FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessModeAsync).not.toHaveBeenCalled();
288
- });
289
-
290
- it('delegates to the native module on Android with a concrete mode', async () => {
291
- fakePlatform.OS = 'android';
292
- await setSystemBrightnessModeAsync(BrightnessMode.MANUAL);
293
- expect(FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessModeAsync).toHaveBeenCalledWith(
294
- BrightnessMode.MANUAL,
295
- );
296
- });
297
-
298
- it('throws an UnavailabilityError-shaped error on Android when the native method is absent', async () => {
299
- fakePlatform.OS = 'android';
300
- const { setSystemBrightnessModeAsync: native } = FAKE_NATIVE_BRIGHTNESS;
301
- // @ts-expect-error -- simulating an Android build missing this native method
302
- FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessModeAsync = undefined;
303
-
304
- await expect(setSystemBrightnessModeAsync(BrightnessMode.MANUAL)).rejects.toThrow(
305
- 'setSystemBrightnessModeAsync is not available on expo-brightness',
306
- );
307
-
308
- FAKE_NATIVE_BRIGHTNESS.setSystemBrightnessModeAsync = native;
309
- });
310
- });
311
-
312
- describe('getPermissionsAsync', () => {
313
- it('passes straight through to the native module', async () => {
314
- await expect(getPermissionsAsync()).resolves.toEqual({ status: 'granted', granted: true });
315
- });
316
- });
317
-
318
- describe('requestPermissionsAsync', () => {
319
- it('passes straight through to the native module', async () => {
320
- await expect(requestPermissionsAsync()).resolves.toEqual({ status: 'granted', granted: true });
321
- });
322
- });
323
-
324
- describe('addBrightnessListener', () => {
325
- it('subscribes through the Expo.brightnessDidChange event name', () => {
326
- const listener = vi.fn();
327
- addBrightnessListener(listener);
328
-
329
- expect(FAKE_NATIVE_BRIGHTNESS.addListener).toHaveBeenCalledWith(
330
- 'Expo.brightnessDidChange',
331
- listener,
332
- );
333
- });
334
- });
@@ -1,100 +0,0 @@
1
- // Co-located React-driven test (ADR 0025) for usePermissions. See battery's
2
- // use-battery-state.test.tsx for the shared rationale (mocks `core`, not expo-modules-core
3
- // internals).
4
-
5
- import { createElement, type ReactElement } from 'react';
6
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
- import { mount, unmount, View } from '@symbiote-native/react';
8
- import { installFabric } from '@symbiote-native/test-utils';
9
- import { usePermissions } from './index';
10
- import { PermissionStatus, type PermissionResponse } from '../../../core';
11
-
12
- const { getPermissionsAsync, requestPermissionsAsync } = vi.hoisted(() => ({
13
- getPermissionsAsync: vi.fn(),
14
- requestPermissionsAsync: vi.fn(),
15
- }));
16
-
17
- // Same enum-shaped-object mock trick packages/battery/src/react/hooks/use-battery-state's test
18
- // uses for BatteryState — the mock factory's runtime object stands in for the real enum
19
- // (imported here purely for its type), so `PermissionStatus.GRANTED` still type-checks.
20
- vi.mock('../../../core', () => ({
21
- getPermissionsAsync,
22
- requestPermissionsAsync,
23
- PermissionStatus: { GRANTED: 'granted', DENIED: 'denied', UNDETERMINED: 'undetermined' },
24
- }));
25
-
26
- const ROOT_TAG = 953;
27
-
28
- const GRANTED: PermissionResponse = {
29
- status: PermissionStatus.GRANTED,
30
- granted: true,
31
- canAskAgain: true,
32
- expires: 'never',
33
- };
34
- const DENIED: PermissionResponse = {
35
- status: PermissionStatus.DENIED,
36
- granted: false,
37
- canAskAgain: true,
38
- expires: 'never',
39
- };
40
-
41
- const results: (PermissionResponse | null)[] = [];
42
- let latestRequest: (() => Promise<PermissionResponse>) | undefined;
43
- let latestGet: (() => Promise<PermissionResponse>) | undefined;
44
-
45
- function Probe(): ReactElement {
46
- const [status, request, get] = usePermissions();
47
- results.push(status);
48
- latestRequest = request;
49
- latestGet = get;
50
- return createElement(View);
51
- }
52
-
53
- const fabric = installFabric();
54
-
55
- beforeEach(() => {
56
- fabric.reset();
57
- results.length = 0;
58
- latestRequest = undefined;
59
- latestGet = undefined;
60
- vi.clearAllMocks();
61
- getPermissionsAsync.mockResolvedValue(GRANTED);
62
- requestPermissionsAsync.mockResolvedValue(GRANTED);
63
- });
64
-
65
- afterEach(() => unmount(ROOT_TAG));
66
-
67
- describe('usePermissions', () => {
68
- it('starts at null before the initial fetch resolves', () => {
69
- mount(ROOT_TAG, createElement(Probe));
70
-
71
- expect(results[results.length - 1]).toBe(null);
72
- });
73
-
74
- it('fetches the permission status once on mount', async () => {
75
- mount(ROOT_TAG, createElement(Probe));
76
-
77
- await vi.waitFor(() => expect(results[results.length - 1]).toEqual(GRANTED));
78
- expect(getPermissionsAsync).toHaveBeenCalledTimes(1);
79
- });
80
-
81
- it('request() delegates to requestPermissionsAsync and updates the status', async () => {
82
- mount(ROOT_TAG, createElement(Probe));
83
- await vi.waitFor(() => expect(results[results.length - 1]).toEqual(GRANTED));
84
-
85
- requestPermissionsAsync.mockResolvedValueOnce(DENIED);
86
- await latestRequest?.();
87
-
88
- await vi.waitFor(() => expect(results[results.length - 1]).toEqual(DENIED));
89
- });
90
-
91
- it('get() re-fetches and updates the status', async () => {
92
- mount(ROOT_TAG, createElement(Probe));
93
- await vi.waitFor(() => expect(results[results.length - 1]).toEqual(GRANTED));
94
-
95
- getPermissionsAsync.mockResolvedValueOnce(DENIED);
96
- await latestGet?.();
97
-
98
- await vi.waitFor(() => expect(results[results.length - 1]).toEqual(DENIED));
99
- });
100
- });
@@ -1,99 +0,0 @@
1
- // Co-located Vue-driven test (ADR 0025) for usePermissions. See battery's
2
- // use-battery-state.test.ts for the shared rationale.
3
-
4
- import { defineComponent, h } from '@vue/runtime-core';
5
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
- import { mount, unmount } from '@symbiote-native/vue';
7
- import { installFabric } from '@symbiote-native/test-utils';
8
- import { usePermissions } from './index';
9
- import { PermissionStatus, type PermissionResponse } from '../../../core';
10
-
11
- const { getPermissionsAsync, requestPermissionsAsync } = vi.hoisted(() => ({
12
- getPermissionsAsync: vi.fn(),
13
- requestPermissionsAsync: vi.fn(),
14
- }));
15
-
16
- // Same enum-shaped-object mock trick packages/battery/src/vue/composables/use-battery-state's
17
- // test uses for BatteryState.
18
- vi.mock('../../../core', () => ({
19
- getPermissionsAsync,
20
- requestPermissionsAsync,
21
- PermissionStatus: { GRANTED: 'granted', DENIED: 'denied', UNDETERMINED: 'undetermined' },
22
- }));
23
-
24
- const GRANTED: PermissionResponse = {
25
- status: PermissionStatus.GRANTED,
26
- granted: true,
27
- canAskAgain: true,
28
- expires: 'never',
29
- };
30
- const DENIED: PermissionResponse = {
31
- status: PermissionStatus.DENIED,
32
- granted: false,
33
- canAskAgain: true,
34
- expires: 'never',
35
- };
36
-
37
- const ROOT_TAG = 9953;
38
- const fabric = installFabric();
39
-
40
- beforeEach(() => {
41
- fabric.reset();
42
- vi.clearAllMocks();
43
- getPermissionsAsync.mockResolvedValue(GRANTED);
44
- requestPermissionsAsync.mockResolvedValue(GRANTED);
45
- });
46
-
47
- afterEach(() => unmount(ROOT_TAG));
48
-
49
- function mountPermissions(): ReturnType<typeof usePermissions> {
50
- let result: ReturnType<typeof usePermissions> | undefined;
51
- mount(
52
- ROOT_TAG,
53
- defineComponent({
54
- setup: () => {
55
- result = usePermissions();
56
- return () => h('symbiote-text', {}, 'brightness');
57
- },
58
- }),
59
- );
60
- if (result === undefined) {
61
- throw new Error('setup() did not run');
62
- }
63
- return result;
64
- }
65
-
66
- describe('usePermissions (Vue)', () => {
67
- it('starts at null before the initial fetch resolves', () => {
68
- const { status } = mountPermissions();
69
-
70
- expect(status.value).toBe(null);
71
- });
72
-
73
- it('fetches the permission status once on mount', async () => {
74
- const { status } = mountPermissions();
75
-
76
- await vi.waitFor(() => expect(status.value).toEqual(GRANTED));
77
- expect(getPermissionsAsync).toHaveBeenCalledTimes(1);
78
- });
79
-
80
- it('request() delegates to requestPermissionsAsync and updates the status', async () => {
81
- const { status, request } = mountPermissions();
82
- await vi.waitFor(() => expect(status.value).toEqual(GRANTED));
83
-
84
- requestPermissionsAsync.mockResolvedValueOnce(DENIED);
85
- await request();
86
-
87
- expect(status.value).toEqual(DENIED);
88
- });
89
-
90
- it('get() re-fetches and updates the status', async () => {
91
- const { status, get } = mountPermissions();
92
- await vi.waitFor(() => expect(status.value).toEqual(GRANTED));
93
-
94
- getPermissionsAsync.mockResolvedValueOnce(DENIED);
95
- await get();
96
-
97
- expect(status.value).toEqual(DENIED);
98
- });
99
- });