Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
1.5 MiB
SCRATCHPAD — Invoice Template JSON AST Renderer Cutover
Context
- Plan folder:
ee/docs/plans/2026-02-12-invoice-template-json-ast-renderer-cutover/ - Date started:
2026-02-12 - Status: Draft
- Supersedes architecture direction in:
ee/docs/plans/2026-02-09-invoice-template-designer-preview-workspace/
Key Decisions
- Treat invoice templates as declarative data (AST), not executable code.
- Keep future calculation/grouping flexibility via declarative transform specs.
- Add optional
strategyIdhooks only through explicit allowlist resolution. - Use one shared React renderer for preview and backend PDF generation.
- Keep migration effort minimal: no custom tenant templates exist that require backfill.
Scope Boundaries
In scope:
- AST schema + evaluator + renderer cutover.
- Preview + save/load + PDF pipeline updates.
- Deletion of compiler and custom executor layers.
Out of scope:
- Arbitrary per-template code execution.
- Complex migration tooling for existing tenant custom templates.
Existing Code Paths Reviewed
- Preview pipeline:
packages/billing/src/actions/invoiceTemplatePreview.tspackages/billing/src/actions/invoiceTemplatePreviewCache.ts
- Designer/editor coupling:
packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsxpackages/billing/src/components/invoice-designer/DesignerVisualWorkspace.tsxpackages/billing/src/components/invoice-designer/compiler/guiIr.tspackages/billing/src/components/invoice-designer/compiler/assemblyScriptGenerator.tspackages/billing/src/components/invoice-designer/compiler/diagnostics.ts
- Runtime + rendering:
packages/billing/src/lib/invoice-renderer/wasm-executor.tspackages/billing/src/lib/invoice-renderer/quickjs-executor.tspackages/billing/src/lib/invoice-renderer/host-functions.tspackages/billing/src/lib/invoice-renderer/layout-renderer.ts
- Compile orchestration:
packages/billing/src/lib/invoice-template-compiler/assemblyScriptCompile.ts
- PDF path:
server/src/services/pdf-generation.service.ts
- Persistence/types:
packages/billing/src/models/invoice.tspackages/types/src/interfaces/invoice.interfaces.tsserver/src/interfaces/invoice.interfaces.ts
Risks To Watch
- Parity drift while replacing compile/runtime pipeline.
- AST transform model underpowered for future grouping/calc edge cases.
- Strategy hook design becoming an unbounded execution escape hatch.
Notes for Implementation Phase
- Start with pure declarative transform operations.
- Introduce strategy hooks only where declarative operations are insufficient.
- Keep strategy registry narrow and explicit.
- Preserve tenant-safe data access boundaries.
Verification Commands
- Plan lint/shape:
python3 scripts/validate_plan.py ee/docs/plans/2026-02-12-invoice-template-json-ast-renderer-cutover
- Spot-check references:
rg -n "guiIr|assemblyScriptGenerator|assemblyScriptCompile|wasm-executor|quickjs-executor|host-functions" packages/billing/src server/src
Open Questions Tracking
- Final
Codetab behavior for GUI templates (AST JSON read-only vs hidden). - Initial strategy hook set for MVP.
- MVP expectation for layout verification under AST renderer path.
Progress Log
2026-02-12 — F001 implemented
- Implemented shared AST type system in
packages/types/src/lib/invoice-template-ast.ts. - Added explicit versioning root model:
INVOICE_TEMPLATE_AST_VERSION = 1InvoiceTemplateAstwithkind,version,metadata,styles,bindings,transforms,layout.
- Added discriminated node model for layout tree:
document,section,stack,text,field,image,divider,table,totals.
- Added style model:
- token catalog and class declarations via
InvoiceTemplateStyleCatalog. - node style references via
InvoiceTemplateNodeStyleRef.
- token catalog and class declarations via
- Added binding model:
- value and collection binding catalogs, binding refs, and value expression union.
- Added transform model shape:
filter,sort,group,aggregate,computed-field,totals-compose.- transform base includes optional
strategyIdas schema surface for later allowlisted hook implementation.
- Exported new AST type module from
packages/types/src/index.ts.
Rationale:
@alga-psa/typesis the correct shared location for contracts consumed by both app and server paths.- Defining versioned AST and explicit discriminated unions up front reduces ambiguity before schema/runtime evaluator implementation.
Commands run:
npm -w @alga-psa/types run build(fails with existing TS2209 rootDir/export-map ambiguity in this workspace).npx tsc -p packages/types/tsconfig.json --noEmit(same existing TS2209 issue).npm -w @alga-psa/types test(fails on existing unrelatedsrc/interfaces/barrel.test.tsstraytax.interfacesexport).
Gotchas:
@alga-psa/typespackage currently has baseline build/test failures unrelated to AST changes; continue with targeted feature implementation and track failures in commit notes.
2026-02-12 — F002 implemented
- Added runtime AST schema parser in
packages/billing/src/lib/invoice-template-ast/schema.ts. - Implemented strict Zod schemas for:
- AST root (
kind,version,metadata,styles,bindings,transforms,layout), - recursive layout nodes,
- expressions, predicates, and transform operation payloads.
- AST root (
- Added structured validation model:
InvoiceTemplateAstValidationError(code,path,message),validateInvoiceTemplateAst(input)returning success/error union,parseInvoiceTemplateAst(input)throwing a consolidated message for invalid payloads.
- Added targeted validator tests in
packages/billing/src/lib/invoice-template-ast/schema.test.ts.
Rationale:
- Runtime schema validation is required before evaluator/renderer cutover so preview/PDF pipelines can fail fast with actionable diagnostics.
- Strict object validation prevents accidental schema drift and catches unknown fields early.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts(pass).
2026-02-12 — F003 implemented
- Extended AST node model with explicit repeatable region support:
- Added
dynamic-tablenode type inpackages/types/src/lib/invoice-template-ast.ts. - Added
InvoiceTemplateRepeatRegionBindingwith requiredsourceBindinganditemBinding.
- Added
- Updated runtime validator in
packages/billing/src/lib/invoice-template-ast/schema.ts:- Added
dynamic-tableschema variant. - Enforced required repeat metadata (
repeat.sourceBinding,repeat.itemBinding).
- Added
- Added/extended tests in
packages/billing/src/lib/invoice-template-ast/schema.test.tsto ensure:- missing repeat binding metadata fails with structured path-aware errors,
- valid dynamic table payload passes.
Rationale:
- Repeatable line-item regions should be first-class AST semantics, not implicit conventions on generic tables.
- Explicit repeat metadata is required for deterministic evaluator behavior in upcoming features.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts(pass).
2026-02-12 — F004 implemented
- Completed declarative transform operation representation in AST:
- Existing transform union now enforced as strict runtime schema in
packages/billing/src/lib/invoice-template-ast/schema.ts. - Supported operations:
filter,sort,group,aggregate,computed-field,totals-compose.
- Existing transform union now enforced as strict runtime schema in
- Strengthened runtime payload constraints:
transforms.operationsmust be non-empty.sort.keys,aggregate.aggregations,computed-field.fields,totals-compose.totalsmust be non-empty.- logical predicates require at least one condition.
- Added transform-shape tests in
packages/billing/src/lib/invoice-template-ast/schema.test.ts:- invalid empty
sort.keysrejected with structured path errors, - valid composed filter/sort/group/aggregate/computed payload accepted.
- invalid empty
Rationale:
- This locks in declarative transform expressiveness before evaluator implementation and catches malformed transform configs early.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts(pass).
2026-02-12 — F005 implemented
- Confirmed/retained
strategyId?: stringon transform operation base model in:packages/types/src/lib/invoice-template-ast.tspackages/billing/src/lib/invoice-template-ast/schema.ts
- Added runtime acceptance test in
packages/billing/src/lib/invoice-template-ast/schema.test.tsensuringstrategyIdis valid on grouped/aggregate transforms.
Rationale:
- Declares extension points in AST shape now, while deferring actual strategy resolution/execution to allowlisted registry implementation.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts(pass).
2026-02-12 — F006 implemented
- Added allowlisted strategy registry in
packages/billing/src/lib/invoice-template-ast/strategies.ts. - Implemented explicit APIs:
listAllowlistedInvoiceTemplateStrategyIds()isAllowlistedInvoiceTemplateStrategy(strategyId)resolveInvoiceTemplateStrategy(strategyId)executeInvoiceTemplateStrategy(strategyId, input)
- Added strict unknown-strategy rejection with typed error:
InvoiceTemplateStrategyResolutionError- error code:
STRATEGY_NOT_ALLOWLISTED.
- Seeded initial allowlisted strategies for upcoming evaluator usage:
custom-group-keycustom-aggregate
- Added unit tests in
packages/billing/src/lib/invoice-template-ast/strategies.test.tsfor known/unknown strategy behavior.
Rationale:
- Strategy execution must be explicit and allowlisted to preserve non-arbitrary-code security posture while enabling controlled extensibility.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts(pass).
2026-02-12 — F007 implemented
- Added shared AST evaluator in
packages/billing/src/lib/invoice-template-ast/evaluator.ts. - Implemented declarative transform execution over invoice collections:
filtervia predicate evaluationsortvia stable multi-key orderinggroupwith optional strategy hook supportaggregateforsum/count/avg/min/max(overall + per-group aggregates)computed-fieldfor derived numeric expressionstotals-composefor totals from aggregate refs/computation expressions
- Evaluator exports:
evaluateInvoiceTemplateAst(ast, invoiceData)evaluateAstTransforms(ast, invoiceData)alias- typed result with
output,groups,aggregates,totals, and resolvedbindings.
- Added evaluator test suite in
packages/billing/src/lib/invoice-template-ast/evaluator.test.ts.
Rationale:
- Central evaluator module is the core abstraction needed to unify preview and PDF behavior around AST data-shaping semantics.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts(pass).
2026-02-12 — F008 implemented
- Added deterministic output normalization in evaluator (
packages/billing/src/lib/invoice-template-ast/evaluator.ts):- recursive plain-object key sorting before returning
output,groups,aggregates,totals, andbindings. - stable sort implementation already used index tie-break to preserve deterministic ordering.
- recursive plain-object key sorting before returning
- Added explicit determinism test in
packages/billing/src/lib/invoice-template-ast/evaluator.test.ts:- repeated evaluation of identical AST+input yields byte-for-byte identical JSON payload.
Rationale:
- Deterministic evaluation output is required for reproducible preview/PDF parity checks and reliable caching/verification logic.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/evaluator.test.ts(pass).
2026-02-12 — F009 implemented
- Upgraded evaluator failure handling to structured error model in
packages/billing/src/lib/invoice-template-ast/evaluator.ts. - Added
InvoiceTemplateEvaluationIssueand enrichedInvoiceTemplateEvaluationErrorwith:- canonical error code,
- operationId (where applicable),
- issue list payload for multi-error contexts.
- Covered required failure classes:
SCHEMA_VALIDATION_FAILED(integrated runtime schema validation before evaluation),MISSING_BINDING(undefined source binding),UNKNOWN_STRATEGY/STRATEGY_EXECUTION_FAILED,INVALID_TRANSFORM_INPUT,INVALID_OPERAND(e.g., unresolved aggregate references).
- Added evaluator tests asserting explicit codes and structured issue payloads in
packages/billing/src/lib/invoice-template-ast/evaluator.test.ts.
Rationale:
- Preview/PDF pipeline error surfacing needs explicit, machine-readable evaluator errors rather than ad hoc thrown strings.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/evaluator.test.ts(pass).
2026-02-12 — F010 implemented
- Added shared React renderer module in
packages/billing/src/lib/invoice-template-ast/react-renderer.tsx. - Implemented renderer component + server-safe static markup helper:
InvoiceTemplateAstRendererrenderEvaluatedInvoiceTemplateAst(ast, evaluation) -> { html, css }
- Supported node rendering for:
document,section,stack,text,field,image,divider,table,dynamic-table,totals.
- Implemented expression/value resolution against evaluator bindings and row scope.
- Implemented class/token CSS generation from AST style catalog.
- Added renderer tests in
packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsxfor:- static text/field/table/totals rendering,
- style/class consistency,
- unsafe content escaping in output HTML.
Rationale:
- This is the shared rendering surface required for both interactive preview and backend PDF paths.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts(pass).
2026-02-12 — F011 implemented
- Added server-side HTML document wrapper helper in
packages/billing/src/lib/invoice-template-ast/server-render.ts. - Implemented
renderInvoiceTemplateAstHtmlDocument(ast, evaluation, options)to:- call the shared React renderer (
renderEvaluatedInvoiceTemplateAst), - wrap output in a complete
<!doctype html><html><head><body>document, - include generated CSS + optional additional CSS,
- support configurable title/body class with HTML escaping.
- call the shared React renderer (
- Added unit test
packages/billing/src/lib/invoice-template-ast/server-render.test.tsvalidating complete wrapper output for headless PDF use.
Rationale:
- PDF pipeline needs a full HTML document entrypoint, but should reuse the exact same AST React renderer output to maintain parity.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/*.test.ts packages/billing/src/lib/invoice-template-ast/*.test.tsx(pass).
2026-02-12 — F012 implemented
- Added designer workspace -> AST exporter in:
packages/billing/src/components/invoice-designer/ast/workspaceAst.ts- with helper
exportWorkspaceToInvoiceTemplateAst(workspace)and JSON helper.
- Export mapping now emits versioned
InvoiceTemplateAstdirectly from visual workspace (no IR step). - Updated
InvoiceTemplateEditorvisual save/export path (packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx):- replaced IR/AssemblyScript generation in code-view projection with AST JSON projection,
- on save with GUI designer enabled, persists canonical
templateAstpayload directly from workspace export, - keeps legacy
assemblyScriptSourcecomment persistence only as temporary compatibility scaffolding.
- Added exporter tests:
packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts.
Rationale:
- This establishes AST as the designer export artifact and removes compiler-IR coupling from the visual export path.
Commands run:
npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts(pass).npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx(fails due existing React 19 test harness issue:React.act is not a functionfrom@testing-library/react/react-dom-test-utilsin this environment).
2026-02-12 — F013 implemented
- Extended AST utility module (
packages/billing/src/components/invoice-designer/ast/workspaceAst.ts) with import/hydration support:importInvoiceTemplateAstToWorkspace(ast)builds designer workspace snapshot from persisted AST.
- Updated
InvoiceTemplateEditorhydration flow (packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx):- prefers
templateAstpayload hydration when available, - falls back to legacy embedded-source/localStorage workspace hydration only if AST hydration is unavailable or fails.
- prefers
- Added AST import coverage in
packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts. - Added editor integration expectation for
templateAsthydration inpackages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx(execution blocked by existing act-compat issue in current test harness).
Rationale:
- Save/reopen flow should hydrate editor state from canonical AST representation as cutover progresses.
Commands run:
npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts(pass).npx vitest run packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx(editor test files fail due existingReact.act is not a functionharness issue).
2026-02-12 — F014 implemented
- Confirmed
InvoiceTemplateEditorno longer imports or calls:extractInvoiceDesignerIrgenerateAssemblyScriptFromIr
- Save path now uses AST exporter (
exportWorkspaceToInvoiceTemplateAst) instead of IR/compiler generation.
Verification:
rg -n "extractInvoiceDesignerIr|generateAssemblyScriptFromIr" packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.tsx(no matches).
2026-02-12 — F015 implemented
- Updated shared and server invoice template contracts to include canonical AST payload:
packages/types/src/interfaces/invoice.interfaces.tsserver/src/interfaces/invoice.interfaces.ts
- Contract updates:
- added
templateAst?: InvoiceTemplateAst | null - relaxed
assemblyScriptSourcefrom required to optional (assemblyScriptSource?: string) for cutover compatibility.
- added
- Added type contract test:
packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts- verifies
IInvoiceTemplateaccepts AST payload without requiring legacy AssemblyScript source.
Commands run:
npx vitest run packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts(pass).
2026-02-12 — F016 implemented
- Added DB migration for tenant template AST persistence:
server/migrations/20260212143000_add_template_ast_to_invoice_templates.cjs- introduces nullable
templateAstJSONB column oninvoice_templates.
- Updated template read/write repository/model paths:
packages/billing/src/actions/invoiceTemplates.tsgetInvoiceTemplatenow selectstemplateAst,saveInvoiceTemplatenow treatstemplateAstpayload as canonical and skips compile gating for AST templates.
packages/billing/src/models/invoice.ts- tenant template list path includes
templateAst, - upsert merge list includes
templateAst.
- tenant template list path includes
- Updated API schema contract:
server/src/lib/api/schemas/invoiceSchemas.tsassemblyScriptSourceoptional,templateAstoptional nullable object payload.
- Added wiring tests:
packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts.
Rationale:
- Persistence/read paths now treat AST as first-class template payload while keeping legacy fields for transition compatibility.
Commands run:
npx vitest run packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts(pass).npx vitest run packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts(pass).
2026-02-12 — F017 implemented
- Added AST-based standard template definitions:
packages/billing/src/lib/invoice-template-ast/standardTemplates.ts- includes
standard-defaultandstandard-detailedcanonical AST payloads.
- Added DB migration for standard template AST persistence:
server/migrations/20260212143500_add_template_ast_to_standard_invoice_templates.cjs
- Updated standard template read/update wiring:
packages/billing/src/models/invoice.tsnow selectstemplateAstfor standard templates and falls back to AST definitions by standard code.packages/billing/src/actions/invoiceTemplates.tsnow writes canonicaltemplateAstduringcompileStandardTemplateupdates.
- Added tests:
packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts- extended
packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.tsfor standard-template AST wiring assertions.
Rationale:
- Standard templates now have AST-native source representations, enabling unified renderer/evaluator behavior with tenant templates.
Commands run:
npx vitest run packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts(pass).
2026-02-12 — F018 implemented
- Rewrote authoritative preview execution path in
packages/billing/src/actions/invoiceTemplatePreview.ts:- replaced GUI IR + AssemblyScript compile + Wasm execution path inside
runAuthoritativeInvoiceTemplatePreview, - now exports workspace to AST (
exportWorkspaceToInvoiceTemplateAst), validates schema (validateInvoiceTemplateAst), evaluates transforms (evaluateInvoiceTemplateAst), and renders HTML/CSS via shared React renderer (renderEvaluatedInvoiceTemplateAst).
- replaced GUI IR + AssemblyScript compile + Wasm execution path inside
- Preview response semantics for this stage:
sourceHashnow hashes canonical AST JSON,generatedSourcenow carries AST JSON,- compile section is retained for compatibility but no longer performs compilation (
cacheHit=false, diagnostics reflect AST/evaluator issues).
- Updated integration coverage in
packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts:- now asserts AST validation+evaluator+renderer execution and rendered output presence,
- invocation adjusted to pass mocked auth/context args because
withAuthis mocked as identity in this suite.
Rationale:
- This completes the preview runtime cutover for authoritative rendering while preserving response shape compatibility for downstream UI wiring.
Commands run:
pnpm vitest packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(pass).pnpm vitest packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx(tests pass; run exits non-zero in this environment due pre-existing coverage temp dirserver/coverage/.tmpENOENT after reporting).
2026-02-12 — F019 implemented
- Preserved Sample/Existing source-selection semantics for preview UX after AST backend cutover.
- Added source-mode specific test coverage in pure preview state/status modules:
packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts- sample source validity now explicitly verified to depend on preview sample payload.
packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts- source toggle flow verifies sample selection is preserved across Sample <-> Existing transitions.
Rationale:
- These tests guard the source-selection UX contract independently of the compile/runtime pipeline internals.
Commands run:
pnpm vitest packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts(pass).pnpm vitest packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(test passes; command exits non-zero in this environment due existing coverage temp dir issue:server/coverage/.tmpENOENT).- Attempted targeted
DesignerVisualWorkspacecomponent source-switch tests; blocked by pre-existingReact.act is not a functioncompatibility issue in current React/testing-library stack.
2026-02-12 — F020 implemented
- Remapped preview pipeline phase semantics from
compile/render/verifytoshape/render/verifyin designer preview state and UI surface. - Updated preview state model and reducer:
packages/billing/src/components/invoice-designer/preview/previewSessionState.ts- renamed
compileStatus/compileError->shapeStatus/shapeError - phase enum now uses
'shape' | 'render' | 'verify'.
- Updated phase display derivation:
packages/billing/src/components/invoice-designer/preview/previewStatus.ts- status snapshot now tracks
shapeStatus.
- Updated
DesignerVisualWorkspacestatus wiring and UX copy:- dispatches/reads
shapephase state, - status label now reads
Shape, - loading text updated to
Shaping and rendering preview..., - automation IDs moved from
...preview-compile-*to...preview-shape-*for status/error/diagnostics/cache markers.
- dispatches/reads
- Updated related tests:
previewSessionState.test.tspreviewStatus.test.ts- string/automation-id expectations in
DesignerVisualWorkspace.test.tsxaligned toshapeterminology.
Rationale:
- Preview UX now reflects the AST pipeline's shaping step instead of a compiler phase.
Commands run:
pnpm vitest packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts(pass).
2026-02-12 — F021 implemented
- Retained and strengthened structured preview diagnostics with AST/evaluator context in
runAuthoritativeInvoiceTemplatePreview:packages/billing/src/actions/invoiceTemplatePreview.ts- expanded diagnostic payload with
kind,code,path, andoperationIdmetadata. - schema validation failures now emit
kind: 'schema'diagnostics with path/code context. - evaluator failures now emit
kind: 'evaluation'diagnostics with operation/path/code context. - non-evaluator runtime failures now emit
kind: 'runtime'diagnostics.
- Updated preview diagnostics rendering surface:
packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.tsx- diagnostics list now renders contextual
code/path/opmetadata alongside message severity.
- Added integration coverage for structured diagnostics:
packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts- validates schema diagnostic context mapping and evaluator diagnostic context mapping.
Rationale:
- Preview diagnostics now preserve machine-meaningful context needed for targeted AST/evaluator debugging without reverting to compiler-era error formats.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts(pass).
2026-02-12 — F022 implemented
- Updated server PDF generation invoice path to use AST evaluator + shared renderer output instead of Wasm execution in:
server/src/services/pdf-generation.service.ts
- Changes made:
- removed
getCompiledWasm,executeWasmTemplate, andrenderLayoutusage/imports from invoice PDF rendering flow, - now requires canonical
templateAston selected template, - evaluates AST with
evaluateInvoiceTemplateAst, - produces complete HTML document via
renderInvoiceTemplateAstHtmlDocumentfor Puppeteer PDF generation.
- removed
- Added wiring coverage:
packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts- asserts PDF service uses AST helper path and no longer references Wasm execution helpers.
Rationale:
- Backend invoice PDF generation now consumes the declarative AST rendering path and removes runtime dependence on Wasm executor in the PDF service.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(pass).
2026-02-12 — F023 implemented
- Aligned preview and PDF/server render paths onto shared AST evaluator/renderer modules.
- Updated template server-render action in:
packages/billing/src/actions/invoiceTemplates.tsrenderTemplateOnServerno longer executes Wasm; it now:- resolves template from tenant+standard template set,
- requires canonical
templateAst, - evaluates via
evaluateInvoiceTemplateAst, - renders via
renderEvaluatedInvoiceTemplateAst.
- Extended parity wiring assertions in:
packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts- verifies preview action, PDF service, and
renderTemplateOnServerall use AST evaluator/renderer stack.
Rationale:
- This ensures preview and both server-side rendering entry points share the same rendering core and reduces parity drift risk.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(pass).
2026-02-12 — F024 implemented
- Removed preview compile-cache/Wasm artifact cache logic from preview pipeline.
- Deleted cache module and its unit tests:
packages/billing/src/actions/invoiceTemplatePreviewCache.ts(deleted)packages/billing/src/actions/invoiceTemplatePreview.cache.test.ts(deleted)
- Updated preview action contract and implementation:
packages/billing/src/actions/invoiceTemplatePreview.ts- removed cache imports and cache key resolution,
- removed cached artifact lookup/set operations,
- removed
cacheHitfields from preview compile status payload, - removed preview input cache-bypass flag from authoritative preview path.
- Updated preview UI status behavior:
packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.tsx- removed cache-hit badge and cache-bypass request plumbing while preserving manual rerun behavior.
- Updated related tests and added explicit cache-removal wiring coverage:
packages/billing/src/actions/invoiceTemplatePreview.integration.test.tspackages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsxpackages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts(new).
Rationale:
- Preview execution no longer compiles or executes Wasm, so compile-artifact cache lifecycle is obsolete and removed.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts(pass).
2026-02-12 — F025 implemented
- Deleted PRD-listed legacy compiler/executor modules from billing package:
packages/billing/src/components/invoice-designer/compiler/guiIr.tspackages/billing/src/components/invoice-designer/compiler/assemblyScriptGenerator.tspackages/billing/src/components/invoice-designer/compiler/diagnostics.tspackages/billing/src/lib/invoice-template-compiler/assemblyScriptCompile.tspackages/billing/src/lib/invoice-renderer/wasm-executor.tspackages/billing/src/lib/invoice-renderer/quickjs-executor.tspackages/billing/src/lib/invoice-renderer/host-functions.ts
- Removed associated dead test/snapshot scaffolding tied to deleted modules.
- Reworked affected action paths to remove imports of deleted modules:
packages/billing/src/actions/invoiceTemplatePreview.tsnow only contains AST preview runtime path,packages/billing/src/actions/invoiceTemplates.tsno longer imports compiler helper module.
- Added explicit removal wiring test:
packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts.
Rationale:
- This removes the custom compiler/executor layer from billing runtime code and enforces absence via tests.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts(pass).
2026-02-12 — F026 implemented
- Removed save-time AssemblyScript compile and Wasm persistence behavior from invoice template actions:
packages/billing/src/actions/invoiceTemplates.ts
saveInvoiceTemplatenow persists template metadata directly (AST canonical) without compile gating.compileAndSaveTemplateretained as compatibility API shape but now performs direct metadata save (no compile command, no Wasm generation).compileStandardTemplatenow updatesassemblyScriptSource/templateAst/shaonly and no longer writes compiledwasmBinaryartifacts.- Updated startup sync behavior accordingly:
server/src/lib/startupTasks.tsno longer treats missingwasmBinaryas a recompilation trigger.
- Updated wiring tests to enforce no save-time compile path:
packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.tspackages/billing/src/actions/invoiceTemplateCompileParity.test.ts
Rationale:
- Template save/update behavior now reflects AST-as-data architecture and avoids compiler lifecycle during persistence.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts(pass).
2026-02-12 — F027 implemented
- Removed runtime dependency on
getCompiledWasmfor invoice rendering paths. - Active render entry points now use AST evaluator/renderer stack and do not fetch compiled Wasm:
packages/billing/src/actions/invoiceTemplates.ts(renderTemplateOnServer)server/src/services/pdf-generation.service.tspackages/billing/src/actions/invoiceTemplatePreview.ts
getCompiledWasmaction remains only as an explicit unsupported guard path and is not used by rendering flows.- Added/updated wiring assertions to prevent regressions:
packages/billing/src/actions/invoicePdfGenerationAstWiring.test.tspackages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts
Rationale:
- Invoice runtime rendering no longer depends on Wasm artifact retrieval lifecycle.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts(pass).
2026-02-12 — F028 implemented
- Defined and verified compatibility behavior where legacy template columns may coexist with canonical AST payloads.
- Runtime rendering paths now explicitly treat
templateAstas canonical and do not consume legacyassemblyScriptSource/wasmBinarycolumns:server/src/services/pdf-generation.service.tspackages/billing/src/actions/invoiceTemplates.ts(renderTemplateOnServer)
- Extended wiring coverage:
packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts- new assertion checks render-action block uses
template.templateAstand does not depend on legacy runtime columns.
Rationale:
- Legacy columns remain available as temporary scaffolding, but runtime cutover behavior is AST-first and deterministic.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts(pass).
2026-02-12 — F029 implemented
- Reinforced no-arbitrary-code security posture at runtime by exercising strategy allowlist enforcement through preview action integration.
- Added preview integration coverage for non-allowlisted strategy rejection:
packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts- mocks AST export with an invalid
strategyIdand asserts structuredUNKNOWN_STRATEGYevaluator diagnostics are returned.
- Existing strategy registry/evaluator guardrails remain in place:
- allowlist checks in
packages/billing/src/lib/invoice-template-ast/strategies.ts - evaluator rejection path in
packages/billing/src/lib/invoice-template-ast/evaluator.ts.
- allowlist checks in
Rationale:
- Strategy execution remains constrained to explicit allowlisted functions and rejects arbitrary IDs in runtime paths.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(pass).
2026-02-12 — F030 implemented
- Expanded evaluator unit coverage for transform semantics and edge behavior in:
packages/billing/src/lib/invoice-template-ast/evaluator.test.ts
- Added coverage for:
- explicit composition order behavior (
filter -> sort -> group -> aggregate), - empty-item edge case behavior for grouping/aggregate/totals composition outputs.
- explicit composition order behavior (
- Existing AST schema + strategy + evaluator unit suites now cover core transform semantics comprehensively.
Rationale:
- These tests harden deterministic transform semantics and prevent regressions in composition/edge-case handling.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts(pass).
2026-02-12 — F031 implemented
- Established integration coverage for AST-based preview pipeline in:
packages/billing/src/actions/invoiceTemplatePreview.integration.test.tspackages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts
- Covered integration behaviors include:
- end-to-end preview action success over AST validation -> evaluator -> renderer,
- schema diagnostic surfacing,
- evaluator diagnostic surfacing,
- strategy allowlist rejection surfaced through preview diagnostics,
- realistic invoice fixture rendering sanity via mapped invoice payload.
Rationale:
- Preview integration tests now exercise the AST pipeline directly without compiler/Wasm execution dependencies.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts(pass).pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts(pass).
2026-02-12 — F032 implemented
- Added integration-style coverage for shared AST renderer in server-side invoice render action:
packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts
- Coverage verifies:
- canonical
templateAstpayload renders HTML/CSS throughrenderTemplateOnServer, - missing AST payloads fail explicitly, preventing silent legacy runtime fallback.
- canonical
Rationale:
- PDF/server rendering path now has executable tests validating AST renderer behavior beyond static wiring assertions.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts(pass).
2026-02-12 — F033 implemented
- Added preview/PDF parity integration test:
packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts
- Test exercises both render entry points with identical AST + invoice fixture:
- preview action:
runAuthoritativeInvoiceTemplatePreview - server render action:
renderTemplateOnServer
- preview action:
- Parity assertions include:
- exact HTML/CSS equality,
- totals value parity (
Grand Total), - grouped section ordering parity (
ProductsbeforeServices).
Rationale:
- This provides direct automated guardrails against semantic drift between preview and PDF/server render pipelines.
Commands run:
pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts(pass).
2026-02-12 — F034 implemented
- Replaced outdated invoice template architecture documentation with AST cutover documentation:
docs/billing/invoice_templates.md
- Documentation now describes:
- canonical
InvoiceTemplateAstmodel and runtime modules, - shared preview/PDF evaluator+renderer pipeline,
- allowlisted
strategyIdextension mechanism, - compatibility behavior for legacy columns,
- explicit deletion/removal notes for compiler/Wasm stack.
- canonical
Rationale:
- Prior docs still described AssemblyScript/Wasm execution path and removed modules. Updated docs now align with runtime reality and PRD cutover architecture.
Verification:
- Manual doc review of
docs/billing/invoice_templates.mdfor AST pipeline and removal notes coverage.
2026-02-12 — T001 implemented
- Marked minimal valid AST schema acceptance as implemented via schema unit coverage.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::validates a minimal AST document
Verification:
- \ WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})
RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770925966224"
Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > honors public base override [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: 'http://localhost:8085', runnerBase: undefined, publicBase: 'http://localhost:8085' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > supports relative public base for gateway proxy [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: '/runner', publicBase: '/runner' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > uses absolute public base when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/settings', tenantId: undefined, overrideBase: null, runnerBase: 'https://runner.dev/alga', publicBase: 'https://runner.dev/alga' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > appends tenant when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: null, runnerBase: undefined, publicBase: '/runner' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > falls back to /runner when no public base is set [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: undefined, publicBase: '/runner' }
✓ ee/server/src/lib/extensions/tests/assets/url.shared.test.ts (5 tests) 3ms 36 MB heap used ✓ packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx (3 tests) 8ms 41 MB heap used ✓ packages/billing/src/lib/invoice-template-ast/strategies.test.ts (2 tests) 1ms 42 MB heap used ✓ ee/server/src/tests/unit/tenant-creation.test.ts (4 tests) 1ms 43 MB heap used ✓ packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (4 tests) 6ms 68 MB heap used ✓ ee/server/src/tests/unit/routeParams.resolveInstallId.test.ts (3 tests) 0ms 52 MB heap used ❯ ee/temporal-workflows/src/activities/tests/email-activities-simple.test.ts (24 tests | 17 failed) 914ms 79 MB heap used × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with default length of 12 0ms → expected Promise{…} to have property 'length' × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with custom length 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate different passwords each time 0ms × Email Activities - Simple Tests > generateTemporaryPassword > should contain at least one character from each category 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should not contain ambiguous characters 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should handle minimum length of 4 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate secure passwords with high entropy 0ms × Email Activities - Simple Tests > MockEmailService > should send emails successfully 101ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should validate email addresses correctly 0ms × Email Activities - Simple Tests > MockEmailService > should track sent emails for testing 102ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should filter emails by recipient 101ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should simulate failures when configured 101ms × Email Activities - Simple Tests > MockEmailService > should handle invalid email addresses 100ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle multiple recipients 100ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should throw error when no valid recipients 101ms × Email Activities - Simple Tests > MockEmailService > should support email service configuration 0ms → expected Promise{…} to be an instance of MockEmailService ✓ Email Activities - Simple Tests > MockEmailService > should return email templates for testing 0ms ✓ Email Activities - Simple Tests > MockEmailService > should return null for unknown templates 0ms × Email Activities - Simple Tests > MockEmailService > should support clearing sent emails 100ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle delay configuration 102ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > Email Service Factory > should create mock service by default 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should create mock service when explicitly requested 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should throw error for unknown providers 0ms → expected [Function] to throw an error × Email Activities - Simple Tests > Email Service Factory > should pass options to mock service 2ms → expected Promise{…} to be an instance of MockEmailService ✓ server/src/test/unit/readAssistantContentFromSse.test.ts (1 test) 2ms 81 MB heap used stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/projects.e2e.test.ts > Projects API E2E Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/projects.e2e.test.ts (22 tests | 22 skipped) 24ms 109 MB heap used ↓ Projects API E2E Tests > Authentication > should reject requests without API key ↓ Projects API E2E Tests > Authentication > should reject requests with invalid API key ↓ Projects API E2E Tests > Authentication > should accept requests with valid API key ↓ Projects API E2E Tests > CRUD Operations > should create a project ↓ Projects API E2E Tests > CRUD Operations > should get a project by ID ↓ Projects API E2E Tests > CRUD Operations > should update a project ↓ Projects API E2E Tests > CRUD Operations > should delete a project ↓ Projects API E2E Tests > CRUD Operations > should list projects with pagination ↓ Projects API E2E Tests > Project Search > should search projects by query ↓ Projects API E2E Tests > Project Statistics > should get project statistics ↓ Projects API E2E Tests > Project Tasks and Tickets > should get project tasks ↓ Projects API E2E Tests > Project Tasks and Tickets > should get project tickets ↓ Projects API E2E Tests > Error Handling > should return 404 for non-existent project ↓ Projects API E2E Tests > Error Handling > should return 400 for invalid project data ↓ Projects API E2E Tests > Error Handling > should return 400 for invalid UUID ↓ Projects API E2E Tests > Filtering > should filter projects by status ↓ Projects API E2E Tests > Filtering > should filter projects by type ↓ Projects API E2E Tests > Filtering > should filter projects by client ↓ Projects API E2E Tests > Project Export > should export projects as CSV ↓ Projects API E2E Tests > Project Export > should export projects as JSON ↓ Projects API E2E Tests > Permissions > should enforce read permissions for listing ↓ Projects API E2E Tests > Permissions > should enforce create permissions ✓ server/src/test/unit/billingPlanSelection.test.ts (5 tests | 1 skipped) 1ms 117 MB heap used stdout | packages/client-portal/src/actions/client-portal-actions/client-tickets.responseSource.test.ts > addClientTicketComment response source metadata > T001: stores metadata.responseSource=client_portal when inserting a client comment Usage statistics enabled (user IDs anonymized)
stdout | packages/client-portal/src/actions/client-portal-actions/client-tickets.responseSource.test.ts > addClientTicketComment response source metadata > T001: stores metadata.responseSource=client_portal when inserting a client comment Converted markdown content for client comment: markdown-content
❯ packages/client-portal/src/actions/client-portal-actions/client-tickets.responseSource.test.ts (1 test | 1 failed) 210ms 127 MB heap used × addClientTicketComment response source metadata > T001: stores metadata.responseSource=client_portal when inserting a client comment 210ms → Failed to add comment ✓ server/src/test/unit/docs/contractPurchaseOrderSupport.docs.test.ts (1 test) 1ms 129 MB heap used ✓ server/src/test/unit/workflowsCeStubEntry.unit.test.tsx (1 test) 0ms 131 MB heap used ✓ packages/projects/src/lib/timeEntryContext.test.ts (1 test) 0ms 135 MB heap used ✓ packages/billing/src/components/invoice-designer/state/designerStore.layout.test.ts (5 tests) 3ms 112 MB heap used ✓ packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (2 tests) 0ms 119 MB heap used ✓ sdk/samples/component/invoicing-demo/tests/handler.test.ts (4 tests) 1ms 122 MB heap used ✓ server/src/test/unit/ui/reopenForEdits.test.ts (2 tests) 1ms 123 MB heap used ❯ packages/ui/src/context/SchedulingContext.test.tsx (4 tests | 4 failed) 1ms 136 MB heap used × SchedulingContext > returns default callbacks when no provider is present 0ms → document is not defined × SchedulingContext > renders fallback alert element for agent schedule by default 0ms → document is not defined × SchedulingContext > shows a toast when launching time entry without provider 0ms → document is not defined × SchedulingContext > uses provider callbacks when SchedulingCallbackProvider is present 1ms → document is not defined stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Real-world Phase Drag Scenario > should handle dragging phase to before the first phase Moving Phase 3 before Phase 1: new key = Zz
stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should handle multiple insertions at the beginning Keys after multiple insertions at beginning: [ 'Zv', 'Zw', 'Zx', 'Zy', 'Zz', 'a0' ]
stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should generate correct key when placing phase at the end Key for placing after last: a6 (should be > a5)
stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should generate correct key when placing phase between two phases Key for placing between: a1V (should be between a1 and a2)
stdout | server/src/test/unit/project-actions/phaseReordering.test.ts > Phase Reordering Logic > Fractional Indexing Key Generation > should generate correct key when placing phase at the beginning Key for placing before first: Zz (should be < a0)
✓ server/src/test/unit/project-actions/phaseReordering.test.ts (9 tests) 1ms 138 MB heap used ✓ packages/event-bus/src/index.pending.test.ts (1 test) 18ms 120 MB heap used ✓ sdk/samples/component/scheduler-demo/tests/handler.test.ts (6 tests) 1ms 127 MB heap used ✓ packages/billing/src/components/invoice-designer/state/designerStore.labelText.test.ts (4 tests) 2ms 140 MB heap used ❯ server/src/test/unit/timePeriodSuggester.test.ts (10 tests | 10 failed) 10ms 155 MB heap used × TimePeriodSuggester > suggestNewTimePeriod > should suggest monthly periods with no existing periods 0ms → expected undefined to be '2026-02-12' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest monthly periods with existing periods 0ms → expected undefined to be '2025-02-01' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest weekly periods 1ms → expected undefined to be '2026-02-12' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest yearly periods 0ms → expected undefined to be '2026-02-12' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should handle multiple semi-monthly settings together 1ms → expected undefined to be '2025-01-01' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should handle February correctly in leap years 1ms → expected undefined to be '2024-02-01' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should select settings based on period start date, not current date 1ms → expected undefined to be '2025-01-15' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should handle current date before next period start date in semi-monthly periods 0ms → expected undefined to be '2025-01-15' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest next period after existing periods 5ms → expected undefined to be '2025-01-14' // Object.is equality × TimePeriodSuggester > suggestNewTimePeriod > should suggest period starting in the future after current date 0ms → expected undefined to be '2025-06-01' // Object.is equality stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/teams.e2e.test.ts > Teams API E2E Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/teams.e2e.test.ts (36 tests | 36 skipped) 2ms 200 MB heap used ↓ Teams API E2E Tests > Authentication > should require API key for all endpoints ↓ Teams API E2E Tests > Authentication > should reject invalid API key ↓ Teams API E2E Tests > CRUD Operations > Create Team (POST /api/v1/teams) > should create a new team ↓ Teams API E2E Tests > CRUD Operations > Create Team (POST /api/v1/teams) > should validate required fields ↓ Teams API E2E Tests > CRUD Operations > Create Team (POST /api/v1/teams) > should validate manager_id is a valid user ↓ Teams API E2E Tests > CRUD Operations > Get Team (GET /api/v1/teams/:id) > should retrieve a team by ID ↓ Teams API E2E Tests > CRUD Operations > Get Team (GET /api/v1/teams/:id) > should return 404 for non-existent team ↓ Teams API E2E Tests > CRUD Operations > Get Team (GET /api/v1/teams/:id) > should not return teams from other tenants ↓ Teams API E2E Tests > CRUD Operations > Update Team (PUT /api/v1/teams/:id) > should update a team ↓ Teams API E2E Tests > CRUD Operations > Update Team (PUT /api/v1/teams/:id) > should return 404 when updating non-existent team ↓ Teams API E2E Tests > CRUD Operations > Update Team (PUT /api/v1/teams/:id) > should validate update data ↓ Teams API E2E Tests > CRUD Operations > Delete Team (DELETE /api/v1/teams/:id) > should delete a team ↓ Teams API E2E Tests > CRUD Operations > Delete Team (DELETE /api/v1/teams/:id) > should return 404 when deleting non-existent team ↓ Teams API E2E Tests > CRUD Operations > Delete Team (DELETE /api/v1/teams/:id) > should handle teams with members ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should list all teams with default pagination ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should support pagination parameters ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should filter by search query ↓ Teams API E2E Tests > List Teams (GET /api/v1/teams) > should sort teams ↓ Teams API E2E Tests > Team Manager Assignment > Assign Team Manager (PUT /api/v1/teams/:id/manager) > should assign manager and automatically add them as team member ↓ Teams API E2E Tests > Team Manager Assignment > Assign Team Manager (PUT /api/v1/teams/:id/manager) > should not duplicate member if manager is already a team member ↓ Teams API E2E Tests > Team Creation with Manager > should automatically add manager as team member when creating team ↓ Teams API E2E Tests > Team Members > Add Team Member (POST /api/v1/teams/:id/members) > should add a member to a team ↓ Teams API E2E Tests > Team Members > Add Team Member (POST /api/v1/teams/:id/members) > should prevent duplicate members ↓ Teams API E2E Tests > Team Members > Add Team Member (POST /api/v1/teams/:id/members) > should validate user exists ↓ Teams API E2E Tests > Team Members > List Team Members (GET /api/v1/teams/:id/members) > should list team members ↓ Teams API E2E Tests > Team Members > Remove Team Member (DELETE /api/v1/teams/:id/members/:userId) > should remove a member from team ↓ Teams API E2E Tests > Team Members > Remove Team Member (DELETE /api/v1/teams/:id/members/:userId) > should return 404 for non-existent member ↓ Teams API E2E Tests > Team Statistics > should get team statistics ↓ Teams API E2E Tests > Error Handling > should handle invalid UUID format ↓ Teams API E2E Tests > Error Handling > should handle invalid query parameters ↓ Teams API E2E Tests > Error Handling > should handle missing required fields on create ↓ Teams API E2E Tests > Permissions > should enforce read permissions for listing ↓ Teams API E2E Tests > Permissions > should enforce create permissions ↓ Teams API E2E Tests > Permissions > should enforce update permissions ↓ Teams API E2E Tests > Permissions > should enforce delete permissions ↓ Teams API E2E Tests > Multi-tenancy > should isolate teams by tenant stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/contractWizard.integration.test.ts > createClientContractFromWizard Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/contractWizard.integration.test.ts (1 test | 1 skipped) 2ms 207 MB heap used ↓ createClientContractFromWizard > creates downstream client records for fixed-fee contracts ✓ server/src/test/unit/workflowBundleCli.unit.test.ts (2 tests) 4ms 244 MB heap used ✓ packages/core/src/lib/logger.test.ts (1 test) 0ms 247 MB heap used stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts (5 tests | 5 skipped) 2ms 251 MB heap used ↓ Contract Purchase Order Support > T001: invoices table includes po_number + client_contract_id ↓ Contract Purchase Order Support > T002: invoice creation snapshots client_contracts.po_number onto invoices.po_number ↓ Contract Purchase Order Support > T003: invoice generation blocks when po_required=true and po_number is missing ↓ Contract Purchase Order Support > T004: PO consumption sums finalized invoices and unconsumes when status changes away from finalized ↓ Contract Purchase Order Support > T005: overage calculation uses invoice total_amount and contract po_amount (authorized total spend) ✓ server/src/test/unit/tenantSettingsActions.experimentalFeatures.test.ts (10 tests) 7ms 216 MB heap used stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/time-entries.e2e.test.ts (40 tests | 38 failed | 2 skipped) 33ms 236 MB heap used × Time Entries API E2E Tests > Authentication > should require API key for all endpoints 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Authentication > should reject invalid API key 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should start a tracking session 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should stop a tracking session 2ms → → Cannot read properties of undefined (reading 'cleanup') ↓ Time Entries API E2E Tests > Approval Workflow > should approve time entries ↓ Time Entries API E2E Tests > Approval Workflow > should reject invalid entry IDs for approval × Time Entries API E2E Tests > Export > should export time entries to CSV 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Export > should export time entries to JSON 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Statistics > should get time entry statistics 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Templates > should list time entry templates 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk create time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk update time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid UUID format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid query parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid date format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce read permissions for listing 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce create permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce update permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce delete permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant 1ms → → Cannot read properties of undefined (reading 'cleanup') ✓ server/src/test/unit/menuConfig.experimentalFeatures.test.ts (1 test) 0ms 143 MB heap used ✓ packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (3 tests) 1ms 145 MB heap used ✓ packages/billing/tests/deleteContractPermissions.test.ts (1 test) 18ms 150 MB heap used ✓ shared/lib/utils/emailFileConversion.test.ts (4 tests) 4ms 156 MB heap used ✓ ee/server/extensions/samples/ui-kit-showcase/test/scaffold.test.ts (8 tests) 1ms 170 MB heap used stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 999 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-2', remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-2', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Shutdown complete
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 100 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return full bucket for new tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should warn if initialized twice [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should initialize with Redis client [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
✓ server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts (17 tests) 4ms 176 MB heap used ✓ packages/clients/src/lib/durationHelpers.test.ts (7 tests) 0ms 179 MB heap used ❯ server/src/test/unit/clientContractActions.overlapExclusive.test.ts (3 tests | 3 failed) 1ms 182 MB heap used × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (start == invoiced period end) 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (end exclusive == invoiced period start) 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > rejects true overlaps with an invoiced period 1ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: fetch completed { status: undefined, ok: true, url: '/api/ext-proxy/test-extension-id/tickets' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: posting apiproxy_response (reader) { requestId: 'req-123', targetOrigin: '*' }
❯ ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 2 failed) 198ms 92 MB heap used ✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 55ms ✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 59ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 0ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 84ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
✓ packages/projects/tests/projectInfoDrawer.test.tsx (1 test) 63ms 104 MB heap used ✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 7ms 108 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 8 failed) 81ms 137 MB heap used × EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 4ms → Found multiple elements with the placeholder text of: Send a message
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_7"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_8"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[39m [0mAlga[0m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-content"[39m [36m>[39m [36m[39m [0mHi[0m [36m
[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"feedback-container"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"thumbs-container"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<footer[39m [33mclass[39m=[32m"chat-footer"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__inner"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__input"[39m [36m>[39m [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m [36m<p[39m [33mclass[39m=[32m"chat-input__hint"[39m [36m>[39m [0mPress Ctrl+Enter or ⌘+Enter to send.[0m [36m[39m [36m[39m [36m<button[39m [33mclass[39m=[32m"chat-action chat-action--send"[39m [33mtype[39m=[32m"submit"[39m [36m>[39m [0mSEND[0m [36m[39m [36m[39m [36m[39m [36mHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_7"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 6 failed) 4079ms 149 MB heap used × ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 1012ms → Found multiple elements with the text: AI Assistant
Here are the matching elements:
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [36m<svg[39m [33mclass[39m=[32m"lucide lucide-save"[39m [33mfill[39m=[32m"none"[39m [33mheight[39m=[32m"14"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [33mwidth[39m=[32m"14"[39m [33mxmlns[39m=[32m"http://www.w3.org/2000/svg"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"[39m [36m/>[39m [36m<path[39m [33md[39m=[32m"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"[39m [36m/>[39m [36m<path[39m [33md[39m=[32m"M7 3v4a1 1 0 0 0 1 1h7"[39m [36m/>[39m [36m[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative px-3 rounded-md h-8 gap-2 text-primary-600 hover:text-primary-700 hover:bg-primary-50 group"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [36m<svg[39m [33mclass[39m=[32m"lucide lucide-save"[39m [33mfill[39m=[32m"none"[39m [33mheight[39m=[32m"14"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [33mwidth[39m=[32m"14"[39m [33mxmlns[39m=[32m"http://www.w3.org/2000/svg"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"[39m [36m/>[39m [36m<path[39m [33md[39m=[32m"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"[39m [36m/>[39m [36m<path[39m [33md[39m=[32m"M7 3v4a1 1 0 0 0 1 1h7"[39m [36m/>[39m [36m[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 26ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 2ms 170 MB heap used stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/RightSidebar.streaming.test.tsx (1 test | 1 failed) 1009ms 170 MB heap used × RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 1008ms → Found multiple elements with the placeholder text of: Send a message
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_7"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_8"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_a"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[...Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[... ✓ packages/billing/src/components/invoice-designer/DesignerShell.constraints.test.tsx (23 tests) 602ms 253 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 50ms 260 MB heap used ❯ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests | 1 failed) 1140ms 237 MB heap used ✓ InvoiceTemplateEditor preview workspace integration > preserves nested visual workspace state when switching Visual -> Code -> Visual 17ms ✓ InvoiceTemplateEditor preview workspace integration > hydrates workspace from source-embedded designer state 6ms ✓ InvoiceTemplateEditor preview workspace integration > hydrates workspace from localStorage fallback when source has no embedded state 11ms ✓ InvoiceTemplateEditor preview workspace integration > hydrates workspace from persisted templateAst payload 7ms ✓ InvoiceTemplateEditor preview workspace integration > keeps save payload behavior while preview sub-tab is active 20ms ✓ InvoiceTemplateEditor preview workspace integration > does not trigger save writes from preview interactions alone 6ms ✓ InvoiceTemplateEditor preview workspace integration > allows preview workspace access for new templates before name validation 10ms ✓ InvoiceTemplateEditor preview workspace integration > keeps Code tab generated/read-only for GUI templates 30ms × InvoiceTemplateEditor preview workspace integration > enables visual designer in local QA via forceInvoiceDesigner=1 when feature flag is off 1010ms → Unable to find an element by: [data-testid="designer-visual-workspace"]Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[...Ignored nodes: comments, script, style [36m<html>[39m [36m<head />[39m [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33... ✓ InvoiceTemplateEditor preview workspace integration > keeps production behavior when feature flag is off and no override is set 5ms ✓ InvoiceTemplateEditor preview workspace integration > keeps generated source synchronized with GUI model while switching Visual and Code 18ms ✓ server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests) 107ms 236 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.constraintHighlights.test.tsx (2 tests) 3ms 257 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1578ms 291 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 317ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 620ms ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 287ms 289 MB heap used ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1622ms 380 MB heap used ✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 162ms 398 MB heap used ✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 951ms 392 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 307ms ✓ EmailLogsClient > updates results when recipient search changes 307ms ✓ EmailLogsClient > updates results when ticket filter changes 308ms ✓ server/src/test/unit/QuickAskOverlay.streaming.test.tsx (1 test) 14ms 411 MB heap used ✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 186ms 395 MB heap usedTest Files 558 failed | 43 passed (601) Tests 105 failed | 274 passed | 66 skipped | 1 todo (446) Errors 1 error Start at 14:52:46 Duration 25.74s (transform 2.21s, setup 290ms, collect 2.93s, tests 13.48s, environment 235ms, prepare 52ms) (pass).
2026-02-12 — T001 implemented
- Marked minimal AST schema acceptance as implemented.
- Evidence:
packages/billing/src/lib/invoice-template-ast/schema.test.ts(validates a minimal AST document).
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts(pass).
2026-02-12 — T002 implemented
- Marked unknown node-type schema rejection with structured diagnostics as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::returns structured validation errors for invalid AST payloads
Verification:
- \ WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})
RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770925992649"
Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest ✓ packages/billing/src/components/invoice-designer/state/designerStore.layoutMode.test.ts (2 tests) 8ms 15 MB heap used ✓ server/src/test/unit/DocumentationService.test.ts (4 tests) 1ms 41 MB heap used ✓ packages/billing/src/lib/invoice-renderer/layout-renderer.test.ts (2 tests) 1ms 60 MB heap used stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/billingInvoiceTiming.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/src/lib/invoice-template-ast/strategies.test.ts (2 tests) 1ms 254 MB heap used stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.redaction.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/accounting/externalTaxImport.integration.test.ts (14 tests | 14 skipped) 20ms 260 MB heap used ↓ External Tax Import > importing tax from external accounting system > should update invoice charges with tax amounts from QuickBooks ↓ External Tax Import > importing tax from external accounting system > should change invoice tax_source from pending_external to external ↓ External Tax Import > importing tax from external accounting system > should create audit record in external_tax_imports table ↓ External Tax Import > importing tax from external accounting system > should update invoice total_amount to include imported tax ↓ External Tax Import > tax allocation across charges > should apply per-line tax amounts from external system ↓ External Tax Import > tax allocation across charges > should handle mix of taxable and non-taxable items ↓ External Tax Import > tax allocation across charges > should handle different tax rates across items ↓ External Tax Import > tax allocation across charges > should distribute proportionally when line matching fails ↓ External Tax Import > tax allocation across charges > should match by charge ID even when external lines are returned out of order ↓ External Tax Import > internal tax calculation is skipped for external delegation > should set tax to zero when invoice has pending_external tax source ↓ External Tax Import > automatic tax import after export > should automatically import tax after exporting invoice with tax delegation ↓ External Tax Import > error handling > should fail if invoice is not pending_external ↓ External Tax Import > error handling > should fail if invoice has no external mapping ↓ External Tax Import > error handling > should fail if external system returns error stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.eventTrigger.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/surveyEmailTemplates.integration.test.ts (2 tests | 2 skipped) 1ms 269 MB heap used ↓ Survey email templates > registers system templates for each supported locale ↓ Survey email templates > renders locale-specific content and falls back to English stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowPayloadContractInference.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (6 tests) 1ms 277 MB heap used stdout | packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts > renderTemplateOnServer AST integration > renders template HTML/CSS from canonical AST payload [Server Action] Successfully rendered template: tpl-1
✓ packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts (2 tests) 5ms 287 MB heap used stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/ticketPermissions.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/extensions/uiHooks.test.ts (2 tests) 0ms 312 MB heap used ✓ ee/server/src/tests/unit/schedulerHostApi.unit.test.ts (72 tests) 9ms 272 MB heap used ❯ server/src/lib/extensions/ui/iframeBridge.test.ts (5 tests | 5 failed) 1ms 279 MB heap used × bootstrapIframe (host bridge) > applies sandbox="allow-scripts" by default when none provided 0ms → window is not defined × bootstrapIframe (host bridge) > throws when allowedOrigin mismatches iframe src origin and RUNNER_PUBLIC_BASE is absolute 0ms → window is not defined × bootstrapIframe (host bridge) > sends bootstrap message with envelope version after load 0ms → window is not defined × bootstrapIframe (host bridge) > adjusts iframe height on resize messages with clamping 0ms → window is not defined × bootstrapIframe (host bridge) > validates contentHash format 0ms → window is not defined stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts (1 test | 1 skipped) 2ms 285 MB heap used ↓ Tax Rate Changes Mid-Billing Period > should apply correct tax rates based on charge dates stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService – REST usage > refreshes OAuth tokens when expired Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials
stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService – REST usage > retries after 401 by refreshing token once and logs tenant metadata Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials
❯ server/src/test/unit/accounting/xeroClientService.spec.ts (8 tests | 1 failed) 5ms 306 MB heap used ✓ XeroClientService – REST usage > POST /Invoices payload matches spec requirements 0ms ✓ XeroClientService – REST usage > normalizes validation errors returned from POST /Invoices 0ms ✓ XeroClientService – REST usage > handles empty payload array without issuing network request 0ms ✓ XeroClientService – REST usage > sets expected headers for authenticated requests 0ms ✓ XeroClientService – REST usage > refreshes OAuth tokens when expired 1ms ✓ XeroClientService – REST usage > retrieves accounts, items, tax rates, and tracking categories with normalized structures 0ms × XeroClientService – REST usage > retries after 401 by refreshing token once and logs tenant metadata 1ms → expected "spy" to be called 1 times, but got 0 times ✓ XeroClientService – REST usage > allows re-export after validation error once mappings are corrected 0ms ✓ ee/server/src/tests/unit/tenant-creation.test.ts (4 tests) 0ms 310 MB heap used ✓ server/src/lib/auth/sessionCookies.test.ts (2 tests) 6ms 313 MB heap used ✓ server/src/test/unit/security/managerScopeRegression.test.ts (1 test) 1ms 314 MB heap used ✓ server/src/test/unit/scheduling/bundledTicketsWorkItemPickerBehavior.test.ts (2 tests) 1ms 316 MB heap used stdout | server/src/lib/email/delayedEmailQueue.redisRecovery.test.ts > DelayedEmailQueue Redis recovery > recreates the Redis client after a zRangeByScore timeout [DelayedEmailQueue] Processing loop started { intervalMs: 60000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 60000 }
stdout | server/src/lib/email/delayedEmailQueue.redisRecovery.test.ts > DelayedEmailQueue Redis recovery > recreates the Redis client after a zRangeByScore timeout [DelayedEmailQueue] Shutting down... [DelayedEmailQueue] Shutdown complete
✓ server/src/lib/email/delayedEmailQueue.redisRecovery.test.ts (1 test) 2ms 318 MB heap used ✓ packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts (1 test) 0ms 299 MB heap used ❯ server/src/test/integration/billing/invoiceStatusManagement.integration.test.ts (10 tests | 10 skipped) 1ms 100 MB heap used ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to partially_applied when partial credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to paid when full credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should accumulate multiple partial credits and update status accordingly ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to partially_applied when partial payment is recorded ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to paid when full payment is recorded ↓ Invoice Status Management Integration > Combined Payment and Credit Scenarios > should correctly calculate status with both payments and credits ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to partially_applied when partial refund is recorded ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to sent when full refund is recorded ↓ Invoice Status Management Integration > Status Transition Validation > should not allow payment on cancelled invoice ↓ Invoice Status Management Integration > Status Transition Validation > should not allow credit on draft invoice ❯ server/src/test/unit/scheduling/actionGuardWiring.test.ts (7 tests | 4 failed) 2ms 103 MB heap used ✓ delegation guard wiring (static) > fetchTimePeriods enforces delegation via assertCanActOnBehalf 0ms ✓ delegation guard wiring (static) > fetchOrCreateTimeSheet enforces delegation via assertCanActOnBehalf 0ms × delegation guard wiring (static) > fetchTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 1ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeSheet[\s\S]*a…/ × delegation guard wiring (static) > fetchTimeEntriesForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeEntriesForTimeS…/ × delegation guard wiring (static) > fetchWorkItemsForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport { Knex } fro…' to match /export const fetchWorkItemsForTimeShe…/ ✓ delegation guard wiring (static) > reopen/reverse approval is blocked when a timesheet contains invoiced entries 0ms × delegation guard wiring (static) > reopen/reverse approval transitions timesheet and entries to CHANGES_REQUESTED 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /reverseTimeSheetApproval[\s\S]*appr…/ ❯ server/src/test/unit/scheduling/approvalBehavior.test.ts (2 tests | 2 failed) 1ms 108 MB heap used × timesheet approval behavior (static) > approveTimeSheet enforces delegation and marks timesheet APPROVED 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const approveTimeSheet[\s\S]…/ × timesheet approval behavior (static) > bulkApproveTimeSheets enforces manager scope via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const bulkApproveTimeSheets[\…/ ❯ server/src/test/integration/citusTenantFilterEmailProviders.integration.test.ts (2 tests | 2 failed) 2ms 116 MB heap used × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Microsoft webhook route 2ms → expected 'export { GET, POST } from '@alga-psa…' to contain '.where({ id: row.id, tenant: row.tena…' × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Google webhook route 1ms → expected 'export { POST } from '@alga-psa/inte…' to contain '.where({ id: provider.id, tenant: pro…' stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/mappingPermissions.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | eslint-plugin-custom-rules/migration-filename.test.js All tests passed!
✓ eslint-plugin-custom-rules/migration-filename.test.js (14 tests) 17ms 144 MB heap used ✓ server/src/test/unit/workflowsEntryTypingGuard.unit.test.ts (2 tests) 1ms 146 MB heap used ✓ packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts (2 tests) 0ms 152 MB heap used stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/scheduling/deleteTimeEntryBehavior.test.ts (1 test) 1ms 151 MB heap used ✓ tools/nx-tests/nxAffected.test.ts (2 tests) 3861ms 154 MB heap used ✓ nx affected > identifies affected projects from a file list 3087ms ✓ nx affected > includes @alga-psa/clients when client code changes 774ms ✓ packages/clients/src/lib/durationHelpers.test.ts (7 tests) 0ms 156 MB heap used ✓ sdk/samples/component/scheduler-demo/tests/handler.test.ts (6 tests) 1ms 159 MB heap used ✓ tools/nx-tests/nxWorkspace.test.ts (3 tests) 16106ms 162 MB heap used ✓ nx workspace > can generate an nx graph html file 15400ms ✓ nx workspace > runs the alga-module generator in dry-run mode 413ms ✓ packages/core/src/lib/events/publisher.test.ts (1 test) 5ms 126 MB heap used ✓ server/src/test/unit/email/emailLoggingFailure.test.ts (1 test) 22ms 126 MB heap used ❯ server/src/test/unit/clientFormValidation.test.ts (20 tests | 12 failed) 9ms 130 MB heap used ✓ Client Form Validation > validateClientName > should accept valid client names 1ms × Client Form Validation > validateClientName > should reject invalid client names 0ms → expected null to be 'Client name must contain letters and …' // Object.is equality × Client Form Validation > validateWebsiteUrl > should accept valid URLs 0ms → expected 'Please enter a real business website …' to be null × Client Form Validation > validateWebsiteUrl > should reject invalid URLs 1ms → expected 'Please enter a domain name, not an IP…' to be 'Please enter a valid website URL (e.g…' // Object.is equality × Client Form Validation > validateEmailAddress > should accept valid email addresses 0ms → expected 'Please enter a valid business email a…' to be null × Client Form Validation > validateEmailAddress > should reject invalid email addresses 0ms → expected 'Please enter a valid email address' to be 'Please enter a valid business email a…' // Object.is equality ✓ Client Form Validation > validatePhoneNumber > should accept valid phone numbers 1ms × Client Form Validation > validatePhoneNumber > should reject invalid phone numbers 1ms → expected null to be 'Please enter a valid phone number' // Object.is equality ✓ Client Form Validation > validatePostalCode > should accept valid US ZIP codes 0ms × Client Form Validation > validatePostalCode > should reject invalid US ZIP codes 0ms → expected 'Please enter a valid ZIP code (e.g., …' to be 'Please enter a valid US ZIP code (e.g…' // Object.is equality × Client Form Validation > validatePostalCode > should validate Canadian postal codes 0ms → expected 'Please enter a valid Canadian postal …' to be 'Please enter a valid Canadian postal …' // Object.is equality ✓ Client Form Validation > validateCityName > should accept valid city names 0ms × Client Form Validation > validateCityName > should reject invalid city names 0ms → expected 'City name must contain letters' to be 'City name must be at least 2 characte…' // Object.is equality ✓ Client Form Validation > validateAddress > should accept valid addresses 0ms × Client Form Validation > validateAddress > should reject invalid addresses 0ms → expected 'Address must contain letters' to be 'Address must be at least 5 characters…' // Object.is equality ✓ Client Form Validation > validateContactName > should accept valid contact names 0ms × Client Form Validation > validateContactName > should reject invalid contact names 0ms → expected 'Contact name must contain meaningful …' to be 'Contact name cannot contain emojis' // Object.is equality ✓ Client Form Validation > validateClientForm > should validate a complete form successfully 0ms × Client Form Validation > validateClientForm > should return errors for invalid form data 3ms → the given combination of arguments (undefined and string) is invalid for this assertion. You can use an array, a map, an object, a set, a string, or a weakset instead of a string ✓ Client Form Validation > validateClientForm > should allow empty optional fields 0ms ✓ server/src/test/unit/validation/timeEntrySchemaAuditFields.test.ts (2 tests) 1ms 131 MB heap used stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/pricingScheduleIntegration.test.ts > Pricing Schedule Integration Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/pricingScheduleIntegration.test.ts (10 tests | 10 skipped) 2ms 132 MB heap used ↓ Pricing Schedule Integration Tests > Create and Persist Pricing Schedules > should create a pricing schedule and persist to database ↓ Pricing Schedule Integration Tests > Create and Persist Pricing Schedules > should retrieve active pricing schedule for a billing period ↓ Pricing Schedule Integration Tests > Create and Persist Pricing Schedules > should handle multiple schedules and return the most recent effective schedule ↓ Pricing Schedule Integration Tests > Pricing Schedule Boundaries > should correctly filter schedules across billing period boundaries ↓ Pricing Schedule Integration Tests > Pricing Schedule Boundaries > should treat schedules with null end_date as ongoing ↓ Pricing Schedule Integration Tests > Pricing Schedule Updates and Deletes > should update an existing pricing schedule ↓ Pricing Schedule Integration Tests > Pricing Schedule Updates and Deletes > should delete a pricing schedule ↓ Pricing Schedule Integration Tests > Pricing Schedule Updates and Deletes > should mark a schedule as expired when setting end_date ↓ Pricing Schedule Integration Tests > Pricing Schedule for No Rates > should allow schedules without custom_rate and treat them as null overrides ↓ Pricing Schedule Integration Tests > Pricing Schedule for No Rates > should return no schedule when contract has none defined ❯ ee/temporal-workflows/src/activities/tests/portal-domain-reconcile.integration.test.ts (2 tests | 2 failed) 1ms 134 MB heap used × applyPortalDomainResources > routes virtual service traffic to the app once certificate succeeds 0ms → Missing "./admin.js" specifier in "@alga-psa/db" package × applyPortalDomainResources > creates new manifests and prunes legacy virtual services when the domain changes 1ms → Missing "./admin.js" specifier in "@alga-psa/db" package ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1407ms 177 MB heap used ✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 1ms 181 MB heap used ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests) 76ms 190 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' } iframeBridge: posting apiproxy_response { requestId: 'req-123', targetOrigin: '*' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }
❯ ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 3 failed) 142ms 198 MB heap used × Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 60ms → expected "fetch" to be called with arguments: [ StringContaining{…}, …(1) ]
Number of calls: 0
✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 55ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 25ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 2ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? ✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 3ms 202 MB heap used ✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 159ms 228 MB heap used ❯ server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests | 2 failed) 111ms 174 MB heap used ✓ TicketEmailNotifications > renders without errors 1ms ✓ TicketEmailNotifications > is collapsed by default and expands on click 12ms ✓ TicketEmailNotifications > shows loading state while fetching 18ms ✓ TicketEmailNotifications > displays timestamp, recipient, subject, and status for each log entry 12ms ✓ TicketEmailNotifications > shows error message for failed notifications 13ms × TicketEmailNotifications > shows maximum 20 entries initially with Load more when more exist 18ms → Found multiple elements with the role "table"
Here are the matching elements:
Ignored nodes: comments, script, style [36m<table[39m [33mclass[39m=[32m"w-full divide-y divide-[rgb(var(--color-border-200))]"[39m [36m>[39m [36m<thead[39m [33mclass[39m=[32m"bg-background"[39m [36m>[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-client_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mClient[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-template_contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mContract Template[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mContract Name[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-start_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mStart Date[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-end_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mEnd Date[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-status"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mStatus[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-contract_id"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mActions[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<tbody[39m [33mclass[39m=[32m"divide-y divide-gray-100"[39m [36m>[39m [36m<tr[39m [33mclass[39m=[32m" bg-[rgb(var(--color-border-50))] hover:bg-primary-50 cursor-pointer transition-colors cursor-pointer "[39m [36m>[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-client_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0mAcme Co[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-template_contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0mDraft Alpha[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-start_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-end_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-status"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border bg-green-100 text-green-800"[39m [36m>[39m [0mActive[0m [36m[39m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-contract_id"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [36m<button[39m [33maria-expanded[39m=[32m"false"[39m [33maria-haspopup[39m=[32m"menu"[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group"[39m [33mdata-state[39m=[32m"closed"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"sr-only"[39m [36m>[39m [0mOpen menu[0m [36m[39m [36m<svg[39m [33mclass[39m=[32m"lucide lucide-ellipsis-vertical h-4 w-4"[39m [33mfill[39m=[32m"none"[39m [33mheight[39m=[32m"24"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [33mwidth[39m=[32m"24"[39m [33mxmlns[39m=[32m"http://www.w3.org/2000/svg"[39m [36m>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"12"[39m [33mr[39m=[32m"1"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"5"[39m [33mr[39m=[32m"1"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"19"[39m [33mr[39m=[32m"1"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m
Ignored nodes: comments, script, style [36m<table[39m [33mdata-automation-id[39m=[32m"ticket-email-notifications-table"[39m [36m>[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser0@example.com[0m [36m[39m [36m[39m [0mS0[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser1@example.com[0m [36m[39m [36m[39m [0mS1[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser2@example.com[0m [36m[39m [36m[39m [0mS2[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser3@example.com[0m [36m[39m [36m[39m [0mS3[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser4@example.com[0m [36m[39m [36m[39m [0mS4[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser5@example.com[0m [36m[39m [36m[39m [0mS5[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser6@example.com[0m [36m[39m [36m[39m [0mS6[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser7@example.com[0m [36m[39m [36m[39m [0mS7[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser8@example.com[0m [36m[39m [36m[39m [0mS8[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser9@example.com[0m [36m[39m [36m[39m [0mS9[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser10@example.com[0m [36m[39m [36m[39m [0mS10[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser11@example.com[0m [36m[39m [36m[39m [0mS11[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser12@example.com[0m [36m[39m [36m[39m [0mS12[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser13@example.com[0m [36m[39m [36m[39m [0mS13[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser14@example.com[0m [36m[39m [36m[39m [0mS14[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser15@example.com[0m [36m[39m [36m[39m [0mS15[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser16@example.com[0m [36m[39m [36m[39m [0mS16[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser17@example.com[0m [36m[39m [36m[39m [0mS17[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser18@example.com[0m [36m[39m [36m[39m [0mS18[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser19@example.com[0m [36m[39m [36m[39m [0mS19[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<table[39m [33mclass[39m=[32m"w-full divide-y divide-[rgb(var(--color-border-200))]"[39m [36m>[39m [36m<thead[39m [33mclass[39m=[32m"bg-background"[39m [36m>[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-client_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mClient[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-template_contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mContract Template[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mContract Name[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-start_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mStart Date[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-end_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mEnd Date[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-status"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mStatus[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"client-contracts-table-header-contract_id"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mActions[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<tbody[39m [33mclass[39m=[32m"divide-y divide-gray-100"[39m [36m>[39m [36m<tr[39m [33mclass[39m=[32m" bg-[rgb(var(--color-border-50))] hover:bg-primary-50 cursor-pointer transition-colors cursor-pointer "[39m [36m>[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-client_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0mAcme Co[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-template_contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0mDraft Alpha[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-start_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-end_date"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-status"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"inline-flex items-center rounded-full border font-semibold transition-colors text-xs px-2.5 py-0.5 border-border bg-green-100 text-green-800"[39m [36m>[39m [0mActive[0m [36m[39m [36m[39m [36m[39m [36m[39m [36m<td[39m [33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m [33mdata-automation-id[39m=[32m"client-contracts-table-cell-0-contract_id"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [36m<button[39m [33maria-expanded[39m=[32m"false"[39m [33maria-haspopup[39m=[32m"menu"[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group"[39m [33mdata-state[39m=[32m"closed"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"sr-only"[39m [36m>[39m [0mOpen menu[0m [36m[39m [36m<svg[39m [33mclass[39m=[32m"lucide lucide-ellipsis-vertical h-4 w-4"[39m [33mfill[39m=[32m"none"[39m [33mheight[39m=[32m"24"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [33mwidth[39m=[32m"24"[39m [33mxmlns[39m=[32m"http://www.w3.org/2000/svg"[39m [36m>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"12"[39m [33mr[39m=[32m"1"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"5"[39m [33mr[39m=[32m"1"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"19"[39m [33mr[39m=[32m"1"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m
Ignored nodes: comments, script, style [36m<table[39m [33mdata-automation-id[39m=[32m"ticket-email-notifications-table"[39m [36m>[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser0@example.com[0m [36m[39m [36m[39m [0mS0[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser1@example.com[0m [36m[39m [36m[39m [0mS1[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser2@example.com[0m [36m[39m [36m[39m [0mS2[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser3@example.com[0m [36m[39m [36m[39m [0mS3[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser4@example.com[0m [36m[39m [36m[39m [0mS4[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser5@example.com[0m [36m[39m [36m[39m [0mS5[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser6@example.com[0m [36m[39m [36m[39m [0mS6[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser7@example.com[0m [36m[39m [36m[39m [0mS7[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser8@example.com[0m [36m[39m [36m[39m [0mS8[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser9@example.com[0m [36m[39m [36m[39m [0mS9[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser10@example.com[0m [36m[39m [36m[39m [0mS10[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser11@example.com[0m [36m[39m [36m[39m [0mS11[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser12@example.com[0m [36m[39m [36m[39m [0mS12[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser13@example.com[0m [36m[39m [36m[39m [0mS13[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser14@example.com[0m [36m[39m [36m[39m [0mS14[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser15@example.com[0m [36m[39m [36m[39m [0mS15[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser16@example.com[0m [36m[39m [36m[39m [0mS16[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser17@example.com[0m [36m[39m [36m[39m [0mS17[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser18@example.com[0m [36m[39m [36m[39m [0mS18[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser19@example.com[0m [36m[39m [36m[39m [0mS19[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser20@example.com[0m [36m[39m [36m[39m [0mS20[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser21@example.com[0m [36m[39m [36m[39m [0mS21[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser22@example.com[0m [36m[39m [36m[39m [0mS22[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser23@example.com[0m [36m[39m [36m[39m [0mS23[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser24@example.com[0m [36m[39m [36m[39m [0mS24[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 47ms 246 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 16ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 949ms 248 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 306ms ✓ EmailLogsClient > updates results when recipient search changes 306ms ✓ EmailLogsClient > updates results when ticket filter changes 306ms ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 223ms 183 MB heap used ❯ server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 6 failed) 3060ms 189 MB heap used × ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 1005ms → Found multiple elements with the text: AI Assistant
Here are the matching elements:
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 9 failed) 45ms 272 MB heap used × EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 4ms → Found multiple elements with the placeholder text of: Send a message
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l7"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_ku"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m<iframe[39m [33msandbox[39m=[32m"allow-scripts, allow-same-origin"[39m [33msrc[39m=[32m"http://localhost:3000/ext-ui/test-extension-id/hash/index.html"[39m [36m/>[39m [36m
Test Files 561 failed | 40 passed (601) Tests 62 failed | 311 passed | 37 skipped (410) Start at 14:53:12 Duration 37.95s (transform 1.69s, setup 228ms, collect 1.07s, tests 29.30s, environment 249ms, prepare 53ms) (pass).
2026-02-12 — T002 implemented
- Marked unknown node-type rejection with actionable schema diagnostics as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::returns structured validation errors for invalid AST payloads
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T003 implemented
- Marked dynamic-table repeat metadata enforcement as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::requires repeat binding metadata for dynamic-table nodes
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T004 implemented
- Marked transform payload shape validation across filter/sort/group/aggregate/computed operations as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::enforces transform payload shapes
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T005 implemented
- Marked optional strategyId acceptance in schema validation as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::accepts optional strategyId on transform operations
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T006 implemented
- Marked strategy registry allowlist resolution and unknown-ID rejection as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/strategies.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T007 implemented
- Marked evaluator filter transform semantics as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies filter transforms to invoice items
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T008 implemented
- Marked deterministic multi-key sort behavior as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies multi-key sort transforms with stable ordering
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T009 implemented
- Marked grouping transform bucket output behavior as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies grouping and aggregate transforms
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T010 implemented
- Marked aggregate totals math (sum/count/avg) as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies grouping and aggregate transforms
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T011 implemented
- Marked computed-field expression and derived totals behavior as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::computes derived fields and totals composition values
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T012 implemented
- Marked allowlisted strategy hook execution path as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::executes allowlisted strategy hooks
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/schema.test.ts packages/billing/src/lib/invoice-template-ast/strategies.test.ts packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T013 implemented
- Added explicit evaluator unit coverage for strategy hook throw behavior.
- Evidence:
packages/billing/src/lib/invoice-template-ast/evaluator.test.ts(reports explicit strategy execution errors when strategy hooks throw).
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts(pass).
2026-02-12 — T003 implemented
- Marked repeat-binding metadata requirements for dynamic tables as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::requires repeat binding metadata for dynamic-table nodes
Verification:
- \ WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})
RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770926031206"
Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts (1 test | 1 skipped) 20ms 43 MB heap used ↓ Tax Rate Changes Mid-Billing Period > should apply correct tax rates based on charge dates ✓ ee/server/src/tests/unit/basic.test.ts (3 tests) 1ms 32 MB heap used ❯ ee/extensions/samples/ui-kit-showcase/test/build.test.ts (1 test | 1 failed) 2ms 33 MB heap used × build output > iframe bundle is generated in ui/dist/iframe 2ms → expected false to be true // Object.is equality ✓ packages/scheduling/tests/serverPageSchedulingProvider.test.ts (1 test) 0ms 57 MB heap used ✓ packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (2 tests) 0ms 57 MB heap used ✓ packages/clients/src/schemas/client.schema.test.ts (4 tests) 1ms 60 MB heap used ❯ packages/auth/src/lib/rbac.test.ts (3 tests | 3 failed) 4ms 62 MB heap used × rbac permission checks > allows internal users to use MSP permissions only 0ms → promise rejected "Error: [vitest] No "runWithTenant" export… { codeFrame: '…' }" instead of resolving × rbac permission checks > allows client users to use client permissions only 3ms → promise rejected "Error: [vitest] No "runWithTenant" export… { codeFrame: '…' }" instead of resolving × rbac permission checks > returns aggregated permission results 0ms → [vitest] No "runWithTenant" export is defined on the "@alga-psa/db" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
✓ packages/types/src/interfaces/comment.interface.typecheck.test.ts (1 test) 0ms 63 MB heap used stdout | ee/temporal-workflows/src/activities/tests/test-file-check.test.ts > Check if file actually gets created > should show file exists after test File exists: false File path: /var/folders/8g/3xyjqdpd4hx2h39h4qb2lyvm0000gn/T/test-check-gYZTLn/msp/istio-virtualservice.yaml
✓ ee/temporal-workflows/src/activities/tests/test-file-check.test.ts (1 test) 0ms 64 MB heap used stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/appointmentNotifications.integration.test.ts (29 tests | 29 skipped) 2ms 67 MB heap used ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment request received email to client ↓ Appointment Notification System Integration Tests > Email Notifications > should send new appointment request email to MSP staff ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment approved email with correct locale ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment declined email with reason ↓ Appointment Notification System Integration Tests > Email Notifications > should include tenant settings in all emails ↓ Appointment Notification System Integration Tests > Email Notifications > should replace template variables correctly ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notifications for MSP staff on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on approval ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on decline ↓ Appointment Notification System Integration Tests > Internal Notifications > should include correct link in notifications ↓ Appointment Notification System Integration Tests > Internal Notifications > should populate metadata correctly for staff notifications ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct schedule approvers ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct tenant settings ↓ Appointment Notification System Integration Tests > Helper Function Integration > should map contact to client user ID correctly ↓ Appointment Notification System Integration Tests > Helper Function Integration > should return null for non-existent contact ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format dates with correct locale ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format times with correct locale ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should send email notifications in different languages ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should format dates according to locale in notifications ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should default to English when locale is not supported ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should send cancellation notification to client ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should handle cancellation of already cancelled request gracefully ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include actionable metadata in staff notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include appropriate links for client notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should set correct notification types for different events ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should handle missing email addresses gracefully ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should batch notifications to multiple staff members efficiently ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should include all required data fields in notifications ✓ packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts (3 tests) 0ms 67 MB heap used ❯ ee/temporal-workflows/src/activities/tests/email-activities.temporal.test.ts (11 tests | 10 failed) 4393ms 108 MB heap used × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should generate secure passwords with proper entropy 0ms → expected Promise{…} to have property 'length' × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should handle various password lengths correctly 1ms → expected Promise{…} to have property 'length' ✓ Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should ensure consistent randomness across calls 0ms × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should send welcome email with valid input 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle invalid email addresses gracefully 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle empty email addresses 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should work with minimal required fields 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should generate proper email content structure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should handle template variable substitution 1ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should not throw exceptions on failure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should handle missing required fields gracefully 0ms → Cannot read properties of undefined (reading 'info') ✓ packages/billing/src/lib/invoice-template-ast/schema.test.ts (5 tests) 3ms 116 MB heap used ❯ server/src/test/unit/scheduling/actionGuardWiring.test.ts (7 tests | 4 failed) 2ms 119 MB heap used ✓ delegation guard wiring (static) > fetchTimePeriods enforces delegation via assertCanActOnBehalf 0ms ✓ delegation guard wiring (static) > fetchOrCreateTimeSheet enforces delegation via assertCanActOnBehalf 0ms × delegation guard wiring (static) > fetchTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeSheet[\s\S]*a…/ × delegation guard wiring (static) > fetchTimeEntriesForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /export const fetchTimeEntriesForTimeS…/ × delegation guard wiring (static) > fetchWorkItemsForTimeSheet enforces owner-or-delegate access via assertCanActOnBehalf 0ms → expected ''use server'\n\nimport { Knex } fro…' to match /export const fetchWorkItemsForTimeShe…/ ✓ delegation guard wiring (static) > reopen/reverse approval is blocked when a timesheet contains invoiced entries 0ms × delegation guard wiring (static) > reopen/reverse approval transitions timesheet and entries to CHANGES_REQUESTED 1ms → expected ''use server'\n\nimport {\n ITimeEn…' to match /reverseTimeSheetApproval[\s\S]*appr…/ stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.
❯ ee/temporal-workflows/src/test-utils/test-connection.test.ts (3 tests | 1 failed) 122ms 170 MB heap used ✓ Temporal Connection Tests > should connect to temporalio/auto-setup Docker container 9ms ✓ Temporal Connection Tests > should create TestWorkflowEnvironment for unit tests 110ms × Temporal Connection Tests > should verify Docker Postgres connection 3ms → ✓ ee/server/src/tests/unit/invoicingHostApi.unit.test.ts (4 tests) 3ms 172 MB heap used stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > maps tenant snapshot details when provided by the invoice query payload [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-601", "invoice_date": "2026-02-06", "due_date": "2026-02-20", "currency_code": "USD", "client": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "tenantClientInfo": { "client_name": "Northwind MSP", "location_address": "400 SW Main St", "logo_url": "https://cdn.example.com/logo.png" }, "invoice_charges": [], "subtotal": 0, "tax": 0, "total": 0 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-601", "issueDate": "2026-02-06", "dueDate": "2026-02-20", "customer": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "poNumber": null, "tenantClient": { "name": "Northwind MSP", "address": "400 SW Main St", "logoUrl": "https://cdn.example.com/logo.png" }, "items": [], "subtotal": 0, "tax": 0, "total": 0, "taxSource": "internal", "currencyCode": "USD" }
stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > handles nullable/partial values safely [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": null, "invoice_date": null, "due_date": null, "client": { "name": null, "address": null }, "invoice_charges": [ { "item_id": null, "description": null, "quantity": null, "unit_price": null, "total_price": null } ], "subtotal": null, "tax": null, "total": null } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "N/A", "issueDate": "", "dueDate": "", "customer": { "name": "N/A", "address": "N/A" }, "poNumber": null, "tenantClient": null, "items": [ { "id": "", "description": "", "quantity": 0, "unitPrice": 0, "total": 0 } ], "subtotal": 0, "tax": 0, "total": 0, "taxSource": "internal", "currencyCode": "USD" }
stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > keeps canonical minor-unit payloads unchanged [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-2026-0147", "invoice_date": "2026-02-06", "due_date": "2026-02-20", "currency_code": "USD", "client": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "invoice_charges": [ { "item_id": "svc-monitoring", "description": "Managed Endpoint Monitoring", "quantity": 15, "unit_price": 4200, "total_price": 63000 } ], "subtotal": 87000, "tax": 7830, "total": 94830 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-2026-0147", "issueDate": "2026-02-06", "dueDate": "2026-02-20", "customer": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "poNumber": null, "tenantClient": null, "items": [ { "id": "svc-monitoring", "description": "Managed Endpoint Monitoring", "quantity": 15, "unitPrice": 4200, "total": 63000 } ], "subtotal": 87000, "tax": 7830, "total": 94830, "taxSource": "internal", "currencyCode": "USD" }
stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > normalizes legacy existing-invoice major-unit payloads into minor units [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-005", "invoice_date": "2026-01-01", "due_date": "2026-02-16", "currency_code": "USD", "client": { "name": "Emerald City", "address": "1010 Emerald Street" }, "invoice_charges": [ { "item_id": "line-1", "description": "Premium Rabbit Tracking Services", "quantity": 50, "unit_price": 125, "total_price": 6250 }, { "item_id": "line-2", "description": "Monthly Looking Glass Maintenance", "quantity": 1, "unit_price": 1250, "total_price": 1250 } ], "subtotal": 0, "tax": 0, "total": 7500 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-005", "issueDate": "2026-01-01", "dueDate": "2026-02-16", "customer": { "name": "Emerald City", "address": "1010 Emerald Street" }, "poNumber": null, "tenantClient": null, "items": [ { "id": "line-1", "description": "Premium Rabbit Tracking Services", "quantity": 50, "unitPrice": 12500, "total": 625000 }, { "id": "line-2", "description": "Monthly Looking Glass Maintenance", "quantity": 1, "unitPrice": 125000, "total": 125000 } ], "subtotal": 750000, "tax": 0, "total": 750000, "taxSource": "internal", "currencyCode": "USD" }
stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > keeps tenant snapshot null when tenant details are not present [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-602", "invoice_date": "2026-02-06", "due_date": "2026-02-20", "currency_code": "USD", "client": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "invoice_charges": [], "subtotal": 0, "tax": 0, "total": 0 } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-602", "issueDate": "2026-02-06", "dueDate": "2026-02-20", "customer": { "name": "Blue Harbor Dental", "address": "901 Harbor Ave" }, "poNumber": null, "tenantClient": null, "items": [], "subtotal": 0, "tax": 0, "total": 0, "taxSource": "internal", "currencyCode": "USD" }
stdout | packages/billing/src/lib/adapters/invoiceAdapters.test.ts > mapDbInvoiceToWasmViewModel > maps db invoice payload numeric and string fields into wasm preview model [mapDbInvoiceToWasmViewModel] Received Data: { "invoice_number": "INV-500", "invoice_date": "2026-02-01", "due_date": "2026-02-15", "currency_code": "USD", "po_number": "PO-1", "tax_source": "internal", "client": { "name": "Acme", "address": "123 Main" }, "invoice_charges": [ { "item_id": "item-1", "description": "Managed Service", "quantity": "2", "unit_price": "1000", "total_price": "2000" } ], "subtotal": "2000", "tax": "100", "total": "2100" } [mapDbInvoiceToWasmViewModel] Input data appears to be in DbInvoiceViewModel format. Mapping... [mapDbInvoiceToWasmViewModel] Mapped ViewModel: { "invoiceNumber": "INV-500", "issueDate": "2026-02-01", "dueDate": "2026-02-15", "customer": { "name": "Acme", "address": "123 Main" }, "poNumber": "PO-1", "tenantClient": null, "items": [ { "id": "item-1", "description": "Managed Service", "quantity": 2, "unitPrice": 1000, "total": 2000 } ], "subtotal": 2000, "tax": 100, "total": 2100, "taxSource": "internal", "currencyCode": "USD" }
✓ packages/billing/src/lib/adapters/invoiceAdapters.test.ts (6 tests) 1ms 152 MB heap used ✓ packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts (3 tests) 1ms 159 MB heap used ✓ server/src/test/unit/migrations/timeEntriesAuditColumns.test.ts (2 tests) 0ms 160 MB heap used stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | ee/server/src/lib/extensions/tests/registry-v2.test.ts Retrieved secret 'db_password_server' from configured provider.
↓ ee/server/src/lib/extensions/tests/registry-v2.test.ts (5 tests | 5 skipped) ✓ server/src/test/unit/menuConfig.experimentalFeatures.test.ts (1 test) 0ms 186 MB heap used ✓ server/src/test/unit/workflowRunDialogEventUtils.test.ts (3 tests) 1ms 187 MB heap used ✓ packages/tickets/src/lib/tests/ticketOriginCreatePath.test.ts (5 tests) 2ms 193 MB heap used ✓ packages/auth/src/components/ssoProviderButtonsImport.test.ts (1 test) 0ms 195 MB heap used ❯ server/src/test/integration/payments/stripePaymentIntegration.test.ts (21 tests | 21 skipped) 1ms 197 MB heap used ↓ Stripe Payment Integration - Vulnerability Tests > Race Condition in Concurrent Webhook Processing > should correctly update invoice status when processing concurrent webhooks ↓ Stripe Payment Integration - Vulnerability Tests > Race Condition in Concurrent Webhook Processing > should handle duplicate webhook events idempotently ↓ Stripe Payment Integration - Vulnerability Tests > Tenant Isolation Vulnerabilities > should expose tenant isolation gap when webhook contains different tenant_id ↓ Stripe Payment Integration - Vulnerability Tests > Tenant Isolation Vulnerabilities > should prevent cross-tenant payment recording ↓ Stripe Payment Integration - Vulnerability Tests > Missing Amount and Currency Validation > should accept partial payments and update invoice status appropriately ↓ Stripe Payment Integration - Vulnerability Tests > Missing Amount and Currency Validation > should reject payment in different currency than invoice ↓ Stripe Payment Integration - Vulnerability Tests > Missing Refund Handling > should update invoice status when payment is refunded ↓ Stripe Payment Integration - Vulnerability Tests > Missing Refund Handling > should track partial refunds and update invoice balance ↓ Stripe Payment Integration - Vulnerability Tests > Invoice Status Transition Issues > should reject payments for cancelled invoices ↓ Stripe Payment Integration - Vulnerability Tests > Invoice Status Transition Issues > should reject payments for draft invoices ↓ Stripe Payment Integration - Vulnerability Tests > Webhook Error Handling Gaps > should properly report errors for webhooks referencing non-existent invoices ↓ Stripe Payment Integration - Vulnerability Tests > Webhook Error Handling Gaps > should record webhook events for valid invoices ↓ Stripe Payment Integration - Vulnerability Tests > Payment Link Expiration Issues > should expose payment link expiration beyond Stripe limit ↓ Stripe Payment Integration - Vulnerability Tests > Payment Link Expiration Issues > should expose expired payment links remaining in active status ↓ Stripe Payment Integration - Vulnerability Tests > Integer Overflow and Precision Issues > should expose potential precision loss with large payment amounts ↓ Stripe Payment Integration - Vulnerability Tests > Customer Sharing Vulnerability > should expose potential customer sharing across tenants ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Wrong Redirect URLs in Payment Links > should generate correct client portal redirect URLs ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Refund Events Not Parsed Correctly > should parse charge.refunded events with correct amount and currency ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Refund Events Not Parsed Correctly > should process charge.refunded webhook and record refund ↓ Stripe Payment Integration - Vulnerability Tests > BUG: sessionId Parameter Not Used in Verification > should verify the specific session, not just invoice status ↓ Stripe Payment Integration - Vulnerability Tests > BUG: Incorrect Payment Method Recording > should record payment method as "stripe" not "stripe_stripe" ✓ server/src/test/unit/workflowsEntryTypingGuard.unit.test.ts (2 tests) 0ms 201 MB heap used stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > appends tenant when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: null, runnerBase: undefined, publicBase: '/runner' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > supports relative public base for gateway proxy [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: '/runner', publicBase: '/runner' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > uses absolute public base when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/settings', tenantId: undefined, overrideBase: null, runnerBase: 'https://runner.dev/alga', publicBase: 'https://runner.dev/alga' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > honors public base override [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: 'http://localhost:8085', runnerBase: undefined, publicBase: 'http://localhost:8085' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > falls back to /runner when no public base is set [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: undefined, publicBase: '/runner' }
✓ ee/server/src/lib/extensions/tests/assets/url.shared.test.ts (5 tests) 1ms 204 MB heap used ❯ shared/workflow/actions/tests/emailWorkflowActions.responseSource.test.ts (6 tests | 5 failed) 15ms 214 MB heap used × createCommentFromEmail response source metadata > T002: persists metadata.responseSource=inbound_email 0ms → trx is not a function × createCommentFromEmail response source metadata > T003: includes normalized provider type when available 0ms → trx is not a function × createCommentFromEmail response source metadata > google inbound flow resolves to inbound_email metadata source (T017) 0ms → trx is not a function × createCommentFromEmail response source metadata > microsoft inbound flow resolves to inbound_email metadata source (T018) 0ms → trx is not a function × createCommentFromEmail response source metadata > imap inbound flow resolves to inbound_email metadata source (T019) 15ms → trx is not a function ✓ createCommentFromEmail response source metadata > T020: keeps comment response-state semantics unchanged (still non-internal) 0ms ✓ tools/nx-tests/nxWorkspace.test.ts (3 tests) 16520ms 216 MB heap used ✓ nx workspace > initializes and lists projects 423ms ✓ nx workspace > can generate an nx graph html file 15535ms ✓ nx workspace > runs the alga-module generator in dry-run mode 560ms stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts > Internal Notification Preferences (integration) Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/internal-notifications/notificationPreferences.integration.test.ts (5 tests | 5 skipped) 34ms 109 MB heap used ↓ Internal Notification Preferences (integration) > creates a notification when preferences allow it ↓ Internal Notification Preferences (integration) > does not create a notification when category preference is disabled ↓ Internal Notification Preferences (integration) > allows subtype preference to override disabled category ↓ Internal Notification Preferences (integration) > renders notification using user locale when localized template exists ↓ Internal Notification Preferences (integration) > falls back to English template while preserving user locale when translation is missing ↓ server/src/test/integration/inboundEmailInApp.webhooks.integration.test.ts (11 tests | 11 skipped) stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Shutdown > should cleanup on shutdown [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Shutdown > should cleanup on shutdown [DelayedEmailQueue] Shutting down... [DelayedEmailQueue] Shutdown complete
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should not process emails that are not ready yet [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Found ready emails { count: 5 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing queued email { id: 't1-email-1', tenantId: 'tenant-1', to: 'user1@tenant1.com', retryCount: 1 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing queued email { id: 't2-email-1', tenantId: 'tenant-2', to: 'user1@tenant2.com', retryCount: 1 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process one email per tenant for fair scheduling [DelayedEmailQueue] Processing cycle complete { processedCount: 2, durationMs: 0 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Found ready emails { count: 1 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Processing queued email { id: 'test-id-1', tenantId: 'tenant-1', to: 'test@example.com', retryCount: 1 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Process Ready > should process emails that are ready [DelayedEmailQueue] Processing cycle complete { processedCount: 1, durationMs: 0 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Stats > should return zero when queue is empty [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Stats > should return pending count [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Processing loop started { intervalMs: 100000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 100000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Found ready emails { count: 1 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Processing queued email { id: 'test-id-1', tenantId: 'tenant-1', to: 'test@example.com', retryCount: 3 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Retry Count Tracking > should increment retry count on each processing [DelayedEmailQueue] Processing cycle complete { processedCount: 1, durationMs: 1 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Enqueue > should enqueue email with correct delay [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Enqueue > should enqueue email with correct delay [DelayedEmailQueue] Email enqueued for retry { id: '1770926054867-gxjbfn9vg', tenantId: 'tenant-1', to: 'test@example.com', retryCount: 0, readyAt: '2026-02-12T19:55:19.349Z', delayMs: 64482 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Initialization > should warn if initialized twice [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }
stdout | server/src/test/unit/notifications/delayedEmailQueue.test.ts > DelayedEmailQueue > Initialization > should initialize with Redis client and callback [DelayedEmailQueue] Processing loop started { intervalMs: 10000 } [DelayedEmailQueue] Initialized successfully { maxRetries: 5, baseDelayMs: 60000, maxDelayMs: 900000, checkIntervalMs: 10000 }
✓ server/src/test/unit/notifications/delayedEmailQueue.test.ts (18 tests) 3ms 111 MB heap used stdout | sdk/samples/component/secrets-demo/tests/handler.test.ts > handler > echoes secrets and config [mock logging] [secrets-demo] request start tenant=tenant-123 requestId=req-1 method=GET url=/demo configKeys=1 secrets=1 build=2025-11-11T17:34:00Z
stdout | sdk/samples/component/secrets-demo/tests/handler.test.ts > handler > echoes secrets and config [mock logging] [secrets-demo] greeting secret resolved; emitting response
stdout | sdk/samples/component/secrets-demo/tests/handler.test.ts > handler > echoes secrets and config [mock logging] [secrets-demo] request complete requestId=req-1 status=200 build=2025-11-11T17:34:00Z
✓ sdk/samples/component/secrets-demo/tests/handler.test.ts (1 test) 0ms 113 MB heap used stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/imports/importWorkflow.integration.test.ts > Asset import integration Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/imports/importWorkflow.integration.test.ts (3 tests | 3 skipped) 2ms 132 MB heap used ↓ Asset import integration > registers default CSV/RMM importers in the database ↓ Asset import integration > generates preview summaries with validation and duplicate detection for N-able exports ↓ Asset import integration > detects duplicates via MAC normalization and fuzzy hostname matches ✓ ee/server/extensions/samples/ui-kit-showcase/test/scaffold.test.ts (8 tests) 1ms 134 MB heap used stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/calendar/webhookProcessing.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Initializing event bus [EventBus] Creating new Redis client [RedisConfig] Using configuration: { url: 'redis://localhost:6379', prefix: 'alga-psa:', eventBus: { streamPrefix: 'event-stream:', consumerGroup: 'event-processors', maxStreamLength: 1000, blockingTimeout: 5000, claimTimeout: 30000, batchSize: 10, reconnectStrategy: { retries: 10, initialDelay: 100, maxDelay: 3000 } } } Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout CompositeSecretProvider found app secret 'redis_password' from provider 1
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout Retrieved secret 'redis_password' from configured provider.
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Redis Client Connected [EventBus] Redis Client Ready
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_CREATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_UPDATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_CLOSED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_DELETED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_ASSIGNED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_ADDITIONAL_AGENT_ASSIGNED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_COMMENT_ADDED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_COMMENT_UPDATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_RESPONSE_STATE_CHANGED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_STATUS_CHANGED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_PRIORITY_CHANGED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_UNASSIGNED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_REOPENED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_ESCALATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_QUEUE_CHANGED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_MESSAGE_ADDED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_CUSTOMER_REPLIED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_INTERNAL_NOTE_ADDED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_SLA_STAGE_ENTERED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_SLA_STAGE_MET
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TICKET_SLA_STAGE_BREACHED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_CREATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_UPDATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_CLOSED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_ASSIGNED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_TASK_ASSIGNED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:PROJECT_TASK_ADDITIONAL_AGENT_ASSIGNED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TASK_COMMENT_ADDED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TASK_COMMENT_UPDATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TIME_ENTRY_SUBMITTED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:TIME_ENTRY_APPROVED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:INVOICE_GENERATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:INVOICE_FINALIZED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CUSTOM_EVENT
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:INBOUND_EMAIL_RECEIVED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:ACCOUNTING_EXPORT_COMPLETED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:ACCOUNTING_EXPORT_FAILED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:SCHEDULE_ENTRY_CREATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:SCHEDULE_ENTRY_UPDATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:SCHEDULE_ENTRY_DELETED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_SYNC_STARTED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_SYNC_COMPLETED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_SYNC_FAILED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:CALENDAR_CONFLICT_DETECTED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:MESSAGE_SENT
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:USER_MENTIONED_IN_DOCUMENT
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_CREATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_APPROVED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_DECLINED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:APPOINTMENT_REQUEST_CANCELLED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_CREATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_UPDATED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_DELETED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_ONLINE
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_DEVICE_OFFLINE
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_ALERT_TRIGGERED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_ALERT_RESOLVED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_SYNC_STARTED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_SYNC_COMPLETED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_SYNC_FAILED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Created consumer group for stream: alga-psa:event-stream:global:RMM_WEBHOOK_RECEIVED
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] No active subscriptions, waiting for handlers to be registered
stdout | packages/event-bus/src/index.hardTimeout.test.ts > EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout [EventBus] Added handler: { eventType: 'TICKET_CREATED', channel: 'global', handlerName: '', handlersCount: 1 }
❯ packages/event-bus/src/index.hardTimeout.test.ts (1 test | 1 failed) 34ms 209 MB heap used × EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout 34ms → expected 1 to be greater than or equal to 2 ✔ T001: fails with clear error when --test is missing (51.485041ms) ✔ T002: fails with clear error when bundle.json is missing (48.800541ms) ✔ T003: fails with clear error when test.cjs is missing (46.599083ms) stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/auditTrail.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/tickets.e2e.test.ts (47 tests | 47 skipped) 2ms 275 MB heap used ↓ Ticket API E2E Tests > Authentication > should require API key for all endpoints ↓ Ticket API E2E Tests > Authentication > should reject invalid API key ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create a new ticket ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should validate required fields ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create ticket with all optional fields ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should retrieve a ticket by ID ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should return 404 for non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should not return tickets from other tenants ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should update a ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should return 404 when updating non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should validate update data ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should delete a ticket ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should return 404 when deleting non-existent ticket ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should list all tickets with default pagination ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should support pagination parameters ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by client_id ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by status ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by priority ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by assigned user ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter overdue tickets ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should sort tickets by created date ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search tickets by query ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search in specified fields ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should limit search results ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add a comment to a ticket ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add an internal comment ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should list ticket comments ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should return 404 when adding comment to non-existent ticket ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should update ticket status ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should validate status transitions ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should assign ticket to user ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should unassign ticket ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should return ticket statistics ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by date range ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by client ↓ Ticket API E2E Tests > Create Ticket from Asset (POST /api/v1/tickets/from-asset) > should create ticket from asset ↓ Ticket API E2E Tests > Error Handling > should handle invalid UUID format ↓ Ticket API E2E Tests > Error Handling > should handle invalid query parameters ↓ Ticket API E2E Tests > Error Handling > should handle missing required fields on create ↓ Ticket API E2E Tests > Error Handling > should handle invalid date formats ↓ Ticket API E2E Tests > Permissions > should enforce read permissions for GET endpoints ↓ Ticket API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE ↓ Ticket API E2E Tests > Permissions > should enforce assignment permissions ↓ Ticket API E2E Tests > Multi-tenancy > should isolate tickets by tenant ↓ Ticket API E2E Tests > Advanced Features > should support bulk operations ↓ Ticket API E2E Tests > Advanced Features > should support ticket templates ↓ Ticket API E2E Tests > Advanced Features > should track ticket history stdout | server/src/test/unit/ticketPermissions.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/ticketPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/ticketPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":"PO-XYZ"} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""},{"type": "Text", "content": "PO #: PO-XYZ", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}
stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":null} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}
✓ server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts (1 test) 1436ms 293 MB heap used ✓ server/src/test/unit/email/replyTokenExtraction.test.ts (10 tests) 3ms 263 MB heap used ❯ ee/temporal-workflows/src/activities/tests/email-activities-standalone.test.ts (8 tests | 5 failed) 3ms 268 MB heap used × Email Activities - Standalone Tests > Password Generation > should generate secure passwords with default length 0ms → expected Promise{…} to have property 'length' × Email Activities - Standalone Tests > Password Generation > should generate passwords with custom length 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Standalone Tests > Password Generation > should generate unique passwords 0ms × Email Activities - Standalone Tests > Email Activity > should send welcome email successfully 0ms → expected false to be true // Object.is equality × Email Activities - Standalone Tests > Email Activity > should handle invalid email gracefully 1ms → expected 'Tenant ID must be a UUID with 32 hex …' to contain 'Invalid email address' × Email Activities - Standalone Tests > Email Activity > should work with minimal required fields 0ms → expected false to be true // Object.is equality ✓ Email Activities - Standalone Tests > Mock Email Service Integration > should validate email service templates 0ms ✓ Email Activities - Standalone Tests > Mock Email Service Integration > should handle unknown templates 0ms ✓ packages/tickets/src/lib/timeEntryContext.test.ts (3 tests) 0ms 223 MB heap used stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/timeEntryBillingContractLineSelection.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/core/src/lib/events/publisher.test.ts (1 test) 3ms 266 MB heap used stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/services/chatCompletionsService.streaming.test.ts (1 test) 96ms 278 MB heap used ✓ server/src/test/unit/internal-notifications/mentionParser.test.ts (28 tests) 2ms 283 MB heap used ❯ server/src/test/integration/internal-notifications/mentionNotifications.integration.test.ts (2 tests | 2 skipped) 19ms 286 MB heap used ↓ Mention notifications via TICKET_COMMENT_ADDED > creates notifications for mentioned users and excludes the author ↓ Mention notifications via TICKET_COMMENT_ADDED > does not notify client portal contact for internal comments ✓ server/src/test/unit/services/numberingService.test.ts (5 tests) 2ms 290 MB heap used ✓ ee/extensions/samples/ui-kit-showcase/test/scaffold.test.ts (8 tests) 1ms 293 MB heap used ❯ packages/ui/src/context/SchedulingContext.test.tsx (4 tests | 4 failed) 1ms 297 MB heap used × SchedulingContext > returns default callbacks when no provider is present 0ms → document is not defined × SchedulingContext > renders fallback alert element for agent schedule by default 0ms → document is not defined × SchedulingContext > shows a toast when launching time entry without provider 1ms → document is not defined × SchedulingContext > uses provider callbacks when SchedulingCallbackProvider is present 0ms → document is not defined stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts > BaseEmailService → email_sending_logs Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/email/baseEmailServiceLogging.integration.test.ts (2 tests | 2 skipped) 2ms 243 MB heap used ↓ BaseEmailService → email_sending_logs > successful send creates log entry with status sent ↓ BaseEmailService → email_sending_logs > failed send creates log entry with status failed and error_message ❯ server/src/test/integration/billing/invoiceStatusManagement.integration.test.ts (10 tests | 10 skipped) 1ms 246 MB heap used ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to partially_applied when partial credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should set status to paid when full credit is applied ↓ Invoice Status Management Integration > Credit Application Status Transitions > should accumulate multiple partial credits and update status accordingly ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to partially_applied when partial payment is recorded ↓ Invoice Status Management Integration > Payment Recording Status Transitions > should set status to paid when full payment is recorded ↓ Invoice Status Management Integration > Combined Payment and Credit Scenarios > should correctly calculate status with both payments and credits ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to partially_applied when partial refund is recorded ↓ Invoice Status Management Integration > Refund Handling and Status Reversals > should transition from paid to sent when full refund is recorded ↓ Invoice Status Management Integration > Status Transition Validation > should not allow payment on cancelled invoice ↓ Invoice Status Management Integration > Status Transition Validation > should not allow credit on draft invoice stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle database errors gracefully Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/contacts.e2e.test.ts > Contact API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/contacts.e2e.test.ts (29 tests | 29 failed) 22ms 259 MB heap used × Contact API E2E Tests > Authentication > should require API key for all endpoints 1ms → × Contact API E2E Tests > Authentication > should reject invalid API key 1ms → × Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should create a new contact 1ms → × Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate required fields 1ms → × Contact API E2E Tests > CRUD Operations > Create Contact (POST /api/v1/contacts) > should validate email format 1ms → × Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should retrieve a contact by ID 1ms → × Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should return 404 for non-existent contact 1ms → × Contact API E2E Tests > CRUD Operations > Get Contact (GET /api/v1/contacts/:id) > should not return contacts from other tenants 1ms → × Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should update a contact 1ms → × Contact API E2E Tests > CRUD Operations > Update Contact (PUT /api/v1/contacts/:id) > should return 404 when updating non-existent contact 1ms → × Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should delete a contact 1ms → × Contact API E2E Tests > CRUD Operations > Delete Contact (DELETE /api/v1/contacts/:id) > should return 404 when deleting non-existent contact 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should list all contacts with default pagination 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should support pagination parameters 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by client_id 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should filter by is_inactive status 1ms → × Contact API E2E Tests > List Contacts (GET /api/v1/contacts) > should sort contacts by name 1ms → × Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search contacts by query 1ms → × Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should search in specified fields 1ms → × Contact API E2E Tests > Search Contacts (GET /api/v1/contacts/search) > should limit search results 1ms → × Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as CSV 1ms → × Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export contacts as JSON 1ms → × Contact API E2E Tests > Export Contacts (GET /api/v1/contacts/export) > should export only active contacts by default 1ms → × Contact API E2E Tests > Contact Statistics (GET /api/v1/contacts/stats) > should return contact statistics 1ms → × Contact API E2E Tests > Error Handling > should handle invalid query parameters 1ms → × Contact API E2E Tests > Error Handling > should handle database errors gracefully 1ms → × Contact API E2E Tests > Permissions > should enforce read permissions for GET endpoints 1ms → × Contact API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE 1ms → × Contact API E2E Tests > Multi-tenancy > should isolate contacts by tenant 1ms → ↓ server/src/test/integration/inboundEmailInApp.featureFlag.integration.test.ts (1 test | 1 skipped) ❯ server/src/lib/eventBus/index.hardTimeout.test.ts (1 test | 1 failed) 4ms 266 MB heap used × EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout 4ms → Failed to resolve entry for package "@alga-psa/event-schemas". The package may have incorrect main/module/exports specified in its package.json. stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts > Internal notification CRUD (integration) Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/internal-notifications/notificationCrud.integration.test.ts (6 tests | 6 skipped) 8ms 275 MB heap used ↓ Internal notification CRUD (integration) > creates notification with metadata and default locale ↓ Internal notification CRUD (integration) > supports locale preference during creation ↓ Internal notification CRUD (integration) > paginates and filters notifications ↓ Internal notification CRUD (integration) > returns unread counts with category breakdown ↓ Internal notification CRUD (integration) > marks notification as read with timestamp and broadcast ↓ Internal notification CRUD (integration) > marks all notifications as read and soft deletes ✓ server/src/test/unit/workflowBundleCli.unit.test.ts (2 tests) 4ms 279 MB heap used ✓ server/src/test/unit/readAssistantContentFromSse.test.ts (1 test) 1ms 281 MB heap used ✓ packages/billing/tests/draftContractsActions.test.ts (6 tests) 19ms 288 MB heap used ✓ packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts (5 tests) 0ms 291 MB heap used ✓ packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (6 tests) 1ms 298 MB heap used ✓ sdk/samples/component/scheduler-demo/tests/handler.test.ts (6 tests) 1ms 302 MB heap used ✓ server/src/test/unit/api/chatExecute.route.gating.test.ts (1 test) 4ms 251 MB heap used ❯ packages/msp-composition/src/scheduling/MspSchedulingProvider.test.tsx (2 tests | 2 failed) 1ms 257 MB heap used × MspSchedulingProvider > provides renderAgentSchedule that returns AgentScheduleView 0ms → document is not defined × MspSchedulingProvider > provides launchTimeEntry that calls launchTimeEntryForWorkItem 0ms → document is not defined ✓ packages/scheduling/tests/scheduleEntry.test.ts (16 tests) 4ms 266 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerShell.fitSection.test.ts (11 tests) 1ms 276 MB heap used 2026-02-12T19:54:19.842538Z WARN temporalio_sdk_core::worker:💓 Worker heartbeating configured for runtime, but server version does not support it. 2026-02-12T19:54:20.240112Z WARN temporalio_sdk_core::worker:💓 Worker heartbeating configured for runtime, but server version does not support it. 2026-02-12T19:54:20.597915Z WARN temporalio_sdk_core::worker:💓 Worker heartbeating configured for runtime, but server version does not support it. ✓ ee/temporal-workflows/src/workflows/portal-domains/tests/registration.workflow.integration.test.ts (3 tests) 1776ms 430 MB heap used ✓ portalDomainRegistrationWorkflow > marks the domain as certificate_failed when ACME registration fails 343ms ✓ portalDomainRegistrationWorkflow > moves the domain to deploying after applying resources 1062ms ✓ portalDomainRegistrationWorkflow > retries after a failure and succeeds on the next attempt 371ms stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/exportDashboard.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ ee/server/src/tests/unit/schedulerHostApi.unit.test.ts (72 tests) 6ms 424 MB heap used ✓ ee/server/src/lib/extensions/tests/manifest-v2.schema.test.ts (5 tests) 1ms 433 MB heap used stdout | server/src/test/integration/emailProviderCreation.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/src/components/invoice-designer/state/designerStore.size.test.ts (4 tests) 4ms 294 MB heap used stdout | shared/lib/utils/contentConversion.test.ts > convertHtmlToBlockNote > should handle linked images (image inside anchor) Linked Image Result: { "type": "link", "href": "https://google.com", "content": [ { "type": "text", "text": "🖼️ Logo", "styles": {} } ] }
✓ shared/lib/utils/contentConversion.test.ts (14 tests) 7ms 300 MB heap used ✓ server/src/test/unit/mention-detection.test.ts (12 tests) 1ms 304 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewModel.test.ts (5 tests) 1ms 313 MB heap used ❯ server/src/test/infrastructure/billing/invoices/clientBillingCycle.test.ts (1 test | 1 skipped) 2ms 319 MB heap used ↓ Client Billing Cycle Creation > creates a monthly billing cycle if none exists stdout | server/src/test/integration/emailProviderDatabase.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderDatabase.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderDatabase.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderDatabase.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderDatabase.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderDatabase.test.ts > Email Provider Database Integration Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/emailProviderDatabase.test.ts (6 tests | 6 skipped) 1ms 337 MB heap used ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should create a Google provider record in the database ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should handle Google Workspace email addresses ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should update an existing Google provider ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should list all Google providers for a tenant ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should handle provider creation with all optional fields ↓ Email Provider Database Integration Tests > Google Provider Database Operations > should enforce database constraints stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/surveyEmailTemplates.integration.test.ts (2 tests | 2 skipped) 2ms 342 MB heap used ↓ Survey email templates > registers system templates for each supported locale ↓ Survey email templates > renders locale-specific content and falls back to English ✓ packages/billing/src/components/invoice-designer/state/designerStore.layoutMode.test.ts (2 tests) 3ms 354 MB heap used ✓ server/src/test/unit/resendWebhookEvents.test.ts (8 tests) 2ms 300 MB heap used stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/imports/FieldMapper.test.ts (2 tests) 1ms 333 MB heap used stdout | server/src/test/unit/db/workDate.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/db/workDate.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/db/workDate.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/db/workDate.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/db/workDate.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/db/workDate.test.ts (1 test) 3ms 339 MB heap used stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🏗️ Initializing Email Settings Test Fixture (one-time setup)... 📊 Setting up database and services... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🧹 Final test fixture cleanup...
❯ server/src/test/e2e/email-settings/oauth-flow.test.ts (7 tests | 7 skipped) 3ms 352 MB heap used ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should complete OAuth flow and store tokens ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle OAuth error scenarios ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle Microsoft webhook validation token ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should complete OAuth flow with Pub/Sub setup ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should handle expired refresh token ↓ Email Settings OAuth Flow Tests > Token Storage and Encryption > should store tokens securely in database ↓ Email Settings OAuth Flow Tests > State Parameter Validation > should validate state parameter in OAuth callback stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.
❯ shared/services/email/tests/EmailWebhookMaintenanceService.test.ts (3 tests | 1 failed) 2ms 362 MB heap used ✓ EmailWebhookMaintenanceService > should find candidates and renew expired subscription 0ms × EmailWebhookMaintenanceService > should recreate subscription if renewal fails with 404 1ms → expected "spy" to be called with arguments: [ 'https://api.example.com/webhook' ]
Number of calls: 0
✓ EmailWebhookMaintenanceService > should handle unexpected errors gracefully 0ms ✓ packages/auth/src/lib/session.test.ts (6 tests) 3ms 350 MB heap used stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderErrorMessages.test.ts > Email Provider Error Messages Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/emailProviderErrorMessages.test.ts (10 tests | 10 skipped) 1ms 360 MB heap used ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error when provider name is missing ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error when email is invalid ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error when Google Client ID is missing ↓ Email Provider Error Messages > User-Friendly Error Messages > should return multiple errors in a clear format ↓ Email Provider Error Messages > User-Friendly Error Messages > should return helpful error for invalid provider type ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error for provider name that is too long ↓ Email Provider Error Messages > User-Friendly Error Messages > should return helpful error for invalid Microsoft tenant ID ↓ Email Provider Error Messages > User-Friendly Error Messages > should return clear error for invalid max emails per sync ↓ Email Provider Error Messages > User-Friendly Error Messages > should return helpful hint for Google Client ID format ↓ Email Provider Error Messages > User-Friendly Error Messages > should successfully create provider when all fields are valid stdout | server/src/test/unit/templateRenderer.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/templateRenderer.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/templateRenderer.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/templateRenderer.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/templateRenderer.test.tsx Retrieved secret 'db_password_server' from configured provider.
✓ tools/nx-tests/nxCache.test.ts (2 tests) 3726ms 356 MB heap used ✓ nx caching > reuses the local computation cache for repeated builds 732ms ✓ nx caching > caches @alga-psa/core builds when unchanged 2994ms ❯ ee/temporal-workflows/src/activities/tests/email-activities-simple.test.ts (24 tests | 17 failed) 916ms 365 MB heap used × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with default length of 12 0ms → expected Promise{…} to have property 'length' × Email Activities - Simple Tests > generateTemporaryPassword > should generate password with custom length 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate different passwords each time 0ms × Email Activities - Simple Tests > generateTemporaryPassword > should contain at least one character from each category 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should not contain ambiguous characters 0ms → .toMatch() expects to receive a string, but got object × Email Activities - Simple Tests > generateTemporaryPassword > should handle minimum length of 4 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Simple Tests > generateTemporaryPassword > should generate secure passwords with high entropy 0ms × Email Activities - Simple Tests > MockEmailService > should send emails successfully 102ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should validate email addresses correctly 0ms × Email Activities - Simple Tests > MockEmailService > should track sent emails for testing 101ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should filter emails by recipient 102ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should simulate failures when configured 101ms × Email Activities - Simple Tests > MockEmailService > should handle invalid email addresses 101ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle multiple recipients 101ms → Cannot read properties of undefined (reading 'info') ✓ Email Activities - Simple Tests > MockEmailService > should throw error when no valid recipients 101ms × Email Activities - Simple Tests > MockEmailService > should support email service configuration 0ms → expected Promise{…} to be an instance of MockEmailService ✓ Email Activities - Simple Tests > MockEmailService > should return email templates for testing 0ms ✓ Email Activities - Simple Tests > MockEmailService > should return null for unknown templates 0ms × Email Activities - Simple Tests > MockEmailService > should support clearing sent emails 101ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > MockEmailService > should handle delay configuration 102ms → Cannot read properties of undefined (reading 'info') × Email Activities - Simple Tests > Email Service Factory > should create mock service by default 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should create mock service when explicitly requested 0ms → expected Promise{…} to be an instance of MockEmailService × Email Activities - Simple Tests > Email Service Factory > should throw error for unknown providers 0ms → expected [Function] to throw an error × Email Activities - Simple Tests > Email Service Factory > should pass options to mock service 0ms → expected Promise{…} to be an instance of MockEmailService ✓ tools/nx-tests/moduleBoundaries.test.ts (2 tests) 6ms 382 MB heap used ✓ packages/client-portal/src/actions/client-portal-actions/client-tickets.ticketOrigin.test.ts (4 tests) 15ms 392 MB heap used ❯ packages/core/src/index.test.ts (1 test | 1 failed) 48ms 303 MB heap used × @alga-psa/core public exports > exports logger, secrets, events, and encryption APIs 48ms → expected 'undefined' to be 'function' // Object.is equality ✓ server/src/test/integration/emailProviderIntegration.test.ts (11 tests) 5ms 313 MB heap used stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts > CalendarProviderService encryption helpers > encrypts and decrypts Microsoft provider credentials CompositeSecretProvider: app secret 'calendar_oauth_encryption_key' not found in any provider
stdout | server/src/test/unit/calendar/CalendarProviderEncryption.test.ts > CalendarProviderService encryption helpers > encrypts and decrypts Microsoft provider credentials Secret 'calendar_oauth_encryption_key' not found via provider, checking env var 'CALENDAR_OAUTH_ENCRYPTION_KEY'.
✓ server/src/test/unit/calendar/CalendarProviderEncryption.test.ts (3 tests) 1ms 321 MB heap used stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts > emailLogActions.getEmailLogs Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/email/emailLogActions.getEmailLogs.integration.test.ts (6 tests | 6 skipped) 2ms 334 MB heap used ↓ emailLogActions.getEmailLogs > returns paginated results ↓ emailLogActions.getEmailLogs > filters by date range when provided ↓ emailLogActions.getEmailLogs > treats date-only endDate as inclusive end of day ↓ emailLogActions.getEmailLogs > filters by status when provided ↓ emailLogActions.getEmailLogs > filters by recipient email when provided ↓ emailLogActions.getEmailLogs > supports sorting by sent_at ascending/descending ❯ server/src/test/integration/onboardingProgressSubsteps.integration.test.ts (1 test | 1 failed) 1ms 339 MB heap used × getOnboardingProgressAction (substeps) > returns portal + email steps with substeps 1ms → Cannot find package '@alga-psa/onboarding/actions' imported from '/Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/server/src/test/integration/onboardingProgressSubsteps.integration.test.ts' ✓ ee/server/src/tests/unit/routeParams.resolveInstallId.test.ts (3 tests) 0ms 343 MB heap used ✓ packages/msp-composition/src/packageDependencies.test.ts (1 test) 0ms 347 MB heap used ✓ packages/tickets/src/lib/tests/ticketOrigin.test.ts (5 tests) 0ms 354 MB heap used ✓ packages/tickets/src/components/ticket/TicketDetails.originBadge.contract.test.ts (3 tests) 2ms 362 MB heap used ❯ packages/tickets/src/components/ticket/AgentScheduleDrawer.test.tsx (2 tests | 2 failed) 1ms 317 MB heap used × AgentScheduleDrawer > renders calendar when provider is present 0ms → document is not defined × AgentScheduleDrawer > shows fallback alert when no provider is present 1ms → document is not defined ❯ server/src/test/integration/citusTenantFilterEmailProviders.integration.test.ts (2 tests | 2 failed) 2ms 321 MB heap used × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Microsoft webhook route 1ms → expected 'export { GET, POST } from '@alga-psa…' to contain '.where({ id: row.id, tenant: row.tena…' × Citus safety: tenant-scoped updates on distributed tables > scopes email_providers updates by tenant in Google webhook route 1ms → expected 'export { POST } from '@alga-psa/inte…' to contain '.where({ id: provider.id, tenant: pro…' stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/surveyTokenService.integration.test.ts > Survey Token Service integration Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/surveyTokenService.integration.test.ts (2 tests | 2 failed) 2ms 327 MB heap used × Survey Token Service integration > resolves invitation metadata for a valid survey token 0ms → × Survey Token Service integration > throws when the survey token has expired 0ms → ✓ packages/projects/src/lib/timeEntryContext.test.ts (1 test) 0ms 336 MB heap used ✓ server/src/test/unit/billing/billingCycleAnchors.validationMessages.test.ts (3 tests) 1ms 341 MB heap used ✓ packages/billing/tests/contractsTabs.test.ts (5 tests) 0ms 345 MB heap used stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ ee/server/src/tests/unit/invoicingInternalApi.unit.test.ts (1 test) 4ms 375 MB heap used stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/workflowRuntimeV2.e2e.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/utils/utilities.test.ts (13 tests | 13 failed) 792ms 381 MB heap used × E2E Test Utilities > Test Environment Setup > should create a complete test environment 39ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have a valid database connection 52ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a tenant 38ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a user 52ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created an API key 30ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should generate random contact data 42ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create a single contact 56ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create multiple contacts 49ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should build query strings correctly 50ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert successful responses 215ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert error responses 80ms → no such database: test_database × E2E Test Utilities > API Client > should have API key configured 44ms → no such database: test_database × E2E Test Utilities > API Client > should be able to make requests 45ms → no such database: test_database ✓ ee/server/src/lib/extensions/tests/runner/backend.test.ts (4 tests) 11ms 388 MB heap used stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/portalDomainSessionOtt.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/portalDomainSessionOtt.test.ts (5 tests) 3ms 345 MB heap used ✓ packages/projects/tests/packageDependencies.test.ts (1 test) 0ms 350 MB heap used stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateDocumentPreviews] Generating previews for document doc-2 (image/png)
stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateImagePreviews] Image dimensions: 1200x900
stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateImagePreviews] Thumbnail generated: thumb-1
stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > creates thumbnail and preview uploads for large images [generateImagePreviews] Preview generated: preview-2
stdout | server/src/test/unit/documentPreviewGenerator.test.ts > generateDocumentPreviews > skips storage uploads for unsupported mime types [generateDocumentPreviews] Generating previews for document doc-1 (text/plain) [generateDocumentPreviews] Unsupported file type: text/plain
✓ server/src/test/unit/documentPreviewGenerator.test.ts (2 tests) 2ms 373 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.selectionState.test.ts (9 tests) 1ms 379 MB heap used stdout | server/src/test/e2e/email-processing.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-processing.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-processing.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-processing.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-processing.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests 🧪 Initializing persistent E2E test context... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }
stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-processing.test.ts > Email Processing E2E Tests 🧹 Cleaning up persistent E2E test context...
❯ server/src/test/e2e/email-processing.test.ts (5 tests | 5 skipped) 2ms 350 MB heap used ↓ Email Processing E2E Tests > Basic Email Ingestion > should process a simple email and create a ticket ↓ Email Processing E2E Tests > Basic Email Ingestion > should handle emails with attachments ↓ Email Processing E2E Tests > Email Threading > should properly thread email replies ↓ Email Processing E2E Tests > Client Matching > should match emails to existing clients ↓ Email Processing E2E Tests > Client Matching > should handle unknown email addresses with manual fallback ✓ tools/nx-tests/nxAffected.test.ts (2 tests) 621ms 357 MB heap used ✓ nx affected > includes @alga-psa/clients when client code changes 334ms ↓ server/src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.ts (1 test | 1 skipped) ✓ server/src/test/unit/enterpriseAliasEnvSwitch.unit.test.ts (2 tests) 197ms 369 MB heap used ❯ server/src/test/integration/internal-notifications/eventSubscribers.integration.test.ts (14 tests | 14 skipped) 2ms 375 MB heap used ↓ internal notification event subscriber registration > subscribes to all expected event types on the internal channel ↓ internal notification event handling > creates notification for ticket assignment events targeting the assignee ↓ internal notification event handling > creates notifications for ticket additional agent assignments (agent, primary assignee, and client) ↓ internal notification event handling > does not invoke notification creation for events without handlers ↓ internal notification event handling > creates notifications for ticket created events for assignee and portal contact ↓ internal notification event handling > creates status change notifications for ticket updated events ↓ internal notification event handling > creates notifications for ticket closed events including client portal user ↓ internal notification event handling > creates project created notifications for assigned user ↓ internal notification event handling > creates project assigned notifications ↓ internal notification event handling > creates project task assigned notifications ↓ internal notification event handling > creates project task additional agent notifications for the new agent and the primary assignee ↓ internal notification event handling > creates invoice generated notifications ↓ internal notification event handling > creates message sent notifications for recipients ↓ internal notification event handling > creates document mention notifications ❯ server/src/test/unit/clientContractActions.overlapExclusive.test.ts (3 tests | 3 failed) 2ms 380 MB heap used × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (start == invoiced period end) 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > does not treat touching boundaries as overlap (end exclusive == invoiced period start) 1ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package × Client contract overlap validation ([start, end) semantics) > rejects true overlaps with an invoiced period 0ms → Missing "./models/clientContract" specifier in "@alga-psa/clients" package ✓ server/src/test/unit/RightSidebar.streaming.test.tsx (1 test) 486ms 87 MB heap used ✓ RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 485ms ❯ packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 52ms 118 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 32ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
✓ packages/projects/tests/projectInfoDrawer.test.tsx (1 test) 43ms 77 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 7 failed) 4053ms 113 MB heap used × ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 1003ms → Found multiple elements with the text: AI Assistant
Here are the matching elements:
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"font-medium"[39m [36m>[39m [0mAI Assistant[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Ignored nodes: comments, script, style [36m[39m [36m
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 166ms 140 MB heap used ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 249ms 294 MB heap used stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 219ms 308 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 35ms 342 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.constraintHighlights.test.tsx (2 tests) 3ms 347 MB heap used ✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 2ms 331 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1559ms 376 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 316ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 619ms ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1264ms 271 MB heap used stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' } iframeBridge: posting apiproxy_response { requestId: 'req-123', targetOrigin: '*' }
❯ ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 3 failed) 141ms 254 MB heap used × Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 58ms → expected "spy" to be called with arguments: [ StringContaining{…}, …(1) ]
Number of calls: 0
✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 57ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 3ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 24ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? ❯ server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests | 3 failed) 92ms 264 MB heap used ✓ TicketEmailNotifications > renders without errors 1ms ✓ TicketEmailNotifications > is collapsed by default and expands on click 10ms ✓ TicketEmailNotifications > shows loading state while fetching 11ms × TicketEmailNotifications > displays timestamp, recipient, subject, and status for each log entry 12ms → Found multiple elements with the text: /2026/
Here are the matching elements:
Ignored nodes: comments, script, style [36m<div[39m [33mclass[39m=[32m"min-w-0"[39m [36m>[39m [0m1/1/2026[0m [36m[39m
Ignored nodes: comments, script, style [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<table[39m [33mclass[39m=[32m"w-full divide-y divide-[rgb(var(--color-border-200))]"[39m [36m>[39m [36m<thead[39m [33mclass[39m=[32m"bg-background"[39m [36m>[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mContract Name[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-client_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mClient[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-created_at"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mCreated[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-updated_at"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mLast Modified[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m>[39m [0m ↓[0m [36m[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-contract_id"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mActions[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<tbody[39m [33mclass[39m=[32m"divide-y divide-gray-100"[39m [36m>[39m [36m<tr[39m [33mclass[39m=[32m" bg-[rgb(var(--color-border-50))] cursor-default transition-colors
"[39m
[36m>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-contract_name"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0mDraft Alpha[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-client_name"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0mAcme Co[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-created_at"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0m12/31/2025[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-updated_at"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0m1/1/2026[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-contract_id"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[36m<button[39m
[33maria-expanded[39m=[32m"false"[39m
[33maria-haspopup[39m=[32m"menu"[39m
[33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group"[39m
[33mdata-state[39m=[32m"closed"[39m
[33mtype[39m=[32m"button"[39m
[36m>[39m
[36m<span[39m
[33mclass[39m=[32m"sr-only"[39m
[36m>[39m
[0mOpen menu[0m
[36m</span>[39m
[36m<svg[39m
[33mclass[39m=[32m"lucide lucide-ellipsis-vertical h-4 w-4"[39m
[33mfill[39m=[32m"none"[39m
[33mheight[39m=[32m"24"[39m
[33mstroke[39m=[32m"currentColor"[39m
[33mstroke-linecap[39m=[32m"round"[39m
[33mstroke-linejoin[39m=[32m"round"[39m
[33mstroke-width[39m=[32m"2"[39m
[33mviewBox[39m=[32m"0 0 24 24"[39m
[33mwidth[39m=[32m"24"[39m
[33mxmlns[39m=[32m"http://www.w3.org/2000/svg"[39m
[36m>[39m
[36m<circle[39m
[33mcx[39m=[32m"12"[39m
[33mcy[39m=[32m"12"[39m
[33mr[39m=[32m"1"[39m
[36m/>[39m
[36m<circle[39m
[33mcx[39m=[32m"12"[39m
[33mcy[39m=[32m"5"[39m
[33mr[39m=[32m"1"[39m
[36m/>[39m
[36m<circle[39m
[33mcx[39m=[32m"12"[39m
[33mcy[39m=[32m"19"[39m
[33mr[39m=[32m"1"[39m
[36m/>[39m
[36m</svg>[39m
[36m</button>[39m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m</tr>[39m
[36m[39m [36m[39m
Ignored nodes: comments, script, style [36m<table[39m [33mdata-automation-id[39m=[32m"ticket-email-notifications-table"[39m [36m>[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser0@example.com[0m [36m[39m [36m[39m [0mS0[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser1@example.com[0m [36m[39m [36m[39m [0mS1[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser2@example.com[0m [36m[39m [36m[39m [0mS2[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser3@example.com[0m [36m[39m [36m[39m [0mS3[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser4@example.com[0m [36m[39m [36m[39m [0mS4[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser5@example.com[0m [36m[39m [36m[39m [0mS5[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser6@example.com[0m [36m[39m [36m[39m [0mS6[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser7@example.com[0m [36m[39m [36m[39m [0mS7[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser8@example.com[0m [36m[39m [36m[39m [0mS8[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser9@example.com[0m [36m[39m [36m[39m [0mS9[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser10@example.com[0m [36m[39m [36m[39m [0mS10[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser11@example.com[0m [36m[39m [36m[39m [0mS11[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser12@example.com[0m [36m[39m [36m[39m [0mS12[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser13@example.com[0m [36m[39m [36m[39m [0mS13[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser14@example.com[0m [36m[39m [36m[39m [0mS14[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser15@example.com[0m [36m[39m [36m[39m [0mS15[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser16@example.com[0m [36m[39m [36m[39m [0mS16[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser17@example.com[0m [36m[39m [36m[39m [0mS17[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser18@example.com[0m [36m[39m [36m[39m [0mS18[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser19@example.com[0m [36m[39m [36m[39m [0mS19[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<table[39m [33mclass[39m=[32m"w-full divide-y divide-[rgb(var(--color-border-200))]"[39m [36m>[39m [36m<thead[39m [33mclass[39m=[32m"bg-background"[39m [36m>[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-contract_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mContract Name[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-client_name"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mClient[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-created_at"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mCreated[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-updated_at"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mLast Modified[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m>[39m [0m ↓[0m [36m[39m [36m[39m [36m[39m [36m<th[39m [33mclass[39m=[32m"px-6 py-3 text-xs font-medium text-[rgb(var(--color-text-700))] tracking-wider transition-colors cursor-pointer hover:bg-muted text-left"[39m [33mid[39m=[32m"draft-contracts-table-header-contract_id"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"flex space-x-1 items-center"[39m [36m>[39m [36m[39m [0mActions[0m [36m[39m [36m<span[39m [33mclass[39m=[32m"text-muted-foreground"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<tbody[39m [33mclass[39m=[32m"divide-y divide-gray-100"[39m [36m>[39m [36m<tr[39m [33mclass[39m=[32m" bg-[rgb(var(--color-border-50))] cursor-default transition-colors
"[39m
[36m>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-contract_name"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0mDraft Alpha[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-client_name"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0mAcme Co[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-created_at"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0m12/31/2025[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-updated_at"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[0m1/1/2026[0m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m<td[39m
[33mclass[39m=[32m"px-6 py-3 text-[14px] leading-relaxed text-[rgb(var(--color-text-700))] max-w-0 align-top "[39m
[33mdata-automation-id[39m=[32m"draft-contracts-table-cell-0-contract_id"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"break-words min-w-0 [&_button:not(.whitespace-normal)]:whitespace-nowrap [&_a:not(.whitespace-normal)]:whitespace-nowrap"[39m
[36m>[39m
[36m<div[39m
[33mclass[39m=[32m"min-w-0"[39m
[36m>[39m
[36m<button[39m
[33maria-expanded[39m=[32m"false"[39m
[33maria-haspopup[39m=[32m"menu"[39m
[33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative text-[rgb(var(--color-text-700))] hover:bg-[rgb(var(--color-primary-50))] hover:text-[rgb(var(--color-primary-700))] h-8 w-8 p-0 group"[39m
[33mdata-state[39m=[32m"closed"[39m
[33mtype[39m=[32m"button"[39m
[36m>[39m
[36m<span[39m
[33mclass[39m=[32m"sr-only"[39m
[36m>[39m
[0mOpen menu[0m
[36m</span>[39m
[36m<svg[39m
[33mclass[39m=[32m"lucide lucide-ellipsis-vertical h-4 w-4"[39m
[33mfill[39m=[32m"none"[39m
[33mheight[39m=[32m"24"[39m
[33mstroke[39m=[32m"currentColor"[39m
[33mstroke-linecap[39m=[32m"round"[39m
[33mstroke-linejoin[39m=[32m"round"[39m
[33mstroke-width[39m=[32m"2"[39m
[33mviewBox[39m=[32m"0 0 24 24"[39m
[33mwidth[39m=[32m"24"[39m
[33mxmlns[39m=[32m"http://www.w3.org/2000/svg"[39m
[36m>[39m
[36m<circle[39m
[33mcx[39m=[32m"12"[39m
[33mcy[39m=[32m"12"[39m
[33mr[39m=[32m"1"[39m
[36m/>[39m
[36m<circle[39m
[33mcx[39m=[32m"12"[39m
[33mcy[39m=[32m"5"[39m
[33mr[39m=[32m"1"[39m
[36m/>[39m
[36m<circle[39m
[33mcx[39m=[32m"12"[39m
[33mcy[39m=[32m"19"[39m
[33mr[39m=[32m"1"[39m
[36m/>[39m
[36m</svg>[39m
[36m</button>[39m
[36m</div>[39m
[36m</div>[39m
[36m</td>[39m
[36m</tr>[39m
[36m[39m [36m[39m
Ignored nodes: comments, script, style [36m<table[39m [33mdata-automation-id[39m=[32m"ticket-email-notifications-table"[39m [36m>[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser0@example.com[0m [36m[39m [36m[39m [0mS0[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser1@example.com[0m [36m[39m [36m[39m [0mS1[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser2@example.com[0m [36m[39m [36m[39m [0mS2[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser3@example.com[0m [36m[39m [36m[39m [0mS3[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser4@example.com[0m [36m[39m [36m[39m [0mS4[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser5@example.com[0m [36m[39m [36m[39m [0mS5[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser6@example.com[0m [36m[39m [36m[39m [0mS6[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser7@example.com[0m [36m[39m [36m[39m [0mS7[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser8@example.com[0m [36m[39m [36m[39m [0mS8[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser9@example.com[0m [36m[39m [36m[39m [0mS9[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser10@example.com[0m [36m[39m [36m[39m [0mS10[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser11@example.com[0m [36m[39m [36m[39m [0mS11[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser12@example.com[0m [36m[39m [36m[39m [0mS12[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser13@example.com[0m [36m[39m [36m[39m [0mS13[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser14@example.com[0m [36m[39m [36m[39m [0mS14[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser15@example.com[0m [36m[39m [36m[39m [0mS15[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser16@example.com[0m [36m[39m [36m[39m [0mS16[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser17@example.com[0m [36m[39m [36m[39m [0mS17[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser18@example.com[0m [36m[39m [36m[39m [0mS18[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser19@example.com[0m [36m[39m [36m[39m [0mS19[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser20@example.com[0m [36m[39m [36m[39m [0mS20[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser21@example.com[0m [36m[39m [36m[39m [0mS21[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser22@example.com[0m [36m[39m [36m[39m [0mS22[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser23@example.com[0m [36m[39m [36m[39m [0mS23[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m [0mJan 01, 2026, 7:00 AM[0m [36m[39m [36m[39m [0muser24@example.com[0m [36m[39m [36m[39m [0mS24[0m [36m[39m [36m[39m [36m<span[39m [33mclass[39m=[32m"inline-flex items-center gap-2"[39m [36m>[39m [36m<span[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"h-2 w-2 rounded-full bg-emerald-500"[39m [36m/>[39m [36m<span[39m [33mclass[39m=[32m"capitalize"[39m [36m>[39m [0msent[0m [36m[39m [36m[39m [36m[39m [36m[39m [0m—[0m [36m[39m [36m[39m [36m[39m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 9 failed) 31ms 266 MB heap used × EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 4ms → Found multiple elements with the placeholder text of: Send a message
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l7"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l8"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l7"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l6"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l4"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l5"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l3"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_kv"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l0"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l1"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_l2"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m[39m [36m
Test Files 511 failed | 86 passed | 4 skipped (601) Tests 144 failed | 562 passed | 195 skipped (901) Start at 14:53:51 Duration 53.99s (transform 2.69s, setup 344ms, collect 2.87s, tests 40.94s, environment 244ms, prepare 47ms) (pass).
2026-02-12 — T014 implemented
- Marked byte-for-byte deterministic evaluator output as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::returns byte-for-byte stable output for equivalent AST and input data
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T015 implemented
- Marked renderer HTML coverage for text/field/table/totals compositions as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx::renders HTML for text/field/table/totals node combinations
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T016 implemented
- Marked renderer style/class token consistency coverage as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx::applies class tokens and style declarations consistently
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T017 implemented
- Marked unsafe text escaping behavior in renderer output as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx::escapes unsafe text content in rendered HTML
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T018 implemented
- Marked server HTML wrapper coverage for headless PDF rendering as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/server-render.test.ts::returns a full HTML document wrapper
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T019 implemented
- Marked designer workspace export-to-AST integration coverage as implemented.
- Evidence: packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts::exports designer workspace to a versioned AST document
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T020 implemented
- Marked AST hydration back into designer workspace as implemented.
- Evidence: packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts::hydrates a designer workspace from persisted AST
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts packages/billing/src/lib/invoice-template-ast/react-renderer.test.tsx packages/billing/src/lib/invoice-template-ast/server-render.test.ts packages/billing/src/components/invoice-designer/ast/workspaceAst.test.ts' (pass).
2026-02-12 — T004 implemented
- Marked transform payload shape enforcement coverage as implemented for filter/sort/group/aggregate/computed operations.
- Evidence: packages/billing/src/lib/invoice-template-ast/schema.test.ts::enforces transform payload shapes
Verification:
- \ WARN Unsupported engine: wanted: {"node":">=20 <25"} (current: {"node":"v25.5.0","pnpm":"9.15.9"})
RUN v3.2.4 /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer Running tests with seed "1770926085818"
Environment file path: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/.env.localtest stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Sustained Rate > should allow sustained rate equal to refill rate [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 58, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 57, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 56, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 55, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 54, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 53, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 52, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 51, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 50, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 49, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 48, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 47, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 46, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 45, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 44, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 43, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 42, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 41, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 40, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 39, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 38, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 37, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 36, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 35, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 34, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 33, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 32, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 31, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 30, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 29, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 28, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 27, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 26, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 25, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 24, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 23, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 22, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 21, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 20, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 19, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 18, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 17, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 16, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 15, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 14, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 13, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 12, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 11, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 10, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 7, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 6, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 5, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 3, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > Token Bucket vs Sliding Window Comparison > Burst Handling > should allow burst up to maxTokens [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 999 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should initialize with Redis client [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Initialization > should warn if initialized twice [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Shutdown > should cleanup on shutdown [TokenBucketRateLimiter] Shutdown complete
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow request when bucket has tokens [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 59, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-2', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: 'user-1', remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should track tokens separately per user within a tenant [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: 'user-2', remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 2, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Consumption > should allow multiple requests until bucket is empty [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return full bucket for new tenant [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 9, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Get State > should return current bucket state [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 8, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should not exceed maxTokens when refilling [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 4, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 100 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Token Refill > should refill tokens over time [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 1, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should include reason when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Initialized successfully { defaultMaxTokens: 60, defaultRefillRate: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Token consumed { tenantId: 'tenant-1', userId: undefined, remaining: 0, consumed: 1 }
stdout | server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts > TokenBucketRateLimiter > Retry After Calculation > should return correct retryAfterMs when rate limited [TokenBucketRateLimiter] Rate limit exceeded { tenantId: 'tenant-1', userId: undefined, remaining: 0, needed: 1, retryAfterMs: 1000 }
✓ server/src/test/unit/notifications/tokenBucketRateLimiter.test.ts (17 tests) 7ms 15 MB heap used stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/googleProviderDataPersistence.test.ts > Google Provider Data Persistence Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/googleProviderDataPersistence.test.ts (6 tests | 6 skipped) 19ms 90 MB heap used ↓ Google Provider Data Persistence Tests > should create a Google provider record with all required fields in the database ↓ Google Provider Data Persistence Tests > should persist Google Workspace (non-gmail.com) configurations correctly ↓ Google Provider Data Persistence Tests > should store OAuth tokens and authentication data when provided ↓ Google Provider Data Persistence Tests > should enforce proper database constraints for Google providers ↓ Google Provider Data Persistence Tests > should enforce validation for required fields ↓ Google Provider Data Persistence Tests > should correctly handle updates to existing Google provider configurations ❯ server/src/test/unit/Chat.streamingEndpoint.test.ts (2 tests | 1 failed) 3ms 97 MB heap used ✓ EE Chat (source) > uses the streaming completions endpoint for new messages 0ms × EE Chat (source) > reads the streaming response via response.body.getReader() 2ms → expected ''use client';\n\nimport React, { us…' to contain 'response.body.getReader()' ✓ packages/billing/src/actions/invoiceTemplateCompileParity.test.ts (2 tests) 0ms 100 MB heap used ✓ packages/billing/src/components/invoice-designer/state/designerStore.layout.test.ts (5 tests) 3ms 104 MB heap used ✓ packages/tickets/src/lib/timeEntryContext.test.ts (3 tests) 1ms 106 MB heap used ✓ server/src/test/unit/scheduling/eligibleSubjects.test.ts (3 tests) 1ms 107 MB heap used ✓ shared/workflow/runtime/tests/mappingResolver.test.ts (18 tests) 5ms 114 MB heap used ✓ packages/billing/src/components/invoice-designer/DesignerShell.fitSection.test.ts (11 tests) 1ms 123 MB heap used stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.endExclusiveQueries.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/billingEngine.prorationExclusive.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts (4 tests) 8ms 220 MB heap used ❯ server/src/test/integration/ticketBundling.integration.test.ts (8 tests | 8 skipped) 1ms 231 MB heap used ↓ Ticket bundling integration > enforces permissions for bundle operations ↓ Ticket bundling integration > creates bundles, manages membership, and enforces invariants ↓ Ticket bundling integration > supports promote-to-master and preserves membership ↓ Ticket bundling integration > sync_updates propagates workflow changes; children lock workflow fields ↓ Ticket bundling integration > sync_updates mirrors public comments to children, marking them system-generated and immutable ↓ Ticket bundling integration > reopen-on-reply can reopen the master when a client replies on a child ↓ Ticket bundling integration > surfaces inbound child public replies on the master as aggregated view-only items ↓ Ticket bundling integration > blocks time entries on bundled children and allows time entries on masters stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.email.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/core/src/lib/events/publisher.test.ts (1 test) 4ms 239 MB heap used stdout | server/src/test/integration/emailProviderCreation.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderCreation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderCreation.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts > createContractTemplateFromWizard with Currency Support Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/contractTemplateWizardCurrency.integration.test.ts (7 tests | 7 skipped) 2ms 251 MB heap used ↓ createContractTemplateFromWizard with Currency Support > creates a template with USD currency and persists it correctly ↓ createContractTemplateFromWizard with Currency Support > creates a template with EUR currency and persists it correctly ↓ createContractTemplateFromWizard with Currency Support > creates a template with GBP currency and persists it correctly ↓ createContractTemplateFromWizard with Currency Support > creates templates with multiple currencies in same tenant ↓ createContractTemplateFromWizard with Currency Support > creates draft template with currency and verifies status and currency ↓ createContractTemplateFromWizard with Currency Support > creates contract from template and inherits template currency (EUR) ↓ createContractTemplateFromWizard with Currency Support > creates contract with JPY currency from template and preserves currency ❯ packages/core/src/lib/logger.outputs.test.ts (2 tests | 2 failed) 3ms 257 MB heap used × logger outputs > defaults to console-only transport 1ms → Target cannot be null or undefined. × logger outputs > configures external and file transports when enabled 1ms → Cannot read properties of undefined (reading 'find') stdout | server/src/lib/workflow/visualization/ast/flowGraphBuilder.test.ts > flowGraphBuilder > buildFlowGraph > should skip edges that involve state transitions Sorted components by source location: [ 'action at line 2:1' ] Sequential edge: connecting action-action1-2-1 (handle: right) to action-action1-2-1 (handle: left)
stdout | server/src/lib/workflow/visualization/ast/flowGraphBuilder.test.ts > flowGraphBuilder > buildFlowGraph > should exclude state transitions from the graph Sorted components by source location: [ 'action at line 3:1' ]
❯ server/src/lib/workflow/visualization/ast/flowGraphBuilder.test.ts (3 tests | 2 failed) 55ms 275 MB heap used ✓ flowGraphBuilder > buildFlowGraph > should exclude state transitions from the graph 0ms × flowGraphBuilder > buildFlowGraph > should skip edges that involve state transitions 1ms → expected 'action-action1-2-1' to be 'action-0' // Object.is equality × flowGraphBuilder > applyLayout > should position nodes in a directed layout 53ms → expected 12 to be +0 // Object.is equality ✓ packages/billing/src/lib/invoice-template-ast/server-render.test.ts (1 test) 1ms 247 MB heap used ✓ packages/core/src/lib/logger.test.ts (1 test) 0ms 249 MB heap used ❯ packages/ui/src/context/SchedulingContext.test.tsx (4 tests | 4 failed) 1ms 275 MB heap used × SchedulingContext > returns default callbacks when no provider is present 1ms → document is not defined × SchedulingContext > renders fallback alert element for agent schedule by default 0ms → document is not defined × SchedulingContext > shows a toast when launching time entry without provider 0ms → document is not defined × SchedulingContext > uses provider callbacks when SchedulingCallbackProvider is present 0ms → document is not defined ✓ packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts (2 tests) 0ms 286 MB heap used ✓ server/src/test/unit/ui/timeTrackingSubjectSelector.test.ts (3 tests) 1ms 287 MB heap used stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts > email_sending_logs entity context migrations Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/email/emailSendingLogsMigration.integration.test.ts (7 tests | 7 skipped) 2ms 297 MB heap used ↓ email_sending_logs entity context migrations > adds entity_type column ↓ email_sending_logs entity context migrations > adds entity_id column ↓ email_sending_logs entity context migrations > adds contact_id column ↓ email_sending_logs entity context migrations > adds notification_subtype_id column ↓ email_sending_logs entity context migrations > creates tenant/entity index ↓ email_sending_logs entity context migrations > creates tenant/contact index ↓ email_sending_logs entity context migrations > migration files export up/down functions ✓ packages/tickets/src/lib/tests/responseSource.test.ts (8 tests) 0ms 266 MB heap used stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService – REST usage > refreshes OAuth tokens when expired Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials
stdout | server/src/test/unit/accounting/xeroClientService.spec.ts > XeroClientService – REST usage > retries after 401 by refreshing token once and logs tenant metadata Successfully wrote tenant secret: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/secrets/tenants/tenant-123/xero_credentials
❯ server/src/test/unit/accounting/xeroClientService.spec.ts (8 tests | 1 failed) 4ms 271 MB heap used ✓ XeroClientService – REST usage > POST /Invoices payload matches spec requirements 0ms ✓ XeroClientService – REST usage > normalizes validation errors returned from POST /Invoices 0ms ✓ XeroClientService – REST usage > handles empty payload array without issuing network request 0ms ✓ XeroClientService – REST usage > sets expected headers for authenticated requests 0ms ✓ XeroClientService – REST usage > refreshes OAuth tokens when expired 1ms ✓ XeroClientService – REST usage > retrieves accounts, items, tax rates, and tracking categories with normalized structures 1ms × XeroClientService – REST usage > retries after 401 by refreshing token once and logs tenant metadata 1ms → expected "spy" to be called 1 times, but got 0 times ✓ XeroClientService – REST usage > allows re-export after validation error once mappings are corrected 0ms stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/projectTemplatesIntegration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":"PO-XYZ"} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""},{"type": "Text", "content": "PO #: PO-XYZ", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}
stdout | server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts > Standard invoice template PO header > T010: default template renders PO number in header only when invoice has po_number Input JSON to WASM: {"invoiceNumber":"INV-PO","issueDate":"2025-01-01","dueDate":"2025-02-01","currencyCode":"USD","customer":{"name":"Alpha Co","address":"1 Test St"},"tenantClient":{"name":"Tenant","address":"Tenant Address","logoUrl":null},"items":[{"id":"1","description":"Service","quantity":1,"unitPrice":100,"total":100}],"subtotal":100,"tax":0,"total":100,"poNumber":null} [Wasm Log]: Wasm (standard-default): Received data string. [Wasm Log]: Wasm (standard-default): Deserialized Invoice #: INV-PO [Wasm Log]: Wasm (standard-default): Serializing layout... [Wasm Log]: Wasm (standard-default): Returning serialized layout. Output JSON from WASM: {"type": "Document", "children": [{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "[Tenant Logo]", "variant": "", "id": ""}], "id": ""},{"type": "Column", "span": 5, "children": [{"type": "Text", "content": "Tenant", "variant": "heading3", "id": ""},{"type": "Text", "content": "Tenant Address", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em", "paddingTop": "0.5em"}},{"type": "Column", "span": 4, "children": [{"type": "Text", "content": "Invoice #: INV-PO", "variant": "", "id": ""},{"type": "Text", "content": "Date: 2025-01-01", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Bill To:", "variant": "heading3", "id": ""},{"type": "Text", "content": "Alpha Co", "variant": "", "id": ""},{"type": "Text", "content": "1 Test St", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "1em", "paddingTop": "0.5em"}}], "id": ""}], "id": "invoice-header-std-default"},{"type": "Section", "children": [{"type": "Text", "content": "Items", "variant": "heading3", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em", "paddingBottom": "0.2em"}},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Description", "variant": "label", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Qty", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Unit Price", "variant": "label", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Total", "variant": "label", "id": "", "style": {"fontWeight": "bold", "paddingRight": "0.5em"}}], "id": "", "style": {"textAlign": "right"}}], "id": "", "style": {"fontWeight": "bold", "paddingBottom": "0.5em", "borderBottom": "1px solid #ccc"}},{"type": "Row", "children": [{"type": "Column", "span": 6, "children": [{"type": "Text", "content": "Service", "variant": "", "id": ""}], "id": "", "style": {"paddingLeft": "0.5em"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "1.0", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right"}},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": "item-row-1", "style": {"paddingTop": "0.3em", "paddingBottom": "0.3em", "borderBottom": "0px"}}], "id": "items-table-section-items", "style": {"paddingLeft": "1em", "paddingRight": "1em", "paddingTop": "1em", "paddingBottom": "1em", "border": "1px solid #ccc", "marginBottom": "1em"}}], "id": "invoice-items-std-default"},{"type": "Section", "children": [{"type": "Row", "children": [{"type": "Column", "span": 7, "children": [], "id": ""},{"type": "Column", "span": 2, "children": [{"type": "Text", "content": "Subtotal", "variant": "", "id": ""},{"type": "Text", "content": "Tax", "variant": "", "id": ""},{"type": "Text", "content": "Total", "variant": "", "id": ""}], "id": "", "style": {"textAlign": "right", "paddingRight": "1em"}},{"type": "Column", "span": 3, "children": [{"type": "Text", "content": "$1.00", "variant": "", "id": ""},{"type": "Text", "content": "$0.00", "variant": "", "id": ""},{"type": "Text", "content": "$1.00", "variant": "", "id": "", "style": {"fontWeight": "bold"}}], "id": "", "style": {"textAlign": "right", "paddingRight": "0.5em"}}], "id": ""}], "id": "invoice-totals-std-default", "style": {"marginTop": "1em", "paddingTop": "1em", "paddingBottom": "1em", "borderTop": "1px solid #eee"}},{"type": "Section", "children": [{"type": "Text", "content": "Thank you for your business!", "variant": "", "id": "", "style": {"marginTop": "1em", "paddingLeft": "0.5em"}}], "id": "invoice-notes-std-default", "style": {"marginTop": "2em"}}], "id": "invoice-document-standard-default"}
✓ server/src/test/unit/invoiceTemplates/standardTemplatePoNumber.test.ts (1 test) 1355ms 282 MB heap used ❯ server/src/test/unit/tickets/TicketDetails.emailNotifications.integration.test.ts (1 test | 1 failed) 0ms 292 MB heap used × TicketDetails > includes the TicketEmailNotifications section 0ms → ENOENT: no such file or directory, open '/Users/roberisaacs/alga-psa.worktrees/codex/packages/tickets/src/components/ticket/TicketDetails.tsx' ✓ server/src/test/unit/extensions/uiHooks.test.ts (2 tests) 0ms 294 MB heap used stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts > Contract Purchase Order Support Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/billing/contractPurchaseOrderSupport.integration.test.ts (5 tests | 5 skipped) 2ms 298 MB heap used ↓ Contract Purchase Order Support > T001: invoices table includes po_number + client_contract_id ↓ Contract Purchase Order Support > T002: invoice creation snapshots client_contracts.po_number onto invoices.po_number ↓ Contract Purchase Order Support > T003: invoice generation blocks when po_required=true and po_number is missing ↓ Contract Purchase Order Support > T004: PO consumption sums finalized invoices and unconsumes when status changes away from finalized ↓ Contract Purchase Order Support > T005: overage calculation uses invoice total_amount and contract po_amount (authorized total spend) stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/mappingCrud.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/src/components/invoice-designer/state/designerStore.presets.test.ts (1 test) 3ms 311 MB heap used ❯ shared/workflow/actions/tests/emailWorkflowActions.responseSource.test.ts (6 tests | 5 failed) 17ms 317 MB heap used × createCommentFromEmail response source metadata > T002: persists metadata.responseSource=inbound_email 16ms → trx is not a function × createCommentFromEmail response source metadata > T003: includes normalized provider type when available 0ms → trx is not a function × createCommentFromEmail response source metadata > google inbound flow resolves to inbound_email metadata source (T017) 0ms → trx is not a function × createCommentFromEmail response source metadata > microsoft inbound flow resolves to inbound_email metadata source (T018) 0ms → trx is not a function × createCommentFromEmail response source metadata > imap inbound flow resolves to inbound_email metadata source (T019) 0ms → trx is not a function ✓ createCommentFromEmail response source metadata > T020: keeps comment response-state semantics unchanged (still non-internal) 0ms stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/multiCurrencyGaps.integration.test.ts > Multi-Currency Gap Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/multiCurrencyGaps.integration.test.ts (8 tests | 8 skipped) 2ms 279 MB heap used ↓ Multi-Currency Gap Tests > CRITICAL: Prepayment credits should track currency > createPrepaymentInvoice should record currency on the credit transaction ↓ Multi-Currency Gap Tests > CRITICAL: Prepayment credits should track currency > createPrepaymentInvoice should record currency on the credit_tracking entry ↓ Multi-Currency Gap Tests > CRITICAL: Credit application should validate currency > applyCreditToInvoice should reject applying USD credit to EUR invoice ↓ Multi-Currency Gap Tests > HIGH: Credit listing should support currency filtering > listClientCredits should be able to filter credits by currency ↓ Multi-Currency Gap Tests > HIGH: Credit history should support currency filtering > getCreditHistory should return transactions with currency information ↓ Multi-Currency Gap Tests > MEDIUM: Mixed-currency contract creation > should warn when creating contract in different currency than existing active contract ↓ Multi-Currency Gap Tests > VERIFIED: Working currency functionality > billing engine correctly retrieves contract currency via join ↓ Multi-Currency Gap Tests > VERIFIED: Working currency functionality > clients.default_currency_code has NOT NULL constraint stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/roles.e2e.test.ts > Roles API E2E Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/roles.e2e.test.ts (16 tests | 16 skipped) 2ms 191 MB heap used ↓ Roles API E2E Tests > Basic CRUD Operations > should create a new role ↓ Roles API E2E Tests > Basic CRUD Operations > should list roles with pagination ↓ Roles API E2E Tests > Basic CRUD Operations > should get a specific role ↓ Roles API E2E Tests > Basic CRUD Operations > should update a role ↓ Roles API E2E Tests > Basic CRUD Operations > should delete a role ↓ Roles API E2E Tests > Permission Management > should assign permissions to a role ↓ Roles API E2E Tests > Permission Management > should get role permissions ↓ Roles API E2E Tests > Role Templates > should get available role templates ↓ Roles API E2E Tests > Role Cloning > should clone an existing role ↓ Roles API E2E Tests > Bulk Operations > should bulk create roles ↓ Roles API E2E Tests > Error Handling > should return 401 without API key ↓ Roles API E2E Tests > Error Handling > should return 403 without permission ↓ Roles API E2E Tests > Error Handling > should return 400 for invalid data ↓ Roles API E2E Tests > Error Handling > should return 404 for non-existent role ↓ Roles API E2E Tests > Error Handling > should prevent duplicate role names ↓ Roles API E2E Tests > Tenant Isolation > should not access roles from other tenants ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewModel.test.ts (5 tests) 1ms 195 MB heap used ✓ packages/types/src/exports.typecheck.test.ts (1 test) 0ms 196 MB heap used ❯ server/src/test/integration/onboardingProgressSubsteps.integration.test.ts (1 test | 1 failed) 1ms 201 MB heap used × getOnboardingProgressAction (substeps) > returns portal + email steps with substeps 1ms → Cannot find package '@alga-psa/onboarding/actions' imported from '/Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/server/src/test/integration/onboardingProgressSubsteps.integration.test.ts' stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/appointmentNotifications.integration.test.ts > Appointment Notification System Integration Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/appointmentNotifications.integration.test.ts (29 tests | 29 skipped) 3ms 223 MB heap used ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment request received email to client ↓ Appointment Notification System Integration Tests > Email Notifications > should send new appointment request email to MSP staff ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment approved email with correct locale ↓ Appointment Notification System Integration Tests > Email Notifications > should send appointment declined email with reason ↓ Appointment Notification System Integration Tests > Email Notifications > should include tenant settings in all emails ↓ Appointment Notification System Integration Tests > Email Notifications > should replace template variables correctly ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notifications for MSP staff on request submission ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on approval ↓ Appointment Notification System Integration Tests > Internal Notifications > should create notification for client on decline ↓ Appointment Notification System Integration Tests > Internal Notifications > should include correct link in notifications ↓ Appointment Notification System Integration Tests > Internal Notifications > should populate metadata correctly for staff notifications ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct schedule approvers ↓ Appointment Notification System Integration Tests > Helper Function Integration > should get correct tenant settings ↓ Appointment Notification System Integration Tests > Helper Function Integration > should map contact to client user ID correctly ↓ Appointment Notification System Integration Tests > Helper Function Integration > should return null for non-existent contact ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format dates with correct locale ↓ Appointment Notification System Integration Tests > Helper Function Integration > should format times with correct locale ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should send email notifications in different languages ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should format dates according to locale in notifications ↓ Appointment Notification System Integration Tests > Multi-Language Notification Support > should default to English when locale is not supported ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should send cancellation notification to client ↓ Appointment Notification System Integration Tests > Cancellation Notifications > should handle cancellation of already cancelled request gracefully ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include actionable metadata in staff notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should include appropriate links for client notifications ↓ Appointment Notification System Integration Tests > Notification Metadata and Navigation > should set correct notification types for different events ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should handle missing email addresses gracefully ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should batch notifications to multiple staff members efficiently ↓ Appointment Notification System Integration Tests > Error Handling and Edge Cases > should include all required data fields in notifications ❯ packages/documents/tests/storageService.workflowEvents.test.ts (2 tests | 1 failed) 2ms 229 MB heap used ✓ StorageService.uploadFile workflow events > publishes FILE_UPLOADED after creating the file record 0ms × StorageService.uploadFile workflow events > publishes DOCUMENT_DELETED after deleting the file record 1ms → expected "spy" to be called with arguments: [ ObjectContaining{…} ]
Received:
1st spy call:
@@ -1,12 +1,18 @@ [
- ObjectContaining {
-
"ctx": ObjectContaining { -
"tenantId": "tenant-1",
- {
-
"ctx": { -
"actor": { -
"actorType": "USER", -
"actorUserId": "a836a8b5-3df5-47b1-b49b-9a78f2b1a8a0", }, -
"occurredAt": "2026-01-24T12:30:00.000Z", -
"tenantId": undefined, -
}, "eventType": "DOCUMENT_DELETED",
-
"payload": ObjectContaining {
-
"idempotencyKey": "document_deleted:14f1fbf4-17d6-4bdc-8d4b-0b2a2ff8f26a:2026-01-24T12:30:00.000Z", -
},"payload": { "deletedAt": "2026-01-24T12:30:00.000Z", "deletedByUserId": "a836a8b5-3df5-47b1-b49b-9a78f2b1a8a0", "documentId": "14f1fbf4-17d6-4bdc-8d4b-0b2a2ff8f26a", },
Number of calls: 1
✔ T020: ticket-created-hello fixture loads and executes via harness (3.852542ms) ✔ T100: ticket-created-triage-comment fixture loads and executes via harness (1.193708ms) ✔ T101: ticket-created-auto-assign-by-priority fixture loads and executes via harness (1.122709ms) ✔ T102: ticket-created-vip-notify fixture loads and executes via harness (1.090625ms) ✔ T103: ticket-created-outage-escalate fixture loads and executes via harness (0.949917ms) ✔ T104: ticket-created-create-project-task fixture loads and executes via harness (1.035083ms) ✔ T105: ticket-created-assign-trycatch fixture loads and executes via harness (1.134667ms) ✔ T106: ticket-created-notify-multiple fixture loads and executes via harness (1.554667ms) ✔ T107: ticket-created-ignore-system fixture loads and executes via harness (0.582625ms) ✔ T108: ticket-assigned-acknowledge fixture loads and executes via harness (1.149166ms) ✔ T109: ticket-unassigned-return-to-triage fixture loads and executes via harness (0.907625ms) ✔ T110: ticket-status-waiting-on-customer-reminder fixture loads and executes via harness (0.686458ms) ✔ T111: ticket-reopened-notify-tech fixture loads and executes via harness (0.713333ms) ✔ T112: ticket-escalated-crm-note fixture loads and executes via harness (0.87275ms) ✔ T113: ticket-queue-after-hours-email fixture loads and executes via harness (0.759292ms) ✔ T114: ticket-tags-billing-route fixture loads and executes via harness (0.782583ms) stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > honors public base override [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: 'http://localhost:8085', runnerBase: undefined, publicBase: 'http://localhost:8085' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > falls back to /runner when no public base is set [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: undefined, publicBase: '/runner' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > appends tenant when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: 'tenant-123', overrideBase: null, runnerBase: undefined, publicBase: '/runner' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > uses absolute public base when provided [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/settings', tenantId: undefined, overrideBase: null, runnerBase: 'https://runner.dev/alga', publicBase: 'https://runner.dev/alga' }
stdout | ee/server/src/lib/extensions/tests/assets/url.shared.test.ts > buildExtUiSrc > supports relative public base for gateway proxy [ext-ui][buildExtUiSrc] { extensionId: 'ext-1', mode: 'rust', clientPath: '/', tenantId: undefined, overrideBase: null, runnerBase: '/runner', publicBase: '/runner' }
✓ ee/server/src/lib/extensions/tests/assets/url.shared.test.ts (5 tests) 1ms 240 MB heap used ✓ server/src/test/unit/notifications/emailRateLimiting.test.ts (14 tests) 1ms 244 MB heap used stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/boards.e2e.test.ts > Board API E2E Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/boards.e2e.test.ts (10 tests | 10 skipped) 2ms 200 MB heap used ↓ Board API E2E Tests > Authentication > should require API key ↓ Board API E2E Tests > Authentication > should reject invalid API key ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should list active boards by default ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should include inactive boards when requested ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should support pagination ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should support search by name ↓ Board API E2E Tests > List Boards (GET /api/v1/boards) > should sort by display_order by default ↓ Board API E2E Tests > Get Board by ID (GET /api/v1/boards/:id) > should retrieve a board by ID ↓ Board API E2E Tests > Get Board by ID (GET /api/v1/boards/:id) > should return 404 for non-existent board ↓ Board API E2E Tests > Get Board by ID (GET /api/v1/boards/:id) > should return 400 for invalid UUID format ❯ ee/extensions/samples/ui-kit-showcase/test/build.test.ts (1 test | 1 failed) 0ms 202 MB heap used × build output > iframe bundle is generated in ui/dist/iframe 0ms → expected false to be true // Object.is equality stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/workflowRuntimeV2.control.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/api/chatExecute.route.gating.test.ts (1 test) 4ms 229 MB heap used stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Statistics > should get time entry statistics Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should reject invalid API key Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Authentication > should require API key for all endpoints Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Templates > should list time entry templates Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid date format Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid UUID format Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Error Handling > should handle invalid query parameters Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk create time entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Bulk Operations > should bulk update time entries Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce read permissions for listing Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce update permissions Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce delete permissions Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Permissions > should enforce create permissions Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should stop a tracking session Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Time Tracking > should start a tracking session Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to JSON Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/time-entries.e2e.test.ts > Time Entries API E2E Tests > Export > should export time entries to CSV Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/time-entries.e2e.test.ts (40 tests | 38 failed | 2 skipped) 41ms 213 MB heap used × Time Entries API E2E Tests > Authentication > should require API key for all endpoints 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Authentication > should reject invalid API key 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should create a new time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should compute work_date in user timezone and bucket to the correct period 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate required fields 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Create Time Entry (POST /api/v1/time-entries) > should validate time periods overlap 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should retrieve a time entry by ID 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should return 404 for non-existent time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Get Time Entry (GET /api/v1/time-entries/:id) > should not return time entries from other tenants 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should update a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should return 404 when updating non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Update Time Entry (PUT /api/v1/time-entries/:id) > should not allow updating approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should delete a time entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should return 404 when deleting non-existent entry 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > CRUD Operations > Delete Time Entry (DELETE /api/v1/time-entries/:id) > should not allow deleting approved entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should list time entries with default pagination 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should support pagination parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by date range 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by user 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should filter by billable status 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > List Time Entries (GET /api/v1/time-entries) > should sort by date 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should start a tracking session 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Time Tracking > should stop a tracking session 1ms → → Cannot read properties of undefined (reading 'cleanup') ↓ Time Entries API E2E Tests > Approval Workflow > should approve time entries ↓ Time Entries API E2E Tests > Approval Workflow > should reject invalid entry IDs for approval × Time Entries API E2E Tests > Export > should export time entries to CSV 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Export > should export time entries to JSON 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Statistics > should get time entry statistics 2ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Templates > should list time entry templates 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk create time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk update time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Bulk Operations > should bulk delete time entries 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid UUID format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid query parameters 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Error Handling > should handle invalid date format 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce read permissions for listing 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce create permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce update permissions 1ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Permissions > should enforce delete permissions 7ms → → Cannot read properties of undefined (reading 'cleanup') × Time Entries API E2E Tests > Multi-tenancy > should isolate time entries by tenant 1ms → → Cannot read properties of undefined (reading 'cleanup') ❯ server/src/lib/eventBus/index.hardTimeout.test.ts (1 test | 1 failed) 4ms 221 MB heap used × EventBus Redis consumer hard-timeout > resets the Redis client if xReadGroup hangs beyond the hard timeout 4ms → Failed to resolve entry for package "@alga-psa/event-schemas". The package may have incorrect main/module/exports specified in its package.json. stdout | ee/server/src/tests/integration/ticket-response-state.integration.test.ts > Ticket Response State Integration Tests Database config: { host: 'localhost', port: 5438, database: 'server', user: 'app_user', password: '[32 chars]', ssl: false }
❯ ee/server/src/tests/integration/ticket-response-state.integration.test.ts (28 tests | 28 skipped) 2ms 226 MB heap used ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T001: ticket_response_state enum type exists with correct values ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T002: response_state column exists on tickets table and is nullable ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T003: Index exists on (tenant, response_state) ↓ Ticket Response State Integration Tests > Database Migration Tests (T001-T004) > T004: New tickets have null response_state by default ↓ Ticket Response State Integration Tests > Type Definition Tests (T005-T006) > T005-T006: TicketResponseState type exists and allows correct values ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T007: Staff creates client-visible comment → response_state becomes awaiting_client ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T008: Staff creates client-visible comment on ticket already awaiting_client → state unchanged ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T009: Staff creates client-visible comment on ticket awaiting_internal → state becomes awaiting_client ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T010: Client creates comment → response_state becomes awaiting_internal ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T011: Client creates comment on ticket already awaiting_internal → state unchanged ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T012: Client creates comment on ticket awaiting_client → state becomes awaiting_internal ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T013: Staff creates internal note → response_state does not change from null ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T014: Staff creates internal note on awaiting_client ticket → state remains awaiting_client ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T015: Staff creates internal note on awaiting_internal ticket → state remains awaiting_internal ↓ Ticket Response State Integration Tests > Comment-Triggered State Changes (T007-T017) > T016-T017: Comment creation and response state update occur in same transaction ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T018: updateTicket with response_state=awaiting_client updates ticket ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T019: updateTicket with response_state=awaiting_internal updates ticket ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T020: updateTicket with response_state=null clears response state ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T022-T024: Closing ticket clears response_state ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T025: Closing ticket with null response_state keeps response_state null ↓ Ticket Response State Integration Tests > Manual Override and Close Behavior (T018-T026) > T026: Reopening closed ticket does not set response_state ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T054: TICKET_RESPONSE_STATE_CHANGED event type exists ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T055: Event schema validates required fields ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T056-T057: Creating client-visible comment fires TICKET_RESPONSE_STATE_CHANGED event with trigger=comment ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T063-T064: Event includes correct previousState and newState values ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T072: TICKET_COMMENT_ADDED event payload includes author_type ↓ Ticket Response State Integration Tests > Event Publishing Tests (T054-T065, T072, T076) > T076: Internal note does not fire TICKET_RESPONSE_STATE_CHANGED event ↓ Ticket Response State Integration Tests > Tenant Isolation Tests (T073-T075) > T073-T074: Users cannot see or update response_state of tickets in other tenants ❯ server/src/test/integration/ticketEmailDelimiters.test.ts (21 tests | 21 skipped) 54ms 234 MB heap used ↓ sendEventEmail reply markers > adds reply markers when conversation token is provided ↓ sendEventEmail reply markers > generates a conversation token when one is not supplied ↓ sendEventEmail reply markers > includes comment and thread markers for comment notifications ↓ ticket email subscriber reply markers > processes ticket created events with delimiters ↓ ticket email subscriber reply markers > processes ticket updated events with delimiters ↓ ticket email subscriber reply markers > processes ticket comment events with comment markers ↓ ticket email subscriber event publishing > publishes ticket created events and emails the primary contact ↓ ticket email subscriber deduplication > sends only one ticket created email when primary and assigned recipients share address ↓ ticket email subscriber deduplication > sends one internal ticket assigned email when assignee and contact share address ↓ ticket email subscriber deduplication > sends one ticket assigned email when contact and location share address ↓ ticket email subscriber deduplication > sends one ticket assigned email when additional resource shares email with assignee ↓ ticket email subscriber deduplication > sends one ticket comment email when additional resource shares email with assignee ↓ ticket email subscriber notification gating (known gap) > skips ticket created email when tenant notifications are disabled ↓ ticket email subscriber notification gating (known gap) > skips ticket created email when subtype is disabled ↓ ticket email subscriber notification gating (known gap) > skips ticket assigned email when user preference is disabled ↓ ticket email subscriber link routing > uses portal domain for external recipients and MSP URL for internal users ↓ ticket email subscriber link routing > falls back to the client portal path when no custom domain exists ↓ ticket email subscriber rich text formatting > renders rich text comment content as HTML instead of JSON ↓ ticket email subscriber rich text formatting > renders ticket description rich text without leaking JSON ↓ project email subscriber rich text formatting > renders project description rich text in project created emails ↓ project email subscriber rich text formatting > renders project description rich text in project assigned emails stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🏗️ Initializing Email Settings Test Fixture (one-time setup)... 📊 Setting up database and services... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/oauth-flow.test.ts > Email Settings OAuth Flow Tests 🧹 Final test fixture cleanup...
❯ server/src/test/e2e/email-settings/oauth-flow.test.ts (7 tests | 7 skipped) 3ms 248 MB heap used ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should complete OAuth flow and store tokens ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle OAuth error scenarios ↓ Email Settings OAuth Flow Tests > Microsoft OAuth Flow > should handle Microsoft webhook validation token ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should complete OAuth flow with Pub/Sub setup ↓ Email Settings OAuth Flow Tests > Google OAuth Flow > should handle expired refresh token ↓ Email Settings OAuth Flow Tests > Token Storage and Encryption > should store tokens securely in database ↓ Email Settings OAuth Flow Tests > State Parameter Validation > should validate state parameter in OAuth callback ✓ packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts (2 tests) 0ms 260 MB heap used ✓ server/src/test/unit/api/chatCompletions.route.gating.test.ts (2 tests) 4ms 268 MB heap used ✓ server/src/test/unit/billingPlanSelection.test.ts (5 tests | 1 skipped) 1ms 276 MB heap used ✓ sdk/samples/extension-ui/service-proxy-demo/tests/fetch.test.ts (1 test) 0ms 279 MB heap used stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/surveyEmailTemplates.integration.test.ts > Survey email templates Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/surveyEmailTemplates.integration.test.ts (2 tests | 2 skipped) 1ms 253 MB heap used ↓ Survey email templates > registers system templates for each supported locale ↓ Survey email templates > renders locale-specific content and falls back to English stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts > GmailAdapter.listMessagesSince > attempts to recreate Gmail watch when historyId rejection occurs [GOOGLE] Attempting to recreate Gmail watch after history_id invalidation { providerId: 'provider-id', rejectedHistoryId: '31559633' }
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts > GmailAdapter.listMessagesSince > attempts to recreate Gmail watch when historyId rejection occurs [GOOGLE] Gmail watch recreated successfully after history_id invalidation
stdout | server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts > GmailAdapter.listMessagesSince > surfaces a dedicated error when Gmail returns historyId not found [GOOGLE] Attempting to recreate Gmail watch after history_id invalidation { providerId: 'provider-id', rejectedHistoryId: '31559633' }
✓ server/src/test/unit/email/GmailAdapter.listMessagesSince.test.ts (2 tests) 2ms 258 MB heap used ✓ server/src/app/api/client-portal/domain-session/route.test.ts (5 tests) 2ms 262 MB heap used ❯ tools/nx-tests/editionSwapping.test.ts (2 tests | 1 failed) 194ms 265 MB heap used × CE/EE build swapping > CE build excludes EE code in module resolution 97ms → expected '/Users/roberisaacs/alga-psa.worktrees…' to be '/Users/roberisaacs/alga-psa.worktrees…' // Object.is equality ✓ CE/EE build swapping > EE build includes EE code in module resolution 97ms ✓ server/src/test/unit/security/managerScopeRegression.test.ts (1 test) 1ms 267 MB heap used ✓ packages/core/src/lib/encryption.test.ts (2 tests) 2ms 270 MB heap used stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created an API key Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should create a complete test environment Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a user Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have a valid database connection Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Test Environment Setup > should have created a tenant Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert error responses Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should build query strings correctly Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Test Helpers > should assert successful responses Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should be able to make requests Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > API Client > should have API key configured Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create multiple contacts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should generate random contact data Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/utils/utilities.test.ts > E2E Test Utilities > Contact Test Data Factory > should create a single contact Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/utils/utilities.test.ts (13 tests | 13 failed) 566ms 295 MB heap used × E2E Test Utilities > Test Environment Setup > should create a complete test environment 54ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have a valid database connection 39ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a tenant 36ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created a user 44ms → no such database: test_database × E2E Test Utilities > Test Environment Setup > should have created an API key 111ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should generate random contact data 37ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create a single contact 37ms → no such database: test_database × E2E Test Utilities > Contact Test Data Factory > should create multiple contacts 38ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should build query strings correctly 31ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert successful responses 29ms → no such database: test_database × E2E Test Utilities > API Test Helpers > should assert error responses 36ms → no such database: test_database × E2E Test Utilities > API Client > should have API key configured 43ms → no such database: test_database × E2E Test Utilities > API Client > should be able to make requests 31ms → no such database: test_database ✓ packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts (6 tests) 1ms 304 MB heap used ❯ server/src/test/unit/contractLineDisambiguation.test.ts (12 tests | 6 failed) 4ms 310 MB heap used × Contract Line Disambiguation Logic > getEligibleContractLines > should query for eligible contract lines 1ms → knex is not a function × Contract Line Disambiguation Logic > determineDefaultContractLine > should return the only contract line when there is just one eligible contract line 0ms → expected null to be 'contractLine1' // Object.is equality ✓ Contract Line Disambiguation Logic > determineDefaultContractLine > should return null when there are no eligible contract lines 0ms × Contract Line Disambiguation Logic > determineDefaultContractLine > should return the contract line with a bucket overlay when there is only one overlay 0ms → expected null to be 'contractLine2' // Object.is equality ✓ Contract Line Disambiguation Logic > determineDefaultContractLine > should return null when there are multiple eligible contract lines with no clear default 0ms ✓ Contract Line Disambiguation Logic > determineDefaultContractLine > should return null when there are multiple contract lines with bucket overlays 0ms × Contract Line Disambiguation Logic > validateContractLineForService > should return true when the contract line is valid for the service 0ms → expected false to be true // Object.is equality ✓ Contract Line Disambiguation Logic > validateContractLineForService > should return false when the contract line is not valid for the service 0ms × Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return true when this is the only eligible contract line 0ms → expected false to be true // Object.is equality × Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return true when this is the only contract line with a bucket overlay 0ms → expected false to be true // Object.is equality ✓ Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return false when this is not the only eligible contract line and has no bucket overlay 0ms ✓ Contract Line Disambiguation Logic > shouldAllocateUnassignedEntry > should return false when there are multiple contract lines with bucket overlays 0ms ✓ packages/tickets/src/components/ticket/TicketDetails.scheduleDrawer.test.ts (1 test) 0ms 270 MB heap used ✓ packages/types/src/interfaces/ticket.interface.typecheck.test.ts (1 test) 0ms 273 MB heap used stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts > Tax Rate Changes Mid-Billing Period Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/infrastructure/billing/tax/taxRateChanges.test.ts (1 test | 1 skipped) 1ms 280 MB heap used ↓ Tax Rate Changes Mid-Billing Period > should apply correct tax rates based on charge dates ✓ packages/billing/src/lib/invoice-template-ast/evaluator.test.ts (13 tests) 4ms 292 MB heap used stdout | server/src/test/unit/billingEngine.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billingEngine.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billingEngine.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billingEngine.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billingEngine.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/batchLifecycle.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ sdk/extension-runtime/tests/runtime.test.ts (3 tests) 1ms 326 MB heap used ✓ server/src/test/unit/ui/timesheetHeader.test.ts (1 test) 0ms 329 MB heap used ❯ server/src/test/integration/emailAttachmentIngestion.integration.test.ts (6 tests | 6 skipped) 4ms 293 MB heap used ↓ Email attachment ingestion (workflow-worker action override) > skips inline/CID attachments (no documents/files created) ↓ Email attachment ingestion (workflow-worker action override) > rejects attachments >100MB (no documents/files created) ↓ Email attachment ingestion (workflow-worker action override) > is idempotent: duplicate processing does not create duplicate documents/files ↓ Email attachment ingestion (workflow-worker action override) > skips unsupported Microsoft attachment types (records skipped) ↓ Email attachment ingestion (workflow-worker action override) > retries failed processing without duplicating records ↓ Email attachment ingestion (workflow-worker action override) > creates external_files + documents + document_associations with system attribution (Gmail path) ✓ sdk/samples/component/invoicing-demo/tests/handler.test.ts (4 tests) 1ms 297 MB heap used ✓ server/src/test/unit/DocumentationService.test.ts (4 tests) 1ms 300 MB heap used stdout | server/src/test/integration/emailProviderValidation.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderValidation.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderValidation.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderValidation.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderValidation.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/emailProviderValidation.test.ts > Email Provider Validation Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/emailProviderValidation.test.ts (10 tests | 10 skipped) 1ms 312 MB heap used ↓ Email Provider Validation Tests > Google Provider Validation > should return error when missing required Google provider fields ↓ Email Provider Validation Tests > Google Provider Validation > should return error for invalid email format ↓ Email Provider Validation Tests > Google Provider Validation > should return error when provider name is too long ↓ Email Provider Validation Tests > Microsoft Provider Validation > should return error when missing required Microsoft provider fields ↓ Email Provider Validation Tests > Microsoft Provider Validation > should handle missing optional fields gracefully ↓ Email Provider Validation Tests > General Validation > should return error for null or undefined required fields ↓ Email Provider Validation Tests > General Validation > should return error for empty string in required fields ↓ Email Provider Validation Tests > General Validation > should handle special characters in provider names ↓ Email Provider Validation Tests > General Validation > should return meaningful error for duplicate mailbox ↓ Email Provider Validation Tests > Error Message Quality > should provide helpful error messages for common mistakes stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/projects/projectPermissions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/invoiceSelection.integration.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/SettingsPage.experimentalFeatures.lazy.test.ts (1 test) 855ms 409 MB heap used ✓ SettingsPage > loads Experimental Features tab lazily via next/dynamic 855ms ✓ packages/scheduling/tests/scheduleEntryRecurrence.test.ts (22 tests) 11ms 439 MB heap used ❯ packages/msp-composition/src/scheduling/MspSchedulingProvider.test.tsx (2 tests | 2 failed) 1ms 405 MB heap used × MspSchedulingProvider > provides renderAgentSchedule that returns AgentScheduleView 0ms → document is not defined × MspSchedulingProvider > provides launchTimeEntry that calls launchTimeEntryForWorkItem 1ms → document is not defined stdout | packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts > renderTemplateOnServer AST integration > renders template HTML/CSS from canonical AST payload [Server Action] Successfully rendered template: tpl-1
✓ packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts (2 tests) 2ms 414 MB heap used ✓ ee/server/src/tests/unit/tenant-creation.test.ts (4 tests) 0ms 425 MB heap used stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/api/tickets.e2e.test.ts > Ticket API E2E Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/api/tickets.e2e.test.ts (47 tests | 47 skipped) 79ms 441 MB heap used ↓ Ticket API E2E Tests > Authentication > should require API key for all endpoints ↓ Ticket API E2E Tests > Authentication > should reject invalid API key ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create a new ticket ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should validate required fields ↓ Ticket API E2E Tests > CRUD Operations > Create Ticket (POST /api/v1/tickets) > should create ticket with all optional fields ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should retrieve a ticket by ID ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should return 404 for non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Get Ticket (GET /api/v1/tickets/:id) > should not return tickets from other tenants ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should update a ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should return 404 when updating non-existent ticket ↓ Ticket API E2E Tests > CRUD Operations > Update Ticket (PUT /api/v1/tickets/:id) > should validate update data ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should delete a ticket ↓ Ticket API E2E Tests > CRUD Operations > Delete Ticket (DELETE /api/v1/tickets/:id) > should return 404 when deleting non-existent ticket ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should list all tickets with default pagination ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should support pagination parameters ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by client_id ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by status ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by priority ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter by assigned user ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should filter overdue tickets ↓ Ticket API E2E Tests > List Tickets (GET /api/v1/tickets) > should sort tickets by created date ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search tickets by query ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should search in specified fields ↓ Ticket API E2E Tests > Search Tickets (GET /api/v1/tickets/search) > should limit search results ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add a comment to a ticket ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should add an internal comment ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should list ticket comments ↓ Ticket API E2E Tests > Ticket Comments (POST /api/v1/tickets/:id/comments) > should return 404 when adding comment to non-existent ticket ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should update ticket status ↓ Ticket API E2E Tests > Ticket Status Updates (PUT /api/v1/tickets/:id/status) > should validate status transitions ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should assign ticket to user ↓ Ticket API E2E Tests > Ticket Assignment (PUT /api/v1/tickets/:id/assignment) > should unassign ticket ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should return ticket statistics ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by date range ↓ Ticket API E2E Tests > Ticket Statistics (GET /api/v1/tickets/stats) > should filter statistics by client ↓ Ticket API E2E Tests > Create Ticket from Asset (POST /api/v1/tickets/from-asset) > should create ticket from asset ↓ Ticket API E2E Tests > Error Handling > should handle invalid UUID format ↓ Ticket API E2E Tests > Error Handling > should handle invalid query parameters ↓ Ticket API E2E Tests > Error Handling > should handle missing required fields on create ↓ Ticket API E2E Tests > Error Handling > should handle invalid date formats ↓ Ticket API E2E Tests > Permissions > should enforce read permissions for GET endpoints ↓ Ticket API E2E Tests > Permissions > should enforce write permissions for POST/PUT/DELETE ↓ Ticket API E2E Tests > Permissions > should enforce assignment permissions ↓ Ticket API E2E Tests > Multi-tenancy > should isolate tickets by tenant ↓ Ticket API E2E Tests > Advanced Features > should support bulk operations ↓ Ticket API E2E Tests > Advanced Features > should support ticket templates ↓ Ticket API E2E Tests > Advanced Features > should track ticket history ✓ ee/server/src/lib/extensions/tests/gateway/gateway-utils.test.ts (13 tests) 2ms 445 MB heap used ✓ packages/tickets/src/actions/ticketActions.ticketOrigin.test.ts (4 tests) 20ms 455 MB heap used stdout | server/src/test/e2e/email-settings/email-threading.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/email-threading.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-settings/email-threading.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-settings/email-threading.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/email-threading.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests 🏗️ Initializing Email Settings Test Fixture (one-time setup)... 📊 Setting up database and services... 🚀 Initializing E2E Test Context... 🔧 Set E2E environment variables: { DB_HOST: 'localhost', DB_PORT: '5433', DB_NAME_SERVER: 'server_test', DB_USER_ADMIN: 'postgres', PGBOUNCER_HOST: 'localhost', PGBOUNCER_PORT: '6434', REDIS_HOST: 'localhost', REDIS_PORT: '6380', EMAIL_HOST: 'localhost', EMAIL_PORT: '1025' }
stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/e2e/email-settings/email-threading.test.ts > Email Threading Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/e2e/email-settings/email-threading.test.ts (3 tests | 3 skipped) 2ms 465 MB heap used ↓ Email Threading Tests > Email to Ticket Flow > should create ticket from initial email ↓ Email Threading Tests > Reply Threading > should add reply as comment to existing ticket ↓ Email Threading Tests > Thread ID Preservation > should maintain thread ID across email exchanges stdout | packages/db/src/lib/tenantContext.test.ts > tenant context > createTenantKnex falls back to AsyncLocalStorage tenant context [db/tenant] Database configuration { client: 'postgres', connection: { host: 'localhost', port: 5432, database: 'db', user: 'user', password: 'pw' }, pool: {} }
stdout | packages/db/src/lib/tenantContext.test.ts > tenant context > createTenantKnex uses an explicit tenant id when provided [db/tenant] Database configuration { client: 'postgres', connection: { host: 'localhost', port: 5432, database: 'db', user: 'user', password: 'pw' }, pool: {} }
✓ packages/db/src/lib/tenantContext.test.ts (2 tests) 5ms 471 MB heap used ❯ ee/temporal-workflows/src/activities/tests/email-activities.temporal.test.ts (11 tests | 10 failed) 136ms 438 MB heap used × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should generate secure passwords with proper entropy 1ms → expected Promise{…} to have property 'length' × Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should handle various password lengths correctly 0ms → expected Promise{…} to have property 'length' ✓ Email Activities - Temporal Unit Tests > Password Generation with Temporal Context > should ensure consistent randomness across calls 0ms × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should send welcome email with valid input 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle invalid email addresses gracefully 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should handle empty email addresses 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Activity Direct Testing > should work with minimal required fields 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should generate proper email content structure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Email Template Generation > should handle template variable substitution 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should not throw exceptions on failure 0ms → Cannot read properties of undefined (reading 'info') × Email Activities - Temporal Unit Tests > Error Handling and Resilience > should handle missing required fields gracefully 0ms → Cannot read properties of undefined (reading 'info') ✓ shared/lib/utils/emailFileConversion.test.ts (4 tests) 4ms 446 MB heap used ❯ ee/extensions/samples/ui-kit-showcase/test/theme.test.tsx (3 tests | 3 failed) 1ms 450 MB heap used × theme bridge (postMessage) > applyTheme sets CSS variables on document root 0ms → document is not defined × theme bridge (postMessage) > message handler applies theme from Alga envelope format 0ms → document is not defined × theme bridge (postMessage) > ignores non-Alga messages 0ms → document is not defined stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/accounting/externalTaxImport.integration.test.ts > External Tax Import Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/accounting/externalTaxImport.integration.test.ts (14 tests | 14 skipped) 2ms 462 MB heap used ↓ External Tax Import > importing tax from external accounting system > should update invoice charges with tax amounts from QuickBooks ↓ External Tax Import > importing tax from external accounting system > should change invoice tax_source from pending_external to external ↓ External Tax Import > importing tax from external accounting system > should create audit record in external_tax_imports table ↓ External Tax Import > importing tax from external accounting system > should update invoice total_amount to include imported tax ↓ External Tax Import > tax allocation across charges > should apply per-line tax amounts from external system ↓ External Tax Import > tax allocation across charges > should handle mix of taxable and non-taxable items ↓ External Tax Import > tax allocation across charges > should handle different tax rates across items ↓ External Tax Import > tax allocation across charges > should distribute proportionally when line matching fails ↓ External Tax Import > tax allocation across charges > should match by charge ID even when external lines are returned out of order ↓ External Tax Import > internal tax calculation is skipped for external delegation > should set tax to zero when invoice has pending_external tax source ↓ External Tax Import > automatic tax import after export > should automatically import tax after exporting invoice with tax delegation ↓ External Tax Import > error handling > should fail if invoice is not pending_external ↓ External Tax Import > error handling > should fail if invoice has no external mapping ↓ External Tax Import > error handling > should fail if external system returns error ✓ server/src/test/unit/internal-notifications/mentionParser.test.ts (28 tests) 2ms 467 MB heap used stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/integration/googleProviderDatabaseSave.test.ts > Google Provider Database Save Integration Tests Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/integration/googleProviderDatabaseSave.test.ts (6 tests | 6 skipped) 2ms 479 MB heap used ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should save a complete Google provider configuration to the database ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should handle Gmail-specific email addresses correctly ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should handle Google Workspace custom domain emails ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should save OAuth tokens when provided ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should validate required fields for Google provider ↓ Google Provider Database Save Integration Tests > Creating Google Provider via Service > should properly format and save all Google-specific configuration options ✓ packages/client-portal/src/components/tickets/TicketDetails.originBadge.contract.test.ts (3 tests) 1ms 490 MB heap used stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | shared/services/email/tests/EmailWebhookMaintenanceService.test.ts Retrieved secret 'db_password_server' from configured provider.
❯ shared/services/email/tests/EmailWebhookMaintenanceService.test.ts (3 tests | 1 failed) 2ms 506 MB heap used ✓ EmailWebhookMaintenanceService > should find candidates and renew expired subscription 0ms × EmailWebhookMaintenanceService > should recreate subscription if renewal fails with 404 1ms → expected "spy" to be called with arguments: [ 'https://api.example.com/webhook' ]
Number of calls: 0
✓ EmailWebhookMaintenanceService > should handle unexpected errors gracefully 1ms ❯ ee/server/extensions/samples/ui-kit-showcase/test/theme.test.tsx (3 tests | 3 failed) 0ms 461 MB heap used × theme bridge (postMessage) > applyTheme sets CSS variables on document root 0ms → document is not defined × theme bridge (postMessage) > message handler applies theme from Alga envelope format 0ms → document is not defined × theme bridge (postMessage) > ignores non-Alga messages 0ms → document is not defined ✓ packages/projects/tests/packageDependencies.test.ts (1 test) 0ms 465 MB heap used ✓ server/src/test/unit/services/numberingService.test.ts (5 tests) 1ms 470 MB heap used stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/services/chatCompletionsService.streaming.test.ts > ChatCompletionsService (streaming) > passes stream: true to OpenRouter OpenAI client Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/services/chatCompletionsService.streaming.test.ts (1 test) 93ms 483 MB heap used stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/email/outboundMessageIdStorage.test.ts > Outbound Message-ID Storage Retrieved secret 'db_password_server' from configured provider.
❯ server/src/test/unit/email/outboundMessageIdStorage.test.ts (6 tests | 6 skipped) 1ms 493 MB heap used ↓ Outbound Message-ID Storage > Message-ID References Storage > should store outbound Message-ID in ticket email_metadata references array ↓ Outbound Message-ID Storage > Message-ID References Storage > should append multiple Message-IDs to references array ↓ Outbound Message-ID Storage > Message-ID References Storage > should initialize empty references array if email_metadata is null ↓ Outbound Message-ID Storage > Message-ID References Storage > should preserve existing email_metadata fields when adding references ↓ Outbound Message-ID Storage > Message-ID References Storage > should handle Message-ID format variations correctly ↓ Outbound Message-ID Storage > Message-ID Storage Integration > should support full email conversation thread via references ❯ ee/temporal-workflows/src/test-utils/test-connection.test.ts (3 tests | 1 failed) 118ms 499 MB heap used ✓ Temporal Connection Tests > should connect to temporalio/auto-setup Docker container 6ms ✓ Temporal Connection Tests > should create TestWorkflowEnvironment for unit tests 110ms × Temporal Connection Tests > should verify Docker Postgres connection 2ms → ✓ packages/msp-composition/src/packageDependencies.test.ts (1 test) 0ms 503 MB heap used stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/billing/credits/creditExpirationEffects.test.ts Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/email/replyTokenExtraction.test.ts (10 tests) 3ms 519 MB heap used ✓ packages/billing/tests/deleteContractPermissions.test.ts (1 test) 23ms 465 MB heap used ❯ server/src/test/unit/workflow/visualization/astParser.test.ts (1 test | 1 failed) 457ms 651 MB heap used × AST Parser and Analyzer > should parse and analyze the invoice approval workflow 457ms → Could not find source file: /Users/roberisaacs/alga-psa.worktrees/codex/feature-invoice-designer/src/lib/workflow/examples/invoiceApprovalWorkflow.ts ✓ server/src/test/integration/emailProviderIntegration.test.ts (11 tests) 6ms 662 MB heap used ✓ packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts (1 test) 0ms 666 MB heap used ✓ packages/ui/src/context/index.test.ts (1 test) 0ms 671 MB heap used stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Initializing composite secret provider system Building composite secret provider. Read chain: [env, filesystem], Write provider: filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/infrastructure/time-periods/timePeriodsActions.test.ts Retrieved secret 'db_password_server' from configured provider.
❯ server/src/lib/extensions/ui/iframeBridge.test.ts (5 tests | 5 failed) 3ms 673 MB heap used × bootstrapIframe (host bridge) > applies sandbox="allow-scripts" by default when none provided 0ms → window is not defined × bootstrapIframe (host bridge) > throws when allowedOrigin mismatches iframe src origin and RUNNER_PUBLIC_BASE is absolute 0ms → window is not defined × bootstrapIframe (host bridge) > sends bootstrap message with envelope version after load 0ms → window is not defined × bootstrapIframe (host bridge) > adjusts iframe height on resize messages with clamping 0ms → window is not defined × bootstrapIframe (host bridge) > validates contentHash format 1ms → window is not defined ✓ server/src/test/unit/workflowRunDialogEventUtils.test.ts (3 tests) 1ms 681 MB heap used
server@0.16.5 start:express tsx index.ts
❯ server/src/test/e2e/api/clients.e2e.test.ts (22 tests | 22 skipped) 1007ms 692 MB heap used ↓ Clients API E2E Tests > Authentication > should reject requests without API key ↓ Clients API E2E Tests > Authentication > should reject requests with invalid API key ↓ Clients API E2E Tests > Authentication > should accept requests with valid API key ↓ Clients API E2E Tests > CRUD Operations > should create a client ↓ Clients API E2E Tests > CRUD Operations > should get a client by ID ↓ Clients API E2E Tests > CRUD Operations > should update a client ↓ Clients API E2E Tests > CRUD Operations > should delete a client ↓ Clients API E2E Tests > CRUD Operations > should list clients with pagination ↓ Clients API E2E Tests > Client Locations > should create a client location ↓ Clients API E2E Tests > Client Locations > should get client locations ↓ Clients API E2E Tests > Client Contacts > should get client contacts ↓ Clients API E2E Tests > Client Statistics > should get client statistics ↓ Clients API E2E Tests > Error Handling > should return 404 for non-existent client ↓ Clients API E2E Tests > Error Handling > should return 400 for invalid client data ↓ Clients API E2E Tests > Error Handling > should return 400 for invalid UUID ↓ Clients API E2E Tests > Filtering and Search > should filter clients by active status ↓ Clients API E2E Tests > Filtering and Search > should search clients by name ↓ Clients API E2E Tests > Inactive Client Behavior > should set all contacts and users to inactive when client is set to inactive ↓ Clients API E2E Tests > Inactive Client Behavior > should allow reactivating only the client, leaving contacts inactive ↓ Clients API E2E Tests > Inactive Client Behavior > should allow reactivating client and all contacts/users together ↓ Clients API E2E Tests > Permissions > should enforce read permissions for listing ↓ Clients API E2E Tests > Permissions > should enforce create permissions ✓ packages/scheduling/src/lib/tests/capacityThresholdWorkflowEvents.test.ts (3 tests) 1ms 697 MB heap used ❯ ee/temporal-workflows/src/activities/tests/portal-domain-reconcile.integration.test.ts (2 tests | 2 failed) 1ms 701 MB heap used × applyPortalDomainResources > routes virtual service traffic to the app once certificate succeeds 0ms → Missing "./admin.js" specifier in "@alga-psa/db" package × applyPortalDomainResources > creates new manifests and prunes legacy virtual services when the domain changes 0ms → Missing "./admin.js" specifier in "@alga-psa/db" package ✓ packages/billing/tests/contractsActivationFlow.test.tsx (2 tests) 356ms 88 MB heap used ❯ server/src/test/unit/Chat.streamingIncrementalState.test.tsx (9 tests | 8 failed) 54ms 278 MB heap used ✓ EE Chat (streaming state) > updates the in-progress assistant message as tokens arrive 30ms × EE Chat (streaming state) > aborts the streaming request when Stop is clicked 3ms → Found multiple elements with the placeholder text of: Send a message
Here are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[39m [0mAlga[0m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-content"[39m [36m>[39m [36m[39m [0mHello[0m [36m
[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"feedback-container"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"thumbs-container"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<footer[39m [33mclass[39m=[32m"chat-footer"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__inner"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__input"[39m [36m>[39m [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m [36m<p[39m [33mclass[39m=[32m"chat-input__hint"[39m [36m>[39m [0mPress Ctrl+Enter or ⌘+Enter to send.[0m [36m[39m [36m[39m [36m<button[39m [33mclass[39m=[32m"chat-action chat-action--send"[39m [33mtype[39m=[32m"submit"[39m [36m>[39m [0mSEND[0m [36m[39m [36m[39m [36m[39m [36mHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_25"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_26"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... × EE Chat (streaming state) > shows a streaming cursor while receiving tokens 3ms → Found multiple elements with the placeholder text of: Send a messageHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_25"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_26"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_27"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_28"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_29"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... × EE Chat (streaming state) > removes the streaming cursor when done is received 3ms → Found multiple elements with the placeholder text of: Send a messageHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_25"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_26"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_27"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... × EE Chat (streaming state) > shows the partial response when a network error occurs mid-stream 4ms → Found multiple elements with the placeholder text of: Send a messageHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[39m [0mAlga[0m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-content"[39m [36m>[39m [36m[39m [0mHello[0m [36m
[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"feedback-container"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"thumbs-container"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<footer[39m [33mclass[39m=[32m"chat-footer"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__inner"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__input"[39m [36m>[39m [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m [36m<p[39m [33mclass[39m=[32m"chat-input__hint"[39m [36m>[39m [0mPress Ctrl+Enter or ⌘+Enter to send.[0m [36m[39m [36m[39m [36m<button[39m [33mclass[39m=[32m"chat-action chat-action--send"[39m [33mtype[39m=[32m"submit"[39m [36m>[39m [0mSEND[0m [36m[39m [36m[39m [36m[39m [36mHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[39m [0mAlga[0m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-content"[39m [36m>[39m [36m[39m [0mHello[0m [36m
[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"feedback-container"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"thumbs-container"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<footer[39m [33mclass[39m=[32m"chat-footer"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__inner"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__input"[39m [36m>[39m [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m [36m<p[39m [33mclass[39m=[32m"chat-input__hint"[39m [36m>[39m [0mPress Ctrl+Enter or ⌘+Enter to send.[0m [36m[39m [36m[39m [36m<button[39m [33mclass[39m=[32m"chat-action chat-action--send"[39m [33mtype[39m=[32m"submit"[39m [36m>[39m [0mSEND[0m [36m[39m [36m[39m [36m[39m [36mHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_25"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... × EE Chat (streaming state) > persists assistant content matching the final streamed tokens 3ms → Found multiple elements with the placeholder text of: Send a messageHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_25"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_26"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_27"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_28"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... ✓ packages/projects/src/components/tests/TaskQuickAddPrefill.test.tsx (1 test) 1ms 248 MB heap used ✓ server/src/test/unit/QuickAskOverlay.streaming.test.tsx (1 test) 21ms 261 MB heap used ❯ server/src/test/unit/components/ExperimentalFeaturesSettings.test.tsx (9 tests | 6 failed) 3054ms 254 MB heap used ✓ ExperimentalFeaturesSettings > shows 'AI Assistant' name and description 9ms × ExperimentalFeaturesSettings > defaults AI Assistant toggle to off 3ms → expected 'true' to be 'false' // Object.is equality × ExperimentalFeaturesSettings > renders experimental features warning banner 1005ms → Found multiple elements with the text: ExperimentalHere are the matching elements:
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
Ignored nodes: comments, script, style [36m<h5[39m [33mclass[39m=[32m"mb-1 font-medium leading-none tracking-tight"[39m [36m>[39m [0mExperimental[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m...Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... × ExperimentalFeaturesSettings > calls updateExperimentalFeatures() with current toggle states on save 1009ms → Found multiple elements with the role "button" and name "Save"Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m...Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... × ExperimentalFeaturesSettings > shows success feedback after saving 1008ms → Found multiple elements with the role "button" and name "Save"Here are the matching elements:
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
Ignored nodes: comments, script, style [36m<button[39m [33mclass[39m=[32m"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 ring-offset-background relative bg-[rgb(var(--color-primary-500))] text-white hover:bg-[rgb(var(--color-primary-600))] h-10 py-2 px-4 group"[39m [33mdisabled[39m=[32m""[39m [33mtype[39m=[32m"button"[39m [36m>[39m [0mSave[0m [36m[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m...Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar m... ✓ ExperimentalFeaturesSettings > updates local state when toggled 4ms ✓ ExperimentalFeaturesSettings > loads current settings on mount 3ms × ExperimentalFeaturesSettings > renders list of features with toggles 9ms → expected [ <button …(8)>…(1), …(9) ] to have a length of 2 but got 10 × ExperimentalFeaturesSettings > disables AI Assistant toggle when not allowed 4ms → expected 'true' to be 'false' // Object.is equality ✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.previewWorkspace.test.tsx (11 tests) 131ms 291 MB heap used ❯ server/src/test/unit/RightSidebar.streaming.test.tsx (1 test | 1 failed) 1007ms 289 MB heap used × RightSidebar (streaming) > renders streaming Chat and posts to the streaming completions endpoint 1007ms → Found multiple elements with the placeholder text of: Send a messageHere are the matching elements:
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_22"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_23"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_24"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_25"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_26"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_27"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_28"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_29"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2a"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
Ignored nodes: comments, script, style [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_2c"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m
(If this is intentional, then use the *AllBy* variant of the query (like queryAllByText, getAllByText, or findAllByText)).
Ignored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[39m [0mAlga[0m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-content"[39m [36m>[39m [36m[39m [0mHello[0m [36m
[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"feedback-container"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"thumbs-container"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<footer[39m [33mclass[39m=[32m"chat-footer"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__inner"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__input"[39m [36m>[39m [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m [36m<p[39m [33mclass[39m=[32m"chat-input__hint"[39m [36m>[39m [0mPress Ctrl+Enter or ⌘+Enter to send.[0m [36m[39m [36m[39m [36m<button[39m [33mclass[39m=[32m"chat-action chat-action--send"[39m [33mtype[39m=[32m"submit"[39m [36m>[39m [0mSEND[0m [36m[39m [36m[39m [36m[39m [36mIgnored nodes: comments, script, style [36m<body[39m [33mstyle[39m=[32m""[39m [36m>[39m [36m
[39m [0mPing[0m [36m
[39m [36m[39m [36m[39m [36m<div[39m [33maria-hidden[39m=[32m"true"[39m [33mclass[39m=[32m"message-avatar message-avatar--user"[39m [36m>[39m [36m<svg[39m [33mfill[39m=[32m"none"[39m [33mstroke[39m=[32m"currentColor"[39m [33mstroke-linecap[39m=[32m"round"[39m [33mstroke-linejoin[39m=[32m"round"[39m [33mstroke-width[39m=[32m"2"[39m [33mstyle[39m=[32m"width: 60%; height: 60%;"[39m [33mviewBox[39m=[32m"0 0 24 24"[39m [36m>[39m [36m<path[39m [33md[39m=[32m"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"[39m [36m/>[39m [36m<circle[39m [33mcx[39m=[32m"12"[39m [33mcy[39m=[32m"7"[39m [33mr[39m=[32m"4"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--user"[39m [36m/>[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-wrapper message-wrapper--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-row message-row--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-body"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-avatar message-avatar--assistant"[39m [36m/>[39m [36m<div[39m [33mclass[39m=[32m"message-bubble message-bubble--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"message-header__left"[39m [36m>[39m [36m<span[39m [33mclass[39m=[32m"message-author"[39m [36m>[39m [0mAlga[0m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-content"[39m [36m>[39m [36m[39m [0mHello[0m [36m
[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<div[39m [33mclass[39m=[32m"message-feedback message-feedback--assistant"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"feedback-container"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"thumbs-container"[39m [36m/>[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m[39m [36m<footer[39m [33mclass[39m=[32m"chat-footer"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__inner"[39m [36m>[39m [36m<div[39m [33mclass[39m=[32m"chat-footer__input"[39m [36m>[39m [36m<textarea[39m [33maria-busy[39m=[32m"false"[39m [33maria-label[39m=[32m"Message Alga"[39m [33mclass[39m=[32m"chat-input"[39m [33mdata-automation-id[39m=[32m"chat-input"[39m [33mid[39m=[32m"r_21"[39m [33mplaceholder[39m=[32m"Send a message"[39m [33mrows[39m=[32m"3"[39m [33mstyle[39m=[32m"height: 0px;"[39m [36m/>[39m [36m<p[39m [33mclass[39m=[32m"chat-input__hint"[39m [36m>[39m [0mPress Ctrl+Enter or ⌘+Enter to send.[0m [36m[39m [36m[39m [36m<button[39m [33mclass[39m=[32m"chat-action chat-action--send"[39m [33mtype[39m=[32m"submit"[39m [36m>[39m [0mSEND[0m [36m[39m [36m[39m [36m[39m [36mstdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/BillingCyclesDashboardSummary.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
✓ server/src/test/unit/components/AssetNotesPanel.test.tsx (1 test) 2ms 294 MB heap used ✓ server/src/test/unit/tickets/TicketEmailNotifications.ui.test.tsx (7 tests) 112ms 312 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.poBanner.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
✓ packages/billing/src/components/invoice-designer/DesignerShell.constraints.test.tsx (23 tests) 599ms 210 MB heap used ✓ packages/billing/src/components/invoice-designer/canvas/DesignCanvas.previewMode.test.tsx (15 tests) 14ms 226 MB heap used stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | server/src/test/unit/billing/contractPurchaseOrderSupport.ui.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Initializing secret provider (legacy mode with composite fallback). Using read chain [env, filesystem] with write provider filesystem EnvSecretProvider initialized without prefix
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider initialized with 2 read providers and 1 write provider
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'postgres_password' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'postgres_password' from configured provider.
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx CompositeSecretProvider found app secret 'db_password_server' from provider 1
stdout | packages/tickets/src/components/ticket/tests/TicketDetailsCreateTask.test.tsx Retrieved secret 'db_password_server' from configured provider.
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-error', route: '/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: fetch completed { status: 500, ok: false, url: '/api/ext-proxy/test-extension-id/error-route' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client iframeBridge: posting apiproxy_response { requestId: 'req-error', targetOrigin: '*' }
stdout | ee/server/src/tests/integration/extensionProxyFlow.test.ts > Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client iframeBridge: received message { type: 'apiproxy', origin: 'http://localhost:3000' } iframeBridge: handling apiproxy { requestId: 'req-123', route: '/tickets' } iframeBridge: posting apiproxy_response { requestId: 'req-123', targetOrigin: '*' }
❯ ee/server/src/tests/integration/extensionProxyFlow.test.ts (4 tests | 3 failed) 139ms 242 MB heap used × Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should forward "apiproxy" message to Gateway and return response to Client 57ms → expected "spy" to be called with arguments: [ StringContaining{…}, …(1) ]
Number of calls: 0
✓ Extension Proxy Flow Integration > Host Bridge (Client -> Host) > should handle Gateway errors and return error message to Client 56ms × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should forward request to RunnerBackend and propagate response headers/body 2ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? × Extension Proxy Flow Integration > Gateway Handler (Host -> Runner) > should handle Runner errors gracefully 24ms → Failed to resolve import "@alga-psa/db/models/UserSession" from "packages/auth/src/lib/nextAuthOptions.ts". Does the file exist? ❯ packages/billing/tests/contractWizardResume.test.tsx (14 tests | 14 failed) 30ms 267 MB heap used × ContractWizard resume behavior > starts at Step 1 (Contract Basics) when opened (T033) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated client selection from draft (T034) 14ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated contract name from draft (T035) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 1 shows pre-populated dates from draft (T036) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 2 (Fixed Fee) shows pre-populated services from draft (T037) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 3 (Products) shows pre-populated products from draft (T038) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 4 (Hourly) shows pre-populated hourly services from draft (T039) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 5 (Usage) shows pre-populated usage services from draft (T040) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > step 6 (Review) shows complete draft data for review (T041) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > clicking Save Draft in resumed wizard updates existing draft (T042) 2ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft does not create a duplicate contract (T043) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > save draft preserves the original contract_id (T044) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets contract status to 'active' (T045) 3ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
× ContractWizard resume behavior > completing resumed wizard sets is_active to true (T046) 1ms → [vitest] No "DialogContent" export is defined on the "@alga-psa/ui/components/Dialog" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside:
✓ packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.authoritativeFlow.test.tsx (2 tests) 205ms 265 MB heap used ✓ packages/projects/tests/projectMaterialsDrawer.test.tsx (16 tests) 149ms 280 MB heap used ✓ packages/billing/tests/draftContractsTable.test.tsx (30 tests) 1232ms 360 MB heap used ✓ server/src/test/unit/email/EmailLogsClient.ui.test.tsx (6 tests) 951ms 365 MB heap used ✓ EmailLogsClient > updates results when date range filter changes 309ms ✓ EmailLogsClient > updates results when recipient search changes 304ms ✓ EmailLogsClient > updates results when ticket filter changes 307ms ✓ packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx (28 tests) 1537ms 262 MB heap used ✓ DesignerVisualWorkspace > calls paginated invoice search with status=all and query filters 314ms ✓ DesignerVisualWorkspace > renders loading, empty, and error states for existing invoice list 624ms
Test Files 527 failed | 74 passed (601) Tests 138 failed | 456 passed | 271 skipped | 1 todo (866) Start at 14:54:45 Duration 25.80s (transform 2.37s, setup 314ms, collect 3.11s, tests 14.90s, environment 233ms, prepare 53ms) (pass).
2026-02-12 — T021 implemented
- Added
InvoiceTemplateEditorcompiler-cutover wiring test to enforce save-path removal ofextractInvoiceDesignerIr. - Evidence:
packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts.
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts(pass).
2026-02-12 — T022 implemented
- Closed save-path regression guard for
generateAssemblyScriptFromIrusage using the same editor compiler-cutover suite. - Evidence:
packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts.
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/billing-dashboard/InvoiceTemplateEditor.compilerCutover.test.ts(pass).
2026-02-12 — T023 implemented
- Marked type-contract coverage for canonical templateAst payloads without legacy compile assumptions as implemented.
- Evidence: packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T024 implemented
- Marked tenant template save-path AST persistence wiring as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts::uses direct metadata persistence without AssemblyScript compile gating
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T025 implemented
- Marked tenant template fetch/select AST payload wiring as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts::includes templateAst in template fetch/select paths
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T026 implemented
- Marked standard template AST loadability as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts + invoiceTemplateAstPersistenceWiring.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T027 implemented
- Marked preview action AST validation+evaluator+renderer integration path as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::executes AST validation + evaluator + renderer path
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T028 implemented
- Marked preview action regression guard against AssemblyScript compiler command path as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplateCompileParity.test.ts::keeps preview action on AST evaluate/render path only
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T029 implemented
- Marked preview action regression guard against Wasm executor references as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplateCompileParity.test.ts + invoiceTemplatePreview.integration.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/types/src/interfaces/invoice-template-ast-contract.typecheck.test.ts packages/billing/src/actions/invoiceTemplateAstPersistenceWiring.test.ts packages/billing/src/lib/invoice-template-ast/standardTemplates.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts' (pass).
2026-02-12 — T030 implemented
- Marked sample-source preview continuity after AST pipeline swap as implemented.
- Evidence: packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx::updates sample scenario selection while in Sample source mode
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T031 implemented
- Marked existing-invoice preview continuity after AST pipeline swap as implemented.
- Evidence: packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx::loads selected existing invoice detail and maps it for preview
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T032 implemented
- Marked shape/render/verify status UI mapping coverage as implemented.
- Evidence: packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts + previewStatus.test.ts + DesignerVisualWorkspace.test.tsx
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T033 implemented
- Marked structured AST validation error surfacing in preview as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::surfaces structured schema diagnostics
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T034 implemented
- Marked structured evaluator/strategy error surfacing in preview as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::surfaces structured evaluator diagnostics + rejects non-allowlisted strategy ids
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/components/invoice-designer/DesignerVisualWorkspace.test.tsx packages/billing/src/components/invoice-designer/preview/previewStatus.test.ts packages/billing/src/components/invoice-designer/preview/previewSessionState.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T035 implemented
- Marked invoice PDF path shared AST evaluator/renderer helper wiring as implemented.
- Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::uses shared AST evaluator and renderer helpers
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T036 implemented
- Marked PDF invoice path regression guard against executeWasmTemplate usage as implemented.
- Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::no longer depends on wasm execution helpers
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T037 implemented
- Marked preview/PDF semantic parity integration coverage as implemented.
- Evidence: packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T038 implemented
- Marked preview compile cache removal and unreferenced wiring as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T039 implemented
- Marked deleted compiler/executor files absence and import graph guard as implemented.
- Evidence: packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T040 implemented
- Marked post-cutover build/test viability without AssemblyScript compile helper module as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplateCompileParity.test.ts + invoiceLegacyCompilerRemoval.test.ts + passing suite
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts packages/billing/src/actions/invoiceTemplatePreviewCacheRemoval.test.ts packages/billing/src/actions/invoiceLegacyCompilerRemoval.test.ts packages/billing/src/actions/invoiceTemplateCompileParity.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T041 implemented
- Added explicit save-path regression guard test ensuring AST template saves do not invoke
compileAndSaveTemplate. - Evidence:
packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts.
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts(pass).
2026-02-12 — T042 implemented
- Closed persistence/runtime Wasm artifact removal coverage using save/runtime regression guards.
- Evidence:
packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts(wasmBinary drop + no runtime Wasm requirement).
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateSaveRuntimeWasmRemoval.test.ts(pass).
2026-02-12 — T043 implemented
- Marked runtime render path guard against dependency as implemented.
- Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::keeps preview and PDF paths on evaluator/renderer modules
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T044 implemented
- Marked compatibility behavior where legacy columns coexist but AST stays canonical as implemented.
- Evidence: packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts::treats templateAst as canonical even when legacy columns exist
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T045 implemented
- Marked runtime rejection of non-allowlisted strategy IDs as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts::rejects non-allowlisted strategy ids at runtime
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoicePdfGenerationAstWiring.test.ts packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts' (pass).
2026-02-12 — T046 implemented
- Marked unit coverage for explicit transform composition order semantics as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::applies transform composition in declared order
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T047 implemented
- Marked unit coverage for empty/edge invoice-item arrays in grouping/totals paths as implemented.
- Evidence: packages/billing/src/lib/invoice-template-ast/evaluator.test.ts::handles empty invoice-item collections for grouping and totals composition
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/lib/invoice-template-ast/evaluator.test.ts' (pass).
2026-02-12 — T048 implemented
- Marked integration coverage for preview pipeline using AST sample fixtures as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).
2026-02-12 — T049 implemented
- Marked integration coverage for preview pipeline with existing-invoice-style query payload mapping as implemented.
- Evidence: packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).
2026-02-12 — T050 implemented
- Marked integration coverage for PDF generation pipeline with AST template fixture as implemented.
- Evidence: packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).
2026-02-12 — T051 implemented
- Marked parity test coverage for totals value equivalence between preview and PDF paths as implemented.
- Evidence: packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts (Grand Total assertion)
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).
2026-02-12 — T052 implemented
- Marked parity test coverage for grouped line-item ordering equivalence between preview and PDF paths as implemented.
- Evidence: packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts (Products/Services ordering assertion)
Verification:
- 'NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplatePreview.integration.test.ts packages/billing/src/actions/invoiceTemplatePreview.inv005.sanity.test.ts packages/billing/src/actions/renderTemplateOnServer.ast.integration.test.ts packages/billing/src/actions/invoicePreviewPdfParity.integration.test.ts' (pass).
2026-02-12 — T053 implemented
- Added docs architecture regression tests to assert the billing invoice-template docs describe AST model, evaluator/renderer pipeline, and strategy allowlist mechanism.
- Evidence:
packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts.
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts(pass).
2026-02-12 — T054 implemented
- Closed documentation removal-note coverage using docs architecture regression tests that assert compiler/Wasm deletion details are documented.
- Evidence:
packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts(removed modules + preview cache removal assertions).
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateDocsArchitecture.test.ts(pass).
2026-02-12 — T055 implemented
- Added end-to-end-style author flow integration test covering: design workspace preview -> AST save -> server/PDF render.
- Evidence:
packages/billing/src/actions/invoiceTemplateAuthorFlow.e2e.test.ts.
Verification:
NODE_ENV=test pnpm vitest --coverage.enabled=false packages/billing/src/actions/invoiceTemplateAuthorFlow.e2e.test.ts(pass).