mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-04-29 12:45:45 +08:00
Merge branch 'master' into fcm-rewrite
# Conflicts: # lib/modules/core/firebase.js # tests/ios/Podfile.lock
This commit is contained in:
@@ -164,7 +164,7 @@ PODS:
|
||||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNFirebase (3.2.5):
|
||||
- RNFirebase (3.3.0):
|
||||
- React
|
||||
- yoga (0.52.0.React)
|
||||
|
||||
@@ -228,7 +228,7 @@ SPEC CHECKSUMS:
|
||||
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
|
||||
Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03
|
||||
React: 61a6bdf17a9ff16875c230e6ff278d9de274e16c
|
||||
RNFirebase: e3448c730955d51d06dee59a265011536abdd7c4
|
||||
RNFirebase: 056b672391f3e7b572d8ef221c84603970e0c114
|
||||
yoga: 646606bf554d54a16711f35596178522fbc00480
|
||||
|
||||
PODFILE CHECKSUM: 67c98bcb203cb992da590bcab6f690f727653ca5
|
||||
|
||||
@@ -1016,7 +1016,7 @@
|
||||
);
|
||||
inputPaths = (
|
||||
"${SRCROOT}/Pods/Target Support Files/Pods-ReactNativeFirebaseDemo/Pods-ReactNativeFirebaseDemo-resources.sh",
|
||||
$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle,
|
||||
"$PODS_CONFIGURATION_BUILD_DIR/gRPC/gRPCCertificates.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
|
||||
1238
tests/package-lock.json
generated
1238
tests/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -28,26 +28,26 @@
|
||||
"bows": "^1.6.0",
|
||||
"cuid": "^1.3.8",
|
||||
"deeps": "^1.4.4",
|
||||
"firebase": "^4.8.2",
|
||||
"js-beautify": "^1.6.11",
|
||||
"firebase": "^4.10.1",
|
||||
"js-beautify": "^1.7.5",
|
||||
"lodash.groupby": "^4.6.0",
|
||||
"lodash.some": "^4.6.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"query-string": "^5.0.0",
|
||||
"prop-types": "^15.6.1",
|
||||
"query-string": "^5.1.0",
|
||||
"react": "^16.2.0",
|
||||
"react-native": "^0.52.0",
|
||||
"react-native": "^0.52.3",
|
||||
"react-native-vector-icons": "^4.5.0",
|
||||
"react-navigation": "^1.0.0-beta.9",
|
||||
"react-redux": "^5.0.3",
|
||||
"react-navigation": "^1.2.1",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-test-renderer": "16.2.0",
|
||||
"redux": "^3.6.0",
|
||||
"redux-logger": "^2.8.2",
|
||||
"redux-persist": "^4.4.2",
|
||||
"redux-persist": "^4.10.2",
|
||||
"redux-thunk": "^2.2.0",
|
||||
"should": "^11.2.0",
|
||||
"should-sinon": "^0.0.5",
|
||||
"sinon": "^3.2.1",
|
||||
"url-parse": "^1.1.9"
|
||||
"url-parse": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.0",
|
||||
@@ -59,8 +59,8 @@
|
||||
"colors": "^1.1.2",
|
||||
"eslint": "^3.16.1",
|
||||
"eslint-config-airbnb": "^14.1.0",
|
||||
"eslint-plugin-flowtype": "^2.30.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-flowtype": "^2.46.1",
|
||||
"eslint-plugin-import": "^2.9.0",
|
||||
"eslint-plugin-jsx-a11y": "^4.0.0",
|
||||
"eslint-plugin-react": "^6.10.0",
|
||||
"jest": "19.0.2",
|
||||
|
||||
@@ -4,8 +4,12 @@ import firebase from 'firebase';
|
||||
import RNfirebase from './../firebase';
|
||||
import DatabaseContents from './tests/support/DatabaseContents';
|
||||
|
||||
RNfirebase.database.enableLogging(true);
|
||||
RNfirebase.firestore.enableLogging(true);
|
||||
// RNfirebase.database.enableLogging(true);
|
||||
// RNfirebase.firestore.enableLogging(true);
|
||||
|
||||
// RNfirebase.utils().logLevel = 'debug';
|
||||
// RNfirebase.utils().logLevel = 'info';
|
||||
RNfirebase.utils().logLevel = 'warn'; // default
|
||||
|
||||
const init = async () => {
|
||||
try {
|
||||
@@ -112,18 +116,22 @@ console.log('RNApps -->', RNfirebase.apps);
|
||||
// no need for ready checks
|
||||
instances.native
|
||||
.auth()
|
||||
.signInAnonymously()
|
||||
.then(user => {
|
||||
console.log('defaultApp user ->', user.toJSON());
|
||||
.signInAnonymouslyAndRetrieveData()
|
||||
.then(credential => {
|
||||
if (credential) {
|
||||
console.log('anotherApp credential ->', credential.user.toJSON());
|
||||
}
|
||||
});
|
||||
|
||||
// dynamically initialized apps need a ready check
|
||||
instances.another.onReady().then(app => {
|
||||
app
|
||||
.auth()
|
||||
.signInAnonymously()
|
||||
.then(user => {
|
||||
console.log('anotherApp user ->', user.toJSON());
|
||||
.signInAnonymouslyAndRetrieveData()
|
||||
.then(credential => {
|
||||
if (credential) {
|
||||
console.log('anotherApp credential ->', credential.user.toJSON());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -16,6 +16,24 @@ export default function addTests({ describe, it, firebase }) {
|
||||
resolve();
|
||||
}));
|
||||
|
||||
it('logEvent should error if name is not a string', () => {
|
||||
(() => {
|
||||
firebase.native.analytics().logEvent(123456);
|
||||
}).should.throw(
|
||||
`analytics.logEvent(): First argument 'name' is required and must be a string value.`
|
||||
);
|
||||
});
|
||||
|
||||
it('logEvent should error if params is not an object', () => {
|
||||
(() => {
|
||||
firebase.native
|
||||
.analytics()
|
||||
.logEvent('test_event', 'this should be an object');
|
||||
}).should.throw(
|
||||
`analytics.logEvent(): Second optional argument 'params' must be an object if provided.`
|
||||
);
|
||||
});
|
||||
|
||||
it('setAnalyticsCollectionEnabled: it should run without error', () =>
|
||||
new Promise(resolve => {
|
||||
firebase.native.analytics().setAnalyticsCollectionEnabled(true);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,9 +2,13 @@ import firebase from '../../firebase';
|
||||
import TestSuite from '../../../lib/TestSuite';
|
||||
|
||||
import authTests from './authTests';
|
||||
import providerTests from './providerTests';
|
||||
import userTests from './userTests';
|
||||
|
||||
const suite = new TestSuite('Auth', 'firebase.auth()', firebase);
|
||||
|
||||
suite.addTests(authTests);
|
||||
suite.addTests(providerTests);
|
||||
suite.addTests(userTests);
|
||||
|
||||
export default suite;
|
||||
|
||||
219
tests/src/tests/auth/providerTests.js
Normal file
219
tests/src/tests/auth/providerTests.js
Normal file
@@ -0,0 +1,219 @@
|
||||
export default (providerTests = ({ context, describe, it, firebase }) => {
|
||||
describe('EmailAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.EmailAuthProvider()).should.throw(
|
||||
'`new EmailAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const email = 'email@email.com';
|
||||
const password = 'password';
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
password
|
||||
);
|
||||
credential.providerId.should.equal('password');
|
||||
credential.token.should.equal(email);
|
||||
credential.secret.should.equal(password);
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return password', () => {
|
||||
firebase.native.auth.EmailAuthProvider.PROVIDER_ID.should.equal(
|
||||
'password'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('FacebookAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.FacebookAuthProvider()).should.throw(
|
||||
'`new FacebookAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const token = '123456';
|
||||
const credential = firebase.native.auth.FacebookAuthProvider.credential(
|
||||
token
|
||||
);
|
||||
credential.providerId.should.equal('facebook.com');
|
||||
credential.token.should.equal(token);
|
||||
credential.secret.should.equal('');
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return facebook.com', () => {
|
||||
firebase.native.auth.FacebookAuthProvider.PROVIDER_ID.should.equal(
|
||||
'facebook.com'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GithubAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.GithubAuthProvider()).should.throw(
|
||||
'`new GithubAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const token = '123456';
|
||||
const credential = firebase.native.auth.GithubAuthProvider.credential(
|
||||
token
|
||||
);
|
||||
credential.providerId.should.equal('github.com');
|
||||
credential.token.should.equal(token);
|
||||
credential.secret.should.equal('');
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return github.com', () => {
|
||||
firebase.native.auth.GithubAuthProvider.PROVIDER_ID.should.equal(
|
||||
'github.com'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GoogleAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.GoogleAuthProvider()).should.throw(
|
||||
'`new GoogleAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const token = '123456';
|
||||
const secret = '654321';
|
||||
const credential = firebase.native.auth.GoogleAuthProvider.credential(
|
||||
token,
|
||||
secret
|
||||
);
|
||||
credential.providerId.should.equal('google.com');
|
||||
credential.token.should.equal(token);
|
||||
credential.secret.should.equal(secret);
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return google.com', () => {
|
||||
firebase.native.auth.GoogleAuthProvider.PROVIDER_ID.should.equal(
|
||||
'google.com'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('OAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.OAuthProvider()).should.throw(
|
||||
'`new OAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const idToken = '123456';
|
||||
const accessToken = '654321';
|
||||
const credential = firebase.native.auth.OAuthProvider.credential(
|
||||
idToken,
|
||||
accessToken
|
||||
);
|
||||
credential.providerId.should.equal('oauth');
|
||||
credential.token.should.equal(idToken);
|
||||
credential.secret.should.equal(accessToken);
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return oauth', () => {
|
||||
firebase.native.auth.OAuthProvider.PROVIDER_ID.should.equal('oauth');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('PhoneAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.PhoneAuthProvider()).should.throw(
|
||||
'`new PhoneAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const verificationId = '123456';
|
||||
const code = '654321';
|
||||
const credential = firebase.native.auth.PhoneAuthProvider.credential(
|
||||
verificationId,
|
||||
code
|
||||
);
|
||||
credential.providerId.should.equal('phone');
|
||||
credential.token.should.equal(verificationId);
|
||||
credential.secret.should.equal(code);
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return phone', () => {
|
||||
firebase.native.auth.PhoneAuthProvider.PROVIDER_ID.should.equal(
|
||||
'phone'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TwitterAuthProvider', () => {
|
||||
context('constructor', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => new firebase.native.auth.TwitterAuthProvider()).should.throw(
|
||||
'`new TwitterAuthProvider()` is not supported on the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('credential', () => {
|
||||
it('should return a credential object', () => {
|
||||
const token = '123456';
|
||||
const secret = '654321';
|
||||
const credential = firebase.native.auth.TwitterAuthProvider.credential(
|
||||
token,
|
||||
secret
|
||||
);
|
||||
credential.providerId.should.equal('twitter.com');
|
||||
credential.token.should.equal(token);
|
||||
credential.secret.should.equal(secret);
|
||||
});
|
||||
});
|
||||
|
||||
context('PROVIDER_ID', () => {
|
||||
it('should return twitter.com', () => {
|
||||
firebase.native.auth.TwitterAuthProvider.PROVIDER_ID.should.equal(
|
||||
'twitter.com'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
504
tests/src/tests/auth/userTests.js
Normal file
504
tests/src/tests/auth/userTests.js
Normal file
@@ -0,0 +1,504 @@
|
||||
const randomString = (length, chars) => {
|
||||
let mask = '';
|
||||
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
|
||||
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
if (chars.indexOf('#') > -1) mask += '0123456789';
|
||||
if (chars.indexOf('!') > -1) mask += '~`!@#$%^&*()_+-={}[]:";\'<>?,./|\\';
|
||||
let result = '';
|
||||
for (let i = length; i > 0; --i) {
|
||||
result += mask[Math.round(Math.random() * (mask.length - 1))];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default (userTests = ({ context, describe, it, firebase }) => {
|
||||
describe('User', () => {
|
||||
context('getIdToken()', () => {
|
||||
it('should return a token', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
const newUser = await firebase.native
|
||||
.auth()
|
||||
.createUserWithEmailAndPassword(email, pass);
|
||||
|
||||
// Test
|
||||
const token = await newUser.getIdToken();
|
||||
|
||||
// Assertions
|
||||
token.should.be.a.String();
|
||||
token.length.should.be.greaterThan(24);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('getToken()', () => {
|
||||
it('should return a token', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
const newUser = await firebase.native
|
||||
.auth()
|
||||
.createUserWithEmailAndPassword(email, pass);
|
||||
|
||||
// Test
|
||||
const token = await newUser.getToken();
|
||||
|
||||
// Assertions
|
||||
token.should.be.a.String();
|
||||
token.length.should.be.greaterThan(24);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('linkWithCredential()', () => {
|
||||
it('should link anonymous account <-> email account', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
|
||||
// Test
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
|
||||
const linkedUser = await currentUser.linkWithCredential(credential);
|
||||
|
||||
// Assertions
|
||||
linkedUser.should.be.an.Object();
|
||||
linkedUser.should.equal(firebase.native.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.native.auth().currentUser.delete();
|
||||
});
|
||||
|
||||
it('should error on link anon <-> email if email already exists', async () => {
|
||||
const email = 'test@test.com';
|
||||
const pass = 'test1234';
|
||||
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
|
||||
// Test
|
||||
try {
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
await currentUser.linkWithCredential(credential);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().signOut();
|
||||
|
||||
// Reject
|
||||
Promise.reject(new Error('Did not error on link'));
|
||||
} catch (error) {
|
||||
// Assertions
|
||||
error.code.should.equal('auth/email-already-in-use');
|
||||
error.message.should.equal(
|
||||
'The email address is already in use by another account.'
|
||||
);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('linkAndRetrieveDataWithCredential()', () => {
|
||||
it('should link anonymous account <-> email account', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
|
||||
// Test
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
|
||||
const linkedUserCredential = await currentUser.linkAndRetrieveDataWithCredential(
|
||||
credential
|
||||
);
|
||||
|
||||
// Assertions
|
||||
const linkedUser = linkedUserCredential.user;
|
||||
linkedUser.should.be.an.Object();
|
||||
linkedUser.should.equal(firebase.native.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.native.auth().currentUser.delete();
|
||||
});
|
||||
|
||||
it('should error on link anon <-> email if email already exists', async () => {
|
||||
const email = 'test@test.com';
|
||||
const pass = 'test1234';
|
||||
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
|
||||
// Test
|
||||
try {
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
await currentUser.linkAndRetrieveDataWithCredential(credential);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().signOut();
|
||||
|
||||
// Reject
|
||||
Promise.reject(new Error('Did not error on link'));
|
||||
} catch (error) {
|
||||
// Assertions
|
||||
error.code.should.equal('auth/email-already-in-use');
|
||||
error.message.should.equal(
|
||||
'The email address is already in use by another account.'
|
||||
);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('reauthenticateWithCredential()', () => {
|
||||
it('should reauthenticate correctly', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
await firebase.native
|
||||
.auth()
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, pass);
|
||||
|
||||
// Test
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
await firebase.native
|
||||
.auth()
|
||||
.currentUser.reauthenticateWithCredential(credential);
|
||||
|
||||
// Assertions
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
currentUser.email.should.equal(email.toLowerCase());
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('reauthenticateAndRetrieveDataWithCredential()', () => {
|
||||
it('should reauthenticate correctly', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
await firebase.native
|
||||
.auth()
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, pass);
|
||||
|
||||
// Test
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
await firebase.native
|
||||
.auth()
|
||||
.currentUser.reauthenticateAndRetrieveDataWithCredential(credential);
|
||||
|
||||
// Assertions
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
currentUser.email.should.equal(email.toLowerCase());
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('reload()', () => {
|
||||
it('should not error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
|
||||
try {
|
||||
await firebase.native.auth().currentUser.reload();
|
||||
await firebase.native.auth().signOut();
|
||||
} catch (error) {
|
||||
// Reject
|
||||
await firebase.native.auth().signOut();
|
||||
Promise.reject(new Error('reload() caused an error', error));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('sendEmailVerification()', () => {
|
||||
it('should not error', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
await firebase.native
|
||||
.auth()
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, pass);
|
||||
|
||||
try {
|
||||
await firebase.native.auth().currentUser.sendEmailVerification();
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
} catch (error) {
|
||||
// Reject
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
Promise.reject(
|
||||
new Error('sendEmailVerification() caused an error', error)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
context('unlink()', () => {
|
||||
it('should unlink the email address', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
const currentUser = firebase.native.auth().currentUser;
|
||||
|
||||
const credential = firebase.native.auth.EmailAuthProvider.credential(
|
||||
email,
|
||||
pass
|
||||
);
|
||||
await currentUser.linkAndRetrieveDataWithCredential(credential);
|
||||
|
||||
// Test
|
||||
await currentUser.unlink(
|
||||
firebase.native.auth.EmailAuthProvider.PROVIDER_ID
|
||||
);
|
||||
|
||||
// Assertions
|
||||
const unlinkedUser = firebase.native.auth().currentUser;
|
||||
unlinkedUser.providerData.should.be.an.Array();
|
||||
unlinkedUser.providerData.length.should.equal(0);
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('updateEmail()', () => {
|
||||
it('should update the email address', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const random2 = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const email2 = `${random2}@${random2}.com`;
|
||||
const pass = random;
|
||||
|
||||
// Setup
|
||||
await firebase.native
|
||||
.auth()
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, pass);
|
||||
firebase.native
|
||||
.auth()
|
||||
.currentUser.email.toLowerCase()
|
||||
.should.equal(email.toLowerCase());
|
||||
|
||||
// Update user email
|
||||
await firebase.native.auth().currentUser.updateEmail(email2);
|
||||
|
||||
// Assertions
|
||||
firebase.native
|
||||
.auth()
|
||||
.currentUser.email.toLowerCase()
|
||||
.should.equal(email2.toLowerCase());
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('updatePassword()', () => {
|
||||
it('should update the password', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const random2 = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
const pass2 = random2;
|
||||
|
||||
// Setup
|
||||
await firebase.native
|
||||
.auth()
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, pass);
|
||||
|
||||
// Update user password
|
||||
await firebase.native.auth().currentUser.updatePassword(pass2);
|
||||
|
||||
// Sign out
|
||||
await firebase.native.auth().signOut();
|
||||
|
||||
// Log in with the new password
|
||||
await firebase.native
|
||||
.auth()
|
||||
.signInAndRetrieveDataWithEmailAndPassword(email, pass2);
|
||||
|
||||
// Assertions
|
||||
firebase.native.auth().currentUser.should.be.an.Object();
|
||||
firebase.native
|
||||
.auth()
|
||||
.currentUser.email.should.equal(email.toLowerCase());
|
||||
|
||||
// Clean up
|
||||
await firebase.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('updateProfile()', () => {
|
||||
it('should update the profile', async () => {
|
||||
const random = randomString(12, '#aA');
|
||||
const email = `${random}@${random}.com`;
|
||||
const pass = random;
|
||||
const displayName = random;
|
||||
const photoURL = `http://${random}.com/${random}.jpg`;
|
||||
|
||||
// Setup
|
||||
await firebase.native
|
||||
.auth()
|
||||
.createUserAndRetrieveDataWithEmailAndPassword(email, pass);
|
||||
|
||||
// Update user profile
|
||||
await firebase.native.auth().currentUser.updateProfile({
|
||||
displayName,
|
||||
photoURL,
|
||||
});
|
||||
|
||||
// Assertions
|
||||
const user = firebase.native.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.native.auth().currentUser.delete();
|
||||
});
|
||||
});
|
||||
|
||||
context('linkWithPhoneNumber()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.linkWithPhoneNumber();
|
||||
}).should.throw(
|
||||
'User.linkWithPhoneNumber() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('linkWithPopup()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.linkWithPopup();
|
||||
}).should.throw(
|
||||
'User.linkWithPopup() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('linkWithRedirect()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.linkWithRedirect();
|
||||
}).should.throw(
|
||||
'User.linkWithRedirect() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('reauthenticateWithPhoneNumber()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.reauthenticateWithPhoneNumber();
|
||||
}).should.throw(
|
||||
'User.reauthenticateWithPhoneNumber() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('reauthenticateWithPopup()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.reauthenticateWithPopup();
|
||||
}).should.throw(
|
||||
'User.reauthenticateWithPopup() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('reauthenticateWithRedirect()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.reauthenticateWithRedirect();
|
||||
}).should.throw(
|
||||
'User.reauthenticateWithRedirect() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('updatePhoneNumber()', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => {
|
||||
firebase.native.auth().currentUser.updatePhoneNumber();
|
||||
}).should.throw(
|
||||
'User.updatePhoneNumber() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
|
||||
context('refreshToken', () => {
|
||||
it('should throw an unsupported error', async () => {
|
||||
await firebase.native.auth().signInAnonymouslyAndRetrieveData();
|
||||
(() => firebase.native.auth().currentUser.refreshToken).should.throw(
|
||||
'User.refreshToken is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
await firebase.native.auth().signOut();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Platform } from 'react-native';
|
||||
import should from 'should';
|
||||
|
||||
import RNFirebase from './../../../firebase';
|
||||
import firebase from './../../../firebase';
|
||||
|
||||
const androidTestConfig = {
|
||||
// firebase android sdk completely ignores client id
|
||||
@@ -33,52 +33,47 @@ function rand(from = 1, to = 9999) {
|
||||
}
|
||||
|
||||
function coreTests({ describe, it }) {
|
||||
describe('Core', () => {
|
||||
describe('Firebase', () => {
|
||||
it('it should create js apps for natively initialized apps', () => {
|
||||
should.equal(RNFirebase.app()._nativeInitialized, true);
|
||||
should.equal(firebase.app()._nativeInitialized, true);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
it('natively initialized apps should have options available in js', () => {
|
||||
should.equal(
|
||||
RNFirebase.app().options.apiKey,
|
||||
firebase.app().options.apiKey,
|
||||
Platform.OS === 'ios' ? iosTestConfig.apiKey : androidTestConfig.apiKey
|
||||
);
|
||||
should.equal(
|
||||
RNFirebase.app().options.appId,
|
||||
firebase.app().options.appId,
|
||||
Platform.OS === 'ios' ? iosTestConfig.appId : androidTestConfig.appId
|
||||
);
|
||||
should.equal(
|
||||
RNFirebase.app().options.databaseURL,
|
||||
firebase.app().options.databaseURL,
|
||||
iosTestConfig.databaseURL
|
||||
);
|
||||
should.equal(
|
||||
RNFirebase.app().options.messagingSenderId,
|
||||
firebase.app().options.messagingSenderId,
|
||||
iosTestConfig.messagingSenderId
|
||||
);
|
||||
should.equal(RNFirebase.app().options.projectId, iosTestConfig.projectId);
|
||||
should.equal(firebase.app().options.projectId, iosTestConfig.projectId);
|
||||
should.equal(
|
||||
RNFirebase.app().options.storageBucket,
|
||||
firebase.app().options.storageBucket,
|
||||
iosTestConfig.storageBucket
|
||||
);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
it('it should resolve onReady for natively initialized apps', () =>
|
||||
RNFirebase.app().onReady());
|
||||
|
||||
it('it should provide an array of apps', () => {
|
||||
should.equal(!!RNFirebase.apps.length, true);
|
||||
should.equal(RNFirebase.apps.includes(RNFirebase.app('[DEFAULT]')), true);
|
||||
return Promise.resolve();
|
||||
});
|
||||
firebase.app().onReady());
|
||||
|
||||
it('it should initialize dynamic apps', () => {
|
||||
const name = `testscoreapp${rand()}`;
|
||||
return RNFirebase.initializeApp(
|
||||
Platform.OS === 'ios' ? iosTestConfig : androidTestConfig,
|
||||
name
|
||||
)
|
||||
return firebase
|
||||
.initializeApp(
|
||||
Platform.OS === 'ios' ? iosTestConfig : androidTestConfig,
|
||||
name
|
||||
)
|
||||
.onReady()
|
||||
.then(newApp => {
|
||||
newApp.name.should.equal(name.toUpperCase());
|
||||
@@ -90,6 +85,52 @@ function coreTests({ describe, it }) {
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
|
||||
it('SDK_VERSION should return a string version', () => {
|
||||
firebase.SDK_VERSION.should.be.a.String();
|
||||
});
|
||||
});
|
||||
|
||||
describe('App', () => {
|
||||
it('apps should provide an array of apps', () => {
|
||||
should.equal(!!firebase.apps.length, true);
|
||||
should.equal(firebase.apps.includes(firebase.app('[DEFAULT]')), true);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
it('delete is unsupported', () => {
|
||||
(() => {
|
||||
firebase.app().delete();
|
||||
}).should.throw(
|
||||
'app.delete() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
|
||||
it('extendApp should error if an object is not supplied', () => {
|
||||
(() => {
|
||||
firebase.app().extendApp('string');
|
||||
}).should.throw(
|
||||
"Missing required argument of type 'Object' for method 'extendApp()'."
|
||||
);
|
||||
});
|
||||
|
||||
it('extendApp should error if a protected property is supplied', () => {
|
||||
(() => {
|
||||
firebase.app().extendApp({
|
||||
database: {},
|
||||
});
|
||||
}).should.throw(
|
||||
"Property 'database' is protected and can not be overridden by extendApp."
|
||||
);
|
||||
});
|
||||
|
||||
it('extendApp should provide additional functionality', () => {
|
||||
const extension = {};
|
||||
firebase.app().extendApp({
|
||||
extension,
|
||||
});
|
||||
firebase.app().extension.should.equal(extension);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,15 @@ function collectionReferenceTests({
|
||||
}));
|
||||
});
|
||||
|
||||
context('parent', () => {
|
||||
it('should return parent document', () => {
|
||||
const collection = firebase.native
|
||||
.firestore()
|
||||
.collection('collection/document/subcollection');
|
||||
collection.parent.path.should.equal('collection/document');
|
||||
});
|
||||
});
|
||||
|
||||
context('add()', () => {
|
||||
it('should create Document', () =>
|
||||
firebase.native
|
||||
@@ -51,6 +60,15 @@ function collectionReferenceTests({
|
||||
should.equal(docRef.path, 'collection-tests/doc');
|
||||
resolve();
|
||||
}));
|
||||
|
||||
it('should error when supplied an incorrect path', () => {
|
||||
(() => {
|
||||
firebase.native
|
||||
.firestore()
|
||||
.collection('collection')
|
||||
.doc('invalid/doc');
|
||||
}).should.throw('Argument "documentPath" must point to a document.');
|
||||
});
|
||||
});
|
||||
|
||||
context('get()', () => {
|
||||
@@ -68,6 +86,47 @@ function collectionReferenceTests({
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('QuerySnapshot has correct properties', async () => {
|
||||
const snapshot = await firebase.native
|
||||
.firestore()
|
||||
.collection('collection-tests')
|
||||
.get();
|
||||
|
||||
snapshot.docChanges.should.be.an.Array();
|
||||
snapshot.empty.should.equal(false);
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
snapshot.query.should.be.an.Object();
|
||||
});
|
||||
|
||||
it('DocumentChange has correct properties', async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
.collection('collection-tests');
|
||||
|
||||
// Test
|
||||
|
||||
let unsubscribe;
|
||||
let changes;
|
||||
await new Promise(resolve2 => {
|
||||
unsubscribe = collectionRef.onSnapshot(snapshot => {
|
||||
changes = snapshot.docChanges;
|
||||
resolve2();
|
||||
});
|
||||
});
|
||||
|
||||
// Assertions
|
||||
|
||||
changes.should.be.a.Array();
|
||||
changes[0].doc.should.be.an.Object();
|
||||
changes[0].newIndex.should.be.a.Number();
|
||||
changes[0].oldIndex.should.be.a.Number();
|
||||
changes[0].type.should.be.a.String();
|
||||
|
||||
// Tear down
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
it('calls callback with the initial data and then when document changes', async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
@@ -104,9 +163,7 @@ function collectionReferenceTests({
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('calls callback with the initial data and then when document is added', async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
@@ -144,9 +201,7 @@ function collectionReferenceTests({
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it("doesn't call callback when the ref is updated with the same value", async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
@@ -181,9 +236,7 @@ function collectionReferenceTests({
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('allows binding multiple callbacks to the same ref', async () => {
|
||||
// Setup
|
||||
const collectionRef = firebase.native
|
||||
@@ -234,9 +287,7 @@ function collectionReferenceTests({
|
||||
unsubscribeA();
|
||||
unsubscribeB();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('listener stops listening when unsubscribed', async () => {
|
||||
// Setup
|
||||
const collectionRef = firebase.native
|
||||
@@ -310,9 +361,7 @@ function collectionReferenceTests({
|
||||
callbackA.should.be.calledTwice();
|
||||
callbackB.should.be.calledThrice();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('supports options and callback', async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
@@ -354,9 +403,7 @@ function collectionReferenceTests({
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('supports observer', async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
@@ -396,9 +443,7 @@ function collectionReferenceTests({
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('supports options and observer', async () => {
|
||||
const collectionRef = firebase.native
|
||||
.firestore()
|
||||
@@ -416,6 +461,7 @@ function collectionReferenceTests({
|
||||
snapshot.forEach(doc => callback(doc.data()));
|
||||
resolve2();
|
||||
},
|
||||
error: () => {},
|
||||
};
|
||||
unsubscribe = collectionRef.onSnapshot(
|
||||
{
|
||||
@@ -443,6 +489,91 @@ function collectionReferenceTests({
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
it('errors when invalid parameters supplied', async () => {
|
||||
const colRef = firebase.native
|
||||
.firestore()
|
||||
.collection('collection-tests');
|
||||
|
||||
(() => {
|
||||
colRef.onSnapshot(() => {}, 'error');
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Second argument must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot({
|
||||
next: () => {},
|
||||
error: 'error',
|
||||
});
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot({
|
||||
next: 'error',
|
||||
});
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
},
|
||||
() => {},
|
||||
'error'
|
||||
);
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Third argument must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
},
|
||||
{
|
||||
next: () => {},
|
||||
error: 'error',
|
||||
}
|
||||
);
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
},
|
||||
{
|
||||
next: 'error',
|
||||
}
|
||||
);
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot(
|
||||
{
|
||||
includeQueryMetadataChanges: true,
|
||||
},
|
||||
'error'
|
||||
);
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Second argument must be a function or observer.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot({
|
||||
error: 'error',
|
||||
});
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: First argument must be a function, observer or options.'
|
||||
);
|
||||
(() => {
|
||||
colRef.onSnapshot();
|
||||
}).should.throw(
|
||||
'Query.onSnapshot failed: Called with invalid arguments.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Where
|
||||
@@ -1005,6 +1136,56 @@ function collectionReferenceTests({
|
||||
});
|
||||
});
|
||||
|
||||
context('orderBy()', () => {
|
||||
it('errors if called after startAt', () => {
|
||||
(() => {
|
||||
firebase.native
|
||||
.firestore()
|
||||
.collection('collections')
|
||||
.startAt({})
|
||||
.orderBy('test');
|
||||
}).should.throw(
|
||||
'Cannot specify an orderBy() constraint after calling startAt(), startAfter(), endBefore() or endAt().'
|
||||
);
|
||||
});
|
||||
|
||||
it('errors if called after startAfter', () => {
|
||||
(() => {
|
||||
firebase.native
|
||||
.firestore()
|
||||
.collection('collections')
|
||||
.startAfter({})
|
||||
.orderBy('test');
|
||||
}).should.throw(
|
||||
'Cannot specify an orderBy() constraint after calling startAt(), startAfter(), endBefore() or endAt().'
|
||||
);
|
||||
});
|
||||
|
||||
it('errors if called after endBefore', () => {
|
||||
(() => {
|
||||
firebase.native
|
||||
.firestore()
|
||||
.collection('collections')
|
||||
.endBefore({})
|
||||
.orderBy('test');
|
||||
}).should.throw(
|
||||
'Cannot specify an orderBy() constraint after calling startAt(), startAfter(), endBefore() or endAt().'
|
||||
);
|
||||
});
|
||||
|
||||
it('errors if called after endAt', () => {
|
||||
(() => {
|
||||
firebase.native
|
||||
.firestore()
|
||||
.collection('collections')
|
||||
.endAt({})
|
||||
.orderBy('test');
|
||||
}).should.throw(
|
||||
'Cannot specify an orderBy() constraint after calling startAt(), startAfter(), endBefore() or endAt().'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('gets called correctly', async () => {
|
||||
const collectionRef = collectionTests
|
||||
|
||||
@@ -17,6 +17,28 @@ function documentReferenceTests({ describe, it, context, firebase }) {
|
||||
}));
|
||||
});
|
||||
|
||||
context('id', () => {
|
||||
it('should return document id', () => {
|
||||
const document = firebase.native.firestore().doc('documents/doc1');
|
||||
document.id.should.equal('doc1');
|
||||
});
|
||||
});
|
||||
|
||||
context('parent', () => {
|
||||
it('should return parent collection', () => {
|
||||
const document = firebase.native.firestore().doc('documents/doc1');
|
||||
document.parent.id.should.equal('documents');
|
||||
});
|
||||
});
|
||||
|
||||
context('collection()', () => {
|
||||
it('should return a child collection', () => {
|
||||
const document = firebase.native.firestore().doc('documents/doc1');
|
||||
const collection = document.collection('pages');
|
||||
collection.id.should.equal('pages');
|
||||
});
|
||||
});
|
||||
|
||||
context('delete()', () => {
|
||||
it('should delete Document', () =>
|
||||
firebase.native
|
||||
@@ -32,6 +54,17 @@ function documentReferenceTests({ describe, it, context, firebase }) {
|
||||
}));
|
||||
});
|
||||
|
||||
context('get()', () => {
|
||||
it('DocumentSnapshot should have correct properties', async () => {
|
||||
const snapshot = await firebase.native
|
||||
.firestore()
|
||||
.doc('document-tests/doc1')
|
||||
.get();
|
||||
snapshot.id.should.equal('doc1');
|
||||
snapshot.metadata.should.be.an.Object();
|
||||
});
|
||||
});
|
||||
|
||||
context('onSnapshot()', () => {
|
||||
it('calls callback with the initial data and then when value changes', async () => {
|
||||
const docRef = firebase.native.firestore().doc('document-tests/doc1');
|
||||
@@ -321,6 +354,7 @@ function documentReferenceTests({ describe, it, context, firebase }) {
|
||||
callback(snapshot.data());
|
||||
resolve2();
|
||||
},
|
||||
error: () => {},
|
||||
};
|
||||
unsubscribe = docRef.onSnapshot(
|
||||
{ includeMetadataChanges: true },
|
||||
@@ -346,6 +380,88 @@ function documentReferenceTests({ describe, it, context, firebase }) {
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
|
||||
it('errors when invalid parameters supplied', async () => {
|
||||
const docRef = firebase.native.firestore().doc('document-tests/doc1');
|
||||
(() => {
|
||||
docRef.onSnapshot(() => {}, 'error');
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Second argument must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot({
|
||||
next: () => {},
|
||||
error: 'error',
|
||||
});
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot({
|
||||
next: 'error',
|
||||
});
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot(
|
||||
{
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
() => {},
|
||||
'error'
|
||||
);
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Third argument must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot(
|
||||
{
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
{
|
||||
next: () => {},
|
||||
error: 'error',
|
||||
}
|
||||
);
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Observer.error must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot(
|
||||
{
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
{
|
||||
next: 'error',
|
||||
}
|
||||
);
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Observer.next must be a valid function.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot(
|
||||
{
|
||||
includeMetadataChanges: true,
|
||||
},
|
||||
'error'
|
||||
);
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Second argument must be a function or observer.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot({
|
||||
error: 'error',
|
||||
});
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: First argument must be a function, observer or options.'
|
||||
);
|
||||
(() => {
|
||||
docRef.onSnapshot();
|
||||
}).should.throw(
|
||||
'DocumentReference.onSnapshot failed: Called with invalid arguments.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('set()', () => {
|
||||
@@ -464,6 +580,25 @@ function documentReferenceTests({ describe, it, context, firebase }) {
|
||||
doc.data().nested.firstname.should.equal('First Name');
|
||||
doc.data().nested.lastname.should.equal('Last Name');
|
||||
}));
|
||||
|
||||
it('errors when invalid parameters supplied', async () => {
|
||||
const docRef = firebase.native.firestore().doc('document-tests/doc1');
|
||||
(() => {
|
||||
docRef.update('error');
|
||||
}).should.throw(
|
||||
'DocumentReference.update failed: If using a single argument, it must be an object.'
|
||||
);
|
||||
(() => {
|
||||
docRef.update('error1', 'error2', 'error3');
|
||||
}).should.throw(
|
||||
'DocumentReference.update failed: Must have either a single object argument, or equal numbers of key/value pairs.'
|
||||
);
|
||||
(() => {
|
||||
docRef.update(0, 'error');
|
||||
}).should.throw(
|
||||
'DocumentReference.update failed: Argument at index 0 must be a string or FieldPath'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('types', () => {
|
||||
|
||||
@@ -2,6 +2,13 @@ import should from 'should';
|
||||
|
||||
function fieldPathTests({ describe, it, context, firebase }) {
|
||||
describe('FieldPath', () => {
|
||||
context('documentId', () => {
|
||||
it('should be a FieldPath', () => {
|
||||
const documentId = firebase.native.firestore.FieldPath.documentId();
|
||||
documentId.should.be.instanceof(firebase.native.firestore.FieldPath);
|
||||
});
|
||||
});
|
||||
|
||||
context('DocumentSnapshot.get()', () => {
|
||||
it('should get the correct values', () =>
|
||||
firebase.native
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import should from 'should';
|
||||
|
||||
function firestoreTests({ describe, it, context, firebase }) {
|
||||
function firestoreTests({ describe, it, context, fcontext, firebase }) {
|
||||
describe('firestore()', () => {
|
||||
context('collection()', () => {
|
||||
it('should create CollectionReference with the right id', () =>
|
||||
@@ -11,6 +11,14 @@ function firestoreTests({ describe, it, context, firebase }) {
|
||||
should.equal(collectionRef.id, 'collection2');
|
||||
resolve();
|
||||
}));
|
||||
|
||||
it('should error if invalid collection path supplied', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().collection('collection1/doc1');
|
||||
}).should.throw(
|
||||
'Argument "collectionPath" must point to a collection.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('doc()', () => {
|
||||
@@ -22,6 +30,12 @@ function firestoreTests({ describe, it, context, firebase }) {
|
||||
should.equal(docRef.path, 'collection1/doc1/collection2/doc2');
|
||||
resolve();
|
||||
}));
|
||||
|
||||
it('should error if invalid document path supplied', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().doc('collection1');
|
||||
}).should.throw('Argument "documentPath" must point to a document.');
|
||||
});
|
||||
});
|
||||
|
||||
context('batch()', () => {
|
||||
@@ -90,6 +104,148 @@ function firestoreTests({ describe, it, context, firebase }) {
|
||||
sfDoc.data().nested.lastname.should.equal('Last Name');
|
||||
});
|
||||
});
|
||||
|
||||
it('errors when invalid parameters supplied', async () => {
|
||||
const ref = firebase.native.firestore().doc('collection/doc');
|
||||
const batch = firebase.native.firestore().batch();
|
||||
(() => {
|
||||
batch.update(ref, 'error');
|
||||
}).should.throw(
|
||||
'WriteBatch.update failed: If using two arguments, the second must be an object.'
|
||||
);
|
||||
(() => {
|
||||
batch.update(ref, 'error1', 'error2', 'error3');
|
||||
}).should.throw(
|
||||
'WriteBatch.update failed: Must have a document reference, followed by either a single object argument, or equal numbers of key/value pairs.'
|
||||
);
|
||||
(() => {
|
||||
batch.update(ref, 0, 'error');
|
||||
}).should.throw(
|
||||
'WriteBatch.update failed: Argument at index 0 must be a string or FieldPath'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('disableNetwork()', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().disableNetwork();
|
||||
}).should.throw(
|
||||
'firebase.firestore().disableNetwork() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('enableNetwork()', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().enableNetwork();
|
||||
}).should.throw(
|
||||
'firebase.firestore().enableNetwork() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('enablePersistence()', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().enablePersistence();
|
||||
}).should.throw(
|
||||
'Persistence is enabled by default on the Firestore SDKs'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('setLogLevel()', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().setLogLevel();
|
||||
}).should.throw(
|
||||
'firebase.firestore().setLogLevel() is unsupported by the native Firebase SDKs.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('settings()', () => {
|
||||
it('should throw an unsupported error', () => {
|
||||
(() => {
|
||||
firebase.native.firestore().settings();
|
||||
}).should.throw('firebase.firestore().settings() coming soon');
|
||||
});
|
||||
});
|
||||
|
||||
context('runTransaction()', () => {
|
||||
it('should set, update and delete transactionally and allow a return value', async () => {
|
||||
let deleteMe = false;
|
||||
const firestore = firebase.native.firestore();
|
||||
|
||||
const docRef = firestore
|
||||
.collection('transactions')
|
||||
.doc(Date.now().toString());
|
||||
|
||||
const updateFunction = async transaction => {
|
||||
const doc = await transaction.get(docRef);
|
||||
if (doc.exists && deleteMe) {
|
||||
transaction.delete(docRef);
|
||||
return 'bye';
|
||||
}
|
||||
|
||||
if (!doc.exists) {
|
||||
transaction.set(docRef, { value: 1 });
|
||||
return 1;
|
||||
}
|
||||
|
||||
const newValue = doc.data().value + 1;
|
||||
|
||||
if (newValue > 2) {
|
||||
return Promise.reject(
|
||||
new Error('Value should not be greater than 2!')
|
||||
);
|
||||
}
|
||||
|
||||
transaction.update(docRef, {
|
||||
value: newValue,
|
||||
somethingElse: 'update',
|
||||
});
|
||||
|
||||
return newValue;
|
||||
};
|
||||
|
||||
// set tests
|
||||
const val1 = await firestore.runTransaction(updateFunction);
|
||||
should.equal(val1, 1);
|
||||
const doc1 = await docRef.get();
|
||||
doc1.data().value.should.equal(1);
|
||||
should.equal(doc1.data().somethingElse, undefined);
|
||||
|
||||
// update
|
||||
const val2 = await firestore.runTransaction(updateFunction);
|
||||
should.equal(val2, 2);
|
||||
const doc2 = await docRef.get();
|
||||
doc2.data().value.should.equal(2);
|
||||
doc2.data().somethingElse.should.equal('update');
|
||||
|
||||
// rejecting / cancelling transaction
|
||||
let didReject = false;
|
||||
try {
|
||||
await firestore.runTransaction(updateFunction);
|
||||
} catch (e) {
|
||||
didReject = true;
|
||||
}
|
||||
should.equal(didReject, true);
|
||||
const doc3 = await docRef.get();
|
||||
doc3.data().value.should.equal(2);
|
||||
doc3.data().somethingElse.should.equal('update');
|
||||
|
||||
// delete
|
||||
deleteMe = true;
|
||||
const val4 = await firestore.runTransaction(updateFunction);
|
||||
should.equal(val4, 'bye');
|
||||
const doc4 = await docRef.get();
|
||||
should.equal(doc4.exists, false);
|
||||
|
||||
return Promise.resolve('Test Completed');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user