Skip to content

Commit

Permalink
feat: Switch to vitest pool workers for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AdiRishi committed Jul 18, 2024
1 parent 9419e8e commit ad71bdb
Show file tree
Hide file tree
Showing 17 changed files with 808 additions and 971 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
- run: pnpm install
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm build
- run: pnpm test
- run: pnpm build

- name: Coveralls Coverage Report
uses: coverallsapp/github-action@v2
5 changes: 5 additions & 0 deletions .ncurc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/raineorshine/npm-check-updates/main/src/types/RunOptions.json",
"root": true,
"reject": ["eslint", "vitest", "@vitest/coverage-v8", "@vitest/ui"]
}
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
"build": "wrangler deploy --dry-run --minify --outdir dist",
"dev": "wrangler dev --test-scheduled",
"deploy": "wrangler deploy",
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 vitest run --coverage",
"test:ui": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 vitest --coverage --ui",
"test:watch": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 vitest",
"test": "vitest run --coverage",
"test:ui": "vitest --coverage --ui",
"test:watch": "vitest",
"lint": "eslint . && prettier --check .",
"format": "prettier --write .",
"typecheck": "tsc --noEmit",
Expand All @@ -48,12 +48,13 @@
"devDependencies": {
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.7",
"@cloudflare/vitest-pool-workers": "^0.4.12",
"@cloudflare/workers-types": "^4.20240712.0",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@typescript-eslint/eslint-plugin": "^7.16.1",
"@typescript-eslint/parser": "^7.16.1",
"@vitest/coverage-v8": "^2.0.3",
"@vitest/ui": "^2.0.3",
"@vitest/coverage-istanbul": "1.5.3",
"@vitest/ui": "1.5.3",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
Expand All @@ -62,8 +63,7 @@
"typescript": "^5.5.3",
"vite-tsconfig-paths": "^4.3.2",
"vitepress": "1.3.1",
"vitest": "^2.0.3",
"vitest-environment-miniflare": "^2.14.2",
"vitest": "1.5.3",
"wrangler": "^3.65.0"
},
"dependencies": {
Expand Down
1,584 changes: 716 additions & 868 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/storage/storage-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export class StorageManager {
public static async readableStreamToBuffer(stream: ReadableStream): Promise<ArrayBuffer> {
return await new Response(stream).arrayBuffer();
}
public static textToReadableStream(text: string): ReadableStream {
return new Response(text).body!;
}
}

export class InvalidStorageError extends Error {
Expand Down
7 changes: 3 additions & 4 deletions tests/crons/deleteOldCache.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { type MockedFunction, test, expect, afterEach, beforeEach, vi } from 'vitest';
import { env } from 'cloudflare:test';
import { type MockedFunction, describe, test, expect, afterEach, beforeEach, vi } from 'vitest';
import { CURSOR_SIZE, deleteOldCache } from '~/crons/deleteOldCache';
import { Env } from '~/index';
import { KvStorage, R2Storage, StorageInterface, StorageManager } from '~/storage';
import { isDateOlderThan } from '~/utils/date';

const describe = setupMiniflareIsolatedStorage();

vi.mock('~/utils/date', async (importActual) => {
const actual = await importActual<typeof import('~/utils/date')>();
return {
Expand All @@ -24,7 +23,7 @@ describe('deleteOldCache', () => {
const artifactContent = '🎉😄😇';

beforeEach(() => {
workerEnv = getMiniflareBindings();
workerEnv = env;
});

describe('r2 storage', () => {
Expand Down
36 changes: 11 additions & 25 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { expect, it, beforeAll, afterAll, vi, type MockedFunction } from 'vitest';
import { unstable_dev } from 'wrangler';
import type { UnstableDevWorker } from 'wrangler';
import '../src';
import { env, createExecutionContext } from 'cloudflare:test';
import { SELF } from 'cloudflare:test';
import { expect, it, describe, vi, type MockedFunction, beforeEach } from 'vitest';
import { deleteOldCache } from '~/crons/deleteOldCache';
import { Env, workerHandler } from '~/index';
import { app } from '~/routes';

const describe = setupMiniflareIsolatedStorage();

vi.mock('~/crons/deleteOldCache', async (importActual) => {
const actual = await importActual<typeof import('~/crons/deleteOldCache')>();
return {
Expand All @@ -17,29 +16,16 @@ vi.mock('~/crons/deleteOldCache', async (importActual) => {
const deleteOldCacheMock = deleteOldCache as MockedFunction<typeof deleteOldCache>;

describe('remote-cache worker', () => {
let worker: UnstableDevWorker;
let workerEnv: Env;
let ctx: ExecutionContext;

beforeAll(async () => {
worker = await unstable_dev('src/index.ts', {
ip: '0.0.0.0',
experimental: { disableExperimentalWarning: true },
});
workerEnv = getMiniflareBindings();
ctx = new ExecutionContext();
});

afterAll(async () => {
await worker.stop();
});

it('Worker should be able to boot successfully', () => {
expect(worker.address).toBeTruthy();
beforeEach(() => {
workerEnv = env;
ctx = createExecutionContext();
});

it('should respond to the ping route by simulating the worker', async () => {
const response = await worker.fetch('/ping');
const response = await SELF.fetch('https://iso-util.com/ping');
expect(response).toBeTruthy();
expect(response.status).toBe(200);
const text = await response.text();
Expand Down Expand Up @@ -73,9 +59,9 @@ describe('remote-cache scheduled event', () => {
let workerEnv: Env;
let ctx: ExecutionContext;

beforeAll(() => {
workerEnv = getMiniflareBindings();
ctx = new ExecutionContext();
beforeEach(() => {
workerEnv = env;
ctx = createExecutionContext();
});

it('should call deleteOldCache', async () => {
Expand Down
9 changes: 4 additions & 5 deletions tests/routes/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { beforeEach, test, expect } from 'vitest';
import { env, createExecutionContext } from 'cloudflare:test';
import { describe, beforeEach, test, expect } from 'vitest';
import { Env } from '~/index';
import { app } from '~/routes';

const describe = setupMiniflareIsolatedStorage();

describe('Homepage route', () => {
let workerEnv: Env;
let ctx: ExecutionContext;

beforeEach(() => {
workerEnv = getMiniflareBindings();
ctx = new ExecutionContext();
workerEnv = env;
ctx = createExecutionContext();
});

test('should return a 200 status code', async () => {
Expand Down
17 changes: 8 additions & 9 deletions tests/routes/internal.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { MockedFunction, afterEach, beforeEach, expect, test, vi } from 'vitest';
import { env, createExecutionContext } from 'cloudflare:test';
import { describe, MockedFunction, afterEach, beforeEach, expect, test, vi } from 'vitest';
import { deleteOldCache } from '~/crons/deleteOldCache';
import { Env, workerHandler } from '~/index';

Expand All @@ -11,17 +12,15 @@ vi.mock('~/crons/deleteOldCache', async (importActual) => {
});
const deleteOldCacheMock = deleteOldCache as MockedFunction<typeof deleteOldCache>;

const describe = setupMiniflareIsolatedStorage();

describe('/internal Routes', () => {
let workerEnv: Env;
let ctx: ExecutionContext;
const app = workerHandler;

describe('/internal/delete-old-cache route', () => {
beforeEach(() => {
workerEnv = getMiniflareBindings();
ctx = new ExecutionContext();
workerEnv = env;
ctx = createExecutionContext();
});

afterEach(() => {
Expand Down Expand Up @@ -75,8 +74,8 @@ describe('/internal Routes', () => {

describe('/internal/populate-random-objects route', () => {
beforeEach(() => {
workerEnv = getMiniflareBindings();
ctx = new ExecutionContext();
workerEnv = env;
ctx = createExecutionContext();
});

afterEach(() => {
Expand Down Expand Up @@ -116,8 +115,8 @@ describe('/internal Routes', () => {

describe('/internal/count-objects route', () => {
beforeEach(() => {
workerEnv = getMiniflareBindings();
ctx = new ExecutionContext();
workerEnv = env;
ctx = createExecutionContext();
});

afterEach(() => {
Expand Down
22 changes: 11 additions & 11 deletions tests/routes/v8/artifacts.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { beforeEach, expect, test } from 'vitest';
import { createExecutionContext } from 'cloudflare:test';
import { env } from 'cloudflare:test';
import { describe, beforeEach, expect, test } from 'vitest';
import { Env, workerHandler } from '~/index';
import { DEFAULT_TEAM_ID } from '~/routes/v8/artifacts';
import { StorageManager } from '~/storage';

const describe = setupMiniflareIsolatedStorage();

describe('v8 Artifacts API', () => {
const app = workerHandler;
let workerEnv: Env;
Expand All @@ -16,9 +16,9 @@ describe('v8 Artifacts API', () => {

describe('GET artifact endpoint', () => {
beforeEach(async () => {
workerEnv = getMiniflareBindings();
workerEnv = env;
workerEnv.STORAGE_MANAGER = new StorageManager(workerEnv);
ctx = new ExecutionContext();
ctx = createExecutionContext();
await workerEnv.STORAGE_MANAGER.getActiveStorage().write(
`${teamId}/${artifactId}`,
artifactContent,
Expand Down Expand Up @@ -121,9 +121,9 @@ describe('v8 Artifacts API', () => {

describe('PUT artifact endpoint', () => {
beforeEach(() => {
workerEnv = getMiniflareBindings();
workerEnv = env;
workerEnv.STORAGE_MANAGER = new StorageManager(workerEnv);
ctx = new ExecutionContext();
ctx = createExecutionContext();
});

function createArtifactPutRequest(url: string, includeTag = false) {
Expand Down Expand Up @@ -209,9 +209,9 @@ describe('v8 Artifacts API', () => {

describe('HEAD artifact endpoint', () => {
beforeEach(async () => {
workerEnv = getMiniflareBindings();
workerEnv = env;
workerEnv.STORAGE_MANAGER = new StorageManager(workerEnv);
ctx = new ExecutionContext();
ctx = createExecutionContext();
await workerEnv.STORAGE_MANAGER.getActiveStorage().write(
`${teamId}/${artifactId}`,
artifactContent,
Expand Down Expand Up @@ -274,9 +274,9 @@ describe('v8 Artifacts API', () => {

describe('Artifact events endpoint', () => {
beforeEach(() => {
workerEnv = getMiniflareBindings();
workerEnv = env;
workerEnv.STORAGE_MANAGER = new StorageManager(workerEnv);
ctx = new ExecutionContext();
ctx = createExecutionContext();
});

test('it should return 200', async () => {
Expand Down
14 changes: 4 additions & 10 deletions tests/storage/kv-storage.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { beforeEach, afterEach, test, expect, vi } from 'vitest';
import { env } from 'cloudflare:test';
import { beforeEach, afterEach, describe, test, expect, vi } from 'vitest';
import { Env } from '~/index';
import { StorageManager } from '~/storage';
import { KvStorage } from '~/storage/kv-storage';

const describe = setupMiniflareIsolatedStorage();

describe('kv-storage', () => {
let workerEnv: Required<Env>;
let storage: KvStorage;
let startTime: number;

beforeEach(() => {
workerEnv = getMiniflareBindings();
workerEnv = env as Required<Env>;
storage = new KvStorage(workerEnv.KV_STORE);
startTime = Date.now();
vi.useFakeTimers();
Expand Down Expand Up @@ -111,12 +110,7 @@ describe('kv-storage', () => {
});

test('can write stream value', async () => {
const stream = new ReadableStream({
start: (controller) => {
controller.enqueue('value1');
controller.close();
},
});
const stream = StorageManager.textToReadableStream('value1');
await storage.write('key1', stream);
const result = await storage.read('key1');
const dataAsText = await StorageManager.readableStreamToText(result!);
Expand Down
25 changes: 9 additions & 16 deletions tests/storage/r2-storage.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { beforeEach, afterEach, test, expect, vi } from 'vitest';
import { env } from 'cloudflare:test';
import { beforeEach, afterEach, describe, test, expect, vi } from 'vitest';
import { Env } from '~/index';
import { StorageManager } from '~/storage';
import { R2Storage } from '~/storage/r2-storage';

const describe = setupMiniflareIsolatedStorage();

describe('r2-storage', () => {
let workerEnv: Required<Env>;
let storage: R2Storage;
let startTime: number;

beforeEach(() => {
workerEnv = getMiniflareBindings();
workerEnv = env as Required<Env>;
storage = new R2Storage(workerEnv.R2_STORE);
startTime = Date.now();
vi.useFakeTimers();
Expand Down Expand Up @@ -39,11 +38,10 @@ describe('r2-storage', () => {
customMetadata,
customMetadata,
]);
expect(result.keys.map((k) => k.metadata?.staticMetadata.createdAt)).toEqual([
new Date(startTime),
new Date(startTime),
new Date(startTime),
]);
// Go back to checking startDate for createdAt when mocking time is fixed
expect(result.keys.every((k) => k.metadata?.staticMetadata.createdAt instanceof Date)).toBe(
true
);
expect(result.cursor).toBeUndefined();
expect(result.truncated).toBe(false);
});
Expand Down Expand Up @@ -76,7 +74,7 @@ describe('r2-storage', () => {
const dataAsText = await StorageManager.readableStreamToText(result.data!);
expect(dataAsText).toBe('value1');
expect(result.metadata?.customMetadata).toEqual(customMetadata);
expect(result.metadata?.staticMetadata.createdAt).toEqual(new Date(startTime));
expect(result.metadata?.staticMetadata.createdAt instanceof Date).toBe(true);
});

test('returns undefined for missing key', async () => {
Expand Down Expand Up @@ -111,12 +109,7 @@ describe('r2-storage', () => {
});

test('can write stream value', async () => {
const stream = new ReadableStream({
start: (controller) => {
controller.enqueue('value1');
controller.close();
},
});
const stream = StorageManager.textToReadableStream('value1');
await storage.write('key1', stream);
const result = await storage.read('key1');
const dataAsText = await StorageManager.readableStreamToText(result!);
Expand Down
7 changes: 3 additions & 4 deletions tests/storage/storage-manager.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { beforeEach, afterEach, test, expect, vi } from 'vitest';
import { env } from 'cloudflare:test';
import { beforeEach, describe, afterEach, test, expect, vi } from 'vitest';
import { Env } from '~/index';
import { R2Storage, KvStorage, StorageManager } from '~/storage';

const describe = setupMiniflareIsolatedStorage();

describe('storage-manager', () => {
let workerEnv: Required<Env>;
let storageManager: StorageManager;

beforeEach(() => {
workerEnv = getMiniflareBindings();
workerEnv = env as Required<Env>;
});

afterEach(() => {
Expand Down
Loading

0 comments on commit ad71bdb

Please sign in to comment.