Skip to content

Commit

Permalink
Add integration test in react sdk (#214)
Browse files Browse the repository at this point in the history
* Modify calling signTypedData by wallet client

* Upload pnpm-lock.yaml

* Remove useless code

* Set up test env

* Modify error handle logic

* Modify timeout time

* Add util methods and wrapper

* Add dispute integration test

* Make test serially execute

* Add ipAsset integration test

* Add ipAccount integration

* Add useLicense integration test

* Add permission, royalty, nftClient integration test in react sdk

* Modify test description

* Add nftClient integration test

* Move babel config into package.json

* Return false when license Terms are already attached to IP Asset
  • Loading branch information
bonnie57 authored Jul 2, 2024
1 parent 003e6df commit 2629456
Show file tree
Hide file tree
Showing 31 changed files with 2,807 additions and 262 deletions.
4 changes: 1 addition & 3 deletions packages/core-sdk/src/resources/license.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,7 @@ export class LicenseClient {
licenseTermsId: request.licenseTermsId,
});
if (isAttachedLicenseTerms) {
throw new Error(
`License terms id ${request.licenseTermsId} is already attached to the IP with id ${request.ipId}.`,
);
return { txHash: "", success: false };
}
const txHash = await this.licensingModuleClient.attachLicenseTerms({
ipId: request.ipId,
Expand Down
1 change: 0 additions & 1 deletion packages/core-sdk/src/types/resources/dispute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export type RaiseDisputeRequest = {
export type RaiseDisputeResponse = {
txHash: string;
disputeId?: bigint;
arbitrationPolicy?: Address;
};

export type CancelDisputeRequest = {
Expand Down
6 changes: 3 additions & 3 deletions packages/core-sdk/test/integration/dispute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe("Dispute Functions", () => {

before(async () => {
clientA = getStoryClientInSepolia();
clientB = getStoryClientInSepolia(process.env.SEPOLIA_WALLET_PRIVATE_KEY2 as Address);
clientB = getStoryClientInSepolia();
const mockERC20 = new MockERC20();
await mockERC20.approve(arbitrationPolicyAddress);
const tokenId = await getTokenId();
Expand All @@ -33,7 +33,7 @@ describe("Dispute Functions", () => {
).ipId!;
});

it("raise a dispute", async () => {
it("should not throw error when raise a dispute", async () => {
const raiseDisputeRequest: RaiseDisputeRequest = {
targetIpId: ipIdB,
arbitrationPolicy: arbitrationPolicyAddress,
Expand All @@ -50,7 +50,7 @@ describe("Dispute Functions", () => {
expect(response.disputeId).to.be.a("bigint");
});

it("cancel a dispute", async () => {
it("should not throw error when cancel a dispute", async () => {
const cancelDispute: CancelDisputeRequest = {
disputeId: disputeId,
txOptions: {
Expand Down
2 changes: 0 additions & 2 deletions packages/core-sdk/test/integration/ipAccount.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
accessControllerAddress,
coreMetadataModuleAddress,
} from "../../src/abi/generated";
import { privateKeyToAccount } from "viem/accounts";
import { getDeadline } from "../../src/utils/sign";

chai.use(chaiAsPromised);
Expand Down Expand Up @@ -61,7 +60,6 @@ describe("Ip Account functions", () => {
});

it("should not throw error when executeWithSig setting permission", async () => {
const account = privateKeyToAccount(process.env.SEPOLIA_WALLET_PRIVATE_KEY as Hex);
const state = await client.ipAccount.getIpAccountNonce(ipId);
const expectedState = state + 1n;
const deadline = getDeadline(60000n);
Expand Down
21 changes: 21 additions & 0 deletions packages/core-sdk/test/integration/nftClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { expect } from "chai";
import { StoryClient } from "../../src";
import { getStoryClientInSepolia } from "./utils/util";

describe("nftClient Functions", () => {
let client: StoryClient;
before(async () => {
client = getStoryClientInSepolia();
});
it("should success when create nft collection", async () => {
const txData = await client.nftClient.createNFTCollection({
name: "test-collection",
symbol: "TEST",
maxSupply: 100,
txOptions: {
waitForTransaction: true,
},
});
expect(txData.nftContract).to.be.a("string").and.not.empty;
});
});
8 changes: 2 additions & 6 deletions packages/core-sdk/test/integration/utils/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,11 @@ export const getTokenId = async (nftContract?: Address): Promise<number | undefi
}
};

export const getStoryClientInSepolia = (privateKey?: Address): StoryClient => {
export const getStoryClientInSepolia = (): StoryClient => {
const config: StoryConfig = {
chainId: "sepolia",
transport: http(RPC),
account: privateKeyToAccount(privateKey || (process.env.SEPOLIA_WALLET_PRIVATE_KEY as Address)),
account: privateKeyToAccount(process.env.SEPOLIA_WALLET_PRIVATE_KEY as Address),
};
return StoryClient.newClient(config);
};

export const getBlockTimestamp = async (): Promise<bigint> => {
return (await publicClient.getBlock()).timestamp;
};
21 changes: 9 additions & 12 deletions packages/core-sdk/test/unit/resources/license.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,23 +291,20 @@ describe("Test LicenseClient", () => {
}
});

it("should throw attached error when call attachLicenseTerms given licenseTermsId is already attached", async () => {
it("should return txHash of empty and success of false when call attachLicenseTerms given licenseTermsId is already attached", async () => {
sinon.stub(licenseClient.ipAssetRegistryClient, "isRegistered").resolves(true);
sinon.stub(licenseClient.piLicenseTemplateReadOnlyClient, "exists").resolves(true);
sinon
.stub(licenseClient.licenseRegistryReadOnlyClient, "hasIpAttachedLicenseTerms")
.resolves(true);

try {
await licenseClient.attachLicenseTerms({
ipId: zeroAddress,
licenseTermsId: "1",
});
} catch (error) {
expect((error as Error).message).equal(
"Failed to attach license terms: License terms id 1 is already attached to the IP with id 0x0000000000000000000000000000000000000000.",
);
}
const result = await licenseClient.attachLicenseTerms({
ipId: zeroAddress,
licenseTermsId: "1",
});
expect(result).to.deep.equal({
txHash: "",
success: false,
});
});

it("should return txHash when call attachLicenseTerms given args is correct", async () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-sdk/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SEPOLIA_TEST_WALLET_ADDRESS = 0x0000000000000000000000000000000000000000
SEPOLIA_WALLET_PRIVATE_KEY = 0x0000000000000000000000000000000000000000
10 changes: 5 additions & 5 deletions packages/react-sdk/generator/templates/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ const methodTemplate = `<%=comments%>\nconst <%=method.name %> = async (<% metho
setLoadings((prev ) => ({ ...prev, <%=method.name %>: false }));
return response;
}catch(e){
if(e instanceof Error){
setErrors((prev) => ({ ...prev, <%=method.name %>: e.message }));
setLoadings((prev) => ({ ...prev, <%=method.name %>: false }));
}
throw new Error(\`unhandled error type\`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, <%=method.name %>: errorMessage }));
setLoadings((prev) => ({ ...prev, <%=method.name %>: false }));
throw new Error(errorMessage);
}
};
`;
Expand All @@ -28,6 +27,7 @@ const startTemplate = `import { <% types.forEach((type,index)=>{%>\n<%=type %><%
import { useState } from "react";
import { useStoryContext } from "../StoryProtocolContext";
import { handleError } from "../util";
const use<%=name %> = () => {
const client = useStoryContext();
const [loadings,setLoadings] = useState<Record<string,boolean>>({<% methodNames.forEach((name,index)=>{%><%=name %>: false<%=index === methodNames.length - 1 ? '' : ',' %> <%})%>});
Expand Down
9 changes: 9 additions & 0 deletions packages/react-sdk/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('jest').Config} */
const config = {
verbose: true,
testEnvironment: "./test/jest-environment-jsdom.ts",
setupFiles: ["./test/jest-setup.ts"],
testTimeout: 1000 * 60,
};

module.exports = config;
32 changes: 25 additions & 7 deletions packages/react-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"scripts": {
"generate": "node ./generator/index.js && npm run fix",
"build": "pnpm run fix && preconstruct build",
"test": "jest -i",
"fix": "pnpm run format:fix && pnpm run lint:fix",
"format": "prettier --check .",
"format:fix": "prettier --write .",
Expand Down Expand Up @@ -43,7 +44,14 @@
],
"babel": {
"presets": [
"@babel/preset-env",
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"@babel/preset-typescript",
[
"@babel/preset-react",
Expand All @@ -57,19 +65,29 @@
"dependencies": {
"@story-protocol/core-sdk": "1.0.0-rc.14",
"react": "^18.3.1",
"viem": "^2.8.12",
"@types/react": "^18.3.3"
"viem": "^2.8.12"
},
"devDependencies": {
"@babel/preset-env": "^7.22.20",
"@babel/core": "^7.23.0",
"@babel/preset-env": "^7.24.4",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.23.0",
"@babel/preset-typescript": "^7.24.1",
"@preconstruct/cli": "^2.8.1",
"@story-protocol/eslint-config": "workspace:*",
"@story-protocol/prettier-config": "workspace:*",
"@story-protocol/tsconfig": "workspace:*",
"@testing-library/react": "^16.0.0",
"@types/jest": "^29.5.12",
"@types/node": "^20.8.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"babel-jest": "^29.7.0",
"dotenv": "^16.3.1",
"ejs": "^3.1.10",
"eslint-plugin-jest-dom": "^5.4.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"ts-node": "^10.9.1",
"typescript": "^5.4.5",
"ejs": "^3.1.10"
"typescript": "^5.4.5"
}
}
28 changes: 13 additions & 15 deletions packages/react-sdk/src/resources/useDispute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { useState } from "react";

import { useStoryContext } from "../StoryProtocolContext";
import { handleError } from "../util";

const useDispute = () => {
const client = useStoryContext();
Expand Down Expand Up @@ -49,11 +50,10 @@ const useDispute = () => {
setLoadings((prev) => ({ ...prev, raiseDispute: false }));
return response;
} catch (e) {
if (e instanceof Error) {
setErrors((prev) => ({ ...prev, raiseDispute: e.message }));
setLoadings((prev) => ({ ...prev, raiseDispute: false }));
}
throw new Error(`unhandled error type`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, raiseDispute: errorMessage }));
setLoadings((prev) => ({ ...prev, raiseDispute: false }));
throw new Error(errorMessage);
}
};

Expand All @@ -79,11 +79,10 @@ const useDispute = () => {
setLoadings((prev) => ({ ...prev, cancelDispute: false }));
return response;
} catch (e) {
if (e instanceof Error) {
setErrors((prev) => ({ ...prev, cancelDispute: e.message }));
setLoadings((prev) => ({ ...prev, cancelDispute: false }));
}
throw new Error(`unhandled error type`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, cancelDispute: errorMessage }));
setLoadings((prev) => ({ ...prev, cancelDispute: false }));
throw new Error(errorMessage);
}
};

Expand All @@ -107,11 +106,10 @@ const useDispute = () => {
setLoadings((prev) => ({ ...prev, resolveDispute: false }));
return response;
} catch (e) {
if (e instanceof Error) {
setErrors((prev) => ({ ...prev, resolveDispute: e.message }));
setLoadings((prev) => ({ ...prev, resolveDispute: false }));
}
throw new Error(`unhandled error type`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, resolveDispute: errorMessage }));
setLoadings((prev) => ({ ...prev, resolveDispute: false }));
throw new Error(errorMessage);
}
};

Expand Down
28 changes: 13 additions & 15 deletions packages/react-sdk/src/resources/useIpAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { useState } from "react";

import { useStoryContext } from "../StoryProtocolContext";
import { handleError } from "../util";

const useIpAccount = () => {
const client = useStoryContext();
Expand Down Expand Up @@ -41,11 +42,10 @@ const useIpAccount = () => {
setLoadings((prev) => ({ ...prev, execute: false }));
return response;
} catch (e) {
if (e instanceof Error) {
setErrors((prev) => ({ ...prev, execute: e.message }));
setLoadings((prev) => ({ ...prev, execute: false }));
}
throw new Error(`unhandled error type`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, execute: errorMessage }));
setLoadings((prev) => ({ ...prev, execute: false }));
throw new Error(errorMessage);
}
};

Expand All @@ -70,11 +70,10 @@ const useIpAccount = () => {
setLoadings((prev) => ({ ...prev, executeWithSig: false }));
return response;
} catch (e) {
if (e instanceof Error) {
setErrors((prev) => ({ ...prev, executeWithSig: e.message }));
setLoadings((prev) => ({ ...prev, executeWithSig: false }));
}
throw new Error(`unhandled error type`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, executeWithSig: errorMessage }));
setLoadings((prev) => ({ ...prev, executeWithSig: false }));
throw new Error(errorMessage);
}
};

Expand All @@ -92,11 +91,10 @@ const useIpAccount = () => {
setLoadings((prev) => ({ ...prev, getIpAccountNonce: false }));
return response;
} catch (e) {
if (e instanceof Error) {
setErrors((prev) => ({ ...prev, getIpAccountNonce: e.message }));
setLoadings((prev) => ({ ...prev, getIpAccountNonce: false }));
}
throw new Error(`unhandled error type`);
const errorMessage = handleError(e);
setErrors((prev) => ({ ...prev, getIpAccountNonce: errorMessage }));
setLoadings((prev) => ({ ...prev, getIpAccountNonce: false }));
throw new Error(errorMessage);
}
};

Expand Down
Loading

0 comments on commit 2629456

Please sign in to comment.