From e1a9200f1ea81471303aaa11b8319f42f3a162f7 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 22 Feb 2026 22:04:49 +1100 Subject: [PATCH] [bug] Fix custom logo and splash (#11391) * Add custom logo and splash to playwright fixtures * Render custom logo in frontend * Add playwright tests for customization settings * Separate playwright run for customization * Update ci file * Update playwright config file * Do not call get_custom_file from withing settings.py - django app not fully initialized yet - can cause loops * Disable default tests (for now) * Re-enable normal tests * Update qc checks * Order of operations? * Debug output * Use env * Add more debug info * More debug * Further debug * Add collectstatic check * Run normal tests too * Remove debug prints --- .github/workflows/qc_checks.yaml | 8 ++++- src/backend/InvenTree/.gitignore | 3 ++ src/backend/InvenTree/InvenTree/helpers.py | 1 - src/backend/InvenTree/InvenTree/settings.py | 16 +++------ src/frontend/playwright.config.ts | 13 +++++-- .../src/components/items/InvenTreeLogo.tsx | 23 ++++++++++-- .../tests/customization/customization.spec.ts | 33 ++++++++++++++++++ .../tests/fixtures/playwright_custom_logo.png | Bin 0 -> 496 bytes .../fixtures/playwright_custom_splash.png | Bin 0 -> 10670 bytes 9 files changed, 78 insertions(+), 19 deletions(-) create mode 100644 src/frontend/tests/customization/customization.spec.ts create mode 100644 src/frontend/tests/fixtures/playwright_custom_logo.png create mode 100644 src/frontend/tests/fixtures/playwright_custom_splash.png diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index dd366d6e26..985c0e213d 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -694,7 +694,13 @@ jobs: cd src/frontend && npx playwright install --with-deps - name: Run Playwright tests id: tests - run: cd src/frontend && npx nyc playwright test + run: | + cd src/frontend + cp ./tests/fixtures/playwright_custom_logo.png ../backend/InvenTree/InvenTree/static/img/playwright_custom_logo.png + cp ./tests/fixtures/playwright_custom_splash.png ../backend/InvenTree/InvenTree/static/img/playwright_custom_splash.png + invoke static + env INVENTREE_CUSTOM_SPLASH="img/playwright_custom_splash.png" INVENTREE_CUSTOM_LOGO="img/playwright_custom_logo.png" npx nyc playwright test --project=customization + npx nyc playwright test --project=chromium --project=firefox - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # pin@v6.0.0 if: ${{ !cancelled() && steps.tests.outcome == 'failure' }} with: diff --git a/src/backend/InvenTree/.gitignore b/src/backend/InvenTree/.gitignore index 4af4473ebe..ec668443c9 100644 --- a/src/backend/InvenTree/.gitignore +++ b/src/backend/InvenTree/.gitignore @@ -1,2 +1,5 @@ # Files generated during unit testing _testfolder/ + +# Playwright files for CI +InvenTree/static/img/playwright*.png diff --git a/src/backend/InvenTree/InvenTree/helpers.py b/src/backend/InvenTree/InvenTree/helpers.py index 3acf31c67d..efa4d355c6 100644 --- a/src/backend/InvenTree/InvenTree/helpers.py +++ b/src/backend/InvenTree/InvenTree/helpers.py @@ -250,7 +250,6 @@ def getBlankThumbnail(): def getLogoImage(as_file=False, custom=True): """Return the InvenTree logo image, or a custom logo if available.""" - """Return the path to the logo-file.""" if custom and settings.CUSTOM_LOGO: static_storage = StaticFilesStorage() diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index 533ea28f0d..8206e101cc 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -26,12 +26,7 @@ from corsheaders.defaults import default_headers as default_cors_headers import InvenTree.backup from InvenTree.cache import get_cache_config, is_global_cache_enabled -from InvenTree.config import ( - get_boolean_setting, - get_custom_file, - get_oidc_private_key, - get_setting, -) +from InvenTree.config import get_boolean_setting, get_oidc_private_key, get_setting from InvenTree.ready import isInMainThread from InvenTree.sentry import default_sentry_dsn, init_sentry from InvenTree.version import checkMinPythonVersion, inventreeCommitHash @@ -1453,12 +1448,9 @@ if len(GLOBAL_SETTINGS_OVERRIDES) > 0: logger.debug('- Override value for %s = ********', key) # User interface customization values -CUSTOM_LOGO = get_custom_file( - 'INVENTREE_CUSTOM_LOGO', 'customize.logo', 'custom logo', lookup_media=True -) -CUSTOM_SPLASH = get_custom_file( - 'INVENTREE_CUSTOM_SPLASH', 'customize.splash', 'custom splash' -) +CUSTOM_LOGO = get_setting('INVENTREE_CUSTOM_LOGO', 'customize.logo', typecast=str) + +CUSTOM_SPLASH = get_setting('INVENTREE_CUSTOM_SPLASH', 'customize.splash', typecast=str) CUSTOMIZE = get_setting( 'INVENTREE_CUSTOMIZE', 'customize', default_value=None, typecast=dict diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts index 182c669ba4..93e298eb7e 100644 --- a/src/frontend/playwright.config.ts +++ b/src/frontend/playwright.config.ts @@ -48,13 +48,22 @@ export default defineConfig({ name: 'chromium', use: { ...devices['Desktop Chrome'] - } + }, + testIgnore: /customization/ // Ignore all tests in the "customization" folder for this project }, { name: 'firefox', use: { ...devices['Desktop Firefox'] - } + }, + testIgnore: /customization/ // Ignore all tests in the "customization" folder for this project + }, + { + name: 'customization', + use: { + ...devices['Desktop Firefox'] + }, + testIgnore: /pui_.*\.spec\.ts/ // Ignore all "pui_*.spec.ts" tests for this project } ], diff --git a/src/frontend/src/components/items/InvenTreeLogo.tsx b/src/frontend/src/components/items/InvenTreeLogo.tsx index f623003103..b03f321980 100644 --- a/src/frontend/src/components/items/InvenTreeLogo.tsx +++ b/src/frontend/src/components/items/InvenTreeLogo.tsx @@ -1,8 +1,10 @@ import { t } from '@lingui/core/macro'; import { ActionIcon } from '@mantine/core'; -import { forwardRef } from 'react'; +import { type ReactNode, forwardRef } from 'react'; import { NavLink } from 'react-router-dom'; +import { useShallow } from 'zustand/react/shallow'; +import { useServerApiState } from '../../states/ServerApiState'; import InvenTreeIcon from './inventree.svg'; export const InvenTreeLogoHomeButton = forwardRef( @@ -19,6 +21,21 @@ export const InvenTreeLogoHomeButton = forwardRef( } ); -export const InvenTreeLogo = () => { +/* + * Render the InvenTree logo + * - Uses the custom logo if one is defined on the server + * - Otherwise, uses the default logo + */ +export function InvenTreeLogo(): ReactNode { + const [server] = useServerApiState( + useShallow((state) => [state.server, state.fetchServerApiState]) + ); + + if (server.server && server.customize?.logo) { + return ( + {t`InvenTree + ); + } + return {t`InvenTree; -}; +} diff --git a/src/frontend/tests/customization/customization.spec.ts b/src/frontend/tests/customization/customization.spec.ts new file mode 100644 index 0000000000..fc34324940 --- /dev/null +++ b/src/frontend/tests/customization/customization.spec.ts @@ -0,0 +1,33 @@ +import test, { expect } from '@playwright/test'; +import { navigate } from '../helpers'; +import { doLogin } from '../login'; + +/** + * Tests for user interface customization functionality. + * + * Note: The correct environment variables must be set for these tests to work correctly. See "playwright.config.ts" for details. + * These tests are designed to run in CI environments where specific environment variables are set to enable custom logos and splash screens. The tests verify that these customizations are correctly applied in the user interface. + */ + +test('Customization - Splash', async ({ page }) => { + await navigate(page, '/'); + + await page.waitForLoadState('networkidle'); + + // Check for the custom splash screen + await expect( + page.locator('[style*="playwright_custom_splash.png"]') + ).toBeVisible(); +}); + +test('Customization - Logo', async ({ page }) => { + await doLogin(page, { + username: 'noaccess', + password: 'youshallnotpass' + }); + + await page.waitForLoadState('networkidle'); + + await page.waitForTimeout(2500); + return; +}); diff --git a/src/frontend/tests/fixtures/playwright_custom_logo.png b/src/frontend/tests/fixtures/playwright_custom_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..07c831872a3113cc956f5d23334d38817f9d011f GIT binary patch literal 496 zcmeAS@N?(olHy`uVBq!ia0vp^lYqFNgAGUu8aJH=QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKn<;)E{-7;ac?gvGBPMI954{NuwQ890p*89 wNzZ;IuiyFb`VQtj211<56GsV}g+V9t-=i!WR-NpT0LBu7r>mdKI;Vst0L2n=3jhEB literal 0 HcmV?d00001 diff --git a/src/frontend/tests/fixtures/playwright_custom_splash.png b/src/frontend/tests/fixtures/playwright_custom_splash.png new file mode 100644 index 0000000000000000000000000000000000000000..56356b160808cae22b870775d1b6addfd3df673a GIT binary patch literal 10670 zcmeAS@N?(olHy`uVBq!ia0y~yU~gbxV6os}1B$%3e9#$4F%}28J29*~C-V}>VM%xN zb!1@J*w6hZkrl}2EbxddW?aKNDFK|JHM z4UG1D5mjGiw)Sp)&Ir^A1P|&T^Fmk*e@-%htOSA%g9fOy5>EnHgrR|hSpvdRI5esZ z7!soa0!a>|DFhr2qge(V45NhuI2c9?hta};VKgs{=7rIw6r>;+%?qP>VKgs{<^=|Z z(f$HB6^!;5z`-zDFO1d;qxHgQy)arYj1Ikyj;W50x&uqX(I&xYlVG$-Fxn&-Z4!(& z2}YX)qfLU*Cc)?$3{Y)2I${QH6O1;G!ND*(!wwFH(cyGRFpL%sqlE*t^Mc;30+(Zd S!*Z8_g4Wa3&t;ucLK6VzwyYxn literal 0 HcmV?d00001