diff --git a/web/.storybook/css-import-maps.ts b/web/.storybook/css-import-maps.ts deleted file mode 100644 index f24ea30428..0000000000 --- a/web/.storybook/css-import-maps.ts +++ /dev/null @@ -1,84 +0,0 @@ -// THIS IS A GENERATED FILE. DO NOT EDIT BY HAND. -// -// This file is generated by the build-storybook-import-maps script in the UI's base directory. -// This is a *hack* to work around an inconsistency in the way rollup, vite, and storybook -// import CSS modules. -// -// Sometime around 2030 or so, the Javascript community may finally get its collective act together -// and we'll have one unified way of doing this. I can only hope. - -const rawCssImportMaps = [ - 'import AKGlobal from "../../../common/styles/authentik.css";', - 'import AKGlobal from "../../common/styles/authentik.css";', - 'import AKGlobal from "../common/styles/authentik.css";', - 'import AKGlobal from "@goauthentik/common/styles/authentik.css";', - 'import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";', - 'import PFAlertGroup from "@patternfly/patternfly/components/AlertGroup/alert-group.css";', - 'import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css";', - 'import PFBackdrop from "@patternfly/patternfly/components/Backdrop/backdrop.css";', - 'import PFBackgroundImage from "@patternfly/patternfly/components/BackgroundImage/background-image.css";', - 'import PFBanner from "@patternfly/patternfly/components/Banner/banner.css";', - 'import PFBase from "@patternfly/patternfly/patternfly-base.css";', - 'import PFBrand from "@patternfly/patternfly/components/Brand/brand.css";', - 'import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";', - 'import PFButton from "@patternfly/patternfly/components/Button/button.css";', - 'import PFCard from "@patternfly/patternfly/components/Card/card.css";', - 'import PFCheck from "@patternfly/patternfly/components/Check/check.css";', - 'import PFChip from "@patternfly/patternfly/components/Chip/chip.css";', - 'import PFChipGroup from "@patternfly/patternfly/components/ChipGroup/chip-group.css";', - 'import PFContent from "@patternfly/patternfly/components/Content/content.css";', - 'import PFDataList from "@patternfly/patternfly/components/DataList/data-list.css";', - 'import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";', - 'import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css";', - 'import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";', - 'import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";', - 'import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css";', - 'import PFDualListSelector from "@patternfly/patternfly/components/DualListSelector/dual-list-selector.css";', - 'import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";', - 'import PFExpandableSection from "@patternfly/patternfly/components/ExpandableSection/expandable-section.css";', - 'import PFFAIcons from "@patternfly/patternfly/base/patternfly-fa-icons.css";', - 'import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css";', - 'import PFForm from "@patternfly/patternfly/components/Form/form.css";', - 'import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";', - 'import PFGallery from "@patternfly/patternfly/layouts/Gallery/gallery.css";', - 'import PFGlobal from "@patternfly/patternfly/patternfly-base.css";', - 'import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";', - 'import PFInputGroup from "@patternfly/patternfly/components/InputGroup/input-group.css";', - 'import PFLabel from "@patternfly/patternfly/components/Label/label.css";', - 'import PFList from "@patternfly/patternfly/components/List/list.css";', - 'import PFLogin from "@patternfly/patternfly/components/Login/login.css";', - 'import PFModalBox from "@patternfly/patternfly/components/ModalBox/modal-box.css";', - 'import PFNav from "@patternfly/patternfly/components/Nav/nav.css";', - 'import PFNotificationBadge from "@patternfly/patternfly/components/NotificationBadge/notification-badge.css";', - 'import PFNotificationDrawer from "@patternfly/patternfly/components/NotificationDrawer/notification-drawer.css";', - 'import PFPage from "@patternfly/patternfly/components/Page/page.css";', - 'import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css";', - 'import PFProgress from "@patternfly/patternfly/components/Progress/progress.css";', - 'import PFProgressStepper from "@patternfly/patternfly/components/ProgressStepper/progress-stepper.css";', - 'import PFRadio from "@patternfly/patternfly/components/Radio/radio.css";', - 'import PFSelect from "@patternfly/patternfly/components/Select/select.css";', - 'import PFSidebar from "@patternfly/patternfly/components/Sidebar/sidebar.css";', - 'import PFSizing from "@patternfly/patternfly/utilities/Sizing/sizing.css";', - 'import PFSpacing from "@patternfly/patternfly/utilities/Spacing/spacing.css";', - 'import PFSpinner from "@patternfly/patternfly/components/Spinner/spinner.css";', - 'import PFSplit from "@patternfly/patternfly/layouts/Split/split.css";', - 'import PFStack from "@patternfly/patternfly/layouts/Stack/stack.css";', - 'import PFSwitch from "@patternfly/patternfly/components/Switch/switch.css";', - 'import PFTable from "@patternfly/patternfly/components/Table/table.css";', - 'import PFTabs from "@patternfly/patternfly/components/Tabs/tabs.css";', - 'import PFTitle from "@patternfly/patternfly/components/Title/title.css";', - 'import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle-group.css";', - 'import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";', - 'import PFTreeView from "@patternfly/patternfly/components/TreeView/tree-view.css";', - 'import PFWizard from "@patternfly/patternfly/components/Wizard/wizard.css";', - 'import ThemeDark from "@goauthentik/common/styles/theme-dark.css";', - 'import styles from "./LibraryPageImpl.css";', -]; - -const cssImportMaps = rawCssImportMaps.reduce( - (acc, line) => ({ ...acc, [line]: line.replace(/\.css/, ".css?inline") }), - {}, -); - -export { cssImportMaps }; -export default cssImportMaps; diff --git a/web/.storybook/main.ts b/web/.storybook/main.ts index f2e7a0b895..722433a4b6 100644 --- a/web/.storybook/main.ts +++ b/web/.storybook/main.ts @@ -5,11 +5,19 @@ import modify from "rollup-plugin-modify"; import postcssLit from "rollup-plugin-postcss-lit"; import tsconfigPaths from "vite-tsconfig-paths"; -import { cssImportMaps } from "./css-import-maps"; - export const isProdBuild = process.env.NODE_ENV === "production"; export const apiBasePath = process.env.AK_API_BASE_PATH || ""; +const importInlinePatterns = [ + 'import AKGlobal from "(\\.\\./)*common/styles/authentik\\.css', + 'import AKGlobal from "@goauthentik/common/styles/authentik\\.css', + 'import PF.+ from "@patternfly/patternfly/\\S+\\.css', + 'import ThemeDark from "@goauthentik/common/styles/theme-dark\\.css', + 'import styles from "\\./LibraryPageImpl\\.css', +]; + +const importInlineRegexp = new RegExp(importInlinePatterns.map((a) => `(${a})`).join("|")); + const config: StorybookConfig = { stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], addons: [ @@ -43,7 +51,12 @@ const config: StorybookConfig = { return { ...config, plugins: [ - modify(cssImportMaps), + modify({ + find: importInlineRegexp, + replace: (match: RegExpMatchArray) => { + return `${match}?inline`; + }, + }), replace({ "process.env.NODE_ENV": JSON.stringify( isProdBuild ? "production" : "development", diff --git a/web/package.json b/web/package.json index 2d6104aa74..9d65bb730a 100644 --- a/web/package.json +++ b/web/package.json @@ -133,8 +133,8 @@ "pseudolocalize": "wireit", "storybook": "storybook dev -p 6006", "storybook:build": "wireit", - "storybook:build-import-map": "wireit", "test": "wireit", + "test:e2e": "wireit", "test:e2e:watch": "wireit", "test:watch": "wireit", "tsc": "wireit", @@ -316,9 +316,6 @@ "NODE_OPTIONS": "--max_old_space_size=8192" } }, - "storybook:build-import-map": { - "command": "node scripts/build-storybook-import-maps.mjs" - }, "test": { "command": "wdio ./wdio.conf.ts --logLevel=warn", "env": { @@ -326,6 +323,16 @@ "TS_NODE_PROJECT": "tsconfig.test.json" } }, + "test:e2e": { + "command": "wdio run ./tests/wdio.conf.ts", + "dependencies": [ + "build" + ], + "env": { + "CI": "true", + "TS_NODE_PROJECT": "./tests/tsconfig.test.json" + } + }, "test:e2e:watch": { "command": "wdio run ./tests/wdio.conf.ts", "dependencies": [ diff --git a/web/scripts/build-storybook-import-maps.mjs b/web/scripts/build-storybook-import-maps.mjs deleted file mode 100644 index 3009ace8b2..0000000000 --- a/web/scripts/build-storybook-import-maps.mjs +++ /dev/null @@ -1,91 +0,0 @@ -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; - -const __dirname = fileURLToPath(new URL(".", import.meta.url)); - -function* walkFilesystem(dir) { - const openeddir = fs.opendirSync(dir); - if (!openeddir) { - return; - } - let d; - while ((d = openeddir?.readSync())) { - if (!d) { - break; - } - const entry = path.join(dir, d.name); - if (d.isDirectory()) yield* walkFilesystem(entry); - else if (d.isFile()) yield entry; - } - openeddir.close(); -} - -const import_re = /^(import \w+ from .*\.css)";/; - -function extractImportLinesFromFile(path) { - const source = fs.readFileSync(path, { encoding: "utf8", flag: "r" }); - const lines = source?.split("\n") ?? []; - return lines.filter((l) => import_re.test(l)); -} - -function createOneImportLine(line) { - const importMatch = import_re.exec(line); - if (!importMatch) { - throw new Error("How did an unmatchable line get here?"); - } - const importContent = importMatch[1]; - if (!importContent) { - throw new Error("How did an unmatchable line get here!?"); - } - return ` '${importContent}";',`; -} - -const isSourceFile = /\.ts$/; - -function getTheSourceFiles() { - return Array.from(walkFilesystem(path.join(__dirname, "..", "src"))).filter((path) => - isSourceFile.test(path), - ); -} - -function getTheImportLines(importPaths) { - const importLines = importPaths.reduce( - (acc, path) => [...acc, extractImportLinesFromFile(path)].flat(), - [], - ); - const uniqueImportLines = new Set(importLines); - const sortedImportLines = Array.from(uniqueImportLines.keys()); - sortedImportLines.sort(); - return sortedImportLines; -} - -const importPaths = getTheSourceFiles(); -const importLines = getTheImportLines(importPaths); - -const outputFile = `// THIS IS A GENERATED FILE. DO NOT EDIT BY HAND. -// -// This file is generated by the build-storybook-import-maps script in the UI's base directory. -// This is a *hack* to work around an inconsistency in the way rollup, vite, and storybook -// import CSS modules. -// -// Sometime around 2030 or so, the Javascript community may finally get its collective act together -// and we'll have one unified way of doing this. I can only hope. - -const rawCssImportMaps = [ -${importLines.map(createOneImportLine).join("\n")} -]; - -const cssImportMaps = rawCssImportMaps.reduce( - (acc, line) => ({ ...acc, [line]: line.replace(/\\.css/, ".css?inline") }), - {}, -); - -export { cssImportMaps }; -export default cssImportMaps; -`; - -fs.writeFileSync(path.join(__dirname, "..", ".storybook", "css-import-maps.ts"), outputFile, { - encoding: "utf8", - flag: "w", -}); diff --git a/web/wdio.conf.ts b/web/wdio.conf.ts index b041defcf5..8c7777763d 100644 --- a/web/wdio.conf.ts +++ b/web/wdio.conf.ts @@ -59,7 +59,7 @@ const maxInstances = process.env.MAX_INSTANCES !== undefined ? parseInt(process.env.MAX_INSTANCES, DEFAULT_MAX_INSTANCES) : runHeadless - ? 10 + ? 1 : 1; export const config: WebdriverIO.Config = {