From 865552445a5b3f05b7ea5d2e972984342bbfe996 Mon Sep 17 00:00:00 2001 From: MisRob Date: Tue, 4 Jul 2023 13:07:05 +0200 Subject: [PATCH] Move handler to composable to keep the logic related to groups loading in one place --- .../src/composables/__mocks__/useGroups.js | 46 +++++++++++++++ .../coach/assets/src/composables/useGroups.js | 58 ++++++++++++++++++- .../assets/src/modules/groups/handlers.js | 58 ------------------- .../coach/assets/src/routes/planRoutes.js | 4 +- 4 files changed, 106 insertions(+), 60 deletions(-) create mode 100644 kolibri/plugins/coach/assets/src/composables/__mocks__/useGroups.js delete mode 100644 kolibri/plugins/coach/assets/src/modules/groups/handlers.js diff --git a/kolibri/plugins/coach/assets/src/composables/__mocks__/useGroups.js b/kolibri/plugins/coach/assets/src/composables/__mocks__/useGroups.js new file mode 100644 index 00000000000..f1fcb9dde7e --- /dev/null +++ b/kolibri/plugins/coach/assets/src/composables/__mocks__/useGroups.js @@ -0,0 +1,46 @@ +/** + * `useGroups` composable function mock. + * + * If default values are sufficient for tests, + * you only need call `jest.mock('')` + * at the top of a test file. + * + * If you need to override some default values from some tests, + * you can import a helper function `useGroupsMock` that accepts + * an object with values to be overriden and use it together + * with `mockImplementation` as follows: + * + * ``` + * // eslint-disable-next-line import/named + * import useGroups, { useGroupsMock } from ''; + * + * jest.mock('') + * + * it('test', () => { + * useGroups.mockImplementation( + * () => useGroupsMock({ groupsAreLoading: true }) + * ); + * }) + * ``` + * + * You can reset your mock implementation back to default values + * for other tests by calling the following in `beforeEach`: + * + * ``` + * useGroups.mockImplementation(() => useGroupsMock()) + * ``` + */ + +const MOCK_DEFAULTS = { + groupsAreLoading: false, + showGroupsPage: jest.fn(), +}; + +export function useGroupsMock(overrides = {}) { + return { + ...MOCK_DEFAULTS, + ...overrides, + }; +} + +export default jest.fn(() => useGroupsMock()); diff --git a/kolibri/plugins/coach/assets/src/composables/useGroups.js b/kolibri/plugins/coach/assets/src/composables/useGroups.js index 9cac09dc6f9..595c9930712 100644 --- a/kolibri/plugins/coach/assets/src/composables/useGroups.js +++ b/kolibri/plugins/coach/assets/src/composables/useGroups.js @@ -1,4 +1,6 @@ import { ref } from 'kolibri.lib.vueCompositionApi'; +import samePageCheckGenerator from 'kolibri.utils.samePageCheckGenerator'; +import { LearnerGroupResource, FacilityUserResource } from 'kolibri.resources'; // Place outside the function to keep the state const groupsAreLoading = ref(false); @@ -8,8 +10,62 @@ export function useGroups() { groupsAreLoading.value = loading; } + function showGroupsPage(store, classId) { + // On this page, handle loading state locally + // TODO: Open follow-up so that we don't need to do this + store.dispatch('notLoading'); + + setGroupsLoading(true); + + const promises = [ + FacilityUserResource.fetchCollection({ + getParams: { member_of: classId }, + force: true, + }), + LearnerGroupResource.fetchCollection({ + getParams: { parent: classId }, + force: true, + }), + ]; + const shouldResolve = samePageCheckGenerator(store); + return Promise.all(promises).then( + ([classUsers, groupsCollection]) => { + if (shouldResolve()) { + const groups = groupsCollection.map(group => ({ ...group, users: [] })); + const groupUsersPromises = groups.map(group => + FacilityUserResource.fetchCollection({ + getParams: { member_of: group.id }, + force: true, + }) + ); + + Promise.all(groupUsersPromises).then( + groupsUsersCollection => { + if (shouldResolve()) { + groupsUsersCollection.forEach((groupUsers, index) => { + groups[index].users = [...groupUsers]; + }); + store.commit('groups/SET_STATE', { + classUsers: [...classUsers], + groups, + groupModalShown: false, + }); + setGroupsLoading(false); + store.dispatch('clearError'); + } + }, + error => (shouldResolve() ? store.dispatch('handleError', error) : null) + ); + } + }, + error => { + shouldResolve() ? store.dispatch('handleError', error) : null; + } + ); + } + return { groupsAreLoading, - setGroupsLoading, + showGroupsPage, }; } diff --git a/kolibri/plugins/coach/assets/src/modules/groups/handlers.js b/kolibri/plugins/coach/assets/src/modules/groups/handlers.js deleted file mode 100644 index ffe9e32b06b..00000000000 --- a/kolibri/plugins/coach/assets/src/modules/groups/handlers.js +++ /dev/null @@ -1,58 +0,0 @@ -import samePageCheckGenerator from 'kolibri.utils.samePageCheckGenerator'; -import { LearnerGroupResource, FacilityUserResource } from 'kolibri.resources'; -import { useGroups } from '../../composables/useGroups'; - -const { setGroupsLoading } = useGroups(); - -export function showGroupsPage(store, classId) { - // on this page, don't handle loading state globally so we can do it locally - store.dispatch('notLoading'); - - setGroupsLoading(true); - - const promises = [ - FacilityUserResource.fetchCollection({ - getParams: { member_of: classId }, - force: true, - }), - LearnerGroupResource.fetchCollection({ - getParams: { parent: classId }, - force: true, - }), - ]; - const shouldResolve = samePageCheckGenerator(store); - return Promise.all(promises).then( - ([classUsers, groupsCollection]) => { - if (shouldResolve()) { - const groups = groupsCollection.map(group => ({ ...group, users: [] })); - const groupUsersPromises = groups.map(group => - FacilityUserResource.fetchCollection({ - getParams: { member_of: group.id }, - force: true, - }) - ); - - Promise.all(groupUsersPromises).then( - groupsUsersCollection => { - if (shouldResolve()) { - groupsUsersCollection.forEach((groupUsers, index) => { - groups[index].users = [...groupUsers]; - }); - store.commit('groups/SET_STATE', { - classUsers: [...classUsers], - groups, - groupModalShown: false, - }); - setGroupsLoading(false); - store.dispatch('clearError'); - } - }, - error => (shouldResolve() ? store.dispatch('handleError', error) : null) - ); - } - }, - error => { - shouldResolve() ? store.dispatch('handleError', error) : null; - } - ); -} diff --git a/kolibri/plugins/coach/assets/src/routes/planRoutes.js b/kolibri/plugins/coach/assets/src/routes/planRoutes.js index 918bd3d0d23..05f1b5a2c3d 100644 --- a/kolibri/plugins/coach/assets/src/routes/planRoutes.js +++ b/kolibri/plugins/coach/assets/src/routes/planRoutes.js @@ -1,12 +1,14 @@ import store from 'kolibri.coreVue.vuex.store'; import { PageNames } from '../constants'; +import { useGroups } from '../composables/useGroups'; import GroupsPage from '../views/plan/GroupsPage'; import GroupMembersPage from '../views/plan/GroupMembersPage'; import GroupEnrollPage from '../views/plan/GroupEnrollPage'; -import { showGroupsPage } from '../modules/groups/handlers'; import planLessonsRoutes from './planLessonsRoutes'; import planExamRoutes from './planExamRoutes'; +const { showGroupsPage } = useGroups(); + export default [ ...planLessonsRoutes, ...planExamRoutes,