Skip to content

Commit bfaa04e

Browse files
authored
rework init (#457)
* rework init * readd config * change default testcases * add schema to config * update docs
1 parent 626e860 commit bfaa04e

File tree

11 files changed

+270
-66
lines changed

11 files changed

+270
-66
lines changed

.changeset/khaki-cycles-unite.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@moonwall/types": minor
3+
"@moonwall/cli": minor
4+
"@moonwall/docs": minor
5+
---
6+
7+
Updated `init` command

.github/workflows/main.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ jobs:
4949
cache: "pnpm"
5050
- run: pnpm install
5151
- run: pnpm run fmt
52+
53+
test_init:
54+
runs-on: ubuntu-latest
55+
needs: ["build"]
56+
steps:
57+
- uses: actions/checkout@v4
58+
- uses: pnpm/action-setup@v4
59+
with:
60+
version: 9.1.4
61+
- uses: actions/setup-node@v4
62+
with:
63+
node-version: 23
64+
cache: "pnpm"
65+
- name: Build like before
66+
run: |
67+
pnpm install
68+
pnpm run build
69+
- name: Initialize config
70+
run: |
71+
cd test
72+
rm moonwall.config.json
73+
pnpm moonwall init --acceptAllDefaults
74+
- name: Run test
75+
run: |
76+
cd test
77+
pnpm moonwall test default_env
5278
5379
test_basic:
5480
runs-on: ubuntu-latest

docs/guide/cmd/init.md

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,77 @@
11
# Init
22

3-
The moonwall `init` command walks you through a step-by-step process to setting up your `moonwall.config.json` file.
3+
The `init` command guides you through a step-by-step process to create a configuration file for Moonwall. This command will set up a new `moonwall.config.json` file in your current directory—provided one does not already exist.
44

5-
The command takes no parameters but you'll be asked for the following to complete the setup of your `moonwall.config.json` file. Press `enter` at each step to accept the default parameters or enter your own at each step. These parameters and their default values are listed below:
5+
When you run:
66

7-
- Label: *moonwall_config*
8-
- Global timeout value: *30000*
9-
- Environment Name: *default_env*
10-
- Path for where tests for this environment are kept: *tests/*
11-
- Network Foundation: *dev*
12-
- Would you like to generate this config? (no to restart from beginning) (Y/n) *Y*
7+
`pnpm moonwall init`
138

14-
For more details about configuring your `Moonwall.config` see the [Quick Start Guide](/guide/test/quick-start).
9+
::: tip
10+
You can provide the option `--acceptAllDefaults` to YOLO the defaults and save a config file immediately.
11+
:::
1512

16-
![Moonwall init terminal screenshot](/init.png)
13+
you will be prompted to enter a few key configuration values. Press `Enter` at each prompt to accept the default value or type your own. The prompts include:
14+
15+
- **Label:** The name for your config file.
16+
_Default: `moonwall_config`_
17+
18+
- **Global Timeout:** The default timeout for tests (in milliseconds).
19+
_Default: `30000`_
20+
21+
- **Environment Name:** The name of the Moonwall environment you want to create first (you can always make as many new environments as you like).
22+
_Default: `default_env`_
23+
24+
- **Test Directory:** The path where tests for this environment are stored.
25+
_Default: `tests/default/`_
26+
27+
::: info
28+
By default, the `foundation` is set to `dev` but you can change it to `chopsticks`, `zombie`, or `read_only` as required.
29+
:::
30+
31+
After enter and confirming these values, the following will happen:
32+
33+
- Creates the directories `scripts`, `tests`, and `tmp` (if they don’t already exist).
34+
- Generates a new `moonwall.config.json` file with your specified settings.
35+
- Writes a sample test file into your test directory to help you get started.
36+
37+
## Generated Configuration Example
38+
39+
Below is an example of the generated `moonwall.config.json`:
40+
41+
```json
42+
{
43+
"$schema": "https://raw.githubusercontent.com/Moonsong-Labs/moonwall/main/packages/types/config_schema.json",
44+
"label": "moonwall_config",
45+
"defaultTestTimeout": 30000,
46+
"environments": [
47+
{
48+
"name": "default_env",
49+
"testFileDir": ["tests/default/"],
50+
"multiThreads": false,
51+
"foundation": {
52+
"type": "dev",
53+
"launchSpec": [
54+
{
55+
"name": "moonbeam",
56+
"useDocker": true,
57+
"newRpcBehaviour": true,
58+
"binPath": "moonbeamfoundation/moonbeam"
59+
}
60+
]
61+
}
62+
}
63+
]
64+
}
65+
```
66+
67+
After initialization, a sample test file is created in the specified test directory so you can immediately begin writing tests for your local dev environment.
68+
69+
The tests should run successfully with default settings, as it will use a moonbeam docker image to spin up a local dev environment. You can modify this environment to whichever substrate node binary location or docker as you like.
70+
71+
::: info
72+
If a `moonwall.config.json` file already exists, the init command will abort to prevent overwriting your configuration. Remove or rename the existing file if you wish to run the init process again.
73+
:::
74+
75+
For more details about configuration options and further customization, please see the [Quick Start Guide](/guide/test/quick-start).
76+
77+
![Moonwall init terminal screenshot](/init.png)

docs/public/init.png

-80.9 KB
Loading

packages/cli/src/cmds/entrypoint.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,19 @@ yargs(hideBin(process.argv))
5252
default: "moonwall.config.json",
5353
},
5454
})
55-
.command("init", "Run tests for a given Environment", async () => {
56-
await generateConfig();
57-
})
55+
.command(
56+
"init",
57+
"Run tests for a given Environment",
58+
(yargs) =>
59+
yargs.option("acceptAllDefaults", {
60+
type: "boolean",
61+
description: "Accept all defaults",
62+
alias: "A",
63+
}),
64+
async (argv) => {
65+
await generateConfig(argv);
66+
}
67+
)
5868
.command<fetchArtifactArgs>(
5969
"download <bin> [ver] [path]",
6070
"Download x86 artifact from GitHub",

packages/cli/src/cmds/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ async function mainMenu(config?: MoonwallConfig) {
160160

161161
switch (menuChoice) {
162162
case "init":
163-
await generateConfig();
163+
await generateConfig({});
164164
await createFolders();
165165
return false;
166166
case "run": {
Lines changed: 140 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,91 @@
11
import type { FoundationType, MoonwallConfig } from "@moonwall/types";
22
import fs from "node:fs/promises";
3-
import { input, number, confirm } from "@inquirer/prompts";
3+
import { input, number, confirm, select } from "@inquirer/prompts";
44

55
export async function createFolders() {
66
await fs.mkdir("scripts").catch(() => "scripts folder already exists, skipping");
77
await fs.mkdir("tests").catch(() => "tests folder already exists, skipping");
88
await fs.mkdir("tmp").catch(() => "tmp folder already exists, skipping");
99
}
1010

11-
export async function generateConfig() {
12-
for (;;) {
13-
if (await fs.access("moonwall.config.json").catch(() => true)) {
14-
const label = await input({
15-
message: "Provide a label for the config file",
16-
default: "moonwall_config",
17-
});
18-
19-
const timeout = await number({
20-
message: "Provide a global timeout value",
21-
default: 30000,
22-
});
11+
export async function generateConfig(argv: { acceptAllDefaults?: boolean }) {
12+
interface ConfigAnswers {
13+
label: string;
14+
timeout: number;
15+
environmentName: string;
16+
foundation: FoundationType;
17+
useDocker?: boolean;
18+
testDir: string;
19+
}
2320

24-
const environmentName = await input({
25-
message: "Provide a name for this environment",
26-
default: "default_env",
27-
});
21+
let answers: ConfigAnswers;
2822

29-
const foundation = (await input({
30-
message: "What type of network foundation is this?",
31-
default: "dev",
32-
})) as FoundationType;
23+
try {
24+
await fs.access("moonwall.config.json");
25+
console.log("ℹ️ Config file already exists at this location. Quitting.");
26+
return;
27+
} catch (_) {
28+
// File does not exist — proceed with configuration
29+
}
3330

34-
const testDir = await input({
35-
message: "Provide the path for where tests for this environment are kept",
36-
default: "tests/",
37-
});
31+
if (argv.acceptAllDefaults) {
32+
answers = {
33+
label: "moonwall_config",
34+
timeout: 30000,
35+
environmentName: "default_env",
36+
foundation: "dev",
37+
testDir: "tests/default/",
38+
};
39+
} else {
40+
while (true) {
41+
answers = {
42+
label: await input({
43+
message: "Provide a label for the config file",
44+
default: "moonwall_config",
45+
}),
46+
timeout:
47+
(await number({
48+
message: "Provide a global timeout value",
49+
default: 30000,
50+
})) ?? 30000,
51+
environmentName: await input({
52+
message: "Provide a name for this environment",
53+
default: "default_env",
54+
}),
55+
foundation: "dev",
56+
testDir: await input({
57+
message: "Provide the path for where tests for this environment are kept",
58+
default: "tests/default/",
59+
}),
60+
};
3861

3962
const proceed = await confirm({
4063
message: "Would you like to generate this config? (no to restart from beginning)",
4164
});
4265

43-
if (proceed === false) {
44-
continue;
66+
if (proceed) {
67+
break;
4568
}
46-
47-
const JSONBlob = JSON.stringify(
48-
createConfig({
49-
label,
50-
timeout: timeout ?? 30000,
51-
environmentName,
52-
foundation,
53-
testDir,
54-
}),
55-
null,
56-
3
57-
);
58-
59-
await fs.writeFile("moonwall.config", textBlob + JSONBlob, "utf-8");
60-
process.env.MOON_CONFIG_PATH = "./moonwall.config";
61-
break;
69+
console.log("Restarting the configuration process...");
6270
}
63-
console.log("ℹ️ Config file already exists at this location. Quitting.");
64-
return;
6571
}
72+
73+
const config = createSampleConfig({
74+
label: answers.label,
75+
timeout: answers.timeout,
76+
environmentName: answers.environmentName,
77+
foundation: answers.foundation,
78+
testDir: answers.testDir,
79+
});
80+
81+
const JSONBlob = JSON.stringify(config, null, 3);
82+
await fs.writeFile("moonwall.config.json", JSONBlob, "utf-8");
83+
process.env.MOON_CONFIG_PATH = "./moonwall.config.json";
84+
await createSampleTest(answers.testDir);
85+
console.log("Test directory created at: ", answers.testDir);
86+
console.log(
87+
`You can now add tests to this directory and run them with 'pnpm moonwall test ${answers.environmentName}'`
88+
);
6689
console.log("Goodbye! 👋");
6790
}
6891

@@ -88,8 +111,76 @@ export function createConfig(options: {
88111
};
89112
}
90113

91-
const textBlob = `// This Moonwall Config file should be modified to include all types
92-
// of environments you wish to test against.
114+
export function createSampleConfig(options: {
115+
label: string;
116+
timeout: number;
117+
environmentName: string;
118+
foundation: FoundationType;
119+
testDir: string;
120+
}): MoonwallConfig {
121+
return {
122+
$schema:
123+
"https://raw.githubusercontent.com/Moonsong-Labs/moonwall/main/packages/types/config_schema.json",
124+
label: options.label,
125+
defaultTestTimeout: options.timeout,
126+
environments: [
127+
{
128+
name: options.environmentName,
129+
testFileDir: [options.testDir],
130+
multiThreads: false,
131+
foundation: {
132+
type: "dev",
133+
launchSpec: [
134+
{
135+
name: "moonbeam",
136+
useDocker: true,
137+
newRpcBehaviour: true,
138+
binPath: "moonbeamfoundation/moonbeam",
139+
},
140+
],
141+
},
142+
},
143+
],
144+
};
145+
}
146+
147+
async function createSampleTest(directory: string) {
148+
await fs.mkdir(directory, { recursive: true });
149+
await fs.writeFile(`${directory}/sample.test.ts`, sampleTest, "utf-8");
150+
}
151+
152+
const sampleTest = `import { describeSuite, expect } from "@moonwall/cli";
153+
154+
describeSuite({
155+
id: "B01",
156+
title: "Sample test suite for moonbeam network",
157+
foundationMethods: "dev",
158+
testCases: ({ context, it }) => {
159+
160+
const ALITH_ADDRESS = "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
161+
162+
it({
163+
id: "T01",
164+
title: "Test that API is connected correctly",
165+
test: async () => {
166+
const chainName = context.pjsApi.consts.system.version.specName.toString();
167+
const specVersion = context.pjsApi.consts.system.version.specVersion.toNumber();
168+
expect(chainName.length).toBeGreaterThan(0)
169+
expect(chainName).toBe("moonbase")
170+
expect(specVersion).toBeGreaterThan(0)
171+
},
172+
});
173+
174+
it({
175+
id: "T02",
176+
title: "Test that chain queries can be made",
177+
test: async () => {
178+
const balance = (await context.pjsApi.query.system.account(ALITH_ADDRESS)).data.free
179+
expect(balance.toBigInt()).toBeGreaterThan(0n)
180+
},
181+
});
182+
183+
},
184+
});
93185
94-
// For more information on how to configure Moonwall, please visit:
95-
// https://moonsong-labs.github.io/moonwall/config/intro.html\n`;
186+
`;

packages/cli/src/internal/commandParsers.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ export class LaunchCommandParser {
6262
this.cmd = launchSpec.binPath;
6363
this.args = launchSpec.options
6464
? [...launchSpec.options]
65-
: launchSpec.useDocker
66-
? []
67-
: fetchDefaultArgs(path.basename(launchSpec.binPath), additionalRepos);
65+
: fetchDefaultArgs(path.basename(launchSpec.binPath), additionalRepos);
6866
}
6967

7068
private overrideArg(newArg: string): void {

packages/cli/src/lib/repoDefinitions/moonbeam.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const repo: RepoSpec = {
1010
"--no-telemetry",
1111
"--reserved-only",
1212
"--rpc-cors=all",
13+
"--unsafe-rpc-external",
1314
"--unsafe-force-node-key-generation",
1415
"--no-grandpa",
1516
"--sealing=manual",

0 commit comments

Comments
 (0)