@bigbinary/neeto-playwright-commons 2.2.0 → 2.2.1

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/index.cjs.js CHANGED
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var child_process = require('child_process');
4
3
  var neetoCist = require('@bigbinary/neeto-cist');
5
4
  var faker = require('@faker-js/faker');
6
5
  var fs$4 = require('fs');
@@ -10,6 +9,7 @@ var test = require('@playwright/test');
10
9
  var playwrightI18nextFixture = require('playwright-i18next-fixture');
11
10
  var require$$0$3 = require('util');
12
11
  var ramda = require('ramda');
12
+ var child_process = require('child_process');
13
13
  var dayjs = require('dayjs');
14
14
  var require$$0$7 = require('stream');
15
15
  var require$$0$6 = require('node:buffer');
@@ -247,86 +247,63 @@ class MemberApis {
247
247
  });
248
248
  }
249
249
 
250
- class RailsEmailRakeClient {
251
- workingDirectory;
252
- constructor() {
253
- this.workingDirectory = process.env.RAILS_ROOT || "..";
254
- }
255
- convertRawEmail = (rawEmail) => ({
256
- from: rawEmail.from,
257
- to: rawEmail.to,
258
- cc: rawEmail.cc,
259
- bcc: rawEmail.bcc,
260
- replyTo: rawEmail.reply_to,
261
- subject: rawEmail.subject,
262
- htmlBody: rawEmail.html_body,
263
- textBody: rawEmail.text_body,
264
- receivedAt: rawEmail.received_at,
265
- attachments: rawEmail.attachments?.map(att => ({
266
- name: att.filename,
267
- type: att.mime_type,
268
- content: att.data,
250
+ class RailsEmailApiClient {
251
+ port = process.env.RAILS_SERVER_PORT;
252
+ subdomain = process.env.SUBDOMAIN ?? "spinkart";
253
+ baseUrl = `http://${this.subdomain}.lvh.me:${this.port}`;
254
+ emailsEndpoint = `${this.baseUrl}/api/v1/testing/emails`;
255
+ constructor() { }
256
+ convertRawEmail = (raw) => ({
257
+ from: raw.from,
258
+ to: raw.to,
259
+ cc: raw.cc,
260
+ bcc: raw.bcc,
261
+ replyTo: raw.reply_to,
262
+ subject: raw.subject,
263
+ htmlBody: raw.html_body,
264
+ textBody: raw.text_body,
265
+ receivedAt: raw.received_at,
266
+ attachments: raw.attachments?.map(({ filename, mime_type, data }) => ({
267
+ name: filename,
268
+ type: mime_type,
269
+ content: data,
269
270
  })),
270
271
  });
271
- executeRakeTask = async (taskName, args = []) => {
272
- const childProcess = child_process.spawn("bundle", ["exec", "rake", taskName, "--", ...args], {
273
- cwd: this.workingDirectory,
274
- stdio: ["ignore", "pipe", "pipe"],
275
- });
276
- let stdout = "";
277
- let stderr = "";
278
- childProcess.stdout?.on("data", data => {
279
- stdout += data.toString();
280
- });
281
- childProcess.stderr?.on("data", data => {
282
- stderr += data.toString();
283
- });
284
- const exitCode = await new Promise((resolve, reject) => {
285
- childProcess.on("error", reject);
286
- childProcess.on("close", resolve);
287
- });
288
- if (exitCode !== 0) {
289
- throw new Error(`Rake task ${taskName} failed: ${stderr || stdout || `Exit code ${exitCode}`}`);
290
- }
291
- return this.extractJsonFromOutput(stdout);
292
- };
293
- extractJsonFromOutput = (output) => {
294
- const delimiterMatch = output.match(/<-- Captured Emails Start-->([\s\S]*?)<-- Captured Emails End-->/);
295
- return delimiterMatch ? delimiterMatch[1].trim() : output.trim();
272
+ buildQueryString = (params) => {
273
+ if (!params)
274
+ return "";
275
+ const filtered = Object.fromEntries(Object.entries(neetoCist.keysToSnakeCase(params))
276
+ .filter(([, v]) => v != null && v !== "")
277
+ .map(([k, v]) => [k, String(v)]));
278
+ const query = new URLSearchParams(filtered).toString();
279
+ return query ? `?${query}` : "";
296
280
  };
297
- listEmails = async (searchParams) => {
281
+ fetchJson = async (url, options) => {
298
282
  try {
299
- const args = this.buildSearchArgs(searchParams);
300
- const output = await this.executeRakeTask("playwright:fetch_captured_emails", args);
301
- if (!output)
302
- return [];
303
- const rawEmails = JSON.parse(output);
304
- return rawEmails.map(this.convertRawEmail);
283
+ const res = await fetch(url, options);
284
+ if (!res.ok)
285
+ return null;
286
+ return (await res.json());
305
287
  }
306
- catch (error) {
307
- console.error("Failed to fetch emails:", error);
308
- return [];
288
+ catch (err) {
289
+ console.error("API error:", err);
290
+ return null;
309
291
  }
310
292
  };
311
- buildSearchArgs = (searchParams) => Object.entries(neetoCist.keysToSnakeCase(searchParams ?? {}))
312
- .filter(([, value]) => value != null && value !== "")
313
- .map(([key, value]) => `--${key}=${value}`);
293
+ listEmails = async (searchParams) => {
294
+ const query = this.buildQueryString(searchParams);
295
+ const data = await this.fetchJson(`${this.emailsEndpoint}${query}`);
296
+ return data?.map(this.convertRawEmail) ?? [];
297
+ };
314
298
  getLatestEmail = async (searchParams) => {
315
299
  const emails = await this.listEmails(searchParams);
316
- if (emails.length === 0)
317
- return null;
318
- return emails.reduce((latest, current) => new Date(current.receivedAt) > new Date(latest.receivedAt)
319
- ? current
320
- : latest);
321
- };
322
- clearEmails = async () => {
323
- try {
324
- await this.executeRakeTask("playwright:clear_captured_emails");
325
- }
326
- catch (error) {
327
- console.error("Failed to clear emails:", error);
328
- }
300
+ return emails.reduce((latest, curr) => !latest || new Date(curr.receivedAt) > new Date(latest.receivedAt)
301
+ ? curr
302
+ : latest, null);
329
303
  };
304
+ clearEmails = () => this.fetchJson(this.emailsEndpoint, {
305
+ method: "DELETE",
306
+ });
330
307
  }
331
308
 
332
309
  class RoleApis {
@@ -60309,10 +60286,10 @@ const hexToRGB = (hex) => {
60309
60286
 
60310
60287
  class RailsEmailUtils {
60311
60288
  neetoPlaywrightUtilities;
60312
- railsEmailRakeClient;
60289
+ railsEmailClient;
60313
60290
  constructor(neetoPlaywrightUtilities) {
60314
60291
  this.neetoPlaywrightUtilities = neetoPlaywrightUtilities;
60315
- this.railsEmailRakeClient = new RailsEmailRakeClient();
60292
+ this.railsEmailClient = new RailsEmailApiClient();
60316
60293
  }
60317
60294
  convertRailsEmailToFormattedList = (railsEmail) => {
60318
60295
  if (!railsEmail)
@@ -60363,11 +60340,11 @@ class RailsEmailUtils {
60363
60340
  blobId: "",
60364
60341
  };
60365
60342
  };
60366
- clearEmails = () => this.railsEmailRakeClient.clearEmails();
60367
- getLatestEmail = (searchParams) => this.railsEmailRakeClient.getLatestEmail(searchParams);
60368
- listEmails = (searchParams) => this.railsEmailRakeClient.listEmails(searchParams);
60343
+ clearEmails = () => this.railsEmailClient.clearEmails();
60344
+ getLatestEmail = (searchParams) => this.railsEmailClient.getLatestEmail(searchParams);
60345
+ listEmails = (searchParams) => this.railsEmailClient.listEmails(searchParams);
60369
60346
  listMessages = async (messageSearchCriteria = {}, { receivedAfter = new Date(new Date().valueOf() - 60 * 60 * 1000), } = {}) => {
60370
- const emails = await this.railsEmailRakeClient.listEmails({
60347
+ const emails = await this.railsEmailClient.listEmails({
60371
60348
  ...messageSearchCriteria,
60372
60349
  receivedAfter: receivedAfter.toISOString(),
60373
60350
  });
@@ -60378,7 +60355,7 @@ class RailsEmailUtils {
60378
60355
  findMessage = async (messageSearchCriteria = {}, { timeout = 10_000, receivedAfter = new Date(new Date().valueOf() - 60 * 60 * 1000), expectedEmailCount = 1, } = {}, shouldThrowErrorOnTimeout = true) => {
60379
60356
  const email = (await this.neetoPlaywrightUtilities.executeRecursively({
60380
60357
  callback: async () => {
60381
- const railsEmail = await this.railsEmailRakeClient.getLatestEmail({
60358
+ const railsEmail = await this.railsEmailClient.getLatestEmail({
60382
60359
  ...messageSearchCriteria,
60383
60360
  receivedAfter: receivedAfter.toISOString(),
60384
60361
  });
@@ -60387,7 +60364,7 @@ class RailsEmailUtils {
60387
60364
  return this.convertRailsEmailToFormattedList(railsEmail);
60388
60365
  },
60389
60366
  condition: async () => {
60390
- const emails = await this.railsEmailRakeClient.listEmails({
60367
+ const emails = await this.railsEmailClient.listEmails({
60391
60368
  ...messageSearchCriteria,
60392
60369
  receivedAfter: receivedAfter.toISOString(),
60393
60370
  });
@@ -60406,7 +60383,7 @@ class RailsEmailUtils {
60406
60383
  findOtpFromEmail = async ({ email, subjectSubstring = OTP_EMAIL_PATTERN, timeout = 10_000, receivedAfter = new Date(), expectedEmailCount = 1, }) => {
60407
60384
  const otp = await this.neetoPlaywrightUtilities.executeRecursively({
60408
60385
  callback: async () => {
60409
- const railsEmail = await this.railsEmailRakeClient.getLatestEmail({
60386
+ const railsEmail = await this.railsEmailClient.getLatestEmail({
60410
60387
  to: email,
60411
60388
  subject: subjectSubstring,
60412
60389
  receivedAfter: receivedAfter.toISOString(),
@@ -60419,7 +60396,7 @@ class RailsEmailUtils {
60419
60396
  return formattedEmail.html.codes?.[0] || formattedEmail.text.codes?.[0];
60420
60397
  },
60421
60398
  condition: async () => {
60422
- const emails = await this.railsEmailRakeClient.listEmails({
60399
+ const emails = await this.railsEmailClient.listEmails({
60423
60400
  to: email,
60424
60401
  subject: subjectSubstring,
60425
60402
  receivedAfter: receivedAfter.toISOString(),
@@ -60433,7 +60410,7 @@ class RailsEmailUtils {
60433
60410
  getEmailAttachment = async (attachmentName, messageSearchCriteria = {}, { receivedAfter = new Date(new Date().valueOf() - 60 * 60 * 1000), expectedEmailCount = 1, timeout = 10_000, } = {}, shouldThrowErrorOnTimeout = true) => {
60434
60411
  const attachmentDetails = (await this.neetoPlaywrightUtilities.executeRecursively({
60435
60412
  callback: async () => {
60436
- const railsEmail = await this.railsEmailRakeClient.getLatestEmail({
60413
+ const railsEmail = await this.railsEmailClient.getLatestEmail({
60437
60414
  ...messageSearchCriteria,
60438
60415
  receivedAfter: receivedAfter.toISOString(),
60439
60416
  });
@@ -60450,7 +60427,7 @@ class RailsEmailUtils {
60450
60427
  };
60451
60428
  },
60452
60429
  condition: async () => {
60453
- const emails = await this.railsEmailRakeClient.listEmails({
60430
+ const emails = await this.railsEmailClient.listEmails({
60454
60431
  ...messageSearchCriteria,
60455
60432
  receivedAfter: receivedAfter.toISOString(),
60456
60433
  });
@@ -107252,7 +107229,35 @@ class ColorPickerUtils {
107252
107229
  };
107253
107230
  }
107254
107231
 
107232
+ const STATIC_ASSET_PATTERN = /\.(js|css|woff2?|ttf|eot|png|svg|ico|gif|webp)(\?.*)?$/;
107233
+ const assetCache = new Map();
107255
107234
  const commands = {
107235
+ context: async ({ context }, use) => {
107236
+ if (IS_DEV_ENV) {
107237
+ await context.route(STATIC_ASSET_PATTERN, async (route) => {
107238
+ const url = route.request().url();
107239
+ const hit = assetCache.get(url);
107240
+ if (hit)
107241
+ return route.fulfill(hit);
107242
+ try {
107243
+ const response = await route.fetch();
107244
+ const body = await response.body();
107245
+ const entry = {
107246
+ body,
107247
+ status: response.status(),
107248
+ headers: response.headers(),
107249
+ };
107250
+ if (response.ok())
107251
+ assetCache.set(url, entry);
107252
+ return route.fulfill(entry);
107253
+ }
107254
+ catch {
107255
+ return route.continue();
107256
+ }
107257
+ });
107258
+ }
107259
+ await use(context);
107260
+ },
107256
107261
  neetoPlaywrightUtilities: async ({ page, request, baseURL }, use) => {
107257
107262
  const commands = new CustomCommands(page, request, baseURL);
107258
107263
  await use(commands);
@@ -124970,6 +124975,31 @@ const generatePhoneNumberDetails = () => {
124970
124975
  return { flag: country.flag, name: country.name, code: country.code, number };
124971
124976
  };
124972
124977
 
124978
+ const DEFAULT_WARMUP_URLS = ["/login"];
124979
+ async function warmup({ urls = DEFAULT_WARMUP_URLS, timeout = 60_000, } = {}) {
124980
+ if (!IS_DEV_ENV)
124981
+ return;
124982
+ const { RAILS_SERVER_PORT, SUBDOMAIN = "spinkart" } = process.env;
124983
+ if (!RAILS_SERVER_PORT) {
124984
+ throw new Error("RAILS_SERVER_PORT is not defined in environment variables.");
124985
+ }
124986
+ const baseURL = `http://${SUBDOMAIN}.lvh.me:${RAILS_SERVER_PORT}`;
124987
+ const browser = await test.chromium.launch();
124988
+ const page = await browser.newPage();
124989
+ try {
124990
+ for (const url of urls) {
124991
+ const fullUrl = url.startsWith("http") ? url : `${baseURL}${url}`;
124992
+ await page.goto(fullUrl, {
124993
+ waitUntil: "networkidle", // eslint-disable-line playwright/no-networkidle
124994
+ timeout,
124995
+ });
124996
+ }
124997
+ }
124998
+ finally {
124999
+ await browser.close();
125000
+ }
125001
+ }
125002
+
124973
125003
  const CONFIG = {
124974
125004
  DIR: "/tmp/neeto-auth-web",
124975
125005
  LOG: "/tmp/neeto-auth-server.log",
@@ -125985,7 +126015,7 @@ exports.PROJECT_NAMES = PROJECT_NAMES;
125985
126015
  exports.PROJECT_TRANSLATIONS_PATH = PROJECT_TRANSLATIONS_PATH;
125986
126016
  exports.ROLES_SELECTORS = ROLES_SELECTORS;
125987
126017
  exports.ROUTES = ROUTES;
125988
- exports.RailsEmailRakeClient = RailsEmailRakeClient;
126018
+ exports.RailsEmailApiClient = RailsEmailApiClient;
125989
126019
  exports.RailsEmailUtils = RailsEmailUtils;
125990
126020
  exports.RoleApis = RoleApis;
125991
126021
  exports.RolesPage = RolesPage;
@@ -126087,5 +126117,6 @@ exports.stealthTest = stealth;
126087
126117
  exports.tableUtils = tableUtils;
126088
126118
  exports.toCamelCase = toCamelCase;
126089
126119
  exports.updateCredentials = updateCredentials;
126120
+ exports.warmup = warmup;
126090
126121
  exports.writeDataToFile = writeDataToFile;
126091
126122
  //# sourceMappingURL=index.cjs.js.map