import React from 'react';
import {mount} from 'enzyme';
import Feature from 'app/components/acl/feature';
import ConfigStore from 'app/stores/configStore';
import HookStore from 'app/stores/hookStore';
describe('Feature', function() {
const organization = TestStubs.Organization({
features: ['org-foo', 'org-bar', 'bar'],
});
const project = TestStubs.Project({
features: ['project-foo', 'project-bar'],
});
const routerContext = TestStubs.routerContext([
{
organization,
project,
},
]);
describe('as render prop', function() {
const childrenMock = jest.fn().mockReturnValue(null);
beforeEach(function() {
childrenMock.mockClear();
});
it('has features', function() {
const features = ['org-foo', 'project-foo'];
mount({childrenMock}, routerContext);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: true,
features,
organization,
project,
});
});
it('has features when requireAll is false', function() {
const features = ['org-foo', 'project-foo', 'apple'];
mount(
{childrenMock}
,
routerContext
);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: true,
organization,
project,
features,
});
});
it('has no features', function() {
mount({childrenMock}, routerContext);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: false,
organization,
project,
features: ['org-baz'],
});
});
it('calls render function when no features', function() {
const noFeatureRenderer = jest.fn(() => null);
mount(
{childrenMock}
,
routerContext
);
expect(childrenMock).not.toHaveBeenCalled();
expect(noFeatureRenderer).toHaveBeenCalledWith({
hasFeature: false,
children: childrenMock,
organization,
project,
features: ['org-baz'],
});
});
it('can specify org from props', function() {
const customOrg = TestStubs.Organization({features: ['org-bazar']});
mount(
{childrenMock}
,
routerContext
);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: true,
organization: customOrg,
project,
features: ['org-bazar'],
});
});
it('can specify project from props', function() {
const customProject = TestStubs.Project({features: ['project-baz']});
mount(
{childrenMock}
,
routerContext
);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: true,
organization,
project: customProject,
features: ['project-baz'],
});
});
it('handles no org/project', function() {
const features = ['org-foo', 'project-foo'];
mount(
{childrenMock}
,
routerContext
);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: false,
organization: null,
project: null,
features,
});
});
it('handles features prefixed with org/project', function() {
mount(
{childrenMock},
routerContext
);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: true,
organization,
project,
features: ['organizations:org-bar'],
});
mount({childrenMock}, routerContext);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: false,
organization,
project,
features: ['projects:bar'],
});
});
it('checks ConfigStore.config.features (e.g. `organizations:create`)', function() {
ConfigStore.config = {
features: new Set(['organizations:create']),
};
mount(
{childrenMock},
routerContext
);
expect(childrenMock).toHaveBeenCalledWith({
hasFeature: true,
organization,
project,
features: ['organizations:create'],
});
});
});
describe('no children', function() {
it('should display renderDisabled with no feature', function() {
const wrapper = mount(
disabled} />,
routerContext
);
expect(wrapper.find('Feature span').text()).toBe('disabled');
});
it('should display be empty when on', function() {
const wrapper = mount(
disabled} />,
routerContext
);
expect(wrapper.find('Feature').text()).toBe('');
});
});
describe('as React node', function() {
it('has features', function() {
const wrapper = mount(
The Child
,
routerContext
);
expect(wrapper.find('Feature div').text()).toBe('The Child');
});
it('has no features', function() {
const wrapper = mount(
The Child
,
routerContext
);
expect(wrapper.find('Feature div')).toHaveLength(0);
});
it('renders a default disabled component', function() {
const wrapper = mount(
The Child
,
routerContext
);
expect(wrapper.exists('ComingSoon')).toBe(true);
expect(wrapper.exists('Feature div[children="The Child"]')).not.toBe(true);
});
it('calls renderDisabled function when no features', function() {
const noFeatureRenderer = jest.fn(() => null);
const children = The Child
;
const wrapper = mount(
{children}
,
routerContext
);
expect(wrapper.find('Feature div')).toHaveLength(0);
expect(noFeatureRenderer).toHaveBeenCalledWith({
hasFeature: false,
children,
organization,
project,
features: ['org-baz'],
});
});
});
describe('using HookStore for renderDisabled', function() {
let hookFn;
beforeEach(function() {
hookFn = jest.fn(() => null);
HookStore.hooks['feature-disabled:org-baz'] = [hookFn];
HookStore.hooks['feature-disabled:test-hook'] = [hookFn];
});
afterEach(function() {
delete HookStore.hooks['feature-disabled:org-baz'];
});
it('uses hookName if provided', function() {
const children = The Child
;
const wrapper = mount(
{children}
,
routerContext
);
expect(wrapper.find('Feature div')).toHaveLength(0);
expect(hookFn).toHaveBeenCalledWith({
hasFeature: false,
children,
organization,
project,
features: ['org-bazar'],
});
});
});
});