Skip to content

Commit

Permalink
protocol: add MockClient and refactor VCR cassette file reading (#85)
Browse files Browse the repository at this point in the history
* Move `VcrClient` to `@apibara/protocol` and rename to `MockClient`.
* Abstract cassette file reading to `loadCassette` function
  • Loading branch information
fracek authored Jun 27, 2024
2 parents 3a0f381 + bad6c93 commit b99f419
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 95 deletions.
11 changes: 4 additions & 7 deletions packages/indexer/src/testing/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { test as viTest } from "vitest";
import type { Indexer } from "../indexer";
import {
type CassetteOptions,
VcrClient,
type VcrConfig,
type VcrReplayResult,
isCassetteAvailable,
loadCassette,
record,
replay,
} from "../vcr";
Expand Down Expand Up @@ -46,13 +47,9 @@ async function withClient<TFilter, TBlock, TRet>(

const context: WithClientContext<TFilter, TBlock, TRet> = {
async run(indexer) {
const client = new VcrClient(
vcrConfig,
cassetteName,
indexer.streamConfig,
);
const client = loadCassette<TFilter, TBlock>(vcrConfig, cassetteName);

if (!client.isCassetteAvailable()) {
if (!isCassetteAvailable(vcrConfig, cassetteName)) {
await record(vcrConfig, client, indexer, cassetteOptions);
}

Expand Down
82 changes: 0 additions & 82 deletions packages/indexer/src/vcr/client.ts

This file was deleted.

12 changes: 12 additions & 0 deletions packages/indexer/src/vcr/helper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import type { VcrConfig } from "./config";

export function deserialize(str: string) {
return JSON.parse(str, (_, value) =>
typeof value === "string" && value.match(/^\d+n$/)
Expand All @@ -13,3 +17,11 @@ export function serialize(obj: Record<string, unknown>): string {
"\t",
);
}

export function isCassetteAvailable(
vcrConfig: VcrConfig,
cassetteName: string,
): boolean {
const filePath = path.join(vcrConfig.cassetteDir, `${cassetteName}.json`);
return fs.existsSync(filePath);
}
1 change: 0 additions & 1 deletion packages/indexer/src/vcr/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from "./client";
export * from "./config";
export * from "./helper";
export * from "./record";
Expand Down
25 changes: 21 additions & 4 deletions packages/indexer/src/vcr/replay.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { type Indexer, run } from "@apibara/indexer";
import type { Cursor } from "@apibara/protocol";
import fs from "node:fs";
import path from "node:path";
import type { Client, Cursor } from "@apibara/protocol";
import { MockClient } from "@apibara/protocol/testing";
import { type Indexer, run } from "../indexer";
import { vcr } from "../testing/vcr";
import { VcrClient } from "./client";
import { type CassetteDataType, deserialize } from "../vcr";
import type { VcrConfig } from "./config";

export async function replay<TFilter, TBlock, TRet>(
vcrConfig: VcrConfig,
indexer: Indexer<TFilter, TBlock, TRet>,
cassetteName: string,
): Promise<VcrReplayResult<TRet>> {
const client = new VcrClient(vcrConfig, cassetteName, indexer.streamConfig);
const client = loadCassette<TFilter, TBlock>(vcrConfig, cassetteName);

const sink = vcr<TRet>();

Expand All @@ -23,3 +26,17 @@ export async function replay<TFilter, TBlock, TRet>(
export type VcrReplayResult<TRet> = {
outputs: Array<{ endCursor?: Cursor; data: TRet[] }>;
};

export function loadCassette<TFilter, TBlock>(
vcrConfig: VcrConfig,
cassetteName: string,
): Client<TFilter, TBlock> {
const filePath = path.join(vcrConfig.cassetteDir, `${cassetteName}.json`);

const data = fs.readFileSync(filePath, "utf8");
const cassetteData: CassetteDataType<TFilter, TBlock> = deserialize(data);

const { filter, messages } = cassetteData;

return new MockClient(messages, [filter]);
}
10 changes: 9 additions & 1 deletion packages/protocol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"type": "module",
"source": "./src/index.ts",
"main": "./src/index.ts",
"exports": "./src/index.ts",
"exports": {
".": "./src/index.ts",
"./testing": "./src/testing/index.ts"
},
"publishConfig": {
"files": ["dist", "src", "README.md"],
"main": "./dist/index.mjs",
Expand All @@ -14,6 +17,11 @@
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.mjs"
},
"./testing": {
"types": "./dist/testing/index.d.ts",
"import": "./dist/testing/index.mjs",
"default": "./dist/testing/index.mjs"
}
}
},
Expand Down
49 changes: 49 additions & 0 deletions packages/protocol/src/testing/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import assert from "node:assert";

import type { Client, ClientCallOptions, StreamDataOptions } from "../client";
import type { StatusRequest, StatusResponse } from "../status";
import type { StreamDataRequest, StreamDataResponse } from "../stream";

export class MockClient<TFilter, TBlock> implements Client<TFilter, TBlock> {
constructor(
private messages: StreamDataResponse<TBlock>[],
private filter: TFilter[],
) {}

async status(
request?: StatusRequest,
options?: ClientCallOptions,
): Promise<StatusResponse> {
throw new Error("Client.status is not implemented for VcrClient");
}

streamData(request: StreamDataRequest<TFilter>, options?: StreamDataOptions) {
assert.deepStrictEqual(
this.filter,
request.filter,
"Request and Cassette filter mismatch",
);

return new StreamDataIterable(this.messages);
}
}

export class StreamDataIterable<TBlock> {
constructor(private messages: StreamDataResponse<TBlock>[]) {}

[Symbol.asyncIterator](): AsyncIterator<StreamDataResponse<TBlock>> {
let index = 0;
const messages = this.messages;

return {
async next() {
if (index >= messages.length) {
return { done: true, value: undefined };
}

const message = messages[index++];
return { done: false, value: message };
},
};
}
}
1 change: 1 addition & 0 deletions packages/protocol/src/testing/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./client";

0 comments on commit b99f419

Please sign in to comment.