xref: /expo/apps/test-suite/tests/TaskManager.js (revision fdc6a3a2)
1import { Location, TaskManager } from 'expo';
2
3import * as TestUtils from '../TestUtils';
4
5const DEFINED_TASK_NAME = 'defined task';
6const UNDEFINED_TASK_NAME = 'undefined task';
7
8export const name = 'TaskManager';
9
10export async function test(t) {
11  const shouldSkipTestsRequiringPermissions = await TestUtils.shouldSkipTestsRequiringPermissionsAsync();
12  const describeWithPermissions = shouldSkipTestsRequiringPermissions ? t.xdescribe : t.describe;
13  const locationOptions = {
14    accuracy: Location.Accuracy.Low,
15    showsBackgroundLocationIndicator: false,
16  };
17  /*
18  Some of these tests cause Expo to crash on device farm with the following error:
19  "sdkUnversionedTestSuite failed: java.lang.NullPointerException: Attempt to invoke interface method
20  'java.util.Map org.unimodules.interfaces.taskManager.TaskInterface.getOptions()' on a null object reference"
21
22  getOptions() is being called from within LocationTaskConsumer.java in the expo-location module
23  several times without checking for null
24  */
25  t.describe('TaskManager', () => {
26    t.describe('isTaskDefined()', () => {
27      t.it('returns true if task is defined', () => {
28        t.expect(TaskManager.isTaskDefined(DEFINED_TASK_NAME)).toBe(true);
29      });
30      t.it('returns false if task is not defined', () => {
31        t.expect(TaskManager.isTaskDefined(UNDEFINED_TASK_NAME)).toBe(false);
32      });
33    });
34
35    describeWithPermissions('isTaskRegisteredAsync()', async () => {
36      t.beforeAll(async () => {
37        await Location.startLocationUpdatesAsync(DEFINED_TASK_NAME);
38      });
39
40      t.it('returns true for registered tasks', async () => {
41        t.expect(await TaskManager.isTaskRegisteredAsync(DEFINED_TASK_NAME)).toBe(true);
42      });
43
44      t.it('returns false for unregistered tasks', async () => {
45        t.expect(await TaskManager.isTaskRegisteredAsync(UNDEFINED_TASK_NAME)).toBe(false);
46      });
47
48      t.afterAll(async () => {
49        await Location.stopLocationUpdatesAsync(DEFINED_TASK_NAME);
50      });
51    });
52
53    describeWithPermissions('getTaskOptionsAsync()', async () => {
54      let taskOptions;
55
56      t.it('returns null for unregistered tasks', async () => {
57        taskOptions = await TaskManager.getTaskOptionsAsync(DEFINED_TASK_NAME);
58        t.expect(taskOptions).toBe(null);
59      });
60
61      t.it('returns correct options after register', async () => {
62        await Location.startLocationUpdatesAsync(DEFINED_TASK_NAME, locationOptions);
63        taskOptions = await TaskManager.getTaskOptionsAsync(DEFINED_TASK_NAME);
64        t.expect(taskOptions).toEqual(t.jasmine.objectContaining(locationOptions));
65      });
66
67      t.it('returns null when unregistered', async () => {
68        await Location.stopLocationUpdatesAsync(DEFINED_TASK_NAME);
69        taskOptions = await TaskManager.getTaskOptionsAsync(DEFINED_TASK_NAME);
70        t.expect(taskOptions).toBe(null);
71      });
72    });
73
74    describeWithPermissions('getRegisteredTasksAsync()', async () => {
75      let registeredTasks;
76
77      t.it('returns empty array if there are no tasks', async () => {
78        registeredTasks = await TaskManager.getRegisteredTasksAsync();
79        t.expect(registeredTasks).toBeDefined();
80        t.expect(registeredTasks.length).toBe(0);
81      });
82
83      t.it('returns correct array after registering the task', async () => {
84        await Location.startLocationUpdatesAsync(DEFINED_TASK_NAME, locationOptions);
85
86        registeredTasks = await TaskManager.getRegisteredTasksAsync();
87
88        t.expect(registeredTasks).toBeDefined();
89        t.expect(registeredTasks.length).toBe(1);
90        t.expect(registeredTasks.find(task => task.taskName === DEFINED_TASK_NAME)).toEqual(
91          t.jasmine.objectContaining({
92            taskName: DEFINED_TASK_NAME,
93            taskType: 'location',
94            options: locationOptions,
95          })
96        );
97      });
98
99      t.afterAll(async () => {
100        await Location.stopLocationUpdatesAsync(DEFINED_TASK_NAME);
101      });
102    });
103
104    describeWithPermissions('unregisterAllTasksAsync()', () => {
105      t.it('unregisters tasks correctly', async () => {
106        await Location.startLocationUpdatesAsync(DEFINED_TASK_NAME, locationOptions);
107        await TaskManager.unregisterAllTasksAsync();
108
109        t.expect(await TaskManager.isTaskRegisteredAsync(DEFINED_TASK_NAME)).toBe(false);
110        t.expect((await TaskManager.getRegisteredTasksAsync()).length).toBe(0);
111        t.expect(await Location.hasStartedLocationUpdatesAsync(DEFINED_TASK_NAME)).toBe(false);
112      });
113    });
114
115    describeWithPermissions('rejections', () => {
116      t.it('should reject when trying to unregister task with different consumer', async () => {
117        await Location.startLocationUpdatesAsync(DEFINED_TASK_NAME, locationOptions);
118
119        let error;
120        try {
121          await Location.stopGeofencingAsync(DEFINED_TASK_NAME, locationOptions);
122        } catch (e) {
123          error = e;
124        }
125        t.expect(error).toBeDefined();
126        t.expect(error.message).toMatch(/Invalid task consumer/);
127
128        await Location.stopLocationUpdatesAsync(DEFINED_TASK_NAME);
129      });
130    });
131  });
132}
133
134// Empty task so we can properly test some methods.
135TaskManager.defineTask(DEFINED_TASK_NAME, () => {});
136