1
0
mirror of https://github.com/h3poteto/whalebird-desktop synced 2025-01-24 06:33:52 +01:00

refs #850 Convert some unit tests to integration test

This commit is contained in:
AkiraFukushima 2019-03-25 23:50:11 +09:00
parent 946ead49f5
commit d4ee8d8661
11 changed files with 351 additions and 349 deletions

View File

@ -110,6 +110,11 @@
"testMatch": [
"**/spec/**/*.spec.ts"
],
"preset": "ts-jest/presets/js-with-ts",
"transform": {
"^.+\\.(js|jsx)$": "babel-jest",
"^.+\\.(ts|tsx)$": "ts-jest"
},
"globals": {
"ts-jest": {
"tsConfig": "tsconfig.json"

View File

@ -55,7 +55,7 @@ describe('App', () => {
describe('loadPreferences', () => {
describe('error', () => {
it('should not change', async () => {
ipcMain.once('get-preferences', (event, _) => {
ipcMain.once('get-preferences', (event: any, _) => {
event.sender.send('error-get-preferences', new Error())
})
await store.dispatch('App/loadPreferences')
@ -67,7 +67,7 @@ describe('App', () => {
})
describe('success', () => {
it('should be changed', async () => {
ipcMain.once('get-preferences', (event, _) => {
ipcMain.once('get-preferences', (event: any, _) => {
event.sender.send('response-get-preferences', {
general: {
timeline: {

View File

@ -0,0 +1,93 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import { ipcMain } from '~/spec/mock/electron'
import axios, { AxiosStatic } from 'axios'
import Login from '@/store/Login'
jest.mock('axios')
interface AxiosMock extends AxiosStatic {
mockResolvedValue: Function
mockRejectedValue: Function
mockImplementation: Function
}
const state = () => {
return {
instances: [],
selectedInstance: null,
searching: false
}
}
const initStore = () => {
return {
namespaced: true,
state: state(),
actions: Login.actions,
mutations: Login.mutations
}
}
describe('Login', () => {
let store
let localVue
beforeEach(() => {
localVue = createLocalVue()
localVue.use(Vuex)
store = new Vuex.Store({
modules: {
Login: initStore()
}
})
})
describe('fetchLogin', () => {
describe('error', () => {
it('should return error', async () => {
ipcMain.once('get-auth-url', (event, _) => {
event.sender.send('error-get-auth-url', new Error())
})
await store.dispatch('Login/fetchLogin', 'pleroma.io')
.catch((err: Error) => {
expect(err instanceof Error).toEqual(true)
})
})
})
describe('success', () => {
it('should return url', async () => {
ipcMain.once('get-auth-url', (event, _) => {
event.sender.send('response-get-auth-url', 'http://example.com/auth')
})
const url = await store.dispatch('Login/fetchLogin', 'pleroma.io')
expect(url).toEqual('http://example.com/auth')
})
})
})
describe('pageBack', () => {
it('should reset instance', () => {
store.dispatch('Login/pageBack')
expect(store.state.Login.selectedInstance).toEqual(null)
})
})
// TODO: Could not mock axios for finally
describe.skip('confirmInstance', () => {
it('should change instance', async () => {
// Provide Promise.resolve for finally keywrod.
// https://github.com/facebook/jest/issues/6552
const mockedAxios = axios as AxiosMock
const res: Promise<object> = new Promise<object>((resolve, _) => {
resolve({
data: 'test'
})
})
mockedAxios.mockImplementation(() => res)
const data = await store.dispatch('Login/confirmInstance', 'pleroma.io')
expect(data).toEqual('test')
expect(store.state.Login.selectedInstance).toEqual('pleroma.io')
})
})
})

View File

@ -0,0 +1,131 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import { ipcMain } from '~/spec/mock/electron'
import Account from '@/store/Preferences/Account'
const state = () => {
return {
accounts: [],
accountLoading: false
}
}
const initStore = () => {
return {
namespaced: true,
state: state(),
actions: Account.actions,
mutations: Account.mutations
}
}
describe('Account', () => {
let store
let localVue
beforeEach(() => {
localVue = createLocalVue()
localVue.use(Vuex)
store = new Vuex.Store({
modules: {
Account: initStore()
}
})
})
describe('loadAccounts', () => {
it('error', async () => {
ipcMain.once('list-accounts', (event, _) => {
event.sender.send('error-list-accounts', new Error())
})
await store.dispatch('Account/loadAccounts')
.catch((err: Error) => {
expect(err instanceof Error).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('list-accounts', (event, _) => {
event.sender.send('response-list-accounts', ['accounts'])
})
await store.dispatch('Account/loadAccounts')
expect(store.state.Account.accounts).toEqual(['accounts'])
})
})
describe('removeAccount', () => {
it('error', async () => {
ipcMain.once('remove-account', (event, _) => {
event.sender.send('error-remove-account', new Error())
})
await store.dispatch('Account/removeAccount', 'account')
.catch((err: Error) => {
expect(err instanceof Error).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('remove-account', (event, _) => {
event.sender.send('response-remove-account', 1)
})
const res = await store.dispatch('Account/removeAccount', 'account')
expect(res).toEqual(undefined)
})
})
describe('forwardAccount', () => {
it('error', async () => {
ipcMain.once('forward-account', (event, _) => {
event.sender.send('error-forward-account', new Error())
})
await store.dispatch('Account/forwardAccount', 'account')
.catch((err: Error) => {
expect(err instanceof Error).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('forward-account', (event, _) => {
event.sender.send('response-forward-account', 1)
})
const res = await store.dispatch('Account/forwardAccount', 'account')
expect(res).toEqual(undefined)
})
})
describe('backwardAccount', () => {
it('error', async () => {
ipcMain.once('backward-account', (event, _) => {
event.sender.send('error-backward-account', new Error())
})
await store.dispatch('Account/backwardAccount', 'account')
.catch((err: Error) => {
expect(err instanceof Error).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('backward-account', (event, _) => {
event.sender.send('response-backward-account', 1)
})
const res = await store.dispatch('Account/backwardAccount', 'account')
expect(res).toEqual(undefined)
})
})
describe('removeAllAccounts', () => {
it('error', async () => {
ipcMain.once('remove-all-accounts', (event, _) => {
event.sender.send('error-remove-all-accounts', new Error())
})
await store.dispatch('Account/removeAllAccounts', 'account')
.catch((err: Error) => {
expect(err instanceof Error).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('remove-all-accounts', (event, _) => {
event.sender.send('response-remove-all-accounts', 1)
})
const res = await store.dispatch('Account/removeAllAccounts', 'account')
expect(res).toEqual(undefined)
})
})
})

View File

@ -1,94 +0,0 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import Theme from '~/src/constants/theme'
import DisplayStyle from '~/src/constants/displayStyle'
import TimeFormat from '~/src/constants/timeFormat'
import { LightTheme, DarkTheme } from '~/src/renderer/utils/theme'
import DefaultFonts from '@/utils/fonts'
import Appearance from '@/store/Preferences/Appearance'
import { ipcMain } from '~/spec/mock/electron'
const state = () => {
return {
appearance: {
theme: Theme.Light.key,
fontSize: 14,
displayNameStyle: DisplayStyle.DisplayNameAndUsername.value,
timeFormat: TimeFormat.Absolute.value,
customThemeColor: LightTheme,
font: DefaultFonts[0]
},
fonts: []
}
}
const initStore = () => {
return {
namespaced: true,
state: state(),
actions: Appearance.actions,
mutations: Appearance.mutations
}
}
const App = {
namespaced: true,
actions: {
loadPreferences: jest.fn()
}
}
describe('Preferences/Appearance', () => {
let store
let localVue
beforeEach(() => {
localVue = createLocalVue()
localVue.use(Vuex)
store = new Vuex.Store({
modules: {
Preferences: initStore(),
App: App
}
})
ipcMain.once('update-preferences', (event, config) => {
event.sender.send('response-update-preferences', config)
})
})
it('updateTheme', async () => {
await store.dispatch('Preferences/updateTheme', Theme.Dark.key)
expect(store.state.Preferences.appearance.theme).toEqual(Theme.Dark.key)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateFontSize', async () => {
await store.dispatch('Preferences/updateFontSize', 15)
expect(store.state.Preferences.appearance.fontSize).toEqual(15)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateDisplayNameStyle', async () => {
await store.dispatch('Preferences/updateDisplayNameStyle', DisplayStyle.DisplayName.value)
expect(store.state.Preferences.appearance.displayNameStyle).toEqual(DisplayStyle.DisplayName.value)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateTimeFormat', async () => {
await store.dispatch('Preferences/updateTimeFormat', TimeFormat.Relative.value)
expect(store.state.Preferences.appearance.timeFormat).toEqual(TimeFormat.Relative.value)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateCustomThemeColor', async () => {
await store.dispatch('Preferences/updateCustomThemeColor', DarkTheme)
expect(store.state.Preferences.appearance.customThemeColor).toEqual(DarkTheme)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateFont', async () => {
await store.dispatch('Preferences/updateFont', DefaultFonts[1])
expect(store.state.Preferences.appearance.font).toEqual(DefaultFonts[1])
expect(App.actions.loadPreferences).toBeCalled()
})
})

View File

@ -0,0 +1,119 @@
import { createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import Theme from '~/src/constants/theme'
import DisplayStyle from '~/src/constants/displayStyle'
import TimeFormat from '~/src/constants/timeFormat'
import { LightTheme, DarkTheme } from '~/src/renderer/utils/theme'
import DefaultFonts from '@/utils/fonts'
import Appearance from '@/store/Preferences/Appearance'
import { ipcMain } from '~/spec/mock/electron'
const state = () => {
return {
appearance: {
theme: Theme.Light.key,
fontSize: 14,
displayNameStyle: DisplayStyle.DisplayNameAndUsername.value,
timeFormat: TimeFormat.Absolute.value,
customThemeColor: LightTheme,
font: DefaultFonts[0]
},
fonts: []
}
}
const initStore = () => {
return {
namespaced: true,
state: state(),
actions: Appearance.actions,
mutations: Appearance.mutations
}
}
const App = {
namespaced: true,
actions: {
loadPreferences: jest.fn()
}
}
describe('Preferences/Appearance', () => {
let store
let localVue
beforeEach(() => {
localVue = createLocalVue()
localVue.use(Vuex)
store = new Vuex.Store({
modules: {
Preferences: initStore(),
App: App
}
})
ipcMain.once('update-preferences', (event, config) => {
event.sender.send('response-update-preferences', config)
})
})
describe('load', () => {
it('loadAppearance', async () => {
ipcMain.once('get-preferences', (event, _) => {
event.sender.send('response-get-preferences', {
appearance: {
theme: Theme.Dark.key,
fontSize: 15
}
})
})
await store.dispatch('Preferences/loadAppearance')
expect(store.state.Preferences.appearance.theme).toEqual(Theme.Dark.key)
expect(store.state.Preferences.appearance.fontSize).toEqual(15)
})
it('loadFonts', async () => {
ipcMain.once('list-fonts', (event, _) => {
event.sender.send('response-list-fonts', ['my-font'])
})
await store.dispatch('Preferences/loadFonts')
expect(store.state.Preferences.fonts).toEqual([DefaultFonts[0], 'my-font'])
})
})
describe('update', () => {
it('updateTheme', async () => {
await store.dispatch('Preferences/updateTheme', Theme.Dark.key)
expect(store.state.Preferences.appearance.theme).toEqual(Theme.Dark.key)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateFontSize', async () => {
await store.dispatch('Preferences/updateFontSize', 15)
expect(store.state.Preferences.appearance.fontSize).toEqual(15)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateDisplayNameStyle', async () => {
await store.dispatch('Preferences/updateDisplayNameStyle', DisplayStyle.DisplayName.value)
expect(store.state.Preferences.appearance.displayNameStyle).toEqual(DisplayStyle.DisplayName.value)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateTimeFormat', async () => {
await store.dispatch('Preferences/updateTimeFormat', TimeFormat.Relative.value)
expect(store.state.Preferences.appearance.timeFormat).toEqual(TimeFormat.Relative.value)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateCustomThemeColor', async () => {
await store.dispatch('Preferences/updateCustomThemeColor', DarkTheme)
expect(store.state.Preferences.appearance.customThemeColor).toEqual(DarkTheme)
expect(App.actions.loadPreferences).toBeCalled()
})
it('updateFont', async () => {
await store.dispatch('Preferences/updateFont', DefaultFonts[1])
expect(store.state.Preferences.appearance.font).toEqual(DefaultFonts[1])
expect(App.actions.loadPreferences).toBeCalled()
})
})
})

View File

@ -1,32 +0,0 @@
import Authorize from '@/store/Authorize'
import { ipcMain } from '~/spec/mock/electron'
describe.skip('Authorize', () => {
// TODO: integration
describe('actions', () => {
describe('error', () => {
it('should return error', async () => {
ipcMain.once('get-access-token', (event, _) => {
event.sender.send('error-get-access-token', new AccessTokenError())
})
const commitMock = jest.fn()
await Authorize.actions.submit({ commit: commitMock }, 'code')
.catch((err) => {
expect(err instanceof AccessTokenError).toEqual(true)
})
})
})
describe('success', () => {
it('should return id', async () => {
ipcMain.once('get-access-token', (event, _) => {
event.sender.send('response-get-access-token', 'abcd')
})
const commitMock = jest.fn()
const id = await Authorize.actions.submit({ commit: commitMock }, 'code')
expect(id).toEqual('abcd')
})
})
})
})
class AccessTokenError extends Error { }

View File

@ -1,9 +1,4 @@
import Login from '@/store/Login'
import axios from 'axios'
import { ipcMain } from '~/spec/mock/electron'
jest.mock('axios')
axios.get = jest.fn()
describe('Login', () => {
describe('mutations', () => {
@ -28,55 +23,4 @@ describe('Login', () => {
})
})
})
// TODO: move to integration
describe.skip('actions', () => {
describe('fetchLogin', () => {
describe('error', () => {
it('should return error', async () => {
ipcMain.once('get-auth-url', (event, _) => {
event.sender.send('error-get-auth-url', new AuthError())
})
const commitMock = jest.fn()
await Login.actions.fetchLogin({ commit: commitMock }, 'pleroma.io')
.catch((err) => {
expect(err instanceof AuthError).toEqual(true)
})
})
})
describe('success', () => {
it('should return url', async () => {
ipcMain.once('get-auth-url', (event, _) => {
event.sender.send('response-get-auth-url', 'http://example.com/auth')
})
const commitMock = jest.fn()
const url = await Login.actions.fetchLogin({ commit: commitMock }, 'pleroma.io')
expect(url).toEqual('http://example.com/auth')
})
})
})
describe('pageBack', () => {
it('should reset instance', () => {
const commitMock = jest.fn()
Login.actions.pageBack({ commit: commitMock })
expect(commitMock).toHaveBeenCalledWith('changeInstance', null)
})
})
describe('confirmInstance', () => {
it('should change instance', async () => {
// Provide Promise.resolve for finally keywrod.
// https://github.com/facebook/jest/issues/6552
(<jest.Mock>axios.get).mockReturnValue(Promise.resolve({
data: 'test'
}))
const commitMock = jest.fn()
const data = await Login.actions.confirmInstance({ commit: commitMock }, 'pleroma.io')
expect(data).toEqual('test')
// ref: https://eddyerburgh.me/how-to-unit-test-a-vuex-store
expect(commitMock).toHaveBeenCalledWith('changeInstance', 'pleroma.io')
})
})
})
})
class AuthError extends Error { }

View File

@ -1,5 +1,4 @@
import Account from '@/store/Preferences/Account'
import { ipcMain } from '~/spec/mock/electron'
describe('Preferences/Account', () => {
describe('mutations', () => {
@ -23,114 +22,4 @@ describe('Preferences/Account', () => {
})
})
})
describe('actions', () => {
describe('loadAccounts', () => {
it('error', async () => {
ipcMain.once('list-accounts', (event, _) => {
event.sender.send('error-list-accounts', new LoadAccountsError())
})
const commitMock = jest.fn()
await Account.actions.loadAccounts({ commit: commitMock })
.catch((err) => {
expect(err instanceof LoadAccountsError).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('list-accounts', (event, _) => {
event.sender.send('response-list-accounts', ['accounts'])
})
const commitMock = jest.fn()
const accounts = await Account.actions.loadAccounts({ commit: commitMock })
expect(accounts).toEqual(['accounts'])
expect(commitMock).toHaveBeenCalledWith('updateAccounts', ['accounts'])
})
})
describe('removeAccount', () => {
it('error', async () => {
ipcMain.once('remove-account', (event, _) => {
event.sender.send('error-remove-account', new RemoveAccountError())
})
const commitMock = jest.fn()
await Account.actions.removeAccount({ commit: commitMock }, 'account')
.catch((err) => {
expect(err instanceof RemoveAccountError).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('remove-account', (event, _) => {
event.sender.send('response-remove-account', 1)
})
const commitMock = jest.fn()
const res = await Account.actions.removeAccount({ commit: commitMock }, 'account')
expect(res).toEqual(undefined)
})
})
describe('forwardAccount', () => {
it('error', async () => {
ipcMain.once('forward-account', (event, _) => {
event.sender.send('error-forward-account', new ForwardAccountError())
})
const commitMock = jest.fn()
await Account.actions.forwardAccount({ commit: commitMock }, 'account')
.catch((err) => {
expect(err instanceof ForwardAccountError).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('forward-account', (event, _) => {
event.sender.send('response-forward-account', 1)
})
const commitMock = jest.fn()
const res = await Account.actions.forwardAccount({ commit: commitMock }, 'account')
expect(res).toEqual(undefined)
})
})
describe('backwardAccount', () => {
it('error', async () => {
ipcMain.once('backward-account', (event, _) => {
event.sender.send('error-backward-account', new BackwardAccountError())
})
const commitMock = jest.fn()
await Account.actions.backwardAccount({ commit: commitMock }, 'account')
.catch((err) => {
expect(err instanceof BackwardAccountError).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('backward-account', (event, _) => {
event.sender.send('response-backward-account', 1)
})
const commitMock = jest.fn()
const res = await Account.actions.backwardAccount({ commit: commitMock }, 'account')
expect(res).toEqual(undefined)
})
})
describe('removeAllAccounts', () => {
it('error', async () => {
ipcMain.once('remove-all-accounts', (event, _) => {
event.sender.send('error-remove-all-accounts', new RemoveAllAccountsError())
})
const commitMock = jest.fn()
await Account.actions.removeAllAccounts({ commit: commitMock }, 'account')
.catch((err) => {
expect(err instanceof RemoveAllAccountsError).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('remove-all-accounts', (event, _) => {
event.sender.send('response-remove-all-accounts', 1)
})
const commitMock = jest.fn()
const res = await Account.actions.removeAllAccounts({ commit: commitMock }, 'account')
expect(res).toEqual(undefined)
})
})
})
})
class LoadAccountsError extends Error { }
class RemoveAccountError extends Error { }
class ForwardAccountError extends Error { }
class BackwardAccountError extends Error { }
class RemoveAllAccountsError extends Error { }

View File

@ -4,7 +4,6 @@ import TimeFormat from '~/src/constants/timeFormat'
import { LightTheme } from '~/src/renderer/utils/theme'
import DefaultFonts from '@/utils/fonts'
import Appearance from '@/store/Preferences/Appearance'
import { ipcMain } from '~/spec/mock/electron'
describe('Preferences/Appearance', () => {
let state
@ -37,57 +36,5 @@ describe('Preferences/Appearance', () => {
})
})
})
describe('actions', () => {
describe('loadAppearance', () => {
it('error', async () => {
ipcMain.once('get-preferences', (event, _) => {
event.sender.send('error-get-preferences', new LoadAppearanceError())
})
const commitMock = jest.fn()
await Appearance.actions.loadAppearance({ commit: commitMock })
.catch((err) => {
expect(err instanceof LoadAppearanceError).toEqual(true)
})
})
it('success', async () => {
const conf = {
appearance: {
theme: Theme.Dark.key
}
}
ipcMain.once('get-preferences', (event, _) => {
event.sender.send('response-get-preferences', conf)
})
const commitMock = jest.fn()
const c = await Appearance.actions.loadAppearance({ commit: commitMock })
expect(c).toEqual(conf)
expect(commitMock).toHaveBeenCalledWith('updateAppearance', conf.appearance)
})
})
describe('loadFonts', () => {
it('error', async () => {
ipcMain.once('list-fonts', (event, _) => {
event.sender.send('error-list-fonts', new ListFontsError())
})
const commitMock = jest.fn()
await Appearance.actions.loadFonts({ commit: commitMock })
.catch((err) => {
expect(err instanceof ListFontsError).toEqual(true)
})
})
it('success', async () => {
ipcMain.once('list-fonts', (event, _) => {
event.sender.send('response-list-fonts', ['fonts'])
})
const commitMock = jest.fn()
const fonts = await Appearance.actions.loadFonts({ commit: commitMock })
expect(fonts).toEqual(['fonts'])
expect(commitMock).toHaveBeenCalledWith('updateFonts', [DefaultFonts[0]].concat(['fonts']))
})
})
})
})
class LoadAppearanceError extends Error { }
class ListFontsError extends Error { }

View File

@ -12,12 +12,12 @@
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"allowSyntheticDefaultImports": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"esModuleInterop": true,
"baseUrl": "./",
"paths": {
"@*": ["src/renderer*"],