Skip to content

Commit

Permalink
Merge pull request #1627 from carsonreinke/feature-jest
Browse files Browse the repository at this point in the history
Replace Karma With Jest
  • Loading branch information
Nabil Cheikh authored Feb 3, 2020
2 parents 81e176b + 64460cb commit cf1c2d3
Show file tree
Hide file tree
Showing 18 changed files with 9,206 additions and 5,501 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
116 changes: 116 additions & 0 deletions assets/js/test-unit/theme/common/state-country.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import $ from 'jquery';
import '../../../theme/global/jquery-migrate';
//import { api } from '@bigcommerce/stencil-utils';
jest.mock('@bigcommerce/stencil-utils');
import utils from '@bigcommerce/stencil-utils';
const api = utils.api;
import modalFactory, { alertModal } from '../../../theme/global/modal';
import foundation from '../../../theme/global/foundation';
import stateCountry from '../../../theme/common/state-country';

//console.log(utils);
//jest.mock('api.country');

describe('StateCountry', () => {
let $countryElement, $stateElement;

beforeEach(() => {
$countryElement = $(`
<select class="form-select" id="shipping-country" name="shipping-country" data-field-type="Country">
<option>Country</option>
<option value="1">Peace Land</option>
<option value="2">Serenityville</option>
<option value="3">Moon Place</option>
</select>
`);
$stateElement = $(`
<select class="form-select" id="shipping-state" name="shipping-state" data-field-type="State">
<option>State/province</option>
</select>
`);
$countryElement.appendTo(document.body);
$stateElement.appendTo(document.body);
});

afterEach(() => {
$countryElement.remove();
$stateElement.remove();
});

describe('on error', () => {
let $modalElement, modal;

beforeEach(() => {
$modalElement = $(`
<div id="alert-modal" class="modal modal--alert" data-reveal>
<div class="modal-content"></div>
<div class="loadingOverlay"></div>
</div>
`)
$modalElement.appendTo(document.body);
modal = alertModal();

api.country.getByName.mockImplementation((countryName, callback) => {
callback(new Error(countryName + 'missing'), null);
});
jest.spyOn(modal, 'open');
});

afterEach(() => {
$modalElement.remove();
$('body').removeClass();
});

it('should show modal', (done) => {
stateCountry($stateElement, {state_error: 'Missing'}, {}, (err) => {
expect(modal.open).toHaveBeenCalled();
done();
});

$countryElement.val('1').trigger('change');
});
});

describe('on change', () => {
beforeEach(() => {
api.country.getByName.mockImplementation((countryName, callback) => {
let states = [];
switch(countryName) {
case '1': break;
case '3':
states = [
{id: '1', name: 'Kepler'},
{id: '2', name: 'Grimaldi'},
{id: '3', name: 'Byrgius'}
];
break;
}

callback(null, {data: {states}});
});
});

it('should update states', (done) => {
stateCountry($stateElement, {}, {}, (err) => {
$stateElement.remove();
$stateElement = $('[data-field-type="State"]');
expect($stateElement.find('option').length).toEqual(4);

const names = $stateElement.find('option').map(function() {
return $(this).text();
}).get();
expect(names).toEqual(['undefined', 'Kepler', 'Grimaldi', 'Byrgius']);

done();
});

$countryElement.val('3').trigger('change');
});

it('should erase existing', (done) => {
$countryElement.val('3').trigger('change');
$countryElement.val('1').trigger('change');
done();
});
});
});
Loading

0 comments on commit cf1c2d3

Please sign in to comment.