Skip to content

Commit

Permalink
fix: Add more rn sdk unit tests. (#339)
Browse files Browse the repository at this point in the history
* Added more coverage for rn sdk.
* Added separate tsconfig.json for tests.
* Improved jest config.
* Removed release-as from release please config.

---------

Co-authored-by: LaunchDarklyReleaseBot <[email protected]>
  • Loading branch information
yusinto and LaunchDarklyReleaseBot authored Dec 29, 2023
1 parent df1dae4 commit 913bc00
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 34 deletions.
4 changes: 1 addition & 3 deletions packages/sdk/react-native/example/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"assetBundlePatterns": [
"**/*"
],
"assetBundlePatterns": ["**/*"],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.anonymous.reactnativeexample"
Expand Down
9 changes: 0 additions & 9 deletions packages/sdk/react-native/jest.config.json

This file was deleted.

17 changes: 17 additions & 0 deletions packages/sdk/react-native/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { JestConfigWithTsJest } from 'ts-jest';

const jestConfig: JestConfigWithTsJest = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: 'tsconfig.test.json',
},
],
},
testPathIgnorePatterns: ['node_modules', 'example', 'dist'],
};

export default jestConfig;
11 changes: 7 additions & 4 deletions packages/sdk/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"start": "rimraf dist && yarn tsw",
"lint": "eslint . --ext .ts",
"prettier": "prettier --write '**/*.@(js|ts|tsx|json|css)' --ignore-path ../../../.prettierignore",
"test": "NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" jest --ci --runInBand",
"test": "jest",
"coverage": "yarn test --coverage",
"check": "yarn prettier && yarn lint && yarn build && yarn test",
"link-dev": "./link-dev.sh",
Expand All @@ -50,8 +50,9 @@
"event-target-shim": "^6.0.2"
},
"devDependencies": {
"@testing-library/react": "^14.1.2",
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@types/jest": "^29.5.0",
"@types/jest": "^29.5.11",
"@types/react": "^18.2.31",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
Expand All @@ -61,13 +62,15 @@
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"jest": "^29.7.0",
"launchdarkly-js-test-helpers": "^2.2.0",
"prettier": "^3.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-native": "^0.73.1",
"rimraf": "^5.0.5",
"ts-jest": "^29.1.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typedoc": "0.25.0",
"typescript": "5.1.6"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/react-native/src/ReactNativeLDClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ describe('ReactNativeLDClient', () => {
let ldc: ReactNativeLDClient;

beforeEach(() => {
ldc = new ReactNativeLDClient('mob-test', { sendEvents: false });
ldc = new ReactNativeLDClient('mobile-key', { sendEvents: false });
});

test('constructing a new client', () => {
expect(ldc.sdkKey).toEqual('mob-test');
expect(ldc.sdkKey).toEqual('mobile-key');
expect(ldc.config.serviceEndpoints).toEqual({
analyticsEventPath: '/mobile',
diagnosticEventPath: '/mobile/events/diagnostic',
Expand Down
97 changes: 97 additions & 0 deletions packages/sdk/react-native/src/provider/LDProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { render } from '@testing-library/react';

import type { LDContext, LDOptions } from '@launchdarkly/js-client-sdk-common';

import { useLDClient } from '../hooks';
import ReactNativeLDClient from '../ReactNativeLDClient';
import LDProvider from './LDProvider';
import setupListeners from './setupListeners';

jest.mock('./setupListeners');
jest.mock('../ReactNativeLDClient');

const TestApp = () => {
const ldClient = useLDClient();
return (
<>
<p>ldClient {ldClient ? 'defined' : 'undefined'}</p>
<p>mobileKey {ldClient.sdkKey ? ldClient.sdkKey : 'undefined'}</p>
<p>context {ldClient.getContext() ? 'defined' : 'undefined'}</p>
</>
);
};
describe('LDProvider', () => {
let ldc: ReactNativeLDClient;
let context: LDContext;
let mockSetupListeners = setupListeners as jest.Mock;

beforeEach(() => {
jest.useFakeTimers();
(ReactNativeLDClient as jest.Mock).mockImplementation(
(mobileKey: string, _options?: LDOptions) => {
let context: LDContext;

return {
sdkKey: mobileKey,
identify: jest.fn((c: LDContext) => {
context = c;
return Promise.resolve();
}),
getContext: jest.fn(() => context),
on: jest.fn(),
logger: {
debug: jest.fn(),
},
};
},
);
mockSetupListeners.mockImplementation((client: ReactNativeLDClient, setState: any) => {
setState({ client });
});
ldc = new ReactNativeLDClient('mobile-key');
context = { kind: 'user', key: 'test-user-key-1' };
});

afterEach(() => {
jest.resetAllMocks();
});

test('client is correctly set', () => {
const { getByText } = render(
<LDProvider client={ldc}>
<TestApp />
</LDProvider>,
);

expect(getByText(/ldclient defined/i)).toBeTruthy();
expect(getByText(/mobilekey mobile-key/i)).toBeTruthy();
expect(getByText(/context undefined/i)).toBeTruthy();
});

test('specified context is identified', async () => {
const { getByText } = render(
<LDProvider client={ldc} context={context}>
<TestApp />
</LDProvider>,
);

expect(mockSetupListeners).toHaveBeenCalledWith(ldc, expect.any(Function));
expect(ldc.identify).toHaveBeenCalledWith(context);
expect(ldc.getContext()).toEqual(context);
expect(getByText(/context defined/i)).toBeTruthy();
});

test('identify errors are caught', async () => {
(ldc.identify as jest.Mock).mockImplementation(() => {
return Promise.reject('faking error when identifying');
});
const { getByText } = render(
<LDProvider client={ldc} context={context}>
<TestApp />
</LDProvider>,
);
await jest.runAllTimersAsync();

expect(ldc.logger.debug).toHaveBeenCalledWith(expect.stringMatching(/identify error/));
});
});
2 changes: 1 addition & 1 deletion packages/sdk/react-native/src/provider/LDProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PropsWithChildren, useEffect, useState } from 'react';
import React, { PropsWithChildren, useEffect, useState } from 'react';

import { type LDContext } from '@launchdarkly/js-client-sdk-common';

Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/react-native/src/provider/reactContext.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createContext } from 'react';

import { LDClient } from '@launchdarkly/js-client-sdk-common';
import type ReactNativeLDClient from '../ReactNativeLDClient';

export type ReactContext = {
client: LDClient;
client: ReactNativeLDClient;
};

export const context = createContext<ReactContext>({
Expand Down
32 changes: 32 additions & 0 deletions packages/sdk/react-native/src/provider/setupListeners.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ReactNativeLDClient from '../ReactNativeLDClient';
import setupListeners from './setupListeners';

import resetAllMocks = jest.resetAllMocks;

jest.mock('../ReactNativeLDClient');

describe('setupListeners', () => {
let ldc: ReactNativeLDClient;
let mockSetState: jest.Mock;

beforeEach(() => {
mockSetState = jest.fn();
ldc = new ReactNativeLDClient('mob-test-key');
});

afterEach(() => resetAllMocks());

test('change listener is setup', () => {
setupListeners(ldc, mockSetState);
expect(ldc.on).toHaveBeenCalledWith('change', expect.any(Function));
});

test('client is set on change event', () => {
setupListeners(ldc, mockSetState);

const changeHandler = (ldc.on as jest.Mock).mock.calls[0][1];
changeHandler();

expect(mockSetState).toHaveBeenCalledWith({ client: ldc });
});
});
11 changes: 4 additions & 7 deletions packages/sdk/react-native/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@
"allowSyntheticDefaultImports": true,
"declaration": true,
"declarationMap": true,
"jsx": "react-native",
"lib": [
"es6",
"dom"
],
"jsx": "react-jsx",
"lib": ["es6", "dom"],
"module": "ES6",
"moduleResolution": "node",
"noImplicitOverride": true,
Expand All @@ -21,7 +18,7 @@
"strict": true,
"stripInternal": true,
"target": "ES2017",
"types": ["jest", "node"]
"types": ["node"]
},
"exclude": ["**/*.test.ts", "dist", "node_modules", "__tests__", "example"]
"exclude": ["**/*.test.ts*", "dist", "node_modules", "__tests__", "example"]
}
14 changes: 14 additions & 0 deletions packages/sdk/react-native/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"esModuleInterop": true,
"jsx": "react-jsx",
"lib": ["es6", "dom"],
"module": "ES6",
"moduleResolution": "node",
"resolveJsonModule": true,
"rootDir": ".",
"strict": true,
"types": ["jest", "node"]
},
"exclude": ["dist", "node_modules", "__tests__", "example"]
}
8 changes: 2 additions & 6 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
{
"packages": {
"packages/shared/common": {},
"packages/shared/sdk-client": {
"bump-minor-pre-major": true
},
"packages/shared/sdk-client": {},
"packages/shared/sdk-server": {},
"packages/shared/sdk-server-edge": {},
"packages/shared/akamai-edgeworker-sdk": {},
"packages/sdk/cloudflare": {},
"packages/sdk/react-native": {
"bump-minor-pre-major": true
},
"packages/sdk/react-native": {},
"packages/sdk/server-node": {},
"packages/sdk/vercel": {
"extra-files": ["src/createPlatformInfo.ts"]
Expand Down

0 comments on commit 913bc00

Please sign in to comment.