Skip to content
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

introduce a buildComponent test helper #23

Merged
merged 1 commit into from
Oct 10, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"indent": [2, 2, {"SwitchCase": 1}],
"jsx-quotes": 2,
"key-spacing": 2,
"lines-around-comment": 2,
"lines-around-comment": 0,
"linebreak-style": 2,
"max-nested-callbacks": 2,
"new-cap": 2,
Expand Down
4 changes: 3 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ module.exports = function(grunt) {
src: 'coverage/lcov.json',
options: {
reports: {
lcovonly: 'coverage/lcov-remapped.info'
'lcovonly': 'coverage/lcov-remapped.info',
'text-summary': null,
'html': 'coverage/html'
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion dist/amd/anglue.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions dist/amd/utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/amd/utils.js.map

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ module.exports = function(config) {
dir: 'coverage/',
subdir: '.',
file: 'lcov.json'
}, {
type: 'text-summary'
}]
},

Expand Down
1 change: 1 addition & 0 deletions src/anglue.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './actions';
export * from './component';
export * from './store';
export * from './behaviors';
export * from './test-helpers';
63 changes: 13 additions & 50 deletions src/behaviors/paginatable-component.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/*eslint-env node, jasmine*//*global module, inject*/
/*eslint-env node, jasmine*//*global module*/
/*eslint-disable max-statements, max-params*/
import angular from 'angular';
import 'angular-mocks';
import {buildComponent} from 'anglue/anglue';

import {
Annotations,
Expand Down Expand Up @@ -144,8 +143,7 @@ describe('PaginatableComponent', () => {
};

@Component()
@PaginatableComponent()
class PaginatableTestComponent {
@PaginatableComponent() class PaginatableTestComponent {
paginatableActions = mockActions;
paginatableStore = mockStore;
}
Expand All @@ -155,8 +153,7 @@ describe('PaginatableComponent', () => {
entity: 'foo',
initialPage: 3,
initialLimit: 100
})
class PaginatableEntityConfiguredComponent {
}) class PaginatableEntityConfiguredComponent {
fooActions = mockActions;
fooStore = mockStore;
}
Expand All @@ -165,91 +162,57 @@ describe('PaginatableComponent', () => {
@PaginatableComponent({
actions: 'customActions',
store: 'customStore'
})
class PaginatableCustomConfiguredComponent {
}) class PaginatableCustomConfiguredComponent {
customActions = mockActions;
customStore = mockStore;
}

@Component()
@PaginatableComponent('foo')
class PaginatableStringConfiguredComponent {
@PaginatableComponent('foo') class PaginatableStringConfiguredComponent {
fooActions = mockActions;
fooStore = mockStore;
}

angular.module('paginatableComponents', [
PaginatableTestComponent.annotation.module.name,
PaginatableEntityConfiguredComponent.annotation.module.name,
PaginatableCustomConfiguredComponent.annotation.module.name,
PaginatableStringConfiguredComponent.annotation.module.name
]);

let $compile, $rootScope;
let autoConfiguredComponent;
let entityConfiguredComponent;
let customConfiguredComponent;
let stringConfiguredComponent;

beforeEach(module('paginatableComponents'));
beforeEach(inject((_$compile_, _$rootScope_) => {
$compile = _$compile_;
$rootScope = _$rootScope_;

autoConfiguredComponent = compileTemplate(
'<paginatable-test></paginatable-test>', $compile, $rootScope)
.controller('paginatableTest');
entityConfiguredComponent = compileTemplate(
'<paginatable-entity-configured></paginatable-entity-configured>', $compile, $rootScope)
.controller('paginatableEntityConfigured');
customConfiguredComponent = compileTemplate(
'<paginatable-custom-configured></paginatable-custom-configured>', $compile, $rootScope)
.controller('paginatableCustomConfigured');
stringConfiguredComponent = compileTemplate(
'<paginatable-string-configured></paginatable-string-configured>', $compile, $rootScope)
.controller('paginatableStringConfigured');
}));

it('should define the PaginatableComponent API on the component', () => {
const autoConfiguredComponent = buildComponent(PaginatableTestComponent);
[
'pagination'
].forEach(api => expect(autoConfiguredComponent[api]).toBeDefined());
});

it('should have an instance of PaginatableComponentBehavior as the behavior property', () => {
const autoConfiguredComponent = buildComponent(PaginatableTestComponent);
expect(autoConfiguredComponent.pagination).toEqual(jasmine.any(PaginatableComponentBehavior));
});

it('should use the first uppercased part of class name to determine the actions and store', () => {
const autoConfiguredComponent = buildComponent(PaginatableTestComponent);
expect(autoConfiguredComponent.pagination.actions).toEqual('paginatableActions');
expect(autoConfiguredComponent.pagination.store).toEqual('paginatableStore');
});

it('should be possible to pass the entity property as a string to determine actions and store', () => {
const stringConfiguredComponent = buildComponent(PaginatableStringConfiguredComponent);
expect(stringConfiguredComponent.pagination.actions).toEqual('fooActions');
expect(stringConfiguredComponent.pagination.store).toEqual('fooStore');
});

it('should be possible to configure an entity to determine the actions and store', () => {
const entityConfiguredComponent = buildComponent(PaginatableEntityConfiguredComponent);
expect(entityConfiguredComponent.pagination.actions).toEqual('fooActions');
expect(entityConfiguredComponent.pagination.store).toEqual('fooStore');
});

it('should be possible to pass the actions and store in the configuration', () => {
const customConfiguredComponent = buildComponent(PaginatableCustomConfiguredComponent);
expect(customConfiguredComponent.pagination.actions).toEqual('customActions');
expect(customConfiguredComponent.pagination.store).toEqual('customStore');
});

it('should be possible to configure initial page and limit', () => {
const entityConfiguredComponent = buildComponent(PaginatableEntityConfiguredComponent);
expect(entityConfiguredComponent.pagination.config.initialPage).toEqual(3);
expect(entityConfiguredComponent.pagination.config.initialLimit).toEqual(100);
});
});
});

function compileTemplate(template, $compile, $rootScope) {
const el = angular.element(template.trim());
$compile(el)($rootScope.$new());
$rootScope.$digest();
return el;
}
38 changes: 38 additions & 0 deletions src/test-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import angular from 'angular';
import 'angular-mocks';
import {camelCaseToDashes, dashesToCamelCase} from './utils';

let counter = 0;

export function buildComponent(ComponentClass) {
if (!ComponentClass.annotation || !ComponentClass.annotation.module || !ComponentClass.annotation.module.name) {
throw new Error(`ComponentClass is not annotated: ${ComponentClass.name}`);
}

const tagName = camelCaseToDashes(ComponentClass.annotation.name).toLowerCase();
const template = `<${tagName}></${tagName}>`;
const elProperty = dashesToCamelCase(tagName);

counter += 1;
const componentName = `TestedComponents${counter}`;

angular.module(componentName, [ComponentClass.annotation.module.name]);

let controller = null;

angular.mock.module(componentName);
angular.mock.inject((_$compile_, _$rootScope_) => {
const compiledTemplate = compileTemplate(template, _$compile_, _$rootScope_);
controller = compiledTemplate.controller(elProperty);
controller._element = compiledTemplate;
});

return controller;
}

function compileTemplate(template, $compile, $rootScope) {
const el = angular.element(template.trim());
$compile(el)($rootScope.$new());
$rootScope.$digest();
return el;
}
16 changes: 16 additions & 0 deletions src/test-helpers.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*eslint-env node, jasmine*/
import {buildComponent} from 'anglue/anglue';

describe('Test helpers', () => {
describe('buildComponent', () => {

class Generic {}

it('should throw an error when called with a class without annotation', () => {
expect(() => {
buildComponent(Generic);
}).toThrow(new Error('ComponentClass is not annotated: Generic'));
});

});
});
8 changes: 8 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,11 @@ export function getCurrentDescriptorValue(propertyDescriptor) {
export function camelcase(name) {
return `${name[0].toUpperCase()}${name.slice(1)}`;
}

export function camelCaseToDashes (name) {
return name.replace(/([a-z])([A-Z])/g, '$1-$2');
}

export function dashesToCamelCase (name) {
return String(name).replace(/-([a-z])/g, part => part[1].toUpperCase());
}