Skip to content

Commit

Permalink
test: improve unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
1fabiopereira committed Jun 20, 2023
1 parent 2addc96 commit b07b9cf
Show file tree
Hide file tree
Showing 9 changed files with 292 additions and 162 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-pdf-extractor",
"version": "0.2.0",
"version": "0.2.1",
"description": "This library allows you to extract pdfs file data using matches specifics patterns.",
"main": "lib/commonjs/index.js",
"module": "lib/module/index.js",
Expand Down Expand Up @@ -61,7 +61,8 @@
},
"peerDependencies": {
"react": "*",
"react-native": "*"
"react-native": "*",
"react-native-modal": "*"
},
"commitlint": {
"extends": [
Expand Down
4 changes: 2 additions & 2 deletions sample/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Button, FlatList, StyleSheet, Text, View } from 'react-native';
import DocumentPicker from 'react-native-document-picker';

import { Extractor, Patterns } from '../..';
import { TransientObject } from '../../src/types';
import { Transient } from '../../src/types';

const App: React.FC = (): JSX.Element => {
const [isEncrypted, setIsEncrypted] = useState<boolean | undefined>(false);
Expand All @@ -22,7 +22,7 @@ const App: React.FC = (): JSX.Element => {
setUri(data.uri);
};

const onResult = (data: TransientObject) => {
const onResult = (data: Transient) => {
setPages(data.pages);
setIsEncrypted(data.isEncrypted);
setUri(data.uri);
Expand Down
144 changes: 144 additions & 0 deletions src/extractors/__tests__/Common.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { Platform } from 'react-native';
import { BaseExtractor } from '../core/Base';
import { CommonExtractor } from '../core/Common';

const platformMock = (platform: 'android' | 'ios') => {
Object.defineProperty(Platform, 'OS', { get: jest.fn(() => platform) });
};

const asyncMock = <T>(value: T) => jest.fn().mockResolvedValue(value);

describe('CommonExtractor', () => {
beforeEach(() => jest.clearAllMocks());

describe('file', () => {
it('Should call setUri', async () => {
BaseExtractor.setUri = asyncMock('fake://return');
const spy = jest.spyOn(BaseExtractor, 'setUri');

await CommonExtractor.file({ uri: 'file://fake-uri' });

expect(spy).toBeCalledTimes(1);
});

it('Should throw error when try setUri', async () => {
BaseExtractor.setUri = asyncMock(null);
const spy = jest.spyOn(BaseExtractor, 'setUri');

try {
await CommonExtractor.file({ uri: 'file://fake-uri' });
} catch (error: any) {
expect(spy).toBeCalledTimes(1);
expect(error.message).toBe(
"Invalid uri: 'file://fake-uri'. Cannot find the file."
);
}
});

it('Should call getUri when platform is Android', async () => {
platformMock('android');
const spy = jest.spyOn(BaseExtractor, 'getUri');

try {
await CommonExtractor.file({ uri: undefined });
} catch (error: any) {
expect(error.message).toBe('Could not perfom extraction without URI.');
}

expect(spy).toBeCalledTimes(1);
});

it('Should not call getUri when platform is iOS', async () => {
platformMock('ios');

const spy = jest.spyOn(BaseExtractor, 'getUri');

try {
await CommonExtractor.file({ uri: undefined });
} catch { }

expect(spy).toBeCalledTimes(0);
});
});

describe('check', () => {
it('Should call canIExtract', async () => {
BaseExtractor.canIExtract = asyncMock(true);
const spy = jest.spyOn(BaseExtractor, 'canIExtract');

await CommonExtractor.check({});

expect(spy).toBeCalledTimes(1);
});

it('Should throw error when call canIExtract', async () => {
BaseExtractor.canIExtract = asyncMock(false);
const spy = jest.spyOn(BaseExtractor, 'canIExtract');

try {
await CommonExtractor.check({ uri: undefined });
} catch (error: any) {
expect(error.message).toBe('You cannot continue with extraction.');
}

expect(spy).toBeCalledTimes(1);
});
});

describe('encrypted', () => {
it('Should call isEncrypted', async () => {
BaseExtractor.isEncrypted = asyncMock(false);
const spy = jest.spyOn(BaseExtractor, 'isEncrypted');

await CommonExtractor.encrypted({});

expect(spy).toBeCalledTimes(1);
});
});

describe('pages', () => {
it('Should call getNumberOfPages', async () => {
BaseExtractor.getNumberOfPages = asyncMock(10);
const spy = jest.spyOn(BaseExtractor, 'getNumberOfPages');

await CommonExtractor.pages({ max: 10 });

expect(spy).toBeCalledTimes(1);
});

it('Should call getNumberOfPages and throw error', async () => {
BaseExtractor.getNumberOfPages = asyncMock(12);
const spy = jest.spyOn(BaseExtractor, 'getNumberOfPages');

try {
await CommonExtractor.pages({ max: 10 });
} catch (error: any) {
expect(error.message).toBe(
'This file exceeds maximum size of 10 pages.'
);
}

expect(spy).toBeCalledTimes(1);
});
});

describe('matches', () => {
it('Should call getText', async () => {
BaseExtractor.getText = asyncMock(['abc']);
const spy = jest.spyOn(BaseExtractor, 'getText');

await CommonExtractor.matches({ max: 1 });

expect(spy).toBeCalledTimes(1);
});

it('Should call getTextWithPattern', async () => {
BaseExtractor.getTextWithPattern = asyncMock(['abc']);
const spy = jest.spyOn(BaseExtractor, 'getTextWithPattern');

await CommonExtractor.matches({ max: 1, patterns: /[0-9]{2}/ });

expect(spy).toBeCalledTimes(1);
});
});
});
71 changes: 71 additions & 0 deletions src/extractors/core/Common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Platform } from 'react-native';
import { BaseExtractor } from './Base';
import type { ExtraTransient, Transient } from '../../types';

export class CommonExtractor {
/**
* Verifies if file exists based on URI gave
* or got from intent provider (Android only)
*/
static async file(data: Transient): Promise<Transient> {
if (data.uri) {
const path = await BaseExtractor.setUri(data.uri);

if (path) return { ...data, uri: path };

throw new Error(`Invalid uri: '${data.uri}'. Cannot find the file.`);
}

// From Intent (android only)
if (Platform.OS === 'android') {
const path = await BaseExtractor.getUri();
if (path) return { ...data, uri: path };
}

throw new Error('Could not perfom extraction without URI.');
}

/**
* Checks if params satisfies full specification
* to proceed with data extraction
*/
static async check(data: Transient): Promise<Transient> {
const canIExtract = await BaseExtractor.canIExtract();

if (canIExtract) return data;

throw new Error('You cannot continue with extraction.');
}

/**
* Checks if file is encrypted
*/
static async encrypted(data: Transient): Promise<Transient> {
const isEncrypted = await BaseExtractor.isEncrypted();
return { ...data, isEncrypted };
}

/**
* Counts the number of pages
*/
static async pages(data: ExtraTransient): Promise<Transient> {
const total = await BaseExtractor.getNumberOfPages(data.password);

if (total > data.max) {
throw new Error(`This file exceeds maximum size of ${data.max} pages.`);
}

return { ...data, pages: total };
}

/**
* Applies matches
*/
static async matches(data: ExtraTransient): Promise<Transient> {
const text = !data.patterns
? await BaseExtractor.getText(data.password)
: await BaseExtractor.getTextWithPattern(data.patterns, data.password);

return { ...data, text };
}
}
Loading

0 comments on commit b07b9cf

Please sign in to comment.