Skip to content

Commit

Permalink
tests(auth, e2e): re-enable tests, use auth emulator
Browse files Browse the repository at this point in the history
Found at least 2 unexpected real issues along the way
The emulator is great though, no API limits
  • Loading branch information
mikehardy committed Nov 15, 2020
1 parent 010d46d commit 46cba37
Show file tree
Hide file tree
Showing 10 changed files with 314 additions and 153 deletions.
12 changes: 12 additions & 0 deletions packages/app/e2e/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
exports.getE2eTestProject = function getE2eTestProject() {
return 'react-native-firebase-testing';
};

// Android requires a re-mapped hostname during testing sometimes
exports.getE2eEmulatorHost = function getE2eEmulatorHost() {
// This appears to work from localhost even on android. Different execution context?
// if (platform === 'android') {
// return '10.0.2.2';
// }
return 'localhost';
};
88 changes: 54 additions & 34 deletions packages/auth/e2e/auth.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,41 @@
*
*/

const TEST_EMAIL = '[email protected]';
const TEST_PASS = 'test1234';

const DISABLED_EMAIL = '[email protected]';
const DISABLED_PASS = 'test1234';

const { clearAllUsers } = require('./helpers');

describe('auth()', () => {
before(async () => {
try {
await clearAllUsers();
await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS);
} catch (e) {
// they may already exist, that's fine
}
// Need a way to create the user but have it disabled immediately
// If we had the functions emulator running as well, it would work:
// https://stackoverflow.com/questions/43140441/how-to-disable-user-accounts-on-firebase-authentication-automatically#comment73363725_43141780
// try {
// const userCredential = await firebase
// .auth()
// .createUserWithEmailAndPassword(DISABLED_EMAIL, DISABLED_PASS);
// } catch (e) {
// // they may already exist, that's fine
// }
});

beforeEach(async () => {
if (firebase.auth().currentUser) {
await firebase.auth().signOut();
await Utils.sleep(50);
}
});

describe('namespace', () => {
it('accessible from firebase.app()', () => {
const app = firebase.app();
Expand All @@ -39,6 +73,7 @@ describe('auth()', () => {
});

describe('applyActionCode()', () => {
// Needs a different setup to work against the auth emulator
xit('works as expected', async () => {
await firebase
.auth()
Expand Down Expand Up @@ -127,16 +162,14 @@ describe('auth()', () => {
});

describe('signInWithCustomToken()', () => {
it('signs in with a admin sdk created custom auth token', async () => {
const email = '[email protected]';
const pass = 'test1234';

// Needs a different setup when running against the emulator
xit('signs in with a admin sdk created custom auth token', async () => {
const successCb = currentUserCredential => {
const currentUser = currentUserCredential.user;
currentUser.should.be.an.Object();
currentUser.uid.should.be.a.String();
currentUser.toJSON().should.be.an.Object();
currentUser.toJSON().email.should.eql(email);
currentUser.toJSON().email.should.eql(TEST_EMAIL);
currentUser.isAnonymous.should.equal(false);
currentUser.providerId.should.equal('firebase');
currentUser.should.equal(firebase.auth().currentUser);
Expand All @@ -150,7 +183,7 @@ describe('auth()', () => {

const user = await firebase
.auth()
.signInWithEmailAndPassword(email, pass)
.signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS)
.then(successCb);

const IdToken = await firebase.auth().currentUser.getIdToken();
Expand All @@ -162,7 +195,7 @@ describe('auth()', () => {

await firebase.auth().signInWithCustomToken(token);

firebase.auth().currentUser.email.should.equal('[email protected]');
firebase.auth().currentUser.email.should.equal(TEST_EMAIL);
});
});

Expand Down Expand Up @@ -540,15 +573,12 @@ describe('auth()', () => {

describe('signInWithEmailAndPassword()', () => {
it('it should login with email and password', () => {
const email = '[email protected]';
const pass = 'test1234';

const successCb = currentUserCredential => {
const currentUser = currentUserCredential.user;
currentUser.should.be.an.Object();
currentUser.uid.should.be.a.String();
currentUser.toJSON().should.be.an.Object();
currentUser.toJSON().email.should.eql(email);
currentUser.toJSON().email.should.eql(TEST_EMAIL);
currentUser.isAnonymous.should.equal(false);
currentUser.providerId.should.equal('firebase');
currentUser.should.equal(firebase.auth().currentUser);
Expand All @@ -562,14 +592,12 @@ describe('auth()', () => {

return firebase
.auth()
.signInWithEmailAndPassword(email, pass)
.signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS)
.then(successCb);
});

it('it should error on login if user is disabled', () => {
const email = '[email protected]';
const pass = 'test1234';

// Need to set these up differently to run against emulator
xit('it should error on login if user is disabled', () => {
const successCb = () => Promise.reject(new Error('Did not error.'));

const failureCb = error => {
Expand All @@ -580,15 +608,12 @@ describe('auth()', () => {

return firebase
.auth()
.signInWithEmailAndPassword(email, pass)
.signInWithEmailAndPassword(DISABLED_EMAIL, DISABLED_PASS)
.then(successCb)
.catch(failureCb);
});

it('it should error on login if password incorrect', () => {
const email = '[email protected]';
const pass = 'test1234666';

const successCb = () => Promise.reject(new Error('Did not error.'));

const failureCb = error => {
Expand All @@ -601,7 +626,7 @@ describe('auth()', () => {

return firebase
.auth()
.signInWithEmailAndPassword(email, pass)
.signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS + '666')
.then(successCb)
.catch(failureCb);
});
Expand Down Expand Up @@ -631,14 +656,14 @@ describe('auth()', () => {

describe('signInWithCredential()', () => {
it('it should login with email and password', () => {
const credential = firebase.auth.EmailAuthProvider.credential('[email protected]', 'test1234');
const credential = firebase.auth.EmailAuthProvider.credential(TEST_EMAIL, TEST_PASS);

const successCb = currentUserCredential => {
const currentUser = currentUserCredential.user;
currentUser.should.be.an.Object();
currentUser.uid.should.be.a.String();
currentUser.toJSON().should.be.an.Object();
currentUser.toJSON().email.should.eql('[email protected]');
currentUser.toJSON().email.should.eql(TEST_EMAIL);
currentUser.isAnonymous.should.equal(false);
currentUser.providerId.should.equal('firebase');
currentUser.should.equal(firebase.auth().currentUser);
Expand All @@ -656,11 +681,9 @@ describe('auth()', () => {
.then(successCb);
});

it('it should error on login if user is disabled', () => {
const credential = firebase.auth.EmailAuthProvider.credential(
'[email protected]',
'test1234',
);
// Need to set these up differently to run against emulator
xit('it should error on login if user is disabled', () => {
const credential = firebase.auth.EmailAuthProvider.credential(DISABLED_EMAIL, DISABLED_PASS);

const successCb = () => Promise.reject(new Error('Did not error.'));

Expand All @@ -678,7 +701,7 @@ describe('auth()', () => {
});

it('it should error on login if password incorrect', () => {
const credential = firebase.auth.EmailAuthProvider.credential('[email protected]', 'test1234666');
const credential = firebase.auth.EmailAuthProvider.credential(TEST_EMAIL, TEST_PASS + '666');

const successCb = () => Promise.reject(new Error('Did not error.'));

Expand Down Expand Up @@ -770,9 +793,6 @@ describe('auth()', () => {
});

it('it should error on create if email in use', () => {
const email = '[email protected]';
const pass = 'test123456789';

const successCb = () => Promise.reject(new Error('Did not error.'));

const failureCb = error => {
Expand All @@ -783,7 +803,7 @@ describe('auth()', () => {

return firebase
.auth()
.createUserWithEmailAndPassword(email, pass)
.createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS)
.then(successCb)
.catch(failureCb);
});
Expand Down Expand Up @@ -824,7 +844,7 @@ describe('auth()', () => {

return firebase
.auth()
.fetchSignInMethodsForEmail('[email protected]')
.fetchSignInMethodsForEmail(TEST_EMAIL)
.then(successCb)
.catch(failureCb);
}));
Expand Down
91 changes: 91 additions & 0 deletions packages/auth/e2e/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable no-console */
const { getE2eTestProject, getE2eEmulatorHost } = require('../../app/e2e/helpers');
const http = require('http');

exports.getRandomPhoneNumber = function getRandomPhoneNumber() {
return '+593' + Utils.randString(9, '#19');
};

exports.clearAllUsers = async function clearAllUsers() {
// console.log('auth::helpers::clearAllUsers');
try {
const deleteOptions = {
method: 'DELETE',
headers: {
// Undocumented, but necessary - pulled from watching raw Emulator Web UI network requests
Authorization: 'Bearer owner',
},
port: 9099,
host: getE2eEmulatorHost(),
path: '/emulator/v1/projects/' + getE2eTestProject() + '/accounts',
};
// console.log('request: ' + JSON.stringify(deleteOptions));
await new Promise((resolve, reject) => {
const req = http.request(deleteOptions);
req.on('error', error => reject(error));
req.end(resolve());
});
} catch (e) {
console.error('Unable to wipe auth:', e);
throw e;
}
};

// Email / OOB codes are here http://localhost:9099/emulator/v1/projects/react-native-firebase-testing/oobCodes

exports.getLastSmsCode = async function getLastSmsCode(specificPhone) {
let lastSmsCode = null;
try {
// console.log('auth::e2e:helpers:getLastSmsCode - start');
const getSmsCodesUrl =
'http://' +
getE2eEmulatorHost() +
':9099/emulator/v1/projects/' +
getE2eTestProject() +
'/verificationCodes';

const responseData = await new Promise((resolve, reject) => {
// console.log('auth::e2e:helpers:getLastSmsCode - making request');
const req = http.get(getSmsCodesUrl, response => {
// console.log('auth::e2e:helpers:getLastSmsCode - callback');
let data = '';
response.on('data', chunk => {
// console.log('auth::e2e:helpers:getLastSmsCode - request callback response data callback');
// console.log('data event, got chunk: ' + chunk);
data += chunk;
});
response.on('end', () => {
// console.log('auth::e2e:helpers:getLastSmsCode - request callback response end callback');
resolve(JSON.parse(data));
});
});
req.on('error', error => reject(error));
});
// Process the codes, the last one in the array is the one...
// console.log('getLastSmsCode got ', JSON.stringify(responseData, null, 2));
const codes = responseData ? responseData.verificationCodes : undefined;
if (codes && codes.length > 0) {
if (specificPhone) {
// roll through backwards (to get last valid code) searching for the specific phone
for (let i = codes.length - 1; i >= 0 && !lastSmsCode; i--) {
const codeBlock = codes[i];
if (codeBlock.phoneNumber === specificPhone) {
lastSmsCode = codeBlock.code;
}
}
} else {
lastSmsCode = codes[codes.length - 1].code;
}
} else {
throw new Error('There were no unused verification codes');
}
} catch (e) {
console.error('Unable to get SMS Verification codes', e);
throw e;
}
// console.log('getLastSmsCode returning code: ' + lastSmsCode);
return lastSmsCode;
};

// https://firebase.google.com/docs/reference/rest/auth#section-auth-emulator-smsverification
// const smsCodeFromREST = 'not-implemented';
Loading

0 comments on commit 46cba37

Please sign in to comment.