Reintroduce unit testing for the frontend
This commit is contained in:
parent
7dff941979
commit
8127bc10ba
|
@ -10,7 +10,7 @@
|
|||
"build:deployment": "vite build --base /front/",
|
||||
"serve": "vite preview",
|
||||
"test:unit": "vitest run --dom --coverage",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"lint": "eslint --ext .js,.vue src tests",
|
||||
"fix-fomantic-css": "scripts/fix-fomantic-css.sh",
|
||||
"i18n-compile": "scripts/i18n-compile.sh",
|
||||
"i18n-extract": "scripts/i18n-extract.sh",
|
||||
|
|
|
@ -3,8 +3,6 @@ import { mount } from '@vue/test-utils'
|
|||
|
||||
import Username from '@/components/common/Username.vue'
|
||||
|
||||
import { render } from '../../utils'
|
||||
|
||||
describe('Username', () => {
|
||||
it('displays username', () => {
|
||||
const wrapper = mount(Username, {
|
||||
|
@ -12,7 +10,6 @@ describe('Username', () => {
|
|||
username: 'Hello'
|
||||
}
|
||||
})
|
||||
const vm = render(Username, {username: 'Hello'})
|
||||
expect(wrapper.text()).to.equal('Hello')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,25 +6,25 @@ describe('filters', () => {
|
|||
describe('truncate', () => {
|
||||
it('leave strings as it if correct size', () => {
|
||||
const input = 'Hello world'
|
||||
let output = truncate(input, 100)
|
||||
const output = truncate(input, 100)
|
||||
expect(output).to.equal(input)
|
||||
})
|
||||
it('returns shorter string with character', () => {
|
||||
const input = 'Hello world'
|
||||
let output = truncate(input, 5)
|
||||
const output = truncate(input, 5)
|
||||
expect(output).to.equal('Hello…')
|
||||
})
|
||||
it('custom ellipsis', () => {
|
||||
const input = 'Hello world'
|
||||
let output = truncate(input, 5, ' pouet')
|
||||
const output = truncate(input, 5, ' pouet')
|
||||
expect(output).to.equal('Hello pouet')
|
||||
})
|
||||
})
|
||||
describe('ago', () => {
|
||||
it('works', () => {
|
||||
const input = new Date()
|
||||
let output = ago(input)
|
||||
let expected = moment(input).calendar(input, {
|
||||
const output = ago(input)
|
||||
const expected = moment(input).calendar(input, {
|
||||
sameDay: 'LT',
|
||||
nextDay: 'L',
|
||||
nextWeek: 'L',
|
||||
|
@ -38,14 +38,14 @@ describe('filters', () => {
|
|||
describe('year', () => {
|
||||
it('works', () => {
|
||||
const input = '2017-07-13'
|
||||
let output = year(input)
|
||||
const output = year(input)
|
||||
expect(output).to.equal(2017)
|
||||
})
|
||||
})
|
||||
describe('capitalize', () => {
|
||||
it('works', () => {
|
||||
const input = 'hello world'
|
||||
let output = capitalize(input)
|
||||
const output = capitalize(input)
|
||||
expect(output).to.equal('Hello world')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -5,61 +5,61 @@ import {normalizeQuery, parseTokens, compileTokens} from '@/search'
|
|||
describe('search', () => {
|
||||
it('normalizeQuery returns correct tokens', () => {
|
||||
const input = 'this is a "search query" yeah'
|
||||
let output = normalizeQuery(input)
|
||||
const output = normalizeQuery(input)
|
||||
expect(output).to.deep.equal(['this', 'is', 'a', 'search query', 'yeah'])
|
||||
})
|
||||
it('parseTokens can extract fields and values from tokens', () => {
|
||||
const input = ['unhandled', 'key:value', 'status:pending', 'title:"some title"', 'anotherunhandled']
|
||||
let output = parseTokens(input)
|
||||
let expected = [
|
||||
const output = parseTokens(input)
|
||||
const expected = [
|
||||
{
|
||||
'field': null,
|
||||
'value': 'unhandled'
|
||||
field: null,
|
||||
value: 'unhandled'
|
||||
},
|
||||
{
|
||||
'field': 'key',
|
||||
'value': 'value'
|
||||
field: 'key',
|
||||
value: 'value'
|
||||
},
|
||||
{
|
||||
'field': 'status',
|
||||
'value': 'pending',
|
||||
field: 'status',
|
||||
value: 'pending'
|
||||
},
|
||||
{
|
||||
'field': 'title',
|
||||
'value': 'some title'
|
||||
field: 'title',
|
||||
value: 'some title'
|
||||
},
|
||||
{
|
||||
'field': null,
|
||||
'value': 'anotherunhandled'
|
||||
field: null,
|
||||
value: 'anotherunhandled'
|
||||
}
|
||||
]
|
||||
expect(output).to.deep.equal(expected)
|
||||
})
|
||||
it('compileTokens returns proper query string', () => {
|
||||
let input = [
|
||||
const input = [
|
||||
{
|
||||
'field': null,
|
||||
'value': 'unhandled'
|
||||
field: null,
|
||||
value: 'unhandled'
|
||||
},
|
||||
{
|
||||
'field': 'key',
|
||||
'value': 'value'
|
||||
field: 'key',
|
||||
value: 'value'
|
||||
},
|
||||
{
|
||||
'field': 'status',
|
||||
'value': 'pending',
|
||||
field: 'status',
|
||||
value: 'pending'
|
||||
},
|
||||
{
|
||||
'field': 'title',
|
||||
'value': 'some title'
|
||||
field: 'title',
|
||||
value: 'some title'
|
||||
},
|
||||
{
|
||||
'field': null,
|
||||
'value': 'anotherunhandled'
|
||||
field: null,
|
||||
value: 'anotherunhandled'
|
||||
}
|
||||
]
|
||||
const expected = 'unhandled key:value status:pending title:"some title" anotherunhandled'
|
||||
let output = compileTokens(input)
|
||||
const output = compileTokens(input)
|
||||
expect(output).to.deep.equal(expected)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@ import store from '@/store/auth'
|
|||
import { testAction } from '../../utils'
|
||||
|
||||
describe('store/auth', () => {
|
||||
|
||||
describe('mutations', () => {
|
||||
it('profile', () => {
|
||||
const state = {}
|
||||
|
@ -42,7 +41,7 @@ describe('store/auth', () => {
|
|||
})
|
||||
it('token real', () => {
|
||||
const state = {}
|
||||
let token = 'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTUxNTUzMzQyOSwiZXhwIjoxNTE1NTM3MDI5LCJpYXQiOjE1MTU1MzM0MjksImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.'
|
||||
const token = 'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTUxNTUzMzQyOSwiZXhwIjoxNTE1NTM3MDI5LCJpYXQiOjE1MTU1MzM0MjksImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.'
|
||||
store.mutations.token(state, token)
|
||||
expect(state.token).to.equal(token)
|
||||
})
|
||||
|
@ -55,7 +54,7 @@ describe('store/auth', () => {
|
|||
describe('getters', () => {
|
||||
it('header', () => {
|
||||
const state = { oauth: { accessToken: 'helloworld' } }
|
||||
expect(store.getters['header'](state)).to.equal('Bearer helloworld')
|
||||
expect(store.getters.header(state)).to.equal('Bearer helloworld')
|
||||
})
|
||||
})
|
||||
describe('actions', () => {
|
||||
|
@ -79,10 +78,10 @@ describe('store/auth', () => {
|
|||
params: { state: {} },
|
||||
expectedMutations: [
|
||||
{ type: 'authenticated', payload: false },
|
||||
{ type: 'authenticated', payload: true },
|
||||
{ type: 'authenticated', payload: true }
|
||||
],
|
||||
expectedActions: [
|
||||
{ type: 'fetchProfile' },
|
||||
{ type: 'fetchProfile' }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
|
|
@ -22,11 +22,11 @@ describe('store/favorites', () => {
|
|||
describe('getters', () => {
|
||||
it('isFavorite true', () => {
|
||||
const state = { tracks: [1] }
|
||||
expect(store.getters['isFavorite'](state)(1)).to.equal(true)
|
||||
expect(store.getters.isFavorite(state)(1)).to.equal(true)
|
||||
})
|
||||
it('isFavorite false', () => {
|
||||
const state = { tracks: [] }
|
||||
expect(store.getters['isFavorite'](state)(1)).to.equal(false)
|
||||
expect(store.getters.isFavorite(state)(1)).to.equal(false)
|
||||
})
|
||||
})
|
||||
describe('actions', () => {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { describe, beforeEach, afterEach, it, expect } from 'vitest'
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import store from '@/store/instance'
|
||||
import { testAction } from '../../utils'
|
||||
|
||||
describe('store/instance', () => {
|
||||
|
||||
describe('mutations', () => {
|
||||
it('settings', () => {
|
||||
const state = { settings: { users: { upload_quota: { value: 1 } } } }
|
||||
let settings = {users: {registration_enabled: {value: true}}}
|
||||
const settings = { users: { registration_enabled: { value: true } } }
|
||||
store.mutations.settings(state, settings)
|
||||
expect(state.settings).to.deep.equal({
|
||||
users: { upload_quota: { value: 1 }, registration_enabled: { value: true } }
|
||||
|
|
|
@ -90,15 +90,15 @@ describe('store/player', () => {
|
|||
describe('getters', () => {
|
||||
it('durationFormatted', () => {
|
||||
const state = { duration: 12.51 }
|
||||
expect(store.getters['durationFormatted'](state)).to.equal('0:13')
|
||||
expect(store.getters.durationFormatted(state)).to.equal('0:13')
|
||||
})
|
||||
it('currentTimeFormatted', () => {
|
||||
const state = { currentTime: 12.51 }
|
||||
expect(store.getters['currentTimeFormatted'](state)).to.equal('0:13')
|
||||
expect(store.getters.currentTimeFormatted(state)).to.equal('0:13')
|
||||
})
|
||||
it('progress', () => {
|
||||
const state = { currentTime: 4, duration: 10 }
|
||||
expect(store.getters['progress'](state)).to.equal(40)
|
||||
expect(store.getters.progress(state)).to.equal(40)
|
||||
})
|
||||
})
|
||||
describe('actions', () => {
|
||||
|
@ -197,7 +197,7 @@ describe('store/player', () => {
|
|||
params: { state: { volume: 0.7, tempVolume: 0 } },
|
||||
expectedMutations: [
|
||||
{ type: 'tempVolume', payload: 0.7 },
|
||||
{ type: 'volume', payload: 0 },
|
||||
{ type: 'volume', payload: 0 }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
@ -206,7 +206,7 @@ describe('store/player', () => {
|
|||
action: store.actions.unmute,
|
||||
params: { state: { volume: 0, tempVolume: 0.8 } },
|
||||
expectedMutations: [
|
||||
{ type: 'volume', payload: 0.8 },
|
||||
{ type: 'volume', payload: 0.8 }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { describe, beforeEach, afterEach, it, expect } from 'vitest'
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import store from '@/store/playlists'
|
||||
|
||||
import { testAction } from '../../utils'
|
||||
|
||||
describe('store/playlists', () => {
|
||||
|
||||
describe('mutations', () => {
|
||||
it('set playlists', () => {
|
||||
const state = { playlists: [] }
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
import { it, describe, expect } from 'vitest'
|
||||
|
||||
import _ from 'lodash'
|
||||
|
||||
import store from '@/store/queue'
|
||||
import { testAction } from '../../utils'
|
||||
|
||||
describe('store/queue', () => {
|
||||
|
||||
describe('mutations', () => {
|
||||
it('currentIndex', () => {
|
||||
const state = {}
|
||||
|
@ -62,15 +59,15 @@ describe('store/queue', () => {
|
|||
describe('getters', () => {
|
||||
it('currentTrack', () => {
|
||||
const state = { tracks: [1, 2, 3], currentIndex: 2 }
|
||||
expect(store.getters['currentTrack'](state)).to.equal(3)
|
||||
expect(store.getters.currentTrack(state)).to.equal(3)
|
||||
})
|
||||
it('hasNext true', () => {
|
||||
const state = { tracks: [1, 2, 3], currentIndex: 1 }
|
||||
expect(store.getters['hasNext'](state)).to.equal(true)
|
||||
expect(store.getters.hasNext(state)).to.equal(true)
|
||||
})
|
||||
it('hasNext false', () => {
|
||||
const state = { tracks: [1, 2, 3], currentIndex: 2 }
|
||||
expect(store.getters['hasNext'](state)).to.equal(false)
|
||||
expect(store.getters.hasNext(state)).to.equal(false)
|
||||
})
|
||||
})
|
||||
describe('actions', () => {
|
||||
|
@ -102,7 +99,7 @@ describe('store/queue', () => {
|
|||
params: { state: { tracks: [] } },
|
||||
expectedActions: [
|
||||
{ type: 'append', payload: { track: tracks[0], index: 0 } },
|
||||
{ type: 'append', payload: {track: tracks[1], index: 1} },
|
||||
{ type: 'append', payload: { track: tracks[1], index: 1 } }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
@ -114,7 +111,7 @@ describe('store/queue', () => {
|
|||
params: { state: { tracks: [1, 2] } },
|
||||
expectedActions: [
|
||||
{ type: 'append', payload: { track: tracks[0], index: 1 } },
|
||||
{ type: 'append', payload: {track: tracks[1], index: 2} },
|
||||
{ type: 'append', payload: { track: tracks[1], index: 2 } }
|
||||
]
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { describe, beforeEach, it, afterEach, expect } from 'vitest'
|
||||
import { describe, it, expect } from 'vitest'
|
||||
|
||||
import store from '@/store/radios'
|
||||
import { testAction } from '../../utils'
|
||||
|
||||
describe('store/radios', () => {
|
||||
|
||||
describe('mutations', () => {
|
||||
it('current', () => {
|
||||
const state = {}
|
||||
|
|
|
@ -5,27 +5,27 @@ import {parseAPIErrors} from '@/utils'
|
|||
describe('utils', () => {
|
||||
describe('parseAPIErrors', () => {
|
||||
it('handles flat structure', () => {
|
||||
const input = {"old_password": ["Invalid password"]}
|
||||
let expected = ["Invalid password"]
|
||||
let output = parseAPIErrors(input)
|
||||
const input = { old_password: ['Invalid password'] }
|
||||
const expected = ['Invalid password']
|
||||
const output = parseAPIErrors(input)
|
||||
expect(output).to.deep.equal(expected)
|
||||
})
|
||||
it('handles flat structure with multiple errors per field', () => {
|
||||
const input = {"old_password": ["Invalid password", "Too short"]}
|
||||
let expected = ["Invalid password", "Too short"]
|
||||
let output = parseAPIErrors(input)
|
||||
const input = { old_password: ['Invalid password', 'Too short'] }
|
||||
const expected = ['Invalid password', 'Too short']
|
||||
const output = parseAPIErrors(input)
|
||||
expect(output).to.deep.equal(expected)
|
||||
})
|
||||
it('translate field name', () => {
|
||||
const input = {"old_password": ["This field is required"]}
|
||||
let expected = ["Old Password: This field is required"]
|
||||
let output = parseAPIErrors(input)
|
||||
const input = { old_password: ['This field is required'] }
|
||||
const expected = ['Old Password: This field is required']
|
||||
const output = parseAPIErrors(input)
|
||||
expect(output).to.deep.equal(expected)
|
||||
})
|
||||
it('handle nested fields', () => {
|
||||
const input = {"summary": {"text": ["Ensure this field has no more than 5000 characters."]}}
|
||||
let expected = ["Summary - Text: Ensure this field has no more than 5000 characters."]
|
||||
let output = parseAPIErrors(input)
|
||||
const input = { summary: { text: ['Ensure this field has no more than 5000 characters.'] } }
|
||||
const expected = ['Summary - Text: Ensure this field has no more than 5000 characters.']
|
||||
const output = parseAPIErrors(input)
|
||||
expect(output).to.deep.equal(expected)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
import { describe, beforeEach, afterEach, it, expect } from 'vitest'
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils'
|
||||
import AlbumDetail from '@/views/admin/library/AlbumDetail.vue'
|
||||
import GetTextPlugin from 'vue-gettext'
|
||||
|
||||
import HumanDate from '@/components/common/HumanDate.vue'
|
||||
import DangerousButton from '@/components/common/DangerousButton.vue'
|
||||
|
||||
describe('views/admin/library', () => {
|
||||
|
||||
let wrapper
|
||||
describe('Album details', () => {
|
||||
|
||||
it('displays default cover', async () => {
|
||||
const album = { cover: null, artist: { id: null }, title: "dummy" }
|
||||
const localVue = createLocalVue()
|
||||
localVue.directive('title', (() => null))
|
||||
localVue.directive('dropdown', (() => null))
|
||||
localVue.use(GetTextPlugin, { translations: {} })
|
||||
// overrides axios calls
|
||||
//sandbox.stub(AlbumDetail.methods, "fetchData").callsFake(() => null)
|
||||
//sandbox.stub(AlbumDetail.methods, "fetchStats").callsFake(() => null)
|
||||
wrapper = shallowMount(AlbumDetail, {
|
||||
localVue,
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isLoadingStats: false,
|
||||
object: album,
|
||||
stats: [],
|
||||
}
|
||||
},
|
||||
mocks: {
|
||||
$store: {
|
||||
state: { auth: { profile: null }, ui: { lastDate: null } }
|
||||
}
|
||||
},
|
||||
stubs: {
|
||||
'human-date': HumanDate,
|
||||
'dangerous-button': DangerousButton
|
||||
},
|
||||
computed: { labels: () => { return { statsWarning: null } } }
|
||||
})
|
||||
//expect(wrapper.find('img').attributes('src')).to.include("default-cover")
|
||||
})
|
||||
})
|
||||
})
|
|
@ -2,7 +2,6 @@
|
|||
import Vue from 'vue'
|
||||
import { expect } from 'chai'
|
||||
|
||||
|
||||
export const render = (Component, propsData) => {
|
||||
const Constructor = Vue.extend(Component)
|
||||
return new Constructor({ propsData: propsData }).$mount()
|
||||
|
@ -18,9 +17,6 @@ export const testAction = ({action, payload, params, expectedMutations, expected
|
|||
if (!expectedActions) {
|
||||
expectedActions = []
|
||||
}
|
||||
const isOver = () => {
|
||||
return mutationsCount >= expectedMutations.length && actionsCount >= expectedActions.length
|
||||
}
|
||||
// mock commit
|
||||
const commit = (type, payload) => {
|
||||
const mutation = expectedMutations[mutationsCount]
|
||||
|
@ -31,9 +27,6 @@ export const testAction = ({action, payload, params, expectedMutations, expected
|
|||
}
|
||||
|
||||
mutationsCount++
|
||||
if (isOver()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
// mock dispatch
|
||||
const dispatch = (type, payload, options) => {
|
||||
|
@ -49,12 +42,9 @@ export const testAction = ({action, payload, params, expectedMutations, expected
|
|||
expect(options).to.deep.equal(a.options)
|
||||
}
|
||||
actionsCount++
|
||||
if (isOver()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let end = function () {
|
||||
const end = function () {
|
||||
// check if no mutations should have been dispatched
|
||||
if (expectedMutations.length === 0) {
|
||||
expect(mutationsCount).to.equal(0)
|
||||
|
@ -62,12 +52,9 @@ export const testAction = ({action, payload, params, expectedMutations, expected
|
|||
if (expectedActions.length === 0) {
|
||||
expect(actionsCount).to.equal(0)
|
||||
}
|
||||
if (isOver()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
// call the action with mocked store and arguments
|
||||
let promise = action({ commit, dispatch, ...params }, payload)
|
||||
const promise = action({ commit, dispatch, ...params }, payload)
|
||||
if (promise) {
|
||||
promise.then(end)
|
||||
return promise
|
||||
|
|
Loading…
Reference in New Issue