diff --git a/packages/insomnia-app/app/common/__tests__/constants.test.js b/packages/insomnia-app/app/common/__tests__/constants.test.js index c7a6e14e66..536397fe30 100644 --- a/packages/insomnia-app/app/common/__tests__/constants.test.js +++ b/packages/insomnia-app/app/common/__tests__/constants.test.js @@ -6,6 +6,7 @@ import { ACTIVITY_SPEC, ACTIVITY_UNIT_TEST, FLEXIBLE_URL_REGEX, + isValidActivity, isWorkspaceActivity, } from '../constants'; @@ -35,15 +36,32 @@ describe('URL Regex', () => { }); describe('isWorkspaceActivity', () => { - it('return true', () => { + it('should return true', () => { expect(isWorkspaceActivity(ACTIVITY_SPEC)).toBe(true); expect(isWorkspaceActivity(ACTIVITY_DEBUG)).toBe(true); expect(isWorkspaceActivity(ACTIVITY_UNIT_TEST)).toBe(true); }); - it('return false', () => { + it('should return false', () => { expect(isWorkspaceActivity(ACTIVITY_HOME)).toBe(false); expect(isWorkspaceActivity(ACTIVITY_ONBOARDING)).toBe(false); expect(isWorkspaceActivity(ACTIVITY_MIGRATION)).toBe(false); }); }); + +describe('isValidActivity', () => { + it('should return true', () => { + expect(isValidActivity(ACTIVITY_SPEC)).toBe(true); + expect(isValidActivity(ACTIVITY_DEBUG)).toBe(true); + expect(isValidActivity(ACTIVITY_UNIT_TEST)).toBe(true); + expect(isValidActivity(ACTIVITY_HOME)).toBe(true); + expect(isValidActivity(ACTIVITY_ONBOARDING)).toBe(true); + expect(isValidActivity(ACTIVITY_MIGRATION)).toBe(true); + }); + + it('should return false', () => { + expect(isValidActivity('something else')).toBe(false); + expect(isValidActivity(null)).toBe(false); + expect(isValidActivity(undefined)).toBe(false); + }); +}); diff --git a/packages/insomnia-app/app/common/constants.js b/packages/insomnia-app/app/common/constants.js index 515e39001d..e37eccfcfe 100644 --- a/packages/insomnia-app/app/common/constants.js +++ b/packages/insomnia-app/app/common/constants.js @@ -174,6 +174,20 @@ export const isWorkspaceActivity = (activity: GlobalActivity): boolean => { } }; +export const isValidActivity = (activity: GlobalActivity): boolean => { + switch (activity) { + case ACTIVITY_SPEC: + case ACTIVITY_DEBUG: + case ACTIVITY_UNIT_TEST: + case ACTIVITY_HOME: + case ACTIVITY_ONBOARDING: + case ACTIVITY_MIGRATION: + return true; + default: + return false; + } +}; + // HTTP Methods export const METHOD_GET = 'GET'; export const METHOD_POST = 'POST'; diff --git a/packages/insomnia-app/app/ui/redux/modules/__tests__/global.test.js b/packages/insomnia-app/app/ui/redux/modules/__tests__/global.test.js index 5d7d56644e..e4157b37a6 100644 --- a/packages/insomnia-app/app/ui/redux/modules/__tests__/global.test.js +++ b/packages/insomnia-app/app/ui/redux/modules/__tests__/global.test.js @@ -216,6 +216,33 @@ describe('global', () => { expect(store.getActions()).toEqual([expectedEvent]); }); + it.each( + 'something', + null, + undefined, + )('should go to home if initialized with an unsupported value: %s', async activity => { + const settings = createSettings(true, true); + + const store = mockStore({ global: {}, entities: { settings: [settings] } }); + + global.localStorage.setItem(`${LOCALSTORAGE_PREFIX}::activity`, JSON.stringify(activity)); + const expectedEvent = { type: SET_ACTIVE_ACTIVITY, activity: ACTIVITY_HOME }; + + await store.dispatch(initActiveActivity()); + expect(store.getActions()).toEqual([expectedEvent]); + }); + + it('should go to home if local storage key not found', async () => { + const settings = createSettings(true, true); + + const store = mockStore({ global: {}, entities: { settings: [settings] } }); + + const expectedEvent = { type: SET_ACTIVE_ACTIVITY, activity: ACTIVITY_HOME }; + + await store.dispatch(initActiveActivity()); + expect(store.getActions()).toEqual([expectedEvent]); + }); + it('should go to home if initialized at migration and onboarding seen', async () => { const settings = createSettings(true, true); diff --git a/packages/insomnia-app/app/ui/redux/modules/global.js b/packages/insomnia-app/app/ui/redux/modules/global.js index 134c03207e..c4580823f9 100644 --- a/packages/insomnia-app/app/ui/redux/modules/global.js +++ b/packages/insomnia-app/app/ui/redux/modules/global.js @@ -36,6 +36,7 @@ import { ACTIVITY_MIGRATION, ACTIVITY_ONBOARDING, DEPRECATED_ACTIVITY_INSOMNIA, + isValidActivity, } from '../../../common/constants'; import { selectSettings } from '../selectors'; import { getDesignerDataDir } from '../../../common/misc'; @@ -266,6 +267,8 @@ export function goToNextActivity() { Go to an explicit activity */ export function setActiveActivity(activity: GlobalActivity) { + activity = _normalizeActivity(activity); + // Don't need to await settings update switch (activity) { case ACTIVITY_MIGRATION: @@ -680,6 +683,18 @@ function _migrateDeprecatedActivity(activity: GlobalActivity): GlobalActivity { return activity === DEPRECATED_ACTIVITY_INSOMNIA ? ACTIVITY_DEBUG : activity; } +function _normalizeActivity(activity: GlobalActivity): GlobalActivity { + activity = _migrateDeprecatedActivity(activity); + + if (isValidActivity(activity)) { + return activity; + } else { + const fallbackActivity = ACTIVITY_HOME; + console.log(`[app] invalid activity "${activity}"; navigating to ${fallbackActivity}`); + return fallbackActivity; + } +} + /* Initialize with the cached active activity, and navigate to the next activity if necessary This will also decide whether to start with the migration or onboarding activities @@ -700,7 +715,7 @@ export function initActiveActivity() { // Nothing here... } - activeActivity = _migrateDeprecatedActivity(activeActivity); + activeActivity = _normalizeActivity(activeActivity); let overrideActivity = null; switch (activeActivity) {