Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into fix-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kkoscielniak committed Sep 25, 2018
2 parents 5f1194b + c22cab6 commit 892db8d
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 48 deletions.
21 changes: 20 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ jobs:
- run:
name: Compile
command: npm run build
publish_package:
docker:
- image: circleci/node:8.11
steps:
- checkout
- run:
name: npm publish
command: |
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc
npm publish
workflows:
version: 2
build_and_test:
Expand All @@ -85,4 +95,13 @@ workflows:
- build
- compile:
requires:
- build
- build
- publish_package:
requires:
- test
- lint
- compile
filters:
branches:
only:
- master
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ React-permissible is copyright © 2014-2017 [Brainhub](https://brainhub.eu/) It

`react-permissible` is maintained by [@kkoscielniak](https://github.com/kkoscielniak) & [@adam-golab](https://github.com/adam-golab) & [@Lukasz-pluszczewski](https://github.com/Lukasz-pluszczewski/) and the Brainhub development team. It is funded by Brainhub and the names and logos for Brainhub are trademarks of Brainhub Sp. z o.o.. You can check other open-source projects supported/developed by our teammates [here](https://brainhub.eu/?utm_source=github).

[![Brainhub](https://avatars0.githubusercontent.com/u/20307185?s=200&v=4)](https://brainhub.eu/?utm_source=github)
[![Brainhub](https://brainhub.eu/brainhub.svg)](https://brainhub.eu/?utm_source=github)

We love open-source JavaScript software! See our other projects or hire us to build your next web, desktop and mobile application with JavaScript.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@brainhubeu/react-permissible",
"version": "1.0.1",
"version": "1.6.0",
"description": "Permission management component for React",
"engines": {
"npm": ">=4"
Expand All @@ -18,7 +18,8 @@
"author": "Krystian Kościelniak",
"license": "MIT",
"dependencies": {
"is-subset": "^0.1.1"
"lodash.difference": "^4.5.0",
"lodash.intersection": "^4.4.0"
},
"devDependencies": {
"autoprefixer": "^7.1.1",
Expand Down Expand Up @@ -60,7 +61,6 @@
"istanbul": "^0.4.5",
"jsdom": "^11.2.0",
"json-loader": "^0.5.4",
"lodash": "^4.17.4",
"mocha": "^3.4.2",
"node-sass": "^4.5.3",
"postcss-loader": "^2.0.6",
Expand Down
6 changes: 3 additions & 3 deletions src/components/permissible.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import intersection from 'lodash/intersection';
import isSubset from 'is-subset';
import intersection from 'lodash.intersection';
import difference from 'lodash.difference';

export function Permissible(
RestrictedComponent,
Expand All @@ -12,7 +12,7 @@ export function Permissible(
) {
const permissionsStatus = oneperm
? intersection(userPermissions, requiredPermissions).length
: isSubset(userPermissions, requiredPermissions);
: difference(requiredPermissions, userPermissions).length === 0;

class PermissibleHOC extends Component {
static propTypes = {
Expand Down
15 changes: 10 additions & 5 deletions src/components/permissibleRender.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
import intersection from 'lodash/intersection';
import isSubset from 'is-subset';
import intersection from 'lodash.intersection';
import difference from 'lodash.difference';

export class PermissibleRender extends Component {
static propTypes = {
Expand All @@ -18,14 +18,19 @@ export class PermissibleRender extends Component {
if (oneperm) {
return intersection(userPermissions, requiredPermissions).length;
}
return isSubset(userPermissions, requiredPermissions);

return difference(requiredPermissions, userPermissions).length === 0;
}

render() {
const { renderOtherwise } = this.props;
const { children, userPermissions, requiredPermissions, renderOtherwise } = this.props;

if (!children || !userPermissions || !requiredPermissions) {
return null;
}

if (this.checkPermissions()) {
return this.props.children;
return children;
} else if (renderOtherwise) {
return renderOtherwise;
}
Expand Down
38 changes: 38 additions & 0 deletions test/permissible.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,44 @@ describe('Permissible HOC', () => {
done(err);
});

it('doesn\'t run a callback function if `requiredPermissions` and `userPermissions` are both empty', done => {
let err = null;

const AccessibleRoute = Permissible(
() => <AccessedComponent />,
[],
[],
() => {
err = new Error('Callback function called.');
}
);

shallow(
<AccessibleRoute />
);

done(err);
});

it('doesn\'t run a callback function if only `requiredPermissions` are empty', done => {
let err = null;

const AccessibleRoute = Permissible(
() => <AccessedComponent />,
['SOME_PERMISSION'],
[],
() => {
err = new Error('Callback function called.');
}
);

shallow(
<AccessibleRoute />
);

done(err);
});

it('runs a callback function if the permissions don\'t match', done => {
const AccessibleRoute = Permissible(
() => <AccessedComponent />,
Expand Down
89 changes: 54 additions & 35 deletions test/permissibleRender.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { JSDOM } from 'jsdom';

import { PermissibleRender } from '../src/components/permissibleRender';

const should = chai.should();

const { document } = (new JSDOM('')).window;
global.document = document;
global.window = document.defaultView;
Expand All @@ -14,43 +16,36 @@ chai.use(chaiEnzyme());
chai.should();

describe('PermissibleRender', () => {
let props;

const ChildComponent = () => (
<div>
{'Child component'}
Child component
</div>
);

const NotAllowedComponent = () => (
<div>
{'Not allowed component'}
Not allowed component
</div>
);

// clear props before each test
beforeEach(() => {
props = {
userPermissions: [],
requiredPermimissions: [],
it('doesn\'t render a <ChildComponent /> if `userPermissions` prop is not set', () => {
const props = {
requiredPermissions: [],
};
});

it('doesn\'t render a <div /> if there are no props', () => {
const mountedComponent = mount(
<PermissibleRender {...props}>
<ChildComponent />
</PermissibleRender>
);

const searchedElement = mountedComponent.find('div');
const searchedElement = mountedComponent.find('ChildComponent');
searchedElement.length.should.be.equal(0);
});

it('doesn\'t render a <div /> if there is a permission mismatch', () => {
props = {
userPermissions: ['REQUIRED_PERMISSION'],
requiredPermissions: ['ANOTHER_PERMISSION'],
it('doesn\'t render a <ChildComponent /> if `requiredPermissions` prop is not set', () => {
const props = {
userPermissions: [],
};

const mountedComponent = mount(
Expand All @@ -59,14 +54,28 @@ describe('PermissibleRender', () => {
</PermissibleRender>
);

const searchedElement = mountedComponent.find('div');
const searchedElement = mountedComponent.find('ChildComponent');
searchedElement.length.should.be.equal(0);
});

it('always renders a <div /> if the user has required permission', () => {
props = {
userPermissions: ['REQUIRED_PERMISSION'],
requiredPermissions: ['REQUIRED_PERMISSION'],
it('renders nothing if `children` prop is not set', () => {
const props = {
userPermissions: [],
};

const mountedComponent = mount(
<PermissibleRender {...props}>

</PermissibleRender>
);

should.not.exist(mountedComponent.find('PermissibleRender').html());
});

it('renders a <ChildComponent /> if user permissions and required permissions are both empty', () => {
const props = {
userPermissions: [],
requiredPermissions: [],
};

const mountedComponent = mount(
Expand All @@ -75,26 +84,32 @@ describe('PermissibleRender', () => {
</PermissibleRender>
);

const searchedElement = mountedComponent.find('div');
searchedElement.length.should.be.greaterThan(0);
const searchedElement = mountedComponent.find('ChildComponent');
searchedElement.length.should.be.equal(1);
});

it('doesn\'t render a ChildComponent if there are no props', () => {
it('renders a <ChildComponent /> if only required permissions are empty', () => {
const props = {
userPermissions: ['SOME_PERMISSION'],
requiredPermissions: [],
};

const mountedComponent = mount(
<PermissibleRender {...props}>
<ChildComponent />
</PermissibleRender>
);

const searchedElement = mountedComponent.find('ChildComponent');
searchedElement.length.should.be.equal(0);
searchedElement.length.should.be.equal(1);
});

it('doesn\'t render a ChildComponent if there is a permission mismatch', () => {
props = {
it('doesn\'t render a <ChildComponent /> if there is a permission mismatch', () => {
const props = {
userPermissions: ['REQUIRED_PERMISSION'],
requiredPermissions: ['ANOTHER_PERMISSION'],
};

const mountedComponent = mount(
<PermissibleRender {...props}>
<ChildComponent />
Expand All @@ -105,11 +120,12 @@ describe('PermissibleRender', () => {
searchedElement.length.should.be.equal(0);
});

it('always renders a ChildComponent if the user has required permission', () => {
props = {
it('renders a <ChildComponent /> if the user has required permission', () => {
const props = {
userPermissions: ['REQUIRED_PERMISSION'],
requiredPermissions: ['REQUIRED_PERMISSION'],
};

const mountedComponent = mount(
<PermissibleRender {...props}>
<ChildComponent />
Expand All @@ -120,12 +136,13 @@ describe('PermissibleRender', () => {
searchedElement.length.should.be.greaterThan(0);
});

it('renders a NotAllowedCOmponent if the user doesn\'t have required permissions and renderOtherwise is given', () => {
props = {
it('renders a <NotAllowedComponent /> if the user doesn\'t have required permissions and renderOtherwise is given', () => {
const props = {
userPermissions: ['REQUIRED_PERMISSION'],
requiredPermissions: ['NOT_REQUIRED_PERMISSION'],
renderOtherwise: <NotAllowedComponent />,
};

const mountedComponent = mount(
<PermissibleRender {...props}>
<NotAllowedComponent />
Expand All @@ -136,12 +153,13 @@ describe('PermissibleRender', () => {
searchedElement.length.should.be.greaterThan(0);
});

it('renders a component if the user has one of necessary conditions when `oneperm` prop is defined', () => {
props = {
it('renders a <ChildComponent /> if the user has one of necessary conditions when `oneperm` prop is defined', () => {
const props = {
userPermissions: ['ANOTHER_PERMISSION'],
requiredPermissions: ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'],
oneperm: true,
};

const mountedComponent = mount(
<PermissibleRender {...props}>
<ChildComponent />
Expand All @@ -152,12 +170,13 @@ describe('PermissibleRender', () => {
searchedElement.length.should.be.greaterThan(0);
});

it('doesn\'t render a component if the user hasn\'t all of necessary permissions when `oneperm` prop isn\'t defined', () => {
props = {
it('doesn\'t render a <ChildComponent /> if the user doesn\'t have all of necessary permissions when `oneperm` prop is explicitly set to false', () => {
const props = {
userPermissions: ['REQUIRED_PERMISSION'],
requiredPermissions: ['REQUIRED_PERMISSION', 'ANOTHER_PERMISSION'],
oneperm: false,
};

const mountedComponent = mount(
<PermissibleRender {...props}>
<ChildComponent />
Expand Down

0 comments on commit 892db8d

Please sign in to comment.