@hasna/testers 0.0.40 → 0.0.41

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/dist/cli/index.js CHANGED
@@ -16940,17 +16940,29 @@ var init_secrets_resolver = () => {};
16940
16940
  function isSessionCookie(cookieName) {
16941
16941
  return !/(?:csrf|xsrf)/i.test(cookieName);
16942
16942
  }
16943
- function areCookiesFresh(persona) {
16943
+ function getCookieExpires(cookie) {
16944
+ if (typeof cookie.expires === "number" && Number.isFinite(cookie.expires)) {
16945
+ return cookie.expires;
16946
+ }
16947
+ if (typeof cookie.expires === "string") {
16948
+ const parsed = Number(cookie.expires);
16949
+ return Number.isFinite(parsed) ? parsed : null;
16950
+ }
16951
+ return null;
16952
+ }
16953
+ function hasFreshAuthCookies(persona) {
16944
16954
  if (!persona.auth?.cookies?.length)
16945
16955
  return false;
16946
16956
  const cookies = persona.auth.cookies;
16947
- if (!cookies.some((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)))) {
16957
+ const sessionCookies = cookies.filter((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)));
16958
+ if (sessionCookies.length === 0) {
16948
16959
  return false;
16949
16960
  }
16950
16961
  const now2 = Date.now() / 1000;
16951
- const hasFutureExpiry = cookies.some((c) => c.expires && c.expires > now2 + 60);
16952
- if (hasFutureExpiry)
16953
- return true;
16962
+ const expiringSessionCookies = sessionCookies.map(getCookieExpires).filter((expires) => expires !== null && expires > 0);
16963
+ if (expiringSessionCookies.length > 0) {
16964
+ return expiringSessionCookies.some((expires) => expires > now2 + 60);
16965
+ }
16954
16966
  const updatedAt = new Date(persona.updatedAt).getTime();
16955
16967
  return Date.now() - updatedAt < COOKIE_MAX_AGE_MS;
16956
16968
  }
@@ -17140,7 +17152,7 @@ async function ensurePersonaAuthenticated(page, persona, baseUrl) {
17140
17152
  if (!persona.auth) {
17141
17153
  return { success: true, method: "none" };
17142
17154
  }
17143
- if (areCookiesFresh(persona)) {
17155
+ if (hasFreshAuthCookies(persona)) {
17144
17156
  const restored = await restoreCookies(page, persona);
17145
17157
  if (restored) {
17146
17158
  return { success: true, method: "cookies" };
@@ -94025,7 +94037,7 @@ import chalk6 from "chalk";
94025
94037
  // package.json
94026
94038
  var package_default = {
94027
94039
  name: "@hasna/testers",
94028
- version: "0.0.40",
94040
+ version: "0.0.41",
94029
94041
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
94030
94042
  type: "module",
94031
94043
  main: "dist/index.js",
@@ -95752,6 +95764,40 @@ function formatProdDebugPlan(plan) {
95752
95764
  `);
95753
95765
  }
95754
95766
 
95767
+ // src/lib/persona-redaction.ts
95768
+ function stringKeys(value) {
95769
+ return value ? Object.keys(value).sort() : [];
95770
+ }
95771
+ function cookieNames(cookies) {
95772
+ if (!cookies)
95773
+ return [];
95774
+ return cookies.map((cookie) => cookie.name).filter((name) => typeof name === "string" && name.length > 0);
95775
+ }
95776
+ function redactPersona(persona) {
95777
+ if (!persona.auth)
95778
+ return { ...persona, auth: null };
95779
+ const names = cookieNames(persona.auth.cookies);
95780
+ const headerNames = stringKeys(persona.auth.headers);
95781
+ return {
95782
+ ...persona,
95783
+ auth: {
95784
+ emailConfigured: Boolean(persona.auth.email),
95785
+ passwordConfigured: Boolean(persona.auth.password),
95786
+ loginPath: persona.auth.loginPath,
95787
+ strategy: persona.auth.strategy,
95788
+ cookiesConfigured: names.length > 0,
95789
+ cookieCount: names.length,
95790
+ cookieNames: names,
95791
+ headersConfigured: headerNames.length > 0,
95792
+ headerNames,
95793
+ customScriptConfigured: Boolean(persona.auth.customScript)
95794
+ }
95795
+ };
95796
+ }
95797
+ function redactPersonas(personas) {
95798
+ return personas.map(redactPersona);
95799
+ }
95800
+
95755
95801
  // src/cli/index.tsx
95756
95802
  init_projects();
95757
95803
  init_personas();
@@ -100783,7 +100829,7 @@ personaCmd.command("list").description("List personas").option("--project <id>",
100783
100829
  globalOnly: opts.global ? true : undefined
100784
100830
  });
100785
100831
  if (opts.json) {
100786
- log(JSON.stringify(personas, null, 2));
100832
+ log(JSON.stringify(redactPersonas(personas), null, 2));
100787
100833
  return;
100788
100834
  }
100789
100835
  if (personas.length === 0) {
package/dist/index.js CHANGED
@@ -15499,17 +15499,29 @@ var COOKIE_MAX_AGE_MS = 60 * 60 * 1000;
15499
15499
  function isSessionCookie(cookieName) {
15500
15500
  return !/(?:csrf|xsrf)/i.test(cookieName);
15501
15501
  }
15502
- function areCookiesFresh(persona) {
15502
+ function getCookieExpires(cookie) {
15503
+ if (typeof cookie.expires === "number" && Number.isFinite(cookie.expires)) {
15504
+ return cookie.expires;
15505
+ }
15506
+ if (typeof cookie.expires === "string") {
15507
+ const parsed = Number(cookie.expires);
15508
+ return Number.isFinite(parsed) ? parsed : null;
15509
+ }
15510
+ return null;
15511
+ }
15512
+ function hasFreshAuthCookies(persona) {
15503
15513
  if (!persona.auth?.cookies?.length)
15504
15514
  return false;
15505
15515
  const cookies = persona.auth.cookies;
15506
- if (!cookies.some((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)))) {
15516
+ const sessionCookies = cookies.filter((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)));
15517
+ if (sessionCookies.length === 0) {
15507
15518
  return false;
15508
15519
  }
15509
15520
  const now2 = Date.now() / 1000;
15510
- const hasFutureExpiry = cookies.some((c) => c.expires && c.expires > now2 + 60);
15511
- if (hasFutureExpiry)
15512
- return true;
15521
+ const expiringSessionCookies = sessionCookies.map(getCookieExpires).filter((expires) => expires !== null && expires > 0);
15522
+ if (expiringSessionCookies.length > 0) {
15523
+ return expiringSessionCookies.some((expires) => expires > now2 + 60);
15524
+ }
15513
15525
  const updatedAt = new Date(persona.updatedAt).getTime();
15514
15526
  return Date.now() - updatedAt < COOKIE_MAX_AGE_MS;
15515
15527
  }
@@ -15699,7 +15711,7 @@ async function ensurePersonaAuthenticated(page, persona, baseUrl) {
15699
15711
  if (!persona.auth) {
15700
15712
  return { success: true, method: "none" };
15701
15713
  }
15702
- if (areCookiesFresh(persona)) {
15714
+ if (hasFreshAuthCookies(persona)) {
15703
15715
  const restored = await restoreCookies(page, persona);
15704
15716
  if (restored) {
15705
15717
  return { success: true, method: "cookies" };
@@ -6,6 +6,7 @@ export interface LoginResult {
6
6
  method: "cookies" | "login" | "none";
7
7
  error?: string;
8
8
  }
9
+ export declare function hasFreshAuthCookies(persona: Persona): boolean;
9
10
  /**
10
11
  * Perform login using a raw AuthConfig (e.g. from scenario.authConfig or an auth preset).
11
12
  * Resolves credentials via resolveCredential() supporting @secrets: and $ENV references.
@@ -1 +1 @@
1
- {"version":3,"file":"persona-auth.d.ts","sourceRoot":"","sources":["../../src/lib/persona-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMjD,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+OD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACvG,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAsBtB"}
1
+ {"version":3,"file":"persona-auth.d.ts","sourceRoot":"","sources":["../../src/lib/persona-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMjD,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkBD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAsB7D;AA2ND;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACvG,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,WAAW,CAAC,CAsBtB"}
@@ -0,0 +1,19 @@
1
+ import type { Persona } from "../types/index.js";
2
+ export interface RedactedPersonaAuth {
3
+ emailConfigured: boolean;
4
+ passwordConfigured: boolean;
5
+ loginPath: string;
6
+ strategy: string;
7
+ cookiesConfigured: boolean;
8
+ cookieCount: number;
9
+ cookieNames: string[];
10
+ headersConfigured: boolean;
11
+ headerNames: string[];
12
+ customScriptConfigured: boolean;
13
+ }
14
+ export type RedactedPersona = Omit<Persona, "auth"> & {
15
+ auth: RedactedPersonaAuth | null;
16
+ };
17
+ export declare function redactPersona(persona: Persona): RedactedPersona;
18
+ export declare function redactPersonas(personas: Persona[]): RedactedPersona[];
19
+ //# sourceMappingURL=persona-redaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persona-redaction.d.ts","sourceRoot":"","sources":["../../src/lib/persona-redaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,sBAAsB,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG;IACpD,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAClC,CAAC;AAaF,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAoB/D;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,eAAe,EAAE,CAErE"}
package/dist/mcp/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "@hasna/testers",
55
- version: "0.0.40",
55
+ version: "0.0.41",
56
56
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
57
57
  type: "module",
58
58
  main: "dist/index.js",
@@ -20048,17 +20048,29 @@ var init_secrets_resolver = () => {};
20048
20048
  function isSessionCookie(cookieName) {
20049
20049
  return !/(?:csrf|xsrf)/i.test(cookieName);
20050
20050
  }
20051
- function areCookiesFresh(persona) {
20051
+ function getCookieExpires(cookie) {
20052
+ if (typeof cookie.expires === "number" && Number.isFinite(cookie.expires)) {
20053
+ return cookie.expires;
20054
+ }
20055
+ if (typeof cookie.expires === "string") {
20056
+ const parsed = Number(cookie.expires);
20057
+ return Number.isFinite(parsed) ? parsed : null;
20058
+ }
20059
+ return null;
20060
+ }
20061
+ function hasFreshAuthCookies(persona) {
20052
20062
  if (!persona.auth?.cookies?.length)
20053
20063
  return false;
20054
20064
  const cookies = persona.auth.cookies;
20055
- if (!cookies.some((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)))) {
20065
+ const sessionCookies = cookies.filter((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)));
20066
+ if (sessionCookies.length === 0) {
20056
20067
  return false;
20057
20068
  }
20058
20069
  const now2 = Date.now() / 1000;
20059
- const hasFutureExpiry = cookies.some((c) => c.expires && c.expires > now2 + 60);
20060
- if (hasFutureExpiry)
20061
- return true;
20070
+ const expiringSessionCookies = sessionCookies.map(getCookieExpires).filter((expires) => expires !== null && expires > 0);
20071
+ if (expiringSessionCookies.length > 0) {
20072
+ return expiringSessionCookies.some((expires) => expires > now2 + 60);
20073
+ }
20062
20074
  const updatedAt = new Date(persona.updatedAt).getTime();
20063
20075
  return Date.now() - updatedAt < COOKIE_MAX_AGE_MS;
20064
20076
  }
@@ -20248,7 +20260,7 @@ async function ensurePersonaAuthenticated(page, persona, baseUrl) {
20248
20260
  if (!persona.auth) {
20249
20261
  return { success: true, method: "none" };
20250
20262
  }
20251
- if (areCookiesFresh(persona)) {
20263
+ if (hasFreshAuthCookies(persona)) {
20252
20264
  const restored = await restoreCookies(page, persona);
20253
20265
  if (restored) {
20254
20266
  return { success: true, method: "cookies" };
@@ -53463,6 +53475,40 @@ var init_workflow_agent = __esm(() => {
53463
53475
  init_runner();
53464
53476
  });
53465
53477
 
53478
+ // src/lib/persona-redaction.ts
53479
+ function stringKeys(value) {
53480
+ return value ? Object.keys(value).sort() : [];
53481
+ }
53482
+ function cookieNames(cookies) {
53483
+ if (!cookies)
53484
+ return [];
53485
+ return cookies.map((cookie) => cookie.name).filter((name21) => typeof name21 === "string" && name21.length > 0);
53486
+ }
53487
+ function redactPersona(persona) {
53488
+ if (!persona.auth)
53489
+ return { ...persona, auth: null };
53490
+ const names = cookieNames(persona.auth.cookies);
53491
+ const headerNames = stringKeys(persona.auth.headers);
53492
+ return {
53493
+ ...persona,
53494
+ auth: {
53495
+ emailConfigured: Boolean(persona.auth.email),
53496
+ passwordConfigured: Boolean(persona.auth.password),
53497
+ loginPath: persona.auth.loginPath,
53498
+ strategy: persona.auth.strategy,
53499
+ cookiesConfigured: names.length > 0,
53500
+ cookieCount: names.length,
53501
+ cookieNames: names,
53502
+ headersConfigured: headerNames.length > 0,
53503
+ headerNames,
53504
+ customScriptConfigured: Boolean(persona.auth.customScript)
53505
+ }
53506
+ };
53507
+ }
53508
+ function redactPersonas(personas) {
53509
+ return personas.map(redactPersona);
53510
+ }
53511
+
53466
53512
  // src/db/environments.ts
53467
53513
  var exports_environments = {};
53468
53514
  __export(exports_environments, {
@@ -86939,7 +86985,7 @@ function buildServer() {
86939
86985
  authPassword,
86940
86986
  authLoginPath
86941
86987
  });
86942
- return json3(persona);
86988
+ return json3(redactPersona(persona));
86943
86989
  } catch (error40) {
86944
86990
  return errorResponse(error40);
86945
86991
  }
@@ -86951,7 +86997,7 @@ function buildServer() {
86951
86997
  }, async ({ projectId, enabled, globalOnly }) => {
86952
86998
  try {
86953
86999
  const personas = listPersonas({ projectId, enabled, globalOnly });
86954
- return json3({ items: personas, total: personas.length });
87000
+ return json3({ items: redactPersonas(personas), total: personas.length });
86955
87001
  } catch (error40) {
86956
87002
  return errorResponse(error40);
86957
87003
  }
@@ -86966,7 +87012,7 @@ function buildServer() {
86966
87012
  const db2 = getDatabase();
86967
87013
  const scenarioRows = db2.query("SELECT id, short_id, name FROM scenarios WHERE persona_id = ?").all(persona.id);
86968
87014
  return json3({
86969
- ...persona,
87015
+ ...redactPersona(persona),
86970
87016
  usedByScenarios: scenarioRows.map((r2) => ({ id: r2.id, shortId: r2.short_id, name: r2.name }))
86971
87017
  });
86972
87018
  } catch (error40) {
@@ -86989,7 +87035,7 @@ function buildServer() {
86989
87035
  }, async ({ id, version: version2, ...updates }) => {
86990
87036
  try {
86991
87037
  const persona = updatePersona(id, updates, version2);
86992
- return json3(persona);
87038
+ return json3(redactPersona(persona));
86993
87039
  } catch (error40) {
86994
87040
  return errorResponse(error40, {
86995
87041
  fetchCurrent: () => getPersona(id)
@@ -87020,7 +87066,7 @@ function buildServer() {
87020
87066
  if (!scenario)
87021
87067
  return errorResponse(notFoundErr(scenarioId, "Scenario"));
87022
87068
  const updated = updateScenario(scenario.id, { personaId: persona.id }, scenario.version);
87023
- return json3({ ...updated, attachedPersona: persona });
87069
+ return json3({ ...updated, attachedPersona: redactPersona(persona) });
87024
87070
  } catch (error40) {
87025
87071
  return errorResponse(error40);
87026
87072
  }
@@ -87418,7 +87464,7 @@ function buildServer() {
87418
87464
  projectId: scenario.projectId ?? undefined,
87419
87465
  personaId: persona.id
87420
87466
  });
87421
- return json3({ ...clone2, attachedPersona: persona, clonedFrom: scenario.id });
87467
+ return json3({ ...clone2, attachedPersona: redactPersona(persona), clonedFrom: scenario.id });
87422
87468
  } catch (e2) {
87423
87469
  return errorResponse(e2);
87424
87470
  }
@@ -87683,7 +87729,7 @@ Context: ${context2}` : ""}`,
87683
87729
  const updated = syncPersonaFromContact2(persona.id);
87684
87730
  if (!updated)
87685
87731
  return json3({ synced: false, message: "No linked contact found or no changes needed" });
87686
- return json3({ synced: true, persona: updated });
87732
+ return json3({ synced: true, persona: redactPersona(updated) });
87687
87733
  } catch (e2) {
87688
87734
  return errorResponse(e2);
87689
87735
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgHpE,wBAAgB,WAAW,IAAI,SAAS,CA2+EvC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiHpE,wBAAgB,WAAW,IAAI,SAAS,CA2+EvC"}
@@ -46910,7 +46910,7 @@ import { join as join14 } from "path";
46910
46910
  // package.json
46911
46911
  var package_default = {
46912
46912
  name: "@hasna/testers",
46913
- version: "0.0.40",
46913
+ version: "0.0.41",
46914
46914
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
46915
46915
  type: "module",
46916
46916
  main: "dist/index.js",
@@ -48543,17 +48543,29 @@ var COOKIE_MAX_AGE_MS = 60 * 60 * 1000;
48543
48543
  function isSessionCookie(cookieName) {
48544
48544
  return !/(?:csrf|xsrf)/i.test(cookieName);
48545
48545
  }
48546
- function areCookiesFresh(persona) {
48546
+ function getCookieExpires(cookie) {
48547
+ if (typeof cookie.expires === "number" && Number.isFinite(cookie.expires)) {
48548
+ return cookie.expires;
48549
+ }
48550
+ if (typeof cookie.expires === "string") {
48551
+ const parsed = Number(cookie.expires);
48552
+ return Number.isFinite(parsed) ? parsed : null;
48553
+ }
48554
+ return null;
48555
+ }
48556
+ function hasFreshAuthCookies(persona) {
48547
48557
  if (!persona.auth?.cookies?.length)
48548
48558
  return false;
48549
48559
  const cookies = persona.auth.cookies;
48550
- if (!cookies.some((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)))) {
48560
+ const sessionCookies = cookies.filter((cookie) => ("name" in cookie) && isSessionCookie(String(cookie.name)));
48561
+ if (sessionCookies.length === 0) {
48551
48562
  return false;
48552
48563
  }
48553
48564
  const now2 = Date.now() / 1000;
48554
- const hasFutureExpiry = cookies.some((c) => c.expires && c.expires > now2 + 60);
48555
- if (hasFutureExpiry)
48556
- return true;
48565
+ const expiringSessionCookies = sessionCookies.map(getCookieExpires).filter((expires) => expires !== null && expires > 0);
48566
+ if (expiringSessionCookies.length > 0) {
48567
+ return expiringSessionCookies.some((expires) => expires > now2 + 60);
48568
+ }
48557
48569
  const updatedAt = new Date(persona.updatedAt).getTime();
48558
48570
  return Date.now() - updatedAt < COOKIE_MAX_AGE_MS;
48559
48571
  }
@@ -48743,7 +48755,7 @@ async function ensurePersonaAuthenticated(page, persona, baseUrl) {
48743
48755
  if (!persona.auth) {
48744
48756
  return { success: true, method: "none" };
48745
48757
  }
48746
- if (areCookiesFresh(persona)) {
48758
+ if (hasFreshAuthCookies(persona)) {
48747
48759
  const restored = await restoreCookies(page, persona);
48748
48760
  if (restored) {
48749
48761
  return { success: true, method: "cookies" };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/testers",
3
- "version": "0.0.40",
3
+ "version": "0.0.41",
4
4
  "description": "AI-powered QA testing CLI — spawns cheap AI agents to test web apps with headless browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",