Skip to content

Commit

Permalink
Remove Karma, add Jest
Browse files Browse the repository at this point in the history
  • Loading branch information
carsonreinke committed Jan 30, 2020
1 parent 5edd2c2 commit 6203c37
Show file tree
Hide file tree
Showing 16 changed files with 9,080 additions and 5,499 deletions.
3 changes: 2 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ module.exports = function(grunt) {
}
});

grunt.registerTask('default', ['eslint', 'karma', 'scsslint', 'svgstore'])
grunt.loadNpmTasks('grunt-run');
grunt.registerTask('default', ['eslint', 'jest', 'scsslint', 'svgstore'])
};
18 changes: 12 additions & 6 deletions assets/js/test-unit/theme/common/collapsible-group.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,25 @@ describe('CollapsibleGroup', () => {
let childCollapsible;

beforeEach(() => {
collapsible = jasmine.createSpyObj('collapsible', ['close', 'hasCollapsible']);
collapsible = {
close: jest.fn(),
hasCollapsible: jest.fn()
};
childCollapsible = {};

collapsibleGroup.openCollapsible = collapsible;
});

it('should close the currently open collapsible if it does not contain the newly open collapsible', () => {
collapsible.hasCollapsible.and.returnValue(false);
collapsible.hasCollapsible.mockImplementation(() => false);
collapsibleGroup.$component.trigger(CollapsibleEvents.open, [childCollapsible]);

expect(collapsible.close).toHaveBeenCalled();
expect(collapsibleGroup.openCollapsible).toEqual(childCollapsible);
});

it('should not close the currently open collapsible if it contains the newly open collapsible', () => {
collapsible.hasCollapsible.and.returnValue(true);
collapsible.hasCollapsible.mockImplementation(() => true);
collapsibleGroup.$component.trigger(CollapsibleEvents.open, [childCollapsible]);

expect(collapsible.close).not.toHaveBeenCalled();
Expand All @@ -54,21 +57,24 @@ describe('CollapsibleGroup', () => {
let childCollapsible;

beforeEach(() => {
collapsible = jasmine.createSpyObj('collapsible', ['hasCollapsible']);
collapsible = {
close: jest.fn(),
hasCollapsible: jest.fn()
};
childCollapsible = {};

collapsibleGroup.openCollapsible = collapsible;
});

it('should unset `openCollapsible` if it does not contain the newly open collapsible', () => {
collapsible.hasCollapsible.and.returnValue(false);
collapsible.hasCollapsible.mockImplementation(() => false);
collapsibleGroup.$component.trigger(CollapsibleEvents.close, [childCollapsible]);

expect(collapsibleGroup.openCollapsible).toEqual(null);
});

it('should not unset `openCollapsible` if it contains the newly open collapsible', () => {
collapsible.hasCollapsible.and.returnValue(true);
collapsible.hasCollapsible.mockImplementation(() => true);
collapsibleGroup.$component.trigger(CollapsibleEvents.close, [childCollapsible]);

expect(collapsibleGroup.openCollapsible).not.toEqual(null);
Expand Down
6 changes: 3 additions & 3 deletions assets/js/test-unit/theme/common/collapsible.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ describe('Collapsible', () => {

describe('when clicking on a toggle', () => {
beforeEach(() => {
spyOn(collapsible, 'open');
spyOn(collapsible, 'close');
spyOn(collapsible, 'toggle').and.callThrough();
jest.spyOn(collapsible, 'open').mockImplementation(() => {});
jest.spyOn(collapsible, 'close').mockImplementation(() => {});
jest.spyOn(collapsible, 'toggle');
});

it('should open if it is closed', () => {
Expand Down
54 changes: 27 additions & 27 deletions assets/js/test-unit/theme/common/faceted-search.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('FacetedSearch', () => {
let $element;

beforeEach(() => {
onSearchSuccess = jasmine.createSpy('onSearchSuccess');
onSearchSuccess = jest.fn();

requestOptions = {
config: {
Expand Down Expand Up @@ -73,9 +73,9 @@ describe('FacetedSearch', () => {
beforeEach(() => {
content = { html: '<div>Results</div>' };

spyOn(facetedSearch, 'restoreCollapsedFacets');
spyOn(facetedSearch, 'restoreCollapsedFacetItems');
spyOn(Validators, 'setMinMaxPriceValidation');
jest.spyOn(facetedSearch, 'restoreCollapsedFacets').mockImplementation(() => {});
jest.spyOn(facetedSearch, 'restoreCollapsedFacetItems').mockImplementation(() => {});
jest.spyOn(Validators, 'setMinMaxPriceValidation').mockImplementation(() => {});
});

it('should update view with content by firing registered callback', () => {
Expand Down Expand Up @@ -108,21 +108,21 @@ describe('FacetedSearch', () => {
const url = '/current/path?facet=1';

beforeEach(() => {
spyOn(api, 'getPage');
spyOn(facetedSearch, 'refreshView');
spyOn(urlUtils, 'getUrl').and.returnValue(url);
jest.spyOn(api, 'getPage').mockImplementation(() => {});
jest.spyOn(facetedSearch, 'refreshView').mockImplementation(() => {});
jest.spyOn(urlUtils, 'getUrl').mockImplementation(() => url);

content = {};
});

it('should fetch content from remote server', function() {
facetedSearch.updateView();

expect(api.getPage).toHaveBeenCalledWith(url, requestOptions, jasmine.any(Function));
expect(api.getPage).toHaveBeenCalledWith(url, requestOptions, expect.any(Function));
});

it('should refresh view', function() {
api.getPage.and.callFake(function(url, options, callback) {
jest.spyOn(api, 'getPage').mockImplementation(function(url, options, callback) {
callback(null, content);
});

Expand Down Expand Up @@ -153,8 +153,8 @@ describe('FacetedSearch', () => {
let $navList;

beforeEach(() => {
spyOn(facetedSearch, 'getMoreFacetResults');
spyOn(facetedSearch, 'collapseFacetItems');
jest.spyOn(facetedSearch, 'getMoreFacetResults').mockImplementation(() => {});
jest.spyOn(facetedSearch, 'collapseFacetItems').mockImplementation(() => {});

$navList = $('#facet-brands');
});
Expand All @@ -180,11 +180,11 @@ describe('FacetedSearch', () => {
beforeEach(() => {
href = document.location.href;

spyOn(facetedSearch, 'updateView');
jest.spyOn(facetedSearch, 'updateView').mockImplementation(() => {});
});

afterEach(() => {
urlUtils.goToUrl(href);
urlUtils.goToUrl('/');
});

it('should update view', () => {
Expand All @@ -202,21 +202,21 @@ describe('FacetedSearch', () => {
eventName = 'facetedSearch-range-submitted';
event = {
currentTarget: '#facet-range-form',
preventDefault: jasmine.createSpy('preventDefault'),
preventDefault: jest.fn(),
};

spyOn(urlUtils, 'goToUrl');
spyOn(facetedSearch.priceRangeValidator, 'areAll').and.returnValue(true);
jest.spyOn(urlUtils, 'goToUrl').mockImplementation(() => {});
jest.spyOn(facetedSearch.priceRangeValidator, 'areAll').mockImplementation(() => true);
});

it('should set `min_price` and `max_price` query param to corresponding form values if form is valid', () => {
hooks.emit(eventName, event);

expect(urlUtils.goToUrl).toHaveBeenCalledWith('/context.html?min_price=0&max_price=100');
expect(urlUtils.goToUrl).toHaveBeenCalledWith('/?min_price=0&max_price=100');
});

it('should not set `min_price` and `max_price` query param to corresponding form values if form is invalid', () => {
facetedSearch.priceRangeValidator.areAll.and.returnValue(false);
jest.spyOn(facetedSearch.priceRangeValidator, 'areAll').mockImplementation(() => false);
hooks.emit(eventName, event);

expect(urlUtils.goToUrl).not.toHaveBeenCalled();
Expand All @@ -237,17 +237,17 @@ describe('FacetedSearch', () => {
eventName = 'facetedSearch-range-submitted';
event = {
currentTarget: '#facet-range-form-with-other-facets',
preventDefault: jasmine.createSpy('preventDefault'),
preventDefault: jest.fn(),
};

spyOn(urlUtils, 'goToUrl');
spyOn(facetedSearch.priceRangeValidator, 'areAll').and.returnValue(true);
jest.spyOn(urlUtils, 'goToUrl').mockImplementation(() => {});
jest.spyOn(facetedSearch.priceRangeValidator, 'areAll').mockImplementation(() => true);
});

it('send `min_price` and `max_price` query params if form is valid', () => {
hooks.emit(eventName, event);

expect(urlUtils.goToUrl).toHaveBeenCalledWith('/context.html?brand[]=item1&brand[]=item2&min_price=0&max_price=50');
expect(urlUtils.goToUrl).toHaveBeenCalledWith('/?brand[]=item1&brand[]=item2&min_price=0&max_price=50');
});
});

Expand All @@ -259,16 +259,16 @@ describe('FacetedSearch', () => {
eventName = 'sortBy-submitted';
event = {
currentTarget: '#facet-sort',
preventDefault: jasmine.createSpy('preventDefault'),
preventDefault: jest.fn(),
};

spyOn(urlUtils, 'goToUrl');
jest.spyOn(urlUtils, 'goToUrl').mockImplementation(() => {});
});

it('should set `sort` query param to the value of selected option', () => {
hooks.emit(eventName, event);

expect(urlUtils.goToUrl).toHaveBeenCalledWith('/context.html?sort=featured');
expect(urlUtils.goToUrl).toHaveBeenCalledWith('/?sort=featured');
});

it('should prevent default event', function() {
Expand All @@ -286,10 +286,10 @@ describe('FacetedSearch', () => {
eventName = 'facetedSearch-facet-clicked';
event = {
currentTarget: '[href="?brand=item1"]',
preventDefault: jasmine.createSpy('preventDefault'),
preventDefault: jest.fn(),
};

spyOn(urlUtils, 'goToUrl');
jest.spyOn(urlUtils, 'goToUrl').mockImplementation(() => {});
});

it('should change the URL of window to the URL of facet item', () => {
Expand Down
10 changes: 5 additions & 5 deletions assets/js/test-unit/theme/common/form-utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ describe('Validators', () => {
let validator;

beforeEach(() => {
validator = jasmine.createSpyObj('validator', [
'add',
'configure',
'setMessageOptions',
]);
validator = {
add: jest.fn(),
configure: jest.fn(),
setMessageOptions: jest.fn()
};
});

describe('setMinMaxPriceValidation', () => {
Expand Down
25 changes: 21 additions & 4 deletions assets/js/test-unit/theme/global/modal.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../../../theme/global/jquery-migrate';
import modalFactory, { ModalEvents } from '../../../theme/global/modal';
import $ from 'jquery';
import '../../../theme/global/jquery-migrate';

function attachHtml(html) {
const $element = $(html);
Expand Down Expand Up @@ -47,15 +47,32 @@ describe('Modal', () => {
let $modalBody;

beforeEach(() => {
$('body').height(500);

$modalBody = $(`
<div class="modal-body">
<div style="height: 700px;"></div>
</div>
`);

modal.$content.html($modalBody);

//Force heights of each element since jsdom does not provide these
[
$('body')[0]
].forEach((elm) => {
['scollHeight', 'offsetHeight', 'clientHeight', 'innerHeight'].forEach((property) => {
Object.defineProperty(elm, property, { configurable: true, value: 500});
});
});
[
window.document.documentElement,
$modalBody[0],
$modalBody.find('div')[0],
modal.$content[0]
].forEach((elm) => {
['scollHeight', 'offsetHeight', 'clientHeight', 'innerHeight'].forEach((property) => {
Object.defineProperty(elm, property, { configurable: true, value: 700});
});
});
});

afterEach(() => {
Expand All @@ -65,7 +82,7 @@ describe('Modal', () => {
it('should restrain content height', () => {
modal.$modal.trigger(ModalEvents.opened);

expect(parseInt($modalBody.css('max-height'), 10)).toEqual(637);
expect(parseInt($modalBody.css('max-height'), 10)).toEqual(630);
});
});

Expand Down
17 changes: 17 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
plugins: [
'@babel/plugin-syntax-dynamic-import', // add support for dynamic imports (used in app.js)
'lodash', // Tree-shake lodash
],
presets: [
['@babel/preset-env', {
//debug: true,
loose: true, // Enable "loose" transformations for any plugins in this preset that allow them
modules: 'auto',
useBuiltIns: 'usage', // Tree-shake babel-polyfill
targets: {
node: 'current',
},
}],
],
};
5 changes: 4 additions & 1 deletion grunt/aliases.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
---
jest:
- run:jest

check:
- check:js
- check:css

check:js:
- eslint
- karma
- run:jest

check:css:
- scsslint
5 changes: 0 additions & 5 deletions grunt/karma.js

This file was deleted.

8 changes: 8 additions & 0 deletions grunt/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
jest: {
cmd: 'npx',
args: [
'jest'
]
}
};
5 changes: 5 additions & 0 deletions jest-eventemitter2-transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
process(src, filename) {
return src.replace('exports.EventEmitter2 = EventEmitter;', 'module.exports = EventEmitter;');
},
};
Loading

0 comments on commit 6203c37

Please sign in to comment.