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 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 { setupTestEnvironment, getContract, assertTransactionSuccess } from "movehat/helpers";
109
- import type { TestEnvironment, MoveContract } from "movehat/helpers";
110
+ import { getMovehat, type MovehatRuntime } from "movehat";
110
111
 
111
112
  describe("Counter Contract", () => {
112
- let env: TestEnvironment;
113
- let counter: MoveContract;
113
+ let mh: MovehatRuntime;
114
+ let contractAddress: string;
114
115
 
115
116
  before(async function () {
116
117
  this.timeout(30000);
117
- env = await setupTestEnvironment();
118
- counter = getContract(
119
- env.aptos,
120
- env.account.accountAddress.toString(),
121
- "counter"
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 increment counter", async function () {
125
+ it("should initialize counter using simulation", async function () {
126
126
  this.timeout(30000);
127
-
128
- const tx = await counter.call(env.account, "increment", []);
129
- assertTransactionSuccess(tx);
130
-
131
- const value = await counter.view<number>("get", [
132
- env.account.accountAddress.toString()
133
- ]);
134
-
135
- expect(value).to.be.greaterThan(0);
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 TypeScript tests with Mocha')
63
- .action(testCommand);
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":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface TestMoveOptions {
2
+ filter?: string;
3
+ ignoreWarnings?: boolean;
4
+ }
5
+ export default function testMoveCommand(options?: TestMoveOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=test-move.d.ts.map
@@ -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"}
@@ -1,2 +1,9 @@
1
- export default function testCommand(): Promise<void>;
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":"AAIA,wBAA8B,WAAW,kBAqCxC"}
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"}
@@ -1,35 +1,116 @@
1
1
  import { spawn } from "child_process";
2
2
  import { join } from "path";
3
3
  import { existsSync } from "fs";
4
- export default async function testCommand() {
5
- const testDir = join(process.cwd(), "tests");
6
- if (!existsSync(testDir)) {
7
- console.error("❌ No tests directory found.");
8
- console.error(" Create a 'tests' directory with your TypeScript test files.");
9
- process.exit(1);
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
- console.log("🧪 Running TypeScript tests with Mocha...\n");
12
- // Find mocha from project's node_modules
13
- const mochaPath = join(process.cwd(), "node_modules", ".bin", "mocha");
14
- if (!existsSync(mochaPath)) {
15
- console.error("❌ Mocha not found in project dependencies.");
16
- console.error(" Install it with: npm install --save-dev mocha");
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
- // Run mocha with TypeScript support
20
- const child = spawn(mochaPath, [], {
21
- stdio: "inherit",
22
- env: {
23
- ...process.env,
24
- // Inherit network if set
25
- },
26
- });
27
- child.on("exit", (code) => {
28
- process.exit(code || 0);
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
- child.on("error", (error) => {
31
- console.error(`❌ Failed to run tests: ${error.message}`);
32
- process.exit(1);
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;AAEhC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IAE7C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAE3D,yCAAyC;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAEvE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,oCAAoC;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE;QACjC,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE;YACH,GAAG,OAAO,CAAC,GAAG;YACd,yBAAyB;SAC1B;KACF,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACxB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1B,OAAO,CAAC,KAAK,CAAC,0BAA0B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
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;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,IAAI,MAAM,MAAM,CAAC;AASxB,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CAAC,UAAuB,EAAE;IACjE,wBAAwB;IACxB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,8CAA8C;IAC9C,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IAEzC,mCAAmC;IACnC,IAAI,CAAC;QACH,MAAM,gBAAgB,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,4BAA4B;IAC5B,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAe;IACvC,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC;YAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC;YAE5E,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;gBAC5D,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;gBAC3C,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;YAExD,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAChC,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE;gBACpC,KAAK,EAAE,SAAS;gBAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;aACnB,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;oBACrC,OAAO,EAAE,CAAC;gBACZ,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBACzC,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC1B,OAAO,CAAC,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC5D,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;gBACxD,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAiB,KAAK;IAChD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QAE7C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YACvE,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;YACjD,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAEvE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC5D,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;YAClE,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;YACrC,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE;YACnC,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;aACf;SACF,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,6BAA6B,CAAC,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;gBACvC,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;gBAC7C,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,CAAC,KAAK,CAAC,mCAAmC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAClE,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -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,CAwExB"}
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"}
@@ -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
- const networkConfig = userConfig.networks[selectedNetwork];
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
- throw new Error(`Network '${selectedNetwork}' has no accounts configured.\n` +
97
- `Options:\n` +
98
- ` 1. Set PRIVATE_KEY in your .env file (recommended)\n` +
99
- ` 2. Add 'accounts: ["0x..."]' globally in movehat.config.ts\n` +
100
- ` 3. Add 'accounts: ["0x..."]' to the '${selectedNetwork}' network config`);
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 = {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -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": "mocha",
7
- "test:watch": "mocha --watch",
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": "^0.0.7-alpha.0",
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
- import { describe, it, before, after } from "mocha";
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 counter: MoveContract;
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
- console.log(`\n✅ Testing on ${mh.network.name}`);
18
- console.log(` Account: ${mh.account.accountAddress.toString()}\n`);
17
+ contractAddress = mh.account.accountAddress.toString();
19
18
 
20
- // Get counter contract instance
21
- counter = mh.getContract(
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
- const txResult = await counter.call(mh.account, "init", []);
32
- assertTransactionSuccess(txResult);
33
-
34
- const value = await counter.view<number>("get", [
35
- mh.account.accountAddress.toString()
36
- ]);
37
-
38
- expect(value).to.equal(0);
39
- console.log(` ✓ Counter initialized with value: ${value}`);
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
- const initialValue = await counter.view<number>("get", [
46
- mh.account.accountAddress.toString()
47
- ]);
48
-
49
- const txResult = await counter.call(mh.account, "increment", []);
50
- assertTransactionSuccess(txResult);
51
-
52
- const newValue = await counter.view<number>("get", [
53
- mh.account.accountAddress.toString()
54
- ]);
55
-
56
- expect(newValue).to.equal(initialValue + 1);
57
- console.log(` ✓ Counter incremented: ${initialValue} → ${newValue}`);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "movehat",
3
- "version": "0.0.7-alpha.0",
3
+ "version": "0.0.9-alpha.0",
4
4
  "type": "module",
5
5
  "description": "Hardhat-like development framework for Movement L1 and Aptos Move smart contracts",
6
6
  "bin": {
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 TypeScript tests with Mocha')
71
- .action(testCommand);
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
+ }
@@ -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
- export default async function testCommand() {
6
- const testDir = join(process.cwd(), "tests");
7
+ interface TestOptions {
8
+ moveOnly?: boolean;
9
+ tsOnly?: boolean;
10
+ watch?: boolean;
11
+ filter?: string;
12
+ }
7
13
 
8
- if (!existsSync(testDir)) {
9
- console.error("❌ No tests directory found.");
10
- console.error(" Create a 'tests' directory with your TypeScript test files.");
11
- process.exit(1);
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
- console.log("🧪 Running TypeScript tests with Mocha...\n");
20
+ // Handle ts-only flag (current behavior)
21
+ if (options.tsOnly) {
22
+ return runTypeScriptTests(options.watch);
23
+ }
15
24
 
16
- // Find mocha from project's node_modules
17
- const mochaPath = join(process.cwd(), "node_modules", ".bin", "mocha");
25
+ // Default: Run both Move and TypeScript tests
26
+ console.log("Running all tests...\n");
27
+ console.log("=" + "=".repeat(60) + "\n");
18
28
 
19
- if (!existsSync(mochaPath)) {
20
- console.error("❌ Mocha not found in project dependencies.");
21
- console.error(" Install it with: npm install --save-dev mocha");
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
- // Run mocha with TypeScript support
26
- const child = spawn(mochaPath, [], {
27
- stdio: "inherit",
28
- env: {
29
- ...process.env,
30
- // Inherit network if set
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
- child.on("exit", (code) => {
35
- process.exit(code || 0);
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
- child.on("error", (error) => {
39
- console.error(`❌ Failed to run tests: ${error.message}`);
40
- process.exit(1);
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
+ }
@@ -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
- const networkConfig = userConfig.networks[selectedNetwork];
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
- throw new Error(
123
- `Network '${selectedNetwork}' has no accounts configured.\n` +
124
- `Options:\n` +
125
- ` 1. Set PRIVATE_KEY in your .env file (recommended)\n` +
126
- ` 2. Add 'accounts: ["0x..."]' globally in movehat.config.ts\n` +
127
- ` 3. Add 'accounts: ["0x..."]' to the '${selectedNetwork}' network config`
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)
@@ -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": "mocha",
7
- "test:watch": "mocha --watch",
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": "^0.0.7-alpha.0",
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
- import { describe, it, before, after } from "mocha";
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 counter: MoveContract;
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
- console.log(`\n✅ Testing on ${mh.network.name}`);
18
- console.log(` Account: ${mh.account.accountAddress.toString()}\n`);
17
+ contractAddress = mh.account.accountAddress.toString();
19
18
 
20
- // Get counter contract instance
21
- counter = mh.getContract(
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
- const txResult = await counter.call(mh.account, "init", []);
32
- assertTransactionSuccess(txResult);
33
-
34
- const value = await counter.view<number>("get", [
35
- mh.account.accountAddress.toString()
36
- ]);
37
-
38
- expect(value).to.equal(0);
39
- console.log(` ✓ Counter initialized with value: ${value}`);
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
- const initialValue = await counter.view<number>("get", [
46
- mh.account.accountAddress.toString()
47
- ]);
48
-
49
- const txResult = await counter.call(mh.account, "increment", []);
50
- assertTransactionSuccess(txResult);
51
-
52
- const newValue = await counter.view<number>("get", [
53
- mh.account.accountAddress.toString()
54
- ]);
55
-
56
- expect(newValue).to.equal(initialValue + 1);
57
- console.log(` ✓ Counter incremented: ${initialValue} → ${newValue}`);
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
  });