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 0000000000..07c831872a Binary files /dev/null and b/src/frontend/tests/fixtures/playwright_custom_logo.png differ 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 0000000000..56356b1608 Binary files /dev/null and b/src/frontend/tests/fixtures/playwright_custom_splash.png differ