Skip to content

Commit

Permalink
Unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
presidenten committed May 7, 2017
1 parent 5a22226 commit f1252ad
Show file tree
Hide file tree
Showing 16 changed files with 701 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .jestrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"bail": true,
"testMatch": [
"<rootDir>/src/api/**/?(*.)(spec).js?(x)"
"<rootDir>/src/**/?(*.)(spec).js?(x)"
],
"moduleFileExtensions": [
"js",
Expand Down
10 changes: 10 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"language": "node_js",
"node_js": "6.9.1",
"before_script": [
"export DISPLAY=:99.0",
"sh -e /etc/init.d/xvfb start",
"yarn"
],
"script": "npm run test"
}
11 changes: 6 additions & 5 deletions dist/vuex+.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var toCamelCase = function (str) {
if (!str) {
return '';
}
return str.replace(/(-|_)([a-z])/g, function (s) { return s[1].toUpperCase(); });
return str.replace(/(-|_)([\w])/g, function (s) { return s[1].toUpperCase(); });
};


Expand Down Expand Up @@ -181,6 +181,9 @@ var vuexInstance = {};

var handlers = [];




var registerForHMR = function (newStore, baseStoreName, storeInstanceName) {
handlers.push({
storeName: baseStoreName + '-store',
Expand Down Expand Up @@ -264,7 +267,6 @@ function setup(newImporter) {
* - instance {string}: Contains the instance name
* - preserve {boolean}: If true, the store wont be discarded when the final instance is destroyed
* @param {string} baseStoreName - The base store name, same as the store filename
* @param {Object} loadedModule - The loaded javascript module containing the Vuex module store
* @returns {mixin, api} api for the loaded module and a mixin
*/
function add(baseStoreName) {
Expand Down Expand Up @@ -295,7 +297,6 @@ function add(baseStoreName) {
var store = getNewInstanceStore(loadedModule);
if (!this.$store._modules.root._children[this['$vuex+'].storeInstanceName]) { // eslint-disable-line
this.$store.registerModule(this['$vuex+'].storeInstanceName, store);

var remappedApi = remapBaseStore(store.$api, this['$vuex+'].baseStoreName, this['$vuex+'].storeInstanceName);
api[this['$vuex+'].baseStoreName] = store.$api;
api[this['$vuex+'].storeInstanceName] = remappedApi;
Expand Down Expand Up @@ -520,7 +521,7 @@ var _vuePluginInstall = {
var findModuleName = function (parent) {
if (!this$1['$vuex+'] && parent.$parent) {
if (!parent.$parent['$vuex+']) {
findModuleName(parent.$parent, '/');
findModuleName(parent.$parent);
} else {
this$1['$vuex+'] = {
baseStoreName: parent.$parent['$vuex+'].baseStoreName,
Expand All @@ -530,7 +531,7 @@ var _vuePluginInstall = {
}
};

findModuleName(this, '/');
findModuleName(this);
},
});
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vuex-plus",
"version": "0.7.1",
"version": "0.7.2",
"description": "Opinionated library that handles module instances in Vuex",
"main": "dist/vuex+.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/common/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const toCamelCase = (str) => {
if (!str) {
return '';
}
return str.replace(/(-|_)([a-z])/g, s => s[1].toUpperCase());
return str.replace(/(-|_)([\w])/g, s => s[1].toUpperCase());
};


Expand Down
125 changes: 121 additions & 4 deletions src/common/helpers.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,124 @@
import helpers from './helpers.js';
import * as helpers from './helpers.js';

describe.skip('helpers.y', () => {
it('', () => {
expect('').toEqual('');
describe('helpers.getStoreInstanceName', () => {
it('should handle when no instance', () => {
expect(helpers.getStoreInstanceName('foo')).toEqual('foo');
});

it('should handle when instance', () => {
expect(helpers.getStoreInstanceName('foo', 'bar')).toEqual('foo$bar');
});
});

describe('helpers.toCamelCase', () => {
it('convert kebab to camel case', () => {
expect(helpers.toCamelCase('a-foo-bar-a$b')).toEqual('aFooBarA$b');
});
it('convert snake to camel case', () => {
expect(helpers.toCamelCase('a_foo_bar_a$b')).toEqual('aFooBarA$b');
});
it('handles numbers', () => {
expect(helpers.toCamelCase('a-fo1o2-ba3r-4a$5b')).toEqual('aFo1o2Ba3r4a$5b');
});
it('keeps camel case intact', () => {
expect(helpers.toCamelCase('aFooBarA$b')).toEqual('aFooBarA$b');
});
});

describe('helpers.getLocalPath', () => {
it('replaces store name to top instance', () => {
const state = {
'vuex+': {
storeName: 'foo',
instance: 'bar',
},
};
expect(helpers.getLocalPath('foo/piri', state)).toEqual('foo$bar/piri');
});

it('replaces keeps store name when no instance', () => {
const state = {
'vuex+': {
storeName: 'foo',
},
};
expect(helpers.getLocalPath('foo/piri', state)).toEqual('foo/piri');
});
});

describe('helpers.getTagName', () => {
it('returns unknown if no $parent', () => {
expect(helpers.getTagName({})).toEqual('<unknown-tag>');
});

it('returns tag from $vnode', () => {
const self = {
$parent: {
$vnode: {
componentOptions: {
tag: 'foo',
},
},
},
};
expect(helpers.getTagName(self)).toEqual('<foo>');
});

it('returns tag from _vnode', () => {
const self = {
$parent: {
_vnode: {
componentOptions: {
tag: 'foo',
},
},
},
};
expect(helpers.getTagName(self)).toEqual('<foo>');
});
});

describe('helpers.getInstances', () => {
it('goes though parents and retrieves instances', () => {
const self = {
$parent: {
instance: 'foo',
$parent: {
instance: 'bar',
$parent: {
instance: 'chuu',
},
},
},
};
expect(helpers.getInstances('a/b', self)).toEqual(['$chuu', '$bar', '$foo']);
});

it('goes though parents and retrieves instances, and handles when parents lack instances', () => {
const self = {
$parent: {
$parent: {
$parent: {
instance: 'chuu',
},
},
},
};
expect(helpers.getInstances('a/b', self)).toEqual(['$chuu']);
});

it('adds subinstances', () => {
const self = {
$parent: {
instance: 'foo',
},
};
expect(helpers.getInstances('a$a1/b$b1/c$c1/d', self)).toEqual(['$foo', '$a1', '$b1', '$c1']);
});
});

describe('helpers.getSubInstances', () => {
it('returns all instances from substring', () => {
expect(helpers.getSubInstances('a$a1/b/c$c1/d')).toEqual(['$a1', '$c1']);
});
});
5 changes: 5 additions & 0 deletions src/common/hmrHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import vuexInstance from '../vuexInstance.js';

let handlers = [];

export const getHandlers = () => handlers.slice();
export const clearHandlers = () => {
handlers = [];
};

export const registerForHMR = (newStore, baseStoreName, storeInstanceName) => {
handlers.push({
storeName: baseStoreName + '-store',
Expand Down
62 changes: 62 additions & 0 deletions src/common/hmrHandler.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as hmr from './hmrHandler.js';
import * as vuexInstance from '../vuexInstance.js';

beforeEach(() => {
hmr.clearHandlers();
});

describe('hmrHandler.registerForHMR', () => {
it('should be able to register hmr for top stores', () => {
expect(hmr.getHandlers().length).toBe(0);
const newStore = () => {};
hmr.registerForHMR(newStore, 'foo', 'foo$bar');
expect(hmr.getHandlers().length).toBe(1);
expect(hmr.getHandlers()[0]).toEqual({
storeName: 'foo-store',
storeInstanceName: 'foo$bar',
newStore,
});
});
});

describe('hmrHandler.unregisterForHMR', () => {
it('should be able remove handler for top store', () => {
const newStore = () => {};
hmr.registerForHMR(newStore, 'foo', 'foo$bar');
hmr.unregisterForHMR(newStore);
expect(hmr.getHandlers().length).toBe(0);
});
});

describe('hmrHandler.hmrHandler', () => {
it('should return a list of updated stores', () => {
vuexInstance.default.store = {
hotUpdate: jest.fn(),
};

hmr.registerForHMR(() => {}, 'foo1', 'foo1$bar1');
const $api = {
get: 'foo2/bar2',
act: 'foo2/bar2',
mutate: 'foo2/bar2',
};
const newStore = () => ({
name: 'foo2',
$api,
});
hmr.registerForHMR(newStore, 'foo2', 'foo2$bar2');
hmr.registerForHMR(() => {}, 'foo3', 'foo3$bar3');

const updatedStore = {};
hmr.hmrHandler({ 'foo2-store': updatedStore });

expect(vuexInstance.default.store.hotUpdate).toBeCalledWith({
modules: {
foo2$bar2: {
$api,
name: 'foo2',
},
},
});
});
});
2 changes: 0 additions & 2 deletions src/mixins/addStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export function setup(newImporter) {
* - instance {string}: Contains the instance name
* - preserve {boolean}: If true, the store wont be discarded when the final instance is destroyed
* @param {string} baseStoreName - The base store name, same as the store filename
* @param {Object} loadedModule - The loaded javascript module containing the Vuex module store
* @returns {mixin, api} api for the loaded module and a mixin
*/
export default function add(baseStoreName) {
Expand Down Expand Up @@ -44,7 +43,6 @@ export default function add(baseStoreName) {
const store = getNewInstanceStore(loadedModule);
if (!this.$store._modules.root._children[this['$vuex+'].storeInstanceName]) { // eslint-disable-line
this.$store.registerModule(this['$vuex+'].storeInstanceName, store);

const remappedApi = remapBaseStore(store.$api, this['$vuex+'].baseStoreName, this['$vuex+'].storeInstanceName);
api[this['$vuex+'].baseStoreName] = store.$api;
api[this['$vuex+'].storeInstanceName] = remappedApi;
Expand Down
Loading

0 comments on commit f1252ad

Please sign in to comment.