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

Add unit tests #21

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
language: node_js
node_js:
- '8'
cache: npm
before_install:
- cd web
install:
Expand Down
16 changes: 8 additions & 8 deletions web/src/store/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@ const mutations = {
};

const actions = {
setLoading(context, isLoading) {
context.commit('SET_LOADING', isLoading);
setLoading({ commit }, isLoading) {
commit('SET_LOADING', isLoading);
},
setCategories(context, categories) {
context.commit('SET_CATEGORIES', categories);
setCategories({ commit }, categories) {
commit('SET_CATEGORIES', categories);
},
setSelectedIdeaIndex(context, index) {
context.commit('SET_SELECTED_IDEA_INDEX', index);
setSelectedIdeaIndex({ commit }, index) {
commit('SET_SELECTED_IDEA_INDEX', index);
},
setTitle(context, title) {
context.commit('SET_TITLE', title);
setTitle({ commit }, title) {
commit('SET_TITLE', title);
},
setUserDataDB(context, db) {
context.commit('SET_USER_DATA_DB', db);
Expand Down
8 changes: 8 additions & 0 deletions web/tests/unit/StoreFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Vuex from 'vuex';
import Vue from 'vue';

Vue.use(Vuex);

export default (getters, actions = {}) => {
return new Vuex.Store({ getters, actions });
};
48 changes: 48 additions & 0 deletions web/tests/unit/components/IdeaList.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { shallowMount } from '@vue/test-utils';
import IdeaList from '../../../src/components/IdeaList';
import Vuex from 'vuex';
import StoreFactory from '../StoreFactory';

global.window.matchMedia = () => {
return { matches: true };
};

describe('IdeaList.vue', () => {
let store, ideas;

beforeEach(() => {
store = StoreFactory({
selectedIdeaIndex: () => 0
});
ideas = [
{
title: 'Test title',
difficulty: 'Beginner',
progress: 'done',
bookmarked: true
}
];
});

test('It should correctly render the list of ideas', () => {
const wrapper = shallowMount(IdeaList, {
store,
stubs: ['popper', 'progress-modal', 'font-awesome-icon'],
propsData: { ideas }
});

expect(wrapper.findAll('.ideaItem').length).toEqual(ideas.length);
expect(wrapper.find('#ideaList li:first-child #ideaTitle').text()).toEqual(
ideas[0].title
);
expect(
wrapper.find('#ideaList li:first-child #ideaDifficulty').text()
).toEqual(ideas[0].difficulty);
expect(
wrapper
.find('#ideaList li:first-child')
.classes()
.find(e => e == 'progress-done')
).toBeDefined();
});
});
68 changes: 51 additions & 17 deletions web/tests/unit/components/Navbar.spec.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Navbar from '../../../src/components/Navbar.vue';
import Vuex from 'vuex';

const localVue = createLocalVue();
localVue.use(Vuex);
import StoreFactory from '../StoreFactory';

describe('Navbar.vue', () => {
const actions = { logout: jest.fn() };

let store;
beforeEach(() => {
store = new Vuex.Store({
modules: {
app: {
getters: {
navbarTitle: () => 'Ideabag 2 (TEST)'
}
}
}
});
store = StoreFactory({ navbarTitle: () => 'Ideabag 2 (TEST)' });
});

test('It should render app title correctly', () => {
const wrapper = shallowMount(Navbar, {
store,
localVue,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $route: { path: '/' } }
});
Expand All @@ -33,7 +23,6 @@ describe('Navbar.vue', () => {
test('It should not render back button if root route', () => {
const wrapper = shallowMount(Navbar, {
store,
localVue,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $route: { path: '/' } }
});
Expand All @@ -46,11 +35,56 @@ describe('Navbar.vue', () => {
test('It should render back button if not root route', () => {
const wrapper = shallowMount(Navbar, {
store,
localVue,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $route: { path: '/categories/1' } }
});

expect(wrapper.find('.toolbar-left > .icon-button').exists()).toEqual(true);
});

test('It should render correct links when logged in', () => {
let store = StoreFactory({
userLoggedIn: () => true,
userEmail: () => 'test@gmail.com'
});

const wrapper = shallowMount(Navbar, {
store,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $route: { path: '/' } }
});

expect(wrapper.find('#links li:first-child').text()).toEqual(
'Welcome, test@gmail.com!'
);
expect(wrapper.find('#links li:last-child').text()).toEqual('Log out');
});

test('It should render correct links when logged out', () => {
let store = StoreFactory({
userLoggedIn: () => false
});

const wrapper = shallowMount(Navbar, {
store,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $route: { path: '/' } }
});

expect(wrapper.find('#links li:first-child').text()).toEqual('Login');
expect(wrapper.find('#links li:last-child').text()).toEqual('Signup');
});

/*test('It should correctly logout', () => {
store = StoreFactory({ userLoggedIn: () => true }, actions);

const wrapper = shallowMount(Navbar, {
store,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $route: { path: '/' } }
});

wrapper.find('#links li:last-child > a').trigger('click');
expect(actions.logout).toHaveBeenCalled();
});*/
});
86 changes: 86 additions & 0 deletions web/tests/unit/store/app.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import app from '../../../src/store/app';

describe('app.js', () => {
let state, getters, mutations, actions, commit;

beforeAll(() => {
state = app.state;
getters = app.getters;
mutations = app.mutations;
actions = app.actions;
});

beforeEach(() => (commit = jest.fn()));

it('should correctly map getters from state', () => {
let s = {
navbarTitle: 'Test title',
isLoading: true,
selectedIdeaIndex: 1,
categories: [],
userDataDB: null
};

expect(getters.navbarTitle(s)).toEqual(s.navbarTitle);
expect(getters.isLoading(s)).toEqual(s.isLoading);
expect(getters.selectedIdeaIndex(s)).toEqual(s.selectedIdeaIndex);
expect(getters.categories(s)).toEqual(s.categories);
expect(getters.userDataDB(s)).toEqual(s.userDataDB);
});

it('should correctly set Navbar title', () => {
let title = 'Test title';
mutations.SET_TITLE(state, title);
expect(state.navbarTitle).toEqual(title);
});

it('should correctly set app state as loading', () => {
let loading = true;
mutations.SET_LOADING(state, loading);
expect(state.isLoading).toEqual(loading);
});

it('should correctly set selected idea index', () => {
let selectedIdeaIndex = 5;
mutations.SET_SELECTED_IDEA_INDEX(state, selectedIdeaIndex);
expect(state.selectedIdeaIndex).toEqual(selectedIdeaIndex);
});

it('should correctly set categories', () => {
let categories = [{ id: 1 }, { id: 2 }];
mutations.SET_CATEGORIES(state, categories);
expect(state.categories.length).toEqual(categories.length);
expect(state.categories[0].id).toEqual(categories[0].id);
});

it('should correctly set userData db', () => {
let db = { id: 1 };
mutations.SET_USER_DATA_DB(state, db);
expect(state.userDataDB.id).toEqual(db.id);
});

it('should correctly call the SET_LOADING mutation', () => {
actions.setLoading({ commit }, true);
expect(commit).toHaveBeenCalledWith('SET_LOADING', true);
});

it('should correctly call the SET_CATEGORIES mutation', () => {
actions.setCategories({ commit }, [1, 2]);
expect(commit).toHaveBeenCalledWith('SET_CATEGORIES', [1, 2]);
});

it('should correctly call the SET_SELECTED_IDEA_INDEX mutation', () => {
actions.setSelectedIdeaIndex({ commit }, 1);
expect(commit).toHaveBeenCalledWith('SET_SELECTED_IDEA_INDEX', 1);
});

it('should correctly call the SET_TITLE mutation', () => {
actions.setTitle({ commit }, 'Test title');
expect(commit).toHaveBeenCalledWith('SET_TITLE', 'Test title');
});

it('should correctly call the SET_USER_DATA_DB mutation', () => {
actions.setUserDataDB({ commit }, {});
expect(commit).toHaveBeenCalledWith('SET_USER_DATA_DB', {});
});
});
3 changes: 3 additions & 0 deletions web/tests/unit/store/auth.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
describe('auth.js', () => {
it('should map getters from state', () => {});
});
47 changes: 47 additions & 0 deletions web/tests/unit/views/CategoryList.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { shallowMount } from '@vue/test-utils';
import StoreFactory from '../StoreFactory';
import CategoryList from '../../../src/views/CategoryList';

describe('CategoryList.vue', () => {
let store, wrapper;
let $router = {
push: jest.fn()
};
let categories = [
{
id: 1,
categoryLbl: 'Test category title',
categoryCount: 10,
items: []
}
];

beforeEach(() => {
store = StoreFactory({ categories: () => categories });
wrapper = shallowMount(CategoryList, {
store,
stubs: ['router-link', 'font-awesome-icon'],
mocks: { $router }
});
});

test('It should render the list of categories correctly', () => {
expect(wrapper.findAll('.categoryItem').length).toEqual(categories.length);
expect(
wrapper
.find('#categoryList .categoryItem:first-child #categoryTitle')
.text()
).toEqual(categories[0].categoryLbl);
expect(
wrapper
.find('#categoryList .categoryItem:first-child .secondaryLbl')
.text()
).toEqual(`Ideas: ${categories[0].categoryCount}`);
});

test('It should correctly navigate to category detail view', () => {
wrapper.find('#categoryList li:first-child').trigger('click');
expect(wrapper.vm.selectedIndex).toEqual(0);
expect($router.push).toHaveBeenCalled();
});
});
40 changes: 40 additions & 0 deletions web/tests/unit/views/Login.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { shallowMount } from '@vue/test-utils';
import StoreFactory from '../StoreFactory';
import Login from '../../../src/views/Login';

describe('Login.vue', () => {
let store, actions;

beforeEach(() => {
actions = {
loginUser: jest.fn()
};
store = StoreFactory({}, actions);
});

test('It should attempt login if username and password are provided', () => {
const wrapper = shallowMount(Login, {
store,
stubs: ['font-awesome-icon']
});

wrapper.find('#emailTb').setValue('test@gmail.com');
wrapper.find('#passwordTb').setValue('p@ssword');
wrapper.find('.appBtn').trigger('click');

expect(actions.loginUser).toHaveBeenCalled();
});

/*test('It should not attempt login if username or password is not provided', () => {
const wrapper = shallowMount(Login, {
store,
stubs: ['font-awesome-icon']
});

wrapper.find('#emailTb').setValue('');
wrapper.find('#passwordTb').setValue('');
wrapper.find('.appBtn').trigger('click');

expect(actions.loginUser).toHaveBeenCalledTimes(0);
});*/
});
27 changes: 27 additions & 0 deletions web/tests/unit/views/Register.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { shallowMount } from '@vue/test-utils';
import StoreFactory from '../StoreFactory';
import Register from '../../../src/views/Register';

describe('Register.vue', () => {
let store, actions;

beforeEach(() => {
actions = {
registerUser: jest.fn()
};
store = StoreFactory({}, actions);
});

test('It should attempt login if username and password are provided', () => {
const wrapper = shallowMount(Register, {
store,
stubs: ['font-awesome-icon']
});

wrapper.find('#emailTb').setValue('test@gmail.com');
wrapper.find('#passwordTb').setValue('p@ssword');
wrapper.find('.appBtn').trigger('click');

expect(actions.registerUser).toHaveBeenCalled();
});
});