]> source.dussan.org Git - nextcloud-server.git/commitdiff
fix(theming): Adjust dark theme to be accessible adjust cypress tests 41948/head
authorFerdinand Thiessen <opensource@fthiessen.de>
Thu, 30 Nov 2023 22:27:44 +0000 (23:27 +0100)
committerFerdinand Thiessen <opensource@fthiessen.de>
Thu, 30 Nov 2023 23:58:30 +0000 (00:58 +0100)
Also fix warning text color for bright / default theme on blurry background

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
apps/theming/__tests__/accessibility.cy.ts [deleted file]
apps/theming/css/default.css
apps/theming/lib/Themes/DarkTheme.php
apps/theming/lib/Themes/DefaultTheme.php
cypress/e2e/theming/a11y-color-contrast.cy.ts [new file with mode: 0644]
cypress/support/e2e.ts

diff --git a/apps/theming/__tests__/accessibility.cy.ts b/apps/theming/__tests__/accessibility.cy.ts
deleted file mode 100644 (file)
index 3bbf8a6..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// eslint-disable-next-line import/no-webpack-loader-syntax, import/no-unresolved
-import style from '!raw-loader!../css/default.css'
-
-const testCases = {
-       'Main text': {
-               foregroundColors: [
-                       'color-main-text',
-                       // 'color-text-light', deprecated
-                       // 'color-text-lighter', deprecated
-                       'color-text-maxcontrast',
-                       'color-text-maxcontrast-default',
-               ],
-               backgroundColors: [
-                       'color-background-main',
-                       'color-background-hover',
-                       'color-background-dark',
-                       // 'color-background-darker', this should only be used for elements not for text
-               ],
-       },
-       Primary: {
-               foregroundColors: [
-                       'color-primary-text',
-               ],
-               backgroundColors: [
-                       // 'color-primary-default', this should only be used for elements not for text!
-                       // 'color-primary-hover', this should only be used for elements and not for text!
-                       'color-primary',
-               ],
-       },
-       'Primary light': {
-               foregroundColors: [
-                       'color-primary-light-text',
-               ],
-               backgroundColors: [
-                       'color-primary-light',
-                       'color-primary-light-hover',
-               ],
-       },
-       'Primary element': {
-               foregroundColors: [
-                       'color-primary-element-text',
-                       'color-primary-element-text-dark',
-               ],
-               backgroundColors: [
-                       'color-primary-element',
-                       'color-primary-element-hover',
-               ],
-       },
-       'Primary element light': {
-               foregroundColors: [
-                       'color-primary-element-light-text',
-               ],
-               backgroundColors: [
-                       'color-primary-element-light',
-                       'color-primary-element-light-hover',
-               ],
-       },
-       'Servity information texts': {
-               foregroundColors: [
-                       'color-error-text',
-                       'color-warning-text',
-                       'color-success-text',
-                       'color-info-text',
-               ],
-               backgroundColors: [
-                       'color-background-main',
-                       'color-background-hover',
-               ],
-       },
-}
-
-/**
- * Create a wrapper element with color and background set
- *
- * @param foreground The foreground color (css variable without leading --)
- * @param background The background color
- */
-function createTestCase(foreground: string, background: string) {
-       const wrapper = document.createElement('div')
-       wrapper.innerText = `${foreground} ${background}`
-       wrapper.style.color = `var(--${foreground})`
-       wrapper.style.backgroundColor = `var(--${background})`
-       wrapper.style.padding = '4px'
-       wrapper.setAttribute('data-cy-testcase', '')
-       return wrapper
-}
-
-describe('Accessibility of Nextcloud theming', () => {
-       before(() => {
-               cy.injectAxe()
-
-               const el = document.createElement('style')
-               el.innerText = style
-               document.head.appendChild(el)
-       })
-
-       beforeEach(() => {
-               cy.document().then(doc => {
-                       const root = doc.querySelector('[data-cy-root]')
-                       if (root === null) {
-                               throw new Error('No test root found')
-                       }
-                       for (const child of root.children) {
-                               root.removeChild(child)
-                       }
-               })
-       })
-
-       for (const [name, { backgroundColors, foregroundColors }] of Object.entries(testCases)) {
-               context(`Accessibility of CSS color variables for ${name}`, () => {
-                       for (const foreground of foregroundColors) {
-                               for (const background of backgroundColors) {
-                                       it(`color contrast of ${foreground} on ${background}`, () => {
-                                               const element = createTestCase(foreground, background)
-                                               cy.document().then(doc => {
-                                                       const root = doc.querySelector('[data-cy-root]')
-                                                       // eslint-disable-next-line no-unused-expressions
-                                                       expect(root).not.to.be.undefined
-                                                       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-                                                       root!.appendChild(element)
-                                                       cy.checkA11y('[data-cy-testcase]')
-                                               })
-                                       })
-                               }
-                       }
-               })
-       }
-})
index 190ec0fb9cfdaed24e01f8fd1b86833a59a34031..17b3eea8381852d1dc3b7eb512d4aef24ae89bd9 100644 (file)
   --color-error-rgb: 217,24,18;
   --color-error-hover: #dd342f;
   --color-error-text: #c61610;
-  --color-warning: #c28900;
-  --color-warning-rgb: 194,137,0;
-  --color-warning-hover: #cea032;
-  --color-warning-text: #8f6500;
+  --color-warning: #b88100;
+  --color-warning-rgb: 184,129,0;
+  --color-warning-hover: #c69a32;
+  --color-warning-text: #855d00;
   --color-success: #2d7b41;
   --color-success-rgb: 45,123,65;
   --color-success-hover: #448955;
index af374a016035bd0fbc80fb2bc25ff00e4094c456..d33f13dc57909574bbca89351a26ad18bf6ff91f 100644 (file)
@@ -55,15 +55,15 @@ class DarkTheme extends DefaultTheme implements ITheme {
                $colorMainText = '#D8D8D8';
                $colorMainBackground = '#171717';
                $colorMainBackgroundRGB = join(',', $this->util->hexToRGB($colorMainBackground));
-               $colorTextMaxcontrast = $this->util->darken($colorMainText, 30);
+               $colorTextMaxcontrast = $this->util->darken($colorMainText, 28);
 
                $colorBoxShadow = $this->util->darken($colorMainBackground, 70);
                $colorBoxShadowRGB = join(',', $this->util->hexToRGB($colorBoxShadow));
 
-               $colorError = '#d91812';
+               $colorError = '#ee312b';
                $colorWarning = '#c28900';
-               $colorSuccess = '#2d7b41';
-               $colorInfo = '#0071ad';
+               $colorSuccess = '#36914e';
+               $colorInfo = '#007bbd';
 
                return array_merge(
                        $defaultVariables,
index 44930e457fa3c6719101d00856fee8f182d630cd..e215ade7b6dac7a2904934e8dcdefa964f94d847 100644 (file)
@@ -112,7 +112,7 @@ class DefaultTheme implements ITheme {
                $colorBoxShadowRGB = join(',', $this->util->hexToRGB($colorBoxShadow));
 
                $colorError = '#d91812';
-               $colorWarning = '#c28900';
+               $colorWarning = '#b88100';
                $colorSuccess = '#2d7b41';
                $colorInfo = '#0071ad';
 
diff --git a/cypress/e2e/theming/a11y-color-contrast.cy.ts b/cypress/e2e/theming/a11y-color-contrast.cy.ts
new file mode 100644 (file)
index 0000000..03a6814
--- /dev/null
@@ -0,0 +1,153 @@
+const themesToTest = ['light', 'dark', 'light-highcontrast', 'dark-highcontrast']
+
+const testCases = {
+       'Main text': {
+               foregroundColors: [
+                       'color-main-text',
+                       // 'color-text-light', deprecated
+                       // 'color-text-lighter', deprecated
+                       'color-text-maxcontrast',
+               ],
+               backgroundColors: [
+                       'color-main-background',
+                       'color-background-hover',
+                       'color-background-dark',
+                       // 'color-background-darker', this should only be used for elements not for text
+               ],
+       },
+       'blurred background': {
+               foregroundColors: [
+                       'color-main-text',
+                       'color-text-maxcontrast-blur',
+               ],
+               backgroundColors: [
+                       'color-main-background-blur',
+               ],
+       },
+       Primary: {
+               foregroundColors: [
+                       'color-primary-text',
+               ],
+               backgroundColors: [
+                       // 'color-primary-default', this should only be used for elements not for text!
+                       // 'color-primary-hover', this should only be used for elements and not for text!
+                       'color-primary',
+               ],
+       },
+       'Primary light': {
+               foregroundColors: [
+                       'color-primary-light-text',
+               ],
+               backgroundColors: [
+                       'color-primary-light',
+                       'color-primary-light-hover',
+               ],
+       },
+       'Primary element': {
+               foregroundColors: [
+                       'color-primary-element-text',
+                       'color-primary-element-text-dark',
+               ],
+               backgroundColors: [
+                       'color-primary-element',
+                       'color-primary-element-hover',
+               ],
+       },
+       'Primary element light': {
+               foregroundColors: [
+                       'color-primary-element-light-text',
+               ],
+               backgroundColors: [
+                       'color-primary-element-light',
+                       'color-primary-element-light-hover',
+               ],
+       },
+       'Servity information texts': {
+               foregroundColors: [
+                       'color-error-text',
+                       'color-warning-text',
+                       'color-success-text',
+                       'color-info-text',
+               ],
+               backgroundColors: [
+                       'color-main-background',
+                       'color-background-hover',
+                       'color-main-background-blur',
+               ],
+       },
+}
+
+/**
+ * Create a wrapper element with color and background set
+ *
+ * @param foreground The foreground color (css variable without leading --)
+ * @param background The background color
+ */
+function createTestCase(foreground: string, background: string) {
+       const wrapper = document.createElement('div')
+       wrapper.style.padding = '14px'
+       wrapper.style.color = `var(--${foreground})`
+       wrapper.style.backgroundColor = `var(--${background})`
+       if (background.includes('blur')) {
+               wrapper.style.backdropFilter = 'var(--filter-background-blur)'
+       }
+
+       const testCase = document.createElement('div')
+       testCase.innerText = `${foreground} ${background}`
+       testCase.setAttribute('data-cy-testcase', '')
+
+       wrapper.appendChild(testCase)
+       return wrapper
+}
+
+describe('Accessibility of Nextcloud theming colors', () => {
+       for (const theme of themesToTest) {
+               context(`Theme: ${theme}`, () => {
+                       before(() => {
+                               cy.createRandomUser().then(($user) => {
+                                       // set user theme
+                                       cy.runOccCommand(`user:setting -- '${$user.userId}' theming enabled-themes '["${theme}"]'`)
+                                       cy.login($user)
+                                       cy.visit('/')
+                                       cy.injectAxe({ axeCorePath: 'node_modules/axe-core/axe.min.js' })
+                               })
+                       })
+
+                       beforeEach(() => {
+                               cy.document().then(doc => {
+                                       // Unset background image and thus use background-color for testing blur background (images do not work with axe-core)
+                                       doc.body.style.backgroundImage = 'unset'
+
+                                       const root = doc.querySelector('main')
+                                       if (root === null) {
+                                               throw new Error('No test root found')
+                                       }
+                                       root.innerHTML = ''
+                               })
+                       })
+
+                       for (const [name, { backgroundColors, foregroundColors }] of Object.entries(testCases)) {
+                               context(`Accessibility of CSS color variables for ${name}`, () => {
+                                       for (const foreground of foregroundColors) {
+                                               for (const background of backgroundColors) {
+                                                       it(`color contrast of ${foreground} on ${background}`, () => {
+                                                               cy.document().then(doc => {
+                                                                       const element = createTestCase(foreground, background)
+                                                                       const root = doc.querySelector('main')
+                                                                       // eslint-disable-next-line no-unused-expressions
+                                                                       expect(root).not.to.be.undefined
+                                                                       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+                                                                       root!.appendChild(element)
+
+                                                                       cy.checkA11y('[data-cy-testcase]', {
+                                                                               runOnly: ['color-contrast'],
+                                                                       })
+                                                               })
+                                                       })
+                                               }
+                                       }
+                               })
+                       }
+               })
+       }
+})
index 2bc91f83ebd55709b701574e2da884eca6ff01b9..6cf83e949610270bae7f7bbfba983a5c47b9cfbf 100644 (file)
@@ -19,6 +19,7 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  *
  */
+import 'cypress-axe'
 import './commands.ts'
 
 // Fix ResizeObserver loop limit exceeded happening in Cypress only