Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>tags/v26.0.0beta1
@@ -94,7 +94,7 @@ class ImageManager { | |||
case 'favicon': | |||
return $this->urlGenerator->imagePath('core', 'logo/logo.png') . '?v=' . $cacheBusterCounter; | |||
case 'background': | |||
return $this->urlGenerator->linkTo(Application::APP_ID, 'img/background/' . BackgroundService::DEFAULT_BACKGROUND); | |||
return $this->urlGenerator->linkTo(Application::APP_ID, 'img/background/' . BackgroundService::DEFAULT_BACKGROUND_IMAGE); | |||
} | |||
return ''; | |||
} |
@@ -27,7 +27,6 @@ declare(strict_types=1); | |||
namespace OCA\Theming\Jobs; | |||
use OCA\Theming\AppInfo\Application; | |||
use OCP\App\IAppManager; | |||
use OCP\AppFramework\Utility\ITimeFactory; | |||
use OCP\BackgroundJob\IJobList; | |||
use OCP\BackgroundJob\QueuedJob; |
@@ -93,7 +93,7 @@ class BeforeTemplateRenderedListener implements IEventListener { | |||
/** User color */ | |||
$this->initialState->provideInitialState( | |||
'backgroundColor', | |||
$this->config->getUserValue($userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT), | |||
$this->config->getUserValue($userId, Application::APP_ID, 'background_color', BackgroundService::DEFAULT_COLOR), | |||
); | |||
/** | |||
@@ -106,7 +106,7 @@ class BeforeTemplateRenderedListener implements IEventListener { | |||
); | |||
$this->initialState->provideInitialState( | |||
'defaultShippedBackground', | |||
BackgroundService::DEFAULT_BACKGROUND, | |||
BackgroundService::DEFAULT_BACKGROUND_IMAGE, | |||
); | |||
/** List of all shipped backgrounds */ |
@@ -53,7 +53,7 @@ class BackgroundService { | |||
public const BACKGROUND_DEFAULT = 'default'; | |||
public const BACKGROUND_DISABLED = 'disabled'; | |||
public const DEFAULT_BACKGROUND = 'kamil-porembinski-clouds.jpg'; | |||
public const DEFAULT_BACKGROUND_IMAGE = 'kamil-porembinski-clouds.jpg'; | |||
public const SHIPPED_BACKGROUNDS = [ | |||
'anatoly-mikhaltsov-butterfly-wing-scale.jpg' => [ | |||
'attribution' => 'Butterfly wing scale (Anatoly Mikhaltsov, CC BY-SA)', |
@@ -89,16 +89,14 @@ trait CommonThemeTrait { | |||
$variables = []; | |||
// Default last fallback values | |||
$variables['--image-background-default'] = $backgroundDeleted ?: "url('" . $this->themingDefaults->getBackground() . "')"; | |||
$variables['--image-background-default'] = "url('" . $this->themingDefaults->getBackground() . "')"; | |||
$variables['--color-background-plain'] = $this->defaultPrimaryColor; | |||
// If primary as background has been request or if we have a custom primary colour | |||
// let's not define the background image | |||
if ($backgroundDeleted) { | |||
$variables['--color-background-plain'] = $this->themingDefaults->getColorPrimary(); | |||
if ($this->themingDefaults->isUserThemingDisabled() || $user === null) { | |||
$variables['--image-background-plain'] = 'yes'; | |||
} | |||
$variables['--image-background-plain'] = 'yes'; | |||
} | |||
// Register image variables only if custom-defined | |||
@@ -111,7 +109,6 @@ trait CommonThemeTrait { | |||
continue; | |||
} | |||
$variables['--image-background-size'] = 'cover'; | |||
$variables['--image-background-default'] = "url('" . $imageUrl . "')"; | |||
} | |||
// --image-background is overridden by user theming | |||
$variables["--image-$image"] = "url('" . $imageUrl . "')"; |
@@ -227,10 +227,10 @@ class ThemingDefaults extends \OC_Defaults { | |||
// user-defined primary color | |||
if (!empty($user)) { | |||
$themingBackground = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_color', ''); | |||
$themingBackgroundColor = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_color', ''); | |||
// If the user selected a specific colour | |||
if (preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $themingBackground)) { | |||
return $themingBackground; | |||
if (preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $themingBackgroundColor)) { | |||
return $themingBackgroundColor; | |||
} | |||
} | |||
@@ -24,36 +24,46 @@ | |||
<section> | |||
<NcSettingsSection :title="t('theming', 'Theming')" | |||
:description="t('theming', 'Theming makes it possible to easily customize the look and feel of your instance and supported clients. This will be visible for all users.')" | |||
:doc-url="docUrl"> | |||
:doc-url="docUrl" | |||
data-admin-theming-settings> | |||
<div class="admin-theming"> | |||
<NcNoteCard v-if="!isThemable" | |||
type="error" | |||
:show-alert="true"> | |||
<p>{{ notThemableErrorMessage }}</p> | |||
</NcNoteCard> | |||
<!-- Name, web link, slogan... fields --> | |||
<TextField v-for="field in textFields" | |||
:key="field.name" | |||
:name="field.name" | |||
:value.sync="field.value" | |||
:data-admin-theming-setting-field="field.name" | |||
:default-value="field.defaultValue" | |||
:type="field.type" | |||
:display-name="field.displayName" | |||
:placeholder="field.placeholder" | |||
:maxlength="field.maxlength" | |||
:name="field.name" | |||
:placeholder="field.placeholder" | |||
:type="field.type" | |||
:value.sync="field.value" | |||
@update:theming="$emit('update:theming')" /> | |||
<!-- Primary color picker --> | |||
<ColorPickerField :name="colorPickerField.name" | |||
:value.sync="colorPickerField.value" | |||
:default-value="colorPickerField.defaultValue" | |||
:display-name="colorPickerField.displayName" | |||
:value.sync="colorPickerField.value" | |||
data-admin-theming-setting-primary-color | |||
@update:theming="$emit('update:theming')" /> | |||
<!-- Default background picker --> | |||
<FileInputField v-for="field in fileInputFields" | |||
:key="field.name" | |||
:name="field.name" | |||
:mime-name="field.mimeName" | |||
:mime-value.sync="field.mimeValue" | |||
:aria-label="field.ariaLabel" | |||
:default-mime-value="field.defaultMimeValue" | |||
:display-name="field.displayName" | |||
:aria-label="field.ariaLabel" | |||
:mime-name="field.mimeName" | |||
:mime-value.sync="field.mimeValue" | |||
:name="field.name" | |||
data-admin-theming-setting-background | |||
@update:theming="$emit('update:theming')" /> | |||
<div class="admin-theming__preview"> | |||
<div class="admin-theming__preview-logo" /> | |||
@@ -87,6 +97,7 @@ | |||
:display-name="userThemingField.displayName" | |||
:label="userThemingField.label" | |||
:description="userThemingField.description" | |||
data-admin-theming-setting-disable-user-theming | |||
@update:theming="$emit('update:theming')" /> | |||
<a v-if="!canThemeIcons" | |||
:href="docUrlIcons" |
@@ -63,7 +63,8 @@ | |||
</NcSettingsSection> | |||
<NcSettingsSection :title="t('theming', 'Background')" | |||
class="background"> | |||
class="background" | |||
data-user-theming-background-disabled> | |||
<template v-if="isUserThemingDisabled"> | |||
<p>{{ t('theming', 'Customization has been disabled by your administrator') }}</p> | |||
</template> |
@@ -99,7 +99,6 @@ import { Palette } from 'node-vibrant/lib/color' | |||
import { getFilePickerBuilder } from '@nextcloud/dialogs' | |||
import { getCurrentUser } from '@nextcloud/auth' | |||
const backgroundColor = loadState('theming', 'backgroundColor') | |||
const backgroundImage = loadState('theming', 'backgroundImage') | |||
const shippedBackgroundList = loadState('theming', 'shippedBackgrounds') | |||
const themingDefaultBackground = loadState('theming', 'themingDefaultBackground') | |||
@@ -132,7 +131,6 @@ export default { | |||
// User background image and color settings | |||
backgroundImage, | |||
backgroundColor, | |||
} | |||
}, | |||
@@ -210,7 +208,6 @@ export default { | |||
async update(data) { | |||
// Update state | |||
this.backgroundImage = data.backgroundImage | |||
this.backgroundColor = data.backgroundColor | |||
this.Theming.color = data.backgroundColor | |||
// Notify parent and reload style |
@@ -30,13 +30,15 @@ | |||
<NcButton class="field__button" | |||
type="primary" | |||
:id="id" | |||
:aria-label="t('theming', 'Select a custom color')"> | |||
:aria-label="t('theming', 'Select a custom color')" | |||
data-admin-theming-setting-primary-color-picker> | |||
{{ value }} | |||
</NcButton> | |||
</NcColorPicker> | |||
<NcButton v-if="value !== defaultValue" | |||
type="tertiary" | |||
:aria-label="t('theming', 'Reset to default')" | |||
data-admin-theming-setting-primary-color-reset | |||
@click="undo"> | |||
<template #icon> | |||
<Undo :size="20" /> |
@@ -27,6 +27,7 @@ | |||
<NcButton type="secondary" | |||
:id="id" | |||
:aria-label="ariaLabel" | |||
data-admin-theming-setting-background-picker | |||
@click="activateLocalFilePicker"> | |||
<template #icon> | |||
<Upload :size="20" /> | |||
@@ -36,6 +37,7 @@ | |||
<NcButton v-if="showReset" | |||
type="tertiary" | |||
:aria-label="t('theming', 'Reset to default')" | |||
data-admin-theming-setting-background-reset | |||
@click="undo"> | |||
<template #icon> | |||
<Undo :size="20" /> | |||
@@ -44,6 +46,7 @@ | |||
<NcButton v-if="showRemove" | |||
type="tertiary" | |||
:aria-label="t('theming', 'Remove background image')" | |||
data-admin-theming-setting-background-remove | |||
@click="removeBackground"> | |||
<template #icon> | |||
<Delete :size="20" /> |
@@ -85,7 +85,7 @@ class DefaultThemeTest extends TestCase { | |||
$this->themingDefaults | |||
->expects($this->any()) | |||
->method('getBackground') | |||
->willReturn('/apps/' . Application::APP_ID . '/img/background/' . BackgroundService::DEFAULT_BACKGROUND); | |||
->willReturn('/apps/' . Application::APP_ID . '/img/background/' . BackgroundService::DEFAULT_BACKGROUND_IMAGE); | |||
$this->l10n | |||
->expects($this->any()) |
@@ -464,7 +464,7 @@ class ThemingDefaultsTest extends TestCase { | |||
$this->config | |||
->expects($this->once()) | |||
->method('getUserValue') | |||
->with('user', 'theming', 'background') | |||
->with('user', 'theming', 'background_color') | |||
->willReturn(''); | |||
$this->assertEquals(BackgroundService::DEFAULT_COLOR, $this->template->getColorPrimary()); |
@@ -64,6 +64,8 @@ $expectedFiles = [ | |||
'COPYING', | |||
'core', | |||
'cron.php', | |||
'cypress.config.ts', | |||
'cypress', | |||
'dist', | |||
'index.html', | |||
'index.php', | |||
@@ -87,6 +89,7 @@ $expectedFiles = [ | |||
'status.php', | |||
'tests', | |||
'themes', | |||
'tsconfig.json', | |||
'vendor-bin', | |||
'version.php', | |||
'webpack.common.js', |
@@ -26,7 +26,7 @@ | |||
name="login" | |||
:action="loginActionUrl" | |||
@submit="submit"> | |||
<fieldset class="login-form__fieldset"> | |||
<fieldset class="login-form__fieldset" data-login-form> | |||
<NcNoteCard v-if="apacheAuthFailed" | |||
:title="t('core', 'Server side authentication failed!')" | |||
type="warning"> | |||
@@ -52,7 +52,7 @@ | |||
<!-- the following div ensures that the spinner is always inside the #message div --> | |||
<div style="clear: both;" /> | |||
</div> | |||
<h2 class="login-form__headline" v-html="headline" /> | |||
<h2 class="login-form__headline" data-login-form-headline v-html="headline" /> | |||
<NcTextField id="user" | |||
ref="user" | |||
:label="t('core', 'Account name or email')" | |||
@@ -64,6 +64,7 @@ | |||
:spellchecking="false" | |||
:autocomplete="autoCompleteAllowed ? 'username' : 'off'" | |||
required | |||
data-login-form-input-user | |||
@change="updateUsername" /> | |||
<NcPasswordField id="password" | |||
@@ -78,9 +79,10 @@ | |||
:label="t('core', 'Password')" | |||
:helper-text="errorLabel" | |||
:error="isError" | |||
data-login-form-input-password | |||
required /> | |||
<LoginButton :loading="loading" /> | |||
<LoginButton data-login-form-submit :loading="loading" /> | |||
<input v-if="redirectUrl" | |||
type="hidden" |
@@ -0,0 +1,302 @@ | |||
/** | |||
* @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 { User } from '@nextcloud/cypress' | |||
const admin = new User('admin', 'admin') | |||
const defaultPrimary = '#0082c9' | |||
const defaultBackground = 'kamil-porembinski-clouds.jpg' | |||
describe('Admin theming settings', function() { | |||
before(function() { | |||
cy.login(admin) | |||
}) | |||
it('See the admin theming section', function() { | |||
cy.visit('/settings/admin/theming') | |||
cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible') | |||
}) | |||
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') | |||
}) | |||
}) | |||
describe('Change the primary colour', function() { | |||
before(function() { | |||
cy.login(admin) | |||
}) | |||
it('See the admin theming section', function() { | |||
cy.visit('/settings/admin/theming') | |||
cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible') | |||
}) | |||
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() | |||
cy.wait('@setColor') | |||
cy.waitUntil(() => cy.window().then((win) => { | |||
const primary = getComputedStyle(win.document.body).getPropertyValue('--color-primary-default') | |||
return primary !== defaultPrimary | |||
})) | |||
}) | |||
it('Screenshot the login page', function() { | |||
cy.logout() | |||
cy.visit('/') | |||
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('Screenshot the login page', function() { | |||
cy.logout() | |||
cy.visit('/') | |||
cy.screenshot() | |||
}) | |||
}) | |||
describe('Remove the default background', function() { | |||
before(function() { | |||
cy.login(admin) | |||
}) | |||
it('See the admin theming section', function() { | |||
cy.visit('/settings/admin/theming') | |||
cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible') | |||
}) | |||
it('Remove the default background', function() { | |||
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('removeBackground') | |||
cy.get('[data-admin-theming-setting-background-remove]').click() | |||
cy.wait('@removeBackground') | |||
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('Screenshot the login page', function() { | |||
cy.logout() | |||
cy.visit('/') | |||
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('Screenshot the login page', function() { | |||
cy.logout() | |||
cy.visit('/') | |||
cy.screenshot() | |||
}) | |||
}) | |||
describe('Change the login fields', function() { | |||
const name = 'ABCdef123' | |||
const url = 'https://example.com' | |||
const slogan = 'Testing is fun' | |||
before(function() { | |||
cy.login(admin) | |||
}) | |||
it('See the admin theming section', function() { | |||
cy.visit('/settings/admin/theming') | |||
cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible') | |||
}) | |||
it('Change the name field', function() { | |||
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('updateFields') | |||
// Name | |||
cy.get('[data-admin-theming-setting-field="name"] input[type="text"]') | |||
.scrollIntoView() | |||
.type('{selectall}') | |||
.type(name) | |||
.type('{enter}') | |||
cy.wait('@updateFields') | |||
// Url | |||
cy.get('[data-admin-theming-setting-field="url"] input[type="url"]') | |||
.scrollIntoView() | |||
.type('{selectall}') | |||
.type(url) | |||
.type('{enter}') | |||
cy.wait('@updateFields') | |||
// Slogan | |||
cy.get('[data-admin-theming-setting-field="slogan"] input[type="text"]') | |||
.scrollIntoView() | |||
.type('{selectall}') | |||
.type(slogan) | |||
.type('{enter}') | |||
cy.wait('@updateFields') | |||
}) | |||
it('Ensure undo button presence', function() { | |||
cy.get('[data-admin-theming-setting-field="name"] .input-field__clear-button') | |||
.scrollIntoView().should('be.visible') | |||
cy.get('[data-admin-theming-setting-field="url"] .input-field__clear-button') | |||
.scrollIntoView().should('be.visible') | |||
cy.get('[data-admin-theming-setting-field="slogan"] .input-field__clear-button') | |||
.scrollIntoView().should('be.visible') | |||
}) | |||
it('Check login screen changes', function() { | |||
cy.logout() | |||
cy.visit('/') | |||
cy.get('[data-login-form-headline]').should('contain.text', name) | |||
cy.get('footer p a').should('have.text', name) | |||
cy.get('footer p a').should('have.attr', 'href', url) | |||
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('Check login screen changes', function() { | |||
cy.logout() | |||
cy.visit('/') | |||
cy.get('[data-login-form-headline]').should('not.contain.text', name) | |||
cy.get('footer p a').should('not.have.text', name) | |||
cy.get('footer p a').should('not.have.attr', 'href', url) | |||
cy.get('footer p').should('not.contain.text', `– ${slogan}`) | |||
}) | |||
}) | |||
describe('Disable user theming', function() { | |||
before(function() { | |||
cy.login(admin) | |||
}) | |||
it('See the admin theming section', function() { | |||
cy.visit('/settings/admin/theming') | |||
cy.get('[data-admin-theming-settings]').scrollIntoView().should('be.visible') | |||
}) | |||
it('Disable user theming', function() { | |||
cy.intercept('*/apps/theming/ajax/updateStylesheet').as('disableUserTheming') | |||
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"]').check({ force: true }) | |||
cy.get('[data-admin-theming-setting-disable-user-theming] input[type="checkbox"]').should('be.checked') | |||
cy.wait('@disableUserTheming') | |||
}) | |||
it('Login as user', function() { | |||
cy.logout() | |||
cy.createRandomUser().then((user) => { | |||
cy.login(user) | |||
}) | |||
}) | |||
it('See the user disabled background settings', 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() | |||
cy.login(admin) | |||
}) | |||
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') | |||
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') | |||
cy.wait('@enableUserTheming') | |||
}) | |||
}) |
@@ -162,3 +162,55 @@ describe('User select a custom background', function() { | |||
cy.waitUntil(() => validateThemingCss('#4c0c04', 'apps/theming/background?v=')) | |||
}) | |||
}) | |||
describe('User changes settings and reload the page', function() { | |||
const image = 'image.jpg' | |||
const primaryFromImage = '#4c0c04' | |||
let selectedColor = '' | |||
before(function() { | |||
cy.createRandomUser().then((user: User) => { | |||
cy.uploadFile(user, image, 'image/jpeg') | |||
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('Select a custom background', function() { | |||
cy.intercept('*/apps/theming/background/custom').as('setBackground') | |||
// Pick background | |||
cy.get('[data-user-theming-background-custom]').click() | |||
cy.get(`#picker-filestable tr[data-entryname="${image}"]`).click() | |||
cy.get('#oc-dialog-filepicker-content ~ .oc-dialog-buttonrow button.primary').click() | |||
// Wait for background to be set | |||
cy.wait('@setBackground') | |||
cy.waitUntil(() => validateThemingCss(primaryFromImage, 'apps/theming/background?v=')) | |||
}) | |||
it('Select a custom color', function() { | |||
cy.intercept('*/apps/theming/background/color').as('setColor') | |||
cy.get('[data-user-theming-background-color]').click() | |||
cy.get('.color-picker__simple-color-circle:eq(5)').click() | |||
// Validate clear background | |||
cy.wait('@setColor') | |||
cy.waitUntil(() => cy.window().then((win) => { | |||
selectedColor = getComputedStyle(win.document.body).getPropertyValue('--color-primary') | |||
return selectedColor !== primaryFromImage | |||
})) | |||
}) | |||
it('Reload the page and validate persistent changes', function() { | |||
cy.reload() | |||
cy.waitUntil(() => validateThemingCss(selectedColor, 'apps/theming/background?v=')) | |||
}) | |||
}) |
@@ -400,6 +400,8 @@ | |||
/*! https://mths.be/he v1.2.0 by @mathias | MIT license */ | |||
/*! https://mths.be/punycode v1.3.2 by @mathias */ | |||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */ | |||
/*! jQuery Migrate v3.4.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ |
@@ -1,34 +0,0 @@ | |||
@apache | |||
Feature: app-theming | |||
# FIXME test with cypress | |||
# The existing DOM testing framework used here is not fully suitable for testing UIs implemented with modern frontend frameworks like Vue | |||
Scenario: changing the color updates the primary color | |||
Given I am logged in as the admin | |||
And I visit the admin settings page | |||
And I open the "Theming" section | |||
# And I see that the color selector in the Theming app has loaded | |||
# The "eventually" part is not really needed here, as the colour is not | |||
# being animated at this point, but there is no need to create a specific | |||
# step just for this. | |||
# And I see that the primary color is eventually "#00639a" | |||
# And I see that the non-plain background color variable is eventually "#0082c9" | |||
# When I set the "Color" parameter in the Theming app to "#C9C9C9" | |||
# Then I see that the parameters in the Theming app are eventually saved | |||
# And I see that the primary color is eventually "#00639a" | |||
# And I see that the non-plain background color variable is eventually "#C9C9C9" | |||
Scenario: resetting the color updates the primary color | |||
Given I am logged in as the admin | |||
And I visit the admin settings page | |||
And I open the "Theming" section | |||
# And I see that the color selector in the Theming app has loaded | |||
# And I set the "Color" parameter in the Theming app to "#C9C9C9" | |||
# And I see that the parameters in the Theming app are eventually saved | |||
# And I see that the primary color is eventually "#00639a" | |||
# And I see that the non-plain background color variable is eventually "#C9C9C9" | |||
# When I reset the "Color" parameter in the Theming app to its default value | |||
# Then I see that the parameters in the Theming app are eventually saved | |||
# And I see that the primary color is eventually "#00639a" | |||
# And I see that the non-plain background color variable is eventually "#0082c9" |