sw-test-env
Version:
A sandboxed ServiceWorker environment for testing
301 lines (250 loc) • 9.56 kB
TypeScript
// src/_.d.ts
/// <reference types="node" />
/**
* Create/retrieve `ServiceWorkerContainer` instance for `origin`.
* @param origin - the origin under which to host the service worker (default is `http://localhost:3333`)
* @param webroot - the filepath used to resolve path to service worker on disk when registering (default is `process.cwd`)
*/
export function connect(origin?: string, webroot?: string): Promise<MockServiceWorkerContainer>;
/**
* Destroy all active `ServiceWorkerContainer` instances and their associated `ServiceWorker` contexts
*/
export function destroy(): Promise<void>;
// src/api/_.d.ts
// @ts-ignore
export type Headers = import('node-fetch').Headers;
// @ts-ignore
export type Request = import('node-fetch').Request;
// @ts-ignore
export type Response = import('node-fetch').Response;
export interface MockServiceWorkerContainer extends MockEventTarget {
/** The current `ServiceWorker`, if active */
controller: MockServiceWorker | null;
/** Resolves with `ServiceWorkerRegistration` when `ServiceWorker` becomes active */
ready: Promise<MockServiceWorkerRegistration>;
/** The `ServiceWorker` instance associated with this container */
__serviceWorker__: MockServiceWorker;
onmessage: ((this: MockServiceWorkerContainer, evt: MockMessageEvent) => void) | undefined;
/**
* Install or update a service worker
* @param scriptURL - the path to your service worker file (resolved based on optional `webroot` passed to `connect()`)
* @param options - optional directory `scope` under which your service worker should be registered
*/
register(scriptURL: string, options?: { scope: string }): Promise<MockServiceWorkerRegistration>;
/**
* Trigger event in active service worker context
*/
trigger<EventType extends keyof TriggerEvents>(
eventType: EventType,
...args: Array<unknown>
): Promise<TriggerEvents[EventType]>;
/**
* Retrieve the current registration for `scope`
* @param scope
*/
getRegistration(scope: string): Promise<MockServiceWorkerRegistration>;
/**
* Retrieve all current registrations for this container
* @param scope
*/
getRegistrations(scope: string): Promise<Array<MockServiceWorkerRegistration>>;
}
export interface MockServiceWorker extends MockEventTarget {
scriptURL: string;
state: 'installing' | 'installed' | 'activating' | 'activated' | 'redundant';
/** The global execution context of your service worker (`self` inside the worker script) */
self: MockServiceWorkerGlobalScope & Record<string, unknown>;
onstatechange: ((this: MockServiceWorker, evt: Event) => void) | undefined;
postMessage(message: unknown, transferList?: Array<unknown>): void;
}
export interface MockServiceWorkerRegistration extends MockEventTarget {
scope: string;
index?: MockContentIndex;
navigationPreload?: MockNavigationPreloadManager;
pushManager?: MockPushManager;
installing: MockServiceWorker | null;
waiting: MockServiceWorker | null;
activating: MockServiceWorker | null;
active: MockServiceWorker | null;
onupdatefound: ((this: MockServiceWorkerRegistration, evt: Event) => void) | undefined;
getNotifications(options?: { tag?: string }): Promise<Array<MockNotification>>;
showNotification(title: string, options?: NotificationOptions): Promise<void>;
update(): void;
unregister(): Promise<boolean>;
}
export interface MockServiceWorkerGlobalScope extends MockEventTarget {
caches: MockCacheStorage;
clients: MockClients;
registration: MockServiceWorkerRegistration;
oninstall: ((this: MockServiceWorkerGlobalScope, evt: MockExtendableEvent) => void) | undefined;
onactivate: ((this: MockServiceWorkerGlobalScope, evt: MockExtendableEvent) => void) | undefined;
onfetch: ((this: MockServiceWorkerGlobalScope, evt: MockFetchEvent) => void) | undefined;
onmessage: ((this: MockServiceWorkerGlobalScope, evt: MockMessageEvent) => void) | undefined;
onerror: ((this: MockServiceWorkerGlobalScope, evt: MockErrorEvent) => void) | undefined;
skipWaiting(): Promise<void>;
}
export interface MockContentIndex {
add(description: ContentDescription): void;
delete(id: string): void;
getAll(): Promise<Array<ContentDescription>>;
}
export interface MockNavigationPreloadManager {
enable(): Promise<void>;
disable(): Promise<void>;
setHeaderValue(headerValue: string): Promise<void>;
getState(): Promise<{ enabled: boolean; headerValue: string }>;
}
export interface MockCacheStorage {
has(cacheName: string): Promise<boolean>;
open(cacheName: string): Promise<MockCache>;
match(
request: import('node-fetch').Request | string,
options?: CacheQueryOptions & { cacheName?: string },
): Promise<import('node-fetch').Response | undefined>;
keys(): Promise<Array<string>>;
delete(cacheName: string): Promise<boolean>;
}
export interface MockCache {
match(
request: import('node-fetch').Request | string,
options?: CacheQueryOptions,
): Promise<import('node-fetch').Response | undefined>;
matchAll(
request: import('node-fetch').Request | string,
options?: CacheQueryOptions,
): Promise<Array<import('node-fetch').Response>>;
add(request: import('node-fetch').Request | string): Promise<void>;
addAll(requests: Array<import('node-fetch').Request | string>): Promise<Array<void>>;
put(request: import('node-fetch').Request | string, response: import('node-fetch').Response): Promise<void>;
keys(
request?: import('node-fetch').Request | string,
options?: CacheQueryOptions,
): Promise<Array<import('node-fetch').Request>>;
delete(request: import('node-fetch').Request | string, options?: CacheQueryOptions): Promise<boolean>;
}
export interface MockClients {
get(id: string): Promise<MockClient | undefined>;
matchAll(options?: { includeUncontrolled?: boolean; type?: string }): Promise<Array<MockClient>>;
openWindow(url: string): Promise<MockWindowClient>;
claim(): Promise<void>;
}
export interface MockClient {
id: string;
type: string;
url: string;
postMessage(message: unknown, transferList?: Array<unknown>): void;
}
export interface MockWindowClient extends MockClient {
focused: boolean;
visibilityState: 'hidden' | 'visible';
focus(): Promise<MockWindowClient>;
navigate(url: string): Promise<MockWindowClient>;
}
export type PostMessage = (message: unknown, transferList: Array<unknown>) => void;
export interface MockMessageChannel {
port1: MockMessagePort;
port2: MockMessagePort;
}
// @ts-ignore
export class MessageChannel {
port1: MockMessagePort;
port2: MockMessagePort;
}
export interface MockMessagePort extends MockEventTarget {
onmessage: ((this: MockMessagePort, evt: MockMessageEvent) => void) | undefined;
postMessage: PostMessage;
start(): void;
close(): void;
}
export interface MockPushManager {
subscription: MockPushSubscription;
getSubscription(): Promise<MockPushSubscription>;
permissionState(): Promise<string>;
subscribe(): Promise<MockPushSubscription>;
}
export interface MockNotification {
body: string;
data: any;
dir: 'auto' | 'ltr' | 'rtl';
icon: string;
lang: string;
tag: string;
title: string;
close(): void;
}
export interface MockPushMessageData {
arrayBuffer(): ArrayBuffer;
blob(): import('buffer').Blob;
json(): Object;
text(): string;
}
export interface MockPushSubscription {
endpoint: string;
expirationTime: number | null;
options?: { userVisibleOnly: boolean; applicationServerKey: string };
getKey(name: 'p256dh' | 'auth'): ArrayBuffer;
toJSON(): Object;
unsubscribe(): Promise<boolean>;
}
type MockPushSubscriptionOptions = {
userVisibleOnly: boolean;
applicationServerKey: string;
};
type ContentDescription = {
id: string;
title: string;
description: string;
category: '' | 'homepage' | 'article' | 'video' | 'audio';
icons: Array<{ src: string; sizes: string; type: string }>;
url: string;
};
interface TriggerEvents {
install: void;
activate: void;
fetch: import('node-fetch').Response;
error: void;
unhandledrejection: void;
}
// src/api/events/_.d.ts
export interface MockEventTarget {
listeners: Record<string, Array<(event: Event) => void>>;
addEventListener(eventType: string, listener: (event: Event) => void): void;
removeEventListener(eventType: string, listener: (event: Event) => void): void;
removeAllEventListeners(): void;
dispatchEvent(event: Event): boolean;
}
export interface MockExtendableEvent extends Event {
waitUntil(promise: Promise<unknown>): void;
}
export interface MockFetchEvent extends MockExtendableEvent {
request: import('node-fetch').Request;
preloadResponse: Promise<import('node-fetch').Response | undefined>;
clientId: string;
resultingClientId: string;
replacesClientId: string;
respondWith(promise: Promise<unknown>): void;
}
export interface MockMessageEvent extends MockExtendableEvent {
data: unknown | null;
origin: string;
source: MessageEventSource | null;
ports: Array<MockMessagePort>;
}
export interface MockErrorEvent extends MockExtendableEvent {
message: string | null;
error: Error;
}
export interface MockPushEvent extends MockExtendableEvent {
data: MockPushMessageData;
}
export interface MockNotificationEvent extends MockExtendableEvent {
notification: MockNotification;
}
type FetchEventInit = {
request: import('node-fetch').Request;
preloadResponse?: Promise<import('node-fetch').Response>;
clientId?: string;
resultingClientId?: string;
replacesClientId?: string;
isReload?: boolean;
};