bk-press 0.0.2 → 0.0.4
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 +3 -3
- package/bkcodeai.json +30 -0
- package/lib/command/init.js +23 -5
- package/lib/command/run.js +26 -1
- package/lib/index.js +1 -1
- package/package.json +2 -2
- package/src/command/init.ts +29 -6
- package/src/command/run.ts +31 -3
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# bk-press
|
|
2
2
|
|
|
3
|
-
一个用于 Cypress 自动化测试的 CLI
|
|
3
|
+
一个用于 Cypress 自动化测试的 CLI 工具,帮助快速初始化测试环境和并行运行自动化测试。
|
|
4
4
|
|
|
5
5
|
## 📋 目录
|
|
6
6
|
|
|
@@ -58,7 +58,7 @@ pnpm add bk-press
|
|
|
58
58
|
bkpress login
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
4.
|
|
61
|
+
4. **并行运行自动化测试**
|
|
62
62
|
```bash
|
|
63
63
|
bkpress run
|
|
64
64
|
```
|
|
@@ -153,7 +153,7 @@ bkpress init
|
|
|
153
153
|
bkpress login
|
|
154
154
|
# 在浏览器中完成登录,然后按回车
|
|
155
155
|
|
|
156
|
-
# 4.
|
|
156
|
+
# 4. 并行运行测试
|
|
157
157
|
bkpress run
|
|
158
158
|
```
|
|
159
159
|
|
package/bkcodeai.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"crignore_file_patterns": [
|
|
3
|
+
"out/",
|
|
4
|
+
"dist/",
|
|
5
|
+
"assets/",
|
|
6
|
+
"images/",
|
|
7
|
+
"package.json",
|
|
8
|
+
"package-lock.json",
|
|
9
|
+
"yarn.lock",
|
|
10
|
+
".env.*",
|
|
11
|
+
"*.env",
|
|
12
|
+
"*.map",
|
|
13
|
+
"*.yml",
|
|
14
|
+
"*.yaml",
|
|
15
|
+
"*.min.js",
|
|
16
|
+
"libs/",
|
|
17
|
+
"static/",
|
|
18
|
+
"doc/",
|
|
19
|
+
"docs/",
|
|
20
|
+
"*.mo",
|
|
21
|
+
"*.po",
|
|
22
|
+
"*.ini",
|
|
23
|
+
"*.toml",
|
|
24
|
+
"*.json",
|
|
25
|
+
"*.xml",
|
|
26
|
+
"*.lock",
|
|
27
|
+
"*.md",
|
|
28
|
+
"*.txt"
|
|
29
|
+
]
|
|
30
|
+
}
|
package/lib/command/init.js
CHANGED
|
@@ -57,6 +57,11 @@ async function addScriptsToPackageJson() {
|
|
|
57
57
|
}
|
|
58
58
|
// 创建 cypress 文件夹并拉取模板文件
|
|
59
59
|
async function addTemplateFiles() {
|
|
60
|
+
const isCypressExist = await (0, util_1.isFileOrFolderExist)(path_1.default.join(process.cwd(), "cypress"));
|
|
61
|
+
if (isCypressExist) {
|
|
62
|
+
console.log("cypress 文件夹已存在,跳过拉取模板文件");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
60
65
|
const isTsProject = await checkIsTsProject();
|
|
61
66
|
console.log("当前项目是否是 TypeScript 项目: ", isTsProject);
|
|
62
67
|
await createCypressFolder();
|
|
@@ -113,6 +118,11 @@ async function copyTemplateFiles() {
|
|
|
113
118
|
// 添加 cypress.config.ts 文件
|
|
114
119
|
async function addCypressConfigFile() {
|
|
115
120
|
const cypressConfigFile = path_1.default.join(process.cwd(), "cypress.config.ts");
|
|
121
|
+
const isExist = await (0, util_1.isFileOrFolderExist)(cypressConfigFile);
|
|
122
|
+
if (isExist) {
|
|
123
|
+
console.log("cypress.config.ts 文件已存在,跳过创建");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
116
126
|
const fileContent = `import { defineConfig } from 'cypress';
|
|
117
127
|
|
|
118
128
|
export default defineConfig({
|
|
@@ -141,6 +151,11 @@ async function addCypressEnvJsonFile() {
|
|
|
141
151
|
async function addIgnoreToGitignoreFile() {
|
|
142
152
|
const gitignoreFile = path_1.default.join(process.cwd(), ".gitignore");
|
|
143
153
|
const oldFileContent = await (0, util_1.readFile)(gitignoreFile, false);
|
|
154
|
+
const isExist = oldFileContent.includes("cypress");
|
|
155
|
+
if (isExist) {
|
|
156
|
+
console.log(".gitignore 文件中已存在 cypress 相关文件,跳过添加忽略文件");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
144
159
|
const fileContent = `${oldFileContent}\n
|
|
145
160
|
cypress/parallel-weights.json
|
|
146
161
|
cypress/screenshots
|
|
@@ -151,16 +166,19 @@ multi-reporter-config.json`;
|
|
|
151
166
|
}
|
|
152
167
|
// 添加 cypress 类型到 tsconfig.json 文件
|
|
153
168
|
async function addCypressTypesToTsconfigJsonFile() {
|
|
154
|
-
const
|
|
155
|
-
const tsconfigJson = (await (0, util_1.readFile)(
|
|
169
|
+
const tsconfigJsonFilePath = path_1.default.join(process.cwd(), "tsconfig.json");
|
|
170
|
+
const tsconfigJson = (await (0, util_1.readFile)(tsconfigJsonFilePath));
|
|
156
171
|
if (tsconfigJson.include) {
|
|
157
|
-
tsconfigJson.include.
|
|
172
|
+
if (!tsconfigJson.include.includes("cypress/**/*")) {
|
|
173
|
+
tsconfigJson.include.push("cypress/**/*");
|
|
174
|
+
}
|
|
158
175
|
}
|
|
159
176
|
else {
|
|
160
177
|
tsconfigJson.include = ["cypress/**/*"];
|
|
161
178
|
}
|
|
162
179
|
if (tsconfigJson.compilerOptions) {
|
|
163
|
-
if (tsconfigJson.compilerOptions.types
|
|
180
|
+
if (tsconfigJson.compilerOptions.types &&
|
|
181
|
+
!tsconfigJson.compilerOptions.types.includes("cypress")) {
|
|
164
182
|
tsconfigJson.compilerOptions.types.push("cypress");
|
|
165
183
|
}
|
|
166
184
|
else {
|
|
@@ -173,5 +191,5 @@ async function addCypressTypesToTsconfigJsonFile() {
|
|
|
173
191
|
};
|
|
174
192
|
}
|
|
175
193
|
const fileContent = JSON.stringify(tsconfigJson, null, 2);
|
|
176
|
-
await (0, util_1.writeFile)(
|
|
194
|
+
await (0, util_1.writeFile)(tsconfigJsonFilePath, fileContent);
|
|
177
195
|
}
|
package/lib/command/run.js
CHANGED
|
@@ -9,12 +9,17 @@ const login_1 = require("./login");
|
|
|
9
9
|
const os_1 = __importDefault(require("os"));
|
|
10
10
|
async function run() {
|
|
11
11
|
console.log("开始运行自动化测试...");
|
|
12
|
+
console.log("当前工作目录: ", process.cwd());
|
|
12
13
|
const config = await (0, login_1.readCypressEnvConfig)();
|
|
13
14
|
const cpuCount = os_1.default.cpus().length;
|
|
14
15
|
console.log("当前CPU核心数: ", cpuCount, ", 设置测试并发数: ", cpuCount);
|
|
15
16
|
return new Promise((resolve, reject) => {
|
|
16
|
-
(0, child_process_1.exec)(
|
|
17
|
+
const child = (0, child_process_1.exec)(
|
|
18
|
+
// `npm run dev & npx wait-on ${config.localUrl} && npx cypress-parallel -s e2e -t ${cpuCount} -d cypress/e2e`,
|
|
19
|
+
`npx start-server-and-test dev ${config.localUrl} "cypress-parallel -s e2e -t ${cpuCount} -d cypress/e2e"`, {
|
|
17
20
|
cwd: process.cwd(),
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
stdio: "inherit",
|
|
18
23
|
}, (error, stdout, stderr) => {
|
|
19
24
|
if (error) {
|
|
20
25
|
console.error("运行自动化测试失败:", error);
|
|
@@ -24,5 +29,25 @@ async function run() {
|
|
|
24
29
|
console.log("自动化测试运行成功!");
|
|
25
30
|
resolve(stdout);
|
|
26
31
|
});
|
|
32
|
+
child.stdout.setEncoding("utf8"); // 设置编码
|
|
33
|
+
child.stdout.on("data", (data) => {
|
|
34
|
+
// 通常不需要额外添加前缀,直接打印数据即可
|
|
35
|
+
process.stdout.write(data); // 使用 process.stdout.write 避免自动换行
|
|
36
|
+
});
|
|
37
|
+
child.stderr.setEncoding("utf8");
|
|
38
|
+
child.stderr.on("data", (data) => {
|
|
39
|
+
// 错误信息可以输出到标准错误流,方便区分
|
|
40
|
+
process.stderr.write(`STDERR: ${data}`);
|
|
41
|
+
});
|
|
42
|
+
child.on("error", (error) => {
|
|
43
|
+
reject(error);
|
|
44
|
+
console.error(`Failed to start subprocess: ${error}`);
|
|
45
|
+
});
|
|
46
|
+
child.on("close", (code) => {
|
|
47
|
+
if (code !== 0) {
|
|
48
|
+
reject(new Error(`命令执行失败,退出码: ${code}`));
|
|
49
|
+
}
|
|
50
|
+
resolve(1);
|
|
51
|
+
});
|
|
27
52
|
});
|
|
28
53
|
}
|
package/lib/index.js
CHANGED
|
@@ -7,7 +7,7 @@ const program = new commander_1.Command();
|
|
|
7
7
|
program
|
|
8
8
|
.name("bk-press")
|
|
9
9
|
.description("一个用于 Cypress 自动化测试的 CLI 工具,帮助快速初始化和运行端到端测试")
|
|
10
|
-
.version("0.0.
|
|
10
|
+
.version("0.0.4");
|
|
11
11
|
program.command("init").action(command_1.init);
|
|
12
12
|
program.command("login").action(command_1.login);
|
|
13
13
|
// @ts-ignore
|
package/package.json
CHANGED
package/src/command/init.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../util";
|
|
12
12
|
|
|
13
13
|
export async function init() {
|
|
14
|
-
console.log("开始初始化Cypress
|
|
14
|
+
console.log("开始初始化Cypress自动化测试环境...");
|
|
15
15
|
console.log("安装相关依赖...");
|
|
16
16
|
await installDependencies();
|
|
17
17
|
console.log("添加类型到 tsconfig.json 文件...");
|
|
@@ -68,6 +68,13 @@ async function addScriptsToPackageJson() {
|
|
|
68
68
|
|
|
69
69
|
// 创建 cypress 文件夹并拉取模板文件
|
|
70
70
|
async function addTemplateFiles() {
|
|
71
|
+
const isCypressExist = await isFileOrFolderExist(
|
|
72
|
+
path.join(process.cwd(), "cypress")
|
|
73
|
+
);
|
|
74
|
+
if (isCypressExist) {
|
|
75
|
+
console.log("cypress 文件夹已存在,跳过拉取模板文件");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
71
78
|
const isTsProject = await checkIsTsProject();
|
|
72
79
|
console.log("当前项目是否是 TypeScript 项目: ", isTsProject);
|
|
73
80
|
await createCypressFolder();
|
|
@@ -134,6 +141,11 @@ async function copyTemplateFiles() {
|
|
|
134
141
|
// 添加 cypress.config.ts 文件
|
|
135
142
|
async function addCypressConfigFile() {
|
|
136
143
|
const cypressConfigFile = path.join(process.cwd(), "cypress.config.ts");
|
|
144
|
+
const isExist = await isFileOrFolderExist(cypressConfigFile);
|
|
145
|
+
if (isExist) {
|
|
146
|
+
console.log("cypress.config.ts 文件已存在,跳过创建");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
137
149
|
const fileContent = `import { defineConfig } from 'cypress';
|
|
138
150
|
|
|
139
151
|
export default defineConfig({
|
|
@@ -164,6 +176,12 @@ async function addCypressEnvJsonFile() {
|
|
|
164
176
|
async function addIgnoreToGitignoreFile() {
|
|
165
177
|
const gitignoreFile = path.join(process.cwd(), ".gitignore");
|
|
166
178
|
const oldFileContent = await readFile(gitignoreFile, false);
|
|
179
|
+
const isExist = oldFileContent.includes("cypress");
|
|
180
|
+
if (isExist) {
|
|
181
|
+
console.log(".gitignore 文件中已存在 cypress 相关文件,跳过添加忽略文件");
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
167
185
|
const fileContent = `${oldFileContent}\n
|
|
168
186
|
cypress/parallel-weights.json
|
|
169
187
|
cypress/screenshots
|
|
@@ -175,19 +193,24 @@ multi-reporter-config.json`;
|
|
|
175
193
|
|
|
176
194
|
// 添加 cypress 类型到 tsconfig.json 文件
|
|
177
195
|
async function addCypressTypesToTsconfigJsonFile() {
|
|
178
|
-
const
|
|
179
|
-
const tsconfigJson = (await readFile(
|
|
196
|
+
const tsconfigJsonFilePath = path.join(process.cwd(), "tsconfig.json");
|
|
197
|
+
const tsconfigJson = (await readFile(tsconfigJsonFilePath)) as Record<
|
|
180
198
|
string,
|
|
181
199
|
any
|
|
182
200
|
>;
|
|
183
201
|
if (tsconfigJson.include) {
|
|
184
|
-
tsconfigJson.include.
|
|
202
|
+
if (!tsconfigJson.include.includes("cypress/**/*")) {
|
|
203
|
+
tsconfigJson.include.push("cypress/**/*");
|
|
204
|
+
}
|
|
185
205
|
} else {
|
|
186
206
|
tsconfigJson.include = ["cypress/**/*"];
|
|
187
207
|
}
|
|
188
208
|
|
|
189
209
|
if (tsconfigJson.compilerOptions) {
|
|
190
|
-
if (
|
|
210
|
+
if (
|
|
211
|
+
tsconfigJson.compilerOptions.types &&
|
|
212
|
+
!tsconfigJson.compilerOptions.types.includes("cypress")
|
|
213
|
+
) {
|
|
191
214
|
tsconfigJson.compilerOptions.types.push("cypress");
|
|
192
215
|
} else {
|
|
193
216
|
tsconfigJson.compilerOptions.types = ["cypress"];
|
|
@@ -198,5 +221,5 @@ async function addCypressTypesToTsconfigJsonFile() {
|
|
|
198
221
|
};
|
|
199
222
|
}
|
|
200
223
|
const fileContent = JSON.stringify(tsconfigJson, null, 2);
|
|
201
|
-
await writeFile(
|
|
224
|
+
await writeFile(tsconfigJsonFilePath, fileContent);
|
|
202
225
|
}
|
package/src/command/run.ts
CHANGED
|
@@ -4,16 +4,20 @@ import os from "os";
|
|
|
4
4
|
|
|
5
5
|
export async function run() {
|
|
6
6
|
console.log("开始运行自动化测试...");
|
|
7
|
+
// console.log("当前工作目录: ", process.cwd());
|
|
7
8
|
const config = await readCypressEnvConfig();
|
|
8
9
|
const cpuCount = os.cpus().length;
|
|
9
10
|
console.log("当前CPU核心数: ", cpuCount, ", 设置测试并发数: ", cpuCount);
|
|
10
11
|
return new Promise((resolve, reject) => {
|
|
11
|
-
exec(
|
|
12
|
-
`
|
|
12
|
+
const child = exec(
|
|
13
|
+
// `npm run dev & npx wait-on ${config.localUrl} && npx cypress-parallel -s e2e -t ${cpuCount} -d cypress/e2e`,
|
|
14
|
+
`npx start-server-and-test dev ${config.localUrl} "cypress-parallel -s e2e -t ${cpuCount} -d cypress/e2e"`,
|
|
13
15
|
{
|
|
14
16
|
cwd: process.cwd(),
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
stdio: "inherit",
|
|
15
19
|
},
|
|
16
|
-
(error, stdout, stderr) => {
|
|
20
|
+
(error: any, stdout: any, stderr: any) => {
|
|
17
21
|
if (error) {
|
|
18
22
|
console.error("运行自动化测试失败:", error);
|
|
19
23
|
reject(stderr);
|
|
@@ -23,5 +27,29 @@ export async function run() {
|
|
|
23
27
|
resolve(stdout);
|
|
24
28
|
}
|
|
25
29
|
);
|
|
30
|
+
|
|
31
|
+
child.stdout!.setEncoding("utf8"); // 设置编码
|
|
32
|
+
child.stdout!.on("data", (data) => {
|
|
33
|
+
// 通常不需要额外添加前缀,直接打印数据即可
|
|
34
|
+
process.stdout.write(data); // 使用 process.stdout.write 避免自动换行
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
child.stderr!.setEncoding("utf8");
|
|
38
|
+
child.stderr!.on("data", (data) => {
|
|
39
|
+
// 错误信息可以输出到标准错误流,方便区分
|
|
40
|
+
process.stderr.write(`STDERR: ${data}`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
child.on("error", (error) => {
|
|
44
|
+
reject(error);
|
|
45
|
+
console.error(`Failed to start subprocess: ${error}`);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
child.on("close", (code) => {
|
|
49
|
+
if (code !== 0) {
|
|
50
|
+
reject(new Error(`命令执行失败,退出码: ${code}`));
|
|
51
|
+
}
|
|
52
|
+
resolve(1);
|
|
53
|
+
});
|
|
26
54
|
});
|
|
27
55
|
}
|