Merge branch 'hotfix/show-solution-checkbox-ms-394' into develop

This commit is contained in:
Christian Cueni 2021-11-29 08:41:01 +01:00
commit d9240ef1c6
6 changed files with 224 additions and 1 deletions

View File

@ -13280,6 +13280,12 @@
}
}
},
"mock-apollo-client": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/mock-apollo-client/-/mock-apollo-client-0.7.0.tgz",
"integrity": "sha512-r0ICU01m007W0MwMej0lzlg1REtepDZ15Fyj8Hz9tiW/1TPb0PyHryGykrg9YhfbB8/+ZF2ovz+88yMF75TDoA==",
"dev": true
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",

View File

@ -128,6 +128,7 @@
"jest-transform-graphql": "^2.1.0",
"jest-transform-stub": "^2.0.0",
"jest-watch-typeahead": "^0.3.1",
"mock-apollo-client": "^0.7.0",
"ts-loader": "^8.3.0",
"typescript": "^4.4.3",
"vue-jest": "^3.0.4"

View File

@ -0,0 +1,3 @@
mutation {
deleteModuleNodes @client
}

View File

@ -34,5 +34,11 @@ export const resolvers = {
cache.writeQuery({query: SIDEBAR, data});
return data.sidebar;
},
deleteModuleNodes: (_, _query, {cache}) => {
Object.keys(cache.data.data)
.filter(prop => prop.indexOf('ModuleNode:') === 0)
.map(moduleName => cache.data.delete(moduleName)); // v3 uses .evict{id, fieldname}
return {success: true};
},
},
};

View File

@ -1,10 +1,13 @@
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
import UPDATE_USER_SETTING from '@/graphql/gql/mutations/updateUserSetting.gql';
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/queries/mySchoolClass.gql';
import DELETE_MODULE_NODES from '@/graphql/gql/local/mutations/deleteModuleNodes.gql';
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
export default {
methods: {
updateSelectedClass(selectedClass) {
const innerApollo = this.$apollo;
return this.$apollo.mutate({
mutation: UPDATE_USER_SETTING,
variables: {
@ -18,9 +21,18 @@ export default {
meData.me.selectedClass = selectedClass;
store.writeQuery({query: ME_QUERY, data: meData});
innerApollo.mutate({
mutation: DELETE_MODULE_NODES
});
},
refetchQueries: [{
query: MY_SCHOOL_CLASS_QUERY
}, {
query: MODULE_DETAILS_QUERY,
variables: {
slug: this.$route.params.slug
}
}]
}).catch((error) => {
console.warn('failed to update selected class', error);

View File

@ -0,0 +1,195 @@
import {createLocalVue, mount} from '@vue/test-utils'
import { createMockClient } from 'mock-apollo-client'
import SIDEBAR from '@/graphql/gql/local/sidebar.gql';
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
import UPDATE_USER_SETTING from '@/graphql/gql/mutations/updateUserSetting.gql';
import MY_SCHOOL_CLASS_QUERY from '@/graphql/gql/queries/mySchoolClass.gql';
import DELETE_MODULE_NODES from '@/graphql/gql/local/mutations/deleteModuleNodes.gql';
import MODULE_DETAILS_QUERY from '@/graphql/gql/queries/modules/moduleDetailsQuery.gql';
import VueApollo from 'vue-apollo'
import ClassSelectionWidget from '@/components/school-class/ClassSelectionWidget';
// https://dev.to/n_tepluhina/testing-vue-apollo-2020-edition-2l2p
const localVue = createLocalVue();
localVue.use(VueApollo);
const updateSettingsResponse = {
data: {
updateSetting: {
success: true,
errors:null,
__typename: 'UpdateSettingPayload'
}
}
};
const querySidebarResponse = {
data: {}
};
const deleteModulesResponse = {
data: {}
};
const meQueryResponse = {
data: {
me: {
__typename: "PrivateUserNode",
id: "UHJpdmF0ZVVzZXJOb2RlOjI=",
pk: 2,
username: "ross.geller",
email: "ross.geller@skillbox.example",
firstName: "Ross",
lastName: "Geller",
avatarUrl: "https://ucarecdn.com/fe10f9cc-a509-4170-9396-258abc418247/",
expiryDate: "2021-11-29",
readOnly: false,
lastModule: null,
lastTopic: {
id: "VG9waWNOb2RlOjQ5",
slug: "berufliche-grundbildung",
__typename: "TopicNode"
},
selectedClass: {
id: "U2Nob29sQ2xhc3NOb2RlOjM=",
readOnly: false,
__typename: "SchoolClassNode"
},
recentModules: {
edges: [],
__typename: "ModuleNodeConnection"
},
schoolClasses: {
edges: [
{
node: {
id: "U2Nob29sQ2xhc3NOb2RlOjE=",
name: "Friends",
__typename: "SchoolClassNode"
},
__typename: "SchoolClassNodeEdge"
},
{
node: {
id: "U2Nob29sQ2xhc3NOb2RlOjM=",
name: "ghfgfh",
__typename: "SchoolClassNode"
},
__typename: "SchoolClassNodeEdge"
}
],
__typename: "SchoolClassNodeConnection"
},
team: null,
isTeacher: true,
permissions: [
"users.can_manage_school_class_content"
],
onboardingVisited: true
}
}
}
const mySchoolClassResponse = {
data: {}
};
const moduleDetailResponse = {
data: {}
};
const slug = '/some/123';
const schoolClasses = [
{
id: 'abcd123',
name: 'Hello'
},{
id: 'xyz098',
name: 'Kitty'
}
];
describe('ClassSelectionWidget.vue', () => {
let mockClient;
let apolloProvider;
let wrapper;
const requestHandlers = {
updateSettingsHandler: jest.fn().mockResolvedValueOnce(updateSettingsResponse),
querySidebarHandler: jest.fn().mockResolvedValueOnce(querySidebarResponse),
meQueryHandler: jest.fn().mockResolvedValueOnce(meQueryResponse),
deleteModulesHandler: jest.fn().mockResolvedValueOnce(deleteModulesResponse),
mySchoolClassHandler: jest.fn().mockResolvedValueOnce(mySchoolClassResponse),
moduleDetailHandler: jest.fn().mockResolvedValueOnce(moduleDetailResponse),
}
const createComponent = () => {
mockClient = createMockClient();
mockClient.cache.writeQuery = jest.fn();
mockClient.setRequestHandler(UPDATE_USER_SETTING, requestHandlers.updateSettingsHandler);
mockClient.setRequestHandler(SIDEBAR, requestHandlers.querySidebarHandler);
mockClient.setRequestHandler(ME_QUERY, requestHandlers.meQueryHandler);
mockClient.setRequestHandler(DELETE_MODULE_NODES, requestHandlers.deleteModulesHandler);
mockClient.setRequestHandler(MY_SCHOOL_CLASS_QUERY, requestHandlers.mySchoolClassHandler);
mockClient.setRequestHandler(MODULE_DETAILS_QUERY, requestHandlers.moduleDetailHandler);
apolloProvider = new VueApollo({
defaultClient: mockClient,
});
wrapper = mount(ClassSelectionWidget, {
localVue,
apolloProvider,
mocks: {
$route: {
params: {
slug
}
}
}
});
wrapper.vm.me.schoolClass = schoolClasses;
}
it('should delete the modules cache and query the current module on a class change', async () => {
createComponent();
wrapper.vm.me.selectedClass = {id: 'abcd123'}
wrapper.vm.updateSelectedClassAndHidePopover(schoolClasses[1]);
expect(requestHandlers.updateSettingsHandler).toHaveBeenCalledWith({
input: {
id: schoolClasses[1].id
}
});
await wrapper.vm.$nextTick();
// modules have been removed from cache
expect(requestHandlers.deleteModulesHandler).toHaveBeenCalled();
expect(requestHandlers.mySchoolClassHandler).toHaveBeenCalled();
// current module is being refetched
expect(requestHandlers.moduleDetailHandler).toHaveBeenCalledWith({slug});
});
afterEach(() => {
wrapper.destroy()
mockClient = null
apolloProvider = null
})
})