diff options
author | John Molakvoæ <skjnldsv@protonmail.com> | 2022-11-30 17:45:58 +0100 |
---|---|---|
committer | John Molakvoæ <skjnldsv@protonmail.com> | 2022-11-30 18:39:57 +0100 |
commit | f26ee9c69d98b9208f709e0c7aa284755708adbd (patch) | |
tree | 1edfb8f4d680e6e4ff3940e3f1ac3f068326fd8e /cypress | |
parent | 8434259b1bfef22adbf30b166043e29763bf9507 (diff) | |
download | nextcloud-server-f26ee9c69d98b9208f709e0c7aa284755708adbd.tar.gz nextcloud-server-f26ee9c69d98b9208f709e0c7aa284755708adbd.zip |
Faster theming tests, better colours comparison and properly follow admin theming changes
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'cypress')
-rw-r--r-- | cypress/e2e/theming/admin-settings.cy.ts | 170 | ||||
-rw-r--r-- | cypress/e2e/theming/themingUtils.ts | 75 | ||||
-rw-r--r-- | cypress/e2e/theming/user-background.cy.ts | 10 | ||||
-rw-r--r-- | cypress/support/commands.ts | 33 |
4 files changed, 202 insertions, 86 deletions
diff --git a/cypress/e2e/theming/admin-settings.cy.ts b/cypress/e2e/theming/admin-settings.cy.ts index 1c825ecd89e..23e7ab9858f 100644 --- a/cypress/e2e/theming/admin-settings.cy.ts +++ b/cypress/e2e/theming/admin-settings.cy.ts @@ -20,6 +20,9 @@ * */ import { User } from '@nextcloud/cypress' +import { colord } from 'colord' + +import { pickRandomColor, validateBodyThemingCss, validateUserThemingDefaultCss } from './themingUtils' const admin = new User('admin', 'admin') @@ -28,6 +31,8 @@ const defaultBackground = 'kamil-porembinski-clouds.jpg' describe('Admin theming settings', function() { before(function() { + // Just in case previous test failed + cy.resetTheming() cy.login(admin) }) @@ -39,13 +44,16 @@ describe('Admin theming settings', function() { it('See the default settings', function() { cy.get('[data-admin-theming-setting-primary-color-picker]').should('contain.text', defaultPrimary) cy.get('[data-admin-theming-setting-primary-color-reset]').should('not.exist') - cy.get('[data-admin-theming-setting-background-reset]').should('not.exist') - cy.get('[data-admin-theming-setting-background-remove]').should('be.visible') + cy.get('[data-admin-theming-setting-file-reset]').should('not.exist') + cy.get('[data-admin-theming-setting-file-remove]').should('be.visible') }) }) -describe('Change the primary colour', function() { +describe('Change the primary colour and reset it', function() { + let selectedColor = '' before(function() { + // Just in case previous test failed + cy.resetTheming() cy.login(admin) }) @@ -57,14 +65,11 @@ describe('Change the primary colour', function() { it('Change the primary colour', function() { cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor') - cy.get('[data-admin-theming-setting-primary-color-picker]').click() - cy.get('.color-picker__simple-color-circle:eq(3)').click() + pickRandomColor('[data-admin-theming-setting-primary-color-picker]') + .then(color => selectedColor = color) cy.wait('@setColor') - cy.waitUntil(() => cy.window().then((win) => { - const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary-default') - return primary !== defaultPrimary - })) + cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground)) }) it('Screenshot the login page', function() { @@ -73,32 +78,21 @@ describe('Change the primary colour', function() { cy.screenshot() }) - it('Login again and go to the admin theming section', function() { - cy.login(admin) - cy.visit('/settings/admin/theming') - }) - - it('Reset the primary colour', function() { - cy.intercept('*/apps/theming/ajax/undoChanges').as('undoChanges') - - cy.get('[data-admin-theming-setting-primary-color-reset]').click() - - cy.wait('@undoChanges') - cy.waitUntil(() => cy.window().then((win) => { - const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary-default') - return primary === defaultPrimary - })) + it('Undo theming settings', function() { + cy.resetTheming() }) it('Screenshot the login page', function() { - cy.logout() cy.visit('/') + cy.waitUntil(validateBodyThemingCss) cy.screenshot() }) }) -describe('Remove the default background', function() { +describe('Remove the default background and restore it', function() { before(function() { + // Just in case previous test failed + cy.resetTheming() cy.login(admin) }) @@ -110,13 +104,13 @@ describe('Remove the default background', function() { it('Remove the default background', function() { cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground') - cy.get('[data-admin-theming-setting-background-remove]').click() + cy.get('[data-admin-theming-setting-file-remove]').click() cy.wait('@removeBackground') cy.waitUntil(() => cy.window().then((win) => { - const backgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default') + const currentBackgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default') const backgroundPlain = getComputedStyle(win.document.body).getPropertyValue('--image-background-plain') - return !backgroundDefault.includes(defaultBackground) + return !currentBackgroundDefault.includes(defaultBackground) && backgroundPlain !== '' })) }) @@ -127,38 +121,25 @@ describe('Remove the default background', function() { cy.screenshot() }) - it('Login again and go to the admin theming section', function() { - cy.login(admin) - cy.visit('/settings/admin/theming') - }) - - it('Restore the default background', function() { - cy.intercept('*/apps/theming/ajax/undoChanges').as('undoChanges') - - cy.get('[data-admin-theming-setting-background-reset]').click() - - cy.wait('@undoChanges') - cy.waitUntil(() => cy.window().then((win) => { - const backgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default') - const backgroundPlain = getComputedStyle(win.document.body).getPropertyValue('--image-background-plain') - return backgroundDefault.includes(defaultBackground) - && backgroundPlain === '' - })) + it('Undo theming settings', function() { + cy.resetTheming() }) it('Screenshot the login page', function() { - cy.logout() cy.visit('/') + cy.waitUntil(validateBodyThemingCss) cy.screenshot() }) }) -describe('Change the login fields', function() { +describe('Change the login fields then reset them', function() { const name = 'ABCdef123' const url = 'https://example.com' const slogan = 'Testing is fun' before(function() { + // Just in case previous test failed + cy.resetTheming() cy.login(admin) }) @@ -214,29 +195,11 @@ describe('Change the login fields', function() { cy.get('footer p').should('contain.text', `– ${slogan}`) }) - it('Login again and go to the admin theming section', function() { - cy.login(admin) - cy.visit('/settings/admin/theming') - }) - - it('Undo changes', function() { - cy.intercept('*/apps/theming/ajax/undoChanges').as('undoChanges') - - cy.get('[data-admin-theming-setting-field="name"] .input-field__clear-button') - .scrollIntoView().click() - cy.wait('@undoChanges') - - cy.get('[data-admin-theming-setting-field="url"] .input-field__clear-button') - .scrollIntoView().click() - cy.wait('@undoChanges') - - cy.get('[data-admin-theming-setting-field="slogan"] .input-field__clear-button') - .scrollIntoView().click() - cy.wait('@undoChanges') + it('Undo theming settings', function() { + cy.resetTheming() }) it('Check login screen changes', function() { - cy.logout() cy.visit('/') cy.get('[data-login-form-headline]').should('not.contain.text', name) @@ -246,8 +209,10 @@ describe('Change the login fields', function() { }) }) -describe('Disable user theming', function() { +describe('Disable user theming and enable it back', function() { before(function() { + // Just in case previous test failed + cy.resetTheming() cy.login(admin) }) @@ -278,25 +243,74 @@ describe('Disable user theming', function() { cy.visit('/settings/user/theming') cy.get('[data-user-theming-background-disabled]').scrollIntoView().should('be.visible') }) +}) - it('Login back as admin', function() { - cy.logout() +describe('User default option matches admin theming', function() { + let selectedColor = '' + + before(function() { + // Just in case previous test failed + cy.resetTheming() cy.login(admin) }) + after(function() { + cy.resetTheming() + }) + it('See the admin theming section', function() { cy.visit('/settings/admin/theming') cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible') }) - it('Enable back user theming', function() { - cy.intercept('*/apps/theming/ajax/updateStylesheet').as('enableUserTheming') + it('Change the primary colour', function() { + cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor') - cy.get('[data-admin-theming-setting-disable-user-theming]') - .scrollIntoView().should('be.visible') - cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').uncheck({ force: true }) - cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').should('not.be.checked') + pickRandomColor('[data-admin-theming-setting-primary-color-picker]') + .then(color => selectedColor = color) + + cy.wait('@setColor') + cy.waitUntil(() => cy.window().then((win) => { + const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary-default') + return colord(primary).isEqual(selectedColor) + })) + }) + + it('Change the default background', function() { + cy.intercept('*/apps/theming/ajax/uploadImage').as('setBackground') + + cy.fixture('image.jpg', null).as('background') + cy.get('[data-admin-theming-setting-file="background"] input[type="file"]').selectFile('@background', { force: true }) + + cy.wait('@setBackground') + cy.waitUntil(() => cy.window().then((win) => { + const currentBackgroundDefault = getComputedStyle(win.document.body).getPropertyValue('--image-background-default') + return currentBackgroundDefault.includes('/apps/theming/image/background?v=') + })) + }) + + it('Logout and check changes', function() { + cy.logout() + cy.visit('/') + + cy.waitUntil(() => validateBodyThemingCss(selectedColor, '/apps/theming/image/background?v=')) + }) + + it('Login as user', function() { + cy.createRandomUser().then((user) => { + cy.login(user) + }) + }) + + it('See the user background settings', function() { + cy.visit('/settings/user/theming') + cy.get('[data-user-theming-background-settings]').scrollIntoView().should('be.visible') + }) + + it('See the default background option selected', function() { + cy.get('[data-user-theming-background-default]').should('be.visible') + cy.get('[data-user-theming-background-default]').should('have.class', 'background--active') - cy.wait('@enableUserTheming') + cy.waitUntil(() => validateUserThemingDefaultCss(selectedColor, '/apps/theming/image/background?v=')) }) }) diff --git a/cypress/e2e/theming/themingUtils.ts b/cypress/e2e/theming/themingUtils.ts new file mode 100644 index 00000000000..2cdbb07c000 --- /dev/null +++ b/cypress/e2e/theming/themingUtils.ts @@ -0,0 +1,75 @@ +/** + * @copyright Copyright (c) 2022 John Molakvoæ <skjnldsv@protonmail.com> + * + * @author John Molakvoæ <skjnldsv@protonmail.com> + * + * @license AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +import { colord } from 'colord' + +/** + * Validate the current page body css variables + * + * @param {string} expectedColor the expected color + * @param {string} expectedBackground the expected background + */ +export const validateBodyThemingCss = function(expectedColor = '#0082c9', expectedBackground = 'kamil-porembinski-clouds.jpg') { + return cy.window().then((win) => { + const guestBackgroundColor = getComputedStyle(win.document.body).backgroundColor + const guestBackgroundImage = getComputedStyle(win.document.body).backgroundImage + return colord(guestBackgroundColor).isEqual(expectedColor) + && guestBackgroundImage.includes(expectedBackground) + }) +} + +/** + * Validate the user theming default select option css + * + * @param {string} expectedColor the expected color + * @param {string} expectedBackground the expected background + */ +export const validateUserThemingDefaultCss = function(expectedColor = '#0082c9', expectedBackground = 'kamil-porembinski-clouds.jpg') { + return cy.window().then((win) => { + const defaultSelectButton = win.document.querySelector('[data-user-theming-background-default]') + const customColorSelectButton = win.document.querySelector('[data-user-theming-background-color]') + if (!defaultSelectButton || !customColorSelectButton) { + return false + } + + const defaultOptionBackground = getComputedStyle(defaultSelectButton).backgroundImage + const defaultOptionBorderColor = getComputedStyle(defaultSelectButton).borderColor + const colorPickerOptionColor = getComputedStyle(customColorSelectButton).backgroundColor + return defaultOptionBackground.includes(expectedBackground) + && colord(defaultOptionBorderColor).isEqual(expectedColor) + && colord(colorPickerOptionColor).isEqual(expectedColor) + }) +} + +export const pickRandomColor = function(pickerSelector: string): Cypress.Chainable<string> { + // Pick one of the first 8 options + const randColour = Math.floor(Math.random() * 8) + + // Open picker + cy.get(pickerSelector).click() + + // Return selected colour + return cy.get(pickerSelector).get(`.color-picker__simple-color-circle`).eq(randColour) + .click().then(colorElement => { + const selectedColor = colorElement.css('background-color') + return selectedColor + }) +}
\ No newline at end of file diff --git a/cypress/e2e/theming/user-background.cy.ts b/cypress/e2e/theming/user-background.cy.ts index 846bc984fe1..ded0d89efec 100644 --- a/cypress/e2e/theming/user-background.cy.ts +++ b/cypress/e2e/theming/user-background.cy.ts @@ -23,16 +23,17 @@ import type { User } from '@nextcloud/cypress' const defaultPrimary = '#006aa3' const defaultBackground = 'kamil-porembinski-clouds.jpg' +import { colord } from 'colord' const validateThemingCss = function(expectedPrimary = '#0082c9', expectedBackground = 'kamil-porembinski-clouds.jpg', bright = false) { return cy.window().then((win) => { - const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary') - const background = getComputedStyle(win.document.body).getPropertyValue('--image-background') + const backgroundColor = getComputedStyle(win.document.body).backgroundColor + const backgroundImage = getComputedStyle(win.document.body).backgroundImage const invertIfBright = getComputedStyle(win.document.body).getPropertyValue('--background-image-invert-if-bright') // Returning boolean for cy.waitUntil usage - return primary === expectedPrimary - && background.includes(expectedBackground) + return colord(backgroundColor).isEqual(expectedPrimary) + && backgroundImage.includes(expectedBackground) && invertIfBright === (bright ? 'invert(100%)' : 'no') }) } @@ -163,7 +164,6 @@ describe('User select a custom background', function() { }) }) - describe('User changes settings and reload the page', function() { const image = 'image.jpg' const primaryFromImage = '#4c0c04' diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 2b51f719452..eab26beda79 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -21,7 +21,7 @@ */ /* eslint-disable node/no-unpublished-import */ import axios from '@nextcloud/axios' -import { addCommands, type User} from '@nextcloud/cypress' +import { addCommands, User } from '@nextcloud/cypress' import { basename } from 'path' // Add custom commands @@ -33,7 +33,8 @@ declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Cypress { interface Chainable<Subject = any> { - uploadFile(user: User, fixture: string, mimeType: string, target ?: string): Cypress.Chainable<void> + uploadFile(user: User, fixture?: string, mimeType?: string, target ?: string): Cypress.Chainable<void>, + resetTheming(): Cypress.Chainable<void>, } } } @@ -50,7 +51,7 @@ Cypress.env('baseUrl', url) * @param {string} mimeType e.g. image/png * @param {string} [target] the target of the file relative to the user root */ -Cypress.Commands.add('uploadFile', (user, fixture, mimeType, target = `/${fixture}`) => { +Cypress.Commands.add('uploadFile', (user, fixture = 'image.jpg', mimeType = 'image/jpeg', target = `/${fixture}`) => { cy.clearCookies() const fileName = basename(target) @@ -84,3 +85,29 @@ Cypress.Commands.add('uploadFile', (user, fixture, mimeType, target = `/${fixtur } }) }) + +/** + * Reset the admin theming entirely + */ + Cypress.Commands.add('resetTheming', () => { + const admin = new User('admin', 'admin') + + cy.clearCookies() + cy.login(admin) + + // Clear all settings + cy.request('/csrftoken').then(({ body }) => { + const requestToken = body.token + + axios({ + method: 'POST', + url: '/index.php/apps/theming/ajax/undoAllChanges', + headers: { + 'requesttoken': requestToken, + }, + }) + }) + + // Clear admin session + cy.clearCookies() +}) |