maplibre-gl
Version:
BSD licensed community fork of mapbox-gl, a WebGL interactive maps library
127 lines (98 loc) • 5.47 kB
text/typescript
import {describe, test, expect, beforeEach, afterEach, vi} from 'vitest';
import {workerFactory} from './web_worker.ts';
import {config} from './config.ts';
describe('workerFactory', () => {
const originalWorker = (globalThis as any).Worker;
const originalWorkerUrl = config.WORKER_URL;
beforeEach(() => {
config.WORKER_URL = '';
});
afterEach(() => {
(globalThis as any).Worker = originalWorker;
config.WORKER_URL = originalWorkerUrl;
vi.restoreAllMocks();
});
test('creates a module worker when WORKER_URL is empty', async () => {
const WorkerSpy = vi.fn();
(globalThis as any).Worker = WorkerSpy;
await workerFactory();
expect(WorkerSpy).toHaveBeenCalledTimes(1);
expect(WorkerSpy.mock.calls[0]).toEqual(['', {type: 'module'}]);
});
test('creates a classic worker when WORKER_URL ends with .cjs', async () => {
const WorkerSpy = vi.fn();
(globalThis as any).Worker = WorkerSpy;
config.WORKER_URL = '/path/to/worker.cjs';
await workerFactory();
expect(WorkerSpy).toHaveBeenCalledTimes(1);
expect(WorkerSpy.mock.calls[0]).toEqual(['/path/to/worker.cjs']);
});
test('creates a module worker when WORKER_URL ends with .mjs', async () => {
const WorkerSpy = vi.fn();
(globalThis as any).Worker = WorkerSpy;
config.WORKER_URL = '/path/to/worker.mjs';
await workerFactory();
expect(WorkerSpy).toHaveBeenCalledTimes(1);
expect(WorkerSpy.mock.calls[0]).toEqual(['/path/to/worker.mjs', {type: 'module'}]);
});
test('falls back to classic worker if module worker construction throws', async () => {
const WorkerSpy = vi.fn()
.mockImplementationOnce(() => { throw new Error('module workers not supported'); });
(globalThis as any).Worker = WorkerSpy;
config.WORKER_URL = '/path/to/worker.mjs';
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
await workerFactory();
expect(WorkerSpy).toHaveBeenCalledTimes(2);
expect(WorkerSpy.mock.calls[0]).toEqual(['/path/to/worker.mjs', {type: 'module'}]);
expect(WorkerSpy.mock.calls[1]).toEqual(['/path/to/worker.mjs']);
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('Module worker not supported'),
expect.any(Error)
);
});
test('cross-origin module worker URL is converted to an import script and the worker is constructed from a Blob URL', async () => {
const WorkerSpy = vi.fn(function() {
return {postMessage: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), terminate: vi.fn()};
});
(globalThis as any).Worker = WorkerSpy;
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue({
ok: true,
text: () => Promise.resolve('// worker code'),
} as any);
const BlobSpy = vi.spyOn(globalThis, 'Blob');
const createObjectURLSpy = vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:http://localhost/abc');
const revokeObjectURLSpy = vi.spyOn(URL, 'revokeObjectURL').mockImplementation(() => {});
config.WORKER_URL = 'https://unpkg.com/maplibre-gl/dist/maplibre-gl-worker.mjs';
await workerFactory();
expect(fetchSpy).toHaveBeenCalledTimes(0);
expect(BlobSpy).toHaveBeenCalledWith(['import "https://unpkg.com/maplibre-gl/dist/maplibre-gl-worker.mjs"'], {type: 'text/javascript'});
expect(createObjectURLSpy).toHaveBeenCalled();
expect(WorkerSpy).toHaveBeenCalledTimes(1);
expect(WorkerSpy.mock.calls[0]).toEqual(['blob:http://localhost/abc', {type: 'module'}]);
expect(revokeObjectURLSpy).toHaveBeenCalledWith('blob:http://localhost/abc');
});
test('cross-origin classic worker URL is fetched and the worker is constructed from a Blob URL', async () => {
const WorkerSpy = vi.fn(function() {
return {postMessage: vi.fn(), addEventListener: vi.fn(), removeEventListener: vi.fn(), terminate: vi.fn()};
});
(globalThis as any).Worker = WorkerSpy;
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue({
ok: true,
text: () => Promise.resolve('// worker code'),
} as any);
const createObjectURLSpy = vi.spyOn(URL, 'createObjectURL').mockReturnValue('blob:http://localhost/abc');
const revokeObjectURLSpy = vi.spyOn(URL, 'revokeObjectURL').mockImplementation(() => {});
config.WORKER_URL = 'https://unpkg.com/maplibre-gl/dist/maplibre-gl-worker.cjs';
await workerFactory();
expect(fetchSpy).toHaveBeenCalledWith('https://unpkg.com/maplibre-gl/dist/maplibre-gl-worker.cjs');
expect(createObjectURLSpy).toHaveBeenCalled();
expect(WorkerSpy).toHaveBeenCalledTimes(1);
expect(WorkerSpy.mock.calls[0]).toEqual(['blob:http://localhost/abc']);
expect(revokeObjectURLSpy).toHaveBeenCalledWith('blob:http://localhost/abc');
});
test('cross-origin fetch failure rejects the promise', async () => {
vi.spyOn(globalThis, 'fetch').mockResolvedValue({ok: false, status: 404} as any);
config.WORKER_URL = 'https://unpkg.com/maplibre-gl/dist/maplibre-gl-worker.cjs';
await expect(workerFactory()).rejects.toThrow('Failed to fetch worker script (404)');
});
});