@dev-blinq/cucumber_client 1.0.1581-dev → 1.0.1582-dev

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.
@@ -5,6 +5,8 @@ import path from "path";
5
5
  import { CodePage } from "./page_reflection.js";
6
6
  import { convertToIdentifier, escapeNonPrintables } from "./utils.js";
7
7
  import socketLogger from "../utils/socket_logger.js";
8
+ import fs from "fs";
9
+
8
10
  const findElementIdentifier = (node, step, userData, elements) => {
9
11
  if (node.key) {
10
12
  // incase of rerunning implemented steps
@@ -366,7 +368,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
366
368
  codeLines.push(line);
367
369
  break;
368
370
  }
369
- case Types.VERIFY_PAGE_SNAPSHOT:
371
+ case Types.VERIFY_PAGE_SNAPSHOT: {
370
372
  comment = step.nestFrmLoc
371
373
  ? `// Verify page snapshot ${step.parameters[0]} in the frame ${step.selectors.iframe_src}`
372
374
  : `// Verify page snapshot ${step.parameters[0]}`;
@@ -375,7 +377,24 @@ const _generateCodeFromCommand = (step, elements, userData) => {
375
377
  codeLines.push(line);
376
378
  line = `await context.web.snapshotValidation(frameLocator, _param_0 , _params, ${JSON.stringify(options)}, this);`;
377
379
  codeLines.push(line);
380
+
381
+ const data = step.data;
382
+ if (data) {
383
+ try {
384
+ const { snapshot, fileName, filePath } = data;
385
+ const folderPath = process.env.BVT_TEMP_SNAPSHOTS_FOLDER ?? filePath;
386
+ const filePathWithName = path.join(folderPath, fileName);
387
+ if (!fs.existsSync(folderPath)) {
388
+ fs.mkdirSync(folderPath, { recursive: true });
389
+ }
390
+ fs.writeFileSync(filePathWithName, snapshot, "utf-8");
391
+ } catch (e) {
392
+ console.log(`Error saving snapshot file: ${e}`);
393
+ throw e;
394
+ }
395
+ }
378
396
  break;
397
+ }
379
398
  case Types.VERIFY_PAGE_CONTAINS_TEXT:
380
399
  line = "await context.web.verifyTextExistInPage( ";
381
400
  input = `${escapeNonPrintables(JSON.stringify(step.parameters[0]))}`;
@@ -4,7 +4,7 @@ import { existsSync, readdirSync, readFileSync, rmSync } from "fs";
4
4
  import path from "path";
5
5
  import url from "url";
6
6
  import { getImplementedSteps, parseRouteFiles } from "./implemented_steps.js";
7
- import { NamesService, RemoteBrowserService } from "./services.js";
7
+ import { NamesService, RemoteBrowserService, PublishService } from "./services.js";
8
8
  import { BVTStepRunner } from "./step_runner.js";
9
9
  import { readFile, writeFile } from "fs/promises";
10
10
  import { updateStepDefinitions, loadStepDefinitions, getCommandsForImplementedStep } from "./step_utils.js";
@@ -197,12 +197,17 @@ export class BVTRecorder {
197
197
  projectDir: this.projectDir,
198
198
  logger: this.logger,
199
199
  });
200
+ this.workspaceService = new PublishService(this.TOKEN);
200
201
  this.pageSet = new Set();
201
202
  this.lastKnownUrlPath = "";
202
203
  this.world = { attach: () => {} };
203
204
  this.shouldTakeScreenshot = true;
204
205
  this.watcher = null;
205
206
  this.networkEventsFolder = path.join(tmpdir(), "blinq_network_events");
207
+
208
+ this.tempProjectFolder = `${tmpdir()}/bvt_temp_project_${Math.floor(Math.random() * 1000000)}`;
209
+ this.tempSnapshotsFolder = path.join(this.tempProjectFolder, "data/snapshots");
210
+
206
211
  if (existsSync(this.networkEventsFolder)) {
207
212
  rmSync(this.networkEventsFolder, { recursive: true, force: true });
208
213
  }
@@ -926,6 +931,7 @@ export class BVTRecorder {
926
931
  REPORT_FOLDER: this.bvtContext.reportFolder,
927
932
  BLINQ_ENV: this.envName,
928
933
  DEBUG: "blinq:route",
934
+ BVT_TEMP_SNAPSHOTS_FOLDER: this.tempSnapshotsFolder,
929
935
  };
930
936
 
931
937
  this.bvtContext.navigate = true;
@@ -972,10 +978,23 @@ export class BVTRecorder {
972
978
  this.bvtContext.navigate = false;
973
979
  }
974
980
  }
975
- async saveScenario({ scenario, featureName, override, isSingleStep }) {
976
- await updateStepDefinitions({ scenario, featureName, projectDir: this.projectDir }); // updates mjs files
977
- if (!isSingleStep) await updateFeatureFile({ featureName, scenario, override, projectDir: this.projectDir }); // updates gherkin files
978
- await this.cleanup({ tags: scenario.tags });
981
+ async saveScenario({ scenario, featureName, override, isSingleStep, branch, isEditing }) {
982
+ // await updateStepDefinitions({ scenario, featureName, projectDir: this.projectDir }); // updates mjs files
983
+ // if (!isSingleStep) await updateFeatureFile({ featureName, scenario, override, projectDir: this.projectDir }); // updates gherkin files
984
+ const res = await this.workspaceService.saveScenario({
985
+ scenario,
986
+ featureName,
987
+ override,
988
+ isSingleStep,
989
+ branch,
990
+ isEditing,
991
+ projectId: path.basename(this.projectDir),
992
+ });
993
+ if (res.success) {
994
+ await this.cleanup({ tags: scenario.tags });
995
+ } else {
996
+ throw new Error(res.message || "Error saving scenario");
997
+ }
979
998
  }
980
999
  async getImplementedSteps() {
981
1000
  const stepsAndScenarios = await getImplementedSteps(this.projectDir);
@@ -147,6 +147,69 @@ export class NamesService {
147
147
  return result.data;
148
148
  }
149
149
  }
150
+ export class PublishService {
151
+ TOKEN;
152
+ constructor(TOKEN) {
153
+ this.TOKEN = TOKEN;
154
+ }
155
+ async saveScenario({ scenario, featureName, override, branch, isEditing, projectId }) {
156
+ const url = path.join(`${getRunsServiceBaseURL()}`, "..", "workspace/publish-recording");
157
+ const result = await axiosClient({
158
+ url,
159
+ method: "POST",
160
+ data: {
161
+ scenario,
162
+ featureName,
163
+ override,
164
+ },
165
+ params: {
166
+ branch,
167
+ },
168
+ headers: {
169
+ Authorization: `Bearer ${this.TOKEN}`,
170
+ "X-Source": "recorder",
171
+ },
172
+ });
173
+ if (result.status !== 200) {
174
+ return { success: false, message: "Error while saving scenario" };
175
+ }
176
+ try {
177
+ this.updateProjectMetadata({
178
+ featureName,
179
+ scenarioName: scenario.name,
180
+ projectId,
181
+ branch,
182
+ isEditing: override,
183
+ });
184
+ }
185
+ catch (error) { }
186
+ return { success: true, data: result.data };
187
+ }
188
+ async updateProjectMetadata({ featureName, scenarioName, projectId, branch, isEditing }) {
189
+ try {
190
+ await axiosClient({
191
+ method: "POST",
192
+ url: `${getRunsServiceBaseURL()}/project/updateProjectMetadata`,
193
+ data: {
194
+ featureName,
195
+ scenarioName,
196
+ eventType: isEditing ? "editScenario" : "createScenario",
197
+ projectId,
198
+ branch: branch,
199
+ },
200
+ headers: {
201
+ Authorization: `Bearer ${this.TOKEN}`,
202
+ "X-Source": "recorder",
203
+ },
204
+ });
205
+ }
206
+ catch (error) {
207
+ // logger.error("Failed to update project metadata: " + error.message);
208
+ // @ts-ignore
209
+ console.error("run_recorder", `Failed to update project metadata: ${error.message ?? error}`);
210
+ }
211
+ }
212
+ }
150
213
  export class RemoteBrowserService extends EventEmitter {
151
214
  CDP_CONNECT_URL;
152
215
  context;
@@ -296,6 +296,7 @@ const _toRecordingStep = (cmd) => {
296
296
  type: "verify_page_snapshot",
297
297
  parameters: [cmd.value],
298
298
  selectors: cmd.selectors,
299
+ data: cmd.data,
299
300
  };
300
301
  }
301
302
  default: {
@@ -38,7 +38,7 @@ export class SocketLogger {
38
38
  const eventPayload = {
39
39
  level,
40
40
  context: context || this.defaultContext,
41
- data,
41
+ data: JSON.stringify(data),
42
42
  timestamp: new Date().toISOString(),
43
43
  dataSize,
44
44
  ...extra,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1581-dev",
3
+ "version": "1.0.1582-dev",
4
4
  "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",