bk-press 0.0.3 → 0.0.5

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.
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fixture = fixture;
7
+ const path_1 = __importDefault(require("path"));
8
+ const util_1 = require("../util");
9
+ async function fixture() {
10
+ console.log("开始生成 fixture 文件...");
11
+ const logJsonFile = path_1.default.join(process.cwd(), "web-interaction-log.json");
12
+ const isExistJsonFile = await (0, util_1.isFileOrFolderExist)(logJsonFile);
13
+ if (!isExistJsonFile) {
14
+ throw new Error("web-interaction-log.json 文件不存在,请在 Chrome 应用商店安装 Web Interaction Logger 插件后,录制并导出 web-interaction-log.json 到项目根目录下。");
15
+ }
16
+ const logList = (await (0, util_1.readFile)(logJsonFile));
17
+ const validLogList = logList.filter((log) => log.type === "network" &&
18
+ log.subtype === "response-body" &&
19
+ log.url.startsWith("/"));
20
+ const commonPath = path_1.default.join(process.cwd(), "cypress_fixtures");
21
+ const isExistFolder = await (0, util_1.isFileOrFolderExist)(commonPath);
22
+ if (!isExistFolder) {
23
+ await (0, util_1.createFolder)(commonPath);
24
+ console.log(`创建 fixtures 文件夹: ${commonPath}`);
25
+ }
26
+ validLogList.forEach(async (log) => {
27
+ const jsonContent = log.responseBody;
28
+ const jsonString = JSON.stringify(jsonContent, null, 2);
29
+ const isExistQuery = log.url.includes("?");
30
+ let fileName = "";
31
+ if (isExistQuery) {
32
+ fileName = log.url.split("?")[0].replace(/\//g, "_");
33
+ }
34
+ else {
35
+ fileName = log.url.replace(/\//g, "_");
36
+ }
37
+ fileName = `${log.method}_${fileName.substring(1, fileName.length - 1)}.json`;
38
+ console.log(`生成 fixture 文件: ${fileName}`);
39
+ const fixtureFile = path_1.default.join(commonPath, fileName);
40
+ await (0, util_1.writeFile)(fixtureFile, jsonString);
41
+ });
42
+ }
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./login"), exports);
18
18
  __exportStar(require("./init"), exports);
19
19
  __exportStar(require("./run"), exports);
20
+ __exportStar(require("./fixture"), exports);
@@ -10,7 +10,7 @@ const path_1 = __importDefault(require("path"));
10
10
  const fs_extra_1 = __importDefault(require("fs-extra"));
11
11
  const util_1 = require("../util");
12
12
  async function init() {
13
- console.log("开始初始化Cypress自动化测试...");
13
+ console.log("开始初始化Cypress自动化测试环境...");
14
14
  console.log("安装相关依赖...");
15
15
  await installDependencies();
16
16
  console.log("添加类型到 tsconfig.json 文件...");
@@ -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 tsconfigJsonFile = path_1.default.join(process.cwd(), "tsconfig.json");
155
- const tsconfigJson = (await (0, util_1.readFile)(tsconfigJsonFile));
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.push("cypress/**/*");
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)(tsconfigJsonFile, fileContent);
194
+ await (0, util_1.writeFile)(tsconfigJsonFilePath, fileContent);
177
195
  }
@@ -9,11 +9,14 @@ 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
- const child = (0, child_process_1.exec)(`start-server-and-test dev ${config.localUrl} 'cypress-parallel -s e2e -t ${cpuCount} -d cypress/e2e'`, {
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(),
18
21
  // @ts-ignore
19
22
  stdio: "inherit",
package/lib/index.js CHANGED
@@ -7,9 +7,19 @@ const program = new commander_1.Command();
7
7
  program
8
8
  .name("bk-press")
9
9
  .description("一个用于 Cypress 自动化测试的 CLI 工具,帮助快速初始化和运行端到端测试")
10
- .version("0.0.3");
11
- program.command("init").action(command_1.init);
12
- program.command("login").action(command_1.login);
10
+ .version("0.0.5");
11
+ program
12
+ .command("init")
13
+ .description("初始化 Cypress 自动化测试环境")
14
+ .action(command_1.init);
15
+ program
16
+ .command("login")
17
+ .description("登录本地开发环境并保存 Cookie")
18
+ .action(command_1.login);
13
19
  // @ts-ignore
14
- program.command("run").action(command_1.run);
20
+ program.command("run").description("并行运行自动化测试").action(command_1.run);
21
+ program
22
+ .command("fixture")
23
+ .description("根据 Chrome 插件 Web Interaction Logger 导出的 web-interaction-log.json 生成 fixture 拦截数据")
24
+ .action(command_1.fixture);
15
25
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bk-press",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "一个用于 Cypress 自动化测试的 CLI 工具,帮助快速初始化测试环境和并行运行自动化测试",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -0,0 +1,58 @@
1
+ import path from "path";
2
+ import {
3
+ isFileOrFolderExist,
4
+ readFile,
5
+ writeFile,
6
+ createFolder,
7
+ } from "../util";
8
+
9
+ interface WebInteractionLog {
10
+ type: string;
11
+ subtype: string;
12
+ requestId: string;
13
+ url: string;
14
+ method: string;
15
+ status: number;
16
+ statusText: string;
17
+ responseHeaders: string;
18
+ responseBody: Record<string, any>;
19
+ }
20
+
21
+ export async function fixture() {
22
+ console.log("开始生成 fixture 文件...");
23
+ const logJsonFile = path.join(process.cwd(), "web-interaction-log.json");
24
+ const isExistJsonFile = await isFileOrFolderExist(logJsonFile);
25
+ if (!isExistJsonFile) {
26
+ throw new Error(
27
+ "web-interaction-log.json 文件不存在,请在 Chrome 应用商店安装 Web Interaction Logger 插件后,录制并导出 web-interaction-log.json 到项目根目录下。",
28
+ );
29
+ }
30
+ const logList = (await readFile(logJsonFile)) as WebInteractionLog[];
31
+ const validLogList = logList.filter(
32
+ (log) =>
33
+ log.type === "network" &&
34
+ log.subtype === "response-body" &&
35
+ log.url.startsWith("/"),
36
+ );
37
+ const commonPath = path.join(process.cwd(), "cypress_fixtures");
38
+ const isExistFolder = await isFileOrFolderExist(commonPath);
39
+ if (!isExistFolder) {
40
+ await createFolder(commonPath);
41
+ console.log(`创建 fixtures 文件夹: ${commonPath}`);
42
+ }
43
+ validLogList.forEach(async (log) => {
44
+ const jsonContent = log.responseBody;
45
+ const jsonString = JSON.stringify(jsonContent, null, 2);
46
+ const isExistQuery = log.url.includes("?");
47
+ let fileName = "";
48
+ if (isExistQuery) {
49
+ fileName = log.url.split("?")[0].replace(/\//g, "_");
50
+ } else {
51
+ fileName = log.url.replace(/\//g, "_");
52
+ }
53
+ fileName = `${log.method}_${fileName.substring(1, fileName.length - 1)}.json`;
54
+ console.log(`生成 fixture 文件: ${fileName}`);
55
+ const fixtureFile = path.join(commonPath, fileName);
56
+ await writeFile(fixtureFile, jsonString);
57
+ });
58
+ }
@@ -1,3 +1,4 @@
1
1
  export * from "./login";
2
2
  export * from "./init";
3
3
  export * from "./run";
4
+ export * from "./fixture";
@@ -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 tsconfigJsonFile = path.join(process.cwd(), "tsconfig.json");
179
- const tsconfigJson = (await readFile(tsconfigJsonFile)) as Record<
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.push("cypress/**/*");
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 (tsconfigJson.compilerOptions.types) {
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(tsconfigJsonFile, fileContent);
224
+ await writeFile(tsconfigJsonFilePath, fileContent);
202
225
  }
@@ -4,12 +4,14 @@ 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
12
  const child = exec(
12
- `start-server-and-test dev ${config.localUrl} 'cypress-parallel -s e2e -t ${cpuCount} -d cypress/e2e'`,
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(),
15
17
  // @ts-ignore
package/src/index.ts CHANGED
@@ -1,19 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Command } from "commander";
4
- import { login, init, run } from "./command";
4
+ import { login, init, run, fixture } from "./command";
5
5
 
6
6
  const program = new Command();
7
7
 
8
8
  program
9
9
  .name("bk-press")
10
10
  .description(
11
- "一个用于 Cypress 自动化测试的 CLI 工具,帮助快速初始化和运行端到端测试"
11
+ "一个用于 Cypress 自动化测试的 CLI 工具,帮助快速初始化和运行端到端测试",
12
12
  )
13
- .version("0.0.3");
13
+ .version("0.0.5");
14
14
 
15
- program.command("init").action(init);
16
- program.command("login").action(login);
15
+ program
16
+ .command("init")
17
+ .description("初始化 Cypress 自动化测试环境")
18
+ .action(init);
19
+ program
20
+ .command("login")
21
+ .description("登录本地开发环境并保存 Cookie")
22
+ .action(login);
17
23
  // @ts-ignore
18
- program.command("run").action(run);
24
+ program.command("run").description("并行运行自动化测试").action(run);
25
+ program
26
+ .command("fixture")
27
+ .description(
28
+ "根据 Chrome 插件 Web Interaction Logger 导出的 web-interaction-log.json 生成 fixture 拦截数据",
29
+ )
30
+ .action(fixture);
19
31
  program.parse(process.argv);