diff --git a/client/cypress/fixtures/mocks.js b/client/cypress/fixtures/mocks.js index 8e36001f..18bbc97a 100644 --- a/client/cypress/fixtures/mocks.js +++ b/client/cypress/fixtures/mocks.js @@ -44,7 +44,7 @@ export default { id: getChapterId(), title: 'chapter-title', description: 'chapter-description', - + bookmark: null }), ContentBlockNode: () => ({ contents: [], diff --git a/client/cypress/fixtures/module.minimal.js b/client/cypress/fixtures/module.minimal.js index 80900ba9..27946e89 100644 --- a/client/cypress/fixtures/module.minimal.js +++ b/client/cypress/fixtures/module.minimal.js @@ -4,7 +4,7 @@ export default { heroImage: 'heroImage', teaser: 'A Module Mock Teaser', intro: 'intro', - assignments: {}, + assignments: [], objectiveGroups: [], id: 'TW9kdWxlTm9kZToxMjM=', chapters: [], diff --git a/client/cypress/integration/e2e/bookmarks.spec.js b/client/cypress/integration/e2e/bookmarks.spec.js deleted file mode 100644 index 6f154431..00000000 --- a/client/cypress/integration/e2e/bookmarks.spec.js +++ /dev/null @@ -1,36 +0,0 @@ -describe('Bookmarks', () => { - beforeEach(() => { - // todo: mock all the graphql queries and mutations - cy.exec('python ../server/manage.py prepare_bookmarks_for_cypress'); - - cy.viewport('macbook-15'); - cy.apolloLogin('rachel.green', 'test'); - }); - - it('should bookmark content block', () => { - cy.visit('/module/lohn-und-budget/'); - - cy.get('.content-component').contains('Das folgende Interview').parent().parent().as('interviewContent'); - - cy.get('@interviewContent').within(() => { - cy.get('.bookmark-actions__bookmark').click(); - cy.get('.bookmark-actions__add-note').click(); - }); - - cy.get('[data-cy=bookmark-note]').within(() => { - cy.get('.skillbox-input').type('Hallo Velo'); - }); - - cy.get('[data-cy=modal-save-button]').click(); - - cy.get('@interviewContent').within(() => { - cy.get('.bookmark-actions__edit-note').click(); - }); - - cy.get('[data-cy=bookmark-note]').within(() => { - cy.get('.skillbox-input').clear().type('Hello Bike'); - }); - - cy.get('[data-cy=modal-save-button]').click(); - }); -}); diff --git a/client/cypress/integration/frontend/bookmarks.spec.js b/client/cypress/integration/frontend/bookmarks.spec.js new file mode 100644 index 00000000..9dcc3e54 --- /dev/null +++ b/client/cypress/integration/frontend/bookmarks.spec.js @@ -0,0 +1,124 @@ +import {getMinimalMe} from '../../support/helpers'; +import minimalModule from '../../fixtures/module.minimal'; + +const {me: minimalMe} = getMinimalMe({}); + + +describe('Bookmarks', () => { + beforeEach(() => { + cy.setup(); + cy.mockGraphqlOps({ + operations: { + MeQuery: { + me: minimalMe + }, + ModuleDetailsQuery: { + module: { + ...minimalModule, + chapters: [ + { + title: 'My super Chapter', + contentBlocks: [ + { + contents: [ + { + type: 'text_block', + value: { + text: 'Das folgende Interview' + }, + id: "df8212ee-3e82-49fa-977e-c4b60789163e" + } + ] + } + ] + } + ] + } + }, + UpdateLastModule: {}, + UpdateContentBookmark: { + updateContentBookmark: { + success: true + } + }, + UpdateChapterBookmark: { + updateChapterBookmark: { + success: true + } + }, + AddNote: ({input: {note}}) => ({ + addNote: { + note + } + }), + UpdateNote: ({input: {note}}) => ({ + updateNote: { + note + } + }) + } + }); + }); + + it('should bookmark instrument', () => { + cy.visit(); + }); + + it('should bookmark module', () => { + cy.visit(); + }); + + it('should bookmark chapter', () => { + cy.visit('/module/lohn-und-budget/'); + + cy.getByDataCy('chapter-bookmark-actions').as('chapterBookmark'); + + cy.get('@chapterBookmark').within(() => { + cy.getByDataCy('bookmark-action').click(); + cy.getByDataCy('add-note-action').click(); + }); + + cy.get('[data-cy=bookmark-note]').within(() => { + cy.get('.skillbox-input').type('Hallo Velo'); + }); + + cy.get('[data-cy=modal-save-button]').click(); + + cy.get('@chapterBookmark').within(() => { + cy.getByDataCy('edit-note-action').click(); + }); + + cy.get('[data-cy=bookmark-note]').within(() => { + cy.get('.skillbox-input').clear().type('Hello Bike'); + }); + + cy.get('[data-cy=modal-save-button]').click(); + }); + + it('should bookmark content block', () => { + cy.visit('/module/lohn-und-budget/'); + + cy.getByDataCy('content-component').contains('Das folgende Interview').parent().parent().as('interviewContent'); + + cy.get('@interviewContent').within(() => { + cy.get('.bookmark-actions__bookmark').click(); + cy.get('.bookmark-actions__add-note').click(); + }); + + cy.get('[data-cy=bookmark-note]').within(() => { + cy.get('.skillbox-input').type('Hallo Velo'); + }); + + cy.get('[data-cy=modal-save-button]').click(); + + cy.get('@interviewContent').within(() => { + cy.get('.bookmark-actions__edit-note').click(); + }); + + cy.get('[data-cy=bookmark-note]').within(() => { + cy.get('.skillbox-input').clear().type('Hello Bike'); + }); + + cy.get('[data-cy=modal-save-button]').click(); + }); +}); diff --git a/client/src/components/Chapter.vue b/client/src/components/Chapter.vue index aa44d271..02bc76a2 100644 --- a/client/src/components/Chapter.vue +++ b/client/src/components/Chapter.vue @@ -2,6 +2,7 @@
{ const query = CHAPTER_QUERY; const variables = {id}; - const data = store.readQuery({ + const {chapter} = store.readQuery({ query, variables, }); - const chapter = data.chapter; + let bookmark; if (bookmarked) { - chapter.bookmark = { + bookmark = { __typename: 'ChapterBookmarkNode', note: null, }; } else { - chapter.bookmark = null; + bookmark = null; } - data.chapter = chapter; + const data = { + chapter: { + ...chapter, + bookmark + } + }; store.writeQuery({ data, diff --git a/client/src/components/content-blocks/ContentComponent.vue b/client/src/components/content-blocks/ContentComponent.vue index b901e381..48d1e4b8 100644 --- a/client/src/components/content-blocks/ContentComponent.vue +++ b/client/src/components/content-blocks/ContentComponent.vue @@ -2,6 +2,7 @@
@@ -19,6 +21,7 @@ getCacheKey({__typename: 'ContentBlockNode', id: args.id}), - contentBlock: { - read: idToRefFactory('ContentBlockNode') - // read(_, {args, toReference}) { - // return toReference({ - // __typename: 'ContentBlockNode', - // id: args.id - // }); - // } - } - }, - // chapter: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ChapterNode', id: args.id}), - chapter: {read: idToRefFactory('ChapterNode')}, - assignment: {read: idToRefFactory('AssignmentNode')}, - objective: {read: idToRefFactory('ObjectiveNode')}, - objectiveGroup: {read: idToRefFactory('ObjectiveGroupNode')}, - projectEntry: {read: idToRefFactory('ProjectEntryNode')}, - project: { - read(_, {args: {slug, id}, toReference}) { - console.log(`Trying to reference project with slug ${slug}, id ${id}`); - if (slug) { - return toReference({ - __typename: 'ProjectNode', - slug - }); - } else { - return toReference({ - __typename: 'ProjectNode', - id - }); - } - } - }, - // assignment: (_, args, {getCacheKey}) => getCacheKey({__typename: 'AssignmentNode', id: args.id}), - // objective: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveNode', id: args.id}), - // objectiveGroup: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveGroupNode', id: args.id}), - // projectEntry: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ProjectEntryNode', id: args.id}), + // these used to be in cacheRedirects, now here + contentBlock: { read: idToRefFactory('ContentBlockNode') }, + chapter: {read: idToRefFactory('ChapterNode')}, + assignment: {read: idToRefFactory('AssignmentNode')}, + objective: {read: idToRefFactory('ObjectiveNode')}, + objectiveGroup: {read: idToRefFactory('ObjectiveGroupNode')}, + projectEntry: {read: idToRefFactory('ProjectEntryNode')}, + project: { + read(_, {args: {slug, id}, toReference}) { + console.log(`Trying to reference project with slug ${slug}, id ${id}`); + if (slug) { + return toReference({ + __typename: 'ProjectNode', + slug + }); + } else { + return toReference({ + __typename: 'ProjectNode', + id + }); + } + } + }, + } }, }; diff --git a/client/src/helpers/new-note-mutation.js b/client/src/helpers/new-note-mutation.js index 39499d89..5c2ccba9 100644 --- a/client/src/helpers/new-note-mutation.js +++ b/client/src/helpers/new-note-mutation.js @@ -16,22 +16,35 @@ export const constructNoteMutation = (n) => { if (n.type === 'ContentBlockNode') { const query = CONTENT_BLOCK_QUERY; const variables = {id: n.block}; - const data = store.readQuery({ + const {contentBlock} = store.readQuery({ query, variables }); - const bookmarks = data.contentBlock.bookmarks; + let bookmarks; - let index = bookmarks.findIndex(compareUuid(n)); + let index = contentBlock.bookmarks.findIndex(compareUuid(n)); if (index > -1) { - let el = bookmarks[index]; - el.note = note; - bookmarks.splice(index, 1, el); + const el = { + ...contentBlock.bookmarks[index], + note + }; + bookmarks = [ + ...contentBlock.bookmarks.slice(0, index), + el, + ...contentBlock.bookmarks.slice(index + 1) + ]; + } else { + bookmarks = [...contentBlock.bookmarks]; } - data.contentBlock.bookmarks = bookmarks; + const data = { + contentBlock: { + ...contentBlock, + bookmarks + } + }; store.writeQuery({ data, @@ -70,16 +83,23 @@ export const constructNoteMutation = (n) => { const type = getBlockType(n.parent) === 'ChapterNode' ? 'chapter' : 'module'; const query = type === 'chapter' ? CHAPTER_QUERY : MODULE_QUERY; const variables = {id: n.parent}; - const data = store.readQuery({ + const fromStore = store.readQuery({ query, variables }); - const bookmark = data[type].bookmark; + const entity = fromStore[type]; + let bookmark = { + ...entity.bookmark, + note + }; - bookmark.note = note; - - data[type].bookmark = bookmark; + const data = { + [type]: { + ...entity, + bookmark + } + }; store.writeQuery({ data, diff --git a/client/src/helpers/update-content-bookmark-mutation.js b/client/src/helpers/update-content-bookmark-mutation.js index 76592747..81e19f1c 100644 --- a/client/src/helpers/update-content-bookmark-mutation.js +++ b/client/src/helpers/update-content-bookmark-mutation.js @@ -70,27 +70,40 @@ export const constructContentComponentBookmarkMutation = (uuid, bookmarked, pare update: (store) => { const query = CONTENT_BLOCK_QUERY; const variables = {id: root}; - const data = store.readQuery({ + const {contentBlock} = store.readQuery({ query, variables }); - const bookmarks = data.contentBlock.bookmarks; + // const bookmarks = data.contentBlock.bookmarks; + let bookmarks; if (bookmarked) { - bookmarks.push({ + bookmarks = [ + ...contentBlock.bookmarks, + { note: null, uuid, __typename: 'ContentBlockBookmarkNode' - }); + } + ]; } else { let index = bookmarks.findIndex(compareUuid(uuid)); if (index > -1) { bookmarks.splice(index, 1); } + bookmarks = [ + ...contentBlock.bookmarks.slice(0, index), + ...contentBlock.bookmarks.slice(index + 1) + ]; } - data.contentBlock.bookmarks = bookmarks; + const data = { + contentBlock: { + ...contentBlock, + bookmarks + } + }; store.writeQuery({ data,