movehat 0.0.7-alpha.0 → 0.0.9-alpha.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/README.md +37 -20
- package/dist/cli.js +18 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/test-move.d.ts +7 -0
- package/dist/commands/test-move.d.ts.map +1 -0
- package/dist/commands/test-move.js +50 -0
- package/dist/commands/test-move.js.map +1 -0
- package/dist/commands/test.d.ts +8 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +106 -25
- package/dist/commands/test.js.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +50 -8
- package/dist/core/config.js.map +1 -1
- package/dist/templates/README.md +20 -0
- package/dist/templates/movehat.config.ts +10 -0
- package/dist/templates/package.json +5 -3
- package/dist/templates/tests/Counter.test.ts +47 -50
- package/package.json +1 -1
- package/src/cli.ts +20 -2
- package/src/commands/test-move.ts +61 -0
- package/src/commands/test.ts +124 -26
- package/src/core/config.ts +54 -10
- package/src/templates/README.md +20 -0
- package/src/templates/movehat.config.ts +10 -0
- package/src/templates/package.json +5 -3
- package/src/templates/tests/Counter.test.ts +47 -50
package/README.md
CHANGED
|
@@ -102,41 +102,58 @@ MH_NETWORK=testnet
|
|
|
102
102
|
|
|
103
103
|
## Writing Tests
|
|
104
104
|
|
|
105
|
+
Movehat uses **Transaction Simulation** for testing - no real blockchain or gas costs required:
|
|
106
|
+
|
|
105
107
|
```typescript
|
|
106
108
|
import { describe, it, before } from "mocha";
|
|
107
109
|
import { expect } from "chai";
|
|
108
|
-
import {
|
|
109
|
-
import type { TestEnvironment, MoveContract } from "movehat/helpers";
|
|
110
|
+
import { getMovehat, type MovehatRuntime } from "movehat";
|
|
110
111
|
|
|
111
112
|
describe("Counter Contract", () => {
|
|
112
|
-
let
|
|
113
|
-
let
|
|
113
|
+
let mh: MovehatRuntime;
|
|
114
|
+
let contractAddress: string;
|
|
114
115
|
|
|
115
116
|
before(async function () {
|
|
116
117
|
this.timeout(30000);
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
);
|
|
118
|
+
|
|
119
|
+
// Initialize Movehat Runtime Environment
|
|
120
|
+
// Uses Movement testnet by default with auto-generated test accounts
|
|
121
|
+
mh = await getMovehat();
|
|
122
|
+
contractAddress = mh.account.accountAddress.toString();
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
it("should
|
|
125
|
+
it("should initialize counter using simulation", async function () {
|
|
126
126
|
this.timeout(30000);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
127
|
+
|
|
128
|
+
// Build transaction
|
|
129
|
+
const transaction = await mh.aptos.transaction.build.simple({
|
|
130
|
+
sender: mh.account.accountAddress,
|
|
131
|
+
data: {
|
|
132
|
+
function: `${contractAddress}::counter::init`,
|
|
133
|
+
functionArguments: []
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Simulate transaction (no gas cost, instant)
|
|
138
|
+
const [simulation] = await mh.aptos.transaction.simulate.simple({
|
|
139
|
+
signerPublicKey: mh.account.publicKey,
|
|
140
|
+
transaction
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Verify simulation succeeded
|
|
144
|
+
expect(simulation.success).to.be.true;
|
|
145
|
+
console.log(`Gas used: ${simulation.gas_used}`);
|
|
136
146
|
});
|
|
137
147
|
});
|
|
138
148
|
```
|
|
139
149
|
|
|
150
|
+
**Benefits of Transaction Simulation:**
|
|
151
|
+
- No blockchain or fork server required
|
|
152
|
+
- Instant test execution
|
|
153
|
+
- No gas costs
|
|
154
|
+
- Perfect for TDD and CI/CD
|
|
155
|
+
- Uses Movement testnet with auto-generated accounts by default
|
|
156
|
+
|
|
140
157
|
## Writing Deployment Scripts
|
|
141
158
|
|
|
142
159
|
```typescript
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readFileSync } from 'fs';
|
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import testCommand from './commands/test.js';
|
|
7
|
+
import testMoveCommand from './commands/test-move.js';
|
|
7
8
|
import compileCommand from './commands/compile.js';
|
|
8
9
|
import initCommand from './commands/init.js';
|
|
9
10
|
import runCommand from './commands/run.js';
|
|
@@ -59,8 +60,23 @@ program
|
|
|
59
60
|
.action(runCommand);
|
|
60
61
|
program
|
|
61
62
|
.command('test')
|
|
62
|
-
.description('Run
|
|
63
|
-
.
|
|
63
|
+
.description('Run all tests (Move + TypeScript)')
|
|
64
|
+
.option('--move-only', 'Run only Move unit tests')
|
|
65
|
+
.option('--ts-only', 'Run only TypeScript integration tests')
|
|
66
|
+
.option('--watch', 'Run TypeScript tests in watch mode')
|
|
67
|
+
.option('--filter <pattern>', 'Filter Move tests by name pattern')
|
|
68
|
+
.action((options) => testCommand(options));
|
|
69
|
+
program
|
|
70
|
+
.command('test:move')
|
|
71
|
+
.description('Run Move unit tests')
|
|
72
|
+
.option('--filter <pattern>', 'Filter tests by name pattern')
|
|
73
|
+
.option('--ignore-warnings', 'Ignore compilation warnings')
|
|
74
|
+
.action((options) => testMoveCommand(options));
|
|
75
|
+
program
|
|
76
|
+
.command('test:ts')
|
|
77
|
+
.description('Run TypeScript integration tests')
|
|
78
|
+
.option('--watch', 'Run tests in watch mode')
|
|
79
|
+
.action((options) => testCommand({ tsOnly: true, watch: options.watch }));
|
|
64
80
|
// Fork commands
|
|
65
81
|
const fork = program
|
|
66
82
|
.command('fork')
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,WAAW,MAAM,oBAAoB,CAAC;AAC7C,OAAO,cAAc,MAAM,uBAAuB,CAAC;AACnD,OAAO,WAAW,MAAM,oBAAoB,CAAC;AAC7C,OAAO,UAAU,MAAM,mBAAmB,CAAC;AAC3C,OAAO,iBAAiB,MAAM,2BAA2B,CAAC;AAC1D,OAAO,uBAAuB,MAAM,kCAAkC,CAAC;AACvE,OAAO,eAAe,MAAM,yBAAyB,CAAC;AACtD,OAAO,eAAe,MAAM,yBAAyB,CAAC;AACtD,OAAO,gBAAgB,MAAM,0BAA0B,CAAC;AAExD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1F,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC;;GAEG;AACH,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QAC5C,MAAM,IAAI,0BAA0B,CAAC,6CAA6C,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,8CAA8C,CAAC;KAC3D,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,YAAY,EAAE,yCAAyC,CAAC;KAC/D,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACjC,6DAA6D;IAC7D,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAC/C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC;IACvC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO;KACF,OAAO,CAAC,qBAAqB,CAAC;KAC9B,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE;IACpB,WAAW,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEP,OAAO;KACF,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,cAAc,CAAC,CAAC;AAE5B,OAAO;KACF,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,UAAU,CAAC,CAAC;AAExB,OAAO;KACF,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-move.d.ts","sourceRoot":"","sources":["../../src/commands/test-move.ts"],"names":[],"mappings":"AAKA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAA8B,eAAe,CAAC,OAAO,GAAE,eAAoB,iBAkD1E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { loadUserConfig } from "../core/config.js";
|
|
5
|
+
export default async function testMoveCommand(options = {}) {
|
|
6
|
+
try {
|
|
7
|
+
const userConfig = await loadUserConfig();
|
|
8
|
+
const moveDir = path.resolve(process.cwd(), userConfig.moveDir || "./move");
|
|
9
|
+
if (!fs.existsSync(moveDir)) {
|
|
10
|
+
console.error(`Move directory not found: ${moveDir}`);
|
|
11
|
+
console.error(` Update movehat.config.ts -> moveDir`);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
console.log("Running Move unit tests...\n");
|
|
15
|
+
const args = ["move", "test", "--package-dir", moveDir];
|
|
16
|
+
// Add filter if provided
|
|
17
|
+
if (options.filter) {
|
|
18
|
+
args.push("--filter", options.filter);
|
|
19
|
+
}
|
|
20
|
+
// Add ignore-warnings flag if provided
|
|
21
|
+
if (options.ignoreWarnings) {
|
|
22
|
+
args.push("--ignore-compile-warnings");
|
|
23
|
+
}
|
|
24
|
+
// Spawn movement CLI
|
|
25
|
+
const child = spawn("movement", args, {
|
|
26
|
+
stdio: "inherit",
|
|
27
|
+
cwd: process.cwd(),
|
|
28
|
+
});
|
|
29
|
+
child.on("exit", (code) => {
|
|
30
|
+
if (code === 0) {
|
|
31
|
+
console.log("\n✓ Move tests passed");
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.error("\n✗ Move tests failed");
|
|
35
|
+
}
|
|
36
|
+
process.exit(code || 0);
|
|
37
|
+
});
|
|
38
|
+
child.on("error", (error) => {
|
|
39
|
+
console.error(`Failed to run Move tests: ${error.message}`);
|
|
40
|
+
console.error(" Make sure Movement CLI is installed");
|
|
41
|
+
console.error(" Run: movement --version");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.error("Move tests failed:", err.message ?? err);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=test-move.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-move.js","sourceRoot":"","sources":["../../src/commands/test-move.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAOnD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,eAAe,CAAC,UAA2B,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC;QAE5E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAE5C,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;QAExD,yBAAyB;QACzB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QAED,uCAAuC;QACvC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACzC,CAAC;QAED,qBAAqB;QACrB,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE;YACpC,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;SACnB,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YACzC,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACxD,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/commands/test.d.ts
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
interface TestOptions {
|
|
2
|
+
moveOnly?: boolean;
|
|
3
|
+
tsOnly?: boolean;
|
|
4
|
+
watch?: boolean;
|
|
5
|
+
filter?: string;
|
|
6
|
+
}
|
|
7
|
+
export default function testCommand(options?: TestOptions): Promise<void>;
|
|
8
|
+
export {};
|
|
2
9
|
//# sourceMappingURL=test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAA8B,WAAW,CAAC,OAAO,GAAE,WAAgB,iBA2BlE"}
|
package/dist/commands/test.js
CHANGED
|
@@ -1,35 +1,116 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
import { loadUserConfig } from "../core/config.js";
|
|
5
|
+
import path from "path";
|
|
6
|
+
export default async function testCommand(options = {}) {
|
|
7
|
+
// Handle move-only flag
|
|
8
|
+
if (options.moveOnly) {
|
|
9
|
+
return runMoveTestsSync(options.filter);
|
|
10
|
+
}
|
|
11
|
+
// Handle ts-only flag (current behavior)
|
|
12
|
+
if (options.tsOnly) {
|
|
13
|
+
return runTypeScriptTests(options.watch);
|
|
10
14
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Default: Run both Move and TypeScript tests
|
|
16
|
+
console.log("Running all tests...\n");
|
|
17
|
+
console.log("=" + "=".repeat(60) + "\n");
|
|
18
|
+
// First run Move tests (fail fast)
|
|
19
|
+
try {
|
|
20
|
+
await runMoveTestsSync();
|
|
21
|
+
console.log("\n" + "=" + "=".repeat(60) + "\n");
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error("\n✗ Move tests failed");
|
|
25
|
+
console.log("\n" + "=" + "=".repeat(60));
|
|
17
26
|
process.exit(1);
|
|
18
27
|
}
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
// Then run TypeScript tests
|
|
29
|
+
return runTypeScriptTests(false);
|
|
30
|
+
}
|
|
31
|
+
function runMoveTestsSync(filter) {
|
|
32
|
+
return new Promise(async (resolve, reject) => {
|
|
33
|
+
console.log("1. Move Unit Tests");
|
|
34
|
+
console.log("-" + "-".repeat(60) + "\n");
|
|
35
|
+
try {
|
|
36
|
+
const userConfig = await loadUserConfig();
|
|
37
|
+
const moveDir = path.resolve(process.cwd(), userConfig.moveDir || "./move");
|
|
38
|
+
if (!existsSync(moveDir)) {
|
|
39
|
+
console.log("⊘ No Move directory found (./move not found)");
|
|
40
|
+
console.log(" Skipping Move tests...\n");
|
|
41
|
+
resolve();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const args = ["move", "test", "--package-dir", moveDir];
|
|
45
|
+
if (filter) {
|
|
46
|
+
args.push("--filter", filter);
|
|
47
|
+
}
|
|
48
|
+
const child = spawn("movement", args, {
|
|
49
|
+
stdio: "inherit",
|
|
50
|
+
cwd: process.cwd(),
|
|
51
|
+
});
|
|
52
|
+
child.on("exit", (code) => {
|
|
53
|
+
if (code === 0) {
|
|
54
|
+
console.log("\n✓ Move tests passed");
|
|
55
|
+
resolve();
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
reject(new Error("Move tests failed"));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
child.on("error", (error) => {
|
|
62
|
+
console.error(`Failed to run Move tests: ${error.message}`);
|
|
63
|
+
console.error(" Make sure Movement CLI is installed");
|
|
64
|
+
reject(error);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
reject(error);
|
|
69
|
+
}
|
|
29
70
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
71
|
+
}
|
|
72
|
+
function runTypeScriptTests(watch = false) {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
console.log("2. TypeScript Integration Tests");
|
|
75
|
+
console.log("-" + "-".repeat(60) + "\n");
|
|
76
|
+
const testDir = join(process.cwd(), "tests");
|
|
77
|
+
if (!existsSync(testDir)) {
|
|
78
|
+
console.log("⊘ No TypeScript tests found (tests directory not found)");
|
|
79
|
+
console.log(" Skipping TypeScript tests...\n");
|
|
80
|
+
resolve();
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const mochaPath = join(process.cwd(), "node_modules", ".bin", "mocha");
|
|
84
|
+
if (!existsSync(mochaPath)) {
|
|
85
|
+
console.error("✗ Mocha not found in project dependencies.");
|
|
86
|
+
console.error(" Install it with: npm install --save-dev mocha");
|
|
87
|
+
reject(new Error("Mocha not found"));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const args = watch ? ["--watch"] : [];
|
|
91
|
+
const child = spawn(mochaPath, args, {
|
|
92
|
+
stdio: "inherit",
|
|
93
|
+
env: {
|
|
94
|
+
...process.env,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
child.on("exit", (code) => {
|
|
98
|
+
if (code === 0) {
|
|
99
|
+
console.log("\n✓ TypeScript tests passed");
|
|
100
|
+
console.log("\n" + "=" + "=".repeat(60));
|
|
101
|
+
console.log("\n✓ All tests passed!\n");
|
|
102
|
+
resolve();
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
console.error("\n✗ TypeScript tests failed");
|
|
106
|
+
console.log("\n" + "=" + "=".repeat(60));
|
|
107
|
+
process.exit(code || 1);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
child.on("error", (error) => {
|
|
111
|
+
console.error(`Failed to run TypeScript tests: ${error.message}`);
|
|
112
|
+
reject(error);
|
|
113
|
+
});
|
|
33
114
|
});
|
|
34
115
|
}
|
|
35
116
|
//# sourceMappingURL=test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEtE;;;;;;GAMG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAyDjE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,iBAAiB,EAC7B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEtE;;;;;;GAMG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAyDjE;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,iBAAiB,EAC7B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAoHxB"}
|
package/dist/core/config.js
CHANGED
|
@@ -62,16 +62,34 @@ export async function loadUserConfig() {
|
|
|
62
62
|
*/
|
|
63
63
|
export async function resolveNetworkConfig(userConfig, networkName) {
|
|
64
64
|
// Determine which network to use
|
|
65
|
+
// Default to "testnet" for testing with simulation
|
|
65
66
|
const selectedNetwork = networkName ||
|
|
66
67
|
process.env.MH_CLI_NETWORK ||
|
|
67
68
|
process.env.MH_DEFAULT_NETWORK ||
|
|
68
69
|
userConfig.defaultNetwork ||
|
|
69
70
|
"testnet";
|
|
70
71
|
// Check if network exists in config
|
|
71
|
-
|
|
72
|
+
let networkConfig = userConfig.networks[selectedNetwork];
|
|
73
|
+
// Special case: Auto-generate config for testnet (public test network)
|
|
74
|
+
// This provides a better dev experience - no local setup required
|
|
75
|
+
if (!networkConfig && selectedNetwork === "testnet") {
|
|
76
|
+
networkConfig = {
|
|
77
|
+
url: "https://testnet.movementnetwork.xyz/v1",
|
|
78
|
+
chainId: "testnet",
|
|
79
|
+
};
|
|
80
|
+
console.log(`testnet not found in config - using default Movement testnet configuration`);
|
|
81
|
+
}
|
|
82
|
+
// Special case: Auto-generate config for local fork server
|
|
83
|
+
if (!networkConfig && selectedNetwork === "local") {
|
|
84
|
+
networkConfig = {
|
|
85
|
+
url: "http://localhost:8080/v1",
|
|
86
|
+
chainId: "local",
|
|
87
|
+
};
|
|
88
|
+
console.log(`Local network not found in config - using default fork server configuration`);
|
|
89
|
+
}
|
|
72
90
|
if (!networkConfig) {
|
|
73
91
|
const availableNetworks = Object.keys(userConfig.networks).join(", ");
|
|
74
|
-
throw new Error(`Network '${selectedNetwork}' not found in configuration.\nAvailable networks: ${availableNetworks}`);
|
|
92
|
+
throw new Error(`Network '${selectedNetwork}' not found in configuration.\nAvailable networks: ${availableNetworks}, testnet (auto-generated), local (auto-generated)`);
|
|
75
93
|
}
|
|
76
94
|
// Get accounts using Hardhat-style resolution:
|
|
77
95
|
// 1. Network-specific accounts (if defined)
|
|
@@ -91,13 +109,37 @@ export async function resolveNetworkConfig(userConfig, networkName) {
|
|
|
91
109
|
if (accounts.length === 0 && process.env.PRIVATE_KEY) {
|
|
92
110
|
accounts = [process.env.PRIVATE_KEY];
|
|
93
111
|
}
|
|
94
|
-
// 4. Validate we have at least one account
|
|
112
|
+
// 4. Validate we have at least one account (unless using testnet/local)
|
|
95
113
|
if (accounts.length === 0 || !accounts[0]) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
114
|
+
// Special case: Auto-generate test accounts for testing networks
|
|
115
|
+
// testnet = public Movement test network (recommended)
|
|
116
|
+
// local = local fork server
|
|
117
|
+
if (selectedNetwork === "testnet" || selectedNetwork === "local") {
|
|
118
|
+
// Security: Using a deterministic test account (like Hardhat's default accounts)
|
|
119
|
+
// This is SAFE because:
|
|
120
|
+
// 1. Only used for testnet/local (never mainnet - that throws error below)
|
|
121
|
+
// 2. Perfect for transaction simulation (no real funds)
|
|
122
|
+
// 3. Deterministic = consistent test results
|
|
123
|
+
const testPrivateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
124
|
+
accounts = [testPrivateKey];
|
|
125
|
+
console.log(`\n[TESTNET] Using auto-generated test account (safe for testing only)`);
|
|
126
|
+
console.log(`[TESTNET] For mainnet, set PRIVATE_KEY in .env\n`);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// For any other network (especially mainnet), REQUIRE explicit configuration
|
|
130
|
+
// This prevents accidentally using the test key on production networks
|
|
131
|
+
throw new Error(`Network '${selectedNetwork}' has no accounts configured.\n` +
|
|
132
|
+
`\n` +
|
|
133
|
+
`SECURITY: This network requires explicit account configuration.\n` +
|
|
134
|
+
`\n` +
|
|
135
|
+
`Options:\n` +
|
|
136
|
+
` 1. Set PRIVATE_KEY in your .env file (recommended for ${selectedNetwork})\n` +
|
|
137
|
+
` 2. Add 'accounts: ["0x..."]' globally in movehat.config.ts\n` +
|
|
138
|
+
` 3. Add 'accounts: ["0x..."]' to the '${selectedNetwork}' network config\n` +
|
|
139
|
+
`\n` +
|
|
140
|
+
`For testing without configuration, use:\n` +
|
|
141
|
+
` movehat <command> --network testnet (auto-generates safe test accounts)`);
|
|
142
|
+
}
|
|
101
143
|
}
|
|
102
144
|
// Merge named addresses (network-specific overrides global)
|
|
103
145
|
const mergedNamedAddresses = {
|
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAGhC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,gDAAgD;IAChD,MAAM,aAAa,GAAG;QACpB,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC;QAC9B,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC;KAC/B,CAAC;IAEF,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,UAAU,GAAG,IAAI,CAAC;YAClB,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,6GAA6G,CAC9G,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,IAAI,YAAY,CAAC;QAEjB,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,2DAA2D;YAC3D,oCAAoC;YACpC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,QAAQ,EAAE,CAAC;YAE9B,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;gBACjD,YAAY,GAAG,MAAM,MAAM,CAAC,SAAS,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAC9D,CAAC;oBAAS,CAAC;gBACT,UAAU,EAAE,CAAC;YACf,CAAC;QACH,CAAC;aAAM,CAAC;YACN,qCAAqC;YACrC,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YACjD,YAAY,GAAG,MAAM,MAAM,CAAC,SAAS,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,UAAU,GAAG,YAAY,CAAC,OAA4B,CAAC;QAE7D,qCAAqC;QACrC,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1E,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,sCAAsC,UAAU,MAAM,KAAK,EAAE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAA6B,EAC7B,WAAoB;IAEpB,iCAAiC;IACjC,MAAM,eAAe,GACnB,WAAW;QACX,OAAO,CAAC,GAAG,CAAC,cAAc;QAC1B,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC9B,UAAU,CAAC,cAAc;QACzB,SAAS,CAAC;IAEZ,oCAAoC;IACpC,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
package/dist/templates/README.md
CHANGED
|
@@ -52,6 +52,26 @@ npm run compile
|
|
|
52
52
|
npm test
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
**Two types of tests available:**
|
|
56
|
+
|
|
57
|
+
1. **Move Unit Tests** (`tests/Counter.move` lines 50-63)
|
|
58
|
+
- Written in Move with `#[test]` annotations
|
|
59
|
+
- Test internal logic and business rules
|
|
60
|
+
- Ultra-fast execution (milliseconds)
|
|
61
|
+
- Run with: `npm run test:move`
|
|
62
|
+
|
|
63
|
+
2. **TypeScript Integration Tests** (`tests/Counter.test.ts`)
|
|
64
|
+
- Written in TypeScript using Transaction Simulation
|
|
65
|
+
- Test end-to-end flows and SDK integration
|
|
66
|
+
- No blockchain or gas costs required
|
|
67
|
+
- Run with: `npm run test:ts`
|
|
68
|
+
|
|
69
|
+
**Commands:**
|
|
70
|
+
- `npm test` - Runs both Move + TypeScript tests
|
|
71
|
+
- `npm run test:move` - Only Move unit tests (fast)
|
|
72
|
+
- `npm run test:ts` - Only TypeScript integration tests
|
|
73
|
+
- `npm run test:watch` - TypeScript tests in watch mode
|
|
74
|
+
|
|
55
75
|
### 5. Deploy (optional)
|
|
56
76
|
|
|
57
77
|
```bash
|
|
@@ -3,18 +3,28 @@ dotenv.config();
|
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
// Default network to use when no --network flag is provided
|
|
6
|
+
// "testnet" = Movement testnet (public, auto-generates test accounts)
|
|
7
|
+
// "mainnet" = Movement mainnet (requires PRIVATE_KEY in .env)
|
|
8
|
+
// "local" = Fork server running on localhost:8080
|
|
6
9
|
defaultNetwork: "testnet",
|
|
7
10
|
|
|
8
11
|
// Network configurations
|
|
9
12
|
networks: {
|
|
13
|
+
// Movement Testnet - Public test network (recommended for development)
|
|
14
|
+
// Auto-generates test accounts - no local setup required
|
|
15
|
+
// Perfect for running tests with transaction simulation
|
|
10
16
|
testnet: {
|
|
11
17
|
url: process.env.MOVEMENT_RPC_URL || "https://testnet.movementnetwork.xyz/v1",
|
|
12
18
|
chainId: "testnet",
|
|
13
19
|
},
|
|
20
|
+
// Movement Mainnet - Production network
|
|
21
|
+
// REQUIRES PRIVATE_KEY in .env - uses real MOVE tokens
|
|
14
22
|
mainnet: {
|
|
15
23
|
url: "https://mainnet.movementnetwork.xyz/v1",
|
|
16
24
|
chainId: "mainnet",
|
|
17
25
|
},
|
|
26
|
+
// Local fork server (requires: movehat fork serve)
|
|
27
|
+
// Useful for testing against a snapshot of real network state
|
|
18
28
|
local: {
|
|
19
29
|
url: "http://localhost:8080/v1",
|
|
20
30
|
chainId: "local",
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "
|
|
7
|
-
"test:
|
|
6
|
+
"test": "movehat test",
|
|
7
|
+
"test:move": "movehat test:move",
|
|
8
|
+
"test:ts": "movehat test:ts",
|
|
9
|
+
"test:watch": "movehat test:ts --watch",
|
|
8
10
|
"deploy": "movehat run scripts/deploy-counter.ts"
|
|
9
11
|
},
|
|
10
12
|
"dependencies": {
|
|
11
|
-
"movehat": "
|
|
13
|
+
"movehat": "latest",
|
|
12
14
|
"@aptos-labs/ts-sdk": "^5.1.5",
|
|
13
15
|
"dotenv": "^17.2.3"
|
|
14
16
|
},
|
|
@@ -1,75 +1,72 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-nocheck - This is a template file, dependencies are installed in user projects
|
|
2
|
+
import { describe, it, before } from "mocha";
|
|
2
3
|
import { expect } from "chai";
|
|
3
4
|
import { getMovehat, type MovehatRuntime } from "movehat";
|
|
4
|
-
import type { MoveContract } from "movehat/helpers";
|
|
5
|
-
import { assertTransactionSuccess, snapshot } from "movehat/helpers";
|
|
6
5
|
|
|
7
6
|
describe("Counter Contract", () => {
|
|
8
7
|
let mh: MovehatRuntime;
|
|
9
|
-
let
|
|
8
|
+
let contractAddress: string;
|
|
10
9
|
|
|
11
10
|
before(async function () {
|
|
12
11
|
this.timeout(30000);
|
|
13
12
|
|
|
14
13
|
// Initialize Movehat Runtime Environment
|
|
14
|
+
// Uses testnet by default - no local setup required
|
|
15
15
|
mh = await getMovehat();
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
console.log(` Account: ${mh.account.accountAddress.toString()}\n`);
|
|
17
|
+
contractAddress = mh.account.accountAddress.toString();
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
mh.account.accountAddress.toString(),
|
|
23
|
-
"counter"
|
|
24
|
-
);
|
|
19
|
+
console.log(`\nTesting on ${mh.network.name}`);
|
|
20
|
+
console.log(`Account: ${contractAddress}\n`);
|
|
25
21
|
});
|
|
26
22
|
|
|
27
23
|
describe("Counter functionality", () => {
|
|
28
|
-
it("should initialize counter", async function () {
|
|
24
|
+
it("should initialize counter using simulation", async function () {
|
|
29
25
|
this.timeout(30000);
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
// Build transaction
|
|
28
|
+
const transaction = await mh.aptos.transaction.build.simple({
|
|
29
|
+
sender: mh.account.accountAddress,
|
|
30
|
+
data: {
|
|
31
|
+
function: `${contractAddress}::counter::init`,
|
|
32
|
+
functionArguments: []
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Simulate transaction (no gas cost, instant)
|
|
37
|
+
const [simulation] = await mh.aptos.transaction.simulate.simple({
|
|
38
|
+
signerPublicKey: mh.account.publicKey,
|
|
39
|
+
transaction
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Verify simulation succeeded
|
|
43
|
+
expect(simulation.success).to.be.true;
|
|
44
|
+
console.log(`Counter init simulated successfully`);
|
|
45
|
+
console.log(`Gas used: ${simulation.gas_used}`);
|
|
40
46
|
});
|
|
41
47
|
|
|
42
|
-
it("should increment counter", async function () {
|
|
48
|
+
it("should increment counter using simulation", async function () {
|
|
43
49
|
this.timeout(30000);
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
// Build increment transaction
|
|
52
|
+
const transaction = await mh.aptos.transaction.build.simple({
|
|
53
|
+
sender: mh.account.accountAddress,
|
|
54
|
+
data: {
|
|
55
|
+
function: `${contractAddress}::counter::increment`,
|
|
56
|
+
functionArguments: []
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Simulate transaction
|
|
61
|
+
const [simulation] = await mh.aptos.transaction.simulate.simple({
|
|
62
|
+
signerPublicKey: mh.account.publicKey,
|
|
63
|
+
transaction
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Verify simulation succeeded
|
|
67
|
+
expect(simulation.success).to.be.true;
|
|
68
|
+
console.log(`Counter increment simulated successfully`);
|
|
69
|
+
console.log(`Gas used: ${simulation.gas_used}`);
|
|
58
70
|
});
|
|
59
71
|
});
|
|
60
|
-
|
|
61
|
-
// Optional: Create a snapshot after tests for debugging
|
|
62
|
-
// Uncomment to enable
|
|
63
|
-
/*
|
|
64
|
-
after(async function () {
|
|
65
|
-
this.timeout(30000);
|
|
66
|
-
|
|
67
|
-
const snapshotPath = await snapshot({
|
|
68
|
-
name: 'counter-test-final'
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
console.log(`\n📸 Snapshot created: ${snapshotPath}`);
|
|
72
|
-
console.log(` Use 'aptos move sim view-resource --session ${snapshotPath}' to inspect state\n`);
|
|
73
|
-
});
|
|
74
|
-
*/
|
|
75
72
|
});
|
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { readFileSync } from 'fs';
|
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import testCommand from './commands/test.js';
|
|
7
|
+
import testMoveCommand from './commands/test-move.js';
|
|
7
8
|
import compileCommand from './commands/compile.js';
|
|
8
9
|
import initCommand from './commands/init.js';
|
|
9
10
|
import runCommand from './commands/run.js';
|
|
@@ -67,8 +68,25 @@ program
|
|
|
67
68
|
|
|
68
69
|
program
|
|
69
70
|
.command('test')
|
|
70
|
-
.description('Run
|
|
71
|
-
.
|
|
71
|
+
.description('Run all tests (Move + TypeScript)')
|
|
72
|
+
.option('--move-only', 'Run only Move unit tests')
|
|
73
|
+
.option('--ts-only', 'Run only TypeScript integration tests')
|
|
74
|
+
.option('--watch', 'Run TypeScript tests in watch mode')
|
|
75
|
+
.option('--filter <pattern>', 'Filter Move tests by name pattern')
|
|
76
|
+
.action((options) => testCommand(options));
|
|
77
|
+
|
|
78
|
+
program
|
|
79
|
+
.command('test:move')
|
|
80
|
+
.description('Run Move unit tests')
|
|
81
|
+
.option('--filter <pattern>', 'Filter tests by name pattern')
|
|
82
|
+
.option('--ignore-warnings', 'Ignore compilation warnings')
|
|
83
|
+
.action((options) => testMoveCommand(options));
|
|
84
|
+
|
|
85
|
+
program
|
|
86
|
+
.command('test:ts')
|
|
87
|
+
.description('Run TypeScript integration tests')
|
|
88
|
+
.option('--watch', 'Run tests in watch mode')
|
|
89
|
+
.action((options) => testCommand({ tsOnly: true, watch: options.watch }));
|
|
72
90
|
|
|
73
91
|
// Fork commands
|
|
74
92
|
const fork = program
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { loadUserConfig } from "../core/config.js";
|
|
5
|
+
|
|
6
|
+
interface TestMoveOptions {
|
|
7
|
+
filter?: string;
|
|
8
|
+
ignoreWarnings?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default async function testMoveCommand(options: TestMoveOptions = {}) {
|
|
12
|
+
try {
|
|
13
|
+
const userConfig = await loadUserConfig();
|
|
14
|
+
const moveDir = path.resolve(process.cwd(), userConfig.moveDir || "./move");
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(moveDir)) {
|
|
17
|
+
console.error(`Move directory not found: ${moveDir}`);
|
|
18
|
+
console.error(` Update movehat.config.ts -> moveDir`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.log("Running Move unit tests...\n");
|
|
23
|
+
|
|
24
|
+
const args = ["move", "test", "--package-dir", moveDir];
|
|
25
|
+
|
|
26
|
+
// Add filter if provided
|
|
27
|
+
if (options.filter) {
|
|
28
|
+
args.push("--filter", options.filter);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Add ignore-warnings flag if provided
|
|
32
|
+
if (options.ignoreWarnings) {
|
|
33
|
+
args.push("--ignore-compile-warnings");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Spawn movement CLI
|
|
37
|
+
const child = spawn("movement", args, {
|
|
38
|
+
stdio: "inherit",
|
|
39
|
+
cwd: process.cwd(),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
child.on("exit", (code) => {
|
|
43
|
+
if (code === 0) {
|
|
44
|
+
console.log("\n✓ Move tests passed");
|
|
45
|
+
} else {
|
|
46
|
+
console.error("\n✗ Move tests failed");
|
|
47
|
+
}
|
|
48
|
+
process.exit(code || 0);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
child.on("error", (error) => {
|
|
52
|
+
console.error(`Failed to run Move tests: ${error.message}`);
|
|
53
|
+
console.error(" Make sure Movement CLI is installed");
|
|
54
|
+
console.error(" Run: movement --version");
|
|
55
|
+
process.exit(1);
|
|
56
|
+
});
|
|
57
|
+
} catch (err: any) {
|
|
58
|
+
console.error("Move tests failed:", err.message ?? err);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
}
|
package/src/commands/test.ts
CHANGED
|
@@ -1,42 +1,140 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
|
+
import { loadUserConfig } from "../core/config.js";
|
|
5
|
+
import path from "path";
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
interface TestOptions {
|
|
8
|
+
moveOnly?: boolean;
|
|
9
|
+
tsOnly?: boolean;
|
|
10
|
+
watch?: boolean;
|
|
11
|
+
filter?: string;
|
|
12
|
+
}
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
export default async function testCommand(options: TestOptions = {}) {
|
|
15
|
+
// Handle move-only flag
|
|
16
|
+
if (options.moveOnly) {
|
|
17
|
+
return runMoveTestsSync(options.filter);
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
// Handle ts-only flag (current behavior)
|
|
21
|
+
if (options.tsOnly) {
|
|
22
|
+
return runTypeScriptTests(options.watch);
|
|
23
|
+
}
|
|
15
24
|
|
|
16
|
-
//
|
|
17
|
-
|
|
25
|
+
// Default: Run both Move and TypeScript tests
|
|
26
|
+
console.log("Running all tests...\n");
|
|
27
|
+
console.log("=" + "=".repeat(60) + "\n");
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
// First run Move tests (fail fast)
|
|
30
|
+
try {
|
|
31
|
+
await runMoveTestsSync();
|
|
32
|
+
console.log("\n" + "=" + "=".repeat(60) + "\n");
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("\n✗ Move tests failed");
|
|
35
|
+
console.log("\n" + "=" + "=".repeat(60));
|
|
22
36
|
process.exit(1);
|
|
23
37
|
}
|
|
24
38
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
// Then run TypeScript tests
|
|
40
|
+
return runTypeScriptTests(false);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function runMoveTestsSync(filter?: string): Promise<void> {
|
|
44
|
+
return new Promise(async (resolve, reject) => {
|
|
45
|
+
console.log("1. Move Unit Tests");
|
|
46
|
+
console.log("-" + "-".repeat(60) + "\n");
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const userConfig = await loadUserConfig();
|
|
50
|
+
const moveDir = path.resolve(process.cwd(), userConfig.moveDir || "./move");
|
|
51
|
+
|
|
52
|
+
if (!existsSync(moveDir)) {
|
|
53
|
+
console.log("⊘ No Move directory found (./move not found)");
|
|
54
|
+
console.log(" Skipping Move tests...\n");
|
|
55
|
+
resolve();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const args = ["move", "test", "--package-dir", moveDir];
|
|
60
|
+
|
|
61
|
+
if (filter) {
|
|
62
|
+
args.push("--filter", filter);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const child = spawn("movement", args, {
|
|
66
|
+
stdio: "inherit",
|
|
67
|
+
cwd: process.cwd(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
child.on("exit", (code) => {
|
|
71
|
+
if (code === 0) {
|
|
72
|
+
console.log("\n✓ Move tests passed");
|
|
73
|
+
resolve();
|
|
74
|
+
} else {
|
|
75
|
+
reject(new Error("Move tests failed"));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
33
78
|
|
|
34
|
-
|
|
35
|
-
|
|
79
|
+
child.on("error", (error) => {
|
|
80
|
+
console.error(`Failed to run Move tests: ${error.message}`);
|
|
81
|
+
console.error(" Make sure Movement CLI is installed");
|
|
82
|
+
reject(error);
|
|
83
|
+
});
|
|
84
|
+
} catch (error) {
|
|
85
|
+
reject(error);
|
|
86
|
+
}
|
|
36
87
|
});
|
|
88
|
+
}
|
|
37
89
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
90
|
+
function runTypeScriptTests(watch: boolean = false): Promise<void> {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
console.log("2. TypeScript Integration Tests");
|
|
93
|
+
console.log("-" + "-".repeat(60) + "\n");
|
|
94
|
+
|
|
95
|
+
const testDir = join(process.cwd(), "tests");
|
|
96
|
+
|
|
97
|
+
if (!existsSync(testDir)) {
|
|
98
|
+
console.log("⊘ No TypeScript tests found (tests directory not found)");
|
|
99
|
+
console.log(" Skipping TypeScript tests...\n");
|
|
100
|
+
resolve();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const mochaPath = join(process.cwd(), "node_modules", ".bin", "mocha");
|
|
105
|
+
|
|
106
|
+
if (!existsSync(mochaPath)) {
|
|
107
|
+
console.error("✗ Mocha not found in project dependencies.");
|
|
108
|
+
console.error(" Install it with: npm install --save-dev mocha");
|
|
109
|
+
reject(new Error("Mocha not found"));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const args = watch ? ["--watch"] : [];
|
|
114
|
+
|
|
115
|
+
const child = spawn(mochaPath, args, {
|
|
116
|
+
stdio: "inherit",
|
|
117
|
+
env: {
|
|
118
|
+
...process.env,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
child.on("exit", (code) => {
|
|
123
|
+
if (code === 0) {
|
|
124
|
+
console.log("\n✓ TypeScript tests passed");
|
|
125
|
+
console.log("\n" + "=" + "=".repeat(60));
|
|
126
|
+
console.log("\n✓ All tests passed!\n");
|
|
127
|
+
resolve();
|
|
128
|
+
} else {
|
|
129
|
+
console.error("\n✗ TypeScript tests failed");
|
|
130
|
+
console.log("\n" + "=" + "=".repeat(60));
|
|
131
|
+
process.exit(code || 1);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
child.on("error", (error) => {
|
|
136
|
+
console.error(`Failed to run TypeScript tests: ${error.message}`);
|
|
137
|
+
reject(error);
|
|
138
|
+
});
|
|
41
139
|
});
|
|
42
|
-
}
|
|
140
|
+
}
|
package/src/core/config.ts
CHANGED
|
@@ -78,6 +78,7 @@ export async function resolveNetworkConfig(
|
|
|
78
78
|
networkName?: string
|
|
79
79
|
): Promise<MovehatConfig> {
|
|
80
80
|
// Determine which network to use
|
|
81
|
+
// Default to "testnet" for testing with simulation
|
|
81
82
|
const selectedNetwork =
|
|
82
83
|
networkName ||
|
|
83
84
|
process.env.MH_CLI_NETWORK ||
|
|
@@ -86,11 +87,31 @@ export async function resolveNetworkConfig(
|
|
|
86
87
|
"testnet";
|
|
87
88
|
|
|
88
89
|
// Check if network exists in config
|
|
89
|
-
|
|
90
|
+
let networkConfig = userConfig.networks[selectedNetwork];
|
|
91
|
+
|
|
92
|
+
// Special case: Auto-generate config for testnet (public test network)
|
|
93
|
+
// This provides a better dev experience - no local setup required
|
|
94
|
+
if (!networkConfig && selectedNetwork === "testnet") {
|
|
95
|
+
networkConfig = {
|
|
96
|
+
url: "https://testnet.movementnetwork.xyz/v1",
|
|
97
|
+
chainId: "testnet",
|
|
98
|
+
};
|
|
99
|
+
console.log(`testnet not found in config - using default Movement testnet configuration`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Special case: Auto-generate config for local fork server
|
|
103
|
+
if (!networkConfig && selectedNetwork === "local") {
|
|
104
|
+
networkConfig = {
|
|
105
|
+
url: "http://localhost:8080/v1",
|
|
106
|
+
chainId: "local",
|
|
107
|
+
};
|
|
108
|
+
console.log(`Local network not found in config - using default fork server configuration`);
|
|
109
|
+
}
|
|
110
|
+
|
|
90
111
|
if (!networkConfig) {
|
|
91
112
|
const availableNetworks = Object.keys(userConfig.networks).join(", ");
|
|
92
113
|
throw new Error(
|
|
93
|
-
`Network '${selectedNetwork}' not found in configuration.\nAvailable networks: ${availableNetworks}`
|
|
114
|
+
`Network '${selectedNetwork}' not found in configuration.\nAvailable networks: ${availableNetworks}, testnet (auto-generated), local (auto-generated)`
|
|
94
115
|
);
|
|
95
116
|
}
|
|
96
117
|
|
|
@@ -117,15 +138,38 @@ export async function resolveNetworkConfig(
|
|
|
117
138
|
accounts = [process.env.PRIVATE_KEY];
|
|
118
139
|
}
|
|
119
140
|
|
|
120
|
-
// 4. Validate we have at least one account
|
|
141
|
+
// 4. Validate we have at least one account (unless using testnet/local)
|
|
121
142
|
if (accounts.length === 0 || !accounts[0]) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
143
|
+
// Special case: Auto-generate test accounts for testing networks
|
|
144
|
+
// testnet = public Movement test network (recommended)
|
|
145
|
+
// local = local fork server
|
|
146
|
+
if (selectedNetwork === "testnet" || selectedNetwork === "local") {
|
|
147
|
+
// Security: Using a deterministic test account (like Hardhat's default accounts)
|
|
148
|
+
// This is SAFE because:
|
|
149
|
+
// 1. Only used for testnet/local (never mainnet - that throws error below)
|
|
150
|
+
// 2. Perfect for transaction simulation (no real funds)
|
|
151
|
+
// 3. Deterministic = consistent test results
|
|
152
|
+
const testPrivateKey = "0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
153
|
+
accounts = [testPrivateKey];
|
|
154
|
+
console.log(`\n[TESTNET] Using auto-generated test account (safe for testing only)`);
|
|
155
|
+
console.log(`[TESTNET] For mainnet, set PRIVATE_KEY in .env\n`);
|
|
156
|
+
} else {
|
|
157
|
+
// For any other network (especially mainnet), REQUIRE explicit configuration
|
|
158
|
+
// This prevents accidentally using the test key on production networks
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Network '${selectedNetwork}' has no accounts configured.\n` +
|
|
161
|
+
`\n` +
|
|
162
|
+
`SECURITY: This network requires explicit account configuration.\n` +
|
|
163
|
+
`\n` +
|
|
164
|
+
`Options:\n` +
|
|
165
|
+
` 1. Set PRIVATE_KEY in your .env file (recommended for ${selectedNetwork})\n` +
|
|
166
|
+
` 2. Add 'accounts: ["0x..."]' globally in movehat.config.ts\n` +
|
|
167
|
+
` 3. Add 'accounts: ["0x..."]' to the '${selectedNetwork}' network config\n` +
|
|
168
|
+
`\n` +
|
|
169
|
+
`For testing without configuration, use:\n` +
|
|
170
|
+
` movehat <command> --network testnet (auto-generates safe test accounts)`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
129
173
|
}
|
|
130
174
|
|
|
131
175
|
// Merge named addresses (network-specific overrides global)
|
package/src/templates/README.md
CHANGED
|
@@ -52,6 +52,26 @@ npm run compile
|
|
|
52
52
|
npm test
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
**Two types of tests available:**
|
|
56
|
+
|
|
57
|
+
1. **Move Unit Tests** (`tests/Counter.move` lines 50-63)
|
|
58
|
+
- Written in Move with `#[test]` annotations
|
|
59
|
+
- Test internal logic and business rules
|
|
60
|
+
- Ultra-fast execution (milliseconds)
|
|
61
|
+
- Run with: `npm run test:move`
|
|
62
|
+
|
|
63
|
+
2. **TypeScript Integration Tests** (`tests/Counter.test.ts`)
|
|
64
|
+
- Written in TypeScript using Transaction Simulation
|
|
65
|
+
- Test end-to-end flows and SDK integration
|
|
66
|
+
- No blockchain or gas costs required
|
|
67
|
+
- Run with: `npm run test:ts`
|
|
68
|
+
|
|
69
|
+
**Commands:**
|
|
70
|
+
- `npm test` - Runs both Move + TypeScript tests
|
|
71
|
+
- `npm run test:move` - Only Move unit tests (fast)
|
|
72
|
+
- `npm run test:ts` - Only TypeScript integration tests
|
|
73
|
+
- `npm run test:watch` - TypeScript tests in watch mode
|
|
74
|
+
|
|
55
75
|
### 5. Deploy (optional)
|
|
56
76
|
|
|
57
77
|
```bash
|
|
@@ -3,18 +3,28 @@ dotenv.config();
|
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
// Default network to use when no --network flag is provided
|
|
6
|
+
// "testnet" = Movement testnet (public, auto-generates test accounts)
|
|
7
|
+
// "mainnet" = Movement mainnet (requires PRIVATE_KEY in .env)
|
|
8
|
+
// "local" = Fork server running on localhost:8080
|
|
6
9
|
defaultNetwork: "testnet",
|
|
7
10
|
|
|
8
11
|
// Network configurations
|
|
9
12
|
networks: {
|
|
13
|
+
// Movement Testnet - Public test network (recommended for development)
|
|
14
|
+
// Auto-generates test accounts - no local setup required
|
|
15
|
+
// Perfect for running tests with transaction simulation
|
|
10
16
|
testnet: {
|
|
11
17
|
url: process.env.MOVEMENT_RPC_URL || "https://testnet.movementnetwork.xyz/v1",
|
|
12
18
|
chainId: "testnet",
|
|
13
19
|
},
|
|
20
|
+
// Movement Mainnet - Production network
|
|
21
|
+
// REQUIRES PRIVATE_KEY in .env - uses real MOVE tokens
|
|
14
22
|
mainnet: {
|
|
15
23
|
url: "https://mainnet.movementnetwork.xyz/v1",
|
|
16
24
|
chainId: "mainnet",
|
|
17
25
|
},
|
|
26
|
+
// Local fork server (requires: movehat fork serve)
|
|
27
|
+
// Useful for testing against a snapshot of real network state
|
|
18
28
|
local: {
|
|
19
29
|
url: "http://localhost:8080/v1",
|
|
20
30
|
chainId: "local",
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "
|
|
7
|
-
"test:
|
|
6
|
+
"test": "movehat test",
|
|
7
|
+
"test:move": "movehat test:move",
|
|
8
|
+
"test:ts": "movehat test:ts",
|
|
9
|
+
"test:watch": "movehat test:ts --watch",
|
|
8
10
|
"deploy": "movehat run scripts/deploy-counter.ts"
|
|
9
11
|
},
|
|
10
12
|
"dependencies": {
|
|
11
|
-
"movehat": "
|
|
13
|
+
"movehat": "latest",
|
|
12
14
|
"@aptos-labs/ts-sdk": "^5.1.5",
|
|
13
15
|
"dotenv": "^17.2.3"
|
|
14
16
|
},
|
|
@@ -1,75 +1,72 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-nocheck - This is a template file, dependencies are installed in user projects
|
|
2
|
+
import { describe, it, before } from "mocha";
|
|
2
3
|
import { expect } from "chai";
|
|
3
4
|
import { getMovehat, type MovehatRuntime } from "movehat";
|
|
4
|
-
import type { MoveContract } from "movehat/helpers";
|
|
5
|
-
import { assertTransactionSuccess, snapshot } from "movehat/helpers";
|
|
6
5
|
|
|
7
6
|
describe("Counter Contract", () => {
|
|
8
7
|
let mh: MovehatRuntime;
|
|
9
|
-
let
|
|
8
|
+
let contractAddress: string;
|
|
10
9
|
|
|
11
10
|
before(async function () {
|
|
12
11
|
this.timeout(30000);
|
|
13
12
|
|
|
14
13
|
// Initialize Movehat Runtime Environment
|
|
14
|
+
// Uses testnet by default - no local setup required
|
|
15
15
|
mh = await getMovehat();
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
console.log(` Account: ${mh.account.accountAddress.toString()}\n`);
|
|
17
|
+
contractAddress = mh.account.accountAddress.toString();
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
mh.account.accountAddress.toString(),
|
|
23
|
-
"counter"
|
|
24
|
-
);
|
|
19
|
+
console.log(`\nTesting on ${mh.network.name}`);
|
|
20
|
+
console.log(`Account: ${contractAddress}\n`);
|
|
25
21
|
});
|
|
26
22
|
|
|
27
23
|
describe("Counter functionality", () => {
|
|
28
|
-
it("should initialize counter", async function () {
|
|
24
|
+
it("should initialize counter using simulation", async function () {
|
|
29
25
|
this.timeout(30000);
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
// Build transaction
|
|
28
|
+
const transaction = await mh.aptos.transaction.build.simple({
|
|
29
|
+
sender: mh.account.accountAddress,
|
|
30
|
+
data: {
|
|
31
|
+
function: `${contractAddress}::counter::init`,
|
|
32
|
+
functionArguments: []
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Simulate transaction (no gas cost, instant)
|
|
37
|
+
const [simulation] = await mh.aptos.transaction.simulate.simple({
|
|
38
|
+
signerPublicKey: mh.account.publicKey,
|
|
39
|
+
transaction
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Verify simulation succeeded
|
|
43
|
+
expect(simulation.success).to.be.true;
|
|
44
|
+
console.log(`Counter init simulated successfully`);
|
|
45
|
+
console.log(`Gas used: ${simulation.gas_used}`);
|
|
40
46
|
});
|
|
41
47
|
|
|
42
|
-
it("should increment counter", async function () {
|
|
48
|
+
it("should increment counter using simulation", async function () {
|
|
43
49
|
this.timeout(30000);
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
// Build increment transaction
|
|
52
|
+
const transaction = await mh.aptos.transaction.build.simple({
|
|
53
|
+
sender: mh.account.accountAddress,
|
|
54
|
+
data: {
|
|
55
|
+
function: `${contractAddress}::counter::increment`,
|
|
56
|
+
functionArguments: []
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Simulate transaction
|
|
61
|
+
const [simulation] = await mh.aptos.transaction.simulate.simple({
|
|
62
|
+
signerPublicKey: mh.account.publicKey,
|
|
63
|
+
transaction
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Verify simulation succeeded
|
|
67
|
+
expect(simulation.success).to.be.true;
|
|
68
|
+
console.log(`Counter increment simulated successfully`);
|
|
69
|
+
console.log(`Gas used: ${simulation.gas_used}`);
|
|
58
70
|
});
|
|
59
71
|
});
|
|
60
|
-
|
|
61
|
-
// Optional: Create a snapshot after tests for debugging
|
|
62
|
-
// Uncomment to enable
|
|
63
|
-
/*
|
|
64
|
-
after(async function () {
|
|
65
|
-
this.timeout(30000);
|
|
66
|
-
|
|
67
|
-
const snapshotPath = await snapshot({
|
|
68
|
-
name: 'counter-test-final'
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
console.log(`\n📸 Snapshot created: ${snapshotPath}`);
|
|
72
|
-
console.log(` Use 'aptos move sim view-resource --session ${snapshotPath}' to inspect state\n`);
|
|
73
|
-
});
|
|
74
|
-
*/
|
|
75
72
|
});
|