Skip to content

Commit

Permalink
fix(mongoose): mock query result on collection level
Browse files Browse the repository at this point in the history
Unmock `Query.prototype.exec` and mock collection methods instead.

Fixes #218
  • Loading branch information
stalniy committed Sep 14, 2019
1 parent 918108c commit 1e8c241
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 31 deletions.
14 changes: 14 additions & 0 deletions packages/casl-mongoose/spec/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"env": {
"jest": true
},
"globals": {
"expect": true,
"spy": true
},
"rules": {
"semi": ["error", "never"],
"no-use-before-define": "off",
"no-unused-expressions": "off"
}
}
8 changes: 4 additions & 4 deletions packages/casl-mongoose/spec/accessible_records.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AbilityBuilder, Ability } from '@casl/ability'
import { AbilityBuilder } from '@casl/ability'
import mongoose from 'mongoose'
import { accessibleRecordsPlugin, toMongoQuery } from '../src'

Expand Down Expand Up @@ -33,7 +33,7 @@ describe('Accessible Records Plugin', () => {

describe('`accessibleBy` method', () => {
beforeEach(() => {
ability = AbilityBuilder.define(can => {
ability = AbilityBuilder.define((can) => {
can('read', 'Post', { state: 'draft' })
can('update', 'Post', { state: 'published' })
})
Expand Down Expand Up @@ -77,7 +77,6 @@ describe('Accessible Records Plugin', () => {
let query

beforeEach(() => {
Post.Query.prototype.exec = spy(() => Promise.resolve('original `exec` method call'))
query = Post.find().accessibleBy(ability, 'notAllowedAction')
})

Expand Down Expand Up @@ -128,7 +127,8 @@ describe('Accessible Records Plugin', () => {
})

it('calls original `exec` for other cases', async () => {
await query.update({ $set: { state: 'draft' } }).exec()
Post.Query.prototype.exec = spy(() => Promise.resolve('original `exec` method call'))
await query.update({ $set: { state: 'draft' } })

expect(Post.Query.prototype.exec).to.have.been.called()
})
Expand Down
51 changes: 24 additions & 27 deletions packages/casl-mongoose/src/accessible_records.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
import { toMongoQuery } from './mongo';

const DENY_CONDITION_NAME = '__forbiddenByCasl__';

function returnQueryResult(original, returnValue, ...args) {
const [conditions, , callback] = args;

if (conditions[DENY_CONDITION_NAME]) {
return typeof callback === 'function'
? callback(null, returnValue)
: Promise.resolve(returnValue);
}

if (conditions.hasOwnProperty(DENY_CONDITION_NAME)) {
delete conditions[DENY_CONDITION_NAME];
}

return original.apply(this, args);
}

function emptyQuery(query) {
const originalExec = query.exec;

query.where({ __forbiddenByCasl__: 1 });
query.exec = function exec(operation, callback) {
const op = typeof operation === 'string' ? operation : this.op;
const cb = typeof operation === 'function' ? operation : callback;
let value;

if (op.indexOf('findOne') === 0) {
value = null;
} else if (op.indexOf('find') === 0) {
value = [];
} else if (op === 'count') {
value = 0;
} else {
return originalExec.call(this, operation, callback);
}

return Promise.resolve(value)
.then((v) => {
if (typeof cb === 'function') {
cb(null, v);
}

return v;
});
};
query.where({ [DENY_CONDITION_NAME]: 1 });
const collection = Object.create(query._collection) // eslint-disable-line
query._collection = collection // eslint-disable-line
collection.find = returnQueryResult.bind(collection, collection.find, []);
collection.findOne = returnQueryResult.bind(collection, collection.findOne, null);
collection.count = returnQueryResult.bind(collection, collection.count, 0);

return query;
}
Expand Down

0 comments on commit 1e8c241

Please sign in to comment.