Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Navigation Service Fix #82

Merged
merged 7 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install npm dependencies
run: |
yarn
run: yarn

- name: Lint
run: |
npm run lint
run: npm run lint

- name: Test and generate coverage report
uses: artiomtr/[email protected]
with:
Expand All @@ -23,6 +23,10 @@ jobs:
package-manager: yarn
skip-step: install
test-script: yarn test

- name: Tests
run: npm run test

- name: SonarQube Scan
uses: sonarsource/sonarqube-scan-action@master
env:
Expand Down
2 changes: 1 addition & 1 deletion app/scenes/ExampleScreen/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const exampleContainerReducer = (state = initialState, action) =>
produce(state, () => {
switch (action.type) {
case exampleScreenTypes.REQUEST_FETCH_USER:
return fetchUser(state, action);
return fetchUser(state);
case exampleScreenTypes.SUCCESS_FETCH_USER:
return successFetchUser(state, action);
case exampleScreenTypes.FAILURE_FETCH_USER:
Expand Down
26 changes: 13 additions & 13 deletions app/scenes/RootScreen/tests/saga.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,41 @@
/* eslint-disable redux-saga/yield-effects */

import { takeLatest } from 'redux-saga/effects';
import { setTopLevelNavigator } from 'app/services/navigationService';
import { navigateAndReset } from '@app/services/navigationService';
import { timeout } from 'app/utils/testUtils';
import rootScreenSaga, { startup } from '../saga';
import { rootScreenTypes } from '../reducer';

jest.mock('@app/services/navigationService', () => ({
...jest.requireActual('@app/services/navigationService'),
navigateAndReset: jest.fn()
}));
describe('Tests for RootScreen sagas', () => {
let generator;
let submitSpy;

beforeEach(() => {
generator = rootScreenSaga();
submitSpy = jest.fn();
afterEach(() => {
jest.clearAllMocks();
});

it('should start task to watch for STARTUP action', () => {
const generator = rootScreenSaga();
expect(generator.next().value).toEqual(
takeLatest(rootScreenTypes.STARTUP, startup)
);
});

it('should ensure that the navigation service is called after waiting for 1000ms', async () => {
const method = startup();
setTopLevelNavigator({ dispatch: submitSpy });
method.next();
await timeout(2000);
expect(submitSpy).toHaveBeenCalled();
await timeout(1000);
expect(navigateAndReset).toHaveBeenCalled();
expect(navigateAndReset).toHaveBeenCalledWith('MainScreen');
Comment on lines +33 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case correctly checks if navigateAndReset is called with the expected arguments. However, consider using toHaveBeenCalledTimes(1) for more precise testing.

- expect(navigateAndReset).toHaveBeenCalled();
+ expect(navigateAndReset).toHaveBeenCalledTimes(1);

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
expect(navigateAndReset).toHaveBeenCalled();
expect(navigateAndReset).toHaveBeenCalledWith('MainScreen');
expect(navigateAndReset).toHaveBeenCalledTimes(1);
expect(navigateAndReset).toHaveBeenCalledWith('MainScreen');

});

it('should ensure that the navigation service is called after waiting for 1000ms', async () => {
const method = startup();
setTopLevelNavigator({ dispatch: submitSpy });
method.next();
await timeout(650);
expect(submitSpy).not.toHaveBeenCalled();
expect(navigateAndReset).not.toHaveBeenCalled();
await timeout(200);
expect(submitSpy).not.toHaveBeenCalled();
expect(navigateAndReset).not.toHaveBeenCalled();
});
});
11 changes: 6 additions & 5 deletions app/services/navigationService.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { NavigationActions, StackActions } from '@react-navigation/compat';

/**
* The navigation is implemented as a service so that it can be used outside of components, for example in sagas.
*
* @see https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
*/

let navigator;
const navigatorObject = {
navigator: null
};

/**
* This function is called when the RootScreen is created to set the navigator instance to use.
*/
export function setTopLevelNavigator(navigatorRef) {
navigator = navigatorRef;
Object.assign(navigatorObject, { navigator: navigatorRef });
}

/**
Expand All @@ -22,7 +23,7 @@ export function setTopLevelNavigator(navigatorRef) {
* @param params Route parameters.
*/
export function navigate(routeName, params) {
navigator.dispatch(
navigatorObject.navigator.dispatch(
NavigationActions.navigate({
routeName,
params
Expand All @@ -40,7 +41,7 @@ export function navigate(routeName, params) {
* @param params Route parameters.
*/
export function navigateAndReset(routeName, params) {
navigator.dispatch(
navigatorObject.navigator.dispatch(
StackActions.replace({
routeName,
params
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
sonar.projectKey=wednesday-solutions_react-native-template_AY7hdnRSB2n8RRmGoU2M
sonar.language=js
sonar.sources=app
sonar.sources=.
sonar.tests=app
sonar.exclusions=**/android/**,**/ios/**,**/node_modules/**
sonar.test.inclusions=**/*.test.js
Expand Down
Loading