From fbc37fca0efab7bb6003ba899978ba81b9812d2d Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 15 Nov 2023 12:26:24 +0100 Subject: [PATCH] test(cy) extract and use api for seeding pages Signed-off-by: Max --- cypress/e2e/collective-readonly.spec.js | 6 +- cypress/e2e/dashboard-widget.spec.js | 3 +- cypress/e2e/page-details.spec.js | 5 +- cypress/e2e/page-landingpage.spec.js | 7 +- cypress/e2e/page-list.spec.js | 32 +++---- cypress/e2e/pages-links.spec.js | 20 ++-- cypress/e2e/pages.spec.js | 14 +-- cypress/support/commands.js | 121 ++++++++++++------------ src/api.js | 15 +++ src/store/pages.js | 19 ++-- 10 files changed, 131 insertions(+), 111 deletions(-) diff --git a/cypress/e2e/collective-readonly.spec.js b/cypress/e2e/collective-readonly.spec.js index b141f1fbf3..a8696e274e 100644 --- a/cypress/e2e/collective-readonly.spec.js +++ b/cypress/e2e/collective-readonly.spec.js @@ -25,11 +25,11 @@ describe('Read-only collective', function() { before(function() { cy.loginAs('alice') cy.deleteAndSeedCollective('PermissionCollective') - cy.visit('apps/collectives/PermissionCollective') - cy.seedPage('SecondPage', '', 'Readme.md') - cy.seedCollectivePermissions('PermissionCollective', 'edit', 4) + .seedPage('SecondPage') cy.circleFind('PermissionCollective') .circleAddMember('bob') + cy.visit('apps/collectives/PermissionCollective') + cy.seedCollectivePermissions('PermissionCollective', 'edit', 4) }) describe('in read-only collective', function() { diff --git a/cypress/e2e/dashboard-widget.spec.js b/cypress/e2e/dashboard-widget.spec.js index 15b7b18122..4671f4aada 100644 --- a/cypress/e2e/dashboard-widget.spec.js +++ b/cypress/e2e/dashboard-widget.spec.js @@ -31,8 +31,7 @@ describe('Collectives dashboard widget', function() { cy.loginAs('bob') cy.enableDashboardWidget('collectives-recent-pages') cy.deleteAndSeedCollective('Dashboard Collective1') - cy.visit('apps/collectives/Dashboard Collective1') - cy.seedPage('Page 1', '', 'Readme.md') + .seedPage('Page 1', '', 'Readme.md') }) it('Lists pages in the dashboard widget', function() { cy.visit('/apps/dashboard/') diff --git a/cypress/e2e/page-details.spec.js b/cypress/e2e/page-details.spec.js index 0c039e4aa5..ddfd98d842 100644 --- a/cypress/e2e/page-details.spec.js +++ b/cypress/e2e/page-details.spec.js @@ -28,10 +28,9 @@ describe('Page details', function() { before(function() { cy.loginAs('bob') cy.deleteAndSeedCollective('Our Garden') - cy.visit('/apps/collectives/Our Garden') - cy.seedPage('Day 1', '', 'Readme.md') + .seedPage('Day 1', '', 'Readme.md') + .seedPage('TableOfContents', '', 'Readme.md') cy.seedPageContent('Our Garden/Day 2.md', 'A test string with Day 2 in the middle and a [link to Day 1](/index.php/apps/collectives/Our%20Garden/Day%201).') - cy.seedPage('TableOfContents', '', 'Readme.md') cy.seedPageContent('Our Garden/TableOfContents.md', '## Second-Level Heading') }) diff --git a/cypress/e2e/page-landingpage.spec.js b/cypress/e2e/page-landingpage.spec.js index f2b2cad785..a7d8710e9e 100644 --- a/cypress/e2e/page-landingpage.spec.js +++ b/cypress/e2e/page-landingpage.spec.js @@ -30,13 +30,12 @@ describe('Page landing page', function() { before(function() { cy.loginAs('bob') cy.deleteAndSeedCollective(collective) - cy.visit(`/apps/collectives/${collective}`) + .seedPage('Page 1', '', 'Readme.md') + .seedPage('Page 2', '', 'Readme.md') + .seedPage('Page 3', '', 'Readme.md') cy.circleFind(collective).circleAddMember('alice') cy.circleFind(collective).circleAddMember('jane') cy.circleFind(collective).circleAddMember('john') - cy.seedPage('Page 1', '', 'Readme.md') - cy.seedPage('Page 2', '', 'Readme.md') - cy.seedPage('Page 3', '', 'Readme.md') }) beforeEach(function() { diff --git a/cypress/e2e/page-list.spec.js b/cypress/e2e/page-list.spec.js index f86298629d..74b0419434 100644 --- a/cypress/e2e/page-list.spec.js +++ b/cypress/e2e/page-list.spec.js @@ -28,24 +28,24 @@ describe('Page list', function() { before(function() { cy.loginAs('bob') cy.deleteAndSeedCollective('Our Garden') - cy.deleteAndSeedCollective('MoveCopyTargetCollective') - cy.visit('apps/collectives/Our Garden') - cy.seedPage('Target', '', 'Readme.md') - cy.seedPage('Target Subpage', '', 'Target.md') + .as('garden') + .seedPage('Target', '', 'Readme.md') + .seedPage('Target Subpage', '', 'Target.md') // Wait 1 second to make sure that page order by time is right cy.wait(1000) // eslint-disable-line cypress/no-unnecessary-waiting - cy.seedPage('Day 1', '', 'Readme.md') - cy.seedPage('Subpage Title', '', 'Day 1.md') - cy.seedPage('Day 2', '', 'Readme.md') - cy.seedPage('Page Title', '', 'Readme.md') - cy.seedPage('Move me internal', '', 'Readme.md') - cy.seedPage('Copy me internal', '', 'Readme.md') - cy.seedPage('Move me external', '', 'Readme.md') - cy.seedPage('Copy me external', '', 'Readme.md') - cy.seedPage('#% special chars', '', 'Readme.md') - cy.openCollective('MoveCopyTargetCollective') - cy.seedPage('Target external', '', 'Readme.md') - cy.seedPage('Target Subpage external', '', 'Target external.md') + cy.then(() => this.garden) + .seedPage('Day 1', '', 'Readme.md') + .seedPage('Subpage Title', '', 'Day 1.md') + .seedPage('Day 2', '', 'Readme.md') + .seedPage('Page Title', '', 'Readme.md') + .seedPage('Move me internal', '', 'Readme.md') + .seedPage('Copy me internal', '', 'Readme.md') + .seedPage('Move me external', '', 'Readme.md') + .seedPage('Copy me external', '', 'Readme.md') + .seedPage('#% special chars', '', 'Readme.md') + cy.deleteAndSeedCollective('MoveCopyTargetCollective') + .seedPage('Target external', '', 'Readme.md') + .seedPage('Target Subpage external', '', 'Target external.md') }) beforeEach(function() { diff --git a/cypress/e2e/pages-links.spec.js b/cypress/e2e/pages-links.spec.js index 0ba9a95ac7..355b4f3fa2 100644 --- a/cypress/e2e/pages-links.spec.js +++ b/cypress/e2e/pages-links.spec.js @@ -33,19 +33,17 @@ describe('Page Link Handling', function() { before(function() { cy.loginAs('bob') cy.deleteAndSeedCollective('Another Collective') + .seedPage('First Page', '', 'Readme.md').then(({ pageId }) => { + anotherCollectiveFirstPageId = pageId + }) cy.deleteAndSeedCollective('Link Testing') - cy.visit('/apps/collectives/Another Collective') - cy.seedPage('First Page', '', 'Readme.md').then((id) => { - anotherCollectiveFirstPageId = id - }) - cy.openCollective('Link Testing') - cy.seedPage('Parent', '', 'Readme.md') - cy.seedPage('Child', '', 'Parent.md') - cy.seedPage('Link Target', '', 'Readme.md').then((id) => { - linkTargetPageId = id - }) + .seedPage('Parent', '', 'Readme.md') + .seedPage('Child', '', 'Parent.md') + .seedPage('Link Target', '', 'Readme.md').then(({ pageId }) => { + linkTargetPageId = pageId + }) + .seedPage('Link Source', '', 'Readme.md') cy.seedPageContent('Link%20Testing/Link%20Target.md', 'Some content') - cy.seedPage('Link Source', '', 'Readme.md') cy.uploadFile('test.md', 'text/markdown').then((id) => { textId = id }).then(() => { diff --git a/cypress/e2e/pages.spec.js b/cypress/e2e/pages.spec.js index 45b6711ef9..6a2ecc4ee9 100644 --- a/cypress/e2e/pages.spec.js +++ b/cypress/e2e/pages.spec.js @@ -27,16 +27,16 @@ describe('Page', function() { before(function() { cy.loginAs('bob') - cy.deleteAndSeedCollective('Our Garden') - cy.visit('/apps/collectives/Our Garden') - cy.seedPage('Day 1', '', 'Readme.md') + cy.deleteAndSeedCollective('Our Garden').as('garden') + .seedPage('Day 1', '', 'Readme.md') // Wait 1 second to make sure that page order by time is right cy.wait(1000) // eslint-disable-line cypress/no-unnecessary-waiting - cy.seedPage('Day 2', '', 'Readme.md') - cy.seedPage('Page Title', '', 'Readme.md') - cy.seedPage('#% special chars', '', 'Readme.md') + cy.then(() => this.garden) + .seedPage('Day 2', '', 'Readme.md') + .seedPage('Page Title', '', 'Readme.md') + .seedPage('#% special chars', '', 'Readme.md') + .seedPage('Template', '', 'Readme.md') cy.seedPageContent('Our Garden/Day 2.md', 'A test string with Day 2 in the middle and a [link to Day 1](/index.php/apps/collectives/Our%20Garden/Day%201).') - cy.seedPage('Template', '', 'Readme.md') cy.seedPageContent('Our Garden/Template.md', 'This is going to be our template.') }) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index a411ae4ddb..f13ae40170 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -5,13 +5,12 @@ import { UPDATE_COLLECTIVE_EDIT_PERMISSIONS, UPDATE_COLLECTIVE_SHARE_PERMISSIONS, UPDATE_COLLECTIVE_PAGE_MODE, - GET_PAGES, - NEW_PAGE, GET_CIRCLES, } from '../../src/store/actions.js' import * as api from '../../src/api.js' import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' const url = Cypress.config('baseUrl').replace(/\/index.php\/?$/g, '') Cypress.env('baseUrl', url) @@ -272,49 +271,37 @@ Cypress.Commands.add('seedCollectivePageMode', (name, mode) => { .dispatch(UPDATE_COLLECTIVE_PAGE_MODE, { mode }) }) -/** - * Add a page to a collective - */ -Cypress.Commands.add('seedPage', (name, parentFilePath, parentFileName) => { - Cypress.log() - cy.dispatch(GET_PAGES) - cy.store('state.pages.pages') - .findBy({ filePath: parentFilePath, fileName: parentFileName }) - .its('id') - .as('parentId') - .then(id => ({ parentId: id })) - .dispatch(NEW_PAGE, { title: name, pagePath: name }) - // Return pageId of created page - cy.get('@parentId').then(parentId => { - return cy.store('state.pages.pages') - .findBy({ parentId, title: name }) - .its('id') - }) +function collectiveContext(collective) { + return { + isPublic: false, + collectiveId: collective.id, + shareTokenParam: null, + } +} + +Cypress.Commands.add('getPages', collective => { + return api.getPages(collectiveContext(collective)) + .then(response => response.data.data) }) /** - * Upload a file + * Add a page to a collective */ -Cypress.Commands.add('uploadFile', (path, mimeType, remotePath = '') => { - Cypress.log() - // Get fixture - return cy.fixture(path, 'base64').then(file => { - // convert the base64 string to a blob - const blob = Cypress.Blob.base64StringToBlob(file, mimeType) - try { - const file = new File([blob], path, { type: mimeType }) - return cy.uploadContent(remotePath + path, file, mimeType) - .then(response => { - const ocFileId = response.headers['oc-fileid'] - const fileId = parseInt(ocFileId.substring(0, ocFileId.indexOf('oc'))) - return fileId - }) - } catch (error) { - cy.log(error) - throw new Error(`Unable to process file ${path}`) - } +Cypress.Commands.add('seedPage', + { prevSubject: true }, + (subject, name, parentFilePath = '', parentFileName = 'Readme.md') => { + Cypress.log() + cy.getPages(subject) + .findBy({ filePath: parentFilePath, fileName: parentFileName }) + .then(({ id: parentId }) => { + return api.createPage( + collectiveContext(subject), + { parentId, title: name, pagePath: name }, + ) + }) + .its('data.data.id') + .then(pageId => ({ ...subject, pageId })) }) -}) /** * Upload content of a page @@ -327,22 +314,38 @@ Cypress.Commands.add('seedPageContent', (pagePath, content) => { cy.uploadContent(`Collectives/${pagePath}`, content) }) +Cypress.Commands.add('uploadFile', (path, mimeType, remotePath = '') => { + Cypress.log() + // Get fixture + return cy.fixture(path, 'base64').then(data => { + // convert the base64 string to a blob + const blob = Cypress.Blob.base64StringToBlob(data, mimeType) + const file = new File([blob], path, { type: mimeType }) + return cy.uploadContent(remotePath + path, file, mimeType) + .then(response => { + const ocFileId = response.headers['oc-fileid'] + const fileId = parseInt(ocFileId.substring(0, ocFileId.indexOf('oc'))) + return fileId + }) + }) +}) + + /** * Generic upload of content - used by seedPageContent and uploadPage */ Cypress.Commands.add('uploadContent', (path, content, mimetype = 'text/markdown') => { // @nextcloud/axios automatic handling for request tokens does not work for webdav - cy.window() - .its('app.OC.requestToken') - .then(requesttoken => { - const url = `${Cypress.env('baseUrl')}/remote.php/webdav/${path}` - return axios.put(url, content, { - headers: { - requesttoken, - 'Content-Type': mimetype, - }, - }) + cy.request('/csrftoken').then(({ body }) => { + const requesttoken = body.token + const url = `${Cypress.env('baseUrl')}/remote.php/webdav/${path}` + return axios.put(url, content, { + headers: { + requesttoken, + 'Content-Type': mimetype, + }, }) + }) }) /** @@ -350,9 +353,7 @@ Cypress.Commands.add('uploadContent', (path, content, mimetype = 'text/markdown' */ Cypress.Commands.add('seedCircle', (name, config = null) => { Cypress.log() - cy.dispatch(GET_CIRCLES) - cy.store('state.circles.circles') - .findBy({ sanitizedName: name }) + cy.circleFind(name) .then(async circle => { const url = `${Cypress.env('baseUrl')}/ocs/v2.php/apps/circles/circles` let circleId @@ -380,16 +381,20 @@ Cypress.Commands.add('seedCircle', (name, config = null) => { }) }) -/** - * Add someone to a circle - */ +Cypress.Commands.add('getCircles', () => { + return axios.get(generateOcsUrl('apps/circles/circles')) + .then(response => response.data.ocs.data) +}) + Cypress.Commands.add('circleFind', (name) => { Cypress.log() - cy.dispatch(GET_CIRCLES) - return cy.store('state.circles.circles') + cy.getCircles() .findBy({ sanitizedName: name }) }) +/** + * Add someone to a circle + */ Cypress.Commands.add('circleAddMember', { prevSubject: true }, async ({ id }, userId, type = 1) => { diff --git a/src/api.js b/src/api.js index bdf9c1d9d2..d73da56ba3 100644 --- a/src/api.js +++ b/src/api.js @@ -34,3 +34,18 @@ export function deleteCollective(id, circle) { } return axios.delete(url('/trash/' + id + doCircle)) } + +export function getPages(context) { + return axios.get(pagesUrl(context)) +} + +export function createPage(context, page) { + const url = pagesUrl(context) + '/' + page.parentId + return axios.post(url, page) +} + +export function pagesUrl({ isPublic = false, shareTokenParam, collectiveId }) { + return isPublic + ? url(`/p/${shareTokenParam}/_pages`) + : url(`/${collectiveId}/_pages`) +} diff --git a/src/store/pages.js b/src/store/pages.js index d11f47f1be..29e94bbd48 100644 --- a/src/store/pages.js +++ b/src/store/pages.js @@ -6,6 +6,7 @@ import { generateRemoteUrl, generateUrl } from '@nextcloud/router' /* eslint import/namespace: ['error', { allowComputed: true }] */ import * as sortOrders from '../util/sortOrders.js' import { sortedSubpages, pageParents } from './pageExtracts.js' +import * as api from '../api.js' import { SET_PAGES, @@ -242,16 +243,20 @@ export default { return state.newPage && getters.pagePath(state.newPage) }, + context(_state, getters) { + return { + isPublic: getters.isPublic, + collectiveId: getters.currentCollective.id, + shareTokenParam: getters.shareTokenParam, + } + }, + pagesUrl(_state, getters) { return getters.isPublic ? generateUrl(`/apps/collectives/_api/p/${getters.shareTokenParam}/_pages`) : generateUrl(`/apps/collectives/_api/${getters.currentCollective.id}/_pages`) }, - pageCreateUrl(_state, getters) { - return parentId => `${getters.pagesUrl}/${parentId}` - }, - pageUrl(_state, getters) { return (pageId) => `${getters.pagesUrl}/${pageId}` }, @@ -507,7 +512,7 @@ export default { if (setLoading) { commit('load', 'collective') } - const response = await axios.get(getters.pagesUrl) + const response = await api.getPages(getters.context) commit(SET_PAGES, { pages: response.data.data, current: getters.currentPage, @@ -557,7 +562,7 @@ export default { // We'll be done when the editor is loaded. commit('load', 'newPageContent') - const response = await axios.post(getters.pageCreateUrl(page.parentId), page) + const response = await api.createPage(getters.context, page) // Add new page to the beginning of pages array commit(ADD_PAGE, response.data.data) }, @@ -579,7 +584,7 @@ export default { // We'll be done when the editor is loaded. commit('load', 'newPageContent') - const response = await axios.post(getters.pageCreateUrl(page.parentId), page) + const response = await api.createPage(getters.context, page) // Add new page to the beginning of pages array commit(ADD_PAGE, response.data.data) },