Skip to content

Commit

Permalink
feat(auth, emulator): add useEmulator javascript code + jest tests
Browse files Browse the repository at this point in the history
Native implementation is not complete in this commit, but that is next
  • Loading branch information
mikehardy committed Nov 16, 2020
1 parent 441c52b commit 532adb5
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 5 deletions.
24 changes: 19 additions & 5 deletions jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ jest.doMock('react-native', () => {
},
NativeModules: {
...ReactNative.NativeModules,
RNFBAdMobModule: {},
RNFBAdMobInterstitialModule: {},
RNFBAdMobRewardedModule: {},
RNFBAdsConsentModule: {},
RNFBAppModule: {
NATIVE_FIREBASE_APPS: [
{
Expand All @@ -25,13 +29,23 @@ jest.doMock('react-native', () => {
options: {},
},
],
addListener: jest.fn(),
eventsAddListener: jest.fn(),
eventsNotifyReady: jest.fn(),
},
RNFBAuthModule: {
APP_LANGUAGE: {
'[DEFAULT]': 'en-US',
},
APP_USER: {
'[DEFAULT]': 'jestUser',
},
addAuthStateListener: jest.fn(),
addIdTokenListener: jest.fn(),
useEmulator: jest.fn(),
},
RNFBPerfModule: {},
RNFBAdMobModule: {},
RNFBAdMobInterstitialModule: {},
RNFBAdMobRewardedModule: {},
RNFBAdsConsentModule: {},
RNFBCrashlyticsModule: {},
RNFBPerfModule: {},
},
},
ReactNative,
Expand Down
46 changes: 46 additions & 0 deletions packages/auth/__tests__/auth.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import auth, { firebase } from '../lib';

describe('Auth', () => {
describe('namespace', () => {
it('accessible from firebase.app()', () => {
const app = firebase.app();
expect(app.auth).toBeDefined();
expect(app.auth().useEmulator).toBeDefined();
});
});

describe('useEmulator()', () => {
it('useEmulator requires a string url', () => {
// @ts-ignore because we pass an invalid argument...
expect(() => auth().useEmulator()).toThrow(
'firebase.auth().useEmulator() takes a non-empty string',
);
expect(() => auth().useEmulator('')).toThrow(
'firebase.auth().useEmulator() takes a non-empty string',
);
// @ts-ignore because we pass an invalid argument...
expect(() => auth().useEmulator(123)).toThrow(
'firebase.auth().useEmulator() takes a non-empty string',
);
});

it('useEmulator requires a well-formed url', () => {
// No http://
expect(() => auth().useEmulator('localhost:9099')).toThrow(
'firebase.auth().useEmulator() unable to parse host and port from url',
);
// No port
expect(() => auth().useEmulator('http://localhost')).toThrow(
'firebase.auth().useEmulator() unable to parse host and port from url',
);
});

it('useEmulator -> remaps Android loopback to host', () => {
const foo = auth().useEmulator('http://localhost:9099');
expect(foo).toEqual(['10.0.2.2', 9099]);

const bar = auth().useEmulator('http://127.0.0.1:9099');
expect(bar).toEqual(['10.0.2.2', 9099]);
});
});
});
8 changes: 8 additions & 0 deletions packages/auth/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,14 @@ export namespace FirebaseAuthTypes {
* @param userAccessGroup A string of the keychain id i.e. "TEAMID.com.example.group1"
*/
useUserAccessGroup(userAccessGroup: string): Promise<null>;
/**
* Modify this Auth instance to communicate with the Firebase Auth emulator.
* This must be called synchronously immediately following the first call to firebase.auth().
* Do not use with production credentials as emulator traffic is not encrypted.
*
* @param url: emulator URL, must have host and port (eg, 'http://localhost:9099')
*/
useEmulator(url: string): void;
}
}

Expand Down
27 changes: 27 additions & 0 deletions packages/auth/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,33 @@ class FirebaseAuthModule extends FirebaseModule {
'firebase.auth().useDeviceLanguage() is unsupported by the native Firebase SDKs.',
);
}

useEmulator(url) {
if (!url || !isString(url) || url === '') {
throw new Error('firebase.auth().useEmulator() takes a non-empty string');
}

let _url = url;
if (isAndroid && _url) {
if (_url.startsWith('http://localhost')) {
_url = _url.replace('http://localhost', 'http://10.0.2.2');
}
if (_url.startsWith('http://127.0.0.1')) {
_url = _url.replace('http://127.0.0.1', 'http://10.0.2.2');
}
}

// Native calls take the host and port split out
const hostPortRegex = /^http:\/\/([\w\d.]+):(\d+)$/;
const urlMatches = _url.match(hostPortRegex);
if (!urlMatches) {
throw new Error('firebase.auth().useEmulator() unable to parse host and port from url');
}
const host = urlMatches[1];
const port = parseInt(urlMatches[2], 10);
this.native.useEmulator(host, port);
return [host, port]; // undocumented return, useful for unit testing
}
}

// import { SDK_VERSION } from '@react-native-firebase/auth';
Expand Down

0 comments on commit 532adb5

Please sign in to comment.