Skip to content

Commit

Permalink
chore: integration tests (#9)
Browse files Browse the repository at this point in the history
* Adjust configuration settings for Vitest and TypeScript

Disabled test concurrency and adjusted file parallelism to avoid nonce errors in Vitest. Updated TypeScript configuration to change rootDir and include test files.

* Add comprehensive integration tests for stream management

Implemented tests for primitive, composed, and permission-based streams to ensure correct behavior in various scenarios. Additionally, added utilities to facilitate the testing of different wallet roles and transaction management.

* Refactor imports and correct value type conversion

Standardize import formatting and replace `value` type from string to number in stream methods. Fixed minor typos and aligned the code for consistency across multiple files, including updates to import styles and type conversions.

* Simplify stream cleanup in composedStream test

Replaced Promise.allSettled with a for-loop for stream destruction in the composedStream integration test. This change ensures that each stream is destroyed sequentially.

* update kwil to support results precision
  • Loading branch information
outerlook authored Oct 24, 2024
1 parent d0c4499 commit 722aa68
Show file tree
Hide file tree
Showing 11 changed files with 711 additions and 214 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"lodash": "4.17.21"
},
"peerDependencies": {
"@kwilteam/kwil-js": "0.7.1"
"@kwilteam/kwil-js": "0.7.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "8.11.0",
Expand Down
199 changes: 0 additions & 199 deletions src/client/client.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, expect, it } from "vitest";
import { ethers } from "ethers";
import { StreamId } from "../util/StreamId";
import { NodeTSNClient } from "./nodeClient";

describe.sequential("Client", { timeout: 30000 }, () => {
Expand Down Expand Up @@ -30,202 +29,4 @@ describe.sequential("Client", { timeout: 30000 }, () => {
const chainInfo = await kwilClient.chainInfo();
expect(chainInfo.data?.chain_id).toBeDefined();
});

it("should deploy a stream", async () => {
const chainId = await NodeTSNClient.getDefaultChainId(
"http://localhost:8484",
);
if (!chainId) {
throw new Error("Chain id not found");
}
const client = new NodeTSNClient({
chainId,
endpoint: "http://localhost:8484",
walletProvider,
});
const streamId = await StreamId.generate("test");
await using cleanup = new AsyncDisposableStack();
cleanup.defer(async () => {
await client.destroyStream(streamId, true);
});
const receipt = await client.deployStream(streamId, "primitive", true);
expect(receipt.status).toBe(200);
});

it("should wait for a transaction", async () => {
const chainId = await NodeTSNClient.getDefaultChainId(
"http://localhost:8484",
);
if (!chainId) {
throw new Error("Chain id not found");
}
const client = new NodeTSNClient({
endpoint: "http://localhost:8484",
walletProvider,
chainId,
});
await using cleanup = new AsyncDisposableStack();
cleanup.defer(async () => {
await client.destroyStream(streamId, true).catch(() => {});
});
const streamId = await StreamId.generate("test");
const receipt = await client.deployStream(streamId, "primitive", false);
if (!receipt.data?.tx_hash) {
throw new Error("Tx hash not found");
}
const receipt2 = await client.waitForTx(receipt.data.tx_hash);
expect(receipt2.height).toBeGreaterThan(0);
});

it("list my streams", async () => {
const chainId = await NodeTSNClient.getDefaultChainId(
"http://localhost:8484",
);
if (!chainId) {
throw new Error("Chain id not found");
}
const client = new NodeTSNClient({
endpoint: "http://localhost:8484",
walletProvider,
chainId,
});
await using cleanup = new AsyncDisposableStack();
cleanup.defer(async () => {
await client.destroyStream(streamId, true).catch(() => {});
});
const streamId = await StreamId.generate("test");
await client.deployStream(streamId, "primitive", true);
const streams = await client.getAllStreams(client.address());
expect(streams.length).toBeGreaterThan(0);
});

it("try query a stream", async () => {
// TODO: this test is temporary just for development, will get replaced by one that also deploys streams
const chainId = await NodeTSNClient.getDefaultChainId(
"http://localhost:8484",
);
if (!chainId) {
throw new Error("Chain id not found");
}

const client = new NodeTSNClient({
endpoint: "http://localhost:8484",
walletProvider,
chainId,
autoAuthenticate: true,
});
const streamId = StreamId.fromString(
"st39830c44932bc42a3bffef72310948",
).throw();
const stream = client.loadStream(client.ownStreamLocator(streamId));
const record = await (await stream).getRecord({});
expect(record.length).toBeGreaterThan(0);
});

it("insert records", async () => {
const chainId = await NodeTSNClient.getDefaultChainId(
"http://localhost:8484",
);
if (!chainId) {
throw new Error("Chain id not found");
}
const client = new NodeTSNClient({
endpoint: "http://localhost:8484",
walletProvider,
chainId,
});
await using cleanup = new AsyncDisposableStack();
const streamId = await StreamId.generate("test");
cleanup.defer(async () => {
await client.destroyStream(streamId, true).catch(() => {});
});

// deploy a stream
await client.deployStream(streamId, "primitive", true);

const primitiveStream = client.loadPrimitiveStream({
streamId,
dataProvider: client.address(),
});

{
const tx = await primitiveStream.initializeStream();
if (!tx.data?.tx_hash) {
throw new Error("Tx hash not found");
}
await client.waitForTx(tx.data.tx_hash);
}

{
const tx = await primitiveStream.insertRecords([
{ dateValue: "2024-01-01", value: "100" },
]);
if (!tx.data?.tx_hash) {
throw new Error("Tx hash not found");
}
await client.waitForTx(tx.data.tx_hash);
}
});

it("composed stream", async () => {
const chainId = await NodeTSNClient.getDefaultChainId(
"http://localhost:8484",
);
if (!chainId) {
throw new Error("Chain id not found");
}
const client = new NodeTSNClient({
endpoint: "http://localhost:8484",
walletProvider,
chainId,
});
await using cleanup = new AsyncDisposableStack();
const streamId = await StreamId.generate("test");
cleanup.defer(async () => {
await client.destroyStream(streamId, true).catch(() => {});
});

// deploy a composed stream
await client.deployStream(streamId, "composed", true);

const composedStream = client.loadComposedStream({
streamId,
dataProvider: client.address(),
});

// Initialize the composed stream
{
const tx = await composedStream.initializeStream();
if (!tx.data?.tx_hash) {
throw new Error("Tx hash not found");
}
await client.waitForTx(tx.data.tx_hash);
}

// Set taxonomy
{
const tx = await composedStream.setTaxonomy({
taxonomyItems: [
{
childStream: {
streamId: StreamId.fromString("test-child").throw(),
dataProvider: client.address(),
},
weight: "1",
},
],
startDate: "2024-01-01",
});
if (!tx.data?.tx_hash) {
throw new Error("Tx hash not found");
}
await client.waitForTx(tx.data.tx_hash);
}

// Get taxonomies
const taxonomies = await composedStream.describeTaxonomies({
latestVersion: true,
});
expect(taxonomies.length).toBeGreaterThan(0);
});
});
22 changes: 11 additions & 11 deletions src/contracts-api/composedStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { KwilSigner, NodeKwil, WebKwil } from "@kwilteam/kwil-js";
import { ActionInput } from "@kwilteam/kwil-js/dist/core/action";
import { GenericResponse } from "@kwilteam/kwil-js/dist/core/resreq";
import { TxReceipt } from "@kwilteam/kwil-js/dist/core/tx";
import { StreamType } from "./contractValues";
import { DateString } from "../types/other";
import { StreamLocator } from "../types/stream";
import { EthereumAddress } from "../util/EthereumAddress";
import { StreamId } from "../util/StreamId";
import { StreamType } from "./contractValues";
import { Stream } from "./stream";

export const ErrorStreamNotComposed = "stream is not a composed stream";
Expand Down Expand Up @@ -93,17 +93,17 @@ export class ComposedStream extends Stream {
.mapRight((records) => {
const taxonomyItems: Map<DateString, TaxonomyItem[]> = records.reduce(
(acc, record) => {
acc.set(record.start_date, [
{
childStream: {
streamId: StreamId.fromString(record.child_stream_id).throw(),
dataProvider: EthereumAddress.fromString(
record.child_data_provider,
).throw(),
},
weight: record.weight,
const currentArray = acc.get(record.start_date) || [];
currentArray.push({
childStream: {
streamId: StreamId.fromString(record.child_stream_id).throw(),
dataProvider: EthereumAddress.fromString(
record.child_data_provider,
).throw(),
},
]);
weight: record.weight,
});
acc.set(record.start_date, currentArray);
return acc;
},
new Map<DateString, TaxonomyItem[]>(),
Expand Down
3 changes: 2 additions & 1 deletion src/contracts-api/stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ export class Stream {
* Returns the records of the stream within the given date range
*/
public async getRecord(input: GetRecordInput): Promise<StreamRecord[]> {
// TODO: change value to string when kwil-js is updated
const result = await this.call<{ date_value: string; value: string }[]>(
"get_record",
[
Expand Down Expand Up @@ -278,7 +279,7 @@ export class Stream {
ActionInput.fromObject({
$key: key,
$value: value,
$value_type: MetadataKeyValueMap[key],
$val_type: MetadataKeyValueMap[key],
}),
]);
}
Expand Down
Loading

0 comments on commit 722aa68

Please sign in to comment.