Skip to content

Commit 6e4a897

Browse files
authored
Convert tests to typescript (#12)
* Convert tests to TypeScript * Remove some `@ts-expect-error` comments
1 parent bc6abf4 commit 6e4a897

19 files changed

+828
-300
lines changed

.github/workflows/node.js.yml

+12-13
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ name: Node.js CI
55

66
on:
77
push:
8-
branches: [ "main" ]
8+
branches: ["main"]
99
pull_request:
10-
branches: [ "main" ]
10+
branches: ["main"]
1111

1212
jobs:
1313
build:
14-
1514
runs-on: ubuntu-latest
1615

1716
strategy:
@@ -20,13 +19,13 @@ jobs:
2019
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
2120

2221
steps:
23-
- uses: actions/checkout@v4
24-
- name: Use Node.js ${{ matrix.node-version }}
25-
uses: actions/setup-node@v4
26-
with:
27-
node-version: ${{ matrix.node-version }}
28-
cache: 'npm'
29-
- run: npm ci
30-
- run: npx playwright install
31-
- run: npm run build --if-present
32-
- run: npm test
22+
- uses: actions/checkout@v4
23+
- name: Use Node.js ${{ matrix.node-version }}
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: ${{ matrix.node-version }}
27+
cache: "npm"
28+
- run: npm ci
29+
- run: npx playwright install --with-deps
30+
- run: npm run build --if-present
31+
- run: npm test

index.ts

+53-17
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { ObservableMap } from "./observable-map.js";
2-
import { createContext, ContextEvent, UnknownContext } from "./context-protocol.js";
2+
import {
3+
createContext,
4+
ContextEvent,
5+
UnknownContext,
6+
} from "./context-protocol.js";
37

4-
interface CustomElement extends HTMLElement {
5-
new (...args: any[]): CustomElement;
6-
observedAttributes: string[];
8+
export interface CustomElement extends Element {
79
connectedCallback?(): void;
810
attributeChangedCallback?(
911
name: string,
@@ -12,26 +14,47 @@ interface CustomElement extends HTMLElement {
1214
): void;
1315
disconnectedCallback?(): void;
1416
adoptedCallback?(): void;
17+
formAssociatedCallback?(form: HTMLFormElement): void;
18+
formDisabledCallback?(disabled: boolean): void;
19+
formResetCallback?(): void;
20+
formStateRestoreCallback?(
21+
state: unknown,
22+
reason: "autocomplete" | "restore",
23+
): void;
1524
}
1625

17-
export function ProviderMixin(Class: CustomElement): CustomElement {
26+
export declare type Constructor<T> = new (...args: any[]) => T;
27+
28+
type ProviderElement = CustomElement & {
29+
contexts?: Record<PropertyKey, () => unknown>;
30+
updateContext?(name: string, value: unknown): void;
31+
};
32+
33+
type ConsumerElement = CustomElement & {
34+
contexts?: Record<PropertyKey, (data: any) => void>;
35+
};
36+
37+
export function ProviderMixin<T extends Constructor<ProviderElement>>(
38+
Class: T,
39+
): T & Constructor<ProviderElement> {
1840
return class extends Class {
1941
#dataStore = new ObservableMap();
2042

2143
connectedCallback() {
2244
super.connectedCallback?.();
2345

24-
// @ts-expect-error todo
25-
for (const [key, value] of Object.entries(this.contexts || {})) {
26-
// @ts-expect-error todo
46+
const contexts = "contexts" in this ? this.contexts : {};
47+
48+
for (const [key, value] of Object.entries(contexts || {})) {
2749
this.#dataStore.set(key, value());
2850
}
2951

30-
this.addEventListener('context-request', this);
52+
this.addEventListener("context-request", this);
3153
}
3254

3355
disconnectedCallback(): void {
3456
this.#dataStore = new ObservableMap();
57+
this.removeEventListener("context-request", this);
3558
}
3659

3760
handleEvent(event: Event) {
@@ -72,15 +95,29 @@ export function ProviderMixin(Class: CustomElement): CustomElement {
7295
};
7396
}
7497

75-
export function ConsumerMixin(Class: CustomElement): CustomElement {
98+
export function ConsumerMixin<T extends Constructor<ConsumerElement>>(
99+
Class: T,
100+
): T & Constructor<ConsumerElement> {
76101
return class extends Class {
77-
unsubscribes: Array<() => void> = [];
102+
#unsubscribes: Array<() => void> = [];
103+
104+
getContext(contextName: string) {
105+
let result;
106+
107+
this.dispatchEvent(
108+
new ContextEvent(createContext(contextName), (data) => {
109+
result = data;
110+
}),
111+
);
112+
113+
return result;
114+
}
78115

79116
connectedCallback() {
80117
super.connectedCallback?.();
81118

82-
// @ts-expect-error don't worry about it babe
83-
for (const [contextName, callback] of Object.entries(this.contexts)) {
119+
const contexts = "contexts" in this ? this.contexts : {};
120+
for (const [contextName, callback] of Object.entries(contexts || {})) {
84121
const context = createContext(contextName);
85122

86123
// We dispatch a event with that context. The event will bubble up the tree until it
@@ -90,10 +127,9 @@ export function ConsumerMixin(Class: CustomElement): CustomElement {
90127
new ContextEvent(
91128
context,
92129
(data, unsubscribe) => {
93-
// @ts-expect-error
94130
callback(data);
95131
if (unsubscribe) {
96-
this.unsubscribes.push(unsubscribe);
132+
this.#unsubscribes.push(unsubscribe);
97133
}
98134
},
99135
// Always subscribe. Consumers can ignore updates if they'd like.
@@ -105,12 +141,12 @@ export function ConsumerMixin(Class: CustomElement): CustomElement {
105141

106142
// Unsubscribe from all callbacks when disconnecting
107143
disconnectedCallback() {
108-
for (const unsubscribe of this.unsubscribes) {
144+
for (const unsubscribe of this.#unsubscribes) {
109145
unsubscribe?.();
110146
}
111147
// Empty out the array in case this element is still stored in memory but just not connected
112148
// to the DOM.
113-
this.unsubscribes = [];
149+
this.#unsubscribes = [];
114150
}
115151
};
116152
}

observable-map.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export class ObservableMap {
66
set(key: string, value: unknown, subscribers = new Set<Subscriber<unknown>>()) {
77
const data = this.#store.get(key);
88
subscribers = new Set([...subscribers, ...(data?.subscribers || new Set())]);
9+
910
this.#store.set(key, {value, subscribers});
1011
for (const subscriber of subscribers) {
1112
subscriber(value);

0 commit comments

Comments
 (0)