diff --git a/package.json b/package.json index 3b84ba37..512656e7 100644 --- a/package.json +++ b/package.json @@ -244,7 +244,7 @@ "electron-builder": "^22.9.1", "electron-debug": "^3.1.0", "electron-devtools-installer": "^3.1.1", - "electron-mock-ipc": "^0.3.7", + "electron-mock-ipc": "^0.3.9", "electron-packager": "^15.0.0", "eslint": "^7.12.1", "eslint-config-prettier": "^6.15.0", diff --git a/spec/renderer/integration/store/App.spec.ts b/spec/renderer/integration/store/App.spec.ts index 462af272..ed93aa0b 100644 --- a/spec/renderer/integration/store/App.spec.ts +++ b/spec/renderer/integration/store/App.spec.ts @@ -57,19 +57,20 @@ describe('App', () => { describe('loadPreferences', () => { describe('error', () => { it('should not change', async () => { - ipcMain.once('get-preferences', (event: any, _) => { - event.sender.send('error-get-preferences', new Error()) + ipcMain.handle('get-preferences', async () => { + throw new Error() }) await store.dispatch('App/loadPreferences').catch(err => { expect(err instanceof Error).toEqual(true) expect(store.state.App.theme).toEqual(LightTheme) }) + ipcMain.removeHandler('get-preferences') }) }) describe('success', () => { it('should be changed', async () => { - ipcMain.once('get-preferences', (event: any, _) => { - event.sender.send('response-get-preferences', { + ipcMain.handle('get-preferences', () => { + return { general: { timeline: { cw: true, @@ -95,13 +96,14 @@ describe('App', () => { customThemeColor: LightTheme, font: DefaultFonts[0] } - }) + } }) await store.dispatch('App/loadPreferences') expect(store.state.App.fontSize).toEqual(13) expect(store.state.App.theme).toEqual(DarkTheme) expect(store.state.App.ignoreCW).toEqual(true) expect(store.state.App.ignoreNFSW).toEqual(true) + ipcMain.removeHandler('get-preferences') }) }) }) diff --git a/spec/renderer/integration/store/GlobalHeader.spec.ts b/spec/renderer/integration/store/GlobalHeader.spec.ts index 5fb99a81..2ada19f2 100644 --- a/spec/renderer/integration/store/GlobalHeader.spec.ts +++ b/spec/renderer/integration/store/GlobalHeader.spec.ts @@ -48,10 +48,13 @@ describe('GlobalHeader', () => { describe('listAccounts', () => { beforeEach(() => { - ipcMain.once('list-accounts', (event, _) => { - event.sender.send('response-list-accounts', ['account']) + ipcMain.handle('list-accounts', () => { + return ['account'] }) }) + afterEach(() => { + ipcMain.removeHandler('list-accounts') + }) it('should be updated', async () => { await store.dispatch('GlobalHeader/listAccounts') expect(store.state.GlobalHeader.accounts).toEqual(['account']) @@ -60,10 +63,13 @@ describe('GlobalHeader', () => { describe('refreshAccounts', () => { beforeEach(() => { - ipcMain.once('refresh-accounts', (event, _) => { - event.sender.send('response-refresh-accounts', ['accounts']) + ipcMain.handle('refresh-accounts', () => { + return ['accounts'] }) }) + afterEach(() => { + ipcMain.removeHandler('refresh-accounts') + }) it('should be refreshed', async () => { await store.dispatch('GlobalHeader/refreshAccounts') expect(store.state.GlobalHeader.accounts).toEqual(['accounts']) @@ -79,10 +85,13 @@ describe('GlobalHeader', () => { describe('loadHide', () => { beforeEach(() => { - ipcMain.once('get-global-header', (event, _) => { - event.sender.send('response-get-global-header', true) + ipcMain.handle('get-global-header', () => { + return true }) }) + afterEach(() => { + ipcMain.removeHandler('get-global-header') + }) it('should be changed', async () => { await store.dispatch('GlobalHeader/loadHide') expect(store.state.GlobalHeader.hide).toEqual(true) @@ -91,10 +100,13 @@ describe('GlobalHeader', () => { describe('switchHide', () => { beforeEach(() => { - ipcMain.once('change-global-header', (event, value) => { - event.sender.send('response-change-global-header', value) + ipcMain.handle('change-global-header', (_, value) => { + return value }) }) + afterEach(() => { + ipcMain.removeHandler('change-global-header') + }) it('should be switched', async () => { const hide = await store.dispatch('GlobalHeader/switchHide', true) expect(hide).toEqual(true) diff --git a/spec/renderer/integration/store/Login.spec.ts b/spec/renderer/integration/store/Login.spec.ts index c9c8ac7a..854e9e19 100644 --- a/spec/renderer/integration/store/Login.spec.ts +++ b/spec/renderer/integration/store/Login.spec.ts @@ -53,21 +53,23 @@ describe('Login', () => { describe('fetchLogin', () => { describe('error', () => { it('should return error', async () => { - ipcMain.once('get-auth-url', event => { - event.sender.send('error-get-auth-url', new Error()) + ipcMain.handle('get-auth-url', () => { + throw new Error() }) await store.dispatch('Login/fetchLogin', 'pleroma.io').catch((err: Error) => { expect(err instanceof Error).toEqual(true) }) + ipcMain.removeHandler('get-auth-url') }) }) describe('success', () => { it('should return url', async () => { - ipcMain.once('get-auth-url', event => { - event.sender.send('response-get-auth-url', 'http://example.com/auth') + ipcMain.handle('get-auth-url', () => { + return 'http://example.com/auth' }) const url = await store.dispatch('Login/fetchLogin', 'pleroma.io') expect(url).toEqual('http://example.com/auth') + ipcMain.removeHandler('get-auth-url') }) }) }) diff --git a/spec/renderer/integration/store/Preferences/Account.spec.ts b/spec/renderer/integration/store/Preferences/Account.spec.ts index 1fe62825..4ae7658b 100644 --- a/spec/renderer/integration/store/Preferences/Account.spec.ts +++ b/spec/renderer/integration/store/Preferences/Account.spec.ts @@ -52,92 +52,102 @@ describe('Account', () => { describe('loadAccounts', () => { it('error', async () => { - ipcMain.once('list-accounts', (event: any, _) => { - event.sender.send('error-list-accounts', new Error()) + ipcMain.handle('list-accounts', async () => { + throw new Error() }) await store.dispatch('Account/loadAccounts').catch((err: Error) => { expect(err instanceof Error).toEqual(true) }) + ipcMain.removeHandler('list-accounts') }) it('success', async () => { - ipcMain.once('list-accounts', (event: any, _) => { - event.sender.send('response-list-accounts', [account]) + ipcMain.handle('list-accounts', () => { + return [account] }) await store.dispatch('Account/loadAccounts') expect(store.state.Account.accounts).toEqual([account]) + ipcMain.removeHandler('list-accounts') }) }) describe('removeAccount', () => { it('error', async () => { - ipcMain.once('remove-account', (event: any, _) => { - event.sender.send('error-remove-account', new Error()) + ipcMain.handle('remove-account', async () => { + throw new Error() }) await store.dispatch('Account/removeAccount', account).catch((err: Error) => { expect(err instanceof Error).toEqual(true) }) + ipcMain.removeHandler('remove-account') }) it('success', async () => { - ipcMain.once('remove-account', (event: any, _) => { - event.sender.send('response-remove-account') + ipcMain.handle('remove-account', () => { + return true }) const res = await store.dispatch('Account/removeAccount', account) expect(res).toEqual(undefined) + ipcMain.removeHandler('remove-account') }) }) describe('forwardAccount', () => { it('error', async () => { - ipcMain.once('forward-account', (event: any, _) => { - event.sender.send('error-forward-account', new Error()) + ipcMain.handle('forward-account', async () => { + throw new Error() }) await store.dispatch('Account/forwardAccount', account).catch((err: Error) => { expect(err instanceof Error).toEqual(true) }) + ipcMain.removeHandler('forward-account') }) it('success', async () => { - ipcMain.once('forward-account', (event: any, _) => { - event.sender.send('response-forward-account') + ipcMain.handle('forward-account', () => { + return {} }) const res = await store.dispatch('Account/forwardAccount', account) expect(res).toEqual(undefined) + ipcMain.removeHandler('forward-account') }) }) describe('backwardAccount', () => { it('error', async () => { - ipcMain.once('backward-account', (event: any, _) => { - event.sender.send('error-backward-account', new Error()) + ipcMain.handle('backward-account', () => { + throw new Error() }) await store.dispatch('Account/backwardAccount', account).catch((err: Error) => { expect(err instanceof Error).toEqual(true) }) + ipcMain.removeHandler('backward-account') }) it('success', async () => { - ipcMain.once('backward-account', (event: any, _) => { - event.sender.send('response-backward-account') + ipcMain.handle('backward-account', () => { + return {} }) const res = await store.dispatch('Account/backwardAccount', account) expect(res).toEqual(undefined) + ipcMain.removeHandler('backward-account') }) }) describe('removeAllAccounts', () => { it('error', async () => { - ipcMain.once('remove-all-accounts', (event: any, _) => { - event.sender.send('error-remove-all-accounts', new Error()) + ipcMain.handle('remove-all-accounts', () => { + throw new Error() }) await store.dispatch('Account/removeAllAccounts', account).catch((err: Error) => { expect(err instanceof Error).toEqual(true) }) + ipcMain.removeHandler('remove-all-accounts') }) it('success', async () => { - ipcMain.once('remove-all-accounts', (event: any, _) => { - event.sender.send('response-remove-all-accounts') + ipcMain.handle('remove-all-accounts', () => { + return {} }) const res = await store.dispatch('Account/removeAllAccounts', account) expect(res).toEqual(undefined) + ipcMain.removeHandler('remove-all-accounts') }) }) }) diff --git a/spec/renderer/integration/store/Preferences/Appearance.spec.ts b/spec/renderer/integration/store/Preferences/Appearance.spec.ts index ecdaee09..4b0dcbd6 100644 --- a/spec/renderer/integration/store/Preferences/Appearance.spec.ts +++ b/spec/renderer/integration/store/Preferences/Appearance.spec.ts @@ -1,4 +1,4 @@ -import { IpcMainEvent } from 'electron' +import { IpcMainInvokeEvent } from 'electron' import { createLocalVue } from '@vue/test-utils' import Vuex from 'vuex' import Theme from '~/src/constants/theme' @@ -60,15 +60,18 @@ describe('Preferences/Appearance', () => { describe('load', () => { describe('loadAppearance', () => { beforeEach(() => { - ipcMain.once('get-preferences', (event: IpcMainEvent, _) => { - event.sender.send('response-get-preferences', { + ipcMain.handle('get-preferences', () => { + return { appearance: { theme: Theme.Dark.key, fontSize: 15 } - }) + } }) }) + afterEach(() => { + ipcMain.removeHandler('get-preferences') + }) it('should be loaded', async () => { await store.dispatch('Preferences/loadAppearance') expect(store.state.Preferences.appearance.theme).toEqual(Theme.Dark.key) @@ -77,10 +80,13 @@ describe('Preferences/Appearance', () => { }) describe('loadFonts', () => { beforeEach(() => { - ipcMain.once('list-fonts', (event: IpcMainEvent, _) => { - event.sender.send('response-list-fonts', ['my-font']) + ipcMain.handle('list-fonts', () => { + return ['my-font'] }) }) + afterEach(() => { + ipcMain.removeHandler('list-fonts') + }) it('should be loaded', async () => { await store.dispatch('Preferences/loadFonts') expect(store.state.Preferences.fonts).toEqual([DefaultFonts[0], 'my-font']) @@ -90,10 +96,13 @@ describe('Preferences/Appearance', () => { describe('update', () => { beforeEach(() => { - ipcMain.once('update-preferences', (event: IpcMainEvent, config: any) => { - event.sender.send('response-update-preferences', config) + ipcMain.handle('update-preferences', (_: IpcMainInvokeEvent, config: any) => { + return config }) }) + afterEach(() => { + ipcMain.removeHandler('update-preferences') + }) it('updateTheme', async () => { await store.dispatch('Preferences/updateTheme', Theme.Dark.key) expect(store.state.Preferences.appearance.theme).toEqual(Theme.Dark.key) diff --git a/spec/renderer/integration/store/Preferences/General.spec.ts b/spec/renderer/integration/store/Preferences/General.spec.ts index 7f7084c1..65b1cf8c 100644 --- a/spec/renderer/integration/store/Preferences/General.spec.ts +++ b/spec/renderer/integration/store/Preferences/General.spec.ts @@ -3,6 +3,7 @@ import Vuex from 'vuex' import { ipcMain, ipcRenderer } from '~/spec/mock/electron' import General, { GeneralState } from '@/store/Preferences/General' import { MyWindow } from '~/src/types/global' +import { IpcMainInvokeEvent } from 'electron' ;((window as any) as MyWindow).ipcRenderer = ipcRenderer const state = (): GeneralState => { @@ -59,17 +60,20 @@ describe('Preferences/General', () => { describe('loadGeneral', () => { beforeEach(() => { - ipcMain.once('get-preferences', (event, _) => { - event.sender.send('response-get-preferences', { + ipcMain.handle('get-preferences', () => { + return { general: { sound: { fav_rb: false, toot: false } } - }) + } }) }) + afterEach(() => { + ipcMain.removeHandler('get-preferences') + }) it('should be updated', async () => { await store.dispatch('Preferences/loadGeneral') expect(store.state.Preferences.general.sound.fav_rb).toEqual(false) @@ -80,10 +84,13 @@ describe('Preferences/General', () => { describe('updateSound', () => { beforeEach(() => { - ipcMain.once('update-preferences', (event, config) => { - event.sender.send('response-update-preferences', config) + ipcMain.handle('update-preferences', (_: IpcMainInvokeEvent, config: any) => { + return config }) }) + afterEach(() => { + ipcMain.removeHandler('update-preferences') + }) it('should be updated', async () => { await store.dispatch('Preferences/updateSound', { fav_rb: false, @@ -97,10 +104,13 @@ describe('Preferences/General', () => { describe('updateTimeline', () => { beforeEach(() => { - ipcMain.once('update-preferences', (event, config) => { - event.sender.send('response-update-preferences', config) + ipcMain.handle('update-preferences', (_: IpcMainInvokeEvent, config: any) => { + return config }) }) + afterEach(() => { + ipcMain.removeHandler('update-preferences') + }) it('should be updated', async () => { await store.dispatch('Preferences/updateTimeline', { cw: true, diff --git a/spec/renderer/integration/store/Preferences/Language.spec.ts b/spec/renderer/integration/store/Preferences/Language.spec.ts index 1e035757..35a42457 100644 --- a/spec/renderer/integration/store/Preferences/Language.spec.ts +++ b/spec/renderer/integration/store/Preferences/Language.spec.ts @@ -39,14 +39,17 @@ describe('Preferences/Language', () => { describe('loadLanguage', () => { beforeEach(() => { - ipcMain.once('get-preferences', (event: any, _) => { - event.sender.send('response-get-preferences', { + ipcMain.handle('get-preferences', () => { + return { language: { language: DefaultLanguage.ja.key } - }) + } }) }) + afterEach(() => { + ipcMain.removeHandler('get-preferences') + }) it('should be updated', async () => { await store.dispatch('Language/loadLanguage') expect(store.state.Language.language.language).toEqual(DefaultLanguage.ja.key) @@ -55,10 +58,13 @@ describe('Preferences/Language', () => { describe('changeLanguage', () => { beforeEach(() => { - ipcMain.once('change-language', (event: any, key: string) => { - event.sender.send('response-change-language', key) + ipcMain.handle('change-language', (_, key: string) => { + return key }) }) + afterEach(() => { + ipcMain.removeHandler('change-language') + }) it('should be changed', async () => { await store.dispatch('Language/changeLanguage', DefaultLanguage.ja.key) expect(store.state.Language.language.language).toEqual(DefaultLanguage.ja.key) diff --git a/spec/renderer/integration/store/Preferences/Notification.spec.ts b/spec/renderer/integration/store/Preferences/Notification.spec.ts index 14d2afd5..fabf6442 100644 --- a/spec/renderer/integration/store/Preferences/Notification.spec.ts +++ b/spec/renderer/integration/store/Preferences/Notification.spec.ts @@ -53,8 +53,8 @@ describe('Preferences/Notification', () => { describe('loadNotification', () => { beforeEach(() => { - ipcMain.once('get-preferences', (event: any, _) => { - event.sender.send('response-get-preferences', { + ipcMain.handle('get-preferences', () => { + return { notification: { notify: { reply: false, @@ -65,7 +65,10 @@ describe('Preferences/Notification', () => { reaction: false } } - }) + } + }) + afterEach(() => { + ipcMain.removeHandler('get-preferences') }) it('should be updated', async () => { await store.dispatch('Notification/loadNotification') @@ -85,10 +88,13 @@ describe('Preferences/Notification', () => { describe('updateNotify', () => { beforeEach(() => { - ipcMain.once('update-preferences', (event: any, conf: object) => { - event.sender.send('response-update-preferences', conf) + ipcMain.handle('update-preferences', (_, conf: object) => { + return conf }) }) + afterEach(() => { + ipcMain.removeHandler('update-preferences') + }) it('should be updated', async () => { await store.dispatch('Notification/updateNotify', { reply: false, diff --git a/spec/renderer/integration/store/TimelineSpace.spec.ts b/spec/renderer/integration/store/TimelineSpace.spec.ts index 58ce242d..1e302ea4 100644 --- a/spec/renderer/integration/store/TimelineSpace.spec.ts +++ b/spec/renderer/integration/store/TimelineSpace.spec.ts @@ -182,12 +182,15 @@ describe('TimelineSpace', () => { describe('localAccount', () => { describe('account already exists', () => { beforeEach(() => { - ipcMain.once('get-local-account', (event: any) => { - event.sender.send('response-get-local-account', { + ipcMain.handle('get-local-account', () => { + return { username: 'test' - }) + } }) }) + afterEach(() => { + ipcMain.removeHandler('get-local-account') + }) it('should be updated', async () => { await store.dispatch('TimelineSpace/localAccount', 1) expect(store.state.TimelineSpace.account.username).toEqual('test') @@ -196,15 +199,19 @@ describe('TimelineSpace', () => { describe('account does not exist', () => { beforeEach(() => { - ipcMain.once('get-local-account', (event: any) => { - event.sender.send('response-get-local-account', {}) + ipcMain.handle('get-local-account', () => { + return {} }) - ipcMain.once('update-account', (event: any) => { - event.sender.send('response-update-account', { + ipcMain.handle('update-account', () => { + return { username: 'fetched' - }) + } }) }) + afterEach(() => { + ipcMain.removeHandler('get-local-account') + ipcMain.removeHandler('update-account') + }) it('should be fetched', async () => { await store.dispatch('TimelineSpace/localAccount', 1) expect(store.state.TimelineSpace.account.username).toEqual('fetched') @@ -238,12 +245,12 @@ describe('TimelineSpace', () => { describe('loadUnreadNotification', () => { describe('success', () => { it('should be updated', async () => { - ipcMain.once('get-unread-notification', (event: any) => { - event.sender.send('response-get-unread-notification', { + ipcMain.handle('get-unread-notification', () => { + return { direct: false, local: false, public: false - }) + } }) await store.dispatch('TimelineSpace/loadUnreadNotification') expect(store.state.TimelineSpace.unreadNotification).toEqual({ @@ -251,12 +258,13 @@ describe('TimelineSpace', () => { local: false, public: false }) + ipcMain.removeHandler('get-unread-notification') }) }) describe('error', () => { it('should be set default', async () => { - ipcMain.once('get-unread-notification', (event: any) => { - event.sender.send('error-get-unread-notification', new Error()) + ipcMain.handle('get-unread-notification', async () => { + throw new Error() }) await store.dispatch('TimelineSpace/loadUnreadNotification') expect(store.state.TimelineSpace.unreadNotification).toEqual({ @@ -264,6 +272,7 @@ describe('TimelineSpace', () => { local: unreadSettings.Local.default, public: unreadSettings.Public.default }) + ipcMain.removeHandler('get-unread-notification') }) }) }) diff --git a/spec/renderer/integration/store/TimelineSpace/Contents/Hashtag/List.spec.ts b/spec/renderer/integration/store/TimelineSpace/Contents/Hashtag/List.spec.ts index 797214be..7bbd0aca 100644 --- a/spec/renderer/integration/store/TimelineSpace/Contents/Hashtag/List.spec.ts +++ b/spec/renderer/integration/store/TimelineSpace/Contents/Hashtag/List.spec.ts @@ -1,4 +1,4 @@ -import { IpcMainEvent } from 'electron' +import { IpcMainInvokeEvent } from 'electron' import { createLocalVue } from '@vue/test-utils' import { ipcMain, ipcRenderer } from '~/spec/mock/electron' import Vuex from 'vuex' @@ -48,8 +48,11 @@ describe('Hashtag/List', () => { describe('listTags', () => { it('should be updated', async () => { - ipcMain.once('list-hashtags', (event: IpcMainEvent) => { - event.sender.send('response-list-hashtags', [tag1, tag2]) + ipcMain.handle('list-hashtags', () => { + return [tag1, tag2] + }) + afterEach(() => { + ipcMain.removeHandler('list-hashtags') }) await store.dispatch('List/listTags') expect(store.state.List.tags).toEqual([tag1, tag2]) @@ -58,13 +61,10 @@ describe('Hashtag/List', () => { describe('removeTag', () => { it('should be updated', async () => { - ipcMain.once('remove-hashtag', async () => { - ipcMain.once('remove-hashtag', (event: IpcMainEvent, tag: LocalTag) => { - expect(tag).toEqual(tag1) - event.sender.send('response-remove-hashtag') - }) - await store.dispatch('List/removeTag', tag1) + ipcMain.handle('remove-hashtag', (_: IpcMainInvokeEvent, tag: LocalTag) => { + expect(tag).toEqual(tag1) }) + await store.dispatch('List/removeTag', tag1) }) }) }) diff --git a/spec/renderer/integration/store/TimelineSpace/SideMenu.spec.ts b/spec/renderer/integration/store/TimelineSpace/SideMenu.spec.ts index 5f57ac6d..4495c9ab 100644 --- a/spec/renderer/integration/store/TimelineSpace/SideMenu.spec.ts +++ b/spec/renderer/integration/store/TimelineSpace/SideMenu.spec.ts @@ -139,8 +139,8 @@ describe('SideMenu', () => { describe('readCollapse', () => { it('should be read', async () => { - ipcMain.once('get-collapse', (event: any, _) => { - event.sender.send('response-get-collapse', true) + ipcMain.handle('get-collapse', () => { + return true }) await store.dispatch('SideMenu/readCollapse') expect(store.state.SideMenu.collapse).toEqual(true) @@ -155,8 +155,8 @@ describe('SideMenu', () => { const tag2: LocalTag = { tagName: 'tag2' } - ipcMain.once('list-hashtags', (event: any, _) => { - event.sender.send('response-list-hashtags', [tag1, tag2]) + ipcMain.handle('list-hashtags', () => { + return [tag1, tag2] }) await store.dispatch('SideMenu/listTags') expect(store.state.SideMenu.tags).toEqual([tag1, tag2]) diff --git a/yarn.lock b/yarn.lock index 977275eb..0803acc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4597,10 +4597,10 @@ electron-log@^4.2.2: resolved "https://registry.yarnpkg.com/electron-log/-/electron-log-4.2.4.tgz#a13e42a9fc42ca2cc7d2603c3746352efa82112e" integrity sha512-CXbDU+Iwi+TjKzugKZmTRIORIPe3uQRqgChUl19fkW/reFUn5WP7dt+cNGT3bkLV8xfPilpkPFv33HgtmLLewQ== -electron-mock-ipc@^0.3.7: - version "0.3.8" - resolved "https://registry.yarnpkg.com/electron-mock-ipc/-/electron-mock-ipc-0.3.8.tgz#96aaf48b229e7b7e6d5366bc08f8a320c2e55c00" - integrity sha512-MqjZQtAzb7BNb6GB89v+CWZlt7uQsVa5zgq23FMtpmQw272nzFqqC0mvyB1ikW4Z5fcwsnSvAxAcZg9jbvbxJQ== +electron-mock-ipc@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/electron-mock-ipc/-/electron-mock-ipc-0.3.9.tgz#aae1adbc94f7d95a4c6534f7a0497904a338dd5d" + integrity sha512-KLcIfdDfA+DnK29/269zfBF4UxpIpkwj2ZVXdOtMvkPRutlpQZqa+hs24wXc/0DHiTKSKlapGHfPTlcZKGSh6A== electron-notarize@^1.0.0: version "1.0.0" @@ -11226,7 +11226,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.6.5, schema-utils@^2.7.1: +schema-utils@^2.6.5: version "2.7.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==