Skip to content

Commit

Permalink
Merge pull request auth0#81 from auth0/added-link-dev-improvements
Browse files Browse the repository at this point in the history
Return error if native module is not linked
  • Loading branch information
hzalaz committed Aug 18, 2017
2 parents 7008ad2 + d7f8d97 commit 8fb9d55
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 6 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,6 @@ gen-external-apklibs

# Release process
.release
.release-tmp-*/
.release-tmp-*/

.project
27 changes: 27 additions & 0 deletions webauth/__mocks__/auth0.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default class A0Auth0 {
showUrl(url, closeOnLoad, callback) {
this.url = url;
this.hidden = false;
if (this.error || closeOnLoad) {
callback(this.error);
} else {
this.onUrl();
}
}

hide() {
this.hidden = true;
}

reset() {
this.url = null;
this.error = null;
this.hidden = true;
this.parameters = null;
this.onUrl = () => {};
}

oauthParameters(callback) {
callback(this.parameters);
}
}
17 changes: 17 additions & 0 deletions webauth/__mocks__/linking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import EventEmitter from 'events';

class CustomEmitter extends EventEmitter {}

export default class Linking {
constructor() {
this.emitter = new CustomEmitter();
}

addEventListener(event, fn) {
this.emitter.addListener(event, fn);
}

removeEventListener(event, fn) {
this.emitter.removeListener(event, fn);
}
}
9 changes: 9 additions & 0 deletions webauth/__mocks__/react-native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Linking from './linking';
import A0Auth0 from './auth0';

const mock = {};

mock.Linking = new Linking();
mock.NativeModules = { A0Auth0: new A0Auth0() };

module.exports = mock;
15 changes: 15 additions & 0 deletions webauth/__tests__/__snapshots__/agent.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Agent newTransaction should call native integration 1`] = `
Object {
"state": "state",
}
`;

exports[`Agent newTransaction should fail if native module is not linked 1`] = `[Error: Missing NativeModule. Please make sure you run \`react-native link react-native-auth0\`]`;

exports[`Agent show complete web flow should resolve promise with url result 1`] = `"https://auth0.com"`;

exports[`Agent show failed flow should reject with error 1`] = `[Error: failed to load]`;

exports[`Agent show should fail if native module is not linked 1`] = `[Error: Missing NativeModule. Please make sure you run \`react-native link react-native-auth0\`]`;
105 changes: 105 additions & 0 deletions webauth/__tests__/agent.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
jest.mock('react-native');
import Agent from '../agent';
import { NativeModules, Linking } from 'react-native';
const A0Auth0 = NativeModules.A0Auth0;

describe('Agent', () => {
const agent = new Agent();

describe('show', () => {

beforeEach(() => {
NativeModules.A0Auth0 = A0Auth0;
A0Auth0.reset();
});

it('should fail if native module is not linked', async () => {
NativeModules.A0Auth0 = undefined;
expect.assertions(1);
await expect(agent.show('https://auth0.com')).rejects.toMatchSnapshot();
});

describe('complete web flow', () => {
beforeEach(() => {
A0Auth0.onUrl = () => {
Linking.emitter.emit('url', {url: 'https://auth0.com'});
};
});

it('should resolve promise with url result', async () => {
expect.assertions(1);
await expect(agent.show('https://auth0.com')).resolves.toMatchSnapshot();
});

it('should show initial url', async () => {
expect.assertions(1);
const url = 'https://auth0.com/authorize';
await agent.show(url);
expect(A0Auth0.url).toEqual(url);
});
});

describe('listeners', () => {

it('should register url listeners', () => {
A0Auth0.onUrl = () => {};
const url = 'https://auth0.com/authorize';
agent.show(url);
expect(Linking.emitter.listenerCount('url')).toEqual(1);
});

it('should remove url listeners when done', async () => {
A0Auth0.onUrl = () => {
Linking.emitter.emit('url', {url: 'https://auth0.com'});
};
expect.assertions(1);
const url = 'https://auth0.com/authorize';
await agent.show(url);
expect(Linking.emitter.listenerCount('url')).toEqual(0);
});

it('should remove url listeners when load fails', async () => {
expect.assertions(1);
A0Auth0.error = new Error('failed to load');
const url = 'https://auth0.com/authorize';
await agent.show(url).catch((err) => Promise.resolve(err));
expect(Linking.emitter.listenerCount('url')).toEqual(0);
});

it('should remove url listeners on first load', async () => {
expect.assertions(1);
const url = 'https://auth0.com/authorize';
await agent.show(url, true);
expect(Linking.emitter.listenerCount('url')).toEqual(0);
});

});

describe('failed flow', () => {

it('should reject with error', async () => {
expect.assertions(1);
A0Auth0.error = new Error('failed to load');
await expect(agent.show('https://auth0.com')).rejects.toMatchSnapshot();
});

});
});

describe('newTransaction', () => {

it('should call native integration', async () => {
const parameters = {state: 'state'};
A0Auth0.parameters = parameters;
expect.assertions(1);
await expect(agent.newTransaction()).resolves.toMatchSnapshot();
});

it('should fail if native module is not linked', async () => {
NativeModules.A0Auth0 = undefined;
expect.assertions(1);
await expect(agent.newTransaction()).rejects.toMatchSnapshot();
});

});
});
16 changes: 11 additions & 5 deletions webauth/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import {
Linking
} from 'react-native';

const { A0Auth0 } = NativeModules;

export default class Agent {

show(url, closeOnLoad = false) {
if (!NativeModules.A0Auth0) {
return Promise.reject(new Error('Missing NativeModule. Please make sure you run `react-native link react-native-auth0`'));
}

return new Promise((resolve, reject) => {
const urlHandler = (event) => {
A0Auth0.hide();
NativeModules.A0Auth0.hide();
Linking.removeEventListener('url', urlHandler);
resolve(event.url);
};
Linking.addEventListener('url', urlHandler);
A0Auth0.showUrl(url, closeOnLoad, (err) => {
NativeModules.A0Auth0.showUrl(url, closeOnLoad, (err) => {
Linking.removeEventListener('url', urlHandler);
if (err) {
reject(err);
Expand All @@ -27,8 +29,12 @@ export default class Agent {
}

newTransaction() {
if (!NativeModules.A0Auth0) {
return Promise.reject(new Error('Missing NativeModule. Please make sure you run `react-native link react-native-auth0`'));
}

return new Promise((resolve, reject) => {
A0Auth0.oauthParameters((parameters) => {
NativeModules.A0Auth0.oauthParameters((parameters) => {
resolve(parameters);
});
});
Expand Down

0 comments on commit 8fb9d55

Please sign in to comment.