Skip to content

Commit

Permalink
test: unit test Web3FunctionBuilder (#40)
Browse files Browse the repository at this point in the history
* chore: Builder._validateSchema to private from public

* feat: TS-ESM compatible library versioning

* fix: import for jest unit testing

* test: Web3FunctionBuilder unit tests

* fix: test for invalid userargs

* chore: update fail message checker
  • Loading branch information
mkykadir authored Jun 15, 2023
1 parent 1b7d711 commit c056a77
Show file tree
Hide file tree
Showing 15 changed files with 44,670 additions and 58 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ src/logs/
.eslintcache

# resolver builds
.tmp
.tmp

# version file
src/lib/version.ts
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
}
},
"scripts": {
"prebuild": "node -p \"'export const SDK_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > src/lib/version.ts",
"build": "rm -rf dist && tsc --project tsconfig.build.json && yarn deps",
"deps": "yarn link && yarn link @gelatonetwork/web3-functions-sdk",
"format": "prettier --write '*/**/*.{js,json,md,ts}'",
Expand Down
127 changes: 127 additions & 0 deletions src/lib/builder/Web3FunctionBuilder.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import path from "node:path";
import { Web3FunctionBuilder } from "./Web3FunctionBuilder";

describe("Web3FunctionBuilder.build", () => {
const TEST_FOLDER_BASE = path.join(
process.cwd(),
"src/lib/builder/__test__/"
);

const buildTestPath = (folder: string): string => {
return path.join(TEST_FOLDER_BASE, folder);
};

const buildSchemaPath = (folder: string): string => {
return path.join(buildTestPath(folder), "index.ts");
};

test("should fail when input path does not exist", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("not-existing")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch("Missing Web3Function schema");
}
});

test("should fail when input path does not have schema.json", async () => {
const res = await Web3FunctionBuilder.build(buildSchemaPath("no-schema"));

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch("Missing Web3Function schema");
}
});

test("should fail when schema is missing a required field", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("missing-required-field")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch("must have required property");
}
});

test("should fail when schema major version does not match with the SDK version", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("invalid-schema-version")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch(
"must match the major version of the installed sdk"
);
}
});

test("should fail when schema memory config is invalid", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("invalid-schema-memory")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch(
"'memory' must be equal to one of the allowed values"
);
}
});

test("should fail when schema runtime config is invalid", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("invalid-schema-runtime")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch(
"'runtime' must be equal to one of the allowed values"
);
}
});

test("should fail when schema timeout is invalid", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("invalid-schema-timeout")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message.includes("'timeout' must be")).toBeTruthy();
}
});

test("should fail when schema userArgs include unknown types", async () => {
const res = await Web3FunctionBuilder.build(
buildSchemaPath("invalid-schema-userargs")
);

expect(res.success).toBeFalsy();
if (res.success === false) {
expect(res.error.message).toMatch(
"must be equal to one of the allowed values"
);
}
});

test("should pass when schema is valid", async () => {
const filePath = path.join(buildTestPath("valid-schema"), "index.js");
const res = await Web3FunctionBuilder.build(
buildSchemaPath("valid-schema"),
{
filePath,
sourcePath: path.join(buildTestPath("valid-schema"), "source.js"),
}
);

expect(res.success).toBeTruthy();
if (res.success) {
expect(res.filePath).toEqual(filePath);
}
});
});
112 changes: 55 additions & 57 deletions src/lib/builder/Web3FunctionBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import fs from "node:fs";
import { performance } from "perf_hooks";
import esbuild from "esbuild";
import Ajv from "ajv";
import * as web3FunctionSchema from "./web3function.schema.json";
import esbuild from "esbuild";
import fs from "node:fs";
import path from "node:path";
import { performance } from "perf_hooks";
import { Web3FunctionSchema } from "../types";
import { Web3FunctionUploader } from "../uploader";

// eslint-disable-next-line @typescript-eslint/no-var-requires
const packageJson = require("../../../package.json");
import { SDK_VERSION } from "../version";
import web3FunctionSchema from "./web3function.schema.json";

const ajv = new Ajv({ messages: true, allErrors: true });
const web3FunctionSchemaValidator = ajv.compile(web3FunctionSchema);
Expand Down Expand Up @@ -84,55 +82,7 @@ export class Web3FunctionBuilder {
await esbuild.build(options);
}

public static async build(
input: string,
options?: {
debug?: boolean;
filePath?: string;
sourcePath?: string;
alias?: Record<string, string>;
}
): Promise<Web3FunctionBuildResult> {
const {
debug = false,
filePath = path.join(process.cwd(), ".tmp", "index.js"),
sourcePath = path.join(process.cwd(), ".tmp", "source.js"),
alias,
} = options ?? {};

try {
const schemaPath = path.join(path.parse(input).dir, "schema.json");
const schema = await Web3FunctionBuilder._validateSchema(schemaPath);

const start = performance.now();
await Promise.all([
Web3FunctionBuilder._buildBundle(input, filePath, alias),
Web3FunctionBuilder._buildSource(input, sourcePath, alias),
]);
const buildTime = performance.now() - start; // in ms

const stats = fs.statSync(filePath);
const fileSize = stats.size / 1024 / 1024; // size in mb

return {
success: true,
schemaPath,
sourcePath,
filePath,
fileSize,
buildTime,
schema,
};
} catch (err) {
if (debug) console.error(err);
return {
success: false,
error: err,
};
}
}

public static async _validateSchema(
private static async _validateSchema(
input: string
): Promise<Web3FunctionSchema> {
const hasSchema = fs.existsSync(input);
Expand Down Expand Up @@ -176,7 +126,7 @@ Please create 'schema.json', default:
.map((validationErr) => {
let msg = `\n - `;
if (validationErr.instancePath === "/web3FunctionVersion") {
msg += `'web3FunctionVersion' must match the major version of the installed sdk (${packageJson.version})`;
msg += `'web3FunctionVersion' must match the major version of the installed sdk (${SDK_VERSION})`;
if (validationErr.params.allowedValues) {
msg += ` [${validationErr.params.allowedValues.join("|")}]`;
}
Expand All @@ -200,4 +150,52 @@ Please create 'schema.json', default:
}
return schemaBody as Web3FunctionSchema;
}

public static async build(
input: string,
options?: {
debug?: boolean;
filePath?: string;
sourcePath?: string;
alias?: Record<string, string>;
}
): Promise<Web3FunctionBuildResult> {
const {
debug = false,
filePath = path.join(process.cwd(), ".tmp", "index.js"),
sourcePath = path.join(process.cwd(), ".tmp", "source.js"),
alias,
} = options ?? {};

try {
const schemaPath = path.join(path.parse(input).dir, "schema.json");
const schema = await Web3FunctionBuilder._validateSchema(schemaPath);

const start = performance.now();
await Promise.all([
Web3FunctionBuilder._buildBundle(input, filePath, alias),
Web3FunctionBuilder._buildSource(input, sourcePath, alias),
]);
const buildTime = performance.now() - start; // in ms

const stats = fs.statSync(filePath);
const fileSize = stats.size / 1024 / 1024; // size in mb

return {
success: true,
schemaPath,
sourcePath,
filePath,
fileSize,
buildTime,
schema,
};
} catch (err) {
if (debug) console.error(err);
return {
success: false,
error: err,
};
}
}
}
7 changes: 7 additions & 0 deletions src/lib/builder/__test__/invalid-schema-memory/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"web3FunctionVersion": "2.0.0",
"runtime": "js-1.0",
"memory": 512,
"timeout": 30,
"userArgs": {}
}
7 changes: 7 additions & 0 deletions src/lib/builder/__test__/invalid-schema-runtime/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"web3FunctionVersion": "2.0.0",
"runtime": "js-2.0",
"memory": 128,
"timeout": 30,
"userArgs": {}
}
7 changes: 7 additions & 0 deletions src/lib/builder/__test__/invalid-schema-timeout/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"web3FunctionVersion": "2.0.0",
"runtime": "js-1.0",
"memory": 128,
"timeout": 300,
"userArgs": {}
}
9 changes: 9 additions & 0 deletions src/lib/builder/__test__/invalid-schema-userargs/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"web3FunctionVersion": "2.0.0",
"runtime": "js-1.0",
"memory": 128,
"timeout": 30,
"userArgs": {
"argument": "invalid"
}
}
7 changes: 7 additions & 0 deletions src/lib/builder/__test__/invalid-schema-version/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"web3FunctionVersion": "1.0.0",
"runtime": "js-1.0",
"memory": 128,
"timeout": 30,
"userArgs": {}
}
6 changes: 6 additions & 0 deletions src/lib/builder/__test__/missing-required-field/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"web3FunctionVersion": "2.0.0",
"runtime": "js-1.0",
"memory": 128,
"timeout": 30
}
Empty file.
Loading

0 comments on commit c056a77

Please sign in to comment.