Skip to content

Commit 7d74696

Browse files
committed
Add tests
1 parent 37f78e9 commit 7d74696

File tree

9 files changed

+379
-34
lines changed

9 files changed

+379
-34
lines changed

packages-exp/auth-exp/src/core/credentials/anonymous.test.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,16 @@
1616
*/
1717

1818
import { ProviderId, SignInMethod } from '@firebase/auth-types-exp';
19+
import * as mockFetch from '../../../test/mock_fetch';
1920
import { expect, use } from 'chai';
2021
import * as chaiAsPromised from 'chai-as-promised';
2122
import { testAuth } from '../../../test/mock_auth';
2223
import { Auth } from '../../model/auth';
2324
import { AnonymousCredential } from './anonymous';
24-
/* */
25+
import { mockEndpoint } from '../../../test/api/helper';
26+
import { Endpoint } from '../../api';
27+
import { APIUserInfo } from '../../api/account_management/account';
28+
2529
use(chaiAsPromised);
2630

2731
describe('core/credentials/anonymous', () => {
@@ -47,10 +51,27 @@ describe('core/credentials/anonymous', () => {
4751
});
4852

4953
describe('#_getIdTokenResponse', () => {
50-
it('throws', async () => {
51-
await expect(credential._getIdTokenResponse(auth)).to.be.rejectedWith(
52-
Error
53-
);
54+
const serverUser: APIUserInfo = {
55+
localId: 'local-id'
56+
};
57+
58+
beforeEach(() => {
59+
mockFetch.setUp();
60+
mockEndpoint(Endpoint.SIGN_UP, {
61+
idToken: 'id-token',
62+
refreshToken: 'refresh-token',
63+
expiresIn: '1234',
64+
localId: serverUser.localId!
65+
});
66+
});
67+
afterEach(mockFetch.tearDown);
68+
69+
it('calls signUp', async () => {
70+
const idTokenResponse = await credential._getIdTokenResponse(auth);
71+
expect(idTokenResponse.idToken).to.eq('id-token');
72+
expect(idTokenResponse.refreshToken).to.eq('refresh-token');
73+
expect(idTokenResponse.expiresIn).to.eq('1234');
74+
expect(idTokenResponse.localId).to.eq(serverUser.localId);
5475
});
5576
});
5677

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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 { ProviderId, SignInMethod } from '@firebase/auth-types-exp';
19+
import { expect, use } from 'chai';
20+
import * as chaiAsPromised from 'chai-as-promised';
21+
import { testAuth } from '../../../test/mock_auth';
22+
import { Auth } from '../../model/auth';
23+
import { EmailAuthProvider } from '../providers/email';
24+
import { EmailAuthCredential } from './email';
25+
import * as mockFetch from '../../../test/mock_fetch';
26+
import { mockEndpoint } from '../../../test/api/helper';
27+
import { Endpoint } from '../../api';
28+
import { APIUserInfo } from '../../api/account_management/account';
29+
30+
use(chaiAsPromised);
31+
32+
describe('core/credentials/email', () => {
33+
let auth: Auth;
34+
let apiMock: mockFetch.Route;
35+
const serverUser: APIUserInfo = {
36+
localId: 'local-id'
37+
};
38+
39+
beforeEach(async () => {
40+
auth = await testAuth();
41+
});
42+
43+
context('email & password', () => {
44+
const credential = new EmailAuthCredential('some-email', 'some-password', EmailAuthProvider.PROVIDER_ID, EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD);
45+
46+
beforeEach(() => {
47+
mockFetch.setUp();
48+
apiMock = mockEndpoint(Endpoint.SIGN_IN_WITH_PASSWORD, {
49+
idToken: 'id-token',
50+
refreshToken: 'refresh-token',
51+
expiresIn: '1234',
52+
localId: serverUser.localId!
53+
});
54+
});
55+
afterEach(mockFetch.tearDown);
56+
57+
it('should have an email provider', () => {
58+
expect(credential.providerId).to.eq(ProviderId.PASSWORD);
59+
});
60+
61+
it('should have an anonymous sign in method', () => {
62+
expect(credential.signInMethod).to.eq(SignInMethod.EMAIL_PASSWORD);
63+
});
64+
65+
describe('#toJSON', () => {
66+
it('throws', () => {
67+
expect(credential.toJSON).to.throw(Error);
68+
});
69+
});
70+
71+
describe('#_getIdTokenResponse', () => {
72+
it('call sign in with password', async () => {
73+
const idTokenResponse = await credential._getIdTokenResponse(auth);
74+
expect(idTokenResponse.idToken).to.eq('id-token');
75+
expect(idTokenResponse.refreshToken).to.eq('refresh-token');
76+
expect(idTokenResponse.expiresIn).to.eq('1234');
77+
expect(idTokenResponse.localId).to.eq(serverUser.localId);
78+
expect(apiMock.calls[0].request).to.eql({
79+
returnSecureToken: true,
80+
email: 'some-email',
81+
password: 'some-password'
82+
});
83+
});
84+
});
85+
86+
describe('#_linkToIdToken', () => {
87+
it('throws', async () => {
88+
await expect(
89+
credential._linkToIdToken(auth, 'id-token')
90+
).to.be.rejectedWith(Error);
91+
});
92+
});
93+
94+
describe('#_matchIdTokenWithUid', () => {
95+
it('throws', () => {
96+
expect(() =>
97+
credential._matchIdTokenWithUid(auth, 'other-uid')
98+
).to.throw(Error);
99+
});
100+
});
101+
});
102+
103+
context('email link', () => {
104+
const credential = new EmailAuthCredential('some-email', 'oob-code', EmailAuthProvider.PROVIDER_ID, EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD);
105+
106+
beforeEach(() => {
107+
mockFetch.setUp();
108+
apiMock = mockEndpoint(Endpoint.SIGN_IN_WITH_EMAIL_LINK, {
109+
idToken: 'id-token',
110+
refreshToken: 'refresh-token',
111+
expiresIn: '1234',
112+
localId: serverUser.localId!
113+
});
114+
});
115+
afterEach(mockFetch.tearDown);
116+
117+
it('should have an email provider', () => {
118+
expect(credential.providerId).to.eq(ProviderId.PASSWORD);
119+
});
120+
121+
it('should have an anonymous sign in method', () => {
122+
expect(credential.signInMethod).to.eq(SignInMethod.EMAIL_LINK);
123+
});
124+
125+
describe('#toJSON', () => {
126+
it('throws', () => {
127+
expect(credential.toJSON).to.throw(Error);
128+
});
129+
});
130+
131+
describe('#_getIdTokenResponse', () => {
132+
it('call sign in with email link', async () => {
133+
const idTokenResponse = await credential._getIdTokenResponse(auth);
134+
expect(idTokenResponse.idToken).to.eq('id-token');
135+
expect(idTokenResponse.refreshToken).to.eq('refresh-token');
136+
expect(idTokenResponse.expiresIn).to.eq('1234');
137+
expect(idTokenResponse.localId).to.eq(serverUser.localId);
138+
expect(apiMock.calls[0].request).to.eql({
139+
email: 'some-email',
140+
oobCode: 'oob-code'
141+
});
142+
});
143+
});
144+
145+
describe('#_linkToIdToken', () => {
146+
it('throws', async () => {
147+
await expect(
148+
credential._linkToIdToken(auth, 'id-token')
149+
).to.be.rejectedWith(Error);
150+
});
151+
});
152+
153+
describe('#_matchIdTokenWithUid', () => {
154+
it('throws', () => {
155+
expect(() =>
156+
credential._matchIdTokenWithUid(auth, 'other-uid')
157+
).to.throw(Error);
158+
});
159+
});
160+
});
161+
});

packages-exp/auth-exp/src/core/errors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
// eslint-disable-next-line import/no-extraneous-dependencies
1819
import { ErrorFactory, ErrorMap } from '@firebase/util';
1920
import { AppName } from '../model/auth';
2021
import { User } from '../model/user';
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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 { ProviderId, SignInMethod } from '@firebase/auth-types-exp';
19+
// eslint-disable-next-line import/no-extraneous-dependencies
20+
import { FirebaseError } from '@firebase/util';
21+
import { expect, use } from 'chai';
22+
import * as chaiAsPromised from 'chai-as-promised';
23+
import { testAuth } from '../../../test/mock_auth';
24+
import { Auth } from '../../model/auth';
25+
import { EmailAuthProvider } from './email';
26+
27+
use(chaiAsPromised);
28+
29+
describe('core/providers/email', () => {
30+
let auth: Auth;
31+
32+
beforeEach(async () => {
33+
auth = await testAuth();
34+
});
35+
36+
describe('.credential', () => {
37+
it('should return an email & password credential', () => {
38+
const credential = EmailAuthProvider.credential('some-email', 'some-password');
39+
expect(credential.email).to.eq('some-email');
40+
expect(credential.password).to.eq('some-password');
41+
expect(credential.providerId).to.eq(ProviderId.PASSWORD);
42+
expect(credential.signInMethod).to.eq(SignInMethod.EMAIL_PASSWORD);
43+
});
44+
});
45+
46+
describe('.credentialWithLink', () => {
47+
it('should return an email link credential', () => {
48+
const continueUrl = 'https://www.example.com/path/to/file?a=1&b=2#c=3';
49+
const actionLink =
50+
'https://www.example.com/finishSignIn?' +
51+
'oobCode=CODE&mode=signIn&apiKey=API_KEY&' +
52+
'continueUrl=' +
53+
encodeURIComponent(continueUrl) +
54+
'&languageCode=en&state=bla';
55+
56+
const credential = EmailAuthProvider.credentialWithLink(auth, 'some-email', actionLink);
57+
expect(credential.email).to.eq('some-email');
58+
expect(credential.password).to.eq('CODE');
59+
expect(credential.providerId).to.eq(ProviderId.PASSWORD);
60+
expect(credential.signInMethod).to.eq(SignInMethod.EMAIL_LINK);
61+
});
62+
63+
context('invalid email link', () => {
64+
it('should throw an error', () => {
65+
const actionLink = 'https://www.example.com/finishSignIn?';
66+
expect(() =>
67+
EmailAuthProvider.credentialWithLink(auth, 'some-email', actionLink)
68+
).to.throw(FirebaseError, 'Firebase: Error (auth/argument-error)');
69+
});
70+
});
71+
72+
context('mismatched tenant ID', () => {
73+
it('should throw an error', () => {
74+
const continueUrl = 'https://www.example.com/path/to/file?a=1&b=2#c=3';
75+
const actionLink =
76+
'https://www.example.com/finishSignIn?' +
77+
'oobCode=CODE&mode=signIn&apiKey=API_KEY&' +
78+
'continueUrl=' +
79+
encodeURIComponent(continueUrl) +
80+
'&languageCode=en&tenantId=OTHER_TENANT_ID&state=bla';
81+
expect(() =>
82+
EmailAuthProvider.credentialWithLink(auth, 'some-email', actionLink)
83+
).to.throw(
84+
FirebaseError,
85+
"Firebase: The provided tenant ID does not match the Auth instance's tenant ID (auth/tenant-id-mismatch)."
86+
);
87+
});
88+
});
89+
});
90+
});

packages-exp/auth-exp/src/core/providers/email.ts

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,24 @@ import { EmailAuthCredential } from '../credentials/email';
2323
import { AuthErrorCode, AUTH_ERROR_FACTORY } from '../errors';
2424

2525
export class EmailAuthProvider implements externs.EmailAuthProvider {
26-
static readonly PROVIDER_ID = externs.ProviderId.PASSWORD;
27-
static readonly EMAIL_PASSWORD_SIGN_IN_METHOD =
28-
externs.SignInMethod.EMAIL_PASSWORD;
29-
static readonly EMAIL_LINK_SIGN_IN_METHOD = externs.SignInMethod.EMAIL_LINK;
30-
readonly providerId: externs.ProviderId = EmailAuthProvider.PROVIDER_ID;
26+
static readonly PROVIDER_ID = externs.ProviderId.PASSWORD;
27+
static readonly EMAIL_PASSWORD_SIGN_IN_METHOD =
28+
externs.SignInMethod.EMAIL_PASSWORD;
29+
static readonly EMAIL_LINK_SIGN_IN_METHOD = externs.SignInMethod.EMAIL_LINK;
30+
readonly providerId: externs.ProviderId = EmailAuthProvider.PROVIDER_ID;
3131

32-
static credential(
33-
email: string,
34-
password: string,
35-
signInMethod?: externs.SignInMethod
36-
): EmailAuthCredential {
37-
return new EmailAuthCredential(
38-
email,
39-
password,
40-
EmailAuthProvider.PROVIDER_ID,
41-
signInMethod || this.EMAIL_PASSWORD_SIGN_IN_METHOD
42-
);
43-
}
32+
static credential(
33+
email: string,
34+
password: string,
35+
signInMethod?: externs.SignInMethod
36+
): EmailAuthCredential {
37+
return new EmailAuthCredential(
38+
email,
39+
password,
40+
EmailAuthProvider.PROVIDER_ID,
41+
signInMethod || this.EMAIL_PASSWORD_SIGN_IN_METHOD
42+
);
43+
}
4444

4545
static credentialWithLink(
4646
auth: Auth,
@@ -54,20 +54,18 @@ export class EmailAuthProvider implements externs.EmailAuthProvider {
5454
});
5555
}
5656

57-
const credential: EmailAuthCredential = this.credential(
58-
email,
59-
actionCodeUrl.code,
60-
EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
61-
);
62-
6357
// Check if the tenant ID in the email link matches the tenant ID on Auth
6458
// instance.
65-
if (actionCodeUrl.tenantId !== auth.tenantId) {
59+
if (actionCodeUrl.tenantId !== (auth.tenantId || null)) {
6660
throw AUTH_ERROR_FACTORY.create(AuthErrorCode.TENANT_ID_MISMATCH, {
6761
appName: auth.name
6862
});
6963
}
7064

71-
return credential;
65+
return this.credential(
66+
email,
67+
actionCodeUrl.code,
68+
EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
69+
);
7270
}
73-
}
71+
}

packages-exp/auth-exp/src/core/providers/phone.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import * as externs from '@firebase/auth-types-exp';
1919

20+
// eslint-disable-next-line import/no-extraneous-dependencies
2021
import { FirebaseError } from '@firebase/util';
2122
import { Auth } from '../../model/auth';
2223
import { initializeAuth } from '../auth/auth_impl';

0 commit comments

Comments
 (0)