Skip to content

Commit

Permalink
feat: Allow non-serializable parameters (#12)
Browse files Browse the repository at this point in the history
BREAKING CHANGE
  • Loading branch information
Rapsssito committed Feb 20, 2020
1 parent 0f12188 commit 9addd1e
Show file tree
Hide file tree
Showing 12 changed files with 172 additions and 80 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ jobs:
node-version: 12
- name: Install dependencies
run: yarn ci
- name: ESLint
run: yarn lint
- name: Tests
run: yarn test
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
4 changes: 1 addition & 3 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ codecov.yml
__tests__/
jest.config.js
jest.setup.js
coverage

# Example
examples/
Expand Down Expand Up @@ -94,6 +95,3 @@ bin/test.js
codorials
.vscode
.nyc_output

# Tests
coverage
7 changes: 6 additions & 1 deletion .releaserc
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"branches": ["master"],
"plugins": [
"@semantic-release/commit-analyzer",
["@semantic-release/commit-analyzer", {
"preset": "angular",
"parserOpts": {
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"]
}
}],
"@semantic-release/release-notes-generator",
"@semantic-release/github",
["@semantic-release/changelog", {
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ To use this library you need to ensure you are using the correct version of Reac
```js
import BackgroundService from 'react-native-background-actions';

const veryIntensiveTask = async (taskData) => {
const args = taskData.arguments;
const veryIntensiveTask = async (taskDataArguments) => {
const { delay } = taskDataArguments;
// You can do anything in your task such as network requests, timers and so on, as long as it doesn't touch UI.
// Once your task completes (i.e. the promise is resolved), React Native will go into "paused" mode (unless
// there are other tasks running, or there is a foreground app).
Expand All @@ -117,7 +117,7 @@ const options = {
type: 'mipmap',
},
color: '#ff00ff',
arguments: {
parameters: {
delay: 1000,
},
};
Expand All @@ -142,7 +142,7 @@ options
| `taskDesc` | `<string>` | **Android Required**. Notification description. |
| `taskIcon` | [`<taskIconOptions>`](#taskIconOptions) | **Android Required**. Notification icon. |
| `color` | `<string>` | Notification color. **Default**: `"#ffffff"` |
| `arguments` | `<object>` | Extra parameters to pass to the task. |
| `parameters` | `<any>` | Parameters to pass to the task. |

#### taskIconOptions
```javascript
Expand Down
5 changes: 5 additions & 0 deletions RNBackgroundActionsModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NativeModules } from 'react-native';

const { RNBackgroundActions } = NativeModules;

export default RNBackgroundActions;
4 changes: 4 additions & 0 deletions __mocks__/RNBackgroundActionsModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
start: jest.fn(),
stop: jest.fn(),
};
42 changes: 20 additions & 22 deletions __tests__/index.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,10 @@
import { NativeModules, Platform, AppRegistry } from 'react-native';
import { Platform, AppRegistry } from 'react-native';
import BackgroundActions from '../index';
import RNBackgroundActionsModule from '../RNBackgroundActionsModule';

jest.mock('react-native', () => ({
NativeModules: {
RNBackgroundActions: {
start: jest.fn(),
stop: jest.fn(),
},
},
Platform: {
OS: 'android',
},
AppRegistry: {
registerHeadlessTask: jest.fn((taskName, task) => task()()),
},
}));
Platform.OS = 'android';

AppRegistry.registerHeadlessTask = jest.fn((taskName, task) => task()());

const defaultOptions = {
taskName: 'Example',
Expand All @@ -24,35 +14,43 @@ const defaultOptions = {
name: 'ic_launcher',
type: 'mipmap',
},
arguments: {
parameters: {
delay: 1000,
},
};

test('stop-empty', async () => {
RNBackgroundActionsModule.stop.mockClear();
await BackgroundActions.stop();
expect(RNBackgroundActionsModule.stop).toHaveBeenCalledTimes(1);
});

test('start-android', async () => {
const defaultTask = jest.fn(async () => {});
Platform.OS = 'android';
AppRegistry.registerHeadlessTask.mockClear();
NativeModules.RNBackgroundActions.start.mockClear();
RNBackgroundActionsModule.start.mockClear();
await BackgroundActions.start(defaultTask, defaultOptions);
expect(defaultTask).toHaveBeenCalledTimes(1);
expect(defaultTask).toHaveBeenCalledWith(defaultOptions.parameters);
expect(AppRegistry.registerHeadlessTask).toHaveBeenCalledTimes(1);
expect(NativeModules.RNBackgroundActions.start).toHaveBeenCalledTimes(1);
expect(RNBackgroundActionsModule.start).toHaveBeenCalledTimes(1);
});

test('start-ios', async () => {
const defaultTask = jest.fn(async () => {});
AppRegistry.registerHeadlessTask.mockClear();
Platform.OS = 'ios';
NativeModules.RNBackgroundActions.start.mockClear();
RNBackgroundActionsModule.start.mockClear();
await BackgroundActions.start(defaultTask, defaultOptions);
expect(defaultTask).toHaveBeenCalledTimes(1);
expect(defaultTask).toHaveBeenCalledWith(defaultOptions.parameters);
expect(AppRegistry.registerHeadlessTask).toHaveBeenCalledTimes(0);
expect(NativeModules.RNBackgroundActions.start).toHaveBeenCalledTimes(1);
expect(RNBackgroundActionsModule.start).toHaveBeenCalledTimes(1);
});

test('stop', async () => {
NativeModules.RNBackgroundActions.stop.mockClear();
RNBackgroundActionsModule.stop.mockClear();
await BackgroundActions.stop();
expect(NativeModules.RNBackgroundActions.stop).toHaveBeenCalledTimes(1);
expect(RNBackgroundActionsModule.stop).toHaveBeenCalledTimes(1);
});
55 changes: 41 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,66 @@
import { NativeModules, Platform, AppRegistry } from 'react-native';

const { RNBackgroundActions } = NativeModules;
import { Platform, AppRegistry } from 'react-native';
import RNBackgroundActions from './RNBackgroundActionsModule';

/**
* @typedef {{taskName: string,
* taskTitle: string,
* taskDesc: string,
* taskIcon: {name: string, type: string, package?: string},
* color?: string,
* parameters?: any}} BackgroundTaskOptions
*/
class BackgroundTimer {
constructor() {
this.runnedTasks = 0;
this._runnedTasks = 0;
this._stopTask = () => {};
}

/**
* @param {Promise<void>} task
* @param {{taskName: string, taskTitle: string, taskDesc: string}} options
* @param {(taskData: any) => Promise<void>} task
* @param {BackgroundTaskOptions} options
*/
async start(task, options) {
this.runnedTasks++;
const finalOptions = this.normalizeOptions(options);
this._runnedTasks++;
const finalOptions = this._normalizeOptions(options);
const finalTask = this._generateTask(task, options.parameters);
if (Platform.OS === 'android') {
AppRegistry.registerHeadlessTask(finalOptions.taskName, () => task);
AppRegistry.registerHeadlessTask(finalOptions.taskName, () => finalTask);
await RNBackgroundActions.start(finalOptions);
} else {
await RNBackgroundActions.start(finalOptions);
task(finalOptions).then(() => this.stop());
finalTask();
}
}

/**
* @param {{taskName: string, taskTitle: string, taskDesc: string}} options
* @param {(taskData: any) => Promise<void>} task
* @param {any} [parameters]
*/
_generateTask(task, parameters) {
const self = this;
return async () => {
await new Promise((resolve) => {
self._stopTask = resolve;
task(parameters).then(() => resolve());
});
};
}

/**
* @param {BackgroundTaskOptions} options
*/
normalizeOptions(options) {
_normalizeOptions(options) {
return {
...options,
taskName: options.taskName + this.runnedTasks,
taskName: options.taskName + this._runnedTasks,
taskTitle: options.taskTitle,
taskDesc: options.taskDesc,
taskIcon: { ...options.taskIcon },
color: options.color || '#ffffff',
};
}

async stop() {
this._stopTask();
await RNBackgroundActions.stop();
}
}
Expand Down
1 change: 1 addition & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jest.mock('./RNBackgroundActionsModule');
6 changes: 6 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"checkJs": true,
},
"exclude": ["node_modules", "coverage", ".github", "examples", "ios", "android"],
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@semantic-release/git": "^9.0.0",
"@semantic-release/github": "^7.0.0",
"@semantic-release/npm": "^7.0.0",
"@types/jest": "^25.1.3",
"babel-jest": "^24.9.0",
"eslint": "^6.6.0",
"eslint-config-prettier": "^6.5.0",
Expand Down
Loading

0 comments on commit 9addd1e

Please sign in to comment.