kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
				
				
				
			Restores front tests using jest and vite
							rodzic
							
								
									8b0d4049d4
								
							
						
					
					
						commit
						f3d998c7e0
					
				| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
module.exports = {
 | 
			
		||||
  presets: [
 | 
			
		||||
    '@babel/preset-env',
 | 
			
		||||
  ],
 | 
			
		||||
  plugins: [
 | 
			
		||||
    '@babel/plugin-transform-runtime',
 | 
			
		||||
    function () {
 | 
			
		||||
      return {
 | 
			
		||||
        visitor: {
 | 
			
		||||
          MetaProperty(path) {
 | 
			
		||||
            path.replaceWithSourceString('process')
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  ],
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,7 @@
 | 
			
		|||
    "build": "vite build",
 | 
			
		||||
    "build:deployment": "vite build --base /front/",
 | 
			
		||||
    "serve": "vite preview",
 | 
			
		||||
    "test:unit": "true",
 | 
			
		||||
    "test:unit": "jest",
 | 
			
		||||
    "lint": "eslint --ext .js,.vue src",
 | 
			
		||||
    "fix-fomantic-css": "scripts/fix-fomantic-css.sh",
 | 
			
		||||
    "i18n-compile": "scripts/i18n-compile.sh",
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +45,14 @@
 | 
			
		|||
    "vuex-router-sync": "5.0.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@babel/core": "^7.17.5",
 | 
			
		||||
    "@babel/plugin-transform-runtime": "^7.17.0",
 | 
			
		||||
    "@babel/preset-env": "^7.16.11",
 | 
			
		||||
    "@vue/test-utils": "^1.0.0-beta.22",
 | 
			
		||||
    "autoprefixer": "10.4.4",
 | 
			
		||||
    "babel-core": "^7.0.0-bridge.0",
 | 
			
		||||
    "babel-jest": "^27.5.1",
 | 
			
		||||
    "chai": "^4.3.6",
 | 
			
		||||
    "easygettext": "2.17.0",
 | 
			
		||||
    "eslint": "8.11.0",
 | 
			
		||||
    "eslint-config-standard": "16.0.3",
 | 
			
		||||
| 
						 | 
				
			
			@ -55,8 +62,12 @@
 | 
			
		|||
    "eslint-plugin-promise": "6.0.0",
 | 
			
		||||
    "eslint-plugin-vue": "7.20.0",
 | 
			
		||||
    "glob-all": "3.3.0",
 | 
			
		||||
    "jest-cli": "^27.5.1",
 | 
			
		||||
    "moxios": "^0.4.0",
 | 
			
		||||
    "sinon": "^13.0.1",
 | 
			
		||||
    "vite": "2.8.6",
 | 
			
		||||
    "vite-plugin-vue2": "1.9.3",
 | 
			
		||||
    "vue-jest": "^3.0.7",
 | 
			
		||||
    "vue-template-compiler": "2.6.14"
 | 
			
		||||
  },
 | 
			
		||||
  "resolutions": {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,5 +120,20 @@
 | 
			
		|||
    "iOS >= 9",
 | 
			
		||||
    "Android >= 4",
 | 
			
		||||
    "not dead"
 | 
			
		||||
  ]
 | 
			
		||||
  ],
 | 
			
		||||
  "jest": {
 | 
			
		||||
    "moduleFileExtensions": [
 | 
			
		||||
      "js",
 | 
			
		||||
      "json",
 | 
			
		||||
      "vue"
 | 
			
		||||
    ],
 | 
			
		||||
    "transform": {
 | 
			
		||||
      ".*\\.(vue)$": "vue-jest",
 | 
			
		||||
      "^.+\\.js$": "babel-jest"
 | 
			
		||||
    },
 | 
			
		||||
    "moduleNameMapper": {
 | 
			
		||||
      "^@/(.*)$": "<rootDir>/src/$1"
 | 
			
		||||
    },
 | 
			
		||||
    "testEnvironment": "jsdom"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@ import Vue from 'vue'
 | 
			
		|||
import axios from 'axios'
 | 
			
		||||
import logger from '@/logging'
 | 
			
		||||
import lodash from 'lodash'
 | 
			
		||||
import router from '@/router'
 | 
			
		||||
 | 
			
		||||
function getDefaultScopedTokens () {
 | 
			
		||||
  return {
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +141,9 @@ export default {
 | 
			
		|||
        // commit('token', response.data.token)
 | 
			
		||||
        dispatch('fetchProfile').then(() => {
 | 
			
		||||
          // Redirect to a specified route
 | 
			
		||||
          return router.push(next)
 | 
			
		||||
          import('@/router').then((router) => {
 | 
			
		||||
            return router.default.push(next)
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
      }, response => {
 | 
			
		||||
        logger.default.error('Error while logging in', response.data)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
{
 | 
			
		||||
  "env": {
 | 
			
		||||
    "mocha": true
 | 
			
		||||
  },
 | 
			
		||||
  "globals": {
 | 
			
		||||
    "expect": true,
 | 
			
		||||
    "sinon": true
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
import { expect } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { toLinearVolumeScale, toLogarithmicVolumeScale } from '@/audio/volume'
 | 
			
		||||
 | 
			
		||||
describe('store/auth', () => {
 | 
			
		||||
    describe('toLinearVolumeScale', () => {
 | 
			
		||||
        it('it should return real 0', () => {
 | 
			
		||||
            expect(toLinearVolumeScale(0.0)).to.equal(0.0)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        it('it should return full volume', () => {
 | 
			
		||||
            expect(toLinearVolumeScale(1.0)).to.be.closeTo(1.0, 0.001)
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    describe('toLogarithmicVolumeScale', () => {
 | 
			
		||||
        it('it should return real 0', () => {
 | 
			
		||||
            expect(toLogarithmicVolumeScale(0.0)).to.equal(0.0)
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        it('it should return full volume', () => {
 | 
			
		||||
            expect(toLogarithmicVolumeScale(1.0)).to.be.closeTo(1.0, 0.001)
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
import Username from '@/components/common/Username.vue'
 | 
			
		||||
 | 
			
		||||
import { render } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('Username', () => {
 | 
			
		||||
  it('displays username', () => {
 | 
			
		||||
    const vm = render(Username, {username: 'Hello'})
 | 
			
		||||
    expect(vm.$el.textContent).to.equal('Hello')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
import { expect } from 'chai'
 | 
			
		||||
import PasswordInput from '@/components/forms/PasswordInput.vue'
 | 
			
		||||
import { shallowMount } from '@vue/test-utils'
 | 
			
		||||
const sinon = require('sinon')
 | 
			
		||||
 | 
			
		||||
describe('PasswordInput', () => {
 | 
			
		||||
  const password = 'password'
 | 
			
		||||
  let sandbox
 | 
			
		||||
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  afterEach(function () {
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
  })
 | 
			
		||||
  const wrapper = shallowMount(PasswordInput, {
 | 
			
		||||
    mocks: {
 | 
			
		||||
      $pgettext: () => 'dummy',
 | 
			
		||||
      $store: {
 | 
			
		||||
        commit: () => { }
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    propsData: {
 | 
			
		||||
      fieldId: 'password',
 | 
			
		||||
      value: password,
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
  wrapper.setProps({ value: password, copyButton: true })
 | 
			
		||||
  it('password input has passed value', () => {
 | 
			
		||||
    const inputElement = wrapper.find('input')
 | 
			
		||||
    expect(inputElement.element.value).to.equal(password)
 | 
			
		||||
  })
 | 
			
		||||
  it('copy password function called', () => {
 | 
			
		||||
    document.execCommand = jest.fn()
 | 
			
		||||
    const spy = sandbox.spy(wrapper.vm, 'copyPassword')     
 | 
			
		||||
    sandbox.stub(PasswordInput.methods, '_copyStringToClipboard').callsFake()
 | 
			
		||||
    const copyButton = wrapper.findAll('button').at(1)
 | 
			
		||||
    copyButton.trigger('click')
 | 
			
		||||
    sandbox.assert.calledOnce(spy)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
import moment from 'moment'
 | 
			
		||||
import {truncate, ago, capitalize, year} from '@/filters'
 | 
			
		||||
 | 
			
		||||
describe('filters', () => {
 | 
			
		||||
  describe('truncate', () => {
 | 
			
		||||
    it('leave strings as it if correct size', () => {
 | 
			
		||||
      const input = 'Hello world'
 | 
			
		||||
      let output = truncate(input, 100)
 | 
			
		||||
      expect(output).to.equal(input)
 | 
			
		||||
    })
 | 
			
		||||
    it('returns shorter string with character', () => {
 | 
			
		||||
      const input = 'Hello world'
 | 
			
		||||
      let output = truncate(input, 5)
 | 
			
		||||
      expect(output).to.equal('Hello…')
 | 
			
		||||
    })
 | 
			
		||||
    it('custom ellipsis', () => {
 | 
			
		||||
      const input = 'Hello world'
 | 
			
		||||
      let 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, {
 | 
			
		||||
        sameDay: 'LT',
 | 
			
		||||
        nextDay: 'L',
 | 
			
		||||
        nextWeek: 'L',
 | 
			
		||||
        lastDay: 'L',
 | 
			
		||||
        lastWeek: 'L',
 | 
			
		||||
        sameElse: 'L'
 | 
			
		||||
    })
 | 
			
		||||
      expect(output).to.equal(expected)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('year', () => {
 | 
			
		||||
    it('works', () => {
 | 
			
		||||
      const input = '2017-07-13'
 | 
			
		||||
      let output = year(input)
 | 
			
		||||
      expect(output).to.equal(2017)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('capitalize', () => {
 | 
			
		||||
    it('works', () => {
 | 
			
		||||
      const input = 'hello world'
 | 
			
		||||
      let output = capitalize(input)
 | 
			
		||||
      expect(output).to.equal('Hello world')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
    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 = [
 | 
			
		||||
      {
 | 
			
		||||
        'field': null,
 | 
			
		||||
        'value': 'unhandled'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': 'key',
 | 
			
		||||
        'value': 'value'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': 'status',
 | 
			
		||||
        'value': 'pending',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': 'title',
 | 
			
		||||
        'value': 'some title'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': null,
 | 
			
		||||
        'value': 'anotherunhandled'
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
    expect(output).to.deep.equal(expected)
 | 
			
		||||
  })
 | 
			
		||||
  it('compileTokens returns proper query string', () => {
 | 
			
		||||
    let input = [
 | 
			
		||||
      {
 | 
			
		||||
        'field': null,
 | 
			
		||||
        'value': 'unhandled'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': 'key',
 | 
			
		||||
        'value': 'value'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': 'status',
 | 
			
		||||
        'value': 'pending',
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': 'title',
 | 
			
		||||
        'value': 'some title'
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        'field': null,
 | 
			
		||||
        'value': 'anotherunhandled'
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
    const expected = 'unhandled key:value status:pending title:"some title" anotherunhandled'
 | 
			
		||||
    let output = compileTokens(input)
 | 
			
		||||
    expect(output).to.deep.equal(expected)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,174 @@
 | 
			
		|||
var sinon = require('sinon')
 | 
			
		||||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
import moxios from 'moxios'
 | 
			
		||||
import store from '@/store/auth'
 | 
			
		||||
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/auth', () => {
 | 
			
		||||
  var sandbox
 | 
			
		||||
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
    moxios.install()
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(function () {
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
    moxios.uninstall()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('profile', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.profile(state, {})
 | 
			
		||||
      expect(state.profile).to.deep.equal({})
 | 
			
		||||
    })
 | 
			
		||||
    it('username', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.username(state, 'world')
 | 
			
		||||
      expect(state.username).to.equal('world')
 | 
			
		||||
    })
 | 
			
		||||
    it('authenticated true', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.authenticated(state, true)
 | 
			
		||||
      expect(state.authenticated).to.equal(true)
 | 
			
		||||
    })
 | 
			
		||||
    it('authenticated false', () => {
 | 
			
		||||
      const state = {
 | 
			
		||||
        username: 'dummy',
 | 
			
		||||
        token: 'dummy',
 | 
			
		||||
        profile: 'dummy',
 | 
			
		||||
        availablePermissions: 'dummy'
 | 
			
		||||
      }
 | 
			
		||||
      store.mutations.authenticated(state, false)
 | 
			
		||||
      expect(state.authenticated).to.equal(false)
 | 
			
		||||
      expect(state.username).to.equal(null)
 | 
			
		||||
      expect(state.token).to.equal(null)
 | 
			
		||||
      expect(state.profile).to.equal(null)
 | 
			
		||||
      expect(state.availablePermissions).to.deep.equal({})
 | 
			
		||||
    })
 | 
			
		||||
    it('token null', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.token(state, null)
 | 
			
		||||
      expect(state.token).to.equal(null)
 | 
			
		||||
    })
 | 
			
		||||
    it('token real', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      let token = 'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpc3MiOiJodHRwczovL2p3dC1pZHAuZXhhbXBsZS5jb20iLCJzdWIiOiJtYWlsdG86bWlrZUBleGFtcGxlLmNvbSIsIm5iZiI6MTUxNTUzMzQyOSwiZXhwIjoxNTE1NTM3MDI5LCJpYXQiOjE1MTU1MzM0MjksImp0aSI6ImlkMTIzNDU2IiwidHlwIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9yZWdpc3RlciJ9.'
 | 
			
		||||
      store.mutations.token(state, token)
 | 
			
		||||
      expect(state.token).to.equal(token)
 | 
			
		||||
    })
 | 
			
		||||
    it('permissions', () => {
 | 
			
		||||
      const state = { availablePermissions: {} }
 | 
			
		||||
      store.mutations.permission(state, {key: 'admin', status: true})
 | 
			
		||||
      expect(state.availablePermissions).to.deep.equal({admin: true})
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('getters', () => {
 | 
			
		||||
    it('header', () => {
 | 
			
		||||
      const state = { oauth: {accessToken: 'helloworld' }}
 | 
			
		||||
      expect(store.getters['header'](state)).to.equal('Bearer helloworld')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('logout', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.logout,
 | 
			
		||||
        params: {state: {}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'auth/reset', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'favorites/reset', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'player/reset', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'playlists/reset', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'queue/reset', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'radios/reset', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('check jwt null', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.check,
 | 
			
		||||
        params: {state: {}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'authenticated', payload: false },
 | 
			
		||||
          { type: 'authenticated', payload: true },
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'fetchProfile' },
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('login success', () => {
 | 
			
		||||
      moxios.stubRequest('token/', {
 | 
			
		||||
        status: 200,
 | 
			
		||||
        response: {
 | 
			
		||||
          token: 'test'
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      const credentials = {
 | 
			
		||||
        username: 'bob'
 | 
			
		||||
      }
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.login,
 | 
			
		||||
        payload: {credentials: credentials},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'token', payload: 'test' }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'fetchProfile' }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('login error', () => {
 | 
			
		||||
      moxios.stubRequest('token/', {
 | 
			
		||||
        status: 500,
 | 
			
		||||
        response: {
 | 
			
		||||
          token: 'test'
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      const credentials = {
 | 
			
		||||
        username: 'bob'
 | 
			
		||||
      }
 | 
			
		||||
      let spy = sandbox.spy()
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.login,
 | 
			
		||||
        payload: {credentials: credentials, onError: spy}
 | 
			
		||||
      }, () => {
 | 
			
		||||
        expect(spy.calledOnce).to.equal(true)
 | 
			
		||||
        done() // eslint-disable-line no-undef
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('fetchProfile', () => {
 | 
			
		||||
      const profile = {
 | 
			
		||||
        username: 'bob',
 | 
			
		||||
        permissions: {
 | 
			
		||||
          admin: true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      moxios.stubRequest('users/me/', {
 | 
			
		||||
        status: 200,
 | 
			
		||||
        response: profile
 | 
			
		||||
      })
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.fetchProfile,
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'authenticated', payload: true },
 | 
			
		||||
          { type: 'profile', payload: profile },
 | 
			
		||||
          { type: 'username', payload: profile.username },
 | 
			
		||||
          { type: 'permission', payload: {key: 'admin', status: true} }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'ui/initSettings', payload: { root: true } },
 | 
			
		||||
          { type: 'updateProfile', payload: profile },
 | 
			
		||||
          { type: 'ui/fetchUnreadNotifications', payload: null },
 | 
			
		||||
          { type: 'favorites/fetch', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'channels/fetchSubscriptions', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'libraries/fetchFollows', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'moderation/fetchContentFilters', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'playlists/fetchOwn', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
import store from '@/store/favorites'
 | 
			
		||||
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/favorites', () => {
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('track true', () => {
 | 
			
		||||
      const state = { tracks: [] }
 | 
			
		||||
      store.mutations.track(state, {id: 1, value: true})
 | 
			
		||||
      expect(state.tracks).to.deep.equal([1])
 | 
			
		||||
      expect(state.count).to.deep.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
    it('track false', () => {
 | 
			
		||||
      const state = { tracks: [1] }
 | 
			
		||||
      store.mutations.track(state, {id: 1, value: false})
 | 
			
		||||
      expect(state.tracks).to.deep.equal([])
 | 
			
		||||
      expect(state.count).to.deep.equal(0)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('getters', () => {
 | 
			
		||||
    it('isFavorite true', () => {
 | 
			
		||||
      const state = { tracks: [1] }
 | 
			
		||||
      expect(store.getters['isFavorite'](state)(1)).to.equal(true)
 | 
			
		||||
    })
 | 
			
		||||
    it('isFavorite false', () => {
 | 
			
		||||
      const state = { tracks: [] }
 | 
			
		||||
      expect(store.getters['isFavorite'](state)(1)).to.equal(false)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('toggle true', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.toggle,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        params: {getters: {isFavorite: () => false}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'set', payload: {id: 1, value: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('toggle true', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.toggle,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        params: {getters: {isFavorite: () => true}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'set', payload: {id: 1, value: false} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
var sinon = require('sinon')
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
import moxios from 'moxios'
 | 
			
		||||
import store from '@/store/instance'
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/instance', () => {
 | 
			
		||||
  var sandbox
 | 
			
		||||
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
    moxios.install()
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(function () {
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
    moxios.uninstall()
 | 
			
		||||
    axios.defaults.baseURL = null
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('settings', () => {
 | 
			
		||||
      const state = {settings: {users: {upload_quota: {value: 1}}}}
 | 
			
		||||
      let 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}}
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('instanceUrl', () => {
 | 
			
		||||
      const state = {instanceUrl: null, knownInstances: ['http://test2/', 'http://test/']}
 | 
			
		||||
      store.mutations.instanceUrl(state, 'http://test')
 | 
			
		||||
      expect(state).to.deep.equal({
 | 
			
		||||
        instanceUrl: 'http://test/',  // trailing slash added
 | 
			
		||||
        knownInstances: ['http://test/', 'http://test2/']
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('fetchSettings', () => {
 | 
			
		||||
      moxios.stubRequest('instance/settings/', {
 | 
			
		||||
        status: 200,
 | 
			
		||||
        response: [
 | 
			
		||||
          {
 | 
			
		||||
            section: 'users',
 | 
			
		||||
            name: 'upload_quota',
 | 
			
		||||
            value: 1
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            section: 'users',
 | 
			
		||||
            name: 'registration_enabled',
 | 
			
		||||
            value: false
 | 
			
		||||
          }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.fetchSettings,
 | 
			
		||||
        payload: null,
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          {
 | 
			
		||||
            type: 'settings',
 | 
			
		||||
            payload: {
 | 
			
		||||
              users: {
 | 
			
		||||
                upload_quota: {
 | 
			
		||||
                  section: 'users',
 | 
			
		||||
                  name: 'upload_quota',
 | 
			
		||||
                  value: 1
 | 
			
		||||
                },
 | 
			
		||||
                registration_enabled: {
 | 
			
		||||
                  section: 'users',
 | 
			
		||||
                  name: 'registration_enabled',
 | 
			
		||||
                  value: false
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,214 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
import store from '@/store/player'
 | 
			
		||||
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/player', () => {
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('set volume', () => {
 | 
			
		||||
      const state = { volume: 0 }
 | 
			
		||||
      store.mutations.volume(state, 0.9)
 | 
			
		||||
      expect(state.volume).to.equal(0.9)
 | 
			
		||||
    })
 | 
			
		||||
    it('set volume max 1', () => {
 | 
			
		||||
      const state = { volume: 0 }
 | 
			
		||||
      store.mutations.volume(state, 2)
 | 
			
		||||
      expect(state.volume).to.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
    it('set volume min to 0', () => {
 | 
			
		||||
      const state = { volume: 0.5 }
 | 
			
		||||
      store.mutations.volume(state, -2)
 | 
			
		||||
      expect(state.volume).to.equal(0)
 | 
			
		||||
    })
 | 
			
		||||
    it('increment volume', () => {
 | 
			
		||||
      const state = { volume: 0 }
 | 
			
		||||
      store.mutations.incrementVolume(state, 0.1)
 | 
			
		||||
      expect(state.volume).to.equal(0.1)
 | 
			
		||||
    })
 | 
			
		||||
    it('increment volume max 1', () => {
 | 
			
		||||
      const state = { volume: 0 }
 | 
			
		||||
      store.mutations.incrementVolume(state, 2)
 | 
			
		||||
      expect(state.volume).to.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
    it('increment volume min to 0', () => {
 | 
			
		||||
      const state = { volume: 0.5 }
 | 
			
		||||
      store.mutations.incrementVolume(state, -2)
 | 
			
		||||
      expect(state.volume).to.equal(0)
 | 
			
		||||
    })
 | 
			
		||||
    it('set duration', () => {
 | 
			
		||||
      const state = { duration: 42 }
 | 
			
		||||
      store.mutations.duration(state, 14)
 | 
			
		||||
      expect(state.duration).to.equal(14)
 | 
			
		||||
    })
 | 
			
		||||
    it('set errored', () => {
 | 
			
		||||
      const state = { errored: false }
 | 
			
		||||
      store.mutations.errored(state, true)
 | 
			
		||||
      expect(state.errored).to.equal(true)
 | 
			
		||||
    })
 | 
			
		||||
    it('set looping', () => {
 | 
			
		||||
      const state = { looping: 1 }
 | 
			
		||||
      store.mutations.looping(state, 2)
 | 
			
		||||
      expect(state.looping).to.equal(2)
 | 
			
		||||
    })
 | 
			
		||||
    it('set playing', () => {
 | 
			
		||||
      const state = { playing: false }
 | 
			
		||||
      store.mutations.playing(state, true)
 | 
			
		||||
      expect(state.playing).to.equal(true)
 | 
			
		||||
    })
 | 
			
		||||
    it('set current time', () => {
 | 
			
		||||
      const state = { currentTime: 1 }
 | 
			
		||||
      store.mutations.currentTime(state, 2)
 | 
			
		||||
      expect(state.currentTime).to.equal(2)
 | 
			
		||||
    })
 | 
			
		||||
    it('toggle looping from 0', () => {
 | 
			
		||||
      const state = { looping: 0 }
 | 
			
		||||
      store.mutations.toggleLooping(state)
 | 
			
		||||
      expect(state.looping).to.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
    it('toggle looping from 1', () => {
 | 
			
		||||
      const state = { looping: 1 }
 | 
			
		||||
      store.mutations.toggleLooping(state)
 | 
			
		||||
      expect(state.looping).to.equal(2)
 | 
			
		||||
    })
 | 
			
		||||
    it('toggle looping from 2', () => {
 | 
			
		||||
      const state = { looping: 2 }
 | 
			
		||||
      store.mutations.toggleLooping(state)
 | 
			
		||||
      expect(state.looping).to.equal(0)
 | 
			
		||||
    })
 | 
			
		||||
    it('increment error count', () => {
 | 
			
		||||
      const state = { errorCount: 0 }
 | 
			
		||||
      store.mutations.incrementErrorCount(state)
 | 
			
		||||
      expect(state.errorCount).to.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
    it('reset error count', () => {
 | 
			
		||||
      const state = { errorCount: 10 }
 | 
			
		||||
      store.mutations.resetErrorCount(state)
 | 
			
		||||
      expect(state.errorCount).to.equal(0)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('getters', () => {
 | 
			
		||||
    it('durationFormatted', () => {
 | 
			
		||||
      const state = { duration: 12.51 }
 | 
			
		||||
      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')
 | 
			
		||||
    })
 | 
			
		||||
    it('progress', () => {
 | 
			
		||||
      const state = { currentTime: 4, duration: 10 }
 | 
			
		||||
      expect(store.getters['progress'](state)).to.equal(40)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('incrementVolume', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.incrementVolume,
 | 
			
		||||
        payload: 0.2,
 | 
			
		||||
        params: {state: {volume: 0.7}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'volume', payload: 0.7 + 0.2 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('toggle playback false', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.togglePlayback,
 | 
			
		||||
        params: {state: {playing: false}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'playing', payload: true }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('toggle playback true', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.togglePlayback,
 | 
			
		||||
        params: {state: {playing: true}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'playing', payload: false }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('resume playback', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.resumePlayback,
 | 
			
		||||
        params: {state: {}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'playing', payload: true }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('pause playback', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.pausePlayback,
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'playing', payload: false }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('trackEnded', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.trackEnded,
 | 
			
		||||
        payload: {test: 'track'},
 | 
			
		||||
        params: {rootState: {queue: {currentIndex: 0, tracks: [1, 2]}}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'queue/next', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('trackEnded calls populateQueue if last', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.trackEnded,
 | 
			
		||||
        payload: {test: 'track'},
 | 
			
		||||
        params: {rootState: {queue: {currentIndex: 1, tracks: [1, 2]}}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'radios/populateQueue', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'queue/next', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('trackErrored', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.trackErrored,
 | 
			
		||||
        payload: {test: 'track'},
 | 
			
		||||
        params: {state: {errorCount: 0, maxConsecutiveErrors: 5}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'errored', payload: true },
 | 
			
		||||
          { type: 'incrementErrorCount' }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'queue/next', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('updateProgress', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.updateProgress,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'currentTime', payload: 1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('mute', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.mute,
 | 
			
		||||
        params: {state: { volume: 0.7, tempVolume: 0}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'tempVolume', payload: 0.7 },
 | 
			
		||||
          { type: 'volume', payload: 0 },
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('unmute', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.unmute,
 | 
			
		||||
        params: {state: { volume: 0, tempVolume: 0.8}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'volume', payload: 0.8 },
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
var sinon = require('sinon')
 | 
			
		||||
import moxios from 'moxios'
 | 
			
		||||
import store from '@/store/playlists'
 | 
			
		||||
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/playlists', () => {
 | 
			
		||||
  var sandbox
 | 
			
		||||
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
    moxios.install()
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(function () {
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
    moxios.uninstall()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('set playlists', () => {
 | 
			
		||||
      const state = { playlists: [] }
 | 
			
		||||
      store.mutations.playlists(state, [{id: 1, name: 'test'}])
 | 
			
		||||
      expect(state.playlists).to.deep.equal([{id: 1, name: 'test'}])
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('fetchOwn does nothing with no user', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.fetchOwn,
 | 
			
		||||
        payload: null,
 | 
			
		||||
        params: {state: { playlists: [] }, rootState: {auth: {profile: {}}}},
 | 
			
		||||
        expectedMutations: []
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,306 @@
 | 
			
		|||
var sinon = require('sinon')
 | 
			
		||||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
 | 
			
		||||
import store from '@/store/queue'
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/queue', () => {
 | 
			
		||||
  var sandbox
 | 
			
		||||
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    // Create a sandbox for the test
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  afterEach(function () {
 | 
			
		||||
    // Restore all the things made through the sandbox
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
  })
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('currentIndex', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.currentIndex(state, 2)
 | 
			
		||||
      expect(state.currentIndex).to.equal(2)
 | 
			
		||||
    })
 | 
			
		||||
    it('ended', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.ended(state, false)
 | 
			
		||||
      expect(state.ended).to.equal(false)
 | 
			
		||||
    })
 | 
			
		||||
    it('tracks', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.tracks(state, [1, 2])
 | 
			
		||||
      expect(state.tracks).to.deep.equal([1, 2])
 | 
			
		||||
    })
 | 
			
		||||
    it('splice', () => {
 | 
			
		||||
      const state = {tracks: [1, 2, 3]}
 | 
			
		||||
      store.mutations.splice(state, {start: 1, size: 2})
 | 
			
		||||
      expect(state.tracks).to.deep.equal([1])
 | 
			
		||||
    })
 | 
			
		||||
    it('insert', () => {
 | 
			
		||||
      const state = {tracks: [1, 3]}
 | 
			
		||||
      store.mutations.insert(state, {track: 2, index: 1})
 | 
			
		||||
      expect(state.tracks).to.deep.equal([1, 2, 3])
 | 
			
		||||
    })
 | 
			
		||||
    it('reorder before', () => {
 | 
			
		||||
      const state = {currentIndex: 3}
 | 
			
		||||
      store.mutations.reorder(state, {oldIndex: 2, newIndex: 1})
 | 
			
		||||
      expect(state.currentIndex).to.equal(3)
 | 
			
		||||
    })
 | 
			
		||||
    it('reorder from after to before', () => {
 | 
			
		||||
      const state = {currentIndex: 3}
 | 
			
		||||
      store.mutations.reorder(state, {oldIndex: 4, newIndex: 1})
 | 
			
		||||
      expect(state.currentIndex).to.equal(4)
 | 
			
		||||
    })
 | 
			
		||||
    it('reorder after', () => {
 | 
			
		||||
      const state = {currentIndex: 3}
 | 
			
		||||
      store.mutations.reorder(state, {oldIndex: 4, newIndex: 5})
 | 
			
		||||
      expect(state.currentIndex).to.equal(3)
 | 
			
		||||
    })
 | 
			
		||||
    it('reorder before to after', () => {
 | 
			
		||||
      const state = {currentIndex: 3}
 | 
			
		||||
      store.mutations.reorder(state, {oldIndex: 1, newIndex: 5})
 | 
			
		||||
      expect(state.currentIndex).to.equal(2)
 | 
			
		||||
    })
 | 
			
		||||
    it('reorder current', () => {
 | 
			
		||||
      const state = {currentIndex: 3}
 | 
			
		||||
      store.mutations.reorder(state, {oldIndex: 3, newIndex: 1})
 | 
			
		||||
      expect(state.currentIndex).to.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('getters', () => {
 | 
			
		||||
    it('currentTrack', () => {
 | 
			
		||||
      const state = { tracks: [1, 2, 3], currentIndex: 2 }
 | 
			
		||||
      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)
 | 
			
		||||
    })
 | 
			
		||||
    it('hasNext false', () => {
 | 
			
		||||
      const state = { tracks: [1, 2, 3], currentIndex: 2 }
 | 
			
		||||
      expect(store.getters['hasNext'](state)).to.equal(false)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('append at end', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.append,
 | 
			
		||||
        payload: {track: 4},
 | 
			
		||||
        params: {state: {tracks: [1, 2, 3]}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'insert', payload: {track: 4, index: 3} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('append at index', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.append,
 | 
			
		||||
        payload: {track: 2, index: 1},
 | 
			
		||||
        params: {state: {tracks: [1, 3]}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'insert', payload: {track: 2, index: 1} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('appendMany', () => {
 | 
			
		||||
      const tracks = [{title: 1}, {title: 2}]
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.appendMany,
 | 
			
		||||
        payload: {tracks: tracks},
 | 
			
		||||
        params: {state: {tracks: []}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'append', payload: {track: tracks[0], index: 0} },
 | 
			
		||||
          { type: 'append', payload: {track: tracks[1], index: 1} },
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('appendMany at index', () => {
 | 
			
		||||
      const tracks = [{title: 1}, {title: 2}]
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.appendMany,
 | 
			
		||||
        payload: {tracks: tracks, index: 1},
 | 
			
		||||
        params: {state: {tracks: [1, 2]}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'append', payload: {track: tracks[0], index: 1} },
 | 
			
		||||
          { type: 'append', payload: {track: tracks[1], index: 2} },
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('cleanTrack after current', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.cleanTrack,
 | 
			
		||||
        payload: 3,
 | 
			
		||||
        params: {state: {currentIndex: 2, tracks: [1, 2, 3, 4, 5]}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'splice', payload: {start: 3, size: 1} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('cleanTrack before current', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.cleanTrack,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        params: {state: {currentIndex: 2, tracks: []}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'splice', payload: {start: 1, size: 1} },
 | 
			
		||||
          { type: 'currentIndex', payload: 1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('cleanTrack current', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.cleanTrack,
 | 
			
		||||
        payload: 2,
 | 
			
		||||
        params: {state: {currentIndex: 2, tracks: []}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'splice', payload: {start: 2, size: 1} },
 | 
			
		||||
          { type: 'currentIndex', payload: 2 }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'player/stop', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('cleanTrack current is last', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.cleanTrack,
 | 
			
		||||
        payload: 5,
 | 
			
		||||
        params: { state: { currentIndex: 5, tracks: [1, 2, 3, 4, 5] } },
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'splice', payload: { start: 5, size: 1 } },
 | 
			
		||||
          { type: 'currentIndex', payload: 4 }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'player/stop', payload: null, options: { root: true } }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('previous when at beginning', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.previous,
 | 
			
		||||
        params: {state: {currentIndex: 0}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'currentIndex', payload: 0 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('previous after less than 3 seconds of playback', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.previous,
 | 
			
		||||
        params: {state: {currentIndex: 1}, rootState: {player: {currentTime: 1}}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'currentIndex', payload: 0 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('previous after more than 3 seconds of playback', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.previous,
 | 
			
		||||
        params: {state: {currentIndex: 1}, rootState: {player: {currentTime: 3}}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'currentIndex', payload: 1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('next on last track when looping on queue', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.next,
 | 
			
		||||
        params: {state: {tracks: [1, 2], currentIndex: 1}, rootState: {player: {looping: 2}}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'currentIndex', payload: 0 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('next track when last track', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.next,
 | 
			
		||||
        params: {state: {tracks: [1, 2], currentIndex: 1}, rootState: {player: {looping: 0}}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'ended', payload: true }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('next track when not last track', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.next,
 | 
			
		||||
        params: {state: {tracks: [1, 2], currentIndex: 0}, rootState: {player: {looping: 0}}},
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'currentIndex', payload: 1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('currentIndex', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.currentIndex,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        params: {state: {tracks: [1, 2], currentIndex: 0}, rootState: {radios: {running: false}}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'ended', payload: false },
 | 
			
		||||
          { type: 'player/currentTime', payload: 0, options: {root: true} },
 | 
			
		||||
          { type: 'currentIndex', payload: 1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('currentIndex with radio and many tracks remaining', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.currentIndex,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        params: {state: {tracks: [1, 2, 3, 4], currentIndex: 0}, rootState: {radios: {running: true}}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'ended', payload: false },
 | 
			
		||||
          { type: 'player/currentTime', payload: 0, options: {root: true} },
 | 
			
		||||
          { type: 'currentIndex', payload: 1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('currentIndex with radio and less than two tracks remaining', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.currentIndex,
 | 
			
		||||
        payload: 1,
 | 
			
		||||
        params: {state: {tracks: [1, 2, 3], currentIndex: 0}, rootState: {radios: {running: true}}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'ended', payload: false },
 | 
			
		||||
          { type: 'player/currentTime', payload: 0, options: {root: true} },
 | 
			
		||||
          { type: 'currentIndex', payload: 1 }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'radios/populateQueue', payload: null, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('clean', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.clean,
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'tracks', payload: [] },
 | 
			
		||||
          { type: 'ended', payload: true }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'radios/stop', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'player/stop', payload: null, options: {root: true} },
 | 
			
		||||
          { type: 'currentIndex', payload: -1 }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('shuffle', () => {
 | 
			
		||||
      let _shuffle = sandbox.stub(_, 'shuffle')
 | 
			
		||||
      let tracks = ['a', 'b', 'c', 'd', 'e']
 | 
			
		||||
      let shuffledTracks = ['a', 'b', 'e', 'd', 'c']
 | 
			
		||||
      _shuffle.returns(shuffledTracks)
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.shuffle,
 | 
			
		||||
        params: {state: {currentIndex: 1, tracks: tracks}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'tracks', payload: [] }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'appendMany', payload: {tracks: shuffledTracks} },
 | 
			
		||||
          { type: 'currentIndex', payload: {tracks: shuffledTracks} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
var sinon = require('sinon')
 | 
			
		||||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
import moxios from 'moxios'
 | 
			
		||||
import store from '@/store/radios'
 | 
			
		||||
import { testAction } from '../../utils'
 | 
			
		||||
 | 
			
		||||
describe('store/radios', () => {
 | 
			
		||||
  var sandbox
 | 
			
		||||
 | 
			
		||||
  beforeEach(function () {
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
    moxios.install()
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(function () {
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
    moxios.uninstall()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('mutations', () => {
 | 
			
		||||
    it('current', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.current(state, 1)
 | 
			
		||||
      expect(state.current).to.equal(1)
 | 
			
		||||
    })
 | 
			
		||||
    it('running', () => {
 | 
			
		||||
      const state = {}
 | 
			
		||||
      store.mutations.running(state, false)
 | 
			
		||||
      expect(state.running).to.equal(false)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
  describe('actions', () => {
 | 
			
		||||
    it('start', () => {
 | 
			
		||||
      moxios.stubRequest('radios/sessions/', {
 | 
			
		||||
        status: 200,
 | 
			
		||||
        response: {id: 2}
 | 
			
		||||
      })
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.start,
 | 
			
		||||
        payload: {type: 'favorites', objectId: 0, customRadioId: null},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          {
 | 
			
		||||
            type: 'current',
 | 
			
		||||
            payload: {
 | 
			
		||||
              type: 'favorites',
 | 
			
		||||
              objectId: 0,
 | 
			
		||||
              customRadioId: null,
 | 
			
		||||
              session: 2
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          { type: 'running', payload: true }
 | 
			
		||||
        ],
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'populateQueue', payload: true }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('stop', () => {
 | 
			
		||||
      return testAction({
 | 
			
		||||
        action: store.actions.stop,
 | 
			
		||||
        params: {state: {}},
 | 
			
		||||
        expectedMutations: [
 | 
			
		||||
          { type: 'current', payload: null },
 | 
			
		||||
          { type: 'running', payload: false }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('populateQueue', () => {
 | 
			
		||||
      moxios.stubRequest('radios/tracks/', {
 | 
			
		||||
        status: 201,
 | 
			
		||||
        response: {track: {id: 1}}
 | 
			
		||||
      })
 | 
			
		||||
      return testAction({
 | 
			
		||||
        action: store.actions.populateQueue,
 | 
			
		||||
        params: {
 | 
			
		||||
          state: {running: true, current: {session: 1}},
 | 
			
		||||
          rootState: {player: {errorCount: 0, maxConsecutiveErrors: 5}}
 | 
			
		||||
 | 
			
		||||
        },
 | 
			
		||||
        expectedActions: [
 | 
			
		||||
          { type: 'queue/append', payload: {track: {id: 1}}, options: {root: true} }
 | 
			
		||||
        ]
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('populateQueue does nothing when not running', () => {
 | 
			
		||||
      testAction({
 | 
			
		||||
        action: store.actions.populateQueue,
 | 
			
		||||
        params: {state: {running: false}},
 | 
			
		||||
        expectedActions: []
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    it('populateQueue does nothing when too much errors', () => {
 | 
			
		||||
      return testAction({
 | 
			
		||||
        action: store.actions.populateQueue,
 | 
			
		||||
        payload: {test: 'track'},
 | 
			
		||||
        params: {
 | 
			
		||||
          rootState: {player: {errorCount: 5, maxConsecutiveErrors: 5}},
 | 
			
		||||
          state: {running: true}
 | 
			
		||||
        },
 | 
			
		||||
        expectedActions: []
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
      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)
 | 
			
		||||
      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)
 | 
			
		||||
      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)
 | 
			
		||||
      expect(output).to.deep.equal(expected)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
const sinon = require('sinon')
 | 
			
		||||
import { expect } from 'chai'
 | 
			
		||||
import { shallowMount, createLocalVue, RouterLinkStub } 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
 | 
			
		||||
  let sandbox
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    sandbox = sinon.createSandbox()
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(() => {
 | 
			
		||||
    sandbox.restore()
 | 
			
		||||
  })
 | 
			
		||||
  describe('Album details', () => {
 | 
			
		||||
 | 
			
		||||
    it('displays default cover', async () => {
 | 
			
		||||
      const album = { cover: null, artist: { id: 1 }, title: "dummy", id: 1, creation_date: "2020-01-01" }
 | 
			
		||||
      const localVue = createLocalVue()
 | 
			
		||||
      localVue.directive('title', (() => null))
 | 
			
		||||
      localVue.directive('dropdown', (() => null))
 | 
			
		||||
      localVue.use(GetTextPlugin, { translations: {} })
 | 
			
		||||
      localVue.filter('truncate', () => null)
 | 
			
		||||
      localVue.filter('humanSize', () => null)
 | 
			
		||||
      localVue.filter('ago', () => null)
 | 
			
		||||
      localVue.filter('moment', () => null)
 | 
			
		||||
      // 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,
 | 
			
		||||
          'router-link': RouterLinkStub
 | 
			
		||||
        },
 | 
			
		||||
        propsData: {
 | 
			
		||||
          id: 1          
 | 
			
		||||
        },
 | 
			
		||||
        computed: { labels: () => { return { statsWarning: null } } }
 | 
			
		||||
      })
 | 
			
		||||
      expect(wrapper.find('img').attributes('src')).to.include("default-cover")
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
// helper for testing action with expected mutations
 | 
			
		||||
import Vue from 'vue'
 | 
			
		||||
import {expect} from 'chai'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export const render = (Component, propsData) => {
 | 
			
		||||
  const Constructor = Vue.extend(Component)
 | 
			
		||||
  return new Constructor({ propsData: propsData }).$mount()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const testAction = ({action, payload, params, expectedMutations, expectedActions}, done) => {
 | 
			
		||||
  let mutationsCount = 0
 | 
			
		||||
  let actionsCount = 0
 | 
			
		||||
 | 
			
		||||
  if (!expectedMutations) {
 | 
			
		||||
    expectedMutations = []
 | 
			
		||||
  }
 | 
			
		||||
  if (!expectedActions) {
 | 
			
		||||
    expectedActions = []
 | 
			
		||||
  }
 | 
			
		||||
  const isOver = () => {
 | 
			
		||||
    return mutationsCount >= expectedMutations.length && actionsCount >= expectedActions.length
 | 
			
		||||
  }
 | 
			
		||||
  // mock commit
 | 
			
		||||
  const commit = (type, payload) => {
 | 
			
		||||
    const mutation = expectedMutations[mutationsCount]
 | 
			
		||||
 | 
			
		||||
    expect(mutation.type).to.equal(type)
 | 
			
		||||
    if (payload) {
 | 
			
		||||
      expect(mutation.payload).to.deep.equal(payload)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mutationsCount++
 | 
			
		||||
    if (isOver()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  // mock dispatch
 | 
			
		||||
  const dispatch = (type, payload, options) => {
 | 
			
		||||
    const a = expectedActions[actionsCount]
 | 
			
		||||
    if (!a) {
 | 
			
		||||
      throw Error(`Unexecpted action ${type}`)
 | 
			
		||||
    }
 | 
			
		||||
    expect(a.type).to.equal(type)
 | 
			
		||||
    if (payload) {
 | 
			
		||||
      expect(a.payload).to.deep.equal(payload)
 | 
			
		||||
    }
 | 
			
		||||
    if (a.options) {
 | 
			
		||||
      expect(options).to.deep.equal(a.options)
 | 
			
		||||
    }
 | 
			
		||||
    actionsCount++
 | 
			
		||||
    if (isOver()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let end = function () {
 | 
			
		||||
    // check if no mutations should have been dispatched
 | 
			
		||||
    if (expectedMutations.length === 0) {
 | 
			
		||||
      expect(mutationsCount).to.equal(0)
 | 
			
		||||
    }
 | 
			
		||||
    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)
 | 
			
		||||
  if (promise) {
 | 
			
		||||
    promise.then(end)
 | 
			
		||||
    return promise
 | 
			
		||||
  } else {
 | 
			
		||||
    return end()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Ładowanie…
	
		Reference in New Issue