aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2024-01-20 07:43:04 +0100
committerFerdinand Thiessen <opensource@fthiessen.de>2024-05-21 20:36:26 +0200
commit538a04968a24f645b12ca2647952a5b73ebc3eac (patch)
treefe6de92830c3cab15b8e2ea96e473566267726c7
parent11dbfa636d746eac4a82460d0677dc6ffe98f068 (diff)
downloadnextcloud-server-538a04968a24f645b12ca2647952a5b73ebc3eac.tar.gz
nextcloud-server-538a04968a24f645b12ca2647952a5b73ebc3eac.zip
fix(tests): Adjust theming test for new splitted background and primary colors
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
-rw-r--r--apps/settings/src/components/AdminAI.vue6
-rw-r--r--apps/theming/css/default.css2
-rw-r--r--apps/theming/lib/Service/BackgroundService.php5
-rw-r--r--apps/theming/lib/Themes/CommonThemeTrait.php3
-rw-r--r--apps/theming/lib/Util.php2
-rw-r--r--apps/theming/openapi.json4
-rw-r--r--apps/theming/tests/Settings/PersonalTest.php14
-rw-r--r--apps/theming/tests/ThemingDefaultsTest.php74
-rw-r--r--cypress/e2e/theming/admin-settings.cy.ts336
-rw-r--r--cypress/e2e/theming/themingUtils.ts70
-rw-r--r--cypress/e2e/theming/user-background.cy.ts67
-rw-r--r--lib/private/Server.php16
-rw-r--r--lib/private/legacy/OC_Defaults.php4
13 files changed, 369 insertions, 234 deletions
diff --git a/apps/settings/src/components/AdminAI.vue b/apps/settings/src/components/AdminAI.vue
index ea444fc25cf..5b71bb0dc04 100644
--- a/apps/settings/src/components/AdminAI.vue
+++ b/apps/settings/src/components/AdminAI.vue
@@ -190,9 +190,9 @@ export default {
.draggable__number {
border-radius: 20px;
- border: 2px solid var(--color-primary-default);
- color: var(--color-primary-default);
- padding: 0px 7px;
+ border: 2px solid var(--color-primary-element);
+ color: var(--color-primary-element);
+ padding: 0px 7px;
margin-right: 3px;
}
diff --git a/apps/theming/css/default.css b/apps/theming/css/default.css
index c96e41d23fc..6a5f91af864 100644
--- a/apps/theming/css/default.css
+++ b/apps/theming/css/default.css
@@ -71,7 +71,6 @@
--primary-invert-if-bright: no;
--primary-invert-if-dark: invert(100%);
--color-primary: #00679e;
- --color-primary-default: #0082c9;
--color-primary-text: #ffffff;
--color-primary-hover: #3285b1;
--color-primary-light: #e5eff5;
@@ -87,4 +86,5 @@
--gradient-primary-background: linear-gradient(40deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
--color-background-plain: #00679e;
--color-background-plain-text: #ffffff;
+ --image-background: url('/apps/theming/img/background/kamil-porembinski-clouds.jpg');
}
diff --git a/apps/theming/lib/Service/BackgroundService.php b/apps/theming/lib/Service/BackgroundService.php
index c323a721b60..cdaff2372a8 100644
--- a/apps/theming/lib/Service/BackgroundService.php
+++ b/apps/theming/lib/Service/BackgroundService.php
@@ -43,7 +43,7 @@ use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
class BackgroundService {
- public const DEFAULT_COLOR = '#0082c9';
+ public const DEFAULT_COLOR = '#00679e';
public const DEFAULT_BACKGROUND_COLOR = '#00679e';
/**
@@ -300,9 +300,10 @@ class BackgroundService {
$meanColor = $this->calculateMeanColor($image);
if ($meanColor !== false) {
$this->config->setAppValue(Application::APP_ID, 'background_color', $meanColor);
+ return $meanColor;
}
- return $meanColor;
}
+ return null;
}
/**
diff --git a/apps/theming/lib/Themes/CommonThemeTrait.php b/apps/theming/lib/Themes/CommonThemeTrait.php
index bdf95d98275..f2d86009cef 100644
--- a/apps/theming/lib/Themes/CommonThemeTrait.php
+++ b/apps/theming/lib/Themes/CommonThemeTrait.php
@@ -61,7 +61,6 @@ trait CommonThemeTrait {
'--primary-invert-if-dark' => $this->util->invertTextColor($colorPrimaryElement) ? 'no' : 'invert(100%)',
'--color-primary' => $this->primaryColor,
- '--color-primary-default' => $this->defaultPrimaryColor,
'--color-primary-text' => $this->util->invertTextColor($this->primaryColor) ? '#000000' : '#ffffff',
'--color-primary-hover' => $this->util->mix($this->primaryColor, $colorMainBackground, 60),
'--color-primary-light' => $colorPrimaryLight,
@@ -105,7 +104,7 @@ trait CommonThemeTrait {
if ($this->imageManager->hasImage($image)) {
$imageUrl = $this->imageManager->getImageUrl($image);
$variables["--image-$image"] = "url('" . $imageUrl . "')";
- } else if ($image === 'background') {
+ } elseif ($image === 'background') {
// Apply default background if nothing is configured
$variables['--image-background'] = "url('" . $this->themingDefaults->getBackground() . "')";
}
diff --git a/apps/theming/lib/Util.php b/apps/theming/lib/Util.php
index a2f8ee0abad..5dd71c1c1d3 100644
--- a/apps/theming/lib/Util.php
+++ b/apps/theming/lib/Util.php
@@ -93,7 +93,7 @@ class Util {
$contrast = $this->colorContrast($color, $blurredBackground);
// Min. element contrast is 3:1 but we need to keep hover states in mind -> min 3.2:1
- $minContrast = $highContrast ? 5.5 : 3.2;
+ $minContrast = $highContrast ? 5.6 : 3.2;
while ($contrast < $minContrast && $iteration++ < 100) {
$hsl = Color::hexToHsl($color);
diff --git a/apps/theming/openapi.json b/apps/theming/openapi.json
index 072b1897f69..fe0f342f993 100644
--- a/apps/theming/openapi.json
+++ b/apps/theming/openapi.json
@@ -63,6 +63,7 @@
"color-element-dark",
"logo",
"background",
+ "background-text",
"background-plain",
"background-default",
"logoheader",
@@ -99,6 +100,9 @@
"background": {
"type": "string"
},
+ "background-text": {
+ "type": "string"
+ },
"background-plain": {
"type": "boolean"
},
diff --git a/apps/theming/tests/Settings/PersonalTest.php b/apps/theming/tests/Settings/PersonalTest.php
index 0a9bf4b59c9..c2b08c72f30 100644
--- a/apps/theming/tests/Settings/PersonalTest.php
+++ b/apps/theming/tests/Settings/PersonalTest.php
@@ -30,6 +30,7 @@ namespace OCA\Theming\Tests\Settings;
use OCA\Theming\AppInfo\Application;
use OCA\Theming\ImageManager;
use OCA\Theming\ITheme;
+use OCA\Theming\Service\BackgroundService;
use OCA\Theming\Service\ThemesService;
use OCA\Theming\Settings\Personal;
use OCA\Theming\Themes\DarkHighContrastTheme;
@@ -116,18 +117,23 @@ class PersonalTest extends TestCase {
->with('enforce_theme', '')
->willReturn($enforcedTheme);
- $this->config->expects($this->once())
+ $this->config->expects($this->any())
->method('getUserValue')
- ->with('admin', 'core', 'apporder')
- ->willReturn('[]');
+ ->willReturnMap([
+ ['admin', 'core', 'apporder', '[]', '[]'],
+ ['admin', 'theming', 'background_image', BackgroundService::BACKGROUND_DEFAULT],
+ ]);
$this->appManager->expects($this->once())
->method('getDefaultAppForUser')
->willReturn('forcedapp');
- $this->initialStateService->expects($this->exactly(4))
+ $this->initialStateService->expects($this->exactly(7))
->method('provideInitialState')
->withConsecutive(
+ ['shippedBackgrounds', BackgroundService::SHIPPED_BACKGROUNDS],
+ ['themingDefaults'],
+ ['userBackgroundImage'],
['themes', $themesState],
['enforceTheme', $enforcedTheme],
['isUserThemingDisabled', false],
diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php
index 2011b62c3ea..0ea12f82563 100644
--- a/apps/theming/tests/ThemingDefaultsTest.php
+++ b/apps/theming/tests/ThemingDefaultsTest.php
@@ -455,82 +455,38 @@ class ThemingDefaultsTest extends TestCase {
'with fallback default' => [
'disableTheming' => 'no',
'primaryColor' => '',
- 'backgroundColor' => '',
- 'userBackgroundColor' => '',
- 'userPrimaryColor' => '',
- 'expected' => BackgroundService::DEFAULT_COLOR,
- ],
- 'with custom admin background' => [
- 'disableTheming' => 'no',
- 'primaryColor' => '',
- 'backgroundColor' => '#123',
- 'userBackgroundColor' => '',
- 'userPrimaryColor' => '',
- 'expected' => '#123',
- ],
- 'with custom invalid admin background' => [
- 'disableTheming' => 'no',
- 'primaryColor' => '',
- 'backgroundColor' => 'invalid-name',
- 'userBackgroundColor' => '',
'userPrimaryColor' => '',
'expected' => BackgroundService::DEFAULT_COLOR,
],
'with custom admin primary' => [
'disableTheming' => 'no',
'primaryColor' => '#aaa',
- 'backgroundColor' => '',
- 'userBackgroundColor' => '',
'userPrimaryColor' => '',
'expected' => '#aaa',
],
'with custom invalid admin primary' => [
'disableTheming' => 'no',
'primaryColor' => 'invalid',
- 'backgroundColor' => '',
- 'userBackgroundColor' => '',
'userPrimaryColor' => '',
'expected' => BackgroundService::DEFAULT_COLOR,
],
- 'with custom user background' => [
- 'disableTheming' => 'no',
- 'primaryColor' => '',
- 'backgroundColor' => '',
- 'userBackgroundColor' => '#456',
- 'userPrimaryColor' => '#456',
- 'expected' => '#456',
- ],
'with custom invalid user primary' => [
'disableTheming' => 'no',
'primaryColor' => '',
- 'backgroundColor' => '',
- 'userBackgroundColor' => '',
'userPrimaryColor' => 'invalid-name',
'expected' => BackgroundService::DEFAULT_COLOR,
],
'with custom user primary' => [
'disableTheming' => 'no',
'primaryColor' => '',
- 'backgroundColor' => '',
- 'userBackgroundColor' => '',
'userPrimaryColor' => '#bbb',
'expected' => '#bbb',
],
- 'with custom invalid user background' => [
- 'disableTheming' => 'no',
- 'primaryColor' => '',
- 'backgroundColor' => '',
- 'userBackgroundColor' => 'invalid-name',
- 'userPrimaryColor' => '',
- 'expected' => BackgroundService::DEFAULT_COLOR,
- ],
- 'with custom admin and user background' => [
- 'disableTheming' => 'no',
- 'primaryColor' => '',
- 'backgroundColor' => '#123',
- 'userBackgroundColor' => '#456',
- 'userPrimaryColor' => '#456',
- 'expected' => '#456',
+ 'with disabled user theming primary' => [
+ 'disableTheming' => 'yes',
+ 'primaryColor' => '#aaa',
+ 'userPrimaryColor' => '#bbb',
+ 'expected' => '#aaa',
],
];
}
@@ -538,7 +494,7 @@ class ThemingDefaultsTest extends TestCase {
/**
* @dataProvider dataGetColorPrimary
*/
- public function testGetColorPrimary(string $disableTheming, string $primaryColor, string $backgroundColor, string $userBackgroundColor, $userPrimaryColor, $expected) {
+ public function testGetColorPrimary(string $disableTheming, string $primaryColor, string $userPrimaryColor, string $expected) {
$user = $this->createMock(IUser::class);
$this->userSession->expects($this->any())
->method('getUser')
@@ -552,15 +508,12 @@ class ThemingDefaultsTest extends TestCase {
->willReturnMap([
['theming', 'disable-user-theming', 'no', $disableTheming],
['theming', 'primary_color', '', $primaryColor],
- ['theming', 'background_color', '', $backgroundColor],
]);
$this->config
->expects($this->any())
->method('getUserValue')
- ->willReturnMap([
- ['user', 'theming', 'background_color', '', $userBackgroundColor],
- ['user', 'theming', 'primary_color', $userBackgroundColor, $userPrimaryColor],
- ]);
+ ->with('user', 'theming', 'primary_color', '')
+ ->willReturn($userPrimaryColor);
$this->assertEquals($expected, $this->template->getColorPrimary());
}
@@ -668,15 +621,10 @@ class ThemingDefaultsTest extends TestCase {
->method('deleteAppValue')
->with('theming', 'primary_color');
$this->config
- ->expects($this->exactly(2))
+ ->expects($this->once())
->method('getAppValue')
- ->withConsecutive(
- ['theming', 'cachebuster', '0'],
- ['theming', 'primary_color', null],
- )->willReturnOnConsecutiveCalls(
- '15',
- $this->defaults->getColorPrimary(),
- );
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('15');
$this->config
->expects($this->once())
->method('setAppValue')
diff --git a/cypress/e2e/theming/admin-settings.cy.ts b/cypress/e2e/theming/admin-settings.cy.ts
index 1c4e3458aae..e721ab4d332 100644
--- a/cypress/e2e/theming/admin-settings.cy.ts
+++ b/cypress/e2e/theming/admin-settings.cy.ts
@@ -21,9 +21,15 @@
*/
/* eslint-disable n/no-unpublished-import */
import { User } from '@nextcloud/cypress'
-import { colord } from 'colord'
-import { defaultPrimary, defaultBackground, pickRandomColor, validateBodyThemingCss, validateUserThemingDefaultCss } from './themingUtils'
+import {
+ defaultPrimary,
+ defaultBackground,
+ pickRandomColor,
+ validateBodyThemingCss,
+ validateUserThemingDefaultCss,
+ expectBackgroundColor,
+} from './themingUtils'
const admin = new User('admin', 'admin')
@@ -36,15 +42,24 @@ describe('Admin theming settings visibility check', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
it('See the default settings', function() {
- cy.get('[data-admin-theming-setting-primary-color-picker]').should('exist')
- cy.get('[data-admin-theming-setting-primary-color-reset]').should('not.exist')
+ cy.get('[data-admin-theming-setting-color-picker]').should('exist')
cy.get('[data-admin-theming-setting-file-reset]').should('not.exist')
- cy.get('[data-admin-theming-setting-file-remove]').should('be.visible')
+ cy.get('[data-admin-theming-setting-file-remove]').should('exist')
+
+ cy.get(
+ '[data-admin-theming-setting-primary-color] [data-admin-theming-setting-color]',
+ ).then(($el) => expectBackgroundColor($el, defaultPrimary))
+
+ cy.get(
+ '[data-admin-theming-setting-background-color] [data-admin-theming-setting-color]',
+ ).then(($el) => expectBackgroundColor($el, defaultPrimary))
})
})
@@ -59,24 +74,42 @@ describe('Change the primary color and reset it', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
it('Change the primary color', function() {
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
- pickRandomColor().then(color => { selectedColor = color })
+ pickRandomColor('[data-admin-theming-setting-primary-color]').then(
+ (color) => {
+ selectedColor = color
+ },
+ )
cy.wait('@setColor')
- cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(
+ selectedColor,
+ defaultBackground,
+ defaultPrimary,
+ ),
+ )
})
it('Screenshot the login page and validate login page', function() {
cy.logout()
cy.visit('/')
- cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(
+ selectedColor,
+ defaultBackground,
+ defaultPrimary,
+ ),
+ )
cy.screenshot()
})
@@ -98,21 +131,29 @@ describe('Remove the default background and restore it', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
it('Remove the default background', function() {
- cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
+ cy.intercept('*/apps/theming/ajax/updateStylesheet').as(
+ 'removeBackground',
+ )
cy.get('[data-admin-theming-setting-file-remove]').click()
cy.wait('@removeBackground')
cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null))
- cy.waitUntil(() => cy.window().then((win) => {
- const backgroundPlain = getComputedStyle(win.document.body).getPropertyValue('--image-background-plain')
- return backgroundPlain !== ''
- }))
+ cy.waitUntil(() =>
+ cy.window().then((win) => {
+ const backgroundPlain = getComputedStyle(
+ win.document.body,
+ ).getPropertyValue('--image-background')
+ return backgroundPlain !== ''
+ }),
+ )
})
it('Screenshot the login page and validate login page', function() {
@@ -132,7 +173,7 @@ describe('Remove the default background and restore it', function() {
})
})
-describe('Remove the default background with a custom primary color', function() {
+describe('Remove the default background with a custom background color', function() {
let selectedColor = ''
before(function() {
@@ -143,23 +184,40 @@ describe('Remove the default background with a custom primary color', function()
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
- it('Change the primary color', function() {
+ it('Change the background color', function() {
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
- pickRandomColor().then(color => { selectedColor = color })
+ pickRandomColor('[data-admin-theming-setting-background-color]').then(
+ (color) => {
+ selectedColor = color
+ },
+ )
cy.wait('@setColor')
- cy.waitUntil(() => validateBodyThemingCss(selectedColor, defaultBackground))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(
+ defaultPrimary,
+ defaultBackground,
+ selectedColor,
+ ),
+ )
})
it('Remove the default background', function() {
- cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
+ cy.intercept('*/apps/theming/ajax/updateStylesheet').as(
+ 'removeBackground',
+ )
- cy.get('[data-admin-theming-setting-file-remove]').click()
+ cy.get('[data-admin-theming-setting-file-remove]').scrollIntoView()
+ cy.get('[data-admin-theming-setting-file-remove]').click({
+ force: true,
+ })
cy.wait('@removeBackground')
})
@@ -168,7 +226,9 @@ describe('Remove the default background with a custom primary color', function()
cy.logout()
cy.visit('/')
- cy.waitUntil(() => validateBodyThemingCss(selectedColor, null))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(defaultPrimary, null, selectedColor),
+ )
cy.screenshot()
})
@@ -182,6 +242,8 @@ describe('Remove the default background with a custom primary color', function()
})
describe('Remove the default background with a bright color', function() {
+ let selectedColor = ''
+
before(function() {
// Just in case previous test failed
cy.resetAdminTheming()
@@ -191,37 +253,51 @@ describe('Remove the default background with a bright color', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
it('Remove the default background', function() {
- cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
+ cy.intercept('*/apps/theming/ajax/updateStylesheet').as(
+ 'removeBackground',
+ )
cy.get('[data-admin-theming-setting-file-remove]').click()
cy.wait('@removeBackground')
})
- it('Change the primary color', function() {
+ it('Change the background color', function() {
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
// Pick one of the bright color preset
- cy.get('[data-admin-theming-setting-primary-color-picker]').click()
- cy.get('.color-picker__simple-color-circle:eq(4)').click()
+ pickRandomColor(
+ '[data-admin-theming-setting-background-color]',
+ 4,
+ ).then((color) => {
+ selectedColor = color
+ })
cy.wait('@setColor')
- cy.waitUntil(() => validateBodyThemingCss('#ddcb55', null))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(defaultPrimary, null, selectedColor),
+ )
})
it('See the header being inverted', function() {
- cy.waitUntil(() => cy.window().then((win) => {
- const firstEntry = win.document.querySelector('.app-menu-main li img')
- if (!firstEntry) {
- return false
- }
- return getComputedStyle(firstEntry).filter === 'invert(1)'
- }))
+ cy.waitUntil(() =>
+ cy.window().then((win) => {
+ const firstEntry = win.document.querySelector(
+ '.app-menu-main li img',
+ )
+ if (!firstEntry) {
+ return false
+ }
+ return getComputedStyle(firstEntry).filter === 'invert(1)'
+ }),
+ )
})
})
@@ -238,7 +314,9 @@ describe('Change the login fields then reset them', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
@@ -246,42 +324,54 @@ describe('Change the login fields then reset them', function() {
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('updateFields')
// Name
- cy.get('[data-admin-theming-setting-field="name"] input[type="text"]')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-field="name"] input[type="text"]')
- .type(`{selectall}${name}{enter}`)
+ cy.get(
+ '[data-admin-theming-setting-field="name"] input[type="text"]',
+ ).scrollIntoView()
+ cy.get(
+ '[data-admin-theming-setting-field="name"] input[type="text"]',
+ ).type(`{selectall}${name}{enter}`)
cy.wait('@updateFields')
// Url
- cy.get('[data-admin-theming-setting-field="url"] input[type="url"]')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-field="url"] input[type="url"]')
- .type(`{selectall}${url}{enter}`)
+ cy.get(
+ '[data-admin-theming-setting-field="url"] input[type="url"]',
+ ).scrollIntoView()
+ cy.get(
+ '[data-admin-theming-setting-field="url"] input[type="url"]',
+ ).type(`{selectall}${url}{enter}`)
cy.wait('@updateFields')
// Slogan
- cy.get('[data-admin-theming-setting-field="slogan"] input[type="text"]')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-field="slogan"] input[type="text"]')
- .type(`{selectall}${slogan}{enter}`)
+ cy.get(
+ '[data-admin-theming-setting-field="slogan"] input[type="text"]',
+ ).scrollIntoView()
+ cy.get(
+ '[data-admin-theming-setting-field="slogan"] input[type="text"]',
+ ).type(`{selectall}${slogan}{enter}`)
cy.wait('@updateFields')
})
it('Ensure undo button presence', function() {
- cy.get('[data-admin-theming-setting-field="name"] .input-field__trailing-button')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-field="name"] .input-field__trailing-button')
- .should('be.visible')
-
- cy.get('[data-admin-theming-setting-field="url"] .input-field__trailing-button')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-field="url"] .input-field__trailing-button')
- .should('be.visible')
-
- cy.get('[data-admin-theming-setting-field="slogan"] .input-field__trailing-button')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-field="slogan"] .input-field__trailing-button')
- .should('be.visible')
+ cy.get(
+ '[data-admin-theming-setting-field="name"] .input-field__trailing-button',
+ ).scrollIntoView()
+ cy.get(
+ '[data-admin-theming-setting-field="name"] .input-field__trailing-button',
+ ).should('be.visible')
+
+ cy.get(
+ '[data-admin-theming-setting-field="url"] .input-field__trailing-button',
+ ).scrollIntoView()
+ cy.get(
+ '[data-admin-theming-setting-field="url"] .input-field__trailing-button',
+ ).should('be.visible')
+
+ cy.get(
+ '[data-admin-theming-setting-field="slogan"] .input-field__trailing-button',
+ ).scrollIntoView()
+ cy.get(
+ '[data-admin-theming-setting-field="slogan"] .input-field__trailing-button',
+ ).should('be.visible')
})
it('Validate login screen changes', function() {
@@ -317,19 +407,29 @@ describe('Disable user theming and enable it back', function() {
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
it('Disable user background theming', function() {
- cy.intercept('*/apps/theming/ajax/updateStylesheet').as('disableUserTheming')
-
- cy.get('[data-admin-theming-setting-disable-user-theming]')
- .scrollIntoView()
- cy.get('[data-admin-theming-setting-disable-user-theming]')
- .should('be.visible')
- cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').check({ force: true })
- cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').should('be.checked')
+ cy.intercept('*/apps/theming/ajax/updateStylesheet').as(
+ 'disableUserTheming',
+ )
+
+ cy.get(
+ '[data-admin-theming-setting-disable-user-theming]',
+ ).scrollIntoView()
+ cy.get('[data-admin-theming-setting-disable-user-theming]').should(
+ 'be.visible',
+ )
+ cy.get(
+ '[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]',
+ ).check({ force: true })
+ cy.get(
+ '[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]',
+ ).should('be.checked')
cy.wait('@disableUserTheming')
})
@@ -343,8 +443,9 @@ describe('Disable user theming and enable it back', function() {
it('User cannot not change background settings', function() {
cy.visit('/settings/user/theming')
- cy.get('[data-user-theming-background-disabled]').scrollIntoView()
- cy.get('[data-user-theming-background-disabled]').should('be.visible')
+ cy.contains(
+ 'Customization has been disabled by your administrator',
+ ).should('exist')
})
})
@@ -363,40 +464,60 @@ describe('The user default background settings reflect the admin theming setting
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
- it('Change the primary color', function() {
- cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
-
- pickRandomColor().then(color => { selectedColor = color })
-
- cy.wait('@setColor')
- cy.waitUntil(() => cy.window().then(($window) => {
- const primary = $window.getComputedStyle($window.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.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=')
- }))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(
+ defaultPrimary,
+ '/apps/theming/image/background?v=',
+ null,
+ ),
+ )
+ })
+
+ it('Change the background color', function() {
+ cy.intercept('*/apps/theming/ajax/updateStylesheet').as('setColor')
+
+ pickRandomColor('[data-admin-theming-setting-background-color]').then(
+ (color) => {
+ selectedColor = color
+ },
+ )
+
+ cy.wait('@setColor')
+ cy.waitUntil(() =>
+ validateBodyThemingCss(
+ defaultPrimary,
+ '/apps/theming/image/background?v=',
+ selectedColor,
+ ),
+ )
})
it('Login page should match admin theming settings', function() {
cy.logout()
cy.visit('/')
- cy.waitUntil(() => validateBodyThemingCss(selectedColor, '/apps/theming/image/background?v='))
+ cy.waitUntil(() =>
+ validateBodyThemingCss(
+ defaultPrimary,
+ '/apps/theming/image/background?v=',
+ selectedColor,
+ ),
+ )
})
it('Login as user', function() {
@@ -413,9 +534,17 @@ describe('The user default background settings reflect the admin theming setting
it('Default user background settings should match admin theming settings', function() {
cy.get('[data-user-theming-background-default]').should('be.visible')
- cy.get('[data-user-theming-background-default]').should('have.class', 'background--active')
-
- cy.waitUntil(() => validateUserThemingDefaultCss(selectedColor, '/apps/theming/image/background?v='))
+ cy.get('[data-user-theming-background-default]').should(
+ 'have.class',
+ 'background--active',
+ )
+
+ cy.waitUntil(() =>
+ validateUserThemingDefaultCss(
+ selectedColor,
+ '/apps/theming/image/background?v=',
+ ),
+ )
})
})
@@ -432,12 +561,16 @@ describe('The user default background settings reflect the admin theming setting
it('See the admin theming section', function() {
cy.visit('/settings/admin/theming')
- cy.get('[data-admin-theming-settings]').should('exist').scrollIntoView()
+ cy.get('[data-admin-theming-settings]')
+ .should('exist')
+ .scrollIntoView()
cy.get('[data-admin-theming-settings]').should('be.visible')
})
it('Remove the default background', function() {
- cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground')
+ cy.intercept('*/apps/theming/ajax/updateStylesheet').as(
+ 'removeBackground',
+ )
cy.get('[data-admin-theming-setting-file-remove]').click()
@@ -466,7 +599,10 @@ describe('The user default background settings reflect the admin theming setting
it('Default user background settings should match admin theming settings', function() {
cy.get('[data-user-theming-background-default]').should('be.visible')
- cy.get('[data-user-theming-background-default]').should('have.class', 'background--active')
+ cy.get('[data-user-theming-background-default]').should(
+ 'have.class',
+ 'background--active',
+ )
cy.waitUntil(() => validateUserThemingDefaultCss(defaultPrimary, null))
})
diff --git a/cypress/e2e/theming/themingUtils.ts b/cypress/e2e/theming/themingUtils.ts
index 2965886c656..a3a0d509278 100644
--- a/cypress/e2e/theming/themingUtils.ts
+++ b/cypress/e2e/theming/themingUtils.ts
@@ -21,29 +21,54 @@
*/
import { colord } from 'colord'
-const defaultNextcloudBlue = '#0082c9'
export const defaultPrimary = '#00679e'
export const defaultBackground = 'kamil-porembinski-clouds.jpg'
/**
+ * Check if a CSS variable is set to a specific color
+ * @param variable Variable to check
+ * @param expectedColor Color that is expected
+ */
+export function validateCSSVariable(variable: string, expectedColor: string) {
+ const value = window.getComputedStyle(Cypress.$('body').get(0)).getPropertyValue(variable)
+ console.debug(`${variable}, is: ${colord(value).toHex()} expected: ${expectedColor}`)
+ return colord(value).isEqual(expectedColor)
+}
+
+/**
* Validate the current page body css variables
*
- * @param {string} expectedColor the expected color
+ * @param {string} expectedColor the expected primary color
* @param {string|null} expectedBackground the expected background
+ * @param {string|null} expectedBackgroundColor the expected background color (null to ignore)
*/
-export const validateBodyThemingCss = function(expectedColor = defaultPrimary, expectedBackground: string|null = defaultBackground) {
+export function validateBodyThemingCss(expectedColor = defaultPrimary, expectedBackground: string|null = defaultBackground, expectedBackgroundColor: string|null = defaultPrimary) {
// We must use `Cypress.$` here as any assertions (get is an assertion) is not allowed in wait-until's check function, see documentation
const guestBackgroundColor = Cypress.$('body').css('background-color')
const guestBackgroundImage = Cypress.$('body').css('background-image')
- const isValidBackgroundColor = colord(guestBackgroundColor).isEqual(expectedColor)
+ const isValidBackgroundColor = expectedBackgroundColor === null || colord(guestBackgroundColor).isEqual(expectedBackgroundColor)
const isValidBackgroundImage = !expectedBackground
? guestBackgroundImage === 'none'
: guestBackgroundImage.includes(expectedBackground)
- console.debug({ guestBackgroundColor: colord(guestBackgroundColor).toHex(), guestBackgroundImage, expectedColor, expectedBackground, isValidBackgroundColor, isValidBackgroundImage })
+ console.debug({
+ isValidBackgroundColor,
+ isValidBackgroundImage,
+ guestBackgroundColor: colord(guestBackgroundColor).toHex(),
+ guestBackgroundImage,
+ })
+
+ return isValidBackgroundColor && isValidBackgroundImage && validateCSSVariable('--color-primary', expectedColor)
+}
- return isValidBackgroundColor && isValidBackgroundImage
+/**
+ * Check background color of element
+ * @param element JQuery element to check
+ * @param color expected color
+ */
+export function expectBackgroundColor(element: JQuery<HTMLElement>, color: string) {
+ expect(colord(element.css('background-color')).toHex()).equal(colord(color).toHex())
}
/**
@@ -58,28 +83,28 @@ export const validateUserThemingDefaultCss = function(expectedColor = defaultPri
return false
}
- const defaultOptionBackground = defaultSelectButton.css('background-image')
- const colorPickerOptionColor = defaultSelectButton.css('background-color')
- const isNextcloudBlue = colord(colorPickerOptionColor).isEqual('#0082c9')
+ const backgroundImage = defaultSelectButton.css('background-image')
+ const backgroundColor = defaultSelectButton.css('background-color')
const isValidBackgroundImage = !expectedBackground
- ? defaultOptionBackground === 'none'
- : defaultOptionBackground.includes(expectedBackground)
-
- console.debug({ colorPickerOptionColor: colord(colorPickerOptionColor).toHex(), expectedColor, isValidBackgroundImage, isNextcloudBlue })
+ ? (backgroundImage === 'none' || Cypress.$('body').css('background-image') === 'none')
+ : backgroundImage.includes(expectedBackground)
+
+ console.debug({
+ colorPickerOptionColor: colord(backgroundColor).toHex(),
+ expectedColor,
+ isValidBackgroundImage,
+ backgroundImage,
+ })
- return isValidBackgroundImage && (
- colord(colorPickerOptionColor).isEqual(expectedColor)
- // we replace nextcloud blue with the the default rpimary (apps/theming/lib/Themes/DefaultTheme.php line 76)
- || (isNextcloudBlue && colord(expectedColor).isEqual(defaultPrimary))
- )
+ return isValidBackgroundImage && colord(backgroundColor).isEqual(expectedColor)
}
-export const pickRandomColor = function(): Cypress.Chainable<string> {
+export const pickRandomColor = function(context: string, index?: number): Cypress.Chainable<string> {
// Pick one of the first 8 options
- const randColour = Math.floor(Math.random() * 8)
+ const randColour = index ?? Math.floor(Math.random() * 8)
- const colorPreviewSelector = '[data-user-theming-background-color],[data-admin-theming-setting-primary-color]'
+ const colorPreviewSelector = `${context} [data-admin-theming-setting-color]`
let oldColor = ''
cy.get(colorPreviewSelector).then(($el) => {
@@ -87,7 +112,8 @@ export const pickRandomColor = function(): Cypress.Chainable<string> {
})
// Open picker
- cy.contains('button', 'Change color').click()
+ cy.get(`${context} [data-admin-theming-setting-color-picker]`).scrollIntoView()
+ cy.get(`${context} [data-admin-theming-setting-color-picker]`).click({ force: true })
// Click on random color
cy.get('.color-picker__simple-color-circle').eq(randColour).click()
diff --git a/cypress/e2e/theming/user-background.cy.ts b/cypress/e2e/theming/user-background.cy.ts
index cdf3ef59f4d..2796247a654 100644
--- a/cypress/e2e/theming/user-background.cy.ts
+++ b/cypress/e2e/theming/user-background.cy.ts
@@ -80,7 +80,7 @@ describe('User select shipped backgrounds and remove background', function() {
// Validate changed background and primary
cy.wait('@setBackground')
- cy.waitUntil(() => validateBodyThemingCss('#a53c17', background))
+ cy.waitUntil(() => validateBodyThemingCss('#a53c17', background, '#652e11'))
})
it('Select a bright shipped background', function() {
@@ -95,21 +95,21 @@ describe('User select shipped backgrounds and remove background', function() {
// Validate changed background and primary
cy.wait('@setBackground')
- cy.waitUntil(() => validateBodyThemingCss('#869171', background))
+ cy.waitUntil(() => validateBodyThemingCss('#56633d', background, '#dee0d3'))
})
it('Remove background', function() {
- cy.intercept('*/apps/theming/background/custom').as('clearBackground')
+ cy.intercept('*/apps/theming/background/color').as('clearBackground')
// Clear background
- cy.get('[data-user-theming-background-clear]').click()
+ cy.get('[data-user-theming-background-color]').click()
// Set the accessibility state
- cy.get('[data-user-theming-background-clear]').should('have.attr', 'aria-pressed', 'true')
+ cy.get('[data-user-theming-background-color]').should('have.attr', 'aria-pressed', 'true')
// Validate clear background
cy.wait('@clearBackground')
- cy.waitUntil(() => validateBodyThemingCss('#869171', null))
+ cy.waitUntil(() => validateBodyThemingCss('#56633d', null, '#dee0d3'))
})
})
@@ -129,14 +129,12 @@ describe('User select a custom color', function() {
it('Select a custom color', function() {
cy.intercept('*/apps/theming/background/color').as('setColor')
- pickRandomColor()
+ cy.get('[data-user-theming-background-color]').click()
+ cy.get('.color-picker__simple-color-circle').eq(5).click()
// Validate custom colour change
cy.wait('@setColor')
- cy.waitUntil(() => cy.window().then((win) => {
- const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary')
- return primary !== defaultPrimary && primary !== defaultPrimary
- }))
+ cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null, '#a5b872'))
})
})
@@ -154,10 +152,11 @@ describe('User select a bright custom color and remove background', function() {
})
it('Remove background', function() {
- cy.intercept('*/apps/theming/background/custom').as('clearBackground')
+ cy.intercept('*/apps/theming/background/color').as('clearBackground')
// Clear background
- cy.get('[data-user-theming-background-clear]').click()
+ cy.get('[data-user-theming-background-color]').click()
+ cy.get('[data-user-theming-background-color]').click()
// Validate clear background
cy.wait('@clearBackground')
@@ -168,7 +167,8 @@ describe('User select a bright custom color and remove background', function() {
cy.intercept('*/apps/theming/background/color').as('setColor')
// Pick one of the bright color preset
- cy.contains('button', 'Change color').click()
+ cy.get('[data-user-theming-background-color]').scrollIntoView()
+ cy.get('[data-user-theming-background-color]').click()
cy.get('.color-picker__simple-color-circle:eq(4)').click()
// Validate custom colour change
@@ -194,7 +194,7 @@ describe('User select a bright custom color and remove background', function() {
// Validate changed background and primary
cy.wait('@setBackground')
- cy.waitUntil(() => validateBodyThemingCss('#a53c17', background))
+ cy.waitUntil(() => validateBodyThemingCss('#a53c17', background, '#652e11'))
})
it('See the header NOT being inverted this time', function() {
@@ -240,15 +240,13 @@ describe('User select a custom background', function() {
// Wait for background to be set
cy.wait('@setBackground')
- cy.waitUntil(() => validateBodyThemingCss('#4c0c04', 'apps/theming/background?v='))
+ cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, 'apps/theming/background?v=', '#2f2221'))
})
})
describe('User changes settings and reload the page', function() {
const image = 'image.jpg'
- const primaryFromImage = '#4c0c04'
-
- let selectedColor = ''
+ const colorFromImage = '#2f2221'
before(function() {
cy.createRandomUser().then((user: User) => {
@@ -280,28 +278,39 @@ describe('User changes settings and reload the page', function() {
// Wait for background to be set
cy.wait('@setBackground')
- cy.waitUntil(() => validateBodyThemingCss(primaryFromImage, 'apps/theming/background?v='))
+ cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, 'apps/theming/background?v=', colorFromImage))
})
it('Select a custom color', function() {
cy.intercept('*/apps/theming/background/color').as('setColor')
- cy.contains('button', 'Change color').click()
+ cy.get('[data-user-theming-background-color]').click()
cy.get('.color-picker__simple-color-circle:eq(5)').click()
+ cy.get('[data-user-theming-background-color]').click()
// Validate clear background
cy.wait('@setColor')
- cy.waitUntil(() => cy.window().then((win) => {
- selectedColor = getComputedStyle(win.document.body).getPropertyValue('--color-primary')
- return selectedColor !== primaryFromImage
- }))
+ cy.waitUntil(() => validateBodyThemingCss(defaultPrimary, null, '#a5b872'))
+ })
+
+ it('Select a custom primary color', function() {
+ cy.intercept('/ocs/v2.php/apps/provisioning_api/api/v1/config/users/theming/primary_color').as('setPrimaryColor')
+
+ cy.get('[data-user-theming-primary-color-trigger]').scrollIntoView()
+ cy.get('[data-user-theming-primary-color-trigger]').click()
+ // eslint-disable-next-line cypress/no-unnecessary-waiting
+ cy.wait(500)
+ cy.get('.color-picker__simple-color-circle').should('be.visible')
+ cy.get('.color-picker__simple-color-circle:eq(2)').click()
+ cy.get('[data-user-theming-primary-color-trigger]').click()
+
+ // Validate clear background
+ cy.wait('@setPrimaryColor')
+ cy.waitUntil(() => validateBodyThemingCss('#c98879', null, '#a5b872'))
})
it('Reload the page and validate persistent changes', function() {
cy.reload()
- cy.waitUntil(() => validateBodyThemingCss(selectedColor, 'apps/theming/background?v='))
-
- // validate accessibility state
- cy.get('[data-user-theming-background-custom]').should('have.attr', 'aria-pressed', 'true')
+ cy.waitUntil(() => validateBodyThemingCss('#c98879', null, '#a5b872'))
})
})
diff --git a/lib/private/Server.php b/lib/private/Server.php
index f62b2426bba..8f2fb2b7383 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -1185,14 +1185,20 @@ class Server extends ServerContainer implements IServerContainer {
}
if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isInstalled('theming') && $c->get(TrustedDomainHelper::class)->isTrustedDomain($c->getRequest()->getInsecureServerHost())) {
+ $backgroundService = new BackgroundService(
+ $c->get(IRootFolder::class),
+ $c->getAppDataDir('theming'),
+ $c->get(\OCP\IConfig::class),
+ $c->get(ISession::class)->get('user_id'),
+ );
$imageManager = new ImageManager(
$c->get(\OCP\IConfig::class),
$c->getAppDataDir('theming'),
$c->get(IURLGenerator::class),
- $this->get(ICacheFactory::class),
- $this->get(LoggerInterface::class),
- $this->get(ITempManager::class),
- $this->get(BackgroundService::class),
+ $c->get(ICacheFactory::class),
+ $c->get(LoggerInterface::class),
+ $c->get(ITempManager::class),
+ $backgroundService,
);
return new ThemingDefaults(
$c->get(\OCP\IConfig::class),
@@ -1204,7 +1210,7 @@ class Server extends ServerContainer implements IServerContainer {
$imageManager,
$c->get(IAppManager::class),
$c->get(INavigationManager::class),
- $c->get(BackgroundService::class),
+ $backgroundService,
);
}
return new \OC_Defaults();
diff --git a/lib/private/legacy/OC_Defaults.php b/lib/private/legacy/OC_Defaults.php
index 01591af8611..97033d353dd 100644
--- a/lib/private/legacy/OC_Defaults.php
+++ b/lib/private/legacy/OC_Defaults.php
@@ -71,8 +71,8 @@ class OC_Defaults {
$this->defaultFDroidClientUrl = $config->getSystemValue('customclient_fdroid', 'https://f-droid.org/packages/com.nextcloud.client/');
$this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
$this->defaultDocVersion = \OC_Util::getVersion()[0]; // used to generate doc links
- $this->defaultColorBackground = '#0069c3';
- $this->defaultColorPrimary = '#0082c9';
+ $this->defaultColorBackground = '#00679e';
+ $this->defaultColorPrimary = '#00679e';
$this->defaultTextColorPrimary = '#ffffff';
$this->defaultProductName = 'Nextcloud';