UNPKG

targaryen

Version:

Test Firebase security rules without connecting to Firebase.

226 lines (154 loc) 7.07 kB
## Standalone Install Targaryen locally and run it like so: ```bash $ npm install -g targaryen ... $ targaryen path/to/rules.json path/to/tests.json 0 failures in 20 tests ``` [See the docs](https://github.com/goldibex/targaryen/blob/master/docs/targaryen) or [take a look at Targaryen's own integration tests](https://github.com/goldibex/targaryen/blob/master/test/integration/tests.json) to learn more. targaryen exits with a non-zero error code if the tests failed, or zero if they passed. ## With a test framework To use either Jasmine or Chai, you'll need to get the Targaryen API. This is as simple as ```bash npm install --save-dev targaryen@3 ``` followed by ```js var targaryen = require('targaryen'); ``` Before your tests start, you need to call two different methods: `targaryen.setFirebaseData(data)`: set the database state for the test. `data` is a plain old Javascript object containing whatever data you want to be accessible via the `root` and `data` objects in the security rules. You can either use the data format of Firebase's `exportVal` (i.e., with ".value" and ".priority" keys) or just a plain Javascript object. The plain object will be converted to the Firebase format. `targaryen.setFirebaseRules(rules)`: set the database rules for the test. `rules` is a plain old Javascript object with the contents `rules.json`, so you can just say `targaryen.setFirebaseRules(require('./rules.json'))` and be on your way. ### Chai Docs are at [docs/chai](https://github.com/goldibex/targaryen/blob/master/docs/chai). A quick example: ```js var chai = require('chai'), expect = chai.expect, targaryen = require('targaryen'); chai.use(targaryen.chai); describe('A set of rules and data', function() { before(function() { // when you call setFirebaseData, you can either use the data format // of `exportVal` (i.e., with ".value" and ".priority" keys) or just a plain // Javascript object. The plain object will be converted to the Firebase format. targaryen.setFirebaseData({ users: { 'password:500f6e96-92c6-4f60-ad5d-207253aee4d3': { name: { '.value': 'Rickard Stark', '.priority': 2 } }, 'password:3403291b-fdc9-4995-9a54-9656241c835d': { name: 'Mad Aerys', king: true } } }); // any logged-in user can read a user object, but only the king can write them! targaryen.setFirebaseRules({ rules: { users: { '.read': 'auth !== null', '.write': "root.child('users').child(auth.uid).child('king').val() === true" } } }); }); it('can be tested', function() { expect(targaryen.users.unauthenticated) .cannot.read.path('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3'); expect(targaryen.users.password) .can.read.path('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3'); expect(targaryen.users.password) .cannot.write(true).to.path('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent'); expect({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d' }) .can.write(true).to.path('users/password:3403291b-fdc9-4995-9a54-9656241c835d/on-fire'); expect(targaryen.users.password) .cannot.patch('/', { 'users/password:3403291b-fdc9-4995-9a54-9656241c835d/on-fire': null, 'users/password:3403291b-fdc9-4995-9a54-9656241c835d/innocent': true }); expect({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d' }) .can.patch('/', { 'users/password:3403291b-fdc9-4995-9a54-9656241c835d/on-fire': true, 'users/password:3403291b-fdc9-4995-9a54-9656241c835d/innocent': null }); }); }); ``` ### Jasmine Docs are at [docs/jasmine](https://github.com/goldibex/targaryen/blob/master/docs/jasmine). A quick example: ```js var targaryen = require('targaryen'); // see Chai example above for format targaryen.setFirebaseData(...); targaryen.setFirebaseRules(...); describe('A set of rules and data', function() { beforeEach(function() { jasmine.addMatchers(targaryen.jasmine.matchers); }); it('can be tested', function() { expect(targaryen.users.unauthenticated) .cannotRead('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3'); expect(targaryen.users.password) .canRead('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3'); expect(targaryen.users.password) .cannotWrite('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent', true); expect({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d'}) .canWrite('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/onFire', true); expect({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d'}) .canPatch('/', { 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/onFire': true, 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent': null }); expect({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d'}) .cannotPatch('/', { 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/onFire': null, 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent': true }); }); }); ``` ### Jest Docs are at [docs/jest](https://github.com/goldibex/targaryen/blob/master/docs/jest). A quick example: ```js const targaryen = require('targaryen/plugins/jest'); // see Chai example above for format const rules = targaryen.json.loadSync(RULES_PATH); const data = require(DATA_PATH); expect.extend({ toAllowRead: targaryen.toAllowRead, toAllowUpdate: targaryen.toAllowUpdate, toAllowWrite: targaryen.toAllowWrite }); describe('A set of rules and data', function() { const database = targaryen.getDatabase(rules, data); it('should allow authenticated user to read all data', function() { expect(database.as({uid: 'foo'})).toAllowRead('/'); expect(database.as(null)).not.toAllowRead('/'); }) it('can be tested', function() { expect(database.as(targaryen.users.unauthenticated)) .not.toAllowRead('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3'); expect(database.as(targaryen.users.password)) .toAllowRead('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3'); expect(database.as(targaryen.users.password)) .not.toAllowWrite('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent', true); expect(database.as({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d'})) .toAllowWrite('users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/onFire', true); expect(database.as({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d'})) .toAllowUpdate('/', { 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/onFire': true, 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent': null }); expect(database.as({ uid: 'password:3403291b-fdc9-4995-9a54-9656241c835d'})) .not.toAllowUpdate('/', { 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/onFire': null, 'users/password:500f6e96-92c6-4f60-ad5d-207253aee4d3/innocent': true }); }); }); ```