Skip to content

Commit

Permalink
feat: make toLowerCase public and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Dec 14, 2023
1 parent 7232984 commit c060a33
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/contract_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1310,7 +1310,7 @@ function implementsToString(obj: unknown): obj is { toString(): string } {
/**
* converts a snake_case string to camelCase
*/
function toLowerCamelCase(str: string): string {
export function toLowerCamelCase(str: string): string {
return str.replace(/_\w/g, (m) => m[1].toUpperCase());
}

Expand Down
191 changes: 124 additions & 67 deletions test/unit/spec/contract_spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { xdr, Address, ContractSpec, Keypair } from "../../..";
import {
xdr,
Address,
ContractSpec,
Keypair,
Wallet,
AssembledTransaction,
u32,
toLowerCamelCase,
} from "../../..";
import { JSONSchemaFaker } from "json-schema-faker";

import spec from "../spec.json";
Expand All @@ -7,6 +16,7 @@ import { expect } from "chai";
const publicKey = "GCBVOLOM32I7OD5TWZQCIXCXML3TK56MDY7ZMTAILIBQHHKPCVU42XYW";
const addr = Address.fromString(publicKey);
let SPEC: ContractSpec;
let contract: any;

JSONSchemaFaker.format("address", () => {
let keypair = Keypair.random();
Expand All @@ -15,6 +25,7 @@ JSONSchemaFaker.format("address", () => {

before(() => {
SPEC = new ContractSpec(spec);
contract = SPEC.generateContractClient(OPTIONS);
});

it("throws if no entries", () => {
Expand Down Expand Up @@ -83,175 +94,190 @@ describe("Can round trip custom types", function () {
});
});

function roundtrip(funcName: string, input: any, typeName?: string) {
async function roundtrip(funcName: string, input: any, typeName?: string) {
let type = getResultType(funcName);
let ty = typeName ?? funcName;
let obj: any = {};
obj[ty] = input;
let scVal = SPEC.funcArgsToScVals(funcName, obj)[0];
let result = SPEC.funcResToNative(funcName, scVal);
let contract = SPEC.generateContractClient(OPTIONS);
//@ts-ignore
let { result: networkResult } = (await contract[toLowerCamelCase(funcName)](
obj
)) as AssembledTransaction<any>;
if (type.switch().value === xdr.ScSpecType.scSpecTypeResult().value) {
console.log('about to unwrap', result);
console.log("about to unwrap", result);
// @ts-ignore
result = result.unwrap();
//@ts-ignore
networkResult = networkResult.unwrap();
}
expect(result).deep.equal(input);
expect(networkResult).deep.equal(input, "failed network call");
}

it("u32", () => {
roundtrip("u32_", 1);
it("u32", async () => {
await roundtrip("u32_", 1);
});

it("i32", () => {
roundtrip("i32_", -1);
it("i32", async () => {
await roundtrip("i32_", -1);
});

it("i64", () => {
roundtrip("i64_", 1n);
it("i64", async () => {
await roundtrip("i64_", 1n);
});

it("strukt", () => {
roundtrip("strukt", { a: 0, b: true, c: "hello" });
it("strukt", async () => {
await roundtrip("strukt", { a: 0, b: true, c: "hello" });
});

describe("simple", () => {
it("first", () => {
it("first", async () => {
const simple = { tag: "First" } as const;
roundtrip("simple", simple);
await roundtrip("simple", simple);
});
it("simple second", () => {
it("simple second", async () => {
const simple = { tag: "Second" } as const;
roundtrip("simple", simple);
await roundtrip("simple", simple);
});

it("simple third", () => {
it("simple third", async () => {
const simple = { tag: "Third" } as const;
roundtrip("simple", simple);
await roundtrip("simple", simple);
});
});

describe("complex", () => {
it("struct", () => {
it("struct", async () => {
const complex = {
tag: "Struct",
values: [{ a: 0, b: true, c: "hello" }],
} as const;
roundtrip("complex", complex);
await roundtrip("complex", complex);
});

it("tuple", () => {
it("tuple", async () => {
const complex = {
tag: "Tuple",
values: [[{ a: 0, b: true, c: "hello" }, { tag: "First" }]],
} as const;
roundtrip("complex", complex);
await roundtrip("complex", complex);
});

it("enum", () => {
it("enum", async () => {
const complex = {
tag: "Enum",
values: [{ tag: "First" }],
} as const;
roundtrip("complex", complex);
await roundtrip("complex", complex);
});

it("asset", () => {
it("asset", async () => {
const complex = { tag: "Asset", values: [addr.toString(), 1n] } as const;
roundtrip("complex", complex);
await roundtrip("complex", complex);
});

it("void", () => {
it("void", async () => {
const complex = { tag: "Void" } as const;
roundtrip("complex", complex);
await roundtrip("complex", complex);
});
});

it('u32_fail_on_even', () => {
roundtrip("u32_fail_on_even", 1, "u32_");
expect(() => roundtrip("u32_fail_on_even", 2, "u32_")).to.throw(/Please provide an odd number/i);
it("u32_fail_on_even", async () => {
await roundtrip("u32_fail_on_even", 1, "u32_");
expect(
async () =>
//@ts-ignore
(
(await contract.u32FailOnEven({
u32_: 2,
})) as AssembledTransaction<u32>
).result
);
});

it("addresse", () => {
roundtrip("addresse", addr.toString());
it("addresse", async () => {
await roundtrip("addresse", addr.toString());
});

it("bytes", () => {
it("bytes", async () => {
const bytes = Buffer.from("hello");
roundtrip("bytes", bytes);
await roundtrip("bytes", bytes);
});

it("bytes_n", () => {
it("bytes_n", async () => {
const bytes_n = Buffer.from("123456789"); // what's the correct way to construct bytes_n?
roundtrip("bytes_n", bytes_n);
await roundtrip("bytes_n", bytes_n);
});

it("card", () => {
it("card", async () => {
const card = 11;
roundtrip("card", card);
await roundtrip("card", card);
});

it("boolean", () => {
roundtrip("boolean", true);
it("boolean", async () => {
await roundtrip("boolean", true);
});

it("not", () => {
roundtrip("boolean", false);
it("not", async () => {
await roundtrip("boolean", false);
});

it("i128", () => {
roundtrip("i128", -1n);
it("i128", async () => {
await roundtrip("i128", -1n);
});

it("u128", () => {
roundtrip("u128", 1n);
it("u128", async () => {
await roundtrip("u128", 1n);
});

it("map", () => {
it("map", async () => {
const map = new Map();
map.set(1, true);
map.set(2, false);
roundtrip("map", [...map.entries()]);
await roundtrip("map", [...map.entries()]);

map.set(3, "hahaha");
expect(() => roundtrip("map", [...map.entries()])).to.throw(
await expectAsyncThrow(
async () => await roundtrip("map", [...map.entries()]),
/invalid type scSpecTypeBool specified for string value/i
);
});

it("vec", () => {
it("vec", async () => {
const vec = [1, 2, 3];
roundtrip("vec", vec);
await roundtrip("vec", vec);
});

it("tuple", () => {
it("tuple", async () => {
const tuple = ["hello", 1] as const;
roundtrip("tuple", tuple);
await roundtrip("tuple", tuple);
});

it("option", () => {
roundtrip("option", 1);
roundtrip("option", undefined);
it("option", async () => {
await roundtrip("option", 1);
await roundtrip("option", undefined);
});

it("u256", () => {
roundtrip("u256", 1n);
expect(() => roundtrip("u256", -1n)).to.throw(
/expected a positive value, got: -1/i
);
it("u256", async () => {
await roundtrip("u256", 1n);
await expectAsyncThrow(async () => await roundtrip("u256", -1n), /expected a positive value, got: -1/i);
});

it("i256", () => {
roundtrip("i256", -1n);
it("i256", async () => {
await roundtrip("i256", -1n);
});

it("string", () => {
roundtrip("string", "hello");
it("string", async () => {
await roundtrip("string", "hello");
});

it("tuple_strukt", () => {
it("tuple_strukt", async () => {
const arg = [{ a: 0, b: true, c: "hello" }, { tag: "First" }] as const;

roundtrip("tuple_strukt", arg);
await roundtrip("tuple_strukt", arg);
});
});

Expand Down Expand Up @@ -381,3 +407,34 @@ function replaceBigIntWithStrings(obj: any): any {
// Otherwise, return the value as it is
return obj;
}

function getUserInfo() {
return {
publicKey: "GDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCR4W4",
};
}

const OPTIONS = {
contractId: "CBUCOWICZPC3DYYD6ZAV25FEQNY47VJJB6K4XNYDNFT5J73LKTM7LEMB",
rpcUrl: "https://rpc-futurenet.stellar.org:443",
networkPassphrase: "Test SDF Future Network ; October 2022",
wallet: {
getUserInfo,
isConnected: () => true,
isAllowed: () => true,
} as unknown as Wallet,
};

// Utility function to test async error throwing
async function expectAsyncThrow(asyncFn: any, errorMessage: any) {
try {
await asyncFn();
expect.fail("Did not throw expected error");
} catch (error) {
if (errorMessage) {
expect(error.message).to.match(errorMessage);
} else {
expect(error).to.be.an("error");
}
}
}

0 comments on commit c060a33

Please sign in to comment.