-
Notifications
You must be signed in to change notification settings - Fork 938
Migrate testing to rules-unit-testing #3378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
b336c8b
Migrate testing to rules-unit-testing
samtstern ff83ad6
Remove bad dep
samtstern 543fbb3
Merge branch 'master' into ss-fork-testing
samtstern 60381b3
Fix dev dependency
samtstern 318ecca
Fix how env is checked
samtstern 6b85198
var name
samtstern 98c993f
Merge remote-tracking branch 'origin/master' into ss-fork-testing
samtstern a7351d8
Deps
samtstern f4864f0
Update Firestore dep
samtstern d1ac304
Fix yarn.lock
samtstern ab2352b
Make tests pass
samtstern b431203
Merge remote-tracking branch 'origin/master' into ss-fork-testing
samtstern 8f54ed5
Add changeset
samtstern 3e2b499
Update versions and changeset
samtstern 2b92d40
Merge remote-tracking branch 'origin/master' into ss-fork-testing
samtstern f9d9898
Merge remote-tracking branch 'origin/master' into ss-fork-testing
samtstern c5b7268
Restore testing package (#3556)
samtstern d9bdde6
Update changeset ignore config
samtstern 9ee4bf9
Revert some changes
samtstern 23fc04a
Revert some changes
samtstern be695ee
No changelog
samtstern 186908f
Merge branch 'master' into ss-fork-testing
samtstern 9993f0d
Update package.json
samtstern cb12261
No port conflict
samtstern 3b0c125
Merge remote-tracking branch 'origin/master' into ss-fork-testing
samtstern File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions
4
packages/testing/README.md → packages/rules-unit-testing/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,9 @@ | ||
# @firebase/testing | ||
# @firebase/rules-unit-testing | ||
|
||
A set of utilities useful for testing Security Rules with the Realtime Database or Cloud Firestore | ||
emulators. | ||
|
||
See: | ||
|
||
* [Test your Cloud Firestore Security Rules](https://firebase.google.com/docs/firestore/security/test-rules-emulator) | ||
* [Testing Security Rules with the Realtime Database Emulator](https://firebase.google.com/docs/database/security/test-rules-emulator) | ||
* [Testing Security Rules with the Realtime Database Emulator](https://firebase.google.com/docs/database/security/test-rules-emulator) |
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "@firebase/testing", | ||
"version": "0.20.6", | ||
"name": "@firebase/rules-unit-testing", | ||
"version": "0.30.0", | ||
samtstern marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"description": "", | ||
"author": "Firebase <[email protected]> (https://firebase.google.com/)", | ||
"main": "dist/index.cjs.js", | ||
|
@@ -10,7 +10,7 @@ | |
"files": ["dist"], | ||
"scripts": { | ||
"build": "rollup -c", | ||
"build:deps": "lerna run --scope @firebase/testing --include-dependencies build", | ||
"build:deps": "lerna run --scope @firebase/rules-unit-testing --include-dependencies build", | ||
"dev": "rollup -c -w", | ||
"test:nyc": "TS_NODE_CACHE=NO TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter lcovonly -- mocha 'test/{,!(browser)/**/}*.test.ts' --config ../../config/mocharc.node.js", | ||
"test": "firebase emulators:exec 'yarn test:nyc'", | ||
|
@@ -26,12 +26,16 @@ | |
}, | ||
"devDependencies": { | ||
"@types/request": "2.48.5", | ||
"firebase-tools": "8.5.0", | ||
"firebase-tools": "^8.5.0", | ||
"firebase-admin": "^9.0.0", | ||
"rollup": "2.21.0", | ||
"rollup-plugin-typescript2": "0.27.1" | ||
}, | ||
"peerDependencies": { | ||
"firebase-admin": "^9.0.0" | ||
}, | ||
"repository": { | ||
"directory": "packages/testing", | ||
"directory": "packages/rules-unit-testing", | ||
"type": "git", | ||
"url": "https://github.com/firebase/firebase-js-sdk.git" | ||
}, | ||
|
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,28 +26,21 @@ import { Component, ComponentType } from '@firebase/component'; | |
export { database, firestore } from 'firebase'; | ||
|
||
/** If this environment variable is set, use it for the database emulator's address. */ | ||
const DATABASE_ADDRESS_ENV: string = 'FIREBASE_DATABASE_EMULATOR_ADDRESS'; | ||
const DATABASE_ADDRESS_ENV: string = 'FIREBASE_DATABASE_EMULATOR_HOST'; | ||
/** The default address for the local database emulator. */ | ||
const DATABASE_ADDRESS_DEFAULT: string = 'localhost:9000'; | ||
/** The actual address for the database emulator */ | ||
const DATABASE_ADDRESS: string = | ||
process.env[DATABASE_ADDRESS_ENV] || DATABASE_ADDRESS_DEFAULT; | ||
|
||
/** If any of environment variable is set, use it for the Firestore emulator. */ | ||
const FIRESTORE_ADDRESS_ENVS: string[] = [ | ||
'FIRESTORE_EMULATOR_HOST', | ||
'FIREBASE_FIRESTORE_EMULATOR_ADDRESS' | ||
]; | ||
const FIRESTORE_ADDRESS_ENV: string = 'FIRESTORE_EMULATOR_HOST'; | ||
/** The default address for the local Firestore emulator. */ | ||
const FIRESTORE_ADDRESS_DEFAULT: string = 'localhost:8080'; | ||
|
||
/** The actual address for the database emulator */ | ||
let _databaseHost: string | undefined = undefined; | ||
|
||
/** The actual address for the Firestore emulator */ | ||
const FIRESTORE_ADDRESS: string = FIRESTORE_ADDRESS_ENVS.reduce( | ||
(addr, name) => process.env[name] || addr, | ||
FIRESTORE_ADDRESS_DEFAULT | ||
); | ||
let _firestoreHost: string | undefined = undefined; | ||
|
||
/** Passing this in tells the emulator to treat you as an admin. */ | ||
const ADMIN_TOKEN = 'owner'; | ||
/** Create an unsecured JWT for the given auth payload. See https://tools.ietf.org/html/rfc7519#section-6. */ | ||
function createUnsecuredJwt(auth: object): string { | ||
// Unsecured JWTs use "none" as the algorithm. | ||
|
@@ -95,23 +88,84 @@ export type AdminAppOptions = { | |
}; | ||
/** Construct an App authenticated as an admin user. */ | ||
export function initializeAdminApp(options: AdminAppOptions): firebase.app.App { | ||
return initializeApp(ADMIN_TOKEN, options.databaseName, options.projectId); | ||
const admin = require('firebase-admin'); | ||
|
||
const app = admin.initializeApp( | ||
getAppOptions(options.databaseName, options.projectId), | ||
getRandomAppName() | ||
); | ||
|
||
if (options.projectId) { | ||
app.firestore().settings({ | ||
host: getFirestoreHost(), | ||
ssl: false | ||
}); | ||
} | ||
|
||
return app; | ||
} | ||
|
||
function initializeApp( | ||
accessToken?: string, | ||
function getDatabaseHost() { | ||
if (!_databaseHost) { | ||
const fromEnv = process.env[DATABASE_ADDRESS_ENV]; | ||
if (fromEnv) { | ||
_databaseHost = fromEnv; | ||
} else { | ||
console.warn( | ||
`Warning: ${DATABASE_ADDRESS_ENV} not set, using default value ${DATABASE_ADDRESS_DEFAULT}` | ||
); | ||
_databaseHost = DATABASE_ADDRESS_DEFAULT; | ||
} | ||
} | ||
|
||
return _databaseHost; | ||
} | ||
|
||
function getFirestoreHost() { | ||
if (!_firestoreHost) { | ||
const fromEnv = process.env[FIRESTORE_ADDRESS_ENV]; | ||
if (fromEnv) { | ||
_firestoreHost = fromEnv; | ||
} else { | ||
console.warn( | ||
`Warning: ${FIRESTORE_ADDRESS_ENV} not set, using default value ${FIRESTORE_ADDRESS_DEFAULT}` | ||
); | ||
_firestoreHost = FIRESTORE_ADDRESS_DEFAULT; | ||
} | ||
} | ||
|
||
return _firestoreHost; | ||
} | ||
|
||
function getRandomAppName(): string { | ||
return 'app-' + new Date().getTime() + '-' + Math.random(); | ||
} | ||
|
||
function getAppOptions( | ||
databaseName?: string, | ||
projectId?: string | ||
): firebase.app.App { | ||
): { [key: string]: string } { | ||
let appOptions: { [key: string]: string } = {}; | ||
|
||
if (databaseName) { | ||
appOptions['databaseURL'] = `http://${DATABASE_ADDRESS}?ns=${databaseName}`; | ||
appOptions[ | ||
'databaseURL' | ||
] = `http://${getDatabaseHost()}?ns=${databaseName}`; | ||
} | ||
if (projectId) { | ||
appOptions['projectId'] = projectId; | ||
} | ||
const appName = 'app-' + new Date().getTime() + '-' + Math.random(); | ||
let app = firebase.initializeApp(appOptions, appName); | ||
|
||
return appOptions; | ||
} | ||
|
||
function initializeApp( | ||
accessToken?: string, | ||
databaseName?: string, | ||
projectId?: string | ||
): firebase.app.App { | ||
const appOptions = getAppOptions(databaseName, projectId); | ||
const app = firebase.initializeApp(appOptions, getRandomAppName()); | ||
if (accessToken) { | ||
const mockAuthComponent = new Component( | ||
'auth-internal', | ||
|
@@ -141,7 +195,7 @@ function initializeApp( | |
} | ||
if (projectId) { | ||
app.firestore().settings({ | ||
host: FIRESTORE_ADDRESS, | ||
host: getFirestoreHost(), | ||
ssl: false | ||
}); | ||
} | ||
|
@@ -171,7 +225,9 @@ export function loadDatabaseRules( | |
return new Promise((resolve, reject) => { | ||
request.put( | ||
{ | ||
uri: `http://${DATABASE_ADDRESS}/.settings/rules.json?ns=${options.databaseName}`, | ||
uri: `http://${getDatabaseHost()}/.settings/rules.json?ns=${ | ||
options.databaseName | ||
}`, | ||
headers: { Authorization: 'Bearer owner' }, | ||
body: options.rules | ||
}, | ||
|
@@ -206,7 +262,9 @@ export function loadFirestoreRules( | |
return new Promise((resolve, reject) => { | ||
request.put( | ||
{ | ||
uri: `http://${FIRESTORE_ADDRESS}/emulator/v1/projects/${options.projectId}:securityRules`, | ||
uri: `http://${getFirestoreHost()}/emulator/v1/projects/${ | ||
options.projectId | ||
}:securityRules`, | ||
body: JSON.stringify({ | ||
rules: { | ||
files: [{ content: options.rules }] | ||
|
@@ -240,7 +298,9 @@ export function clearFirestoreData( | |
return new Promise((resolve, reject) => { | ||
request.delete( | ||
{ | ||
uri: `http://${FIRESTORE_ADDRESS}/emulator/v1/projects/${options.projectId}/databases/(default)/documents`, | ||
uri: `http://${getFirestoreHost()}/emulator/v1/projects/${ | ||
options.projectId | ||
}/databases/(default)/documents`, | ||
body: JSON.stringify({ | ||
database: `projects/${options.projectId}/databases/(default)` | ||
}) | ||
|
@@ -261,9 +321,23 @@ export function clearFirestoreData( | |
|
||
export function assertFails(pr: Promise<any>): any { | ||
return pr.then( | ||
v => | ||
Promise.reject(new Error('Expected request to fail, but it succeeded.')), | ||
err => err | ||
(v: any) => { | ||
return Promise.reject( | ||
new Error('Expected request to fail, but it succeeded.') | ||
); | ||
}, | ||
(err: any) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We now make sure the error is a |
||
const isPermissionDenied = | ||
err && err.message && err.message.indexOf('PERMISSION_DENIED') >= 0; | ||
if (!isPermissionDenied) { | ||
return Promise.reject( | ||
new Error( | ||
`Expected PERMISSION_DENIED but got unexpected error: ${err}` | ||
) | ||
); | ||
} | ||
return err; | ||
} | ||
); | ||
} | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.