mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
Fix vue test stacktraces (#12612)
* Issue 10786 - Add unit test for Home component * Issue 10786 - Improve test setup and test invite parameter variations * Issue 10786 - Improve Vue.js test isolation by adding async keyword to dispatch function * Issue 10786 - Missing action does not need to be awaited * fix(vuejs-unit-tests): Fewer stacktraces in avatar.spec.js * No more stacktraces in avatar.spec.js * Register dummy directive in chatCard.spec.js * Resolve stacktraces in column.spec.js * Resolve stacktrace in notifications.spec.js * Resolve warnings in user.spec.js * Resolve asynchronous stacktrace from home.spec.js * Remove unnecessary mount call. * Clear up some let clutter in column.spec.js
This commit is contained in:
@@ -227,7 +227,7 @@ export default {
|
||||
return this.member.preferences.costume ? 'costume' : 'equipped';
|
||||
},
|
||||
specialMountClass () {
|
||||
if (!this.avatarOnly && this.member.items.currentMount && this.member.items.currentMount.indexOf('Kangaroo') !== -1) {
|
||||
if (!this.avatarOnly && this.member.items.currentMount && this.member.items.currentMount.includes('Kangaroo')) {
|
||||
return 'offset-kangaroo';
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import Vue from 'vue';
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
import Avatar from '@/components/avatar';
|
||||
import generateStore from '@/store';
|
||||
|
||||
@@ -6,14 +8,10 @@ context('avatar.vue', () => {
|
||||
let Constructr;
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
Constructr = Vue.extend(Avatar);
|
||||
|
||||
vm = new Constructr({
|
||||
propsData: {
|
||||
member: {
|
||||
const baseMember = {
|
||||
stats: {
|
||||
buffs: {},
|
||||
class: 'warrior',
|
||||
},
|
||||
preferences: {
|
||||
hair: {},
|
||||
@@ -23,9 +21,14 @@ context('avatar.vue', () => {
|
||||
equipped: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}).$mount();
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
Constructr = Vue.extend(Avatar);
|
||||
|
||||
vm = new Constructr({
|
||||
propsData: { member: baseMember },
|
||||
});
|
||||
|
||||
vm.$store = generateStore();
|
||||
});
|
||||
@@ -36,11 +39,11 @@ context('avatar.vue', () => {
|
||||
|
||||
describe('hasClass', () => {
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
vm.member = merge({
|
||||
stats: { lvl: 17 },
|
||||
preferences: { disableClasses: true },
|
||||
flags: { classSelected: false },
|
||||
};
|
||||
}, baseMember);
|
||||
});
|
||||
|
||||
it('accurately reports class status', () => {
|
||||
@@ -54,14 +57,6 @@ context('avatar.vue', () => {
|
||||
});
|
||||
|
||||
describe('isBuffed', () => {
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
stats: {
|
||||
buffs: {},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('accurately reports if buffed', () => {
|
||||
expect(vm.isBuffed).to.equal(undefined);
|
||||
|
||||
@@ -72,29 +67,23 @@ context('avatar.vue', () => {
|
||||
});
|
||||
|
||||
describe('paddingTop', () => {
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
items: {},
|
||||
};
|
||||
});
|
||||
|
||||
xit('defaults to 27px', () => {
|
||||
vm.avatarOnly = true;
|
||||
expect(vm.paddingTop).to.equal('27px');
|
||||
});
|
||||
|
||||
it('is 24px if user has a pet', () => {
|
||||
vm.member.items = {
|
||||
vm.member.items = merge({
|
||||
currentPet: { name: 'Foo' },
|
||||
};
|
||||
}, baseMember.items);
|
||||
|
||||
expect(vm.paddingTop).to.equal('24px');
|
||||
});
|
||||
|
||||
it('is 0px if user has a mount', () => {
|
||||
vm.member.items = {
|
||||
currentMount: { name: 'Bar' },
|
||||
};
|
||||
vm.member.items = merge({
|
||||
currentMount: 'Bar',
|
||||
}, baseMember.items);
|
||||
|
||||
expect(vm.paddingTop).to.equal('0px');
|
||||
});
|
||||
@@ -106,28 +95,25 @@ context('avatar.vue', () => {
|
||||
});
|
||||
|
||||
describe('costumeClass', () => {
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
preferences: {},
|
||||
};
|
||||
});
|
||||
|
||||
it('returns if showing equipped gear', () => {
|
||||
expect(vm.costumeClass).to.equal('equipped');
|
||||
});
|
||||
|
||||
it('returns if wearing a costume', () => {
|
||||
vm.member.preferences = { costume: true };
|
||||
vm.member.preferences = { costume: true, hair: {} };
|
||||
vm.member.items.gear.costume = {};
|
||||
|
||||
expect(vm.costumeClass).to.equal('costume');
|
||||
});
|
||||
});
|
||||
|
||||
describe('visualBuffs', () => {
|
||||
it('returns an array of buffs', () => {
|
||||
vm.member = {
|
||||
vm.member = merge({
|
||||
stats: {
|
||||
class: 'warrior',
|
||||
},
|
||||
};
|
||||
}, baseMember);
|
||||
|
||||
expect(vm.visualBuffs).to.include({ snowball: 'avatar_snowball_warrior' });
|
||||
expect(vm.visualBuffs).to.include({ spookySparkles: 'ghost' });
|
||||
@@ -138,7 +124,10 @@ context('avatar.vue', () => {
|
||||
|
||||
describe('backgroundClass', () => {
|
||||
beforeEach(() => {
|
||||
vm.member.preferences = { background: 'pony' };
|
||||
vm.member.preferences = {
|
||||
hair: {},
|
||||
background: 'pony',
|
||||
};
|
||||
});
|
||||
|
||||
it('shows the background', () => {
|
||||
@@ -161,17 +150,11 @@ context('avatar.vue', () => {
|
||||
|
||||
describe('specialMountClass', () => {
|
||||
it('checks if riding a Kangaroo', () => {
|
||||
vm.member = {
|
||||
stats: {
|
||||
class: 'None',
|
||||
},
|
||||
items: {},
|
||||
};
|
||||
|
||||
expect(vm.specialMountClass).to.equal(null);
|
||||
|
||||
vm.member.items = {
|
||||
currentMount: ['Kangaroo'],
|
||||
currentMount: 'Kangaroo',
|
||||
gear: { equipped: {} },
|
||||
};
|
||||
|
||||
expect(vm.specialMountClass).to.equal('offset-kangaroo');
|
||||
@@ -180,24 +163,22 @@ context('avatar.vue', () => {
|
||||
|
||||
describe('skinClass', () => {
|
||||
it('returns current skin color', () => {
|
||||
vm.member = {
|
||||
stats: {},
|
||||
vm.member = merge({
|
||||
preferences: {
|
||||
skin: 'blue',
|
||||
},
|
||||
};
|
||||
}, baseMember);
|
||||
|
||||
expect(vm.skinClass).to.equal('skin_blue');
|
||||
});
|
||||
|
||||
it('returns if sleep or not', () => {
|
||||
vm.member = {
|
||||
stats: {},
|
||||
vm.member = merge({
|
||||
preferences: {
|
||||
skin: 'blue',
|
||||
sleep: false,
|
||||
},
|
||||
};
|
||||
}, baseMember);
|
||||
|
||||
expect(vm.skinClass).to.equal('skin_blue');
|
||||
|
||||
@@ -210,14 +191,14 @@ context('avatar.vue', () => {
|
||||
context('methods', () => {
|
||||
describe('getGearClass', () => {
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
vm.member = merge({
|
||||
items: {
|
||||
gear: {
|
||||
equipped: { Hat: 'Fancy Tophat' },
|
||||
},
|
||||
},
|
||||
preferences: { costume: false },
|
||||
};
|
||||
}, baseMember);
|
||||
});
|
||||
|
||||
it('returns undefined if no match', () => {
|
||||
@@ -242,7 +223,7 @@ context('avatar.vue', () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
vm.member = merge({
|
||||
items: {
|
||||
gear: {
|
||||
equipped: {
|
||||
@@ -254,13 +235,13 @@ context('avatar.vue', () => {
|
||||
},
|
||||
},
|
||||
preferences: { costume: false },
|
||||
};
|
||||
}, baseMember);
|
||||
});
|
||||
});
|
||||
|
||||
describe('show avatar', () => {
|
||||
beforeEach(() => {
|
||||
vm.member = {
|
||||
vm.member = merge({
|
||||
stats: {
|
||||
buffs: {
|
||||
snowball: false,
|
||||
@@ -269,7 +250,7 @@ context('avatar.vue', () => {
|
||||
shinySeed: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
}, baseMember);
|
||||
});
|
||||
it('does if not showing visual buffs', () => {
|
||||
expect(vm.showAvatar()).to.equal(true);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Vue from 'vue';
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
|
||||
import ChatCard from '@/components/chat/chatCard.vue';
|
||||
@@ -5,6 +6,7 @@ import Store from '@/libs/store';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Store);
|
||||
localVue.use(Vue.directive('b-tooltip', {}));
|
||||
|
||||
describe('ChatCard', () => {
|
||||
function createMessage (text) {
|
||||
|
||||
109
website/client/tests/unit/components/home.spec.js
Normal file
109
website/client/tests/unit/components/home.spec.js
Normal file
@@ -0,0 +1,109 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
|
||||
import Home from '@/components/static/home.vue';
|
||||
import Store from '@/libs/store';
|
||||
import * as Analytics from '@/libs/analytics';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Store);
|
||||
|
||||
describe('Home', () => {
|
||||
let registerStub;
|
||||
let socialAuthStub;
|
||||
let store;
|
||||
let wrapper;
|
||||
|
||||
function mountWrapper (query) {
|
||||
return shallowMount(Home, {
|
||||
store,
|
||||
localVue,
|
||||
mocks: {
|
||||
$t: string => string,
|
||||
$route: { query: query || {} },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function fillOutUserForm (username, email, password) {
|
||||
await wrapper.find('#usernameInput').setValue(username);
|
||||
await wrapper.find('input[type=email]').setValue(email);
|
||||
await wrapper.findAll('input[type=password]').setValue(password);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
registerStub = sinon.stub();
|
||||
socialAuthStub = sinon.stub();
|
||||
store = new Store({
|
||||
state: {},
|
||||
getters: {},
|
||||
actions: {
|
||||
'auth:register': registerStub,
|
||||
'auth:socialAuth': socialAuthStub,
|
||||
'auth:verifyUsername': () => Promise.resolve({}),
|
||||
},
|
||||
});
|
||||
|
||||
sinon.stub(Analytics, 'track');
|
||||
|
||||
wrapper = mountWrapper();
|
||||
});
|
||||
|
||||
afterEach(sinon.restore);
|
||||
|
||||
it('has a visible title', () => {
|
||||
expect(wrapper.find('h1').text()).to.equal('motivateYourself');
|
||||
});
|
||||
|
||||
describe('signup form', () => {
|
||||
it('registers a user from the form', async () => {
|
||||
const username = 'newUser';
|
||||
const email = 'rookie@habitica.com';
|
||||
const password = 'ImmaG3tProductive!';
|
||||
await fillOutUserForm(username, email, password);
|
||||
|
||||
await wrapper.find('form').trigger('submit');
|
||||
|
||||
expect(registerStub.calledOnce).to.be.true;
|
||||
expect(registerStub.getCall(0).args[1]).to.deep.equal({
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
passwordConfirm: password,
|
||||
groupInvite: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('registers a user with group invite if groupInvite in the query', async () => {
|
||||
const groupInvite = 'TheBestGroup';
|
||||
wrapper = mountWrapper({ groupInvite });
|
||||
await fillOutUserForm('invitedUser', 'invited@habitica.com', '1veGotFri3ndsHooray!');
|
||||
|
||||
await wrapper.find('form').trigger('submit');
|
||||
|
||||
expect(registerStub.calledOnce).to.be.true;
|
||||
expect(registerStub.getCall(0).args[1].groupInvite).to.equal(groupInvite);
|
||||
});
|
||||
|
||||
it('registers a user with group invite if p in the query', async () => {
|
||||
const p = 'ThePiGroup';
|
||||
wrapper = mountWrapper({ p });
|
||||
await fillOutUserForm('alsoInvitedUser', 'invited2@habitica.com', '1veGotFri3nds2!');
|
||||
|
||||
await wrapper.find('form').trigger('submit');
|
||||
|
||||
expect(registerStub.calledOnce).to.be.true;
|
||||
expect(registerStub.getCall(0).args[1].groupInvite).to.equal(p);
|
||||
});
|
||||
|
||||
it('registers a user with group invite invite if both p and groupInvite are in the query', async () => {
|
||||
const groupInvite = 'StillTheBestGroup';
|
||||
wrapper = mountWrapper({ p: 'LesserGroup', groupInvite });
|
||||
await fillOutUserForm('doublyInvitedUser', 'invited3@habitica.com', '1veGotSm4rtFri3nds!');
|
||||
|
||||
await wrapper.find('form').trigger('submit');
|
||||
|
||||
expect(registerStub.calledOnce).to.be.true;
|
||||
expect(registerStub.getCall(0).args[1].groupInvite).to.equal(groupInvite);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -20,7 +20,7 @@ describe('Notifications', () => {
|
||||
lvl: 0,
|
||||
},
|
||||
flags: {},
|
||||
preferences: {},
|
||||
preferences: { suppressModals: {} },
|
||||
party: {
|
||||
quest: {
|
||||
},
|
||||
@@ -55,6 +55,7 @@ describe('Notifications', () => {
|
||||
|
||||
expect(wrapper.vm.userHasClass).to.be.true;
|
||||
});
|
||||
|
||||
describe('user exp notifcation', () => {
|
||||
it('notifies when user gets more exp', () => {
|
||||
const expSpy = sinon.spy(wrapper.vm, 'exp');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mount, createLocalVue } from '@vue/test-utils';
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import TaskColumn from '@/components/tasks/column.vue';
|
||||
import Store from '@/libs/store';
|
||||
|
||||
@@ -7,10 +7,6 @@ localVue.use(Store);
|
||||
|
||||
describe('Task Column', () => {
|
||||
let wrapper;
|
||||
let store; let
|
||||
getters;
|
||||
let habits; let taskListOverride; let
|
||||
tasks;
|
||||
|
||||
function makeWrapper (additionalSetup = {}) {
|
||||
const type = 'habit';
|
||||
@@ -19,9 +15,12 @@ describe('Task Column', () => {
|
||||
};
|
||||
const stubs = ['b-modal']; // <b-modal> is a custom component and not tested here
|
||||
|
||||
return mount(TaskColumn, {
|
||||
propsData: {
|
||||
type,
|
||||
return shallowMount(TaskColumn, {
|
||||
propsData: { type },
|
||||
store: {
|
||||
getters: {
|
||||
'tasks:getFilteredTaskList': () => [],
|
||||
},
|
||||
},
|
||||
mocks,
|
||||
stubs,
|
||||
@@ -56,6 +55,9 @@ describe('Task Column', () => {
|
||||
});
|
||||
|
||||
describe('Computed Properties', () => {
|
||||
let taskListOverride;
|
||||
let habits;
|
||||
|
||||
beforeEach(() => {
|
||||
habits = [
|
||||
{ id: 1 },
|
||||
@@ -67,14 +69,14 @@ describe('Task Column', () => {
|
||||
{ id: 4 },
|
||||
];
|
||||
|
||||
getters = {
|
||||
const getters = {
|
||||
// (...) => { ... } will return a value
|
||||
// (...) => (...) => { ... } will return a function
|
||||
// Task Column expects a function
|
||||
'tasks:getFilteredTaskList': () => () => habits,
|
||||
};
|
||||
|
||||
store = new Store({ getters });
|
||||
const store = new Store({ getters });
|
||||
|
||||
wrapper = makeWrapper({ store });
|
||||
});
|
||||
@@ -103,6 +105,8 @@ describe('Task Column', () => {
|
||||
});
|
||||
|
||||
describe('Methods', () => {
|
||||
let tasks;
|
||||
|
||||
describe('Filter By Tags', () => {
|
||||
beforeEach(() => {
|
||||
tasks = [
|
||||
|
||||
@@ -6,6 +6,19 @@ const localVue = createLocalVue();
|
||||
localVue.use(Store);
|
||||
|
||||
describe('Tasks User', () => {
|
||||
function createWrapper (challengeTag) {
|
||||
const store = new Store({
|
||||
state: { user: { data: { tags: [challengeTag] } } },
|
||||
getters: {},
|
||||
});
|
||||
return shallowMount(User, {
|
||||
store,
|
||||
localVue,
|
||||
mocks: { $t: s => s },
|
||||
stubs: ['b-tooltip'],
|
||||
});
|
||||
}
|
||||
|
||||
describe('Computed Properties', () => {
|
||||
it('should render a challenge tag under challenge header in tag filter popup when the challenge is active', () => {
|
||||
const activeChallengeTag = {
|
||||
@@ -13,20 +26,7 @@ describe('Tasks User', () => {
|
||||
name: 'Challenge1',
|
||||
challenge: true,
|
||||
};
|
||||
const state = {
|
||||
user: {
|
||||
data: {
|
||||
tags: [activeChallengeTag],
|
||||
},
|
||||
},
|
||||
};
|
||||
const getters = {};
|
||||
const store = new Store({ state, getters });
|
||||
const wrapper = shallowMount(User, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
const wrapper = createWrapper(activeChallengeTag);
|
||||
const computedTagsByType = wrapper.vm.tagsByType;
|
||||
|
||||
expect(computedTagsByType.challenges.tags.length).to.equal(1);
|
||||
@@ -40,20 +40,7 @@ describe('Tasks User', () => {
|
||||
name: 'Challenge1',
|
||||
challenge: false,
|
||||
};
|
||||
const state = {
|
||||
user: {
|
||||
data: {
|
||||
tags: [inactiveChallengeTag],
|
||||
},
|
||||
},
|
||||
};
|
||||
const getters = {};
|
||||
const store = new Store({ state, getters });
|
||||
const wrapper = shallowMount(User, {
|
||||
store,
|
||||
localVue,
|
||||
});
|
||||
|
||||
const wrapper = createWrapper(inactiveChallengeTag);
|
||||
const computedTagsByType = wrapper.vm.tagsByType;
|
||||
|
||||
expect(computedTagsByType.challenges.tags.length).to.equal(0);
|
||||
|
||||
Reference in New Issue
Block a user