Skip to content

Commit f15abbf

Browse files
authored
[Auth] Update and add integration tests to bring us closer to parity with the existing tests (#4605)
* More integration tests * Formatting
1 parent 0ac48bb commit f15abbf

File tree

8 files changed

+281
-12
lines changed

8 files changed

+281
-12
lines changed

packages-exp/auth-exp/test/integration/flows/custom.local.test.ts

+18
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
Auth,
2020
createUserWithEmailAndPassword,
2121
EmailAuthProvider,
22+
getAdditionalUserInfo,
2223
linkWithCredential,
2324
OperationType,
2425
reload,
@@ -73,6 +74,9 @@ describe('Integration test: custom auth', () => {
7374
'some-claim'
7475
);
7576
expect(user.providerId).to.eq('firebase');
77+
const additionalUserInfo = await getAdditionalUserInfo(cred)!;
78+
expect(additionalUserInfo.providerId).to.be.null;
79+
expect(additionalUserInfo.isNewUser).to.be.true;
7680
});
7781

7882
it('uid will overwrite existing user, joining accounts', async () => {
@@ -128,6 +132,20 @@ describe('Integration test: custom auth', () => {
128132
expect(user.photoURL).to.eq('photo-url');
129133
});
130134

135+
it('token can be refreshed', async () => {
136+
const { user } = await signInWithCustomToken(auth, customToken);
137+
const origToken = await user.getIdToken();
138+
await new Promise(resolve => setTimeout(resolve, 1000));
139+
expect(await user.getIdToken(true)).not.to.eq(origToken);
140+
});
141+
142+
it('signing in will not override anonymous user', async () => {
143+
const { user: anonUser } = await signInAnonymously(auth);
144+
const { user: customUser } = await signInWithCustomToken(auth, customToken);
145+
expect(auth.currentUser).to.eql(customUser);
146+
expect(customUser.uid).not.to.eql(anonUser.uid);
147+
});
148+
131149
context('email/password interaction', () => {
132150
let email: string;
133151
let customToken: string;

packages-exp/auth-exp/test/integration/flows/email.test.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import {
2727
updateProfile,
2828
Auth,
2929
OperationType,
30-
UserCredential
30+
UserCredential,
31+
getAdditionalUserInfo
3132
// eslint-disable-next-line import/no-extraneous-dependencies
3233
} from '@firebase/auth-exp';
3334
import { FirebaseError } from '@firebase/util';
@@ -64,6 +65,13 @@ describe('Integration test: email/password auth', () => {
6465
expect(user.uid).to.be.a('string');
6566
expect(user.email).to.eq(email);
6667
expect(user.emailVerified).to.be.false;
68+
expect(user.providerData.length).to.eq(1);
69+
expect(user.providerData[0].providerId).to.eq('password');
70+
expect(user.providerData[0].email).to.eq(email);
71+
72+
const additionalUserInfo = getAdditionalUserInfo(userCred)!;
73+
expect(additionalUserInfo.isNewUser).to.be.true;
74+
expect(additionalUserInfo.providerId).to.eq('password');
6775
});
6876

6977
it('errors when createUser called twice', async () => {
@@ -95,6 +103,9 @@ describe('Integration test: email/password auth', () => {
95103

96104
expect(signInCred.operationType).to.eq(OperationType.SIGN_IN);
97105
expect(signInCred.user.uid).to.eq(signUpCred.user.uid);
106+
const additionalUserInfo = getAdditionalUserInfo(signInCred)!;
107+
expect(additionalUserInfo.isNewUser).to.be.false;
108+
expect(additionalUserInfo.providerId).to.eq('password');
98109
});
99110

100111
it('allows the user to sign in with signInWithCredential', async () => {
@@ -104,6 +115,9 @@ describe('Integration test: email/password auth', () => {
104115

105116
expect(signInCred.operationType).to.eq(OperationType.SIGN_IN);
106117
expect(signInCred.user.uid).to.eq(signUpCred.user.uid);
118+
const additionalUserInfo = getAdditionalUserInfo(signInCred)!;
119+
expect(additionalUserInfo.isNewUser).to.be.false;
120+
expect(additionalUserInfo.providerId).to.eq('password');
107121
});
108122

109123
it('allows the user to update profile', async () => {

packages-exp/auth-exp/test/integration/flows/phone.test.ts

+41-9
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ describe('Integration test: phone auth', () => {
8282
document.body.removeChild(fakeRecaptchaContainer);
8383
});
8484

85+
function resetVerifier(): void {
86+
verifier.clear();
87+
verifier = new RecaptchaVerifier(
88+
fakeRecaptchaContainer,
89+
undefined as any,
90+
auth
91+
);
92+
}
93+
8594
/** If in the emulator, search for the code in the API */
8695
async function code(
8796
crOrId: ConfirmationResult | string,
@@ -126,18 +135,41 @@ describe('Integration test: phone auth', () => {
126135
expect(auth.currentUser!.phoneNumber).to.be.null;
127136
});
128137

138+
it('anonymous users can upgrade using phone number', async () => {
139+
const { user } = await signInAnonymously(auth);
140+
const { uid: anonId } = user;
141+
142+
const provider = new PhoneAuthProvider(auth);
143+
const verificationId = await provider.verifyPhoneNumber(
144+
PHONE_B.phoneNumber,
145+
verifier
146+
);
147+
148+
await updatePhoneNumber(
149+
user,
150+
PhoneAuthProvider.credential(
151+
verificationId,
152+
await code(verificationId, PHONE_B.code)
153+
)
154+
);
155+
expect(user.phoneNumber).to.eq(PHONE_B.phoneNumber);
156+
157+
await auth.signOut();
158+
resetVerifier();
159+
160+
const cr = await signInWithPhoneNumber(auth, PHONE_B.phoneNumber, verifier);
161+
const { user: secondSignIn } = await cr.confirm(
162+
await code(cr, PHONE_B.code)
163+
);
164+
expect(secondSignIn.uid).to.eq(anonId);
165+
expect(secondSignIn.isAnonymous).to.be.false;
166+
expect(secondSignIn.providerData[0].phoneNumber).to.eq(PHONE_B.phoneNumber);
167+
expect(secondSignIn.providerData[0].providerId).to.eq('phone');
168+
});
169+
129170
context('with already-created user', () => {
130171
let signUpCred: UserCredential;
131172

132-
function resetVerifier(): void {
133-
verifier.clear();
134-
verifier = new RecaptchaVerifier(
135-
fakeRecaptchaContainer,
136-
undefined as any,
137-
auth
138-
);
139-
}
140-
141173
beforeEach(async () => {
142174
const cr = await signInWithPhoneNumber(
143175
auth,

packages-exp/auth-exp/test/integration/webdriver/popup.test.ts

+89-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ import { expect, use } from 'chai';
2626
import { IdPPage } from './util/idp_page';
2727
import * as chaiAsPromised from 'chai-as-promised';
2828
import { browserDescribe } from './util/test_runner';
29-
import { AnonFunction, CoreFunction, PopupFunction } from './util/functions';
29+
import {
30+
AnonFunction,
31+
CoreFunction,
32+
EmailFunction,
33+
PopupFunction
34+
} from './util/functions';
3035

3136
use(chaiAsPromised);
3237

@@ -146,6 +151,89 @@ browserDescribe('Popup IdP tests', driver => {
146151
]);
147152
});
148153

154+
it('does not auto-upgrade anon accounts', async () => {
155+
const { user: anonUser }: UserCredential = await driver.call(
156+
AnonFunction.SIGN_IN_ANONYMOUSLY
157+
);
158+
await driver.callNoWait(PopupFunction.IDP_POPUP);
159+
await driver.selectPopupWindow();
160+
const widget = new IdPPage(driver.webDriver);
161+
await widget.pageLoad();
162+
await widget.clickAddAccount();
163+
await widget.fillEmail('[email protected]');
164+
await widget.clickSignIn();
165+
166+
// On redirect, check that the signed in user is different
167+
await driver.selectMainWindow();
168+
const curUser = await driver.getUserSnapshot();
169+
expect(curUser.uid).not.to.eq(anonUser.uid);
170+
});
171+
172+
it('linking with anonymous user upgrades account', async () => {
173+
const { user: anonUser }: UserCredential = await driver.call(
174+
AnonFunction.SIGN_IN_ANONYMOUSLY
175+
);
176+
await driver.callNoWait(PopupFunction.IDP_LINK_POPUP);
177+
await driver.selectPopupWindow();
178+
const widget = new IdPPage(driver.webDriver);
179+
await widget.pageLoad();
180+
await widget.clickAddAccount();
181+
await widget.fillEmail('[email protected]');
182+
await widget.clickSignIn();
183+
184+
// On redirect, check that the signed in user is upgraded
185+
await driver.selectMainWindow();
186+
const curUser = await driver.getUserSnapshot();
187+
expect(curUser.uid).to.eq(anonUser.uid);
188+
expect(curUser.isAnonymous).to.be.false;
189+
});
190+
191+
it('is possible to link with different email', async () => {
192+
const { user: emailUser }: UserCredential = await driver.call(
193+
EmailFunction.CREATE_USER,
194+
195+
);
196+
197+
// Link using pre-poulated user
198+
await driver.callNoWait(PopupFunction.IDP_LINK_POPUP);
199+
await driver.selectPopupWindow();
200+
const widget = new IdPPage(driver.webDriver);
201+
await widget.pageLoad();
202+
await widget.clickAddAccount();
203+
await widget.fillEmail('[email protected]');
204+
await widget.clickSignIn();
205+
206+
// Check the linked account
207+
await driver.selectMainWindow();
208+
const curUser = await driver.getUserSnapshot();
209+
expect(curUser.uid).to.eq(emailUser.uid);
210+
expect(curUser.emailVerified).to.be.false;
211+
expect(curUser.providerData.length).to.eq(2);
212+
});
213+
214+
it('is possible to link with the same email', async () => {
215+
const { user: emailUser }: UserCredential = await driver.call(
216+
EmailFunction.CREATE_USER,
217+
218+
);
219+
220+
// Link using pre-poulated user
221+
await driver.callNoWait(PopupFunction.IDP_LINK_POPUP);
222+
await driver.selectPopupWindow();
223+
const widget = new IdPPage(driver.webDriver);
224+
await widget.pageLoad();
225+
await widget.clickAddAccount();
226+
await widget.fillEmail('[email protected]');
227+
await widget.clickSignIn();
228+
229+
// Check the linked account
230+
await driver.selectMainWindow();
231+
const curUser = await driver.getUserSnapshot();
232+
expect(curUser.uid).to.eq(emailUser.uid);
233+
expect(curUser.emailVerified).to.be.true;
234+
expect(curUser.providerData.length).to.eq(2);
235+
});
236+
149237
context('with existing user', () => {
150238
let user1: User;
151239
let user2: User;

packages-exp/auth-exp/test/integration/webdriver/redirect.test.ts

+87-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ import { expect, use } from 'chai';
2626
import { IdPPage } from './util/idp_page';
2727
import * as chaiAsPromised from 'chai-as-promised';
2828
import { browserDescribe } from './util/test_runner';
29-
import { AnonFunction, CoreFunction, RedirectFunction } from './util/functions';
29+
import {
30+
AnonFunction,
31+
CoreFunction,
32+
EmailFunction,
33+
RedirectFunction
34+
} from './util/functions';
3035

3136
use(chaiAsPromised);
3237

@@ -146,6 +151,87 @@ browserDescribe('WebDriver redirect IdP test', driver => {
146151
]);
147152
});
148153

154+
it('does not auto-upgrade anon accounts', async () => {
155+
const { user: anonUser }: UserCredential = await driver.call(
156+
AnonFunction.SIGN_IN_ANONYMOUSLY
157+
);
158+
await driver.callNoWait(RedirectFunction.IDP_REDIRECT);
159+
const widget = new IdPPage(driver.webDriver);
160+
await widget.pageLoad();
161+
await widget.clickAddAccount();
162+
await widget.fillEmail('[email protected]');
163+
await widget.clickSignIn();
164+
165+
// On redirect, check that the signed in user is different
166+
await driver.reinitOnRedirect();
167+
const curUser = await driver.getUserSnapshot();
168+
expect(curUser.uid).not.to.eq(anonUser.uid);
169+
});
170+
171+
it('linking with anonymous user upgrades account', async () => {
172+
const { user: anonUser }: UserCredential = await driver.call(
173+
AnonFunction.SIGN_IN_ANONYMOUSLY
174+
);
175+
await driver.callNoWait(RedirectFunction.IDP_LINK_REDIRECT);
176+
const widget = new IdPPage(driver.webDriver);
177+
await widget.pageLoad();
178+
await widget.clickAddAccount();
179+
await widget.fillEmail('[email protected]');
180+
await widget.clickSignIn();
181+
182+
// On redirect, check that the signed in user is upgraded
183+
await driver.reinitOnRedirect();
184+
const curUser = await driver.getUserSnapshot();
185+
expect(curUser.uid).to.eq(anonUser.uid);
186+
expect(curUser.isAnonymous).to.be.false;
187+
});
188+
189+
it('is possible to link with different email', async () => {
190+
const { user: emailUser }: UserCredential = await driver.call(
191+
EmailFunction.CREATE_USER,
192+
193+
);
194+
195+
// Link using pre-poulated user
196+
await driver.callNoWait(RedirectFunction.IDP_LINK_REDIRECT);
197+
198+
const widget = new IdPPage(driver.webDriver);
199+
await widget.pageLoad();
200+
await widget.clickAddAccount();
201+
await widget.fillEmail('[email protected]');
202+
await widget.clickSignIn();
203+
204+
// Check the linked account
205+
await driver.reinitOnRedirect();
206+
const curUser = await driver.getUserSnapshot();
207+
expect(curUser.uid).to.eq(emailUser.uid);
208+
expect(curUser.emailVerified).to.be.false;
209+
expect(curUser.providerData.length).to.eq(2);
210+
});
211+
212+
it('is possible to link with the same email', async () => {
213+
const { user: emailUser }: UserCredential = await driver.call(
214+
EmailFunction.CREATE_USER,
215+
216+
);
217+
218+
// Link using pre-poulated user
219+
await driver.callNoWait(RedirectFunction.IDP_LINK_REDIRECT);
220+
221+
const widget = new IdPPage(driver.webDriver);
222+
await widget.pageLoad();
223+
await widget.clickAddAccount();
224+
await widget.fillEmail('[email protected]');
225+
await widget.clickSignIn();
226+
227+
// Check the linked account
228+
await driver.reinitOnRedirect();
229+
const curUser = await driver.getUserSnapshot();
230+
expect(curUser.uid).to.eq(emailUser.uid);
231+
expect(curUser.emailVerified).to.be.true;
232+
expect(curUser.providerData.length).to.eq(2);
233+
});
234+
149235
context('with existing user', () => {
150236
let user1: User;
151237
let user2: User;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { createUserWithEmailAndPassword } from '@firebase/auth-exp';
19+
20+
const TEST_PASSWORD = 'password';
21+
22+
export function createUser(email) {
23+
return createUserWithEmailAndPassword(auth, email, TEST_PASSWORD);
24+
}

packages-exp/auth-exp/test/integration/webdriver/static/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import * as redirect from './redirect';
1919
import * as anonymous from './anonymous';
2020
import * as core from './core';
2121
import * as popup from './popup';
22+
import * as email from './email';
2223
import { initializeApp } from '@firebase/app-exp';
2324
import { getAuth, useAuthEmulator } from '@firebase/auth-exp';
2425

2526
window.core = { ...core };
2627
window.anonymous = { ...anonymous };
2728
window.redirect = { ...redirect };
2829
window.popup = { ...popup };
30+
window.email = { ...email };
2931

3032
// The config and emulator URL are injected by the test. The test framework
3133
// calls this function after that injection.

0 commit comments

Comments
 (0)