diff --git a/.env b/.env index b9b30856c..cedc5b01c 100644 --- a/.env +++ b/.env @@ -41,5 +41,6 @@ CAREER_LINK_URL='' ENABLE_EDX_PERSONAL_DASHBOARD=false ENABLE_PROGRAMS=false NON_BROWSABLE_COURSES=false +SHOW_UNENROLL_SURVEY=true # Fallback in local style files PARAGON_THEME_URLS={} diff --git a/.env.development b/.env.development index 73183ccc2..0af4795f7 100644 --- a/.env.development +++ b/.env.development @@ -47,5 +47,6 @@ CAREER_LINK_URL='' ENABLE_EDX_PERSONAL_DASHBOARD=false ENABLE_PROGRAMS=false NON_BROWSABLE_COURSES=false +SHOW_UNENROLL_SURVEY=true # Fallback in local style files PARAGON_THEME_URLS={} diff --git a/.env.test b/.env.test index aa19975b6..1abe19ae9 100644 --- a/.env.test +++ b/.env.test @@ -46,4 +46,5 @@ CAREER_LINK_URL='' ENABLE_EDX_PERSONAL_DASHBOARD=true ENABLE_PROGRAMS=false NON_BROWSABLE_COURSES=false +SHOW_UNENROLL_SURVEY=true PARAGON_THEME_URLS={} diff --git a/example.env.config.js b/example.env.config.js index 70436fd55..31550b27a 100644 --- a/example.env.config.js +++ b/example.env.config.js @@ -69,4 +69,5 @@ module.exports = { ACCOUNT_PROFILE_URL: 'http://localhost:1995', CAREER_LINK_URL: '', EXPERIMENT_08_23_VAN_PAINTED_DOOR: true, + SHOW_UNENROLL_SURVEY: true }; diff --git a/src/config/index.js b/src/config/index.js index ae923c27e..c8c486889 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -20,6 +20,7 @@ const configuration = { SEARCH_CATALOG_URL: process.env.SEARCH_CATALOG_URL || null, ENABLE_PROGRAMS: process.env.ENABLE_PROGRAMS === 'true', NON_BROWSABLE_COURSES: process.env.NON_BROWSABLE_COURSES === 'true', + SHOW_UNENROLL_SURVEY: process.env.SHOW_UNENROLL_SURVEY === 'true', }; const features = {}; diff --git a/src/containers/UnenrollConfirmModal/hooks/index.js b/src/containers/UnenrollConfirmModal/hooks/index.js index 1db099234..5af54172c 100644 --- a/src/containers/UnenrollConfirmModal/hooks/index.js +++ b/src/containers/UnenrollConfirmModal/hooks/index.js @@ -3,6 +3,7 @@ import React from 'react'; import { StrictDict } from 'utils'; import { apiHooks } from 'hooks'; +import { configuration } from 'config'; import { useUnenrollReasons } from './reasons'; import * as module from '.'; @@ -18,13 +19,21 @@ export const modalStates = StrictDict({ export const useUnenrollData = ({ closeModal, cardId }) => { const [isConfirmed, setIsConfirmed] = module.state.confirmed(false); - const confirm = () => setIsConfirmed(true); const reason = useUnenrollReasons({ cardId }); const refreshList = apiHooks.useInitializeApp(); + const unenrollFromCourse = apiHooks.useUnenrollFromCourse(cardId); + + const confirm = () => { + if (!configuration.SHOW_UNENROLL_SURVEY) { + unenrollFromCourse(); + } + setIsConfirmed(true); + }; + let modalState; if (isConfirmed) { - modalState = (reason.isSubmitted) + modalState = (reason.isSubmitted || !configuration.SHOW_UNENROLL_SURVEY) ? modalStates.finished : modalStates.reason; } else { modalState = modalStates.confirm; diff --git a/src/containers/UnenrollConfirmModal/hooks/index.test.js b/src/containers/UnenrollConfirmModal/hooks/index.test.js index 1db9a118e..6818382d6 100644 --- a/src/containers/UnenrollConfirmModal/hooks/index.test.js +++ b/src/containers/UnenrollConfirmModal/hooks/index.test.js @@ -1,5 +1,6 @@ import { apiHooks } from 'hooks'; import { MockUseState } from 'testUtils'; +import { configuration } from 'config'; import * as reasons from './reasons'; import * as hooks from '.'; @@ -11,13 +12,22 @@ jest.mock('./reasons', () => ({ jest.mock('hooks', () => ({ apiHooks: { useInitializeApp: jest.fn(), + useUnenrollFromCourse: jest.fn(), + }, +})); + +jest.mock('config', () => ({ + configuration: { + SHOW_UNENROLL_SURVEY: true, }, })); const state = new MockUseState(hooks); const testValue = 'test-value'; const initializeApp = jest.fn(); +const unenrollFromCourse = jest.fn(); apiHooks.useInitializeApp.mockReturnValue(initializeApp); +apiHooks.useUnenrollFromCourse.mockReturnValue(unenrollFromCourse); let out; const mockReason = { @@ -79,22 +89,66 @@ describe('UnenrollConfirmModal hooks', () => { expect(initializeApp).toHaveBeenCalled(); }); }); - describe('modalState', () => { - it('returns modalStates.finished if confirmed and submitted', () => { + }); + + describe('SHOW_UNENROLL_SURVEY configuration tests', () => { + beforeEach(() => { + state.mock(); + jest.clearAllMocks(); + }); + afterEach(() => { + state.restore(); + }); + + describe('when SHOW_UNENROLL_SURVEY is true (default)', () => { + beforeEach(() => { + configuration.SHOW_UNENROLL_SURVEY = true; + }); + + test('confirm does not call unenrollFromCourse immediately', () => { + out = createUseUnenrollData(); + out.confirm(); + expect(unenrollFromCourse).not.toHaveBeenCalled(); + expect(state.setState.confirmed).toHaveBeenCalledWith(true); + }); + + test('modalState returns reason when confirmed but not submitted', () => { + state.mockVal(state.keys.confirmed, true); + reasons.useUnenrollReasons.mockReturnValueOnce({ ...mockReason, isSubmitted: false }); + out = createUseUnenrollData(); + expect(out.modalState).toEqual(hooks.modalStates.reason); + }); + + test('modalState returns finished when confirmed and submitted', () => { state.mockVal(state.keys.confirmed, true); reasons.useUnenrollReasons.mockReturnValueOnce({ ...mockReason, isSubmitted: true }); out = createUseUnenrollData(); expect(out.modalState).toEqual(hooks.modalStates.finished); }); - it('returns modalStates.reason if confirmed and not submitted', () => { - state.mockVal(state.keys.confirmed, true); + }); + + describe('when SHOW_UNENROLL_SURVEY is false', () => { + beforeEach(() => { + configuration.SHOW_UNENROLL_SURVEY = false; + }); + + afterEach(() => { + // Reset to default + configuration.SHOW_UNENROLL_SURVEY = true; + }); + + test('confirm calls unenrollFromCourse immediately', () => { out = createUseUnenrollData(); - expect(out.modalState).toEqual(hooks.modalStates.reason); + out.confirm(); + expect(unenrollFromCourse).toHaveBeenCalled(); + expect(state.setState.confirmed).toHaveBeenCalledWith(true); }); - it('returns modalStates.confirm if not confirmed', () => { - state.mockVal(state.keys.confirmed, false); + + test('modalState returns finished when confirmed regardless of submission status', () => { + state.mockVal(state.keys.confirmed, true); + reasons.useUnenrollReasons.mockReturnValueOnce({ ...mockReason, isSubmitted: false }); out = createUseUnenrollData(); - expect(out.modalState).toEqual(hooks.modalStates.confirm); + expect(out.modalState).toEqual(hooks.modalStates.finished); }); }); });