@alwaysmeticulous/cli 2.326.0 → 2.327.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/commonjs-dependencies.spec.d.ts +2 -0
- package/dist/__tests__/commonjs-dependencies.spec.d.ts.map +1 -0
- package/dist/__tests__/commonjs-dependencies.spec.js +82 -0
- package/dist/__tests__/commonjs-dependencies.spec.js.map +1 -0
- package/dist/command-utils/__tests__/parse-rewrites.spec.js +2 -2
- package/dist/command-utils/__tests__/parse-rewrites.spec.js.map +1 -1
- package/dist/command-utils/__tests__/warn-regex-rewrites.spec.js +2 -2
- package/dist/command-utils/__tests__/warn-regex-rewrites.spec.js.map +1 -1
- package/dist/command-utils/common-options.js +2 -2
- package/dist/command-utils/common-options.js.map +1 -1
- package/dist/command-utils/detect-upload-mode.js +2 -2
- package/dist/command-utils/detect-upload-mode.js.map +1 -1
- package/dist/command-utils/detect-upload-mode.spec.js +2 -2
- package/dist/command-utils/detect-upload-mode.spec.js.map +1 -1
- package/dist/command-utils/download-session.utils.js +2 -2
- package/dist/command-utils/download-session.utils.js.map +1 -1
- package/dist/command-utils/json-args.js +2 -2
- package/dist/command-utils/json-args.js.map +1 -1
- package/dist/command-utils/json-args.spec.js +2 -2
- package/dist/command-utils/json-args.spec.js.map +1 -1
- package/dist/command-utils/parse-container-env.js +2 -2
- package/dist/command-utils/parse-container-env.js.map +1 -1
- package/dist/command-utils/parse-rewrites.js +2 -2
- package/dist/command-utils/parse-rewrites.js.map +1 -1
- package/dist/command-utils/print-json.js +2 -2
- package/dist/command-utils/print-json.js.map +1 -1
- package/dist/command-utils/sentry.utils.js +2 -2
- package/dist/command-utils/sentry.utils.js.map +1 -1
- package/dist/command-utils/warn-regex-rewrites.js +2 -2
- package/dist/command-utils/warn-regex-rewrites.js.map +1 -1
- package/dist/commands/agent/agent-review-writes.command.spec.js +2 -2
- package/dist/commands/agent/agent-review-writes.command.spec.js.map +1 -1
- package/dist/commands/agent/build-git-options.js +2 -2
- package/dist/commands/agent/build-git-options.js.map +1 -1
- package/dist/commands/agent/build-git-options.spec.js +2 -2
- package/dist/commands/agent/build-git-options.spec.js.map +1 -1
- package/dist/commands/agent/coverage-columns.util.js +2 -2
- package/dist/commands/agent/coverage-columns.util.js.map +1 -1
- package/dist/commands/agent/create-diff-comment.command.js +2 -2
- package/dist/commands/agent/create-diff-comment.command.js.map +1 -1
- package/dist/commands/agent/diff-comment-write.utils.js +2 -2
- package/dist/commands/agent/diff-comment-write.utils.js.map +1 -1
- package/dist/commands/agent/diff-comments.command.js +2 -2
- package/dist/commands/agent/diff-comments.command.js.map +1 -1
- package/dist/commands/agent/diff-comments.command.spec.js +2 -2
- package/dist/commands/agent/diff-comments.command.spec.js.map +1 -1
- package/dist/commands/agent/ignore-diff.command.js +2 -2
- package/dist/commands/agent/ignore-diff.command.js.map +1 -1
- package/dist/commands/agent/index.js +2 -2
- package/dist/commands/agent/index.js.map +1 -1
- package/dist/commands/agent/js-coverage-diff.command.js +2 -2
- package/dist/commands/agent/js-coverage-diff.command.js.map +1 -1
- package/dist/commands/agent/js-coverage.command.handler.spec.js +2 -2
- package/dist/commands/agent/js-coverage.command.handler.spec.js.map +1 -1
- package/dist/commands/agent/js-coverage.command.js +2 -2
- package/dist/commands/agent/js-coverage.command.js.map +1 -1
- package/dist/commands/agent/js-coverage.command.spec.js +2 -2
- package/dist/commands/agent/js-coverage.command.spec.js.map +1 -1
- package/dist/commands/agent/reject-diff.command.js +2 -2
- package/dist/commands/agent/reject-diff.command.js.map +1 -1
- package/dist/commands/agent/reject-diff.command.spec.js +2 -2
- package/dist/commands/agent/reject-diff.command.spec.js.map +1 -1
- package/dist/commands/agent/reply-to-diff-comment.command.js +2 -2
- package/dist/commands/agent/reply-to-diff-comment.command.js.map +1 -1
- package/dist/commands/agent/screenshot-dom-diff.command.js +2 -2
- package/dist/commands/agent/screenshot-dom-diff.command.js.map +1 -1
- package/dist/commands/agent/screenshot-image-files.command.js +2 -2
- package/dist/commands/agent/screenshot-image-files.command.js.map +1 -1
- package/dist/commands/agent/screenshot-image.command.js +2 -2
- package/dist/commands/agent/screenshot-image.command.js.map +1 -1
- package/dist/commands/agent/sessions.command.js +2 -2
- package/dist/commands/agent/sessions.command.js.map +1 -1
- package/dist/commands/agent/sessions.command.spec.js +2 -2
- package/dist/commands/agent/sessions.command.spec.js.map +1 -1
- package/dist/commands/agent/submit-feedback.command.js +2 -2
- package/dist/commands/agent/submit-feedback.command.js.map +1 -1
- package/dist/commands/agent/test-run-check.command.js +2 -2
- package/dist/commands/agent/test-run-check.command.js.map +1 -1
- package/dist/commands/agent/test-run-check.command.spec.js +2 -2
- package/dist/commands/agent/test-run-check.command.spec.js.map +1 -1
- package/dist/commands/agent/test-run-diffs.command.js +2 -2
- package/dist/commands/agent/test-run-diffs.command.js.map +1 -1
- package/dist/commands/agent/test-run-diffs.command.spec.js +2 -2
- package/dist/commands/agent/test-run-diffs.command.spec.js.map +1 -1
- package/dist/commands/agent/test-run-diffs.utils.js +2 -2
- package/dist/commands/agent/test-run-diffs.utils.js.map +1 -1
- package/dist/commands/agent/test-run-diffs.utils.spec.js +2 -2
- package/dist/commands/agent/test-run-diffs.utils.spec.js.map +1 -1
- package/dist/commands/agent/test-run-for-commit.command.js +2 -2
- package/dist/commands/agent/test-run-for-commit.command.js.map +1 -1
- package/dist/commands/agent/timeline.command.js +2 -2
- package/dist/commands/agent/timeline.command.js.map +1 -1
- package/dist/commands/agent/timeline.command.spec.js +2 -2
- package/dist/commands/agent/timeline.command.spec.js.map +1 -1
- package/dist/commands/agent/trigger-test-run.command.js +2 -2
- package/dist/commands/agent/trigger-test-run.command.js.map +1 -1
- package/dist/commands/agent/trigger-test-run.command.spec.js +2 -2
- package/dist/commands/agent/trigger-test-run.command.spec.js.map +1 -1
- package/dist/commands/agent/upload-build.command.js +2 -2
- package/dist/commands/agent/upload-build.command.js.map +1 -1
- package/dist/commands/all-commands.d.ts.map +1 -1
- package/dist/commands/all-commands.js +8 -6
- package/dist/commands/all-commands.js.map +1 -1
- package/dist/commands/auth/__tests__/get-project.command.spec.js +2 -2
- package/dist/commands/auth/__tests__/get-project.command.spec.js.map +1 -1
- package/dist/commands/auth/__tests__/list-projects.command.spec.js +2 -2
- package/dist/commands/auth/__tests__/list-projects.command.spec.js.map +1 -1
- package/dist/commands/auth/__tests__/login.command.spec.js +2 -2
- package/dist/commands/auth/__tests__/login.command.spec.js.map +1 -1
- package/dist/commands/auth/__tests__/logout.command.spec.js +2 -2
- package/dist/commands/auth/__tests__/logout.command.spec.js.map +1 -1
- package/dist/commands/auth/__tests__/set-project.command.spec.js +2 -2
- package/dist/commands/auth/__tests__/set-project.command.spec.js.map +1 -1
- package/dist/commands/auth/__tests__/whoami.command.spec.js +2 -2
- package/dist/commands/auth/__tests__/whoami.command.spec.js.map +1 -1
- package/dist/commands/auth/get-project.command.js +2 -2
- package/dist/commands/auth/get-project.command.js.map +1 -1
- package/dist/commands/auth/index.js +2 -2
- package/dist/commands/auth/index.js.map +1 -1
- package/dist/commands/auth/list-projects.command.js +2 -2
- package/dist/commands/auth/list-projects.command.js.map +1 -1
- package/dist/commands/auth/login.command.js +2 -2
- package/dist/commands/auth/login.command.js.map +1 -1
- package/dist/commands/auth/logout.command.js +2 -2
- package/dist/commands/auth/logout.command.js.map +1 -1
- package/dist/commands/auth/set-project.command.js +2 -2
- package/dist/commands/auth/set-project.command.js.map +1 -1
- package/dist/commands/auth/whoami.command.js +2 -2
- package/dist/commands/auth/whoami.command.js.map +1 -1
- package/dist/commands/ci/__tests__/label-commit.utils.spec.js +2 -2
- package/dist/commands/ci/__tests__/label-commit.utils.spec.js.map +1 -1
- package/dist/commands/ci/__tests__/session-filter.utils.spec.js +2 -2
- package/dist/commands/ci/__tests__/session-filter.utils.spec.js.map +1 -1
- package/dist/commands/ci/agent-test.command.js +2 -2
- package/dist/commands/ci/agent-test.command.js.map +1 -1
- package/dist/commands/ci/deprecated-trigger-options.js +2 -2
- package/dist/commands/ci/deprecated-trigger-options.js.map +1 -1
- package/dist/commands/ci/index.js +2 -2
- package/dist/commands/ci/index.js.map +1 -1
- package/dist/commands/ci/label-commit.command.js +2 -2
- package/dist/commands/ci/label-commit.command.js.map +1 -1
- package/dist/commands/ci/label-commit.core.js +2 -2
- package/dist/commands/ci/label-commit.core.js.map +1 -1
- package/dist/commands/ci/label-commit.types.js +2 -2
- package/dist/commands/ci/label-commit.types.js.map +1 -1
- package/dist/commands/ci/label-commit.utils.js +2 -2
- package/dist/commands/ci/label-commit.utils.js.map +1 -1
- package/dist/commands/ci/prepare.command.js +2 -2
- package/dist/commands/ci/prepare.command.js.map +1 -1
- package/dist/commands/ci/resolve-git-options.js +2 -2
- package/dist/commands/ci/resolve-git-options.js.map +1 -1
- package/dist/commands/ci/run-local.command.js +2 -2
- package/dist/commands/ci/run-local.command.js.map +1 -1
- package/dist/commands/ci/run-with-uploaded-asset-chunks.command.js +2 -2
- package/dist/commands/ci/run-with-uploaded-asset-chunks.command.js.map +1 -1
- package/dist/commands/ci/run-with-uploaded-asset-chunks.command.spec.js +2 -2
- package/dist/commands/ci/run-with-uploaded-asset-chunks.command.spec.js.map +1 -1
- package/dist/commands/ci/run-with-uploaded-asset-chunks.utils.js +2 -2
- package/dist/commands/ci/run-with-uploaded-asset-chunks.utils.js.map +1 -1
- package/dist/commands/ci/run.command.js +2 -2
- package/dist/commands/ci/run.command.js.map +1 -1
- package/dist/commands/ci/session-filter.utils.js +2 -2
- package/dist/commands/ci/session-filter.utils.js.map +1 -1
- package/dist/commands/ci/start-tunnel.command.js +2 -2
- package/dist/commands/ci/start-tunnel.command.js.map +1 -1
- package/dist/commands/ci/trigger-test-run.core.js +2 -2
- package/dist/commands/ci/trigger-test-run.core.js.map +1 -1
- package/dist/commands/ci/trigger-test-run.types.js +2 -2
- package/dist/commands/ci/trigger-test-run.types.js.map +1 -1
- package/dist/commands/ci/upload-asset-chunk.command.js +2 -2
- package/dist/commands/ci/upload-asset-chunk.command.js.map +1 -1
- package/dist/commands/ci/upload-assets.command.js +2 -2
- package/dist/commands/ci/upload-assets.command.js.map +1 -1
- package/dist/commands/ci/upload-container.command.js +2 -2
- package/dist/commands/ci/upload-container.command.js.map +1 -1
- package/dist/commands/crawl.command.js +2 -2
- package/dist/commands/crawl.command.js.map +1 -1
- package/dist/commands/debug/clean-workspaces.js +2 -2
- package/dist/commands/debug/clean-workspaces.js.map +1 -1
- package/dist/commands/debug/index.js +2 -2
- package/dist/commands/debug/index.js.map +1 -1
- package/dist/commands/debug/present-workspace.js +2 -2
- package/dist/commands/debug/present-workspace.js.map +1 -1
- package/dist/commands/debug/project-worktree.js +2 -2
- package/dist/commands/debug/project-worktree.js.map +1 -1
- package/dist/commands/deprecated-aliases.js +2 -2
- package/dist/commands/deprecated-aliases.js.map +1 -1
- package/dist/commands/download/index.js +2 -2
- package/dist/commands/download/index.js.map +1 -1
- package/dist/commands/download/replay.command.js +2 -2
- package/dist/commands/download/replay.command.js.map +1 -1
- package/dist/commands/download/session.command.js +2 -2
- package/dist/commands/download/session.command.js.map +1 -1
- package/dist/commands/download/test-run.command.js +2 -2
- package/dist/commands/download/test-run.command.js.map +1 -1
- package/dist/commands/local/get-edited-files.utils.js +2 -2
- package/dist/commands/local/get-edited-files.utils.js.map +1 -1
- package/dist/commands/local/get-edited-files.utils.spec.js +2 -2
- package/dist/commands/local/get-edited-files.utils.spec.js.map +1 -1
- package/dist/commands/local/index.js +2 -2
- package/dist/commands/local/index.js.map +1 -1
- package/dist/commands/local/relevant-sessions.command.js +2 -2
- package/dist/commands/local/relevant-sessions.command.js.map +1 -1
- package/dist/commands/onboard/__tests__/build-context.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/build-context.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/build-context.spec.js +179 -0
- package/dist/commands/onboard/__tests__/build-context.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/check-vcs-link.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/check-vcs-link.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/check-vcs-link.spec.js +164 -0
- package/dist/commands/onboard/__tests__/check-vcs-link.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/codex-mcp.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/codex-mcp.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/codex-mcp.spec.js +73 -0
- package/dist/commands/onboard/__tests__/codex-mcp.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/detect-framework.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/detect-framework.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/detect-framework.spec.js +277 -0
- package/dist/commands/onboard/__tests__/detect-framework.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/git-repo-info.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/git-repo-info.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/git-repo-info.spec.js +109 -0
- package/dist/commands/onboard/__tests__/git-repo-info.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/inline-doc-constants.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/inline-doc-constants.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/inline-doc-constants.spec.js +157 -0
- package/dist/commands/onboard/__tests__/inline-doc-constants.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/install-skills.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/install-skills.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/install-skills.spec.js +158 -0
- package/dist/commands/onboard/__tests__/install-skills.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/materialize-workspace.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/materialize-workspace.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/materialize-workspace.spec.js +116 -0
- package/dist/commands/onboard/__tests__/materialize-workspace.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/resolve-app.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/resolve-app.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/resolve-app.spec.js +166 -0
- package/dist/commands/onboard/__tests__/resolve-app.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/safe-repo-fs.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/safe-repo-fs.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/safe-repo-fs.spec.js +137 -0
- package/dist/commands/onboard/__tests__/safe-repo-fs.spec.js.map +1 -0
- package/dist/commands/onboard/__tests__/setup-agent-integrations.spec.d.ts +2 -0
- package/dist/commands/onboard/__tests__/setup-agent-integrations.spec.d.ts.map +1 -0
- package/dist/commands/onboard/__tests__/setup-agent-integrations.spec.js +286 -0
- package/dist/commands/onboard/__tests__/setup-agent-integrations.spec.js.map +1 -0
- package/dist/commands/onboard/build-context.d.ts +16 -0
- package/dist/commands/onboard/build-context.d.ts.map +1 -0
- package/dist/commands/onboard/build-context.js +104 -0
- package/dist/commands/onboard/build-context.js.map +1 -0
- package/dist/commands/onboard/check-vcs-link.d.ts +14 -0
- package/dist/commands/onboard/check-vcs-link.d.ts.map +1 -0
- package/dist/commands/onboard/check-vcs-link.js +111 -0
- package/dist/commands/onboard/check-vcs-link.js.map +1 -0
- package/dist/commands/onboard/codex-mcp.d.ts +24 -0
- package/dist/commands/onboard/codex-mcp.d.ts.map +1 -0
- package/dist/commands/onboard/codex-mcp.js +302 -0
- package/dist/commands/onboard/codex-mcp.js.map +1 -0
- package/dist/commands/onboard/customer-agents.d.ts +9 -0
- package/dist/commands/onboard/customer-agents.d.ts.map +1 -0
- package/dist/commands/onboard/customer-agents.js +19 -0
- package/dist/commands/onboard/customer-agents.js.map +1 -0
- package/dist/commands/onboard/customer-agents.json +17 -0
- package/dist/commands/onboard/customer-docs.d.ts +21 -0
- package/dist/commands/onboard/customer-docs.d.ts.map +1 -0
- package/dist/commands/onboard/customer-docs.js +31 -0
- package/dist/commands/onboard/customer-docs.js.map +1 -0
- package/dist/commands/onboard/customer-docs.json +35 -0
- package/dist/commands/onboard/detect-framework.d.ts +26 -0
- package/dist/commands/onboard/detect-framework.d.ts.map +1 -0
- package/dist/commands/onboard/detect-framework.js +305 -0
- package/dist/commands/onboard/detect-framework.js.map +1 -0
- package/dist/commands/onboard/discover-apps.d.ts +21 -0
- package/dist/commands/onboard/discover-apps.d.ts.map +1 -0
- package/dist/commands/onboard/discover-apps.js +318 -0
- package/dist/commands/onboard/discover-apps.js.map +1 -0
- package/dist/commands/onboard/docs-urls.d.ts +11 -0
- package/dist/commands/onboard/docs-urls.d.ts.map +1 -0
- package/dist/commands/onboard/docs-urls.js +17 -0
- package/dist/commands/onboard/docs-urls.js.map +1 -0
- package/dist/commands/onboard/git-repo-info.d.ts +15 -0
- package/dist/commands/onboard/git-repo-info.d.ts.map +1 -0
- package/dist/commands/onboard/git-repo-info.js +84 -0
- package/dist/commands/onboard/git-repo-info.js.map +1 -0
- package/dist/commands/onboard/index.d.ts +18 -0
- package/dist/commands/onboard/index.d.ts.map +1 -0
- package/dist/commands/onboard/index.js +164 -0
- package/dist/commands/onboard/index.js.map +1 -0
- package/dist/commands/onboard/inline-doc-constants.d.ts +21 -0
- package/dist/commands/onboard/inline-doc-constants.d.ts.map +1 -0
- package/dist/commands/onboard/inline-doc-constants.js +238 -0
- package/dist/commands/onboard/inline-doc-constants.js.map +1 -0
- package/dist/commands/onboard/launch-agent.d.ts +65 -0
- package/dist/commands/onboard/launch-agent.d.ts.map +1 -0
- package/dist/commands/onboard/launch-agent.js +311 -0
- package/dist/commands/onboard/launch-agent.js.map +1 -0
- package/dist/commands/onboard/materialize-workspace.d.ts +68 -0
- package/dist/commands/onboard/materialize-workspace.d.ts.map +1 -0
- package/dist/commands/onboard/materialize-workspace.js +177 -0
- package/dist/commands/onboard/materialize-workspace.js.map +1 -0
- package/dist/commands/onboard/print-summary.d.ts +10 -0
- package/dist/commands/onboard/print-summary.d.ts.map +1 -0
- package/dist/commands/onboard/print-summary.js +49 -0
- package/dist/commands/onboard/print-summary.js.map +1 -0
- package/dist/commands/onboard/resolve-app.d.ts +21 -0
- package/dist/commands/onboard/resolve-app.d.ts.map +1 -0
- package/dist/commands/onboard/resolve-app.js +78 -0
- package/dist/commands/onboard/resolve-app.js.map +1 -0
- package/dist/commands/onboard/resolve-project.d.ts +14 -0
- package/dist/commands/onboard/resolve-project.d.ts.map +1 -0
- package/dist/commands/onboard/resolve-project.js +92 -0
- package/dist/commands/onboard/resolve-project.js.map +1 -0
- package/dist/commands/onboard/safe-repo-fs.d.ts +59 -0
- package/dist/commands/onboard/safe-repo-fs.d.ts.map +1 -0
- package/dist/commands/onboard/safe-repo-fs.js +266 -0
- package/dist/commands/onboard/safe-repo-fs.js.map +1 -0
- package/dist/commands/onboard/setup-agent-integrations.d.ts +43 -0
- package/dist/commands/onboard/setup-agent-integrations.d.ts.map +1 -0
- package/dist/commands/onboard/setup-agent-integrations.js +324 -0
- package/dist/commands/onboard/setup-agent-integrations.js.map +1 -0
- package/dist/commands/onboard/templates/CLAUDE.md +213 -0
- package/dist/commands/onboard/templates/agents/auth-setup.md +117 -0
- package/dist/commands/onboard/templates/agents/ci-setup.md +742 -0
- package/dist/commands/onboard/templates/agents/csp-setup.md +78 -0
- package/dist/commands/onboard/templates/agents/false-positive-prevention.md +268 -0
- package/dist/commands/onboard/templates/agents/feature-flag-setup.md +133 -0
- package/dist/commands/onboard/templates/agents/local-simulation-verification.md +96 -0
- package/dist/commands/onboard/templates/agents/persisted-graphql-queries.md +150 -0
- package/dist/commands/onboard/templates/agents/recorder-installation.md +194 -0
- package/dist/commands/onboard/templates/agents/replay-fetch-retry-compatibility.md +252 -0
- package/dist/commands/onboard/templates/agents/reviewer.md +788 -0
- package/dist/commands/onboard/templates/agents/service-worker-compatibility.md +254 -0
- package/dist/commands/onboard/templates/agents/session-context.md +133 -0
- package/dist/commands/onboard/templates/agents/shared-worker-compatibility.md +187 -0
- package/dist/commands/onboard/templates/docs/additional-guides/backend-recorder.ts +340 -0
- package/dist/commands/onboard/templates/docs/ci/not-yet-run-checks.ts +58 -0
- package/dist/commands/onboard/templates/docs/ci.ts +19 -0
- package/dist/commands/onboard/templates/docs/cloud-replay.ts +145 -0
- package/dist/commands/onboard/templates/docs/constants.ts +37 -0
- package/dist/commands/onboard/templates/docs/github-actions-v2.ts +859 -0
- package/dist/commands/onboard/templates/docs/how-to/auth/bypassing-auth.ts +27 -0
- package/dist/commands/onboard/templates/docs/how-to/auth/enabling-full-auth.ts +91 -0
- package/dist/commands/onboard/templates/docs/how-to/configure-ignore-patterns.ts +77 -0
- package/dist/commands/onboard/templates/docs/how-to/enable-source-coverage.ts +84 -0
- package/dist/commands/onboard/templates/docs/how-to/fix-false-positive-diffs.ts +156 -0
- package/dist/commands/onboard/templates/docs/how-to/link-bitbucket.ts +15 -0
- package/dist/commands/onboard/templates/docs/how-to/link-gitlab.ts +22 -0
- package/dist/commands/onboard/templates/docs/how-to/record-session-context.ts +129 -0
- package/dist/commands/onboard/templates/docs/how-to/recorder-script.ts +139 -0
- package/dist/commands/onboard/templates/docs/how-to/testing-feature-flags.ts +97 -0
- package/dist/commands/onboard/templates/docs/how-to/testing-multiple-apps-or-app-variants.ts +40 -0
- package/dist/commands/onboard/templates/docs/how-to/troubleshoot-auth.ts +58 -0
- package/dist/commands/onboard/templates/docs/how-to/troubleshoot-failed-simulations.ts +97 -0
- package/dist/commands/onboard/templates/docs/how-to/typescript-types.ts +51 -0
- package/dist/commands/onboard/templates/docs/how-to/window-meticulous-object.ts +685 -0
- package/dist/commands/onboard/templates/docs/onboarding-guide.ts +415 -0
- package/dist/commands/onboard/templates/docs/recorder-getting-started.ts +24 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/constants.ts +1 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/explanation-of-methods-to-add-recorder.ts +21 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/npm-package-based-instructions/angular-instructions.ts +34 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/npm-package-based-instructions/any-other-framework-instructions.ts +118 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/npm-package-based-instructions/vue-instructions.ts +39 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-based-instructions/next-js-instructions.ts +49 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-based-instructions/nuxtjs-instructions.ts +68 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-based-instructions/rsbuild-instructions.ts +66 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-based-instructions/storybook-instructions.ts +59 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-based-instructions/sveltekit-instructions.ts +113 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-based-instructions/vite-instructions.ts +58 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/script-requirements.ts +51 -0
- package/dist/commands/onboard/templates/docs/recorder-snippets/steps-after-installing-recorder.ts +25 -0
- package/dist/commands/onboard/templates/docs/reference/cli-commands.ts +1324 -0
- package/dist/commands/onboard/templates/docs/session-recording/csp-exceptions.ts +17 -0
- package/dist/commands/onboard/templates/docs/session-recording/recorder-npm-dependency.ts +62 -0
- package/dist/commands/onboard/templates/docs-imports/src/lib/next/next.constants.ts +46 -0
- package/dist/commands/onboard/templates/docs-imports/src/lib/utils/internal-urls/docs-urls.utils.ts +254 -0
- package/dist/commands/onboard/templates/settings.json +14 -0
- package/dist/commands/project/index.js +2 -2
- package/dist/commands/project/index.js.map +1 -1
- package/dist/commands/project/show.command.js +2 -2
- package/dist/commands/project/show.command.js.map +1 -1
- package/dist/commands/project/upload-source.command.js +2 -2
- package/dist/commands/project/upload-source.command.js.map +1 -1
- package/dist/commands/record/__tests__/backend-dev-command.utils.spec.js +2 -2
- package/dist/commands/record/__tests__/backend-dev-command.utils.spec.js.map +1 -1
- package/dist/commands/record/__tests__/backend-sidecar.utils.spec.js +2 -2
- package/dist/commands/record/__tests__/backend-sidecar.utils.spec.js.map +1 -1
- package/dist/commands/record/__tests__/backend.command.spec.js +2 -2
- package/dist/commands/record/__tests__/backend.command.spec.js.map +1 -1
- package/dist/commands/record/__tests__/login.command.spec.js +2 -2
- package/dist/commands/record/__tests__/login.command.spec.js.map +1 -1
- package/dist/commands/record/__tests__/session.command.spec.js +2 -2
- package/dist/commands/record/__tests__/session.command.spec.js.map +1 -1
- package/dist/commands/record/backend-dev-command.utils.js +2 -2
- package/dist/commands/record/backend-dev-command.utils.js.map +1 -1
- package/dist/commands/record/backend-sidecar.utils.js +2 -2
- package/dist/commands/record/backend-sidecar.utils.js.map +1 -1
- package/dist/commands/record/backend.command.js +2 -2
- package/dist/commands/record/backend.command.js.map +1 -1
- package/dist/commands/record/index.js +2 -2
- package/dist/commands/record/index.js.map +1 -1
- package/dist/commands/record/login.command.js +2 -2
- package/dist/commands/record/login.command.js.map +1 -1
- package/dist/commands/record/session.command.js +2 -2
- package/dist/commands/record/session.command.js.map +1 -1
- package/dist/commands/replay-debugger.ui.js +2 -2
- package/dist/commands/replay-debugger.ui.js.map +1 -1
- package/dist/commands/replay.command.js +2 -2
- package/dist/commands/replay.command.js.map +1 -1
- package/dist/commands/schema.command.js +2 -2
- package/dist/commands/schema.command.js.map +1 -1
- package/dist/commands/schema.command.spec.js +2 -2
- package/dist/commands/schema.command.spec.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/dist/utils/__tests__/handle-auth-failure.spec.js +2 -2
- package/dist/utils/__tests__/handle-auth-failure.spec.js.map +1 -1
- package/dist/utils/__tests__/project-selection-hint.spec.js +2 -2
- package/dist/utils/__tests__/project-selection-hint.spec.js.map +1 -1
- package/dist/utils/__tests__/resolve-project-identifier.spec.js +2 -2
- package/dist/utils/__tests__/resolve-project-identifier.spec.js.map +1 -1
- package/dist/utils/__tests__/resolve-test-run-from-commit.spec.js +2 -2
- package/dist/utils/__tests__/resolve-test-run-from-commit.spec.js.map +1 -1
- package/dist/utils/__tests__/select-project.spec.js +5 -4
- package/dist/utils/__tests__/select-project.spec.js.map +1 -1
- package/dist/utils/cli-user-error.js +2 -2
- package/dist/utils/cli-user-error.js.map +1 -1
- package/dist/utils/constants.js +2 -2
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/environment.utils.js +2 -2
- package/dist/utils/environment.utils.js.map +1 -1
- package/dist/utils/format-coverage-ranges.js +2 -2
- package/dist/utils/format-coverage-ranges.js.map +1 -1
- package/dist/utils/handle-auth-failure.js +2 -2
- package/dist/utils/handle-auth-failure.js.map +1 -1
- package/dist/utils/out-of-date-client-error.js +2 -2
- package/dist/utils/out-of-date-client-error.js.map +1 -1
- package/dist/utils/project-selection-hint.js +2 -2
- package/dist/utils/project-selection-hint.js.map +1 -1
- package/dist/utils/resolve-project-identifier.js +2 -2
- package/dist/utils/resolve-project-identifier.js.map +1 -1
- package/dist/utils/resolve-test-run-from-commit.js +2 -2
- package/dist/utils/resolve-test-run-from-commit.js.map +1 -1
- package/dist/utils/select-project.d.ts +9 -0
- package/dist/utils/select-project.d.ts.map +1 -1
- package/dist/utils/select-project.js +58 -15
- package/dist/utils/select-project.js.map +1 -1
- package/package.json +13 -11
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { METICULOUS_SUPPORT_EMAIL } from "src/lib/next/next.constants";
|
|
2
|
+
import { METICULOUS_WINDOW_OBJECT_URL } from "src/lib/utils/internal-urls/docs-urls.utils";
|
|
3
|
+
|
|
4
|
+
export const document = `---
|
|
5
|
+
{
|
|
6
|
+
"title": "Bypassing Auth"
|
|
7
|
+
}
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# {% $frontmatter.title %}
|
|
11
|
+
|
|
12
|
+
If you are only using Meticulous to test your frontend, then Meticulous won't actually need to authenticate with your backend: it'll automatically
|
|
13
|
+
stub all network responses. However, it may get tripped up if it gets redirected to a login page when trying to simulate a session.
|
|
14
|
+
|
|
15
|
+
You can solve this by disabling the code that performs the redirect or auth check when running Meticulous tests in CI or against your preview URLs.
|
|
16
|
+
|
|
17
|
+
This can be done securely by setting a secret in the 'Custom Request Headers' tab of your project's settings screen, or, if the check or redirect
|
|
18
|
+
being disabled does not have security implications (and only UX implications), or is for localhost inside CI, then you can disable it in code by checking [the window variables or
|
|
19
|
+
request headers that Meticulous sets](${METICULOUS_WINDOW_OBJECT_URL}).
|
|
20
|
+
|
|
21
|
+
## Issues / questions?
|
|
22
|
+
|
|
23
|
+
We're always happy to help you with any issues you encounter while setting up or with anything else you might be unsure about.
|
|
24
|
+
|
|
25
|
+
Get in touch by emailing [${METICULOUS_SUPPORT_EMAIL}](mailto:${METICULOUS_SUPPORT_EMAIL}).
|
|
26
|
+
|
|
27
|
+
`;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { METICULOUS_SUPPORT_EMAIL } from "src/lib/next/next.constants";
|
|
2
|
+
import { TROUBLESHOOT_AUTH_URL } from "src/lib/utils/internal-urls/docs-urls.utils";
|
|
3
|
+
|
|
4
|
+
export const document = `---
|
|
5
|
+
{
|
|
6
|
+
"title": "Enabling Meticulous to replay sessions fully authenticated"
|
|
7
|
+
}
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# {% $frontmatter.title %}
|
|
11
|
+
|
|
12
|
+
Auth issues are some of the most common issues that you might encounter while setting up Meticulous.
|
|
13
|
+
This class of issues is easily identifiable by sessions recorded on logged-in pages which, when simulated, consistently redirect to
|
|
14
|
+
log-in pages or 401 screens.
|
|
15
|
+
|
|
16
|
+
Note that you may not need to enable full authentication if you are only using Meticulous to test your frontend (read more [here](${TROUBLESHOOT_AUTH_URL})). If you
|
|
17
|
+
do wish to enable full authentication, then select the auth provider that you're using from the options below:
|
|
18
|
+
|
|
19
|
+
{% tabs %}
|
|
20
|
+
{% tab label="Auth0" %}
|
|
21
|
+
|
|
22
|
+
## Auth0
|
|
23
|
+
|
|
24
|
+
[Auth0](https://auth0.com/) is a popular auth provider that is used by many web apps. There are many different integration methods with
|
|
25
|
+
Auth0, but, at a high level, there are two main patterns:
|
|
26
|
+
|
|
27
|
+
### Is the user session managed in the browser?
|
|
28
|
+
|
|
29
|
+
This integration pattern is most common in single page applications (SPAs). In these methods, the user session is managed in
|
|
30
|
+
the browser, and the browser is responsible for sending the session data to the backend with every request. Common SDKs used for this
|
|
31
|
+
pattern are [auth0-spa-js](https://github.com/auth0/auth0-spa-js) and [auth0-react](https://github.com/auth0/auth0-react).
|
|
32
|
+
|
|
33
|
+
By default, Auth0 stores user session data in JavaScript memory, which Meticulous cannot access while recording sessions. When Meticulous
|
|
34
|
+
tries to simulate these sessions, Auth0 will fail to refresh the session data and then will force a redirect to the login screen.
|
|
35
|
+
|
|
36
|
+
To fix this, you need to configure Auth0 to store user session data in \`localstorage\`. See Auth0's documentation [here](https://auth0.com/docs/libraries/auth0-single-page-app-sdk#change-storage-options)
|
|
37
|
+
for more information on how to set this configuration.
|
|
38
|
+
|
|
39
|
+
### Is the user session managed in the backend?
|
|
40
|
+
|
|
41
|
+
This integration pattern is most common in traditional web applications and in web applications that make heavy use of server-side rendering.
|
|
42
|
+
In these methods, the user session is managed in the backend, and the backend exposes this session to the frontend via cookies or headers.
|
|
43
|
+
Common SDKs used for this pattern are [auth0-node](https://github.com/auth0/node-auth0) and [nextjs-auth0](https://github.com/auth0/nextjs-auth0).
|
|
44
|
+
|
|
45
|
+
By default, Auth0 stores user session data in httpOnly cookies, which Meticulous cannot access while recording sessions. When Meticulous
|
|
46
|
+
tries to replay these sessions, Meticulous will not pass a session cookie when attempting to load the initial page, so Auth0 will force
|
|
47
|
+
a redirect to the login screen.
|
|
48
|
+
|
|
49
|
+
To fix this, you need to configure Auth0 to not use httpOnly cookies in the environments where Meticulous records sessions. This can be
|
|
50
|
+
accomplished by setting the \`AUTH0_COOKIE_HTTP_ONLY\` environment variable to false in the desired environments. See Auth0's documentation
|
|
51
|
+
[here](https://auth0.github.io/nextjs-auth0/types/config.ConfigParameters.html) for more information on how to set this configuration.
|
|
52
|
+
|
|
53
|
+
### Is the same Auth0 client being used across the record and replay environments?
|
|
54
|
+
|
|
55
|
+
If you have made the suggested changes from the previous sections and are still seeing auth issues, then it is possible that the Auth0
|
|
56
|
+
client is different between the record and simulation environments. Because live requests are being sent to Auth0 at simulation time
|
|
57
|
+
with session data collected at record time, the same Auth0 client must be used across record and simulation environments.
|
|
58
|
+
|
|
59
|
+
Please standardize your Auth0 client across environments, and try recording and simulating a session again.
|
|
60
|
+
|
|
61
|
+
{% /tab %}
|
|
62
|
+
|
|
63
|
+
{% tab label="Other" %}
|
|
64
|
+
|
|
65
|
+
## Other
|
|
66
|
+
|
|
67
|
+
### Is the same auth provider client being used across the record and replay environments?
|
|
68
|
+
|
|
69
|
+
Because live requests are often sent to auth providers at simulation time with session data collected at record time, the same auth provider
|
|
70
|
+
client must be used across record and simulation environments.
|
|
71
|
+
|
|
72
|
+
Please standardize your auth provider client across environments, and try recording and simulating a session again.
|
|
73
|
+
|
|
74
|
+
### Does your backend expose user session data to the browser exclusively via httpOnly cookies?
|
|
75
|
+
|
|
76
|
+
If your backend exclusively uses httpOnly cookies to expose user session data to the browser, then Meticulous will not be able to access
|
|
77
|
+
this data at record time. This will prevent Meticulous from passing a valid session cookie when loading the initial page at simulation time.
|
|
78
|
+
|
|
79
|
+
To fix this, please disable httpOnly cookies in the environments where Meticulous records sessions.
|
|
80
|
+
|
|
81
|
+
{% /tab %}
|
|
82
|
+
|
|
83
|
+
{% /tabs %}
|
|
84
|
+
|
|
85
|
+
## Issues / questions?
|
|
86
|
+
|
|
87
|
+
We're always happy to help you with any issues you encounter while setting up or with anything else you might be unsure about.
|
|
88
|
+
|
|
89
|
+
Get in touch by emailing [${METICULOUS_SUPPORT_EMAIL}](mailto:${METICULOUS_SUPPORT_EMAIL}).
|
|
90
|
+
|
|
91
|
+
`;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { WHERE_CAN_I_REACH_OUT_FOR_SUPPORT } from "../constants";
|
|
2
|
+
import { ENABLE_SOURCE_COVERAGE_URL } from "src/lib/utils/internal-urls/docs-urls.utils";
|
|
3
|
+
|
|
4
|
+
export const document = `---
|
|
5
|
+
{
|
|
6
|
+
"title": "Configuring Ignore Patterns for Coverage"
|
|
7
|
+
}
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# {% $frontmatter.title %}
|
|
11
|
+
|
|
12
|
+
Meticulous uses a \`.meticulousignore\` file at the root of your repository to exclude files from [source coverage](${ENABLE_SOURCE_COVERAGE_URL}) tracking. The file follows the same syntax as [.gitignore](https://git-scm.com/docs/gitignore).
|
|
13
|
+
|
|
14
|
+
## Global ignore patterns
|
|
15
|
+
|
|
16
|
+
Create a \`.meticulousignore\` file at the root of your repository. Any file whose path matches a pattern in this file is excluded from coverage across all Meticulous projects that point to the repository.
|
|
17
|
+
|
|
18
|
+
\`\`\`
|
|
19
|
+
# .meticulousignore
|
|
20
|
+
|
|
21
|
+
# Exclude generated files
|
|
22
|
+
src/generated/**
|
|
23
|
+
|
|
24
|
+
# Exclude Storybook
|
|
25
|
+
apps/storybook/**
|
|
26
|
+
|
|
27
|
+
# Exclude mobile-specific files
|
|
28
|
+
**/*.ios.*
|
|
29
|
+
**/*.android.*
|
|
30
|
+
\`\`\`
|
|
31
|
+
|
|
32
|
+
## Project-specific ignore patterns (monorepos)
|
|
33
|
+
|
|
34
|
+
If your repository contains multiple Meticulous projects — for example, separate \`dashboard\` and \`admin\` apps in a monorepo — you can create per-project ignore files so that each project only tracks coverage for its own source files.
|
|
35
|
+
|
|
36
|
+
Create a \`.meticulousignore.{slug}\` file at the root of your repository, where \`{slug}\` is derived from your Meticulous project name (see [How the slug is computed](#how-the-slug-is-computed) below).
|
|
37
|
+
|
|
38
|
+
For example, a monorepo with a \`dashboard\` project and an \`admin\` project might have:
|
|
39
|
+
|
|
40
|
+
\`\`\`
|
|
41
|
+
# .meticulousignore.dashboard
|
|
42
|
+
# Applied only when running coverage for the "dashboard" project
|
|
43
|
+
|
|
44
|
+
apps/admin/**
|
|
45
|
+
\`\`\`
|
|
46
|
+
|
|
47
|
+
\`\`\`
|
|
48
|
+
# .meticulousignore.admin
|
|
49
|
+
# Applied only when running coverage for the "admin" project
|
|
50
|
+
|
|
51
|
+
apps/dashboard/**
|
|
52
|
+
\`\`\`
|
|
53
|
+
|
|
54
|
+
Patterns from \`.meticulousignore\` (global) and \`.meticulousignore.{slug}\` (project-specific) are merged together, so both apply at the same time.
|
|
55
|
+
|
|
56
|
+
## How the slug is computed
|
|
57
|
+
|
|
58
|
+
The slug is derived from your Meticulous project name using these steps:
|
|
59
|
+
|
|
60
|
+
1. Convert to lowercase
|
|
61
|
+
2. Replace any character that is not alphanumeric, a hyphen (\`-\`), or an underscore (\`_\`) with a hyphen
|
|
62
|
+
3. Collapse consecutive hyphens into a single hyphen
|
|
63
|
+
4. Strip any leading or trailing hyphens
|
|
64
|
+
|
|
65
|
+
| Project name | Ignore file |
|
|
66
|
+
|---|---|
|
|
67
|
+
| \`dashboard\` | \`.meticulousignore.dashboard\` |
|
|
68
|
+
| \`my-next-cloudflare-app\` | \`.meticulousignore.my-next-cloudflare-app\` |
|
|
69
|
+
| \`meticulous_app\` | \`.meticulousignore.meticulous_app\` |
|
|
70
|
+
| \`My Dashboard App\` | \`.meticulousignore.my-dashboard-app\` |
|
|
71
|
+
| \`apps/admin\` | \`.meticulousignore.apps-admin\` |
|
|
72
|
+
| \`My App (v2)\` | \`.meticulousignore.my-app-v2\` |
|
|
73
|
+
|
|
74
|
+
Your project name is shown in the Meticulous UI in the top-left of your project's page, and in the URL: \`app.meticulous.ai/projects/{org}/{project-name}\`.
|
|
75
|
+
|
|
76
|
+
${WHERE_CAN_I_REACH_OUT_FOR_SUPPORT}
|
|
77
|
+
`;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { WHERE_CAN_I_REACH_OUT_FOR_SUPPORT } from "../constants";
|
|
2
|
+
|
|
3
|
+
export const document = `---
|
|
4
|
+
{
|
|
5
|
+
"title": "Viewing source coverage information in Meticulous"
|
|
6
|
+
}
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# {% $frontmatter.title %}
|
|
10
|
+
|
|
11
|
+
Meticulous can be set up to show you what parts of your code are being tested by us. In order to use this feature you must be serving [source maps](https://web.dev/articles/source-maps) for your code in at least some of the environments you're testing against (for instance, if building source maps significantly slows down your build you could do this only on pushes
|
|
12
|
+
to your main branch to avoid delaying PR runs).
|
|
13
|
+
|
|
14
|
+
## How can I view my source coverage?
|
|
15
|
+
|
|
16
|
+
To view your coverage information, visit your project's landing page on Meticulous (that is, the \`Overview\` tab). From there click the
|
|
17
|
+
\`View coverage & snapshots\` button, and select the \`Sources\` tab. You'll see a list of all the files in your project, and for each file
|
|
18
|
+
you'll see a percentage of the lines in that file that are covered by your tests. You can click on a file to see the exact lines that are
|
|
19
|
+
covered and not covered.
|
|
20
|
+
|
|
21
|
+
## How can I serve source maps so Meticulous finds them?
|
|
22
|
+
|
|
23
|
+
Meticulous will autodetect your source maps in three different ways (you only need to do one of these):
|
|
24
|
+
|
|
25
|
+
1. You serve the source map in the same directory as the file it corresponds to, with the same name as the file, but with a \`.map\`
|
|
26
|
+
extension added at the end. For instance, if you have a file \`https://mysite.com/static/assets/index.js\` then you should serve the
|
|
27
|
+
source map at \`https://mysite.com/static/assets/index.js.map\`.
|
|
28
|
+
2. You have a \`sourceMappingURL\` comment at the end of your file that points to the source map as documented
|
|
29
|
+
[here](https://firefox-source-docs.mozilla.org/devtools-user/debugger/how_to/use_a_source_map/index.html).
|
|
30
|
+
3. You set the \`SourceMap\` HTTP header on the response that serves the file to point to the source map as documented
|
|
31
|
+
[here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/SourceMap).
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Monorepos
|
|
35
|
+
|
|
36
|
+
If you're using a monorepo, you'll need to build source maps for each package in your monorepo that your app depends on.
|
|
37
|
+
|
|
38
|
+
For example, if your app is within \`apps/frontend\` and you have a package \`packages/utils\` that the app depends on,
|
|
39
|
+
you'll need to build source maps for both of these packages. You might need to adjust your build process to load source maps
|
|
40
|
+
for your dependencies, e.g. by using \`source-map-loader\` in your webpack config.
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Example Next.js setup
|
|
44
|
+
|
|
45
|
+
1. Enable source maps generation in your dependent packages.
|
|
46
|
+
\`packages/utils/tsconfig.json\`:
|
|
47
|
+
\`\`\`json
|
|
48
|
+
{
|
|
49
|
+
...
|
|
50
|
+
"sourceMap": true,
|
|
51
|
+
"declarationMap": true
|
|
52
|
+
}
|
|
53
|
+
\`\`\`
|
|
54
|
+
2. Install \`source-map-loader\` in your Next.js project:
|
|
55
|
+
\`\`\`bash
|
|
56
|
+
npm install --save-dev source-map-loader <OR>
|
|
57
|
+
yarn add --dev source-map-loader <OR>
|
|
58
|
+
pnpm add --save-dev source-map-loader
|
|
59
|
+
\`\`\`
|
|
60
|
+
3. Add the following to your Next.js project's \`next.config.js\` in order to load source maps from your monorepo packages:
|
|
61
|
+
\`\`\`javascript
|
|
62
|
+
module.exports = {
|
|
63
|
+
...
|
|
64
|
+
webpack: (config, { isServer }) => {
|
|
65
|
+
// Ensure TypeScript source maps from monorepo packages work correctly
|
|
66
|
+
config.module.rules.push({
|
|
67
|
+
test: /\\.js$/,
|
|
68
|
+
use: ['source-map-loader'],
|
|
69
|
+
enforce: 'pre',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Silence source map parsing warnings.
|
|
73
|
+
config.ignoreWarnings = [
|
|
74
|
+
...(config.ignoreWarnings || []),
|
|
75
|
+
/Failed to parse source map/,
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
return config;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
\`\`\`
|
|
82
|
+
|
|
83
|
+
${WHERE_CAN_I_REACH_OUT_FOR_SUPPORT}
|
|
84
|
+
`;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { METICULOUS_SUPPORT_EMAIL } from "src/lib/next/next.constants";
|
|
2
|
+
import { METICULOUS_WINDOW_OBJECT_URL } from "src/lib/utils/internal-urls/docs-urls.utils";
|
|
3
|
+
import { WHERE_CAN_I_REACH_OUT_FOR_SUPPORT } from "../constants";
|
|
4
|
+
|
|
5
|
+
const SERVER_SIDE_RENDERING_ANCHOR = "server-side-rendering";
|
|
6
|
+
const ENV_DIFFERENCES_ANCHOR = "env-differences";
|
|
7
|
+
const PAUSING_METICULOUS_REPLAYS_ANCHOR = "pausing-meticulous-replays";
|
|
8
|
+
const OTHER_CAUSES_ANCHOR = "other-causes";
|
|
9
|
+
const GENERAL_TECHNIQUES_ANCHOR = "general-techniques";
|
|
10
|
+
|
|
11
|
+
export const document = `---
|
|
12
|
+
{
|
|
13
|
+
"title": "Fix False Positive Diffs"
|
|
14
|
+
}
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# {% $frontmatter.title %}
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
Ideally every difference you see in the Meticulous UI for a given PR should be directly caused by a code change introduced by that PR. Differences that
|
|
22
|
+
show up that are unrelated to your code change could be due to:
|
|
23
|
+
|
|
24
|
+
- [Changes in content derived from database data, or the current date/time, when using server side rendering](#${SERVER_SIDE_RENDERING_ANCHOR}) (when using client side rendering Meticulous handles this automatically)
|
|
25
|
+
- Or, [differences in how you build the code for the two different environments you're comparing between (e.g. PR build vs main branch build)](#${ENV_DIFFERENCES_ANCHOR})
|
|
26
|
+
- Or, [executing asynchronous tasks that Meticulous doesn't natively handle](#${PAUSING_METICULOUS_REPLAYS_ANCHOR})
|
|
27
|
+
- Or, [other causes](#${OTHER_CAUSES_ANCHOR})
|
|
28
|
+
|
|
29
|
+
In all of these cases, if you can't solve the underlying cause, then you can just mark the diff to be ignored:
|
|
30
|
+
|
|
31
|
+
{% anchor id="${GENERAL_TECHNIQUES_ANCHOR}" /%}
|
|
32
|
+
### Configuring certain diffs to be ignored
|
|
33
|
+
|
|
34
|
+
You can configure diffs inside certain elements to be ignored by adding a CSS selector to the
|
|
35
|
+
_'Elements to ignore when comparing screenshots'_ list in the _'Screenshotting behavior'_ section in project settings, or by adding the
|
|
36
|
+
\`meticulous-ignore\` class to an element.
|
|
37
|
+
|
|
38
|
+
Please note that if you open a pull request to add a \`meticulous-ignore\` class to an element then the ignore rule will only apply to Meticulous
|
|
39
|
+
test runs for new PRs opened since the original PR adding the \`meticulous-ignore\` class was merged.
|
|
40
|
+
|
|
41
|
+
Alternatively, you can detect if the app is being rendered as part of a Meticulous test, and disable part of the UI or code that is causing
|
|
42
|
+
false positive diffs when being rendered in a test. For frontend components you can use the [Meticulous object on the window](${METICULOUS_WINDOW_OBJECT_URL}),
|
|
43
|
+
and for server side components or server side rendering you can use the [\`meticulous-is-test\` header](#${SERVER_SIDE_RENDERING_ANCHOR}).
|
|
44
|
+
|
|
45
|
+
{% anchor id="${SERVER_SIDE_RENDERING_ANCHOR}" /%}
|
|
46
|
+
## Diffs due to changes in data or the current date when using server side rendering, or rendering NextJS server components
|
|
47
|
+
|
|
48
|
+
By default Meticulous stubs out responses for any fetch or XHR requests from the browser and stubs out the Date functions in the browser.
|
|
49
|
+
This means that even if the data in your database changes or the time changes you won't see any false positive diffs.
|
|
50
|
+
|
|
51
|
+
However if you're using NextJS server components then Meticulous will re-render those server components on the backend every time it replays
|
|
52
|
+
a session -- this means that if the data in your database changes or the date changes in the short window of time between when Meticulous
|
|
53
|
+
replays the session on the base commit and when Meticulous replays the session on the head commit, and you render that data or the date to
|
|
54
|
+
the page inside a server component, then you could see false positive diffs.
|
|
55
|
+
|
|
56
|
+
Meticulous sends a \`meticulous-is-test\` header in every request it makes to your NextJS server. You can use this header to disable parts of
|
|
57
|
+
your server components which cause flakes in Meticulous tests. It'll always be present (with value '1') if the request is being made as part
|
|
58
|
+
of a Meticulous test.
|
|
59
|
+
|
|
60
|
+
If you render text based on the current time (for example "Posted 7 minutes ago"), you can configure Meticulous to send a simulated date
|
|
61
|
+
header with the virtual time by adding a custom header in your project settings (Settings > Custom Request Headers). Use the
|
|
62
|
+
**Simulated Date** template to set the header value - this will be resolved per-request to the virtual time in RFC 7231 format.
|
|
63
|
+
|
|
64
|
+
For example, you could add a custom header named \`meticulous-simulated-date\` using the Simulated Date template, then use it like so:
|
|
65
|
+
|
|
66
|
+
\`\`\`javascript
|
|
67
|
+
import { headers } from 'next/headers'
|
|
68
|
+
|
|
69
|
+
const getCurrentDate = async () => {
|
|
70
|
+
const requestHeaders = await headers()
|
|
71
|
+
|
|
72
|
+
// If a simulated date header is configured in Meticulous project settings, use it instead of the current date
|
|
73
|
+
const simulatedDate = requestHeaders.get('meticulous-simulated-date')
|
|
74
|
+
return simulatedDate ? new Date(Date.parse(simulatedDate)) : new Date()
|
|
75
|
+
}
|
|
76
|
+
\`\`\`
|
|
77
|
+
|
|
78
|
+
This avoids false positive diffs due to the time changing (e.g. "Posted 7 minutes ago" vs "Posted 8 minutes ago"): Meticulous will send
|
|
79
|
+
the same timestamp every time for the same request. The timestamp is a UTC date in RFC 7231 format.
|
|
80
|
+
|
|
81
|
+
You can also [configure Meticulous to ignore the diffs using CSS selectors](#${GENERAL_TECHNIQUES_ANCHOR}).
|
|
82
|
+
|
|
83
|
+
{% anchor id="${ENV_DIFFERENCES_ANCHOR}" /%}
|
|
84
|
+
## Diffs due to differences between environments
|
|
85
|
+
|
|
86
|
+
### Using Vercel
|
|
87
|
+
|
|
88
|
+
If you use Vercel then Meticulous will try to automatically generate previews using the same environmental configuration for both commits to the main branch,
|
|
89
|
+
and to PR branches. So you shouldn't see any false positive diffs due to differences between environments. If you do, then reach out to
|
|
90
|
+
the [Meticulous support team](mailto:${METICULOUS_SUPPORT_EMAIL}).
|
|
91
|
+
|
|
92
|
+
### Using Netlify, or other preview providers
|
|
93
|
+
|
|
94
|
+
If you use another preview URL provider, such as Netlify, then Meticulous will compare visual snapshots from the preview URL of the base commit on the main branch to snapshots from the preview URL of the head commit of the pull request branch.
|
|
95
|
+
|
|
96
|
+
In this case the environment variables and configuration you use to run & build your app needs to be the same for the deployments of the main branch (production deploys) and the deployments of pull request branches (preview deploys). If this isn't the case Meticulous could display false screenshot differences.
|
|
97
|
+
|
|
98
|
+
For example if you configure production deploys of your app (from the main branch) to have a blue banner, and preview deploys of your app (from pull request branches)
|
|
99
|
+
to have a red banner, then Meticulous would display screenshot diffs of the banner changing from blue to red for every screen. You want to make
|
|
100
|
+
sure that the only screenshot diffs Meticulous shows are due to changes in the code introduced by the pull request being tested, rather than
|
|
101
|
+
environmental differences between the environments tested on.
|
|
102
|
+
|
|
103
|
+
To fix this check the environment variables and configuration you use to run & build your app are the same for the deployments of the
|
|
104
|
+
main branch (production deploys) and the deployments of pull request branches (preview deploys).
|
|
105
|
+
|
|
106
|
+
If it's not possible to unify the configuration across the environments then you can [configure Meticulous to ignore the diffs](#${GENERAL_TECHNIQUES_ANCHOR}).
|
|
107
|
+
|
|
108
|
+
### Using GitHub Actions
|
|
109
|
+
|
|
110
|
+
If, instead of preview URLs, you're using the \`report-diffs-action\` GitHub action, then Meticulous will compare snapshots from running your app from the base
|
|
111
|
+
commit of the main branch to snapshots from running your app from the head commit of the pull request branch. In this case it's similarly important to make sure
|
|
112
|
+
that you compile and run your app with the same configuration for both the main branch and the pull request branches.
|
|
113
|
+
|
|
114
|
+
{% anchor id="${PAUSING_METICULOUS_REPLAYS_ANCHOR}" /%}
|
|
115
|
+
## Diffs due to asynchronous tasks not handled natively by Meticulous
|
|
116
|
+
|
|
117
|
+
Meticulous will automatically wait for most browser tasks to complete before continuing with javascript execution. This ensures the
|
|
118
|
+
resultant screenshots are deterministic. However, if your application waits for asynchronous events that are *not* handled natively by Meticulous
|
|
119
|
+
you can use the [Meticulous object on the window](${METICULOUS_WINDOW_OBJECT_URL}) to pause the execution of the replay while the
|
|
120
|
+
asynchronous task is in-progress.
|
|
121
|
+
|
|
122
|
+
For example, let's say you send a message to a custom Chrome extension and then wait for a response.
|
|
123
|
+
In this case you can tell Meticulous to pause the replay until you have received the expected response:
|
|
124
|
+
|
|
125
|
+
\`\`\`javascript
|
|
126
|
+
function sendMessageToExtension() {
|
|
127
|
+
if (window.Meticulous?.isRunningAsTest) {
|
|
128
|
+
// Meticulous will pause test execution for up to 30 seconds. If we don't
|
|
129
|
+
// call pause() here Meticulous will sometimes take a screenshot before the
|
|
130
|
+
// Chrome extension has responded, and sometimes after, causing flaky tests.
|
|
131
|
+
window.Meticulous.replay.pause();
|
|
132
|
+
}
|
|
133
|
+
chrome.runtime.sendMessage(MY_EXTENSION_ID, "My message", (response) => {
|
|
134
|
+
if (window.Meticulous?.isRunningAsTest) {
|
|
135
|
+
// Important: we continue the replay even if the request fails
|
|
136
|
+
window.Meticulous.replay.resume();
|
|
137
|
+
}
|
|
138
|
+
if (response.success) {
|
|
139
|
+
doSomething(response.data);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
\`\`\`
|
|
144
|
+
|
|
145
|
+
{% anchor id="${OTHER_CAUSES_ANCHOR}" /%}
|
|
146
|
+
## False positive diffs due to other reasons
|
|
147
|
+
|
|
148
|
+
Meticulous ensures the session simulation executes identically every time, even if there are animations, timers, random number generators,
|
|
149
|
+
changing data, or changing dates and times. So under normal operation false positive diffs or flakes should not happen.
|
|
150
|
+
|
|
151
|
+
However, if you are making extensive use of web workers, WebGL or WASM, it is possible that in some cases you could see false
|
|
152
|
+
positive diffs. If you do notice a false positive diff please reach out to the [Meticulous support team](mailto:${METICULOUS_SUPPORT_EMAIL}) and
|
|
153
|
+
we'll take a look into it. You can also [configure Meticulous to ignore the diffs](#${GENERAL_TECHNIQUES_ANCHOR}).
|
|
154
|
+
|
|
155
|
+
${WHERE_CAN_I_REACH_OUT_FOR_SUPPORT}
|
|
156
|
+
`;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const linkBitbucketInstructions = `
|
|
2
|
+
1. Create a **repository access token** in Bitbucket:
|
|
3
|
+
- Open your repository in Bitbucket Cloud → **Repository settings** → **Access tokens** → **Create repository access token**
|
|
4
|
+
([guide](https://support.atlassian.com/bitbucket-cloud/docs/create-a-repository-access-token/))
|
|
5
|
+
- Grant **Repositories: Read** and **Pull requests: Read**
|
|
6
|
+
2. In Meticulous, link the repository and paste the token:
|
|
7
|
+
- When creating a Bitbucket project, or from **Project settings → CI settings → Linked repository**
|
|
8
|
+
- Enter your Bitbucket **workspace**, **repository slug**, and paste the access token (it is stored securely and never shown again)
|
|
9
|
+
3. Add the Meticulous webhook in Bitbucket (**Repository settings → Webhooks → Add webhook**):
|
|
10
|
+
- Use the **Webhook URL** and **Secret** shown by Meticulous after linking
|
|
11
|
+
- Enable the pull request **Updated**, **Merged**, **Declined**, and **Superseded** triggers
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
export const bitbucketRepositoryAccessTokenPermissionsSummary =
|
|
15
|
+
"Repositories: Read and Pull requests: Read";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const gitLabLegacyTokenScopesSummary =
|
|
2
|
+
"api (required) and read_repository";
|
|
3
|
+
|
|
4
|
+
export const gitLabLegacyTokenPrefillUrl =
|
|
5
|
+
"https://gitlab.com/-/user_settings/personal_access_tokens?name=Meticulous&scopes=api,read_repository";
|
|
6
|
+
|
|
7
|
+
export const linkGitLabInstructions = `
|
|
8
|
+
1. Create a **legacy** GitLab personal access token (not a fine-grained token):
|
|
9
|
+
- Go to your avatar → **Edit profile** → **Personal access tokens**
|
|
10
|
+
- Choose **Add legacy token** (or **Create legacy token**), not **Generate fine-grained token**
|
|
11
|
+
- Under **Scopes**, enable **api** and **read_repository**
|
|
12
|
+
([guide](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token))
|
|
13
|
+
- Your GitLab user must have **Maintainer** or **Owner** on the project
|
|
14
|
+
- Alternatively, a **project access token** (Premium/Ultimate on GitLab.com) with the same scopes and **Maintainer** role works
|
|
15
|
+
([project token guide](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#create-a-project-access-token))
|
|
16
|
+
2. In Meticulous, link the repository and paste the token:
|
|
17
|
+
- When creating a GitLab project, or from **Project settings → CI settings → Linked repository**
|
|
18
|
+
- Enter your GitLab **project ID** (from **Settings → General** in GitLab), paste the access token, and configure the webhook shown after linking
|
|
19
|
+
3. Add the Meticulous webhook in GitLab (**Settings → Webhooks**):
|
|
20
|
+
- Use the **Webhook URL** and **Secret token** from Meticulous
|
|
21
|
+
- Enable **Merge request events**
|
|
22
|
+
`;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TESTING_FEATURE_FLAGS,
|
|
3
|
+
TYPESCRIPT_TYPES_URL,
|
|
4
|
+
} from "src/lib/utils/internal-urls/docs-urls.utils";
|
|
5
|
+
import { WHERE_CAN_I_REACH_OUT_FOR_SUPPORT } from "../constants";
|
|
6
|
+
|
|
7
|
+
export const document = `---
|
|
8
|
+
{
|
|
9
|
+
"title": "Recording the context of a user session"
|
|
10
|
+
}
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# {% $frontmatter.title %}
|
|
14
|
+
|
|
15
|
+
When recording user sessions with Meticulous, you can add contextual information. This can
|
|
16
|
+
make sessions easier to find, help your developers debug diffs in these sessions more
|
|
17
|
+
easily, and let Meticulous optimise session selection across different combinations of
|
|
18
|
+
context (e.g. flags, roles, themes).
|
|
19
|
+
|
|
20
|
+
All \`window.Meticulous?.context.*\` calls below use optional chaining, so they're safe
|
|
21
|
+
no-ops when the recorder isn't loaded — there's no need to guard them or check
|
|
22
|
+
\`isRunningAsTest\`.
|
|
23
|
+
|
|
24
|
+
If your project uses TypeScript, install
|
|
25
|
+
[\`@alwaysmeticulous/sdk-bundles-api\`](${TYPESCRIPT_TYPES_URL}) and augment the \`Window\`
|
|
26
|
+
interface as shown in the [TypeScript Types page](${TYPESCRIPT_TYPES_URL}); that gives
|
|
27
|
+
every call below full type safety. You only need to do this once per project — the same
|
|
28
|
+
augmentation covers \`recordUserId\`, \`recordUserEmail\`, \`recordFeatureFlag\`,
|
|
29
|
+
\`recordCustomContext\`, and the rest of \`window.Meticulous\`.
|
|
30
|
+
|
|
31
|
+
## Adding context to user sessions
|
|
32
|
+
|
|
33
|
+
Meticulous provides several methods to record different types of context. If you record
|
|
34
|
+
the same piece of context multiple times, the last value will be used.
|
|
35
|
+
|
|
36
|
+
### Recording user information
|
|
37
|
+
|
|
38
|
+
You can record the ID and email address of the logged-in user:
|
|
39
|
+
|
|
40
|
+
\`\`\`js
|
|
41
|
+
// Record the ID of the logged-in user
|
|
42
|
+
window.Meticulous?.context.recordUserId('user-123');
|
|
43
|
+
|
|
44
|
+
// Record the email address of the logged-in user
|
|
45
|
+
window.Meticulous?.context.recordUserEmail('user@example.com');
|
|
46
|
+
\`\`\`
|
|
47
|
+
|
|
48
|
+
This information is associated with the session and makes it easier to find sessions for
|
|
49
|
+
specific users.
|
|
50
|
+
|
|
51
|
+
A natural place for these calls is wherever you load the current user (e.g. a
|
|
52
|
+
\`useCurrentUser\` / \`useSession\` hook, or a \`/me\` query). If your app has a separate
|
|
53
|
+
post-login flow where the user starts logged out and then signs in, you may also want to
|
|
54
|
+
record there so those sessions pick up the user identity too.
|
|
55
|
+
|
|
56
|
+
### Recording feature flags
|
|
57
|
+
|
|
58
|
+
You can record which feature flags were active during a session (the value should be a
|
|
59
|
+
string or boolean):
|
|
60
|
+
|
|
61
|
+
\`\`\`js
|
|
62
|
+
window.Meticulous?.context.recordFeatureFlag('bigUiRefactor', true);
|
|
63
|
+
window.Meticulous?.context.recordFeatureFlag('checkoutFlowStyle', 'v3');
|
|
64
|
+
\`\`\`
|
|
65
|
+
|
|
66
|
+
We recommend looping over the flags your app already evaluates rather than maintaining a
|
|
67
|
+
hand-curated list — that way new flags are picked up automatically:
|
|
68
|
+
|
|
69
|
+
\`\`\`js
|
|
70
|
+
// Use whichever flag map your app already has — an SDK snapshot
|
|
71
|
+
// (e.g. client.getAllFlags() / posthog.getAllFlags()), an API
|
|
72
|
+
// response from your backend, or a shared flag-provider value.
|
|
73
|
+
const flags = client.getAllFlags();
|
|
74
|
+
for (const [name, value] of Object.entries(flags)) {
|
|
75
|
+
window.Meticulous?.context.recordFeatureFlag(name, value);
|
|
76
|
+
}
|
|
77
|
+
\`\`\`
|
|
78
|
+
|
|
79
|
+
If your app uses **both** a client-side SDK *and* server-evaluated flags (whose resolved
|
|
80
|
+
values reach the frontend via something like a \`features\` field on \`/me\`), it's worth
|
|
81
|
+
looping over both — they each affect what the UI renders. Recording the same flag twice
|
|
82
|
+
is fine; the last value wins.
|
|
83
|
+
|
|
84
|
+
A reasonable place to call this is wherever flags first become available (the SDK's
|
|
85
|
+
initial-fetch callback, or the effect that resolves your flags API response). If your app
|
|
86
|
+
re-evaluates flags after login or identity changes, recording there as well keeps the
|
|
87
|
+
context accurate for sessions that started logged out.
|
|
88
|
+
|
|
89
|
+
To learn how Meticulous *tests* the flags you record, see
|
|
90
|
+
[Testing Feature Flags with Meticulous](${TESTING_FEATURE_FLAGS}).
|
|
91
|
+
|
|
92
|
+
### Recording custom context
|
|
93
|
+
|
|
94
|
+
For any other contextual information that doesn't fit into the categories above, you can
|
|
95
|
+
use the custom context method (again with a string or boolean value):
|
|
96
|
+
|
|
97
|
+
\`\`\`js
|
|
98
|
+
window.Meticulous?.context.recordCustomContext('userRole', 'admin');
|
|
99
|
+
\`\`\`
|
|
100
|
+
|
|
101
|
+
Anything that changes how the UI looks or behaves between sessions is worth considering,
|
|
102
|
+
since recording it helps Meticulous tell those differences apart from real diffs. Common
|
|
103
|
+
examples:
|
|
104
|
+
|
|
105
|
+
- **User role / permissions** — admin vs regular user, role-gated menus and actions.
|
|
106
|
+
Often available on the same user object you read for \`recordUserId\`.
|
|
107
|
+
- **Tenant / organization / workspace ID** — for multi-tenant apps, which tenant is
|
|
108
|
+
active.
|
|
109
|
+
- **Theme / colour scheme** — whatever drives the \`dark\` class on \`<html>\` or your
|
|
110
|
+
theme provider.
|
|
111
|
+
- **Locale / language** — i18n setting from cookies, localStorage, \`useLocale\`,
|
|
112
|
+
\`next-intl\`, \`i18next\`, etc.
|
|
113
|
+
- **Viewport / layout mode** — compact vs comfortable, sidebar collapsed, etc., when
|
|
114
|
+
saved per-user.
|
|
115
|
+
- **Plan / subscription tier** — free vs pro vs enterprise, when it changes the UI.
|
|
116
|
+
- **Environment or build version** — useful when comparing diffs across deploys.
|
|
117
|
+
- **A/B test assignments** outside your main flag provider.
|
|
118
|
+
|
|
119
|
+
It's usually enough to record each value once, where it's first read or initialised. If
|
|
120
|
+
the value can change mid-session (a theme toggle, a locale switcher, a tenant switcher),
|
|
121
|
+
recording in the change handler too keeps the context accurate.
|
|
122
|
+
|
|
123
|
+
## Related Pages
|
|
124
|
+
|
|
125
|
+
- [Testing Feature Flags with Meticulous](${TESTING_FEATURE_FLAGS}) - Learn how Meticulous tests the feature flags you record
|
|
126
|
+
- [TypeScript Types for window.Meticulous](${TYPESCRIPT_TYPES_URL}) - Get type definitions for the \`window.Meticulous\` object
|
|
127
|
+
|
|
128
|
+
${WHERE_CAN_I_REACH_OUT_FOR_SUPPORT}
|
|
129
|
+
`;
|