diff --git a/packages/auth/e2e/auth.e2e.js b/packages/auth/e2e/auth.e2e.js index 112fafa016..2e01e90152 100644 --- a/packages/auth/e2e/auth.e2e.js +++ b/packages/auth/e2e/auth.e2e.js @@ -24,926 +24,949 @@ const DISABLED_PASS = 'test1234'; const { clearAllUsers, disableUser, getLastOob, resetPassword } = require('./helpers'); describe('auth() modular', function () { - describe('firebase v8 compatibility', function () { - before(async function () { - await clearAllUsers(); - await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - const disabledUserCredential = await firebase - .auth() - .createUserWithEmailAndPassword(DISABLED_EMAIL, DISABLED_PASS); - await disableUser(disabledUserCredential.user.uid); - }); - - beforeEach(async function () { - if (firebase.auth().currentUser) { - await firebase.auth().signOut(); - await Utils.sleep(50); - } - }); + !skipCompatTests && + describe('firebase v8 compatibility', function () { + before(async function () { + await clearAllUsers(); + await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + const disabledUserCredential = await firebase + .auth() + .createUserWithEmailAndPassword(DISABLED_EMAIL, DISABLED_PASS); + await disableUser(disabledUserCredential.user.uid); + }); - describe('namespace', function () { - it('accessible from firebase.app()', function () { - const app = firebase.app(); - should.exist(app.auth); - app.auth().app.should.equal(app); + beforeEach(async function () { + if (firebase.auth().currentUser) { + await firebase.auth().signOut(); + await Utils.sleep(50); + } }); - // removing as pending if module.options.hasMultiAppSupport = true - it('supports multiple apps', async function () { - firebase.auth().app.name.should.equal('[DEFAULT]'); + describe('namespace', function () { + it('accessible from firebase.app()', function () { + const app = firebase.app(); + should.exist(app.auth); + app.auth().app.should.equal(app); + }); - firebase - .auth(firebase.app('secondaryFromNative')) - .app.name.should.equal('secondaryFromNative'); + // removing as pending if module.options.hasMultiAppSupport = true + it('supports multiple apps', async function () { + firebase.auth().app.name.should.equal('[DEFAULT]'); - firebase.app('secondaryFromNative').auth().app.name.should.equal('secondaryFromNative'); - }); - }); + firebase + .auth(firebase.app('secondaryFromNative')) + .app.name.should.equal('secondaryFromNative'); - describe('applyActionCode()', function () { - // Needs a different setup to work against the auth emulator - xit('works as expected', async function () { - await firebase - .auth() - .applyActionCode('fooby shooby dooby') - .then($ => $); + firebase.app('secondaryFromNative').auth().app.name.should.equal('secondaryFromNative'); + }); }); - it('errors on invalid code', async function () { - try { + describe('applyActionCode()', function () { + // Needs a different setup to work against the auth emulator + xit('works as expected', async function () { await firebase .auth() .applyActionCode('fooby shooby dooby') .then($ => $); - } catch (e) { - e.message.should.containEql('code is invalid'); - } + }); + + it('errors on invalid code', async function () { + try { + await firebase + .auth() + .applyActionCode('fooby shooby dooby') + .then($ => $); + } catch (e) { + e.message.should.containEql('code is invalid'); + } + }); }); - }); - describe('checkActionCode()', function () { - it('errors on invalid code', async function () { - try { - await firebase.auth().checkActionCode('fooby shooby dooby'); - } catch (e) { - e.message.should.containEql('code is invalid'); - } + describe('checkActionCode()', function () { + it('errors on invalid code', async function () { + try { + await firebase.auth().checkActionCode('fooby shooby dooby'); + } catch (e) { + e.message.should.containEql('code is invalid'); + } + }); }); - }); - describe('reload()', function () { - it('Meta data returns as expected with annonymous sign in', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(50); - const firstUser = firebase.auth().currentUser; - await firstUser.reload(); + describe('reload()', function () { + it('Meta data returns as expected with annonymous sign in', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(50); + const firstUser = firebase.auth().currentUser; + await firstUser.reload(); - await firebase.auth().signOut(); + await firebase.auth().signOut(); - await firebase.auth().signInAnonymously(); - await Utils.sleep(50); - const secondUser = firebase.auth().currentUser; - await secondUser.reload(); + await firebase.auth().signInAnonymously(); + await Utils.sleep(50); + const secondUser = firebase.auth().currentUser; + await secondUser.reload(); - firstUser.metadata.creationTime.should.not.equal(secondUser.metadata.creationTime); - }); + firstUser.metadata.creationTime.should.not.equal(secondUser.metadata.creationTime); + }); - it('Meta data returns as expected with email and password sign in', async function () { - const random = Utils.randString(12, '#aA'); - const email1 = `${random}@${random}.com`; - const pass = random; + it('Meta data returns as expected with email and password sign in', async function () { + const random = Utils.randString(12, '#aA'); + const email1 = `${random}@${random}.com`; + const pass = random; - await firebase.auth().createUserWithEmailAndPassword(email1, pass); - const firstUser = firebase.auth().currentUser; - await firstUser.reload(); + await firebase.auth().createUserWithEmailAndPassword(email1, pass); + const firstUser = firebase.auth().currentUser; + await firstUser.reload(); - await firebase.auth().signOut(); + await firebase.auth().signOut(); - const anotherRandom = Utils.randString(12, '#aA'); - const email2 = `${anotherRandom}@${anotherRandom}.com`; + const anotherRandom = Utils.randString(12, '#aA'); + const email2 = `${anotherRandom}@${anotherRandom}.com`; - await firebase.auth().createUserWithEmailAndPassword(email2, pass); - const secondUser = firebase.auth().currentUser; - await secondUser.reload(); + await firebase.auth().createUserWithEmailAndPassword(email2, pass); + const secondUser = firebase.auth().currentUser; + await secondUser.reload(); - firstUser.metadata.creationTime.should.not.equal(secondUser.metadata.creationTime); + firstUser.metadata.creationTime.should.not.equal(secondUser.metadata.creationTime); + }); }); - }); - describe('confirmPasswordReset()', function () { - it('errors on invalid code via API', async function () { - try { - await firebase.auth().confirmPasswordReset('fooby shooby dooby', 'passwordthing'); - } catch (e) { - e.message.should.containEql('code is invalid'); - } + describe('confirmPasswordReset()', function () { + it('errors on invalid code via API', async function () { + try { + await firebase.auth().confirmPasswordReset('fooby shooby dooby', 'passwordthing'); + } catch (e) { + e.message.should.containEql('code is invalid'); + } + }); }); - }); - - describe('signInWithCustomToken()', function () { - // Needs a different setup when running against the emulator - xit('signs in with a admin sdk created custom auth token', async function () { - 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(TEST_EMAIL); - currentUser.isAnonymous.should.equal(false); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); - const { additionalUserInfo } = currentUserCredential; - additionalUserInfo.should.be.an.Object(); - additionalUserInfo.isNewUser.should.equal(false); + describe('signInWithCustomToken()', function () { + // Needs a different setup when running against the emulator + xit('signs in with a admin sdk created custom auth token', async function () { + 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(TEST_EMAIL); + currentUser.isAnonymous.should.equal(false); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); + + const { additionalUserInfo } = currentUserCredential; + additionalUserInfo.should.be.an.Object(); + additionalUserInfo.isNewUser.should.equal(false); - return currentUser; - }; + return currentUser; + }; - const user = await firebase - .auth() - .signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS) - .then(successCb); + const user = await firebase + .auth() + .signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS) + .then(successCb); - const IdToken = await firebase.auth().currentUser.getIdToken(); + const IdToken = await firebase.auth().currentUser.getIdToken(); - firebase.auth().signOut(); - await Utils.sleep(50); + firebase.auth().signOut(); + await Utils.sleep(50); - const token = await new TestAdminApi(IdToken).auth().createCustomToken(user.uid, {}); + const token = await new TestAdminApi(IdToken).auth().createCustomToken(user.uid, {}); - await firebase.auth().signInWithCustomToken(token); + await firebase.auth().signInWithCustomToken(token); - firebase.auth().currentUser.email.should.equal(TEST_EMAIL); + firebase.auth().currentUser.email.should.equal(TEST_EMAIL); + }); }); - }); - describe('onAuthStateChanged()', function () { - it('calls callback with the current user and when auth state changes', async function () { - await firebase.auth().signInAnonymously(); + describe('onAuthStateChanged()', function () { + it('calls callback with the current user and when auth state changes', async function () { + await firebase.auth().signInAnonymously(); - await Utils.sleep(50); + await Utils.sleep(50); - // Test - const callback = sinon.spy(); + // Test + const callback = sinon.spy(); - let unsubscribe; - await new Promise(resolve => { - unsubscribe = firebase.auth().onAuthStateChanged(user => { - callback(user); - resolve(); + let unsubscribe; + await new Promise(resolve => { + unsubscribe = firebase.auth().onAuthStateChanged(user => { + callback(user); + resolve(); + }); }); - }); - - callback.should.be.calledWith(firebase.auth().currentUser); - callback.should.be.calledOnce(); - // Sign out + callback.should.be.calledWith(firebase.auth().currentUser); + callback.should.be.calledOnce(); - await firebase.auth().signOut(); + // Sign out - // Assertions + await firebase.auth().signOut(); - await Utils.sleep(50); + // Assertions - callback.should.be.calledWith(null); - callback.should.be.calledTwice(); + await Utils.sleep(50); - // Tear down + callback.should.be.calledWith(null); + callback.should.be.calledTwice(); - unsubscribe(); - }); + // Tear down - it('accept observer instead callback as well', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + unsubscribe(); + }); - // Test - const observer = { - next(user) { - // Test this access - this.onNext(); - this.user = user; - }, - }; + it('accept observer instead callback as well', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); + + // Test + const observer = { + next(user) { + // Test this access + this.onNext(); + this.user = user; + }, + }; - let unsubscribe; - await new Promise(resolve => { - observer.onNext = resolve; - unsubscribe = firebase.auth().onAuthStateChanged(observer); - }); - should.exist(observer.user); + let unsubscribe; + await new Promise(resolve => { + observer.onNext = resolve; + unsubscribe = firebase.auth().onAuthStateChanged(observer); + }); + should.exist(observer.user); - // Sign out + // Sign out - await firebase.auth().signOut(); + await firebase.auth().signOut(); - // Assertions + // Assertions - await Utils.sleep(50); + await Utils.sleep(50); - should.not.exist(observer.user); + should.not.exist(observer.user); - // Tear down + // Tear down - unsubscribe(); - }); + unsubscribe(); + }); - it('stops listening when unsubscribed', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + it('stops listening when unsubscribed', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); - // Test - const callback = sinon.spy(); + // Test + const callback = sinon.spy(); - let unsubscribe; - await new Promise(resolve => { - unsubscribe = firebase.auth().onAuthStateChanged(user => { - callback(user); - resolve(); + let unsubscribe; + await new Promise(resolve => { + unsubscribe = firebase.auth().onAuthStateChanged(user => { + callback(user); + resolve(); + }); }); - }); - callback.should.be.calledWith(firebase.auth().currentUser); - callback.should.be.calledOnce(); + callback.should.be.calledWith(firebase.auth().currentUser); + callback.should.be.calledOnce(); - // Sign out - await firebase.auth().signOut(); - await Utils.sleep(50); + // Sign out + await firebase.auth().signOut(); + await Utils.sleep(50); - // Assertions - callback.should.be.calledWith(null); - callback.should.be.calledTwice(); + // Assertions + callback.should.be.calledWith(null); + callback.should.be.calledTwice(); - // Unsubscribe - unsubscribe(); + // Unsubscribe + unsubscribe(); - // Sign back in - await firebase.auth().signInAnonymously(); + // Sign back in + await firebase.auth().signInAnonymously(); - // Assertions - callback.should.be.calledTwice(); + // Assertions + callback.should.be.calledTwice(); - // Tear down - await firebase.auth().signOut(); - await Utils.sleep(50); - }); + // Tear down + await firebase.auth().signOut(); + await Utils.sleep(50); + }); - it('returns the same user with multiple subscribers #1815', async function () { - const callback = sinon.spy(); + it('returns the same user with multiple subscribers #1815', async function () { + const callback = sinon.spy(); - let unsubscribe1; - let unsubscribe2; - let unsubscribe3; + let unsubscribe1; + let unsubscribe2; + let unsubscribe3; - await new Promise(resolve => { - unsubscribe1 = firebase.auth().onAuthStateChanged(user => { - callback(user); - resolve(); + await new Promise(resolve => { + unsubscribe1 = firebase.auth().onAuthStateChanged(user => { + callback(user); + resolve(); + }); }); - }); - await new Promise(resolve => { - unsubscribe2 = firebase.auth().onAuthStateChanged(user => { - callback(user); - resolve(); + await new Promise(resolve => { + unsubscribe2 = firebase.auth().onAuthStateChanged(user => { + callback(user); + resolve(); + }); }); - }); - await new Promise(resolve => { - unsubscribe3 = firebase.auth().onAuthStateChanged(user => { - callback(user); - resolve(); + await new Promise(resolve => { + unsubscribe3 = firebase.auth().onAuthStateChanged(user => { + callback(user); + resolve(); + }); }); - }); - callback.should.be.calledThrice(); - callback.should.be.calledWith(null); + callback.should.be.calledThrice(); + callback.should.be.calledWith(null); - await firebase.auth().signInAnonymously(); - await Utils.sleep(800); + await firebase.auth().signInAnonymously(); + await Utils.sleep(800); - unsubscribe1(); - unsubscribe2(); - unsubscribe3(); + unsubscribe1(); + unsubscribe2(); + unsubscribe3(); - callback.should.be.callCount(6); + callback.should.be.callCount(6); - const uid = callback.getCall(3).args[0].uid; + const uid = callback.getCall(3).args[0].uid; - callback.getCall(4).args[0].uid.should.eql(uid); - callback.getCall(5).args[0].uid.should.eql(uid); + callback.getCall(4).args[0].uid.should.eql(uid); + callback.getCall(5).args[0].uid.should.eql(uid); - await firebase.auth().signOut(); - await Utils.sleep(50); + await firebase.auth().signOut(); + await Utils.sleep(50); + }); }); - }); - describe('onIdTokenChanged()', function () { - it('calls callback with the current user and when auth state changes', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + describe('onIdTokenChanged()', function () { + it('calls callback with the current user and when auth state changes', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); - // Test - const callback = sinon.spy(); + // Test + const callback = sinon.spy(); - let unsubscribe; - await new Promise(resolve => { - unsubscribe = firebase.auth().onIdTokenChanged(user => { - callback(user); - resolve(); + let unsubscribe; + await new Promise(resolve => { + unsubscribe = firebase.auth().onIdTokenChanged(user => { + callback(user); + resolve(); + }); }); - }); - callback.should.be.calledWith(firebase.auth().currentUser); - callback.should.be.calledOnce(); + callback.should.be.calledWith(firebase.auth().currentUser); + callback.should.be.calledOnce(); - // Sign out - await firebase.auth().signOut(); - await Utils.sleep(50); + // Sign out + await firebase.auth().signOut(); + await Utils.sleep(50); - // Assertions - callback.should.be.calledWith(null); - callback.should.be.calledTwice(); + // Assertions + callback.should.be.calledWith(null); + callback.should.be.calledTwice(); - // Tear down - unsubscribe(); - }); + // Tear down + unsubscribe(); + }); - it('stops listening when unsubscribed', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + it('stops listening when unsubscribed', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); - // Test - const callback = sinon.spy(); + // Test + const callback = sinon.spy(); - let unsubscribe; - await new Promise(resolve => { - unsubscribe = firebase.auth().onIdTokenChanged(user => { - callback(user); - resolve(); + let unsubscribe; + await new Promise(resolve => { + unsubscribe = firebase.auth().onIdTokenChanged(user => { + callback(user); + resolve(); + }); }); - }); - callback.should.be.calledWith(firebase.auth().currentUser); - callback.should.be.calledOnce(); + callback.should.be.calledWith(firebase.auth().currentUser); + callback.should.be.calledOnce(); - // Sign out - await firebase.auth().signOut(); - await Utils.sleep(50); + // Sign out + await firebase.auth().signOut(); + await Utils.sleep(50); - // Assertions - callback.should.be.calledWith(null); - callback.should.be.calledTwice(); + // Assertions + callback.should.be.calledWith(null); + callback.should.be.calledTwice(); - // Unsubscribe - unsubscribe(); + // Unsubscribe + unsubscribe(); - // Sign back in - await firebase.auth().signInAnonymously(); + // Sign back in + await firebase.auth().signInAnonymously(); - // Assertions - callback.should.be.calledTwice(); + // Assertions + callback.should.be.calledTwice(); - // Tear down - await firebase.auth().signOut(); - await Utils.sleep(50); - }); + // Tear down + await firebase.auth().signOut(); + await Utils.sleep(50); + }); - it('listens to a null user when auth result is not defined', async function () { - let unsubscribe; + it('listens to a null user when auth result is not defined', async function () { + let unsubscribe; - const callback = sinon.spy(); + const callback = sinon.spy(); - await new Promise(resolve => { - unsubscribe = firebase.auth().onIdTokenChanged(user => { - callback(user); - resolve(); - }); + await new Promise(resolve => { + unsubscribe = firebase.auth().onIdTokenChanged(user => { + callback(user); + resolve(); + }); - unsubscribe(); + unsubscribe(); + }); }); }); - }); - describe('onUserChanged()', function () { - it('calls callback with the current user and when auth state changes', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + describe('onUserChanged()', function () { + it('calls callback with the current user and when auth state changes', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); - // Test - const callback = sinon.spy(); + // Test + const callback = sinon.spy(); - let unsubscribe; - await new Promise(resolve => { - unsubscribe = firebase.auth().onUserChanged(user => { - callback(user); - resolve(); + let unsubscribe; + await new Promise(resolve => { + unsubscribe = firebase.auth().onUserChanged(user => { + callback(user); + resolve(); + }); }); - }); - - callback.should.be.calledWith(firebase.auth().currentUser); - callback.should.be.calledOnce(); - - // Sign out - await firebase.auth().signOut(); - await Utils.sleep(500); - // Assertions - callback.should.be.calledWith(null); - // Because of the way onUserChanged works, it will be called double - // - once for onAuthStateChanged - // - once for onIdTokenChanged - callback.should.have.callCount(4); + callback.should.be.calledWith(firebase.auth().currentUser); + callback.should.be.calledOnce(); - // Tear down - unsubscribe(); - }); + // Sign out + await firebase.auth().signOut(); + await Utils.sleep(500); - it('stops listening when unsubscribed', async function () { - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + // Assertions + callback.should.be.calledWith(null); + // Because of the way onUserChanged works, it will be called double + // - once for onAuthStateChanged + // - once for onIdTokenChanged + callback.should.have.callCount(4); - // Test - const callback = sinon.spy(); - - let unsubscribe; - await new Promise(resolve => { - unsubscribe = firebase.auth().onUserChanged(user => { - callback(user); - resolve(); - }); + // Tear down + unsubscribe(); }); - callback.should.be.calledWith(firebase.auth().currentUser); - callback.should.be.calledOnce(); + it('stops listening when unsubscribed', async function () { + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); - // Sign out - await firebase.auth().signOut(); - await Utils.sleep(200); + // Test + const callback = sinon.spy(); - // Assertions - callback.should.be.calledWith(null); - // Because of the way onUserChanged works, it will be called double - // - once for onAuthStateChanged - // - once for onIdTokenChanged - callback.should.have.callCount(4); + let unsubscribe; + await new Promise(resolve => { + unsubscribe = firebase.auth().onUserChanged(user => { + callback(user); + resolve(); + }); + }); - // Unsubscribe - unsubscribe(); + callback.should.be.calledWith(firebase.auth().currentUser); + callback.should.be.calledOnce(); - // Sign back in - await firebase.auth().signInAnonymously(); - await Utils.sleep(200); + // Sign out + await firebase.auth().signOut(); + await Utils.sleep(200); - // Assertions - callback.should.have.callCount(4); + // Assertions + callback.should.be.calledWith(null); + // Because of the way onUserChanged works, it will be called double + // - once for onAuthStateChanged + // - once for onIdTokenChanged + callback.should.have.callCount(4); - // Tear down - await firebase.auth().signOut(); - }); - }); - - describe('signInAnonymously()', function () { - it('it should sign in anonymously', function () { - const successCb = currentUserCredential => { - const currentUser = currentUserCredential.user; - currentUser.should.be.an.Object(); - currentUser.uid.should.be.a.String(); - currentUser.toJSON().should.be.an.Object(); - should.equal(currentUser.toJSON().email, null); - currentUser.isAnonymous.should.equal(true); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); + // Unsubscribe + unsubscribe(); - const { additionalUserInfo } = currentUserCredential; - additionalUserInfo.should.be.an.Object(); + // Sign back in + await firebase.auth().signInAnonymously(); + await Utils.sleep(200); - return firebase.auth().signOut(); - }; + // Assertions + callback.should.have.callCount(4); - return firebase.auth().signInAnonymously().then(successCb); + // Tear down + await firebase.auth().signOut(); + }); }); - }); - describe('signInWithEmailAndPassword()', function () { - it('it should login with email and password', function () { - 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(TEST_EMAIL); - currentUser.isAnonymous.should.equal(false); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); + describe('signInAnonymously()', function () { + it('it should sign in anonymously', function () { + const successCb = currentUserCredential => { + const currentUser = currentUserCredential.user; + currentUser.should.be.an.Object(); + currentUser.uid.should.be.a.String(); + currentUser.toJSON().should.be.an.Object(); + should.equal(currentUser.toJSON().email, null); + currentUser.isAnonymous.should.equal(true); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); - const { additionalUserInfo } = currentUserCredential; - additionalUserInfo.should.be.an.Object(); - additionalUserInfo.isNewUser.should.equal(false); + const { additionalUserInfo } = currentUserCredential; + additionalUserInfo.should.be.an.Object(); - return firebase.auth().signOut(); - }; + return firebase.auth().signOut(); + }; - return firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS).then(successCb); + return firebase.auth().signInAnonymously().then(successCb); + }); }); - it('it should error on login if user is disabled', function () { - const successCb = () => Promise.reject(new Error('Did not error.')); + describe('signInWithEmailAndPassword()', function () { + it('it should login with email and password', function () { + 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(TEST_EMAIL); + currentUser.isAnonymous.should.equal(false); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); - const failureCb = error => { - error.code.should.equal('auth/user-disabled'); - error.message.should.containEql( - 'The user account has been disabled by an administrator.', - ); - return Promise.resolve(); - }; + const { additionalUserInfo } = currentUserCredential; + additionalUserInfo.should.be.an.Object(); + additionalUserInfo.isNewUser.should.equal(false); - return firebase - .auth() - .signInWithEmailAndPassword(DISABLED_EMAIL, DISABLED_PASS) - .then(successCb) - .catch(failureCb); - }); + return firebase.auth().signOut(); + }; - it('it should error on login if password incorrect', function () { - const successCb = () => Promise.reject(new Error('Did not error.')); + return firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS).then(successCb); + }); - const failureCb = error => { - error.code.should.equal('auth/wrong-password'); - error.message.should.containEql( - 'The password is invalid or the user does not have a password.', - ); - return Promise.resolve(); - }; + it('it should error on login if user is disabled', function () { + const successCb = () => Promise.reject(new Error('Did not error.')); - return firebase - .auth() - .signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS + '666') - .then(successCb) - .catch(failureCb); - }); + const failureCb = error => { + error.code.should.equal('auth/user-disabled'); + error.message.should.containEql( + 'The user account has been disabled by an administrator.', + ); + return Promise.resolve(); + }; - it('it should error on login if user not found', function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; + return firebase + .auth() + .signInWithEmailAndPassword(DISABLED_EMAIL, DISABLED_PASS) + .then(successCb) + .catch(failureCb); + }); - const successCb = () => Promise.reject(new Error('Did not error.')); + it('it should error on login if password incorrect', function () { + const successCb = () => Promise.reject(new Error('Did not error.')); - const failureCb = error => { - error.code.should.equal('auth/user-not-found'); - error.message.should.containEql( - 'There is no user record corresponding to this identifier. The user may have been deleted.', - ); - return Promise.resolve(); - }; - - return firebase - .auth() - .signInWithEmailAndPassword(email, pass) - .then(successCb) - .catch(failureCb); - }); - }); + const failureCb = error => { + error.code.should.equal('auth/wrong-password'); + error.message.should.containEql( + 'The password is invalid or the user does not have a password.', + ); + return Promise.resolve(); + }; - describe('signInWithCredential()', function () { - it('it should login with email and password', function () { - const credential = firebase.auth.EmailAuthProvider.credential(TEST_EMAIL, TEST_PASS); + return firebase + .auth() + .signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS + '666') + .then(successCb) + .catch(failureCb); + }); - 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(TEST_EMAIL); - currentUser.isAnonymous.should.equal(false); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); + it('it should error on login if user not found', function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - const { additionalUserInfo } = currentUserCredential; - additionalUserInfo.should.be.an.Object(); - additionalUserInfo.isNewUser.should.equal(false); + const successCb = () => Promise.reject(new Error('Did not error.')); - return firebase.auth().signOut(); - }; + const failureCb = error => { + error.code.should.equal('auth/user-not-found'); + error.message.should.containEql( + 'There is no user record corresponding to this identifier. The user may have been deleted.', + ); + return Promise.resolve(); + }; - return firebase.auth().signInWithCredential(credential).then(successCb); + return firebase + .auth() + .signInWithEmailAndPassword(email, pass) + .then(successCb) + .catch(failureCb); + }); }); - it('it should error on login if user is disabled', function () { - const credential = firebase.auth.EmailAuthProvider.credential( - DISABLED_EMAIL, - DISABLED_PASS, - ); + describe('signInWithCredential()', function () { + it('it should login with email and password', function () { + const credential = firebase.auth.EmailAuthProvider.credential(TEST_EMAIL, TEST_PASS); - const successCb = () => Promise.reject(new Error('Did not error.')); + 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(TEST_EMAIL); + currentUser.isAnonymous.should.equal(false); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); - const failureCb = error => { - error.code.should.equal('auth/user-disabled'); - error.message.should.containEql( - 'The user account has been disabled by an administrator.', - ); - return Promise.resolve(); - }; - - return firebase.auth().signInWithCredential(credential).then(successCb).catch(failureCb); - }); + const { additionalUserInfo } = currentUserCredential; + additionalUserInfo.should.be.an.Object(); + additionalUserInfo.isNewUser.should.equal(false); - it('it should error on login if password incorrect', function () { - const credential = firebase.auth.EmailAuthProvider.credential( - TEST_EMAIL, - TEST_PASS + '666', - ); + return firebase.auth().signOut(); + }; - const successCb = () => Promise.reject(new Error('Did not error.')); + return firebase.auth().signInWithCredential(credential).then(successCb); + }); - const failureCb = error => { - error.code.should.equal('auth/wrong-password'); - error.message.should.containEql( - 'The password is invalid or the user does not have a password.', + it('it should error on login if user is disabled', function () { + const credential = firebase.auth.EmailAuthProvider.credential( + DISABLED_EMAIL, + DISABLED_PASS, ); - return Promise.resolve(); - }; - return firebase.auth().signInWithCredential(credential).then(successCb).catch(failureCb); - }); - - it('it should error on login if user not found', function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; + const successCb = () => Promise.reject(new Error('Did not error.')); - const credential = firebase.auth.EmailAuthProvider.credential(email, pass); + const failureCb = error => { + error.code.should.equal('auth/user-disabled'); + error.message.should.containEql( + 'The user account has been disabled by an administrator.', + ); + return Promise.resolve(); + }; - const successCb = () => Promise.reject(new Error('Did not error.')); + return firebase.auth().signInWithCredential(credential).then(successCb).catch(failureCb); + }); - const failureCb = error => { - error.code.should.equal('auth/user-not-found'); - error.message.should.containEql( - 'There is no user record corresponding to this identifier. The user may have been deleted.', + it('it should error on login if password incorrect', function () { + const credential = firebase.auth.EmailAuthProvider.credential( + TEST_EMAIL, + TEST_PASS + '666', ); - return Promise.resolve(); - }; - return firebase.auth().signInWithCredential(credential).then(successCb).catch(failureCb); - }); - }); - - describe('createUserWithEmailAndPassword()', function () { - it('it should create a user with an email and password', function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; + const successCb = () => Promise.reject(new Error('Did not error.')); - const successCb = newUserCredential => { - const newUser = newUserCredential.user; - newUser.uid.should.be.a.String(); - newUser.email.should.equal(email.toLowerCase()); - newUser.emailVerified.should.equal(false); - newUser.isAnonymous.should.equal(false); - newUser.providerId.should.equal('firebase'); - newUser.should.equal(firebase.auth().currentUser); - const { additionalUserInfo } = newUserCredential; - additionalUserInfo.should.be.an.Object(); - additionalUserInfo.isNewUser.should.equal(true); - - return newUser.delete(); - }; - - return firebase.auth().createUserWithEmailAndPassword(email, pass).then(successCb); - }); - - it('it should error on create with invalid email', function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}${random}.com.boop.shoop`; - const pass = random; + const failureCb = error => { + error.code.should.equal('auth/wrong-password'); + error.message.should.containEql( + 'The password is invalid or the user does not have a password.', + ); + return Promise.resolve(); + }; - const successCb = () => Promise.reject(new Error('Did not error.')); + return firebase.auth().signInWithCredential(credential).then(successCb).catch(failureCb); + }); - const failureCb = error => { - error.code.should.equal('auth/invalid-email'); - error.message.should.containEql('The email address is badly formatted.'); - return Promise.resolve(); - }; + it('it should error on login if user not found', function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - return firebase - .auth() - .createUserWithEmailAndPassword(email, pass) - .then(successCb) - .catch(failureCb); - }); + const credential = firebase.auth.EmailAuthProvider.credential(email, pass); - it('it should error on create if email in use', function () { - const successCb = () => Promise.reject(new Error('Did not error.')); + const successCb = () => Promise.reject(new Error('Did not error.')); - const failureCb = error => { - error.code.should.equal('auth/email-already-in-use'); - error.message.should.containEql( - 'The email address is already in use by another account.', - ); - return Promise.resolve(); - }; + const failureCb = error => { + error.code.should.equal('auth/user-not-found'); + error.message.should.containEql( + 'There is no user record corresponding to this identifier. The user may have been deleted.', + ); + return Promise.resolve(); + }; - return firebase - .auth() - .createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS) - .then(successCb) - .catch(failureCb); + return firebase.auth().signInWithCredential(credential).then(successCb).catch(failureCb); + }); }); - it('it should error on create if password weak', function () { - const email = 'testy@testy.com'; - const pass = '123'; - - const successCb = () => Promise.reject(new Error('Did not error.')); - - const failureCb = error => { - error.code.should.equal('auth/weak-password'); - // cannot test this message - it's different on the web client than ios/android return - // error.message.should.containEql('The given password is invalid.'); - return Promise.resolve(); - }; + describe('createUserWithEmailAndPassword()', function () { + it('it should create a user with an email and password', function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - return firebase - .auth() - .createUserWithEmailAndPassword(email, pass) - .then(successCb) - .catch(failureCb); - }); - }); + const successCb = newUserCredential => { + const newUser = newUserCredential.user; + newUser.uid.should.be.a.String(); + newUser.email.should.equal(email.toLowerCase()); + newUser.emailVerified.should.equal(false); + newUser.isAnonymous.should.equal(false); + newUser.providerId.should.equal('firebase'); + newUser.should.equal(firebase.auth().currentUser); + const { additionalUserInfo } = newUserCredential; + additionalUserInfo.should.be.an.Object(); + additionalUserInfo.isNewUser.should.equal(true); - describe('fetchSignInMethodsForEmail()', function () { - it('it should return password provider for an email address', function () { - return new Promise((resolve, reject) => { - const successCb = providers => { - providers.should.be.a.Array(); - providers.should.containEql('password'); - resolve(); + return newUser.delete(); }; - const failureCb = () => { - reject(new Error('Should not have an error.')); + return firebase.auth().createUserWithEmailAndPassword(email, pass).then(successCb); + }); + + it('it should error on create with invalid email', function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}${random}.com.boop.shoop`; + const pass = random; + + const successCb = () => Promise.reject(new Error('Did not error.')); + + const failureCb = error => { + error.code.should.equal('auth/invalid-email'); + error.message.should.containEql('The email address is badly formatted.'); + return Promise.resolve(); }; return firebase .auth() - .fetchSignInMethodsForEmail(TEST_EMAIL) + .createUserWithEmailAndPassword(email, pass) .then(successCb) .catch(failureCb); }); - }); - it('it should return an empty array for a not found email', function () { - return new Promise((resolve, reject) => { - const successCb = providers => { - providers.should.be.a.Array(); - providers.should.be.empty(); - resolve(); - }; + it('it should error on create if email in use', function () { + const successCb = () => Promise.reject(new Error('Did not error.')); - const failureCb = () => { - reject(new Error('Should not have an error.')); + const failureCb = error => { + error.code.should.equal('auth/email-already-in-use'); + error.message.should.containEql( + 'The email address is already in use by another account.', + ); + return Promise.resolve(); }; return firebase .auth() - .fetchSignInMethodsForEmail('test@i-do-not-exist.com') + .createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS) .then(successCb) .catch(failureCb); }); - }); - it('it should return an error for a bad email address', function () { - return new Promise((resolve, reject) => { - const successCb = () => { - reject(new Error('Should not have successfully resolved.')); - }; + it('it should error on create if password weak', function () { + const email = 'testy@testy.com'; + const pass = '123'; + + const successCb = () => Promise.reject(new Error('Did not error.')); const failureCb = error => { - error.code.should.equal('auth/invalid-email'); - error.message.should.containEql('The email address is badly formatted.'); - resolve(); + error.code.should.equal('auth/weak-password'); + // cannot test this message - it's different on the web client than ios/android return + // error.message.should.containEql('The given password is invalid.'); + return Promise.resolve(); }; return firebase .auth() - .fetchSignInMethodsForEmail('foobar') + .createUserWithEmailAndPassword(email, pass) .then(successCb) .catch(failureCb); }); }); - }); - describe('signOut()', function () { - it('it should reject signOut if no currentUser', function () { - return new Promise((resolve, reject) => { - if (firebase.auth().currentUser) { - return reject( - new Error(`A user is currently signed in. ${firebase.auth().currentUser.uid}`), - ); - } + describe('fetchSignInMethodsForEmail()', function () { + it('it should return password provider for an email address', function () { + return new Promise((resolve, reject) => { + const successCb = providers => { + providers.should.be.a.Array(); + providers.should.containEql('password'); + resolve(); + }; + + const failureCb = () => { + reject(new Error('Should not have an error.')); + }; + + return firebase + .auth() + .fetchSignInMethodsForEmail(TEST_EMAIL) + .then(successCb) + .catch(failureCb); + }); + }); - const successCb = () => { - reject(new Error('No signOut error returned')); - }; + it('it should return an empty array for a not found email', function () { + return new Promise((resolve, reject) => { + const successCb = providers => { + providers.should.be.a.Array(); + providers.should.be.empty(); + resolve(); + }; + + const failureCb = () => { + reject(new Error('Should not have an error.')); + }; + + return firebase + .auth() + .fetchSignInMethodsForEmail('test@i-do-not-exist.com') + .then(successCb) + .catch(failureCb); + }); + }); - const failureCb = error => { - error.code.should.equal('auth/no-current-user'); - error.message.should.containEql('No user currently signed in.'); - resolve(); - }; + it('it should return an error for a bad email address', function () { + return new Promise((resolve, reject) => { + const successCb = () => { + reject(new Error('Should not have successfully resolved.')); + }; + + const failureCb = error => { + error.code.should.equal('auth/invalid-email'); + error.message.should.containEql('The email address is badly formatted.'); + resolve(); + }; + + return firebase + .auth() + .fetchSignInMethodsForEmail('foobar') + .then(successCb) + .catch(failureCb); + }); + }); + }); + + describe('signOut()', function () { + it('it should reject signOut if no currentUser', function () { + return new Promise((resolve, reject) => { + if (firebase.auth().currentUser) { + return reject( + new Error(`A user is currently signed in. ${firebase.auth().currentUser.uid}`), + ); + } + + const successCb = () => { + reject(new Error('No signOut error returned')); + }; - return firebase.auth().signOut().then(successCb).catch(failureCb); + const failureCb = error => { + error.code.should.equal('auth/no-current-user'); + error.message.should.containEql('No user currently signed in.'); + resolve(); + }; + + return firebase.auth().signOut().then(successCb).catch(failureCb); + }); }); }); - }); - describe('delete()', function () { - it('should delete a user', function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; + describe('delete()', function () { + it('should delete a user', function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - const successCb = authResult => { - const newUser = authResult.user; - newUser.uid.should.be.a.String(); - newUser.email.should.equal(email.toLowerCase()); - newUser.emailVerified.should.equal(false); - newUser.isAnonymous.should.equal(false); - newUser.providerId.should.equal('firebase'); - return firebase.auth().currentUser.delete(); - }; + const successCb = authResult => { + const newUser = authResult.user; + newUser.uid.should.be.a.String(); + newUser.email.should.equal(email.toLowerCase()); + newUser.emailVerified.should.equal(false); + newUser.isAnonymous.should.equal(false); + newUser.providerId.should.equal('firebase'); + return firebase.auth().currentUser.delete(); + }; - return firebase.auth().createUserWithEmailAndPassword(email, pass).then(successCb); + return firebase.auth().createUserWithEmailAndPassword(email, pass).then(successCb); + }); }); - }); - describe('languageCode', function () { - it('it should change the language code', async function () { - await firebase.auth().setLanguageCode('en'); + describe('languageCode', function () { + it('it should change the language code', async function () { + await firebase.auth().setLanguageCode('en'); - if (firebase.auth().languageCode !== 'en') { - throw new Error('Expected language code to be "en".'); - } - await firebase.auth().setLanguageCode('fr'); + if (firebase.auth().languageCode !== 'en') { + throw new Error('Expected language code to be "en".'); + } + await firebase.auth().setLanguageCode('fr'); - if (firebase.auth().languageCode !== 'fr') { - throw new Error('Expected language code to be "fr".'); - } - // expect no error - await firebase.auth().setLanguageCode(null); + if (firebase.auth().languageCode !== 'fr') { + throw new Error('Expected language code to be "fr".'); + } + // expect no error + await firebase.auth().setLanguageCode(null); - try { - await firebase.auth().setLanguageCode(123); - return Promise.reject('It did not error'); - } catch (e) { - e.message.should.containEql("expected 'languageCode' to be a string or null value"); - } + try { + await firebase.auth().setLanguageCode(123); + return Promise.reject('It did not error'); + } catch (e) { + e.message.should.containEql("expected 'languageCode' to be a string or null value"); + } - await firebase.auth().setLanguageCode('en'); + await firebase.auth().setLanguageCode('en'); + }); }); - }); - describe('getRedirectResult()', function () { - it('should throw an unsupported error', function () { - (() => { - firebase.auth().getRedirectResult(); - }).should.throw( - 'firebase.auth().getRedirectResult() is unsupported by the native Firebase SDKs.', - ); + describe('getRedirectResult()', function () { + it('should throw an unsupported error', function () { + (() => { + firebase.auth().getRedirectResult(); + }).should.throw( + 'firebase.auth().getRedirectResult() is unsupported by the native Firebase SDKs.', + ); + }); }); - }); - describe('setPersistence()', function () { - it('should throw an unsupported error', function () { - (() => { - firebase.auth().setPersistence(); - }).should.throw( - 'firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.', - ); + describe('setPersistence()', function () { + it('should throw an unsupported error', function () { + (() => { + firebase.auth().setPersistence(); + }).should.throw( + 'firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.', + ); + }); }); - }); - describe('sendPasswordResetEmail()', function () { - it('should not error', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); + describe('sendPasswordResetEmail()', function () { + it('should not error', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - await firebase.auth().sendPasswordResetEmail(email); - } catch (error) { - throw new Error('sendPasswordResetEmail() caused an error', error); - } finally { - await firebase.auth().currentUser.delete(); - } - }); + try { + await firebase.auth().sendPasswordResetEmail(email); + } catch (error) { + throw new Error('sendPasswordResetEmail() caused an error', error); + } finally { + await firebase.auth().currentUser.delete(); + } + }); + + it('should verify with valid code', async function () { + // FIXME Fails on android against auth emulator with: + // com.google.firebase.FirebaseException: An internal error has occurred. + if (device.getPlatform() === 'ios') { + const random = Utils.randString(12, '#a'); + const email = `${random}@${random}.com`; + const userCredential = await firebase + .auth() + .createUserWithEmailAndPassword(email, random); + userCredential.user.emailVerified.should.equal(false); + firebase.auth().currentUser.email.should.equal(email); + firebase.auth().currentUser.emailVerified.should.equal(false); + + try { + await firebase.auth().sendPasswordResetEmail(email); + const { oobCode } = await getLastOob(email); + await firebase.auth().verifyPasswordResetCode(oobCode); + } catch (error) { + throw new Error('sendPasswordResetEmail() caused an error', error); + } finally { + await firebase.auth().currentUser.delete(); + } + } + }); - it('should verify with valid code', async function () { - // FIXME Fails on android against auth emulator with: - // com.google.firebase.FirebaseException: An internal error has occurred. - if (device.getPlatform() === 'ios') { + it('should fail to verify with invalid code', async function () { const random = Utils.randString(12, '#a'); const email = `${random}@${random}.com`; const userCredential = await firebase @@ -956,139 +979,123 @@ describe('auth() modular', function () { try { await firebase.auth().sendPasswordResetEmail(email); const { oobCode } = await getLastOob(email); - await firebase.auth().verifyPasswordResetCode(oobCode); + await firebase.auth().verifyPasswordResetCode(oobCode + 'badcode'); + throw new Error('Invalid code should throw an error'); } catch (error) { - throw new Error('sendPasswordResetEmail() caused an error', error); + error.message.should.containEql('[auth/invalid-action-code]'); } finally { await firebase.auth().currentUser.delete(); } - } - }); - - it('should fail to verify with invalid code', async function () { - const random = Utils.randString(12, '#a'); - const email = `${random}@${random}.com`; - const userCredential = await firebase.auth().createUserWithEmailAndPassword(email, random); - userCredential.user.emailVerified.should.equal(false); - firebase.auth().currentUser.email.should.equal(email); - firebase.auth().currentUser.emailVerified.should.equal(false); - - try { - await firebase.auth().sendPasswordResetEmail(email); - const { oobCode } = await getLastOob(email); - await firebase.auth().verifyPasswordResetCode(oobCode + 'badcode'); - throw new Error('Invalid code should throw an error'); - } catch (error) { - error.message.should.containEql('[auth/invalid-action-code]'); - } finally { - await firebase.auth().currentUser.delete(); - } - }); + }); - it('should change password correctly OOB', async function () { - const random = Utils.randString(12, '#a'); - const email = `${random}@${random}.com`; - const userCredential = await firebase.auth().createUserWithEmailAndPassword(email, random); - userCredential.user.emailVerified.should.equal(false); - firebase.auth().currentUser.email.should.equal(email); - firebase.auth().currentUser.emailVerified.should.equal(false); + it('should change password correctly OOB', async function () { + const random = Utils.randString(12, '#a'); + const email = `${random}@${random}.com`; + const userCredential = await firebase + .auth() + .createUserWithEmailAndPassword(email, random); + userCredential.user.emailVerified.should.equal(false); + firebase.auth().currentUser.email.should.equal(email); + firebase.auth().currentUser.emailVerified.should.equal(false); - try { - await firebase.auth().sendPasswordResetEmail(email); - const { oobCode } = await getLastOob(email); - await resetPassword(oobCode, 'testNewPassword'); - await firebase.auth().signOut(); - await Utils.sleep(50); - await firebase.auth().signInWithEmailAndPassword(email, 'testNewPassword'); - } catch (error) { - throw new Error('sendPasswordResetEmail() caused an error', error); - } finally { - await firebase.auth().currentUser.delete(); - } - }); + try { + await firebase.auth().sendPasswordResetEmail(email); + const { oobCode } = await getLastOob(email); + await resetPassword(oobCode, 'testNewPassword'); + await firebase.auth().signOut(); + await Utils.sleep(50); + await firebase.auth().signInWithEmailAndPassword(email, 'testNewPassword'); + } catch (error) { + throw new Error('sendPasswordResetEmail() caused an error', error); + } finally { + await firebase.auth().currentUser.delete(); + } + }); - it('should change password correctly via API', async function () { - const random = Utils.randString(12, '#a'); - const email = `${random}@${random}.com`; - const userCredential = await firebase.auth().createUserWithEmailAndPassword(email, random); - userCredential.user.emailVerified.should.equal(false); - firebase.auth().currentUser.email.should.equal(email); - firebase.auth().currentUser.emailVerified.should.equal(false); + it('should change password correctly via API', async function () { + const random = Utils.randString(12, '#a'); + const email = `${random}@${random}.com`; + const userCredential = await firebase + .auth() + .createUserWithEmailAndPassword(email, random); + userCredential.user.emailVerified.should.equal(false); + firebase.auth().currentUser.email.should.equal(email); + firebase.auth().currentUser.emailVerified.should.equal(false); - try { - await firebase.auth().sendPasswordResetEmail(email); - const { oobCode } = await getLastOob(email); - await firebase.auth().confirmPasswordReset(oobCode, 'testNewPassword'); - await firebase.auth().signOut(); - await Utils.sleep(50); - await firebase.auth().signInWithEmailAndPassword(email, 'testNewPassword'); - } catch (error) { - throw new Error('sendPasswordResetEmail() caused an error', error); - } finally { - await firebase.auth().currentUser.delete(); - } + try { + await firebase.auth().sendPasswordResetEmail(email); + const { oobCode } = await getLastOob(email); + await firebase.auth().confirmPasswordReset(oobCode, 'testNewPassword'); + await firebase.auth().signOut(); + await Utils.sleep(50); + await firebase.auth().signInWithEmailAndPassword(email, 'testNewPassword'); + } catch (error) { + throw new Error('sendPasswordResetEmail() caused an error', error); + } finally { + await firebase.auth().currentUser.delete(); + } + }); }); - }); - describe('useDeviceLanguage()', function () { - it('should throw an unsupported error', function () { - (() => { - firebase.auth().useDeviceLanguage(); - }).should.throw( - 'firebase.auth().useDeviceLanguage() is unsupported by the native Firebase SDKs.', - ); + describe('useDeviceLanguage()', function () { + it('should throw an unsupported error', function () { + (() => { + firebase.auth().useDeviceLanguage(); + }).should.throw( + 'firebase.auth().useDeviceLanguage() is unsupported by the native Firebase SDKs.', + ); + }); }); - }); - describe('useUserAccessGroup()', function () { - // Android simply does Promise.resolve, that is sufficient for this test multi-platform - it('should return "null" when accessing a group that exists', async function () { - const successfulKeychain = await firebase - .auth() - .useUserAccessGroup('YYX2P3XVJ7.com.invertase.testing'); // iOS signing team is YYX2P3XVJ7 + describe('useUserAccessGroup()', function () { + // Android simply does Promise.resolve, that is sufficient for this test multi-platform + it('should return "null" when accessing a group that exists', async function () { + const successfulKeychain = await firebase + .auth() + .useUserAccessGroup('YYX2P3XVJ7.com.invertase.testing'); // iOS signing team is YYX2P3XVJ7 - should.not.exist(successfulKeychain); + should.not.exist(successfulKeychain); - //clean up - const resetKeychain = await firebase.auth().useUserAccessGroup(null); + //clean up + const resetKeychain = await firebase.auth().useUserAccessGroup(null); - should.not.exist(resetKeychain); - }); + should.not.exist(resetKeychain); + }); - it('should throw when requesting an inaccessible group', async function () { - // Android will never throw, so this test is iOS only - if (device.getPlatform() === 'ios') { - try { - await firebase.auth().useUserAccessGroup('there.is.no.way.this.group.exists'); - throw new Error('Should have thrown an error for inaccessible group'); - } catch (e) { - e.message.should.containEql('auth/keychain-error'); + it('should throw when requesting an inaccessible group', async function () { + // Android will never throw, so this test is iOS only + if (device.getPlatform() === 'ios') { + try { + await firebase.auth().useUserAccessGroup('there.is.no.way.this.group.exists'); + throw new Error('Should have thrown an error for inaccessible group'); + } catch (e) { + e.message.should.containEql('auth/keychain-error'); + } } - } + }); }); - }); - describe('setTenantId()', function () { - it('should return null if tenantId unset', function () { - should.not.exist(firebase.auth().tenantId); - }); + describe('setTenantId()', function () { + it('should return null if tenantId unset', function () { + should.not.exist(firebase.auth().tenantId); + }); - // multi-tenant is not supported by the firebase auth emulator, and requires a valid multi-tenant tenantid - // After setting this, next user creation will result in internal error on emulator, or auth/invalid-tenant-id live - // it('should return tenantId correctly after setting', async function () { - // await firebase.auth().setTenantId('testTenantId'); - // firebase.auth().tenantId.should.equal('testTenantId'); - // }); - // it('user should have tenant after setting tenantId', async function () { - // await firebase.auth().setTenantId('userTestTenantId'); - // firebase.auth().tenantId.should.equal('userTestTenantId'); - // const random = Utils.randString(12, '#a'); - // const email = `${random}@${random}.com`; - // const userCredential = await firebase.auth().createUserWithEmailAndPassword(email, random); - // userCredential.user.tenantId.should.equal('userTestTenantId'); - // }); + // multi-tenant is not supported by the firebase auth emulator, and requires a valid multi-tenant tenantid + // After setting this, next user creation will result in internal error on emulator, or auth/invalid-tenant-id live + // it('should return tenantId correctly after setting', async function () { + // await firebase.auth().setTenantId('testTenantId'); + // firebase.auth().tenantId.should.equal('testTenantId'); + // }); + // it('user should have tenant after setting tenantId', async function () { + // await firebase.auth().setTenantId('userTestTenantId'); + // firebase.auth().tenantId.should.equal('userTestTenantId'); + // const random = Utils.randString(12, '#a'); + // const email = `${random}@${random}.com`; + // const userCredential = await firebase.auth().createUserWithEmailAndPassword(email, random); + // userCredential.user.tenantId.should.equal('userTestTenantId'); + // }); + }); }); - }); describe('modular', function () { before(async function () { diff --git a/packages/auth/e2e/multiFactor.e2e.js b/packages/auth/e2e/multiFactor.e2e.js index d9201e4170..272ea17854 100644 --- a/packages/auth/e2e/multiFactor.e2e.js +++ b/packages/auth/e2e/multiFactor.e2e.js @@ -11,324 +11,331 @@ const TEST_EMAIL = 'test@example.com'; const TEST_PASS = 'test1234'; describe('multi-factor modular', function () { - describe('firebase v8 compatibility', function () { - beforeEach(async function () { - await clearAllUsers(); - await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - if (firebase.auth().currentUser) { - await firebase.auth().signOut(); - await Utils.sleep(50); - } - }); - - it('has no multi-factor information if not enrolled', async function () { - await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - const { multiFactor } = firebase.auth().currentUser; - multiFactor.should.be.an.Object(); - multiFactor.enrolledFactors.should.be.an.Array(); - multiFactor.enrolledFactors.length.should.equal(0); - return Promise.resolve(); - }); - - describe('sign-in', function () { - it('requires multi-factor auth when enrolled', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); + !skipCompatTests && + describe('firebase v8 compatibility', function () { + beforeEach(async function () { + await clearAllUsers(); + await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + if (firebase.auth().currentUser) { + await firebase.auth().signOut(); + await Utils.sleep(50); } - const { phoneNumber, email, password } = await createUserWithMultiFactor(); + }); - try { - await firebase.auth().signInWithEmailAndPassword(email, password); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', - ); - const resolver = firebase.auth().getMultiFactorResolver(e); - resolver.should.be.an.Object(); - resolver.hints.should.be.an.Array(); - resolver.hints.length.should.equal(1); - resolver.session.should.be.a.String(); + it('has no multi-factor information if not enrolled', async function () { + await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + const { multiFactor } = firebase.auth().currentUser; + multiFactor.should.be.an.Object(); + multiFactor.enrolledFactors.should.be.an.Array(); + multiFactor.enrolledFactors.length.should.equal(0); + return Promise.resolve(); + }); - const verificationId = await firebase - .auth() - .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); - verificationId.should.be.a.String(); + describe('sign-in', function () { + it('requires multi-factor auth when enrolled', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } + const { phoneNumber, email, password } = await createUserWithMultiFactor(); - let verificationCode = await getLastSmsCode(phoneNumber); - if (verificationCode == null) { - // iOS simulator uses a masked phone number - const maskedNumber = '+********' + phoneNumber.substring(phoneNumber.length - 4); - verificationCode = await getLastSmsCode(maskedNumber); + try { + await firebase.auth().signInWithEmailAndPassword(email, password); + } catch (e) { + e.message.should.equal( + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + ); + const resolver = firebase.auth().getMultiFactorResolver(e); + resolver.should.be.an.Object(); + resolver.hints.should.be.an.Array(); + resolver.hints.length.should.equal(1); + resolver.session.should.be.a.String(); + + const verificationId = await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); + verificationId.should.be.a.String(); + + let verificationCode = await getLastSmsCode(phoneNumber); + if (verificationCode == null) { + // iOS simulator uses a masked phone number + const maskedNumber = '+********' + phoneNumber.substring(phoneNumber.length - 4); + verificationCode = await getLastSmsCode(maskedNumber); + } + const credential = firebase.auth.PhoneAuthProvider.credential( + verificationId, + verificationCode, + ); + const multiFactorAssertion = + firebase.auth.PhoneMultiFactorGenerator.assertion(credential); + return resolver + .resolveSignIn(multiFactorAssertion) + .then(userCreds => { + userCreds.should.be.an.Object(); + userCreds.user.should.be.an.Object(); + userCreds.user.email.should.equal('verified@example.com'); + userCreds.user.multiFactor.should.be.an.Object(); + userCreds.user.multiFactor.enrolledFactors.length.should.equal(1); + return Promise.resolve(); + }) + .catch(e => { + return Promise.reject(e); + }); } - const credential = firebase.auth.PhoneAuthProvider.credential( - verificationId, - verificationCode, + + return Promise.reject( + new Error('Multi-factor users need to handle an exception on sign-in'), ); - const multiFactorAssertion = - firebase.auth.PhoneMultiFactorGenerator.assertion(credential); - return resolver - .resolveSignIn(multiFactorAssertion) - .then(userCreds => { - userCreds.should.be.an.Object(); - userCreds.user.should.be.an.Object(); - userCreds.user.email.should.equal('verified@example.com'); - userCreds.user.multiFactor.should.be.an.Object(); - userCreds.user.multiFactor.enrolledFactors.length.should.equal(1); - return Promise.resolve(); - }) - .catch(e => { - return Promise.reject(e); - }); - } + }); - return Promise.reject( - new Error('Multi-factor users need to handle an exception on sign-in'), - ); - }); + it('reports an error when providing an invalid sms code', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } - it('reports an error when providing an invalid sms code', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } + const { phoneNumber, email, password } = await createUserWithMultiFactor(); - const { phoneNumber, email, password } = await createUserWithMultiFactor(); + try { + await firebase.auth().signInWithEmailAndPassword(email, password); + } catch (e) { + e.message.should.equal( + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + ); + const resolver = firebase.auth().getMultiFactorResolver(e); + const verificationId = await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); - try { - await firebase.auth().signInWithEmailAndPassword(email, password); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', - ); - const resolver = firebase.auth().getMultiFactorResolver(e); - const verificationId = await firebase - .auth() - .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); + const credential = firebase.auth.PhoneAuthProvider.credential( + verificationId, + 'incorrect', + ); + const assertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); + try { + await resolver.resolveSignIn(assertion); + } catch (e) { + e.message + .toLocaleLowerCase() + .should.containEql('[auth/invalid-verification-code]'.toLocaleLowerCase()); + + const verificationId = await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); + const verificationCode = await getLastSmsCode(phoneNumber); + const credential = firebase.auth.PhoneAuthProvider.credential( + verificationId, + verificationCode, + ); + const assertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); + await resolver.resolveSignIn(assertion); + firebase.auth().currentUser.email.should.equal(email); + return Promise.resolve(); + } + } + return Promise.reject(); + }); + + it('reports an error when providing an invalid verification code', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } + const { phoneNumber, email, password } = await createUserWithMultiFactor(); - const credential = firebase.auth.PhoneAuthProvider.credential( - verificationId, - 'incorrect', - ); - const assertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); try { - await resolver.resolveSignIn(assertion); + await firebase.auth().signInWithEmailAndPassword(email, password); } catch (e) { - e.message - .toLocaleLowerCase() - .should.containEql('[auth/invalid-verification-code]'.toLocaleLowerCase()); - - const verificationId = await firebase + e.message.should.equal( + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + ); + const resolver = firebase.auth().getMultiFactorResolver(e); + await firebase .auth() .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); const verificationCode = await getLastSmsCode(phoneNumber); + const credential = firebase.auth.PhoneAuthProvider.credential( - verificationId, + 'incorrect', verificationCode, ); const assertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); - await resolver.resolveSignIn(assertion); - firebase.auth().currentUser.email.should.equal(email); - return Promise.resolve(); - } - } - return Promise.reject(); - }); + try { + await resolver.resolveSignIn(assertion); + } catch (e) { + e.message.should.equal( + '[auth/invalid-verification-id] The verification ID used to create the phone auth credential is invalid.', + ); - it('reports an error when providing an invalid verification code', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } - const { phoneNumber, email, password } = await createUserWithMultiFactor(); + return Promise.resolve(); + } + } + return Promise.reject(); + }); - try { - await firebase.auth().signInWithEmailAndPassword(email, password); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', - ); - const resolver = firebase.auth().getMultiFactorResolver(e); - await firebase - .auth() - .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); - const verificationCode = await getLastSmsCode(phoneNumber); + it('reports an error when using an unknown factor', async function () { + const { email, password } = await createUserWithMultiFactor(); - const credential = firebase.auth.PhoneAuthProvider.credential( - 'incorrect', - verificationCode, - ); - const assertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); try { - await resolver.resolveSignIn(assertion); + await firebase.auth().signInWithEmailAndPassword(email, password); } catch (e) { e.message.should.equal( - '[auth/invalid-verification-id] The verification ID used to create the phone auth credential is invalid.', + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); + const resolver = firebase.auth().getMultiFactorResolver(e); + const unknownFactor = { + uid: 'notknown', + }; + try { + await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(unknownFactor, resolver.session); + } catch (e) { + e.code.should.equal('auth/multi-factor-info-not-found'); + e.message.should.equal( + '[auth/multi-factor-info-not-found] The user does not have a second factor matching the identifier provided.', + ); - return Promise.resolve(); + return Promise.resolve(); + } } - } - return Promise.reject(); + return Promise.reject(); + }); }); - it('reports an error when using an unknown factor', async function () { - const { email, password } = await createUserWithMultiFactor(); + describe('enroll', function () { + it("can't enroll an existing user without verified email", async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } + + await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - try { - await firebase.auth().signInWithEmailAndPassword(email, password); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', - ); - const resolver = firebase.auth().getMultiFactorResolver(e); - const unknownFactor = { - uid: 'notknown', - }; try { + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); + const session = await multiFactorUser.getSession(); await firebase .auth() - .verifyPhoneNumberWithMultiFactorInfo(unknownFactor, resolver.session); + .verifyPhoneNumberForMultiFactor({ phoneNumber: getRandomPhoneNumber(), session }); } catch (e) { - e.code.should.equal('auth/multi-factor-info-not-found'); e.message.should.equal( - '[auth/multi-factor-info-not-found] The user does not have a second factor matching the identifier provided.', + '[auth/unverified-email] This operation requires a verified email.', ); - + e.code.should.equal('auth/unverified-email'); return Promise.resolve(); } - } - return Promise.reject(); - }); - }); - describe('enroll', function () { - it("can't enroll an existing user without verified email", async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } + return Promise.reject(new Error('Should throw error for unverified user.')); + }); - await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + it('can enroll new factor', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } - try { - const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); - const session = await multiFactorUser.getSession(); - await firebase - .auth() - .verifyPhoneNumberForMultiFactor({ phoneNumber: getRandomPhoneNumber(), session }); - } catch (e) { - e.message.should.equal( - '[auth/unverified-email] This operation requires a verified email.', - ); - e.code.should.equal('auth/unverified-email'); - return Promise.resolve(); - } + try { + await createVerifiedUser('verified@example.com', 'test123'); + const phoneNumber = getRandomPhoneNumber(); - return Promise.reject(new Error('Should throw error for unverified user.')); - }); + should.deepEqual(firebase.auth().currentUser.multiFactor.enrolledFactors, []); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); - it('can enroll new factor', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } + const session = await multiFactorUser.getSession(); - try { - await createVerifiedUser('verified@example.com', 'test123'); - const phoneNumber = getRandomPhoneNumber(); + const verificationId = await firebase + .auth() + .verifyPhoneNumberForMultiFactor({ phoneNumber, session }); + const verificationCode = await getLastSmsCode(phoneNumber); + const cred = firebase.auth.PhoneAuthProvider.credential( + verificationId, + verificationCode, + ); + const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred); + await multiFactorUser.enroll(multiFactorAssertion, 'Hint displayName'); + + const enrolledFactors = firebase.auth().currentUser.multiFactor.enrolledFactors; + enrolledFactors.length.should.equal(1); + enrolledFactors[0].displayName.should.equal('Hint displayName'); + enrolledFactors[0].factorId.should.equal('phone'); + enrolledFactors[0].uid.should.be.a.String(); + enrolledFactors[0].enrollmentTime.should.be.a.String(); + } catch (e) { + return Promise.reject(e); + } + return Promise.resolve(); + }); - should.deepEqual(firebase.auth().currentUser.multiFactor.enrolledFactors, []); - const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); + it('can enroll new factor without display name', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } - const session = await multiFactorUser.getSession(); + try { + await createVerifiedUser('verified@example.com', 'test123'); + const phoneNumber = getRandomPhoneNumber(); - const verificationId = await firebase - .auth() - .verifyPhoneNumberForMultiFactor({ phoneNumber, session }); - const verificationCode = await getLastSmsCode(phoneNumber); - const cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode); - const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred); - await multiFactorUser.enroll(multiFactorAssertion, 'Hint displayName'); + should.deepEqual(firebase.auth().currentUser.multiFactor.enrolledFactors, []); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); - const enrolledFactors = firebase.auth().currentUser.multiFactor.enrolledFactors; - enrolledFactors.length.should.equal(1); - enrolledFactors[0].displayName.should.equal('Hint displayName'); - enrolledFactors[0].factorId.should.equal('phone'); - enrolledFactors[0].uid.should.be.a.String(); - enrolledFactors[0].enrollmentTime.should.be.a.String(); - } catch (e) { - return Promise.reject(e); - } - return Promise.resolve(); - }); + const session = await multiFactorUser.getSession(); - it('can enroll new factor without display name', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } + const verificationId = await firebase + .auth() + .verifyPhoneNumberForMultiFactor({ phoneNumber, session }); + const verificationCode = await getLastSmsCode(phoneNumber); + const cred = firebase.auth.PhoneAuthProvider.credential( + verificationId, + verificationCode, + ); + const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred); + await multiFactorUser.enroll(multiFactorAssertion); - try { - await createVerifiedUser('verified@example.com', 'test123'); - const phoneNumber = getRandomPhoneNumber(); + const enrolledFactors = firebase.auth().currentUser.multiFactor.enrolledFactors; + enrolledFactors.length.should.equal(1); + should.equal(enrolledFactors[0].displayName, null); + } catch (e) { + return Promise.reject(e); + } + return Promise.resolve(); + }); + + it('can enroll multiple factors', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } - should.deepEqual(firebase.auth().currentUser.multiFactor.enrolledFactors, []); + const { email, password, phoneNumber } = await createUserWithMultiFactor(); + await signInUserWithMultiFactor(email, password, phoneNumber); + + const anotherNumber = getRandomPhoneNumber(); const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); - const verificationId = await firebase .auth() - .verifyPhoneNumberForMultiFactor({ phoneNumber, session }); - const verificationCode = await getLastSmsCode(phoneNumber); + .verifyPhoneNumberForMultiFactor({ phoneNumber: anotherNumber, session }); + const verificationCode = await getLastSmsCode(anotherNumber); const cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode); const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred); - await multiFactorUser.enroll(multiFactorAssertion); + const displayName = 'Another displayName'; + await multiFactorUser.enroll(multiFactorAssertion, displayName); const enrolledFactors = firebase.auth().currentUser.multiFactor.enrolledFactors; - enrolledFactors.length.should.equal(1); - should.equal(enrolledFactors[0].displayName, null); - } catch (e) { - return Promise.reject(e); - } - return Promise.resolve(); - }); - - it('can enroll multiple factors', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } - - const { email, password, phoneNumber } = await createUserWithMultiFactor(); - await signInUserWithMultiFactor(email, password, phoneNumber); - - const anotherNumber = getRandomPhoneNumber(); - const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); - - const session = await multiFactorUser.getSession(); - const verificationId = await firebase - .auth() - .verifyPhoneNumberForMultiFactor({ phoneNumber: anotherNumber, session }); - const verificationCode = await getLastSmsCode(anotherNumber); - const cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode); - const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred); - const displayName = 'Another displayName'; - await multiFactorUser.enroll(multiFactorAssertion, displayName); - - const enrolledFactors = firebase.auth().currentUser.multiFactor.enrolledFactors; - enrolledFactors.length.should.equal(2); - const matchingFactor = enrolledFactors.find(factor => factor.displayName === displayName); - matchingFactor.should.be.an.Object(); - matchingFactor.uid.should.be.a.String(); - matchingFactor.enrollmentTime.should.be.a.String(); - matchingFactor.factorId.should.equal('phone'); + enrolledFactors.length.should.equal(2); + const matchingFactor = enrolledFactors.find(factor => factor.displayName === displayName); + matchingFactor.should.be.an.Object(); + matchingFactor.uid.should.be.a.String(); + matchingFactor.enrollmentTime.should.be.a.String(); + matchingFactor.factorId.should.equal('phone'); - return Promise.resolve(); - }); + return Promise.resolve(); + }); - it('can not enroll the same factor twice', async function () { - this.skip(); - // This test should probably be implemented but doesn't work: - // Every time the same phone number requests a verification code, - // the emulator endpoint does not return a code, even though the emulator log - // prints a code. - // See https://github.com/firebase/firebase-tools/issues/4290#issuecomment-1281260335 - /* + it('can not enroll the same factor twice', async function () { + this.skip(); + // This test should probably be implemented but doesn't work: + // Every time the same phone number requests a verification code, + // the emulator endpoint does not return a code, even though the emulator log + // prints a code. + // See https://github.com/firebase/firebase-tools/issues/4290#issuecomment-1281260335 + /* await clearAllUsers(); const { email, password, phoneNumber } = await createUserWithMultiFactor(); await signInUserWithMultiFactor(email, password, phoneNumber); @@ -351,167 +358,173 @@ describe('multi-factor modular', function () { } return Promise.reject(); */ - }); + }); - it('throws an error for wrong verification id', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } + it('throws an error for wrong verification id', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } - const { phoneNumber, email, password } = await createUserWithMultiFactor(); + const { phoneNumber, email, password } = await createUserWithMultiFactor(); - // GIVEN a MultiFactorResolver - let resolver = null; - try { - await firebase.auth().signInWithEmailAndPassword(email, password); - return Promise.reject(); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + // GIVEN a MultiFactorResolver + let resolver = null; + try { + await firebase.auth().signInWithEmailAndPassword(email, password); + return Promise.reject(); + } catch (e) { + e.message.should.equal( + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + ); + resolver = firebase.auth().getMultiFactorResolver(e); + } + await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); + + // AND I request a verification code + const verificationCode = await getLastSmsCode(phoneNumber); + // AND I use an incorrect verificationId + const credential = firebase.auth.PhoneAuthProvider.credential( + 'wrongVerificationId', + verificationCode, ); - resolver = firebase.auth().getMultiFactorResolver(e); - } - await firebase - .auth() - .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); + const multiFactorAssertion = + firebase.auth.PhoneMultiFactorGenerator.assertion(credential); - // AND I request a verification code - const verificationCode = await getLastSmsCode(phoneNumber); - // AND I use an incorrect verificationId - const credential = firebase.auth.PhoneAuthProvider.credential( - 'wrongVerificationId', - verificationCode, - ); - const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); + try { + // WHEN I try to resolve the sign-in + await resolver.resolveSignIn(multiFactorAssertion); + } catch (e) { + // THEN an error message is thrown + e.message.should.equal( + '[auth/invalid-verification-id] The verification ID used to create the phone auth credential is invalid.', + ); + return Promise.resolve(); + } + return Promise.reject(); + }); - try { - // WHEN I try to resolve the sign-in - await resolver.resolveSignIn(multiFactorAssertion); - } catch (e) { - // THEN an error message is thrown - e.message.should.equal( - '[auth/invalid-verification-id] The verification ID used to create the phone auth credential is invalid.', - ); - return Promise.resolve(); - } - return Promise.reject(); - }); + it('throws an error for unknown sessions', async function () { + const { email, password } = await createUserWithMultiFactor(); + let resolver = null; + try { + await firebase.auth().signInWithEmailAndPassword(email, password); + return Promise.reject(); + } catch (e) { + e.message.should.equal( + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + ); + resolver = firebase.auth().getMultiFactorResolver(e); + } - it('throws an error for unknown sessions', async function () { - const { email, password } = await createUserWithMultiFactor(); - let resolver = null; - try { - await firebase.auth().signInWithEmailAndPassword(email, password); + try { + await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], 'unknown-session'); + } catch (e) { + // THEN an error message is thrown + e.message.should.equal( + '[auth/invalid-multi-factor-session] No resolver for session found. Is the session id correct?', + ); + return Promise.resolve(); + } return Promise.reject(); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', - ); - resolver = firebase.auth().getMultiFactorResolver(e); - } + }); - try { - await firebase - .auth() - .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], 'unknown-session'); - } catch (e) { - // THEN an error message is thrown - e.message.should.equal( - '[auth/invalid-multi-factor-session] No resolver for session found. Is the session id correct?', - ); - return Promise.resolve(); - } - return Promise.reject(); - }); + it('throws an error for unknown verification code', async function () { + const { email, password } = await createUserWithMultiFactor(); - it('throws an error for unknown verification code', async function () { - const { email, password } = await createUserWithMultiFactor(); + // GIVEN a MultiFactorResolver + let resolver = null; + try { + await firebase.auth().signInWithEmailAndPassword(email, password); + return Promise.reject(); + } catch (e) { + e.message.should.equal( + '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + ); + resolver = firebase.auth().getMultiFactorResolver(e); + } + const verificationId = await firebase + .auth() + .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); - // GIVEN a MultiFactorResolver - let resolver = null; - try { - await firebase.auth().signInWithEmailAndPassword(email, password); - return Promise.reject(); - } catch (e) { - e.message.should.equal( - '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', + // AND I use an incorrect verificationId + const credential = firebase.auth.PhoneAuthProvider.credential( + verificationId, + 'wrong-verification-code', ); - resolver = firebase.auth().getMultiFactorResolver(e); - } - const verificationId = await firebase - .auth() - .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); - - // AND I use an incorrect verificationId - const credential = firebase.auth.PhoneAuthProvider.credential( - verificationId, - 'wrong-verification-code', - ); - const multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(credential); + const multiFactorAssertion = + firebase.auth.PhoneMultiFactorGenerator.assertion(credential); - try { - // WHEN I try to resolve the sign-in - await resolver.resolveSignIn(multiFactorAssertion); - } catch (e) { - // THEN an error message is thrown - e.message - .toLocaleLowerCase() - .should.containEql('[auth/invalid-verification-code]'.toLocaleLowerCase()); + try { + // WHEN I try to resolve the sign-in + await resolver.resolveSignIn(multiFactorAssertion); + } catch (e) { + // THEN an error message is thrown + e.message + .toLocaleLowerCase() + .should.containEql('[auth/invalid-verification-code]'.toLocaleLowerCase()); - return Promise.resolve(); - } - return Promise.reject(); - }); + return Promise.resolve(); + } + return Promise.reject(); + }); - it('can not enroll with phone authentication (unsupported primary factor)', async function () { - if (device.getPlatform() === 'ios') { - this.skip(); - } + it('can not enroll with phone authentication (unsupported primary factor)', async function () { + if (device.getPlatform() === 'ios') { + this.skip(); + } - // GIVEN a user that only signs in with phone - const testPhone = getRandomPhoneNumber(); - const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); - const lastSmsCode = await getLastSmsCode(testPhone); - await confirmResult.confirm(lastSmsCode); + // GIVEN a user that only signs in with phone + const testPhone = getRandomPhoneNumber(); + const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); + const lastSmsCode = await getLastSmsCode(testPhone); + await confirmResult.confirm(lastSmsCode); - // WHEN they attempt to enroll a second factor - const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); - const session = await multiFactorUser.getSession(); - try { - await firebase - .auth() - .verifyPhoneNumberForMultiFactor({ phoneNumber: '+1123123', session }); - } catch (e) { - e.message.should.equal( - '[auth/unsupported-first-factor] Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.', + // WHEN they attempt to enroll a second factor + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); + const session = await multiFactorUser.getSession(); + try { + await firebase + .auth() + .verifyPhoneNumberForMultiFactor({ phoneNumber: '+1123123', session }); + } catch (e) { + e.message.should.equal( + '[auth/unsupported-first-factor] Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.', + ); + return Promise.resolve(); + } + return Promise.reject( + new Error( + 'Enrolling a second factor when using phone authentication is not supported.', + ), ); - return Promise.resolve(); - } - return Promise.reject( - new Error('Enrolling a second factor when using phone authentication is not supported.'), - ); - }); + }); - it('can not enroll when phone number is missing + sign', async function () { - await createVerifiedUser('verified@example.com', 'test123'); - const multiFactorUser = firebase.auth().multiFactor(firebase.auth().currentUser); - const session = await multiFactorUser.getSession(); - try { - await firebase.auth().verifyPhoneNumberForMultiFactor({ phoneNumber: '491575', session }); - } catch (e) { - e.code.should.equal('auth/invalid-phone-number'); - e.message.should.equal( - '[auth/invalid-phone-number] The format of the phone number provided is incorrect. Please enter the ' + - 'phone number in a format that can be parsed into E.164 format. E.164 ' + - 'phone numbers are written in the format [+][country code][subscriber ' + - 'number including area code].', - ); - return Promise.resolve(); - } - return Promise.reject(); + it('can not enroll when phone number is missing + sign', async function () { + await createVerifiedUser('verified@example.com', 'test123'); + const multiFactorUser = firebase.auth().multiFactor(firebase.auth().currentUser); + const session = await multiFactorUser.getSession(); + try { + await firebase + .auth() + .verifyPhoneNumberForMultiFactor({ phoneNumber: '491575', session }); + } catch (e) { + e.code.should.equal('auth/invalid-phone-number'); + e.message.should.equal( + '[auth/invalid-phone-number] The format of the phone number provided is incorrect. Please enter the ' + + 'phone number in a format that can be parsed into E.164 format. E.164 ' + + 'phone numbers are written in the format [+][country code][subscriber ' + + 'number including area code].', + ); + return Promise.resolve(); + } + return Promise.reject(); + }); }); }); - }); describe('modular', function () { beforeEach(async function () { diff --git a/packages/auth/e2e/phone.e2e.js b/packages/auth/e2e/phone.e2e.js index 2e6f7ec622..0e29f6ebd8 100644 --- a/packages/auth/e2e/phone.e2e.js +++ b/packages/auth/e2e/phone.e2e.js @@ -4,179 +4,186 @@ const { clearAllUsers, getLastSmsCode, getRandomPhoneNumber } = require('./helpers'); describe('auth() => Phone', function () { - describe('firebase v8 compatibility', function () { - before(async function () { - try { - await clearAllUsers(); - } catch (e) { - throw e; - } - firebase.auth().settings.appVerificationDisabledForTesting = true; - await Utils.sleep(50); - }); - - beforeEach(async function () { - if (firebase.auth().currentUser) { - await firebase.auth().signOut(); + !skipCompatTests && + describe('firebase v8 compatibility', function () { + before(async function () { + try { + await clearAllUsers(); + } catch (e) { + throw e; + } + firebase.auth().settings.appVerificationDisabledForTesting = true; await Utils.sleep(50); - } - }); - - describe('signInWithPhoneNumber', function () { - it('signs in with a valid code', async function () { - const testPhone = getRandomPhoneNumber(); - const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); - confirmResult.verificationId.should.be.a.String(); - should.ok(confirmResult.verificationId.length, 'verificationId string should not be empty'); - confirmResult.confirm.should.be.a.Function(); - const lastSmsCode = await getLastSmsCode(testPhone); - const userCredential = await confirmResult.confirm(lastSmsCode); - userCredential.user.should.be.instanceOf(jet.require('packages/auth/lib/User')); - - // Broken check, phone number is undefined - // userCredential.user.phoneNumber.should.equal(TEST_PHONE_A); }); - it('errors on invalid code', async function () { - const testPhone = getRandomPhoneNumber(); - const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); - confirmResult.verificationId.should.be.a.String(); - should.ok(confirmResult.verificationId.length, 'verificationId string should not be empty'); - confirmResult.confirm.should.be.a.Function(); - // Get the last SMS code just to make absolutely sure we don't accidentally use it - const lastSmsCode = await getLastSmsCode(testPhone); - await confirmResult - .confirm(lastSmsCode === '000000' ? '111111' : '000000') - .should.be.rejected(); - // TODO test error code and message - - // If you don't consume the valid code, then it sticks around - await confirmResult.confirm(lastSmsCode); + beforeEach(async function () { + if (firebase.auth().currentUser) { + await firebase.auth().signOut(); + await Utils.sleep(50); + } }); - }); - describe('verifyPhoneNumber', function () { - it('successfully verifies', async function () { - const testPhone = getRandomPhoneNumber(); - const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); - const lastSmsCode = await getLastSmsCode(testPhone); - await confirmResult.confirm(lastSmsCode); - await firebase.auth().verifyPhoneNumber(testPhone, false, false); + describe('signInWithPhoneNumber', function () { + it('signs in with a valid code', async function () { + const testPhone = getRandomPhoneNumber(); + const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); + confirmResult.verificationId.should.be.a.String(); + should.ok( + confirmResult.verificationId.length, + 'verificationId string should not be empty', + ); + confirmResult.confirm.should.be.a.Function(); + const lastSmsCode = await getLastSmsCode(testPhone); + const userCredential = await confirmResult.confirm(lastSmsCode); + userCredential.user.should.be.instanceOf(jet.require('packages/auth/lib/User')); + + // Broken check, phone number is undefined + // userCredential.user.phoneNumber.should.equal(TEST_PHONE_A); + }); + + it('errors on invalid code', async function () { + const testPhone = getRandomPhoneNumber(); + const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); + confirmResult.verificationId.should.be.a.String(); + should.ok( + confirmResult.verificationId.length, + 'verificationId string should not be empty', + ); + confirmResult.confirm.should.be.a.Function(); + // Get the last SMS code just to make absolutely sure we don't accidentally use it + const lastSmsCode = await getLastSmsCode(testPhone); + await confirmResult + .confirm(lastSmsCode === '000000' ? '111111' : '000000') + .should.be.rejected(); + // TODO test error code and message + + // If you don't consume the valid code, then it sticks around + await confirmResult.confirm(lastSmsCode); + }); }); - it('uses the autoVerifyTimeout when a non boolean autoVerifyTimeoutOrForceResend is provided', async function () { - const testPhone = getRandomPhoneNumber(); - const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); - const lastSmsCode = await getLastSmsCode(testPhone); - await confirmResult.confirm(lastSmsCode); - await firebase.auth().verifyPhoneNumber(testPhone, 0, false); - }); + describe('verifyPhoneNumber', function () { + it('successfully verifies', async function () { + const testPhone = getRandomPhoneNumber(); + const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); + const lastSmsCode = await getLastSmsCode(testPhone); + await confirmResult.confirm(lastSmsCode); + await firebase.auth().verifyPhoneNumber(testPhone, false, false); + }); + + it('uses the autoVerifyTimeout when a non boolean autoVerifyTimeoutOrForceResend is provided', async function () { + const testPhone = getRandomPhoneNumber(); + const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); + const lastSmsCode = await getLastSmsCode(testPhone); + await confirmResult.confirm(lastSmsCode); + await firebase.auth().verifyPhoneNumber(testPhone, 0, false); + }); + + it('throws an error with an invalid on event', async function () { + const testPhone = getRandomPhoneNumber(); + try { + await firebase + .auth() + .verifyPhoneNumber(testPhone) + .on('example', () => {}); + + return Promise.reject(new Error('Did not throw Error.')); + } catch (e) { + e.message.should.containEql( + "firebase.auth.PhoneAuthListener.on(*, _, _, _) 'event' must equal 'state_changed'.", + ); + return Promise.resolve(); + } + }); + + it('throws an error with an invalid observer event', async function () { + const testPhone = getRandomPhoneNumber(); + try { + await firebase + .auth() + .verifyPhoneNumber(testPhone) + .on('state_changed', null, null, () => {}); + + return Promise.reject(new Error('Did not throw Error.')); + } catch (e) { + e.message.should.containEql( + "firebase.auth.PhoneAuthListener.on(_, *, _, _) 'observer' must be a function.", + ); + return Promise.resolve(); + } + }); + + it('successfully runs verification complete handler', async function () { + const testPhone = getRandomPhoneNumber(); + const thenCb = sinon.spy(); + await firebase.auth().verifyPhoneNumber(testPhone).then(thenCb); + thenCb.should.be.calledOnce(); + const successAuthSnapshot = thenCb.args[0][0]; + if (device.getPlatform() === 'ios') { + successAuthSnapshot.state.should.equal('sent'); + } else { + successAuthSnapshot.state.should.equal('timeout'); + } + }); + + it('successfully runs and calls success callback', async function () { + const testPhone = getRandomPhoneNumber(); + const successCb = sinon.spy(); + const observerCb = sinon.spy(); + const errorCb = sinon.spy(); - it('throws an error with an invalid on event', async function () { - const testPhone = getRandomPhoneNumber(); - try { await firebase .auth() .verifyPhoneNumber(testPhone) - .on('example', () => {}); + .on('state_changed', observerCb, errorCb, successCb); + + await Utils.spyToBeCalledOnceAsync(successCb); + errorCb.should.be.callCount(0); + successCb.should.be.calledOnce(); + let observerAuthSnapshot = observerCb.args[0][0]; + const successAuthSnapshot = successCb.args[0][0]; + successAuthSnapshot.verificationId.should.be.a.String(); + if (device.getPlatform() === 'ios') { + observerCb.should.be.calledOnce(); + successAuthSnapshot.state.should.equal('sent'); + } else { + // android waits for SMS auto retrieval which does not work on an emulator + // it gets a sent and a timeout message on observer, just the timeout on success + observerCb.should.be.calledTwice(); + observerAuthSnapshot = observerCb.args[1][0]; + successAuthSnapshot.state.should.equal('timeout'); + } + JSON.stringify(successAuthSnapshot).should.equal(JSON.stringify(observerAuthSnapshot)); + }); + + // TODO determine why this is not stable on the emulator, is it also not stable on real device? + xit('successfully runs and calls error callback', async function () { + const successCb = sinon.spy(); + const observerCb = sinon.spy(); + const errorCb = sinon.spy(); - return Promise.reject(new Error('Did not throw Error.')); - } catch (e) { - e.message.should.containEql( - "firebase.auth.PhoneAuthListener.on(*, _, _, _) 'event' must equal 'state_changed'.", - ); - return Promise.resolve(); - } - }); - - it('throws an error with an invalid observer event', async function () { - const testPhone = getRandomPhoneNumber(); - try { await firebase .auth() - .verifyPhoneNumber(testPhone) - .on('state_changed', null, null, () => {}); - - return Promise.reject(new Error('Did not throw Error.')); - } catch (e) { - e.message.should.containEql( - "firebase.auth.PhoneAuthListener.on(_, *, _, _) 'observer' must be a function.", - ); - return Promise.resolve(); - } - }); + .verifyPhoneNumber('notaphonenumber') + .on('state_changed', observerCb, errorCb, successCb); - it('successfully runs verification complete handler', async function () { - const testPhone = getRandomPhoneNumber(); - const thenCb = sinon.spy(); - await firebase.auth().verifyPhoneNumber(testPhone).then(thenCb); - thenCb.should.be.calledOnce(); - const successAuthSnapshot = thenCb.args[0][0]; - if (device.getPlatform() === 'ios') { - successAuthSnapshot.state.should.equal('sent'); - } else { - successAuthSnapshot.state.should.equal('timeout'); - } - }); - - it('successfully runs and calls success callback', async function () { - const testPhone = getRandomPhoneNumber(); - const successCb = sinon.spy(); - const observerCb = sinon.spy(); - const errorCb = sinon.spy(); - - await firebase - .auth() - .verifyPhoneNumber(testPhone) - .on('state_changed', observerCb, errorCb, successCb); - - await Utils.spyToBeCalledOnceAsync(successCb); - errorCb.should.be.callCount(0); - successCb.should.be.calledOnce(); - let observerAuthSnapshot = observerCb.args[0][0]; - const successAuthSnapshot = successCb.args[0][0]; - successAuthSnapshot.verificationId.should.be.a.String(); - if (device.getPlatform() === 'ios') { + await Utils.spyToBeCalledOnceAsync(errorCb); + errorCb.should.be.calledOnce(); observerCb.should.be.calledOnce(); - successAuthSnapshot.state.should.equal('sent'); - } else { - // android waits for SMS auto retrieval which does not work on an emulator - // it gets a sent and a timeout message on observer, just the timeout on success - observerCb.should.be.calledTwice(); - observerAuthSnapshot = observerCb.args[1][0]; - successAuthSnapshot.state.should.equal('timeout'); - } - JSON.stringify(successAuthSnapshot).should.equal(JSON.stringify(observerAuthSnapshot)); - }); - - // TODO determine why this is not stable on the emulator, is it also not stable on real device? - xit('successfully runs and calls error callback', async function () { - const successCb = sinon.spy(); - const observerCb = sinon.spy(); - const errorCb = sinon.spy(); - - await firebase - .auth() - .verifyPhoneNumber('notaphonenumber') - .on('state_changed', observerCb, errorCb, successCb); - - await Utils.spyToBeCalledOnceAsync(errorCb); - errorCb.should.be.calledOnce(); - observerCb.should.be.calledOnce(); - // const observerEvent = observerCb.args[0][0]; - successCb.should.be.callCount(0); - // const errorEvent = errorCb.args[0][0]; - // errorEvent.error.should.containEql('auth/invalid-phone-number'); - // JSON.stringify(errorEvent).should.equal(JSON.stringify(observerEvent)); - }); - - it('catches an error and emits an error event', async function () { - const catchCb = sinon.spy(); - await firebase.auth().verifyPhoneNumber('badphonenumber').catch(catchCb); - catchCb.should.be.calledOnce(); + // const observerEvent = observerCb.args[0][0]; + successCb.should.be.callCount(0); + // const errorEvent = errorCb.args[0][0]; + // errorEvent.error.should.containEql('auth/invalid-phone-number'); + // JSON.stringify(errorEvent).should.equal(JSON.stringify(observerEvent)); + }); + + it('catches an error and emits an error event', async function () { + const catchCb = sinon.spy(); + await firebase.auth().verifyPhoneNumber('badphonenumber').catch(catchCb); + catchCb.should.be.calledOnce(); + }); }); }); - }); describe('modular', function () { before(async function () { diff --git a/packages/auth/e2e/provider.e2e.js b/packages/auth/e2e/provider.e2e.js index 91f4ffbb78..57f00ae923 100644 --- a/packages/auth/e2e/provider.e2e.js +++ b/packages/auth/e2e/provider.e2e.js @@ -1,265 +1,266 @@ describe('auth() -> Providers', function () { - describe('firebase v8 compatibility', function () { - beforeEach(async function () { - if (firebase.auth().currentUser) { - await firebase.auth().signOut(); - await Utils.sleep(50); - } - }); - - describe('EmailAuthProvider', function () { - describe('constructor', function () { - it('should throw an unsupported error', function () { - (() => new firebase.auth.EmailAuthProvider()).should.throw( - '`new EmailAuthProvider()` is not supported on the native Firebase SDKs.', - ); + !skipCompatTests && + describe('firebase v8 compatibility', function () { + beforeEach(async function () { + if (firebase.auth().currentUser) { + await firebase.auth().signOut(); + await Utils.sleep(50); + } + }); + + describe('EmailAuthProvider', function () { + describe('constructor', function () { + it('should throw an unsupported error', function () { + (() => new firebase.auth.EmailAuthProvider()).should.throw( + '`new EmailAuthProvider()` is not supported on the native Firebase SDKs.', + ); + }); }); - }); - describe('credential', function () { - it('should return a credential object', function () { - const email = 'email@email.com'; - const password = 'password'; - const credential = firebase.auth.EmailAuthProvider.credential(email, password); - credential.providerId.should.equal('password'); - credential.token.should.equal(email); - credential.secret.should.equal(password); + describe('credential', function () { + it('should return a credential object', function () { + const email = 'email@email.com'; + const password = 'password'; + const credential = firebase.auth.EmailAuthProvider.credential(email, password); + credential.providerId.should.equal('password'); + credential.token.should.equal(email); + credential.secret.should.equal(password); + }); }); - }); - describe('credentialWithLink', function () { - it('should return a credential object', function () { - const email = 'email@email.com'; - const link = 'link'; - const credential = firebase.auth.EmailAuthProvider.credentialWithLink(email, link); - credential.providerId.should.equal('emailLink'); - credential.token.should.equal(email); - credential.secret.should.equal(link); + describe('credentialWithLink', function () { + it('should return a credential object', function () { + const email = 'email@email.com'; + const link = 'link'; + const credential = firebase.auth.EmailAuthProvider.credentialWithLink(email, link); + credential.providerId.should.equal('emailLink'); + credential.token.should.equal(email); + credential.secret.should.equal(link); + }); }); - }); - describe('EMAIL_PASSWORD_SIGN_IN_METHOD', function () { - it('should return password', function () { - firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD.should.equal('password'); + describe('EMAIL_PASSWORD_SIGN_IN_METHOD', function () { + it('should return password', function () { + firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD.should.equal('password'); + }); }); - }); - describe('EMAIL_LINK_SIGN_IN_METHOD', function () { - it('should return emailLink', function () { - firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD.should.equal('emailLink'); + describe('EMAIL_LINK_SIGN_IN_METHOD', function () { + it('should return emailLink', function () { + firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD.should.equal('emailLink'); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return password', function () { - firebase.auth.EmailAuthProvider.PROVIDER_ID.should.equal('password'); + describe('PROVIDER_ID', function () { + it('should return password', function () { + firebase.auth.EmailAuthProvider.PROVIDER_ID.should.equal('password'); + }); }); }); - }); - describe('FacebookAuthProvider', function () { - describe('constructor', function () { - it('should throw an unsupported error', function () { - (() => new firebase.auth.FacebookAuthProvider()).should.throw( - '`new FacebookAuthProvider()` is not supported on the native Firebase SDKs.', - ); + describe('FacebookAuthProvider', function () { + describe('constructor', function () { + it('should throw an unsupported error', function () { + (() => new firebase.auth.FacebookAuthProvider()).should.throw( + '`new FacebookAuthProvider()` is not supported on the native Firebase SDKs.', + ); + }); }); - }); - describe('credential', function () { - it('should return a credential object', function () { - const token = '123456'; - const credential = firebase.auth.FacebookAuthProvider.credential(token); - credential.providerId.should.equal('facebook.com'); - credential.token.should.equal(token); - credential.secret.should.equal(''); + describe('credential', function () { + it('should return a credential object', function () { + const token = '123456'; + const credential = firebase.auth.FacebookAuthProvider.credential(token); + credential.providerId.should.equal('facebook.com'); + credential.token.should.equal(token); + credential.secret.should.equal(''); + }); }); - }); - describe('credentialLimitedLogin', function () { - it('should return a credential object', function () { - const token = '123456'; - const nonce = '654321'; - const credential = firebase.auth.FacebookAuthProvider.credential(token, nonce); - credential.providerId.should.equal('facebook.com'); - credential.token.should.equal(token); - credential.secret.should.equal(nonce); + describe('credentialLimitedLogin', function () { + it('should return a credential object', function () { + const token = '123456'; + const nonce = '654321'; + const credential = firebase.auth.FacebookAuthProvider.credential(token, nonce); + credential.providerId.should.equal('facebook.com'); + credential.token.should.equal(token); + credential.secret.should.equal(nonce); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return facebook.com', function () { - firebase.auth.FacebookAuthProvider.PROVIDER_ID.should.equal('facebook.com'); + describe('PROVIDER_ID', function () { + it('should return facebook.com', function () { + firebase.auth.FacebookAuthProvider.PROVIDER_ID.should.equal('facebook.com'); + }); }); }); - }); - describe('GithubAuthProvider', function () { - describe('constructor', function () { - it('should throw an unsupported error', function () { - (() => new firebase.auth.GithubAuthProvider()).should.throw( - '`new GithubAuthProvider()` is not supported on the native Firebase SDKs.', - ); + describe('GithubAuthProvider', function () { + describe('constructor', function () { + it('should throw an unsupported error', function () { + (() => new firebase.auth.GithubAuthProvider()).should.throw( + '`new GithubAuthProvider()` is not supported on the native Firebase SDKs.', + ); + }); }); - }); - describe('credential', function () { - it('should return a credential object', function () { - const token = '123456'; - const credential = firebase.auth.GithubAuthProvider.credential(token); - credential.providerId.should.equal('github.com'); - credential.token.should.equal(token); - credential.secret.should.equal(''); + describe('credential', function () { + it('should return a credential object', function () { + const token = '123456'; + const credential = firebase.auth.GithubAuthProvider.credential(token); + credential.providerId.should.equal('github.com'); + credential.token.should.equal(token); + credential.secret.should.equal(''); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return github.com', function () { - firebase.auth.GithubAuthProvider.PROVIDER_ID.should.equal('github.com'); + describe('PROVIDER_ID', function () { + it('should return github.com', function () { + firebase.auth.GithubAuthProvider.PROVIDER_ID.should.equal('github.com'); + }); }); }); - }); - describe('GoogleAuthProvider', function () { - describe('constructor', function () { - it('should throw an unsupported error', function () { - (() => new firebase.auth.GoogleAuthProvider()).should.throw( - '`new GoogleAuthProvider()` is not supported on the native Firebase SDKs.', - ); + describe('GoogleAuthProvider', function () { + describe('constructor', function () { + it('should throw an unsupported error', function () { + (() => new firebase.auth.GoogleAuthProvider()).should.throw( + '`new GoogleAuthProvider()` is not supported on the native Firebase SDKs.', + ); + }); }); - }); - describe('credential', function () { - it('should return a credential object', function () { - const token = '123456'; - const secret = '654321'; - const credential = firebase.auth.GoogleAuthProvider.credential(token, secret); - credential.providerId.should.equal('google.com'); - credential.token.should.equal(token); - credential.secret.should.equal(secret); + describe('credential', function () { + it('should return a credential object', function () { + const token = '123456'; + const secret = '654321'; + const credential = firebase.auth.GoogleAuthProvider.credential(token, secret); + credential.providerId.should.equal('google.com'); + credential.token.should.equal(token); + credential.secret.should.equal(secret); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return google.com', function () { - firebase.auth.GoogleAuthProvider.PROVIDER_ID.should.equal('google.com'); + describe('PROVIDER_ID', function () { + it('should return google.com', function () { + firebase.auth.GoogleAuthProvider.PROVIDER_ID.should.equal('google.com'); + }); }); }); - }); - describe('OAuthProvider', function () { - describe('credential', function () { - it('should return a credential object', function () { - const idToken = '123456'; - const accessToken = '654321'; - const credential = firebase.auth.OAuthProvider.credential(idToken, accessToken); - credential.providerId.should.equal('oauth'); - credential.token.should.equal(idToken); - credential.secret.should.equal(accessToken); + describe('OAuthProvider', function () { + describe('credential', function () { + it('should return a credential object', function () { + const idToken = '123456'; + const accessToken = '654321'; + const credential = firebase.auth.OAuthProvider.credential(idToken, accessToken); + credential.providerId.should.equal('oauth'); + credential.token.should.equal(idToken); + credential.secret.should.equal(accessToken); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return microsoft', function () { - const provider = new firebase.auth.OAuthProvider('microsoft.com'); - provider.PROVIDER_ID.should.equal('microsoft.com'); + describe('PROVIDER_ID', function () { + it('should return microsoft', function () { + const provider = new firebase.auth.OAuthProvider('microsoft.com'); + provider.PROVIDER_ID.should.equal('microsoft.com'); + }); }); - }); - describe('provider object', function () { - it('should return a credential object with scopes and custom parameters', function () { - const provider = new firebase.auth.OAuthProvider('microsoft.com'); - provider.addScope('profile'); - provider.addScope('email'); - provider.setCustomParameters({ - prompt: 'consent', - }); + describe('provider object', function () { + it('should return a credential object with scopes and custom parameters', function () { + const provider = new firebase.auth.OAuthProvider('microsoft.com'); + provider.addScope('profile'); + provider.addScope('email'); + provider.setCustomParameters({ + prompt: 'consent', + }); - provider.toObject().scopes.should.containEql('profile'); - provider.toObject().scopes.should.containEql('email'); - provider.toObject().customParameters.prompt.should.equal('consent'); + provider.toObject().scopes.should.containEql('profile'); + provider.toObject().scopes.should.containEql('email'); + provider.toObject().customParameters.prompt.should.equal('consent'); + }); }); }); - }); - describe('PhoneAuthProvider', function () { - describe('credential', function () { - it('should return a credential object', function () { - const verificationId = '123456'; - const code = '654321'; - const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, code); - credential.providerId.should.equal('phone'); - credential.token.should.equal(verificationId); - credential.secret.should.equal(code); + describe('PhoneAuthProvider', function () { + describe('credential', function () { + it('should return a credential object', function () { + const verificationId = '123456'; + const code = '654321'; + const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, code); + credential.providerId.should.equal('phone'); + credential.token.should.equal(verificationId); + credential.secret.should.equal(code); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return phone', function () { - firebase.auth.PhoneAuthProvider.PROVIDER_ID.should.equal('phone'); + describe('PROVIDER_ID', function () { + it('should return phone', function () { + firebase.auth.PhoneAuthProvider.PROVIDER_ID.should.equal('phone'); + }); }); }); - }); - describe('TwitterAuthProvider', function () { - describe('constructor', function () { - it('should throw an unsupported error', function () { - (() => new firebase.auth.TwitterAuthProvider()).should.throw( - '`new TwitterAuthProvider()` is not supported on the native Firebase SDKs.', - ); + describe('TwitterAuthProvider', function () { + describe('constructor', function () { + it('should throw an unsupported error', function () { + (() => new firebase.auth.TwitterAuthProvider()).should.throw( + '`new TwitterAuthProvider()` is not supported on the native Firebase SDKs.', + ); + }); }); - }); - describe('credential', function () { - it('should return a credential object', function () { - const token = '123456'; - const secret = '654321'; - const credential = firebase.auth.TwitterAuthProvider.credential(token, secret); - credential.providerId.should.equal('twitter.com'); - credential.token.should.equal(token); - credential.secret.should.equal(secret); + describe('credential', function () { + it('should return a credential object', function () { + const token = '123456'; + const secret = '654321'; + const credential = firebase.auth.TwitterAuthProvider.credential(token, secret); + credential.providerId.should.equal('twitter.com'); + credential.token.should.equal(token); + credential.secret.should.equal(secret); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return twitter.com', function () { - firebase.auth.TwitterAuthProvider.PROVIDER_ID.should.equal('twitter.com'); + describe('PROVIDER_ID', function () { + it('should return twitter.com', function () { + firebase.auth.TwitterAuthProvider.PROVIDER_ID.should.equal('twitter.com'); + }); }); }); - }); - describe('OIDCAuthProvider', function () { - describe('constructor', function () { - it('should throw an unsupported error', function () { - (() => new firebase.auth.OIDCAuthProvider()).should.throw( - '`new OIDCAuthProvider()` is not supported on the native Firebase SDKs.', - ); + describe('OIDCAuthProvider', function () { + describe('constructor', function () { + it('should throw an unsupported error', function () { + (() => new firebase.auth.OIDCAuthProvider()).should.throw( + '`new OIDCAuthProvider()` is not supported on the native Firebase SDKs.', + ); + }); }); - }); - describe('credential', function () { - it('should return a credential object', function () { - const token = '123456'; - const secret = '654321'; - const providerSuffix = 'sample-provider'; - const credential = firebase.auth.OIDCAuthProvider.credential( - providerSuffix, - token, - secret, - ); - credential.providerId.should.equal('oidc.' + providerSuffix); - credential.token.should.equal(token); - credential.secret.should.equal(secret); + describe('credential', function () { + it('should return a credential object', function () { + const token = '123456'; + const secret = '654321'; + const providerSuffix = 'sample-provider'; + const credential = firebase.auth.OIDCAuthProvider.credential( + providerSuffix, + token, + secret, + ); + credential.providerId.should.equal('oidc.' + providerSuffix); + credential.token.should.equal(token); + credential.secret.should.equal(secret); + }); }); - }); - describe('PROVIDER_ID', function () { - it('should return oidc.', function () { - firebase.auth.OIDCAuthProvider.PROVIDER_ID.should.equal('oidc.'); + describe('PROVIDER_ID', function () { + it('should return oidc.', function () { + firebase.auth.OIDCAuthProvider.PROVIDER_ID.should.equal('oidc.'); + }); }); }); }); - }); describe('modular', function () { beforeEach(async function () { diff --git a/packages/auth/e2e/rnReload.e2e.js b/packages/auth/e2e/rnReload.e2e.js index 7c44ae5b08..93cb3fb1d6 100644 --- a/packages/auth/e2e/rnReload.e2e.js +++ b/packages/auth/e2e/rnReload.e2e.js @@ -4,90 +4,91 @@ const TEST_PASS = 'test1234'; const { clearAllUsers } = require('./helpers'); describe('auth()', function () { - describe('firebase v8 compatibility', function () { - before(async function () { - try { - await clearAllUsers(); - } catch (e) { - throw e; - } - try { - await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - } catch (e) { - // they may already exist, that's fine - } - }); - - beforeEach(async function () { - if (firebase.auth().currentUser) { - await firebase.auth().signOut(); - await Utils.sleep(50); - } - }); - - describe('firebase.auth().currentUser', function () { - it('exists after reload', async function () { - // Detox on iOS crashing app on reloads, documented - // https://github.com/wix/detox/blob/master/docs/APIRef.DeviceObjectAPI.md#devicereloadreactnative - if (device.getPlatform() === 'ios') { - this.skip(); + !skipCompatTests && + describe('firebase v8 compatibility', function () { + before(async function () { + try { + await clearAllUsers(); + } catch (e) { + throw e; } - let currentUser; - // before reload - await firebase.auth().signInAnonymously(); - - ({ currentUser } = firebase.auth()); - currentUser.should.be.an.Object(); - currentUser.uid.should.be.a.String(); - currentUser.toJSON().should.be.an.Object(); - should.equal(currentUser.toJSON().email, null); - currentUser.isAnonymous.should.equal(true); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); - - // RELOAD - await device.reloadReactNative(); - - // after reload - ({ currentUser } = firebase.auth()); - currentUser.should.be.an.Object(); - currentUser.uid.should.be.a.String(); - currentUser.toJSON().should.be.an.Object(); - should.equal(currentUser.toJSON().email, null); - currentUser.isAnonymous.should.equal(true); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); - - // test correct user is returned after signing - // in with a different user then reloading - await firebase.auth().signOut(); - - await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - - ({ currentUser } = firebase.auth()); - currentUser.should.be.an.Object(); - currentUser.uid.should.be.a.String(); - currentUser.toJSON().should.be.an.Object(); - currentUser.toJSON().email.should.eql(TEST_EMAIL); - currentUser.isAnonymous.should.equal(false); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); - - // RELOAD - await device.reloadReactNative(); + try { + await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + } catch (e) { + // they may already exist, that's fine + } + }); - // after reload - ({ currentUser } = firebase.auth()); - currentUser.should.be.an.Object(); - currentUser.uid.should.be.a.String(); - currentUser.toJSON().should.be.an.Object(); - currentUser.toJSON().email.should.eql(TEST_EMAIL); - currentUser.isAnonymous.should.equal(false); - currentUser.providerId.should.equal('firebase'); - currentUser.should.equal(firebase.auth().currentUser); - }).timeout(15000); + beforeEach(async function () { + if (firebase.auth().currentUser) { + await firebase.auth().signOut(); + await Utils.sleep(50); + } + }); + + describe('firebase.auth().currentUser', function () { + it('exists after reload', async function () { + // Detox on iOS crashing app on reloads, documented + // https://github.com/wix/detox/blob/master/docs/APIRef.DeviceObjectAPI.md#devicereloadreactnative + if (device.getPlatform() === 'ios') { + this.skip(); + } + let currentUser; + // before reload + await firebase.auth().signInAnonymously(); + + ({ currentUser } = firebase.auth()); + currentUser.should.be.an.Object(); + currentUser.uid.should.be.a.String(); + currentUser.toJSON().should.be.an.Object(); + should.equal(currentUser.toJSON().email, null); + currentUser.isAnonymous.should.equal(true); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); + + // RELOAD + await device.reloadReactNative(); + + // after reload + ({ currentUser } = firebase.auth()); + currentUser.should.be.an.Object(); + currentUser.uid.should.be.a.String(); + currentUser.toJSON().should.be.an.Object(); + should.equal(currentUser.toJSON().email, null); + currentUser.isAnonymous.should.equal(true); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); + + // test correct user is returned after signing + // in with a different user then reloading + await firebase.auth().signOut(); + + await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + + ({ currentUser } = firebase.auth()); + currentUser.should.be.an.Object(); + currentUser.uid.should.be.a.String(); + currentUser.toJSON().should.be.an.Object(); + currentUser.toJSON().email.should.eql(TEST_EMAIL); + currentUser.isAnonymous.should.equal(false); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); + + // RELOAD + await device.reloadReactNative(); + + // after reload + ({ currentUser } = firebase.auth()); + currentUser.should.be.an.Object(); + currentUser.uid.should.be.a.String(); + currentUser.toJSON().should.be.an.Object(); + currentUser.toJSON().email.should.eql(TEST_EMAIL); + currentUser.isAnonymous.should.equal(false); + currentUser.providerId.should.equal('firebase'); + currentUser.should.equal(firebase.auth().currentUser); + }).timeout(15000); + }); }); - }); describe('modular', function () { before(async function () { diff --git a/packages/auth/e2e/user.e2e.js b/packages/auth/e2e/user.e2e.js index 1904a84803..cb712d2a54 100644 --- a/packages/auth/e2e/user.e2e.js +++ b/packages/auth/e2e/user.e2e.js @@ -10,920 +10,929 @@ const { } = require('./helpers'); describe('auth().currentUser', function () { - describe('firebase v8 compatibility', function () { - before(async function () { - try { - await clearAllUsers(); - } catch (e) { - throw e; - } - firebase.auth().settings.appVerificationDisabledForTesting = true; - try { - await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); - } catch (e) { - // they may already exist, that's fine - } - }); + !skipCompatTests && + describe('firebase v8 compatibility', function () { + before(async function () { + try { + await clearAllUsers(); + } catch (e) { + throw e; + } + firebase.auth().settings.appVerificationDisabledForTesting = true; + try { + await firebase.auth().createUserWithEmailAndPassword(TEST_EMAIL, TEST_PASS); + } catch (e) { + // they may already exist, that's fine + } + }); - beforeEach(async function () { - if (firebase.auth().currentUser) { - await firebase.auth().signOut(); - await Utils.sleep(50); - } - }); + beforeEach(async function () { + if (firebase.auth().currentUser) { + await firebase.auth().signOut(); + await Utils.sleep(50); + } + }); - describe('getIdToken()', function () { - it('should return a token', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; + describe('getIdToken()', function () { + it('should return a token', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; - const { user } = await firebase.auth().createUserWithEmailAndPassword(email, random); + const { user } = await firebase.auth().createUserWithEmailAndPassword(email, random); - // Test - const token = await user.getIdToken(); + // Test + const token = await user.getIdToken(); - // Assertions - token.should.be.a.String(); - token.length.should.be.greaterThan(24); + // Assertions + token.should.be.a.String(); + token.length.should.be.greaterThan(24); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); }); - }); - describe('getIdTokenResult()', function () { - it('should return a valid IdTokenResult Object', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; + describe('getIdTokenResult()', function () { + it('should return a valid IdTokenResult Object', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; - const { user } = await firebase.auth().createUserWithEmailAndPassword(email, random); + const { user } = await firebase.auth().createUserWithEmailAndPassword(email, random); - // Test - const tokenResult = await user.getIdTokenResult(); + // Test + const tokenResult = await user.getIdTokenResult(); - tokenResult.token.should.be.a.String(); - tokenResult.authTime.should.be.a.String(); - tokenResult.issuedAtTime.should.be.a.String(); - tokenResult.expirationTime.should.be.a.String(); + tokenResult.token.should.be.a.String(); + tokenResult.authTime.should.be.a.String(); + tokenResult.issuedAtTime.should.be.a.String(); + tokenResult.expirationTime.should.be.a.String(); - new Date(tokenResult.authTime).toString().should.not.equal('Invalid Date'); - new Date(tokenResult.issuedAtTime).toString().should.not.equal('Invalid Date'); - new Date(tokenResult.expirationTime).toString().should.not.equal('Invalid Date'); + new Date(tokenResult.authTime).toString().should.not.equal('Invalid Date'); + new Date(tokenResult.issuedAtTime).toString().should.not.equal('Invalid Date'); + new Date(tokenResult.expirationTime).toString().should.not.equal('Invalid Date'); - tokenResult.claims.should.be.a.Object(); - tokenResult.claims.iat.should.be.a.Number(); - tokenResult.claims.exp.should.be.a.Number(); - tokenResult.claims.iss.should.be.a.String(); + tokenResult.claims.should.be.a.Object(); + tokenResult.claims.iat.should.be.a.Number(); + tokenResult.claims.exp.should.be.a.Number(); + tokenResult.claims.iss.should.be.a.String(); - new Date(tokenResult.issuedAtTime).getTime().should.equal(tokenResult.claims.iat * 1000); - new Date(tokenResult.expirationTime).getTime().should.equal(tokenResult.claims.exp * 1000); + new Date(tokenResult.issuedAtTime).getTime().should.equal(tokenResult.claims.iat * 1000); + new Date(tokenResult.expirationTime) + .getTime() + .should.equal(tokenResult.claims.exp * 1000); - tokenResult.signInProvider.should.equal('password'); - tokenResult.token.length.should.be.greaterThan(24); + tokenResult.signInProvider.should.equal('password'); + tokenResult.token.length.should.be.greaterThan(24); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); }); - }); - - describe('linkWithCredential()', function () { - // hanging against auth emulator? - it('should link anonymous account <-> email account', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; - - await firebase.auth().signInAnonymously(); - const { currentUser } = firebase.auth(); - - // Test - const credential = firebase.auth.EmailAuthProvider.credential(email, pass); - const linkedUserCredential = await currentUser.linkWithCredential(credential); - - // Assertions - const linkedUser = linkedUserCredential.user; - linkedUser.should.be.an.Object(); - linkedUser.should.equal(firebase.auth().currentUser); - linkedUser.email.toLowerCase().should.equal(email.toLowerCase()); - linkedUser.isAnonymous.should.equal(false); - linkedUser.providerId.should.equal('firebase'); - linkedUser.providerData.should.be.an.Array(); - linkedUser.providerData.length.should.equal(1); - - // Clean up - await firebase.auth().currentUser.delete(); - }); + describe('linkWithCredential()', function () { + // hanging against auth emulator? + it('should link anonymous account <-> email account', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - it('should error on link anon <-> email if email already exists', async function () { - await firebase.auth().signInAnonymously(); - const { currentUser } = firebase.auth(); + await firebase.auth().signInAnonymously(); + const { currentUser } = firebase.auth(); - // Test - try { - const credential = firebase.auth.EmailAuthProvider.credential(TEST_EMAIL, TEST_PASS); - await currentUser.linkWithCredential(credential); + // Test + const credential = firebase.auth.EmailAuthProvider.credential(email, pass); - // Clean up - await firebase.auth().signOut(); + const linkedUserCredential = await currentUser.linkWithCredential(credential); - // Reject - return Promise.reject(new Error('Did not error on link')); - } catch (error) { // Assertions - error.code.should.equal('auth/email-already-in-use'); - error.message.should.containEql( - 'The email address is already in use by another account.', - ); + const linkedUser = linkedUserCredential.user; + linkedUser.should.be.an.Object(); + linkedUser.should.equal(firebase.auth().currentUser); + linkedUser.email.toLowerCase().should.equal(email.toLowerCase()); + linkedUser.isAnonymous.should.equal(false); + linkedUser.providerId.should.equal('firebase'); + linkedUser.providerData.should.be.an.Array(); + linkedUser.providerData.length.should.equal(1); // Clean up await firebase.auth().currentUser.delete(); - } + }); - return Promise.resolve(); + it('should error on link anon <-> email if email already exists', async function () { + await firebase.auth().signInAnonymously(); + const { currentUser } = firebase.auth(); + + // Test + try { + const credential = firebase.auth.EmailAuthProvider.credential(TEST_EMAIL, TEST_PASS); + await currentUser.linkWithCredential(credential); + + // Clean up + await firebase.auth().signOut(); + + // Reject + return Promise.reject(new Error('Did not error on link')); + } catch (error) { + // Assertions + error.code.should.equal('auth/email-already-in-use'); + error.message.should.containEql( + 'The email address is already in use by another account.', + ); + + // Clean up + await firebase.auth().currentUser.delete(); + } + + return Promise.resolve(); + }); }); - }); - describe('reauthenticateWithCredential()', function () { - it('should reauthenticate correctly', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; + describe('reauthenticateWithCredential()', function () { + it('should reauthenticate correctly', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - await firebase.auth().createUserWithEmailAndPassword(email, pass); + await firebase.auth().createUserWithEmailAndPassword(email, pass); - // Test - const credential = firebase.auth.EmailAuthProvider.credential(email, pass); + // Test + const credential = firebase.auth.EmailAuthProvider.credential(email, pass); - await firebase.auth().currentUser.reauthenticateWithCredential(credential); + await firebase.auth().currentUser.reauthenticateWithCredential(credential); - // Assertions - const { currentUser } = firebase.auth(); - currentUser.email.should.equal(email.toLowerCase()); + // Assertions + const { currentUser } = firebase.auth(); + currentUser.email.should.equal(email.toLowerCase()); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); }); - }); - describe('reload()', function () { - it('should not error', async function () { - await firebase.auth().signInAnonymously(); + describe('reload()', function () { + it('should not error', async function () { + await firebase.auth().signInAnonymously(); - try { - await firebase.auth().currentUser.reload(); - await firebase.auth().signOut(); - } catch (error) { - // Reject - await firebase.auth().signOut(); - return Promise.reject(new Error('reload() caused an error', error)); - } + try { + await firebase.auth().currentUser.reload(); + await firebase.auth().signOut(); + } catch (error) { + // Reject + await firebase.auth().signOut(); + return Promise.reject(new Error('reload() caused an error', error)); + } - return Promise.resolve(); + return Promise.resolve(); + }); }); - }); - describe('sendEmailVerification()', function () { - it('should error if actionCodeSettings.url is not present', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.sendEmailVerification({}); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.url' expected a string value."); - } - await firebase.auth().currentUser.delete(); - }); + describe('sendEmailVerification()', function () { + it('should error if actionCodeSettings.url is not present', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.sendEmailVerification({}); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'actionCodeSettings.url' expected a string value."); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.url is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.sendEmailVerification({ url: 123 }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.url' expected a string value."); - } - await firebase.auth().currentUser.delete(); - }); + it('should error if actionCodeSettings.url is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.sendEmailVerification({ url: 123 }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'actionCodeSettings.url' expected a string value."); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.dynamicLinkDomain is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase - .auth() - .currentUser.sendEmailVerification({ url: 'string', dynamicLinkDomain: 123 }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.dynamicLinkDomain' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + it('should error if actionCodeSettings.dynamicLinkDomain is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase + .auth() + .currentUser.sendEmailVerification({ url: 'string', dynamicLinkDomain: 123 }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.dynamicLinkDomain' expected a string value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if handleCodeInApp is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase - .auth() - .currentUser.sendEmailVerification({ url: 'string', handleCodeInApp: 123 }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.handleCodeInApp' expected a boolean value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + it('should error if handleCodeInApp is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase + .auth() + .currentUser.sendEmailVerification({ url: 'string', handleCodeInApp: 123 }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.handleCodeInApp' expected a boolean value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.iOS is not an object', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.sendEmailVerification({ url: 'string', iOS: 123 }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.iOS' expected an object value."); - } - await firebase.auth().currentUser.delete(); - }); + it('should error if actionCodeSettings.iOS is not an object', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.sendEmailVerification({ url: 'string', iOS: 123 }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'actionCodeSettings.iOS' expected an object value."); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.iOS.bundleId is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase - .auth() - .currentUser.sendEmailVerification({ url: 'string', iOS: { bundleId: 123 } }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.iOS.bundleId' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + it('should error if actionCodeSettings.iOS.bundleId is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase + .auth() + .currentUser.sendEmailVerification({ url: 'string', iOS: { bundleId: 123 } }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.iOS.bundleId' expected a string value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.android is not an object', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.sendEmailVerification({ url: 'string', android: 123 }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.android' expected an object value."); - } - await firebase.auth().currentUser.delete(); - }); - - it('should error if actionCodeSettings.android.packageName is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase - .auth() - .currentUser.sendEmailVerification({ url: 'string', android: { packageName: 123 } }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.android.packageName' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); - - it('should error if actionCodeSettings.android.installApp is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.sendEmailVerification({ - url: 'string', - android: { packageName: 'packageName', installApp: 123 }, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.android.installApp' expected a boolean value.", - ); - } - await firebase.auth().currentUser.delete(); - }); - - it('should error if actionCodeSettings.android.minimumVersion is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.sendEmailVerification({ - url: 'string', - android: { packageName: 'packageName', minimumVersion: 123 }, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.android.minimumVersion' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); - - it('should not error', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - - try { - await firebase.auth().currentUser.sendEmailVerification(); - } catch (error) { - return Promise.reject(new Error('sendEmailVerification() caused an error', error)); - } finally { + it('should error if actionCodeSettings.android is not an object', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.sendEmailVerification({ url: 'string', android: 123 }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android' expected an object value.", + ); + } await firebase.auth().currentUser.delete(); - } + }); - return Promise.resolve(); - }); + it('should error if actionCodeSettings.android.packageName is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase + .auth() + .currentUser.sendEmailVerification({ url: 'string', android: { packageName: 123 } }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android.packageName' expected a string value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should correctly report emailVerified status', async function () { - const random = Utils.randString(12, '#a'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - firebase.auth().currentUser.email.should.equal(email); - firebase.auth().currentUser.emailVerified.should.equal(false); + it('should error if actionCodeSettings.android.installApp is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.sendEmailVerification({ + url: 'string', + android: { packageName: 'packageName', installApp: 123 }, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android.installApp' expected a boolean value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - try { - await firebase.auth().currentUser.sendEmailVerification(); - const { oobCode } = await getLastOob(email); - await verifyEmail(oobCode); - firebase.auth().currentUser.emailVerified.should.equal(false); - await firebase.auth().currentUser.reload(); - firebase.auth().currentUser.emailVerified.should.equal(true); - } catch (error) { - return Promise.reject(new Error('sendEmailVerification() caused an error', error)); - } finally { + it('should error if actionCodeSettings.android.minimumVersion is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.sendEmailVerification({ + url: 'string', + android: { packageName: 'packageName', minimumVersion: 123 }, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android.minimumVersion' expected a string value.", + ); + } await firebase.auth().currentUser.delete(); - } + }); - return Promise.resolve(); - }); + it('should not error', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); - it('should work with actionCodeSettings', async function () { - const actionCodeSettings = { - handleCodeInApp: true, - url: 'https://react-native-firebase-testing.firebaseapp.com/foo', - }; - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + await firebase.auth().currentUser.sendEmailVerification(); + } catch (error) { + return Promise.reject(new Error('sendEmailVerification() caused an error', error)); + } finally { + await firebase.auth().currentUser.delete(); + } - try { - await firebase.auth().currentUser.sendEmailVerification(actionCodeSettings); - } catch (error) { - return Promise.reject( - new Error('sendEmailVerification(actionCodeSettings) error' + error.message), - ); - } finally { - await firebase.auth().currentUser.delete(); - } + return Promise.resolve(); + }); - return Promise.resolve(); - }); + it('should correctly report emailVerified status', async function () { + const random = Utils.randString(12, '#a'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + firebase.auth().currentUser.email.should.equal(email); + firebase.auth().currentUser.emailVerified.should.equal(false); - it('should throw an error within an invalid action code url', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + await firebase.auth().currentUser.sendEmailVerification(); + const { oobCode } = await getLastOob(email); + await verifyEmail(oobCode); + firebase.auth().currentUser.emailVerified.should.equal(false); + await firebase.auth().currentUser.reload(); + firebase.auth().currentUser.emailVerified.should.equal(true); + } catch (error) { + return Promise.reject(new Error('sendEmailVerification() caused an error', error)); + } finally { + await firebase.auth().currentUser.delete(); + } - (() => { - firebase.auth().currentUser.sendEmailVerification({ url: [] }); - }).should.throw( - "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.url' expected a string value.", - ); - }); - }); + return Promise.resolve(); + }); - describe('verifyBeforeUpdateEmail()', function () { - it('should error if newEmail is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; + it('should work with actionCodeSettings', async function () { + const actionCodeSettings = { + handleCodeInApp: true, + url: 'https://react-native-firebase-testing.firebaseapp.com/foo', + }; + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(123); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'newEmail' expected a string value"); - } - await firebase.auth().currentUser.delete(); - }); + try { + await firebase.auth().currentUser.sendEmailVerification(actionCodeSettings); + } catch (error) { + return Promise.reject( + new Error('sendEmailVerification(actionCodeSettings) error' + error.message), + ); + } finally { + await firebase.auth().currentUser.delete(); + } - it('should error if actionCodeSettings.url is not present', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + return Promise.resolve(); + }); - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, {}); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.url' expected a string value."); - } - await firebase.auth().currentUser.delete(); + it('should throw an error within an invalid action code url', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + await firebase.auth().createUserWithEmailAndPassword(email, random); + + (() => { + firebase.auth().currentUser.sendEmailVerification({ url: [] }); + }).should.throw( + "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.url' expected a string value.", + ); + }); }); - it('should error if actionCodeSettings.url is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + describe('verifyBeforeUpdateEmail()', function () { + it('should error if newEmail is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { url: 123 }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.url' expected a string value."); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(123); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'newEmail' expected a string value"); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.dynamicLinkDomain is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.url is not present', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - dynamicLinkDomain: 123, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.dynamicLinkDomain' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, {}); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'actionCodeSettings.url' expected a string value."); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if handleCodeInApp is not a boolean', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.url is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - handleCodeInApp: 123, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.handleCodeInApp' expected a boolean value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { url: 123 }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'actionCodeSettings.url' expected a string value."); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.iOS is not an object', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.dynamicLinkDomain is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - iOS: 123, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.iOS' expected an object value."); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + dynamicLinkDomain: 123, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.dynamicLinkDomain' expected a string value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.iOS.bundleId is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if handleCodeInApp is not a boolean', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - iOS: { bundleId: 123 }, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.iOS.bundleId' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + handleCodeInApp: 123, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.handleCodeInApp' expected a boolean value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.android is not an object', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.iOS is not an object', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - android: 123, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql("'actionCodeSettings.android' expected an object value."); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + iOS: 123, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql("'actionCodeSettings.iOS' expected an object value."); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.android.packageName is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.iOS.bundleId is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - android: { packageName: 123 }, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.android.packageName' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + iOS: { bundleId: 123 }, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.iOS.bundleId' expected a string value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.android.installApp is not a boolean', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.android is not an object', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - android: { packageName: 'string', installApp: 123 }, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.android.installApp' expected a boolean value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + android: 123, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android' expected an object value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - it('should error if actionCodeSettings.android.minimumVersion is not a string', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.android.packageName is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - await firebase.auth().createUserWithEmailAndPassword(email, random); - try { - firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { - url: 'string', - android: { packageName: 'string', minimumVersion: 123 }, - }); - return Promise.reject(new Error('it did not error')); - } catch (error) { - error.message.should.containEql( - "'actionCodeSettings.android.minimumVersion' expected a string value.", - ); - } - await firebase.auth().currentUser.delete(); - }); + await firebase.auth().createUserWithEmailAndPassword(email, random); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + android: { packageName: 123 }, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android.packageName' expected a string value.", + ); + } + await firebase.auth().currentUser.delete(); + }); - // FIXME ios+android failing with an internal error against auth emulator - // com.google.firebase.FirebaseException: An internal error has occurred. [ VERIFY_AND_CHANGE_EMAIL ] - xit('should not error', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; + it('should error if actionCodeSettings.android.installApp is not a boolean', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - try { await firebase.auth().createUserWithEmailAndPassword(email, random); - await firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail); - } catch (e) { - return Promise.reject("'verifyBeforeUpdateEmail()' did not work"); - } - await firebase.auth().currentUser.delete(); - }); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + android: { packageName: 'string', installApp: 123 }, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android.installApp' expected a boolean value.", + ); + } + await firebase.auth().currentUser.delete(); + }); + + it('should error if actionCodeSettings.android.minimumVersion is not a string', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; - // FIXME ios+android failing with an internal error against auth emulator - // com.google.firebase.FirebaseException: An internal error has occurred. [ VERIFY_AND_CHANGE_EMAIL ] - xit('should work with actionCodeSettings', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const updateEmail = `${random2}@${random2}.com`; - const actionCodeSettings = { - url: 'https://react-native-firebase-testing.firebaseapp.com/foo', - }; - try { await firebase.auth().createUserWithEmailAndPassword(email, random); - await firebase - .auth() - .currentUser.verifyBeforeUpdateEmail(updateEmail, actionCodeSettings); + try { + firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail, { + url: 'string', + android: { packageName: 'string', minimumVersion: 123 }, + }); + return Promise.reject(new Error('it did not error')); + } catch (error) { + error.message.should.containEql( + "'actionCodeSettings.android.minimumVersion' expected a string value.", + ); + } await firebase.auth().currentUser.delete(); - } catch (error) { + }); + + // FIXME ios+android failing with an internal error against auth emulator + // com.google.firebase.FirebaseException: An internal error has occurred. [ VERIFY_AND_CHANGE_EMAIL ] + xit('should not error', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; + try { - await firebase.auth().currentUser.delete(); + await firebase.auth().createUserWithEmailAndPassword(email, random); + await firebase.auth().currentUser.verifyBeforeUpdateEmail(updateEmail); } catch (e) { - consle.log(e); - /* do nothing */ + return Promise.reject("'verifyBeforeUpdateEmail()' did not work"); } + await firebase.auth().currentUser.delete(); + }); - return Promise.reject( - "'verifyBeforeUpdateEmail()' with 'actionCodeSettings' did not work", - ); - } - return Promise.resolve(); + // FIXME ios+android failing with an internal error against auth emulator + // com.google.firebase.FirebaseException: An internal error has occurred. [ VERIFY_AND_CHANGE_EMAIL ] + xit('should work with actionCodeSettings', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const updateEmail = `${random2}@${random2}.com`; + const actionCodeSettings = { + url: 'https://react-native-firebase-testing.firebaseapp.com/foo', + }; + try { + await firebase.auth().createUserWithEmailAndPassword(email, random); + await firebase + .auth() + .currentUser.verifyBeforeUpdateEmail(updateEmail, actionCodeSettings); + await firebase.auth().currentUser.delete(); + } catch (error) { + try { + await firebase.auth().currentUser.delete(); + } catch (e) { + consle.log(e); + /* do nothing */ + } + + return Promise.reject( + "'verifyBeforeUpdateEmail()' with 'actionCodeSettings' did not work", + ); + } + return Promise.resolve(); + }); }); - }); - describe('unlink()', function () { - it('should unlink the email address', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; + describe('unlink()', function () { + it('should unlink the email address', async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; - await firebase.auth().signInAnonymously(); - const { currentUser } = firebase.auth(); + await firebase.auth().signInAnonymously(); + const { currentUser } = firebase.auth(); - const credential = firebase.auth.EmailAuthProvider.credential(email, pass); - await currentUser.linkWithCredential(credential); + const credential = firebase.auth.EmailAuthProvider.credential(email, pass); + await currentUser.linkWithCredential(credential); - // Test - await currentUser.unlink(firebase.auth.EmailAuthProvider.PROVIDER_ID); + // Test + await currentUser.unlink(firebase.auth.EmailAuthProvider.PROVIDER_ID); - // Assertions - const unlinkedUser = firebase.auth().currentUser; - unlinkedUser.providerData.should.be.an.Array(); - unlinkedUser.providerData.length.should.equal(0); + // Assertions + const unlinkedUser = firebase.auth().currentUser; + unlinkedUser.providerData.should.be.an.Array(); + unlinkedUser.providerData.length.should.equal(0); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); }); - }); - describe('updateEmail()', function () { - it('should update the email address', async function () { - const random = Utils.randString(12, '#a'); - const random2 = Utils.randString(12, '#a'); - const email = `${random}@${random}.com`; - const email2 = `${random2}@${random2}.com`; - // Setup - await firebase.auth().createUserWithEmailAndPassword(email, random); - firebase.auth().currentUser.email.should.equal(email); + describe('updateEmail()', function () { + it('should update the email address', async function () { + const random = Utils.randString(12, '#a'); + const random2 = Utils.randString(12, '#a'); + const email = `${random}@${random}.com`; + const email2 = `${random2}@${random2}.com`; + // Setup + await firebase.auth().createUserWithEmailAndPassword(email, random); + firebase.auth().currentUser.email.should.equal(email); - // Update user email - await firebase.auth().currentUser.updateEmail(email2); + // Update user email + await firebase.auth().currentUser.updateEmail(email2); - // Assertions - firebase.auth().currentUser.email.should.equal(email2); + // Assertions + firebase.auth().currentUser.email.should.equal(email2); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); }); - }); - describe('updatePhoneNumber()', function () { - it('should update the phone number', async function () { - const testPhone = await getRandomPhoneNumber(); - const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); - const smsCode = await getLastSmsCode(testPhone); - await confirmResult.confirm(smsCode); + describe('updatePhoneNumber()', function () { + it('should update the phone number', async function () { + const testPhone = await getRandomPhoneNumber(); + const confirmResult = await firebase.auth().signInWithPhoneNumber(testPhone); + const smsCode = await getLastSmsCode(testPhone); + await confirmResult.confirm(smsCode); + + firebase.auth().currentUser.phoneNumber.should.equal(testPhone); + + const newPhone = await getRandomPhoneNumber(); + const newPhoneVerificationId = await new Promise((resolve, reject) => { + firebase + .auth() + .verifyPhoneNumber(newPhone) + .on('state_changed', phoneAuthSnapshot => { + if (phoneAuthSnapshot.error) { + reject(phoneAuthSnapshot.error); + } else { + resolve(phoneAuthSnapshot.verificationId); + } + }); + }); - firebase.auth().currentUser.phoneNumber.should.equal(testPhone); + try { + const newSmsCode = await getLastSmsCode(newPhone); + const credential = await firebase.auth.PhoneAuthProvider.credential( + newPhoneVerificationId, + newSmsCode, + ); + + //Update with number? + await firebase + .auth() + .currentUser.updatePhoneNumber(credential) + .then($ => $); + } catch (e) { + throw e; + } - const newPhone = await getRandomPhoneNumber(); - const newPhoneVerificationId = await new Promise((resolve, reject) => { - firebase - .auth() - .verifyPhoneNumber(newPhone) - .on('state_changed', phoneAuthSnapshot => { - if (phoneAuthSnapshot.error) { - reject(phoneAuthSnapshot.error); - } else { - resolve(phoneAuthSnapshot.verificationId); - } - }); + firebase.auth().currentUser.phoneNumber.should.equal(newPhone); }); - - try { - const newSmsCode = await getLastSmsCode(newPhone); - const credential = await firebase.auth.PhoneAuthProvider.credential( - newPhoneVerificationId, - newSmsCode, - ); - - //Update with number? - await firebase - .auth() - .currentUser.updatePhoneNumber(credential) - .then($ => $); - } catch (e) { - throw e; - } - - firebase.auth().currentUser.phoneNumber.should.equal(newPhone); }); - }); - describe('updatePassword()', function () { - it('should update the password', async function () { - const random = Utils.randString(12, '#aA'); - const random2 = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; - const pass2 = random2; + describe('updatePassword()', function () { + it('should update the password', async function () { + const random = Utils.randString(12, '#aA'); + const random2 = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; + const pass2 = random2; - // Setup - await firebase.auth().createUserWithEmailAndPassword(email, pass); + // Setup + await firebase.auth().createUserWithEmailAndPassword(email, pass); - // Update user password - await firebase.auth().currentUser.updatePassword(pass2); + // Update user password + await firebase.auth().currentUser.updatePassword(pass2); - // Sign out - await firebase.auth().signOut(); + // Sign out + await firebase.auth().signOut(); - // Log in with the new password - await firebase.auth().signInWithEmailAndPassword(email, pass2); + // Log in with the new password + await firebase.auth().signInWithEmailAndPassword(email, pass2); - // Assertions - firebase.auth().currentUser.should.be.an.Object(); - firebase.auth().currentUser.email.should.equal(email.toLowerCase()); + // Assertions + firebase.auth().currentUser.should.be.an.Object(); + firebase.auth().currentUser.email.should.equal(email.toLowerCase()); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); + + // Can only be run/reproduced locally with Firebase Auth rate limits lowered on the Firebase console. + xit('should throw too many requests when limit has been reached', async function () { + await Utils.sleep(10000); + try { + // Setup for creating new accounts + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; + const pass = random; + + const promises = []; + + // Create 10 accounts to force the error + [...Array(10).keys()].map($ => + promises.push( + new Promise(r => + r(firebase.auth().createUserWithEmailAndPassword(email + $, pass)), + ), + ), + ); + + await Promise.all(promises); + + return Promise.reject('Should have rejected'); + } catch (ex) { + ex.code.should.equal('auth/too-many-requests'); + return Promise.resolve(); + } + }); }); - // Can only be run/reproduced locally with Firebase Auth rate limits lowered on the Firebase console. - xit('should throw too many requests when limit has been reached', async function () { - await Utils.sleep(10000); - try { - // Setup for creating new accounts + describe('updateProfile()', function () { + it('should update the profile', async function () { const random = Utils.randString(12, '#aA'); const email = `${random}@${random}.com`; const pass = random; + const displayName = random; + const photoURL = `http://${random}.com/${random}.jpg`; - const promises = []; - - // Create 10 accounts to force the error - [...Array(10).keys()].map($ => - promises.push( - new Promise(r => r(firebase.auth().createUserWithEmailAndPassword(email + $, pass))), - ), - ); - - await Promise.all(promises); - - return Promise.reject('Should have rejected'); - } catch (ex) { - ex.code.should.equal('auth/too-many-requests'); - return Promise.resolve(); - } - }); - }); + // Setup + await firebase.auth().createUserWithEmailAndPassword(email, pass); - describe('updateProfile()', function () { - it('should update the profile', async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; - const pass = random; - const displayName = random; - const photoURL = `http://${random}.com/${random}.jpg`; + // Update user profile + await firebase.auth().currentUser.updateProfile({ + displayName, + photoURL, + }); - // Setup - await firebase.auth().createUserWithEmailAndPassword(email, pass); + // Assertions + const user = firebase.auth().currentUser; + user.should.be.an.Object(); + user.email.should.equal(email.toLowerCase()); + user.displayName.should.equal(displayName); + user.photoURL.should.equal(photoURL); - // Update user profile - await firebase.auth().currentUser.updateProfile({ - displayName, - photoURL, + // Clean up + await firebase.auth().currentUser.delete(); }); - // Assertions - const user = firebase.auth().currentUser; - user.should.be.an.Object(); - user.email.should.equal(email.toLowerCase()); - user.displayName.should.equal(displayName); - user.photoURL.should.equal(photoURL); - - // Clean up - await firebase.auth().currentUser.delete(); - }); - - it('should return a valid profile when signing in anonymously', async function () { - // Setup - await firebase.auth().signInAnonymously(); - const { currentUser } = firebase.auth(); + it('should return a valid profile when signing in anonymously', async function () { + // Setup + await firebase.auth().signInAnonymously(); + const { currentUser } = firebase.auth(); - // Assertions - currentUser.should.be.an.Object(); - should.equal(currentUser.email, null); - should.equal(currentUser.displayName, null); - should.equal(currentUser.emailVerified, false); - should.equal(currentUser.isAnonymous, true); - should.equal(currentUser.phoneNumber, null); - should.equal(currentUser.photoURL, null); - should.exist(currentUser.metadata.lastSignInTime); - should.exist(currentUser.metadata.creationTime); - should.deepEqual(currentUser.providerData, []); - should.exist(currentUser.providerId); - should.exist(currentUser.uid); + // Assertions + currentUser.should.be.an.Object(); + should.equal(currentUser.email, null); + should.equal(currentUser.displayName, null); + should.equal(currentUser.emailVerified, false); + should.equal(currentUser.isAnonymous, true); + should.equal(currentUser.phoneNumber, null); + should.equal(currentUser.photoURL, null); + should.exist(currentUser.metadata.lastSignInTime); + should.exist(currentUser.metadata.creationTime); + should.deepEqual(currentUser.providerData, []); + should.exist(currentUser.providerId); + should.exist(currentUser.uid); - // Clean up - await firebase.auth().currentUser.delete(); + // Clean up + await firebase.auth().currentUser.delete(); + }); }); - }); - describe('linkWithPhoneNumber()', function () { - it('should throw an unsupported error', async function () { - await firebase.auth().signInAnonymously(); - (() => { - firebase.auth().currentUser.linkWithPhoneNumber(); - }).should.throw( - 'firebase.auth.User.linkWithPhoneNumber() is unsupported by the native Firebase SDKs.', - ); - await firebase.auth().signOut(); + describe('linkWithPhoneNumber()', function () { + it('should throw an unsupported error', async function () { + await firebase.auth().signInAnonymously(); + (() => { + firebase.auth().currentUser.linkWithPhoneNumber(); + }).should.throw( + 'firebase.auth.User.linkWithPhoneNumber() is unsupported by the native Firebase SDKs.', + ); + await firebase.auth().signOut(); + }); }); - }); - describe('reauthenticateWithPhoneNumber()', function () { - it('should throw an unsupported error', async function () { - await firebase.auth().signInAnonymously(); - (() => { - firebase.auth().currentUser.reauthenticateWithPhoneNumber(); - }).should.throw( - 'firebase.auth.User.reauthenticateWithPhoneNumber() is unsupported by the native Firebase SDKs.', - ); - await firebase.auth().signOut(); + describe('reauthenticateWithPhoneNumber()', function () { + it('should throw an unsupported error', async function () { + await firebase.auth().signInAnonymously(); + (() => { + firebase.auth().currentUser.reauthenticateWithPhoneNumber(); + }).should.throw( + 'firebase.auth.User.reauthenticateWithPhoneNumber() is unsupported by the native Firebase SDKs.', + ); + await firebase.auth().signOut(); + }); }); - }); - describe('refreshToken', function () { - it('should throw an unsupported error', async function () { - await firebase.auth().signInAnonymously(); - (() => firebase.auth().currentUser.refreshToken).should.throw( - 'firebase.auth.User.refreshToken is unsupported by the native Firebase SDKs.', - ); - await firebase.auth().signOut(); + describe('refreshToken', function () { + it('should throw an unsupported error', async function () { + await firebase.auth().signInAnonymously(); + (() => firebase.auth().currentUser.refreshToken).should.throw( + 'firebase.auth.User.refreshToken is unsupported by the native Firebase SDKs.', + ); + await firebase.auth().signOut(); + }); }); - }); - describe('user.metadata', function () { - it("should have the properties 'lastSignInTime' & 'creationTime' which are ISO strings", async function () { - const random = Utils.randString(12, '#aA'); - const email = `${random}@${random}.com`; + describe('user.metadata', function () { + it("should have the properties 'lastSignInTime' & 'creationTime' which are ISO strings", async function () { + const random = Utils.randString(12, '#aA'); + const email = `${random}@${random}.com`; - const { user } = await firebase.auth().createUserWithEmailAndPassword(email, random); + const { user } = await firebase.auth().createUserWithEmailAndPassword(email, random); - const { metadata } = user; + const { metadata } = user; - should(metadata.lastSignInTime).be.a.String(); - should(metadata.creationTime).be.a.String(); + should(metadata.lastSignInTime).be.a.String(); + should(metadata.creationTime).be.a.String(); - new Date(metadata.lastSignInTime).getFullYear().should.equal(new Date().getFullYear()); - new Date(metadata.creationTime).getFullYear().should.equal(new Date().getFullYear()); + new Date(metadata.lastSignInTime).getFullYear().should.equal(new Date().getFullYear()); + new Date(metadata.creationTime).getFullYear().should.equal(new Date().getFullYear()); - await firebase.auth().currentUser.delete(); + await firebase.auth().currentUser.delete(); + }); }); }); - }); describe('modular', function () { before(async function () {