genlayer 0.12.4 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +4 -0
- package/CHANGELOG.md +8 -0
- package/dist/index.js +17970 -17628
- package/esbuild.config.dev.js +1 -2
- package/esbuild.config.prod.js +1 -1
- package/eslint.config.js +2 -1
- package/package.json +5 -3
- package/src/commands/contracts/call.ts +23 -33
- package/src/commands/contracts/deploy.ts +109 -33
- package/src/commands/contracts/index.ts +14 -3
- package/src/commands/general/init.ts +0 -1
- package/src/commands/keygen/create.ts +5 -25
- package/src/commands/scaffold/index.ts +16 -0
- package/src/commands/scaffold/new.ts +34 -0
- package/src/index.ts +2 -0
- package/src/lib/accounts/KeypairManager.ts +43 -0
- package/src/lib/actions/BaseAction.ts +34 -7
- package/src/lib/config/simulator.ts +2 -2
- package/templates/default/LICENSE +21 -0
- package/templates/default/README.md +101 -0
- package/templates/default/__init__.py +0 -0
- package/templates/default/app/.env.example +2 -0
- package/templates/default/app/.vscode/extensions.json +3 -0
- package/templates/default/app/README.md +5 -0
- package/templates/default/app/index.html +17 -0
- package/templates/default/app/package-lock.json +4920 -0
- package/templates/default/app/package.json +23 -0
- package/templates/default/app/postcss.config.js +6 -0
- package/templates/default/app/public/favicon.png +0 -0
- package/templates/default/app/src/App.vue +16 -0
- package/templates/default/app/src/components/Address.vue +38 -0
- package/templates/default/app/src/components/BetsScreen.vue +329 -0
- package/templates/default/app/src/logic/FootballBets.js +100 -0
- package/templates/default/app/src/main.js +5 -0
- package/templates/default/app/src/services/genlayer.js +19 -0
- package/templates/default/app/src/style.css +3 -0
- package/templates/default/app/tailwind.config.js +8 -0
- package/templates/default/app/vite.config.js +7 -0
- package/templates/default/config/__init__.py +0 -0
- package/templates/default/config/genlayer_config.py +14 -0
- package/templates/default/contracts/__init__.py +0 -0
- package/templates/default/contracts/football_bets.py +119 -0
- package/templates/default/deploy/deployScript.ts +31 -0
- package/templates/default/package-lock.json +3231 -0
- package/templates/default/package.json +7 -0
- package/templates/default/requirements.txt +6 -0
- package/templates/default/test/__init__.py +0 -0
- package/templates/default/test/football_bets_get_contract_schema_for_code.py +124 -0
- package/templates/default/test/test_football_bet_success_draw.py +108 -0
- package/templates/default/test/test_football_bet_success_win.py +106 -0
- package/templates/default/test/test_football_bet_unsuccess.py +107 -0
- package/templates/default/tools/__init__.py +0 -0
- package/templates/default/tools/accounts.py +5 -0
- package/templates/default/tools/calldata.py +224 -0
- package/templates/default/tools/request.py +134 -0
- package/templates/default/tools/response.py +52 -0
- package/templates/default/tools/structure.py +39 -0
- package/templates/default/tools/transactions.py +28 -0
- package/templates/default/tools/types.py +214 -0
- package/templates/default/tsconfig.json +7 -0
- package/tests/actions/call.test.ts +39 -79
- package/tests/actions/create.test.ts +11 -72
- package/tests/actions/deploy.test.ts +201 -33
- package/tests/actions/new.test.ts +80 -0
- package/tests/commands/call.test.ts +6 -1
- package/tests/commands/deploy.test.ts +12 -1
- package/tests/commands/new.test.ts +68 -0
- package/tests/index.test.ts +4 -0
- package/tests/libs/accounts/KeypairManager.test.ts +110 -0
- package/tests/libs/baseAction.test.ts +40 -0
- package/vitest.config.ts +1 -1
- package/src/lib/accounts/getPrivateKey.ts +0 -21
- package/tests/libs/getPrivateKey.test.ts +0 -96
|
@@ -20,10 +20,15 @@ describe("KeypairCreator", () => {
|
|
|
20
20
|
address: "0xMockedAddress",
|
|
21
21
|
privateKey: "0xMockedPrivateKey",
|
|
22
22
|
};
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
const mockKeypairManager = {
|
|
25
|
+
createKeypair: vi.fn(),
|
|
26
|
+
};
|
|
24
27
|
|
|
25
28
|
beforeEach(() => {
|
|
26
29
|
vi.clearAllMocks();
|
|
30
|
+
keypairCreator = new KeypairCreator();
|
|
31
|
+
(keypairCreator as any).keypairManager = mockKeypairManager;
|
|
27
32
|
vi.spyOn(keypairCreator as any, "startSpinner").mockImplementation(() => {});
|
|
28
33
|
vi.spyOn(keypairCreator as any, "succeedSpinner").mockImplementation(() => {});
|
|
29
34
|
vi.spyOn(keypairCreator as any, "failSpinner").mockImplementation(() => {});
|
|
@@ -43,86 +48,20 @@ describe("KeypairCreator", () => {
|
|
|
43
48
|
keypairCreator.createKeypairAction(options);
|
|
44
49
|
|
|
45
50
|
expect(keypairCreator["startSpinner"]).toHaveBeenCalledWith("Creating keypair...");
|
|
46
|
-
expect(
|
|
47
|
-
expect(keypairCreator["getFilePath"]).toHaveBeenCalledWith("keypair.json");
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
expect(writeFileSync).toHaveBeenCalledWith(
|
|
51
|
-
"/mocked/path/keypair.json",
|
|
52
|
-
JSON.stringify(
|
|
53
|
-
{
|
|
54
|
-
address: mockWallet.address,
|
|
55
|
-
privateKey: mockWallet.privateKey,
|
|
56
|
-
},
|
|
57
|
-
null,
|
|
58
|
-
2
|
|
59
|
-
)
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
expect(keypairCreator["writeConfig"]).toHaveBeenCalledWith(
|
|
63
|
-
"keyPairPath",
|
|
64
|
-
"/mocked/path/keypair.json"
|
|
65
|
-
);
|
|
66
|
-
|
|
51
|
+
expect(mockKeypairManager.createKeypair).toHaveBeenCalledWith(options.output, options.overwrite);
|
|
67
52
|
expect(keypairCreator["succeedSpinner"]).toHaveBeenCalledWith(
|
|
68
|
-
"Keypair successfully created and saved to:
|
|
69
|
-
);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("skips creation if file exists and overwrite is false", () => {
|
|
73
|
-
vi.mocked(existsSync).mockReturnValue(true);
|
|
74
|
-
const options = { output: "keypair.json", overwrite: false };
|
|
75
|
-
|
|
76
|
-
keypairCreator.createKeypairAction(options);
|
|
77
|
-
|
|
78
|
-
expect(ethers.Wallet.createRandom).not.toHaveBeenCalled();
|
|
79
|
-
expect(writeFileSync).not.toHaveBeenCalled();
|
|
80
|
-
expect(keypairCreator["failSpinner"]).toHaveBeenCalledWith(
|
|
81
|
-
"The file at /mocked/path/keypair.json already exists. Use the '--overwrite' option to replace it."
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("overwrites the file if overwrite is true", () => {
|
|
86
|
-
vi.mocked(existsSync).mockReturnValue(true);
|
|
87
|
-
const options = { output: "keypair.json", overwrite: true };
|
|
88
|
-
|
|
89
|
-
keypairCreator.createKeypairAction(options);
|
|
90
|
-
|
|
91
|
-
expect(keypairCreator["startSpinner"]).toHaveBeenCalledWith("Creating keypair...");
|
|
92
|
-
expect(ethers.Wallet.createRandom).toHaveBeenCalledTimes(1);
|
|
93
|
-
expect(keypairCreator["getFilePath"]).toHaveBeenCalledWith("keypair.json");
|
|
94
|
-
|
|
95
|
-
expect(writeFileSync).toHaveBeenCalledWith(
|
|
96
|
-
"/mocked/path/keypair.json",
|
|
97
|
-
JSON.stringify(
|
|
98
|
-
{
|
|
99
|
-
address: mockWallet.address,
|
|
100
|
-
privateKey: mockWallet.privateKey,
|
|
101
|
-
},
|
|
102
|
-
null,
|
|
103
|
-
2
|
|
104
|
-
)
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
expect(keypairCreator["writeConfig"]).toHaveBeenCalledWith(
|
|
108
|
-
"keyPairPath",
|
|
109
|
-
"/mocked/path/keypair.json"
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
expect(keypairCreator["succeedSpinner"]).toHaveBeenCalledWith(
|
|
113
|
-
"Keypair successfully created and saved to: /mocked/path/keypair.json"
|
|
53
|
+
"Keypair successfully created and saved to: keypair.json"
|
|
114
54
|
);
|
|
115
55
|
});
|
|
116
56
|
|
|
117
57
|
test("handles errors during keypair creation", () => {
|
|
118
|
-
const mockError = new Error("Mocked
|
|
119
|
-
|
|
120
|
-
vi.mocked(writeFileSync).mockImplementation(() => {
|
|
58
|
+
const mockError = new Error("Mocked creation error");
|
|
59
|
+
mockKeypairManager.createKeypair.mockImplementation(() => {
|
|
121
60
|
throw mockError;
|
|
122
61
|
});
|
|
123
62
|
|
|
124
63
|
keypairCreator.createKeypairAction({ output: "keypair.json", overwrite: true });
|
|
125
64
|
|
|
126
|
-
expect(keypairCreator["failSpinner"]).toHaveBeenCalledWith("Failed to generate keypair
|
|
65
|
+
expect(keypairCreator["failSpinner"]).toHaveBeenCalledWith("Failed to generate keypair", mockError);
|
|
127
66
|
});
|
|
128
67
|
});
|
|
@@ -2,17 +2,21 @@ import { describe, test, vi, beforeEach, afterEach, expect } from "vitest";
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import { createClient, createAccount } from "genlayer-js";
|
|
4
4
|
import { DeployAction, DeployOptions } from "../../src/commands/contracts/deploy";
|
|
5
|
-
import {
|
|
5
|
+
import { buildSync } from "esbuild";
|
|
6
|
+
import { pathToFileURL } from "url";
|
|
6
7
|
|
|
7
8
|
vi.mock("fs");
|
|
8
9
|
vi.mock("genlayer-js");
|
|
9
|
-
vi.mock("
|
|
10
|
+
vi.mock("esbuild", () => ({
|
|
11
|
+
buildSync: vi.fn(),
|
|
12
|
+
}));
|
|
10
13
|
|
|
11
|
-
describe("
|
|
14
|
+
describe("DeployAction", () => {
|
|
12
15
|
let deployer: DeployAction;
|
|
13
16
|
const mockClient = {
|
|
14
17
|
deployContract: vi.fn(),
|
|
15
|
-
waitForTransactionReceipt: vi.fn()
|
|
18
|
+
waitForTransactionReceipt: vi.fn(),
|
|
19
|
+
initializeConsensusSmartContract: vi.fn(),
|
|
16
20
|
};
|
|
17
21
|
|
|
18
22
|
const mockPrivateKey = "mocked_private_key";
|
|
@@ -21,8 +25,14 @@ describe("Deploy Action", () => {
|
|
|
21
25
|
vi.clearAllMocks();
|
|
22
26
|
vi.mocked(createClient).mockReturnValue(mockClient as any);
|
|
23
27
|
vi.mocked(createAccount).mockReturnValue({ privateKey: mockPrivateKey } as any);
|
|
24
|
-
vi.mocked(getPrivateKey).mockReturnValue(mockPrivateKey);
|
|
25
28
|
deployer = new DeployAction();
|
|
29
|
+
vi.spyOn(deployer as any, "getPrivateKey").mockResolvedValue(mockPrivateKey);
|
|
30
|
+
|
|
31
|
+
vi.spyOn(deployer as any, "startSpinner").mockImplementation(() => {});
|
|
32
|
+
vi.spyOn(deployer as any, "succeedSpinner").mockImplementation(() => {});
|
|
33
|
+
vi.spyOn(deployer as any, "failSpinner").mockImplementation(() => {});
|
|
34
|
+
vi.spyOn(deployer as any, "setSpinnerText").mockImplementation(() => {});
|
|
35
|
+
vi.spyOn(deployer as any, "log").mockImplementation(() => {});
|
|
26
36
|
});
|
|
27
37
|
|
|
28
38
|
afterEach(() => {
|
|
@@ -52,7 +62,6 @@ describe("Deploy Action", () => {
|
|
|
52
62
|
expect(fs.existsSync).toHaveBeenCalledWith(contractPath);
|
|
53
63
|
});
|
|
54
64
|
|
|
55
|
-
|
|
56
65
|
test("deploys contract with args", async () => {
|
|
57
66
|
const options: DeployOptions = {
|
|
58
67
|
contract: "/mocked/contract/path",
|
|
@@ -63,7 +72,9 @@ describe("Deploy Action", () => {
|
|
|
63
72
|
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
64
73
|
vi.mocked(fs.readFileSync).mockReturnValue(contractContent);
|
|
65
74
|
vi.mocked(mockClient.deployContract).mockResolvedValue("mocked_tx_hash");
|
|
66
|
-
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue({
|
|
75
|
+
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue({
|
|
76
|
+
data: { contract_address: "0xdasdsadasdasdada" },
|
|
77
|
+
});
|
|
67
78
|
|
|
68
79
|
await deployer.deploy(options);
|
|
69
80
|
|
|
@@ -73,31 +84,15 @@ describe("Deploy Action", () => {
|
|
|
73
84
|
args: [1, 2, 3],
|
|
74
85
|
leaderOnly: false,
|
|
75
86
|
});
|
|
76
|
-
expect(mockClient.deployContract).
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("throws error for both args and kwargs", async () => {
|
|
80
|
-
const options: DeployOptions = {
|
|
81
|
-
contract: "/mocked/contract/path",
|
|
82
|
-
args: [1, 2, 3],
|
|
83
|
-
kwargs: "key1=value1,key2=42",
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
await expect(deployer.deploy(options)).rejects.toThrowError(
|
|
87
|
-
"Invalid usage: Please specify either `args` or `kwargs`, but not both."
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
expect(fs.readFileSync).not.toHaveBeenCalled();
|
|
91
|
-
expect(mockClient.deployContract).not.toHaveBeenCalled();
|
|
87
|
+
expect(mockClient.deployContract).toHaveReturnedWith(Promise.resolve("mocked_tx_hash"));
|
|
92
88
|
});
|
|
93
89
|
|
|
94
90
|
test("throws error for missing contract", async () => {
|
|
95
|
-
const options: DeployOptions = {
|
|
96
|
-
};
|
|
91
|
+
const options: DeployOptions = {};
|
|
97
92
|
|
|
98
93
|
await deployer.deploy(options);
|
|
99
94
|
|
|
100
|
-
expect(
|
|
95
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith("No contract specified for deployment.");
|
|
101
96
|
expect(mockClient.deployContract).not.toHaveBeenCalled();
|
|
102
97
|
});
|
|
103
98
|
|
|
@@ -114,15 +109,13 @@ describe("Deploy Action", () => {
|
|
|
114
109
|
new Error("Mocked deployment error")
|
|
115
110
|
);
|
|
116
111
|
|
|
117
|
-
await
|
|
118
|
-
"Contract deployment failed."
|
|
119
|
-
);
|
|
112
|
+
await deployer.deploy(options);
|
|
120
113
|
|
|
121
|
-
expect(
|
|
114
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith("Error deploying contract", expect.any(Error));
|
|
122
115
|
expect(mockClient.deployContract).toHaveBeenCalled();
|
|
123
116
|
});
|
|
124
117
|
|
|
125
|
-
test("
|
|
118
|
+
test("handles empty contract code", async () => {
|
|
126
119
|
const options: DeployOptions = {
|
|
127
120
|
contract: "/mocked/contract/path",
|
|
128
121
|
};
|
|
@@ -132,8 +125,183 @@ describe("Deploy Action", () => {
|
|
|
132
125
|
|
|
133
126
|
await deployer.deploy(options);
|
|
134
127
|
|
|
135
|
-
expect(
|
|
136
|
-
expect(fs.readFileSync).toHaveBeenCalledWith(options.contract, "utf-8");
|
|
128
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith("Contract code is empty.");
|
|
137
129
|
expect(mockClient.deployContract).not.toHaveBeenCalled();
|
|
138
130
|
});
|
|
131
|
+
|
|
132
|
+
test("deployScripts executes scripts in order", async () => {
|
|
133
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
134
|
+
vi.mocked(fs.readdirSync).mockReturnValue([
|
|
135
|
+
"1_first.ts",
|
|
136
|
+
"2_second.js",
|
|
137
|
+
"10_last.ts",
|
|
138
|
+
] as any);
|
|
139
|
+
|
|
140
|
+
vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
|
|
141
|
+
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
142
|
+
|
|
143
|
+
await deployer.deployScripts();
|
|
144
|
+
|
|
145
|
+
expect(deployer["setSpinnerText"]).toHaveBeenCalledWith("Found 3 deploy scripts. Executing...");
|
|
146
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/1_first.ts/));
|
|
147
|
+
expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringMatching(/2_second.js/));
|
|
148
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/10_last.ts/));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("executeTsScript transpiles and executes TypeScript", async () => {
|
|
152
|
+
const filePath = "/mocked/script.ts";
|
|
153
|
+
const outFile = "/mocked/script.compiled.js";
|
|
154
|
+
|
|
155
|
+
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
156
|
+
vi.mocked(buildSync).mockImplementation((() => {}) as any);
|
|
157
|
+
|
|
158
|
+
await deployer["executeTsScript"](filePath);
|
|
159
|
+
|
|
160
|
+
expect(deployer["startSpinner"]).toHaveBeenCalledWith(`Transpiling TypeScript file: ${filePath}`);
|
|
161
|
+
expect(buildSync).toHaveBeenCalledWith({
|
|
162
|
+
entryPoints: [filePath],
|
|
163
|
+
outfile: outFile,
|
|
164
|
+
bundle: false,
|
|
165
|
+
platform: "node",
|
|
166
|
+
format: "esm",
|
|
167
|
+
target: "es2020",
|
|
168
|
+
sourcemap: false,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect(deployer["executeJsScript"]).toHaveBeenCalledWith(filePath, outFile);
|
|
172
|
+
expect(fs.unlinkSync).toHaveBeenCalledWith(outFile);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("deployScripts fails when deploy folder is missing", async () => {
|
|
176
|
+
vi.mocked(fs.existsSync).mockReturnValue(false);
|
|
177
|
+
|
|
178
|
+
await deployer.deployScripts();
|
|
179
|
+
|
|
180
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith("No deploy folder found.");
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test("deployScripts sorts and executes scripts correctly", async () => {
|
|
184
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
185
|
+
vi.mocked(fs.readdirSync).mockReturnValue([
|
|
186
|
+
"10_last.ts",
|
|
187
|
+
"2_second.js",
|
|
188
|
+
"1_first.ts"
|
|
189
|
+
] as any);
|
|
190
|
+
|
|
191
|
+
vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
|
|
192
|
+
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
193
|
+
|
|
194
|
+
await deployer.deployScripts();
|
|
195
|
+
|
|
196
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("1_first.ts"));
|
|
197
|
+
expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringContaining("2_second.js"));
|
|
198
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("10_last.ts"));
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test("deployScripts fails when no scripts are found", async () => {
|
|
202
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
203
|
+
vi.mocked(fs.readdirSync).mockReturnValue([]);
|
|
204
|
+
|
|
205
|
+
await deployer.deployScripts();
|
|
206
|
+
|
|
207
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith("No deploy scripts found.");
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test("deployScripts handles script execution errors", async () => {
|
|
211
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
212
|
+
vi.mocked(fs.readdirSync).mockReturnValue(["1_failing.ts"] as any);
|
|
213
|
+
vi.spyOn(deployer as any, "executeTsScript").mockRejectedValue(new Error("Script error"));
|
|
214
|
+
|
|
215
|
+
await deployer.deployScripts();
|
|
216
|
+
|
|
217
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
218
|
+
expect.stringContaining("Error executing script:"),
|
|
219
|
+
expect.any(Error)
|
|
220
|
+
);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
test("executeJsScript fails gracefully", async () => {
|
|
224
|
+
const filePath = "/mocked/script.js";
|
|
225
|
+
|
|
226
|
+
await deployer["executeJsScript"](filePath);
|
|
227
|
+
|
|
228
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
229
|
+
expect.stringContaining("Error executing:"),
|
|
230
|
+
expect.any(Error)
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("deploy fails when contract code is empty", async () => {
|
|
235
|
+
const options: DeployOptions = { contract: "/mocked/contract/path" };
|
|
236
|
+
|
|
237
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
238
|
+
vi.mocked(fs.readFileSync).mockReturnValue("");
|
|
239
|
+
|
|
240
|
+
await deployer.deploy(options);
|
|
241
|
+
|
|
242
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith("Contract code is empty.");
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("deployScripts correctly sorts mixed numbered and non-numbered scripts", async () => {
|
|
246
|
+
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
247
|
+
vi.mocked(fs.readdirSync).mockReturnValue([
|
|
248
|
+
"script.ts",
|
|
249
|
+
"2alpha_script.ts",
|
|
250
|
+
"3alpha_script.ts",
|
|
251
|
+
"blpha_script.ts",
|
|
252
|
+
"clpha_script.ts"
|
|
253
|
+
] as any);
|
|
254
|
+
|
|
255
|
+
vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
|
|
256
|
+
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
257
|
+
|
|
258
|
+
await deployer.deployScripts();
|
|
259
|
+
|
|
260
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("script.ts"));
|
|
261
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("2alpha_script.ts"));
|
|
262
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("3alpha_script.ts"));
|
|
263
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("blpha_script.ts"));
|
|
264
|
+
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("clpha_script.ts"));
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
test("executeJsScript fails if module has no default export", async () => {
|
|
268
|
+
const filePath = "/mocked/script.js";
|
|
269
|
+
|
|
270
|
+
vi.doMock(pathToFileURL(filePath).href, () => ({ default: "Not a function" }));
|
|
271
|
+
|
|
272
|
+
await deployer["executeJsScript"](filePath);
|
|
273
|
+
|
|
274
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
275
|
+
expect.stringContaining("No \"default\" function found in:"),
|
|
276
|
+
);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test("executeJsScript successfully executes a script", async () => {
|
|
280
|
+
const filePath = "/mocked/script.js";
|
|
281
|
+
const mockFn = vi.fn(); // This mock function simulates the script execution
|
|
282
|
+
|
|
283
|
+
vi.doMock(pathToFileURL(filePath).href, () => ({ default: mockFn }));
|
|
284
|
+
|
|
285
|
+
await deployer["executeJsScript"](filePath);
|
|
286
|
+
|
|
287
|
+
expect(mockFn).toHaveBeenCalledWith(mockClient);
|
|
288
|
+
|
|
289
|
+
expect(deployer["succeedSpinner"]).toHaveBeenCalledWith(`Successfully executed: ${filePath}`);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("executeTsScript fails when buildSync throws an error", async () => {
|
|
293
|
+
const filePath = "/mocked/script.ts";
|
|
294
|
+
const error = new Error("Build failed");
|
|
295
|
+
|
|
296
|
+
vi.mocked(buildSync).mockImplementation(() => {
|
|
297
|
+
throw error; // Simulate an error during transpilation
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
await deployer["executeTsScript"](filePath);
|
|
301
|
+
|
|
302
|
+
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
303
|
+
`Error executing: ${filePath}`,
|
|
304
|
+
error
|
|
305
|
+
);
|
|
306
|
+
});
|
|
139
307
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, test, vi, beforeEach, afterEach, expect } from "vitest";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { NewAction } from "../../src/commands/scaffold/new";
|
|
5
|
+
|
|
6
|
+
vi.mock("fs-extra");
|
|
7
|
+
|
|
8
|
+
describe("NewAction", () => {
|
|
9
|
+
let newAction: NewAction;
|
|
10
|
+
let mockExistsSync: any;
|
|
11
|
+
let mockCopySync: any;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.clearAllMocks();
|
|
15
|
+
newAction = new NewAction();
|
|
16
|
+
|
|
17
|
+
mockExistsSync = vi.mocked(fs.existsSync);
|
|
18
|
+
mockCopySync = vi.mocked(fs.copySync);
|
|
19
|
+
|
|
20
|
+
vi.spyOn(newAction as any, "startSpinner").mockImplementation(() => {});
|
|
21
|
+
vi.spyOn(newAction as any, "succeedSpinner").mockImplementation(() => {});
|
|
22
|
+
vi.spyOn(newAction as any, "failSpinner").mockImplementation(() => {});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
vi.restoreAllMocks();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("should successfully create a new project", async () => {
|
|
30
|
+
mockExistsSync.mockReturnValue(false);
|
|
31
|
+
mockCopySync.mockImplementation(() => {});
|
|
32
|
+
|
|
33
|
+
await newAction.createProject("myProject", { path: ".", overwrite: false });
|
|
34
|
+
|
|
35
|
+
expect(newAction["startSpinner"]).toHaveBeenCalledWith("Creating new GenLayer project: myProject");
|
|
36
|
+
expect(mockCopySync).toHaveBeenCalledWith(expect.any(String), path.resolve(".", "myProject"));
|
|
37
|
+
expect(newAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
38
|
+
`Project "myProject" created successfully at ${path.resolve(".", "myProject")}`
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("should fail if project directory exists and overwrite is not set", async () => {
|
|
43
|
+
mockExistsSync.mockReturnValue(true);
|
|
44
|
+
|
|
45
|
+
await newAction.createProject("existingProject", { path: ".", overwrite: false });
|
|
46
|
+
|
|
47
|
+
expect(newAction["failSpinner"]).toHaveBeenCalledWith(
|
|
48
|
+
`Project directory "${path.resolve(".", "existingProject")}" already exists. Use --overwrite to replace it.`
|
|
49
|
+
);
|
|
50
|
+
expect(mockCopySync).not.toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("should overwrite existing project if overwrite is set", async () => {
|
|
54
|
+
mockExistsSync.mockReturnValue(true);
|
|
55
|
+
mockCopySync.mockImplementation(() => {});
|
|
56
|
+
|
|
57
|
+
await newAction.createProject("overwriteProject", { path: ".", overwrite: true });
|
|
58
|
+
|
|
59
|
+
expect(newAction["startSpinner"]).toHaveBeenCalledWith("Creating new GenLayer project: overwriteProject");
|
|
60
|
+
expect(mockCopySync).toHaveBeenCalledWith(expect.any(String), path.resolve(".", "overwriteProject"));
|
|
61
|
+
expect(newAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
62
|
+
`Project "overwriteProject" created successfully at ${path.resolve(".", "overwriteProject")}`
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("should fail if an error occurs while copying files", async () => {
|
|
67
|
+
mockExistsSync.mockReturnValue(false);
|
|
68
|
+
const error = new Error("Mocked file system error");
|
|
69
|
+
mockCopySync.mockImplementation(() => {
|
|
70
|
+
throw error;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await newAction.createProject("errorProject", { path: ".", overwrite: false });
|
|
74
|
+
|
|
75
|
+
expect(newAction["failSpinner"]).toHaveBeenCalledWith(
|
|
76
|
+
"Error creating project \"errorProject\"",
|
|
77
|
+
error
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -4,6 +4,9 @@ import { vi, describe, beforeEach, afterEach, test, expect } from "vitest";
|
|
|
4
4
|
import { initializeContractsCommands } from "../../src/commands/contracts";
|
|
5
5
|
|
|
6
6
|
vi.mock("../../src/commands/contracts/call");
|
|
7
|
+
vi.mock("esbuild", () => ({
|
|
8
|
+
buildSync: vi.fn(),
|
|
9
|
+
}));
|
|
7
10
|
|
|
8
11
|
describe("call command", () => {
|
|
9
12
|
let program: Command;
|
|
@@ -39,12 +42,14 @@ describe("call command", () => {
|
|
|
39
42
|
"1",
|
|
40
43
|
"2",
|
|
41
44
|
"Hello",
|
|
45
|
+
"false",
|
|
46
|
+
"true"
|
|
42
47
|
]);
|
|
43
48
|
expect(CallAction).toHaveBeenCalledTimes(1);
|
|
44
49
|
expect(CallAction.prototype.call).toHaveBeenCalledWith({
|
|
45
50
|
contractAddress: "0xMockedContract",
|
|
46
51
|
method: "updateData",
|
|
47
|
-
args: [
|
|
52
|
+
args: [1, 2, "Hello", false, true]
|
|
48
53
|
});
|
|
49
54
|
});
|
|
50
55
|
|
|
@@ -4,6 +4,9 @@ import { initializeContractsCommands } from "../../src/commands/contracts";
|
|
|
4
4
|
import { DeployAction } from "../../src/commands/contracts/deploy";
|
|
5
5
|
|
|
6
6
|
vi.mock("../../src/commands/contracts/deploy");
|
|
7
|
+
vi.mock("esbuild", () => ({
|
|
8
|
+
buildSync: vi.fn(),
|
|
9
|
+
}));
|
|
7
10
|
|
|
8
11
|
describe("deploy command", () => {
|
|
9
12
|
let program: Command;
|
|
@@ -42,7 +45,7 @@ describe("deploy command", () => {
|
|
|
42
45
|
expect(DeployAction).toHaveBeenCalledTimes(1);
|
|
43
46
|
expect(DeployAction.prototype.deploy).toHaveBeenCalledWith({
|
|
44
47
|
contract: "./path/to/contract",
|
|
45
|
-
args: [
|
|
48
|
+
args: [1, 2, 3]
|
|
46
49
|
});
|
|
47
50
|
});
|
|
48
51
|
|
|
@@ -66,4 +69,12 @@ describe("deploy command", () => {
|
|
|
66
69
|
program.parse(["node", "test", "deploy", "--contract", "./path/to/contract"])
|
|
67
70
|
).not.toThrow();
|
|
68
71
|
});
|
|
72
|
+
|
|
73
|
+
test("DeployAction.deployScripts is called without throwing errors", async () => {
|
|
74
|
+
program.parse(["node", "test", "deploy"]);
|
|
75
|
+
vi.mocked(DeployAction.prototype.deployScripts).mockResolvedValueOnce(undefined);
|
|
76
|
+
expect(() =>
|
|
77
|
+
program.parse(["node", "test", "deploy"])
|
|
78
|
+
).not.toThrow();
|
|
79
|
+
});
|
|
69
80
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { vi, describe, beforeEach, afterEach, test, expect } from "vitest";
|
|
3
|
+
import { initializeScaffoldCommands } from "../../src/commands/scaffold";
|
|
4
|
+
import { NewAction } from "../../src/commands/scaffold/new";
|
|
5
|
+
|
|
6
|
+
vi.mock("../../src/commands/scaffold/new");
|
|
7
|
+
|
|
8
|
+
describe("new command", () => {
|
|
9
|
+
let program: Command;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
program = new Command();
|
|
13
|
+
initializeScaffoldCommands(program);
|
|
14
|
+
vi.clearAllMocks();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
vi.restoreAllMocks();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("NewAction.createProject is called with default options", async () => {
|
|
22
|
+
program.parse(["node", "test", "new", "myProject"]);
|
|
23
|
+
expect(NewAction).toHaveBeenCalledTimes(1);
|
|
24
|
+
expect(NewAction.prototype.createProject).toHaveBeenCalledWith("myProject", {
|
|
25
|
+
path: ".",
|
|
26
|
+
overwrite: false,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("NewAction.createProject is called with custom path", async () => {
|
|
31
|
+
program.parse(["node", "test", "new", "myProject", "--path", "./customDir"]);
|
|
32
|
+
expect(NewAction).toHaveBeenCalledTimes(1);
|
|
33
|
+
expect(NewAction.prototype.createProject).toHaveBeenCalledWith("myProject", {
|
|
34
|
+
path: "./customDir",
|
|
35
|
+
overwrite: false,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("NewAction.createProject is called with overwrite flag", async () => {
|
|
40
|
+
program.parse(["node", "test", "new", "myProject", "--overwrite"]);
|
|
41
|
+
expect(NewAction).toHaveBeenCalledTimes(1);
|
|
42
|
+
expect(NewAction.prototype.createProject).toHaveBeenCalledWith("myProject", {
|
|
43
|
+
path: ".",
|
|
44
|
+
overwrite: true,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("NewAction is instantiated when the new command is executed", async () => {
|
|
49
|
+
program.parse(["node", "test", "new", "myProject"]);
|
|
50
|
+
expect(NewAction).toHaveBeenCalledTimes(1);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("throws error for unrecognized options", async () => {
|
|
54
|
+
const newCommand = program.commands.find((cmd) => cmd.name() === "new");
|
|
55
|
+
newCommand?.exitOverride();
|
|
56
|
+
expect(() => program.parse(["node", "test", "new", "myProject", "--unknown"])).toThrowError(
|
|
57
|
+
"error: unknown option '--unknown'"
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("NewAction.createProject is called without throwing errors for valid options", async () => {
|
|
62
|
+
program.parse(["node", "test", "new", "myProject"]);
|
|
63
|
+
vi.mocked(NewAction.prototype.createProject).mockResolvedValueOnce(undefined);
|
|
64
|
+
expect(() =>
|
|
65
|
+
program.parse(["node", "test", "new", "myProject"])
|
|
66
|
+
).not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
});
|
package/tests/index.test.ts
CHANGED
|
@@ -33,6 +33,10 @@ vi.mock("../src/commands/update", () => ({
|
|
|
33
33
|
initializeUpdateCommands: vi.fn(),
|
|
34
34
|
}));
|
|
35
35
|
|
|
36
|
+
vi.mock("../src/commands/scaffold", () => ({
|
|
37
|
+
initializeScaffoldCommands: vi.fn(),
|
|
38
|
+
}));
|
|
39
|
+
|
|
36
40
|
|
|
37
41
|
describe("CLI", () => {
|
|
38
42
|
it("should initialize CLI", () => {
|