From 55b11ed7c897c87e6e272a44e8438683b4212af6 Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Sun, 20 Jan 2019 22:44:03 +0900 Subject: [PATCH 1/2] refs #209 Add unit tests for TimelineSpace --- spec/unit/store/TimelineSpace.spec.js | 67 +++++++++++++++++++ src/renderer/store/App.js | 2 +- src/renderer/store/TimelineSpace.js | 2 +- .../store/TimelineSpace/Modals/Jump.js | 2 +- 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 spec/unit/store/TimelineSpace.spec.js diff --git a/spec/unit/store/TimelineSpace.spec.js b/spec/unit/store/TimelineSpace.spec.js new file mode 100644 index 00000000..25e975cf --- /dev/null +++ b/spec/unit/store/TimelineSpace.spec.js @@ -0,0 +1,67 @@ +import TimelineSpace from '~/src/renderer/store/TimelineSpace' +import unreadSettings from '~/src/constants/unreadNotification' + +describe('TimelineSpace', () => { + describe('mutations', () => { + let state + beforeEach(() => { + state = { + account: { + domain: '', + _id: '', + username: '' + }, + loading: false, + emojis: [], + tootMax: 500, + unreadNotification: { + direct: unreadSettings.Direct.default, + local: unreadSettings.Local.default, + public: unreadSettings.Public.default + }, + useWebsocket: false, + pleroma: false + } + }) + + describe('updateEmojis', () => { + it('should be updated', () => { + TimelineSpace.mutations.updateEmojis(state, [ + { + shortcode: 'emacs', + url: 'http://example.com/emacs' + }, + { + shortcode: 'ruby', + url: 'http://example.com/ruby' + } + ]) + expect(state.emojis).toEqual([ + { + name: ':emacs:', + image: 'http://example.com/emacs' + }, + { + name: ':ruby:', + image: 'http://example.com/ruby' + } + ]) + }) + }) + + describe('updateTootMax', () => { + describe('value is null', () => { + it('should be updated with 500', () => { + TimelineSpace.mutations.updateTootMax(state, null) + expect(state.tootMax).toEqual(500) + }) + }) + describe('value is not null', () => { + it('should be updated', () => { + TimelineSpace.mutations.updateTootMax(state, 1200) + expect(state.tootMax).toEqual(1200) + }) + }) + }) + }) +}) diff --git a/src/renderer/store/App.js b/src/renderer/store/App.js index e7c1f416..96e0fe73 100644 --- a/src/renderer/store/App.js +++ b/src/renderer/store/App.js @@ -1,5 +1,5 @@ import { ipcRenderer } from 'electron' -import router from '../router' +import router from '@/router' import { LightTheme, DarkTheme, SolarizedLightTheme, SolarizedDarkTheme, KimbieDarkTheme } from '../utils/theme' import DisplayStyle from '~/src/constants/displayStyle' import Theme from '~/src/constants/theme' diff --git a/src/renderer/store/TimelineSpace.js b/src/renderer/store/TimelineSpace.js index 0ab673ee..6abf622d 100644 --- a/src/renderer/store/TimelineSpace.js +++ b/src/renderer/store/TimelineSpace.js @@ -5,7 +5,7 @@ import SideMenu from './TimelineSpace/SideMenu' import HeaderMenu from './TimelineSpace/HeaderMenu' import Modals from './TimelineSpace/Modals' import Contents from './TimelineSpace/Contents' -import router from '../router' +import router from '@/router' import unreadSettings from '~/src/constants/unreadNotification' const TimelineSpace = { diff --git a/src/renderer/store/TimelineSpace/Modals/Jump.js b/src/renderer/store/TimelineSpace/Modals/Jump.js index 214acc54..4ff75ea6 100644 --- a/src/renderer/store/TimelineSpace/Modals/Jump.js +++ b/src/renderer/store/TimelineSpace/Modals/Jump.js @@ -1,4 +1,4 @@ -import router from '../../../router' +import router from '@/router' import i18n from '~/src/config/i18n' const Jump = { From 487307142c35844eee3947b7872c3ea4a729ff7b Mon Sep 17 00:00:00 2001 From: AkiraFukushima Date: Tue, 22 Jan 2019 23:47:16 +0900 Subject: [PATCH 2/2] refs #209 Add integration tests for TimelineSpace --- spec/integration/store/TimelineSpace.spec.js | 242 +++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 spec/integration/store/TimelineSpace.spec.js diff --git a/spec/integration/store/TimelineSpace.spec.js b/spec/integration/store/TimelineSpace.spec.js new file mode 100644 index 00000000..1180614d --- /dev/null +++ b/spec/integration/store/TimelineSpace.spec.js @@ -0,0 +1,242 @@ +import Mastodon from 'megalodon' +import { createLocalVue } from '@vue/test-utils' +import Vuex from 'vuex' +import { ipcMain } from '~/spec/mock/electron' +import TimelineSpace from '~/src/renderer/store/TimelineSpace' +import unreadSettings from '~/src/constants/unreadNotification' + +jest.genMockFromModule('megalodon') +jest.mock('megalodon') + +const state = () => { + return { + account: { + domain: '', + _id: '', + username: '' + }, + loading: false, + emojis: [], + tootMax: 500, + unreadNotification: { + direct: true, + local: true, + public: true + }, + useWebsocket: false, + pleroma: false + } +} + +const homeStore = { + namespaced: true, + actions: { + fetchTimeline: jest.fn() + } +} + +const notificationStore = { + namespaced: true, + actions: { + fetchNotifications: jest.fn() + } +} + +const DMStore = { + namespaced: true, + actions: { + fetchTimeline: jest.fn() + } +} + +const LocalStore = { + namespaced: true, + actions: { + fetchLocalTimeline: jest.fn() + } +} + +const PublicStore = { + namespaced: true, + actions: { + fetchPublicTimeline: jest.fn() + } +} + +const contentsStore = { + namespaced: true, + modules: { + Home: homeStore, + Notifications: notificationStore, + DirectMessages: DMStore, + Local: LocalStore, + Public: PublicStore + } +} + +const initStore = () => { + return { + namespaced: true, + modules: { + Contents: contentsStore + }, + state: state(), + actions: TimelineSpace.actions, + mutations: TimelineSpace.mutations + } +} + +describe('TimelineSpace', () => { + let store + let localVue + + beforeEach(() => { + localVue = createLocalVue() + localVue.use(Vuex) + store = new Vuex.Store({ + modules: { + TimelineSpace: initStore() + } + }) + }) + + describe('localAccount', () => { + describe('account already exists', () => { + beforeEach(() => { + ipcMain.once('get-local-account', (event, _id) => { + event.sender.send('response-get-local-account', { + username: 'test' + }) + }) + }) + it('should be updated', async () => { + await store.dispatch('TimelineSpace/localAccount', 1) + expect(store.state.TimelineSpace.account.username).toEqual('test') + }) + }) + + describe('account does not exist', () => { + beforeEach(() => { + ipcMain.once('get-local-account', (event, _id) => { + event.sender.send('response-get-local-account', {}) + }) + ipcMain.once('update-account', (event, _account) => { + event.sender.send('response-update-account', { + username: 'fetched' + }) + }) + }) + it('should be fetched', async () => { + await store.dispatch('TimelineSpace/localAccount', 1) + expect(store.state.TimelineSpace.account.username).toEqual('fetched') + }) + }) + }) + + describe('detectPleroma', () => { + describe('API is pleroma', () => { + it('should be detected', async () => { + const mockResponse = { + version: 'Pleroma v0.9.9' + } + Mastodon.get.mockResolvedValue(mockResponse) + await store.dispatch('TimelineSpace/detectPleroma') + expect(store.state.TimelineSpace.pleroma).toEqual(true) + expect(store.state.TimelineSpace.useWebsocket).toEqual(true) + }) + }) + describe('API is not pleroma', () => { + it('should be detected', async () => { + const mockResponse = { + version: '2.7.0' + } + Mastodon.get.mockResolvedValue(mockResponse) + await store.dispatch('TimelineSpace/detectPleroma') + expect(store.state.TimelineSpace.pleroma).toEqual(false) + expect(store.state.TimelineSpace.useWebsocket).toEqual(false) + }) + }) + }) + + describe('fetchEmojis', () => { + it('should be updated', async () => { + const mockResponse = [ + { + shortcode: 'emacs', + url: 'http://example.com/emacs' + }, + { + shortcode: 'ruby', + url: 'http://example.com/ruby' + } + ] + Mastodon.get.mockResolvedValue(mockResponse) + await store.dispatch('TimelineSpace/fetchEmojis', {}) + expect(store.state.TimelineSpace.emojis).toEqual([ + { + name: ':emacs:', + image: 'http://example.com/emacs' + }, + { + name: ':ruby:', + image: 'http://example.com/ruby' + } + ]) + }) + }) + + describe('fetchInstance', () => { + it('should be updated', async () => { + const mockResponse = { + max_toot_chars: 5000 + } + Mastodon.get.mockResolvedValue(mockResponse) + await store.dispatch('TimelineSpace/fetchInstance', {}) + expect(store.state.TimelineSpace.tootMax).toEqual(5000) + }) + }) + + describe('loadUnreadNotification', () => { + describe('success', () => { + it('should be updated', async () => { + ipcMain.once('get-unread-notification', (event, _) => { + event.sender.send('response-get-unread-notification', { + direct: false, + local: false, + public: false + }) + }) + await store.dispatch('TimelineSpace/loadUnreadNotification') + expect(store.state.TimelineSpace.unreadNotification).toEqual({ + direct: false, + local: false, + public: false + }) + }) + }) + describe('error', () => { + it('should be set default', async () => { + ipcMain.once('get-unread-notification', (event, _) => { + event.sender.send('error-get-unread-notification', new Error()) + }) + await store.dispatch('TimelineSpace/loadUnreadNotification') + expect(store.state.TimelineSpace.unreadNotification).toEqual({ + direct: unreadSettings.Direct.default, + local: unreadSettings.Local.default, + public: unreadSettings.Public.default + }) + }) + }) + }) + + describe('fetchContentsTimelines', () => { + it('should be called', async () => { + await store.dispatch('TimelineSpace/fetchContentsTimelines', {}) + expect(homeStore.actions.fetchTimeline).toHaveBeenCalled() + expect(notificationStore.actions.fetchNotifications).toHaveBeenCalled() + expect(DMStore.actions.fetchTimeline).toHaveBeenCalled() + expect(LocalStore.actions.fetchLocalTimeline).toHaveBeenCalled() + expect(PublicStore.actions.fetchPublicTimeline).toHaveBeenCalled() + }) + }) +})