Skip to content

Commit 5fed8ca

Browse files
authored
web: Type Tidy (#14647)
* web: Update Sentry types. * web: Update MDX types. * web: Format. Remove unused script. * web: Clean up test types. * web: Fix label in dark mode.
1 parent f471ddf commit 5fed8ca

File tree

12 files changed

+2556
-946
lines changed

12 files changed

+2556
-946
lines changed

web/commands.mjs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/// <reference types="@wdio/globals/types" />
2+
/// <reference types="./types/webdriver.js" />
3+
4+
/**
5+
*
6+
* @param {WebdriverIO.Browser} browser
7+
*/
8+
export function addCommands(browser) {
9+
/**
10+
* @file Custom WDIO browser commands
11+
*/
12+
13+
browser.addCommand(
14+
"focus",
15+
/**
16+
* @this {HTMLElement}
17+
*/
18+
function () {
19+
this.focus();
20+
21+
return this;
22+
},
23+
/* attachToElement */ true,
24+
);
25+
26+
browser.addCommand(
27+
"blur",
28+
/**
29+
* @this {HTMLElement}
30+
*/
31+
function () {
32+
this.blur();
33+
34+
return this;
35+
},
36+
/* attachToElement */ true,
37+
);
38+
}

web/package-lock.json

Lines changed: 2200 additions & 176 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414
"format": "wireit",
1515
"lint": "eslint --fix .",
1616
"lint-check": "eslint --max-warnings 0 .",
17-
"prettier": "prettier --cache --write -u .",
18-
"prettier-check": "prettier --cache --check -u .",
1917
"lint:imports": "knip --config scripts/knip.config.ts",
2018
"lint:lockfile": "wireit",
2119
"lint:types": "wireit",
2220
"lit-analyse": "wireit",
2321
"precommit": "wireit",
22+
"prettier": "prettier --cache --write -u .",
23+
"prettier-check": "prettier --cache --check -u .",
2424
"pseudolocalize": "node ./scripts/pseudolocalize.mjs",
2525
"storybook": "storybook dev -p 6006",
2626
"storybook:build": "wireit",
@@ -171,6 +171,7 @@
171171
"@wdio/browser-runner": "9.4",
172172
"@wdio/cli": "9.4",
173173
"@wdio/spec-reporter": "^9.1.2",
174+
"@web/test-runner": "^0.20.2",
174175
"chromedriver": "^136.0.3",
175176
"esbuild": "^0.25.4",
176177
"esbuild-plugin-copy": "^2.1.1",
@@ -301,8 +302,7 @@
301302
"lint",
302303
"lint:types",
303304
"lint:components",
304-
"lint:lockfile",
305-
"lint:lockfiles"
305+
"lint:lockfile"
306306
]
307307
},
308308
"storybook:build": {
@@ -371,12 +371,12 @@
371371
"chromedriver": {
372372
"axios": "^1.8.4"
373373
},
374+
"rapidoc": {
375+
"@apitools/openapi-parser@": "0.0.37"
376+
},
374377
"storybook-addon-mock": {
375378
"react": "^19.1.0",
376379
"react-dom": "^19.1.0"
377-
},
378-
"rapidoc": {
379-
"@apitools/openapi-parser@": "0.0.37"
380380
}
381381
}
382382
}

web/src/elements/Label.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { AKElement } from "@goauthentik/elements/Base";
2-
import { type SlottedTemplateResult, type Spread } from "@goauthentik/elements/types";
2+
import type { SlottedTemplateResult, Spread } from "@goauthentik/elements/types";
33
import { spread } from "@open-wc/lit-helpers";
44

5-
import { html, nothing } from "lit";
5+
import { css, html, nothing } from "lit";
66
import { customElement, property } from "lit/decorators.js";
77
import { classMap } from "lit/directives/class-map.js";
88

@@ -44,15 +44,26 @@ export class Label extends AKElement implements ILabel {
4444
@property({ type: Boolean })
4545
compact = false;
4646

47-
static get styles() {
48-
return [PFBase, PFLabel];
49-
}
47+
static styles = [
48+
PFBase,
49+
PFLabel,
50+
css`
51+
:host([theme="dark"]) {
52+
.pf-m-grey {
53+
--pf-c-label__icon--Color: var(--ak-dark-background);
54+
--pf-c-label__content--Color: var(--ak-dark-background);
55+
}
56+
}
57+
`,
58+
];
5059

5160
get classesAndIcon() {
5261
const chrome = chromeList.find(
5362
([level, color]) => this.color === level || this.color === color,
5463
);
64+
5565
const [illo, icon] = chrome ? chrome.slice(2) : ["pf-m-grey", "fa-info-circle"];
66+
5667
return {
5768
classes: {
5869
"pf-c-label": true,
@@ -65,6 +76,7 @@ export class Label extends AKElement implements ILabel {
6576

6677
render() {
6778
const { classes, icon } = this.classesAndIcon;
79+
6880
return html`<span class=${classMap(classes)}>
6981
<span class="pf-c-label__content">
7082
<span class="pf-c-label__icon">

web/src/elements/ak-mdx/components/MDXAnchor.tsx

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,52 @@ const DOCS_DOMAIN = "https://goauthentik.io";
1010
* - Resolves relative links to the public directory in the public docs domain.
1111
* - Intercepts local links and scrolls to the target element.
1212
*/
13-
export const MDXAnchor = memo<React.AnchorHTMLAttributes<HTMLAnchorElement>>(
14-
({ href, children, ...props }) => {
15-
const { publicDirectory } = useMDXModule();
13+
export const MDXAnchor = ({
14+
href,
15+
children,
16+
...props
17+
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
18+
const { publicDirectory } = useMDXModule();
1619

17-
if (href?.startsWith(".") && publicDirectory) {
18-
const nextPathname = resolve(publicDirectory, href);
20+
if (href?.startsWith(".") && publicDirectory) {
21+
const nextPathname = resolve(publicDirectory, href);
1922

20-
const nextURL = new URL(nextPathname, DOCS_DOMAIN);
21-
// Remove trailing .md and .mdx, and trailing "index".
22-
nextURL.pathname = nextURL.pathname.replace(/(index)?\.mdx?$/, "");
23-
href = nextURL.toString();
23+
const nextURL = new URL(nextPathname, DOCS_DOMAIN);
24+
// Remove trailing .md and .mdx, and trailing "index".
25+
nextURL.pathname = nextURL.pathname.replace(/(index)?\.mdx?$/, "");
26+
href = nextURL.toString();
27+
}
28+
29+
const interceptHeadingLinks = (event: React.MouseEvent<HTMLAnchorElement>) => {
30+
if (!href || !href.startsWith("#")) return;
31+
32+
event.preventDefault();
33+
34+
const rootNode = event.currentTarget.getRootNode() as ShadowRoot;
35+
36+
const elementID = href.slice(1);
37+
const target = rootNode.getElementById(elementID);
38+
39+
if (!target) {
40+
console.warn(`Element with ID ${elementID} not found`);
41+
return;
2442
}
2543

26-
const interceptHeadingLinks = (event: React.MouseEvent<HTMLAnchorElement>) => {
27-
if (!href || !href.startsWith("#")) return;
28-
29-
event.preventDefault();
30-
31-
const rootNode = event.currentTarget.getRootNode() as ShadowRoot;
32-
33-
const elementID = href.slice(1);
34-
const target = rootNode.getElementById(elementID);
35-
36-
if (!target) {
37-
console.warn(`Element with ID ${elementID} not found`);
38-
return;
39-
}
40-
41-
target.scrollIntoView({
42-
behavior: "smooth",
43-
block: "center",
44-
});
45-
};
46-
47-
return (
48-
<a
49-
href={href}
50-
onClick={interceptHeadingLinks}
51-
rel="noopener noreferrer"
52-
target="_blank"
53-
{...props}
54-
>
55-
{children}
56-
</a>
57-
);
58-
},
59-
);
60-
61-
MDXAnchor.displayName = "MDXAnchor";
44+
target.scrollIntoView({
45+
behavior: "smooth",
46+
block: "center",
47+
});
48+
};
49+
50+
return (
51+
<a
52+
href={href}
53+
onClick={interceptHeadingLinks}
54+
rel="noopener noreferrer"
55+
target="_blank"
56+
{...props}
57+
>
58+
{children}
59+
</a>
60+
);
61+
};

web/src/elements/ak-mdx/components/MDXWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface MDXWrapperProps {
88
/**
99
* A wrapper component for MDX content that adds a title if one is provided in the frontmatter.
1010
*/
11-
export const MDXWrapper: React.FC<MDXWrapperProps> = ({ children, frontmatter }) => {
11+
export const MDXWrapper = ({ children, frontmatter }: MDXWrapperProps) => {
1212
const { title } = frontmatter;
1313
const nextChildren = React.Children.toArray(children);
1414

web/tests/wdio.conf.mjs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/**
2+
* @file WebdriverIO configuration file for **component unit tests**.
3+
*
4+
* @see https://webdriver.io/docs/configurationfile.html
5+
*/
6+
import { cwd } from "process";
7+
import litCSS from "vite-plugin-lit-css";
8+
import tsconfigPaths from "vite-tsconfig-paths";
9+
10+
import { addCommands } from "../commands.mjs";
11+
12+
const NODE_ENV = process.env.NODE_ENV || "development";
13+
const headless = !!process.env.HEADLESS || !!process.env.CI;
14+
const lemmeSee = !!process.env.WDIO_LEMME_SEE;
15+
16+
/**
17+
* @type {WebdriverIO.Capabilities[]}
18+
*/
19+
const capabilities = [];
20+
21+
const DEFAULT_MAX_INSTANCES = 10;
22+
23+
let maxInstances = 1;
24+
25+
if (headless) {
26+
maxInstances = process.env.MAX_INSTANCES
27+
? parseInt(process.env.MAX_INSTANCES, 10)
28+
: DEFAULT_MAX_INSTANCES;
29+
}
30+
31+
if (!process.env.WDIO_SKIP_CHROME) {
32+
/**
33+
* @satisfies {WebdriverIO.Capabilities}
34+
*/
35+
const chromeBrowserConfig = {
36+
"browserName": "chrome",
37+
"goog:chromeOptions": {
38+
args: ["disable-search-engine-choice-screen"],
39+
},
40+
};
41+
42+
if (headless) {
43+
chromeBrowserConfig["goog:chromeOptions"].args.push(
44+
"headless",
45+
"disable-gpu",
46+
"no-sandbox",
47+
"window-size=1280,672",
48+
"browser-test",
49+
);
50+
}
51+
52+
capabilities.push(chromeBrowserConfig);
53+
}
54+
55+
if (process.env.WDIO_TEST_SAFARI) {
56+
capabilities.push({
57+
browserName: "safari",
58+
});
59+
}
60+
61+
if (process.env.WDIO_TEST_FIREFOX) {
62+
capabilities.push({
63+
browserName: "firefox",
64+
});
65+
}
66+
67+
/**
68+
* @type {WebdriverIO.BrowserRunnerOptions}
69+
*/
70+
const browserRunnerOptions = {
71+
viteConfig: {
72+
define: {
73+
"process.env.NODE_ENV": JSON.stringify(NODE_ENV),
74+
"process.env.CWD": JSON.stringify(cwd()),
75+
"process.env.AK_API_BASE_PATH": JSON.stringify(process.env.AK_API_BASE_PATH || ""),
76+
},
77+
plugins: [
78+
// ---
79+
// @ts-ignore WDIO's Vite is out of date.
80+
litCSS(),
81+
// @ts-ignore WDIO's Vite is out of date.
82+
tsconfigPaths(),
83+
],
84+
},
85+
};
86+
/**
87+
* @satisfies {WebdriverIO.Config}
88+
*/
89+
export const config = {
90+
runner: ["browser", browserRunnerOptions],
91+
92+
tsConfigPath: "./tsconfig.test.json",
93+
94+
specs: ["./src/**/*.test.ts"],
95+
exclude: [],
96+
97+
maxInstances,
98+
capabilities,
99+
logLevel: "warn",
100+
bail: 0,
101+
waitforTimeout: 12000,
102+
connectionRetryTimeout: 12000,
103+
connectionRetryCount: 3,
104+
105+
framework: "mocha",
106+
107+
reporters: ["spec"],
108+
109+
mochaOpts: {
110+
ui: "bdd",
111+
timeout: 60000,
112+
},
113+
/**
114+
* @param {WebdriverIO.Browser} browser
115+
*/
116+
before(_capabilities, _specs, browser) {
117+
addCommands(browser);
118+
},
119+
120+
afterTest() {
121+
if (lemmeSee) return browser.pause(500);
122+
},
123+
};

0 commit comments

Comments
 (0)