Skip to content

Latest commit

 

History

History
177 lines (123 loc) · 13.9 KB

File metadata and controls

177 lines (123 loc) · 13.9 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

QAS CLI (qas-cli) is a Node.js CLI tool for uploading test automation results (JUnit XML / Playwright JSON / Allure results directories) to QA Sphere. It matches test case references (e.g., PRJ-123 markers or Allure TMS links) to QA Sphere test cases, creates or reuses test runs, and uploads results with optional attachments.

Commands

npm install              # Install dependencies
npm run build            # Clean, compile TS, add .js extensions, chmod entry point
npm run check            # Typecheck + lint + format check
npm test                 # Run all tests (Vitest)
npx vitest run src/tests/junit-xml-parsing.spec.ts   # Run a single test file
npx vitest run -t "test name"                        # Run a specific test by name
npm run lint             # ESLint
npm run lint:fix         # ESLint — auto-fix
npm run format           # Prettier — auto-fix
npm run format:check     # Prettier — check only
npm run typecheck        # tsc --noEmit

Node.js compatibility tests: cd mnode-test && ./docker-test.sh (requires Docker, tests against Node 18+).

Architecture

Entry Point & CLI Framework

  • src/bin/qasphere.ts — Entry point (#!/usr/bin/env node). Validates Node version, delegates to run().
  • src/commands/main.ts — Yargs setup. Registers three upload commands (junit-upload, playwright-json-upload, allure-upload) as instances of ResultUploadCommandModule, plus the api command.
  • src/commands/resultUpload.tsResultUploadCommandModule defines CLI options shared by both commands. Loads env vars, then delegates to ResultUploadCommandHandler.

Core Upload Pipeline (src/utils/result-upload/)

The upload flow has two stages handled by two classes, with a shared MarkerParser instance:

  1. MarkerParser — Centralizes all test case marker detection/extraction/matching logic:

    • Supports three marker formats: hyphenated (PRJ-123), underscore-separated hyphenless (test_prj123_foo), and CamelCase hyphenless (TestPrj123Foo or TestFooPrj123)
    • Hyphenless matching (underscore-separated and CamelCase) is gated on type === 'junit-upload' and requires the test name to start with test (case-insensitive)
    • Created by ResultUploadCommandHandler and passed to ResultUploader — both share one instance
    • Also exports a standalone formatMarker() function used by parsers
  2. ResultUploadCommandHandler — Orchestrates the overall flow:

    • Parses report inputs using the appropriate parser (JUnit XML file, Playwright JSON file, or Allure results directory), which return ParseResult objects containing both testCaseResults and runFailureLogs. File-based parsers receive file contents; directory-based parsers (Allure) receive the path — controlled by the module-level directoryInputTypes Set
    • ParserOptions includes allowPartialParse (set from --force) to skip invalid files instead of aborting
    • Detects project code from test case names via MarkerParser (or from --run-url)
    • Creates a new test run (or reuses an existing one if title conflicts)
    • Collects run-level logs from all parsed files and passes them to ResultUploader
  3. ResultUploader — Handles the upload-to-run mechanics:

    • Fetches test cases from the run, maps parsed results to them via MarkerParser matching
    • Validates unmatched/missing test cases (respects --force, --ignore-unmatched)
    • If run-level log is present, uploads it via createRunLog API before uploading test case results
    • Uploads file attachments concurrently (max 10 parallel), then creates results in batches (max 50 per request)

Report Parsers

  • junitXmlParser.ts — Parses JUnit XML via xml2js + Zod validation. Extracts attachments from [[ATTACHMENT|path]] markers in system-out/failure/error/skipped elements. Extracts suite-level <system-err> and empty-name <testcase> errors as run level error logs.
  • playwrightJsonParser.ts — Parses Playwright JSON report. Supports two test case linking methods: (1) test annotations with type: "test case" and URL description, (2) marker in test name. Handles nested suites recursively. Extracts top-level errors[] as run level error logs.
  • allureParser.ts — Parses Allure JSON results directories (*-result.json and *-container.json files; XML/images ignored). Supports test case linking via TMS links (type: "tms") or marker in test name, maps Allure statuses to QA Sphere result statuses (unknown→open, broken→blocked), strips ANSI codes and HTML-escapes messages, and resolves attachments via attachments[].source. Uses formatMarker() from MarkerParser. Extracts run-level failure logs from container files by checking befores/afters fixtures with failed/broken status — primarily useful for pytest (allure-junit5 and allure-playwright leave container fixtures empty).
  • types.ts — Shared TestCaseResult, ParseResult, and Attachment interfaces used by both parsers.

API Command (src/commands/api/)

The api command provides direct programmatic access to the QA Sphere public API: qasphere api <resource> <action> [options]. Each resource (e.g., projects, runs, test-cases) is a subcommand with its own actions. Some resources have nested subgroups (e.g., qasphere api runs test-cases list).

Architecture: The API command uses a manifest-based pattern. Each resource defines its endpoints as declarative ApiEndpointSpec objects (in src/commands/api/manifests/), and shared infrastructure handles yargs registration, validation, and execution.

Key files:

  • types.ts — Defines ApiEndpointSpec as a discriminated union on bodyMode ('none' | 'json' | 'file'), plus supporting types (ApiPathParamSpec, ApiFieldSpec, ApiQueryOptionSpec, ExecuteFn)
  • manifests/ — One file per resource (e.g., runs.ts, test-cases.ts), each exporting an array of ApiEndpointSpec objects. manifests/index.ts aggregates all specs into a single allSpecs array. manifests/utils.ts has shared param definitions (e.g., projectCodeParam)
  • builder.tsbuildCommandsFromSpecs() builds a yargs command tree from the flat specs array, handling nested command paths automatically. Creates yargs options from path params, query options, field options, and body mode
  • executor.tsexecuteCommand() orchestrates execution: collects and validates path params → processes body (based on bodyMode discriminant) → collects and validates query options → connects to API (lazy env loading) → executes with error mapping
  • main.ts — Registers the api command, delegates to buildCommandsFromSpecs()
  • utils.ts — Shared helpers: printJson(), apiDocsEpilog(), formatApiError(), ArgumentValidationError, kebabToCamelCase(), body parsing (parseBodyInput, mergeBodyWithFields), validation (validateFieldValues, validateOptionValues), collection helpers (collectFieldValues, collectPathParamValues, collectQueryValues), and handleApiValidationError() for reformatting API errors into CLI argument names

Important note: Online documentation is available at https://docs.qasphere.com. Most leaf pages have a markdown version available by appending .md in the URL. Use the markdown version before falling back to the original URL if the markdown version returns >= 400 status.

Key design patterns:

  • Manifest-based declarations: Each endpoint is a plain object (ApiEndpointSpec) declaring its command path, params, options, body mode, and execute function. The builder and executor handle all yargs wiring, validation, and error handling generically
  • Lazy env loading: QAS_URL/QAS_TOKEN are loaded only when the API is actually called (inside executeCommand()), so CLI validation errors are reported first
  • Validation flow: Path params and query options are validated against optional Zod schemas. For json body mode, individual field values are validated (with JSON parsing for complex fields), then merged with --body/--body-file input. API-level RequestValidationError is caught and reformatted into CLI argument names (e.g., --query-plans: [0].tcaseIds: not allowed for "live" runs)

API Layer (src/api/)

Composable fetch wrappers using higher-order functions:

  • utils.tswithBaseUrl, withApiKey, withJson, withDevAuth decorators that wrap fetch; jsonResponse<T>() for parsing responses; appendSearchParams() for building query strings; resourceIdSchema for validating resource identifiers; printJson() for formatted JSON output
  • index.tscreateApi(baseUrl, apiKey) assembles the API client from all sub-modules
  • schemas.ts — Shared types (ResourceId, ResultStatus, PaginatedResponse<T>, PaginatedRequest, MessageResponse), RequestValidationError class, validateRequest() helper, and common Zod field definitions (sortFieldParam, sortOrderParam, pageParam, limitParam)
  • One sub-module per resource (e.g., projects.ts, runs.ts, tcases.ts, folders.ts), each exporting a create<Resource>Api(fetcher) factory function. Each module defines Zod schemas for its request types (PascalCase, e.g., CreateRunRequestSchema), derives TypeScript types via z.infer, and validates inputs with validateRequest() inside API functions

The main createApi() composes the fetch chain: withDevAuth(withApiKey(withBaseUrl(fetch, baseUrl), apiKey)).

Configuration (src/utils/)

  • env.ts — Loads QAS_TOKEN and QAS_URL from environment variables, .env, or .qaspherecli (searched up the directory tree). Optional QAS_DEV_AUTH adds a dev cookie via the withDevAuth fetch decorator
  • config.ts — Constants (required Node version)
  • misc.ts — URL parsing, template string processing ({env:VAR}, date placeholders), error handling utilities. Note: marker-related functions have been moved to MarkerParser.ts
  • version.ts — Reads version from package.json by traversing parent directories

Testing

Tests use Vitest with MSW (Mock Service Worker) for API mocking. Test files are in src/tests/.

Upload Command Tests

  • result-upload.spec.ts — Integration tests for the full upload flow (JUnit, Playwright, and Allure), with MSW intercepting all API calls. Includes hyphenless and CamelCase marker tests (JUnit only)
  • marker-parser.spec.ts — Unit tests for MarkerParser (detection, extraction, matching across all marker formats and command types)
  • junit-xml-parsing.spec.ts — Unit tests for JUnit XML parser
  • playwright-json-parsing.spec.ts — Unit tests for Playwright JSON parser
  • allure-parsing.spec.ts — Unit tests for Allure parser
  • template-string-processing.spec.ts — Unit tests for run name template processing

Test fixtures live in src/tests/fixtures/ (XML files, JSON files, and mock test case data).

API Command Tests (src/tests/api/)

Tests for the api command are organized by resource under src/tests/api/, with one spec file per action (e.g., projects/list.spec.ts, runs/create.spec.ts). Tests support both mocked and live modes.

Shared infrastructure (src/tests/api/test-helper.ts):

  • baseURL, token — Configured base URL and token (mocked values or real from env vars)
  • useMockServer(...handlers) — Sets up MSW server with lifecycle hooks (before/after each test)
  • runCli(...args) — Invokes the CLI programmatically via run(args), captures and parses JSON output. Useful only if the command prints JSON.
  • test fixture — Extended Vitest test that provides a project fixture (mock project in mocked mode, real project with cleanup in live mode)
  • expectValidationError(runner, pattern) — Asserts a command exits with a validation error matching the given regex
  • Helper functions for live tests: createFolder(), createTCase(), createRun()

Global setup (src/tests/global-setup.ts): Authenticates against the live API (if env vars are set) and provides a session token for test project cleanup.

Test pattern: Each spec file typically contains:

  1. A describe('mocked', ...) block with MSW handlers and assertions on request headers/params
  2. Validation error tests checking CLI argument validation
  3. Live tests tagged with { tags: ['live'] } that run against a real QA Sphere instance

Other tests:

  • missing-subcommand-help.spec.ts — Verifies incomplete commands (e.g., api alone, api projects alone) show help text
  • api/utils.spec.ts — Unit tests for API command utility functions

Running Tests

npm run test                                    # Run all tests (mocked only by default)
npm run test:live                               # Run live tests only (requires env vars)

Environment Variables for Live API Tests

Live tests require all four variables to be set; otherwise tests run in mocked mode only:

Variable Purpose
QAS_TEST_URL Base URL of the QA Sphere instance
QAS_TEST_TOKEN API token for authenticated API calls
QAS_TEST_USERNAME Email for login endpoint (used by global setup)
QAS_TEST_PASSWORD Password for login endpoint (used by global setup)
QAS_DEV_AUTH (Optional) Dev auth cookie value for dev environments

The tsconfig.json excludes src/tests from compilation output.

Build

ESM project ("type": "module"). TypeScript compiles to build/, then ts-add-js-extension adds .js extensions to imports (required for ESM). The CLI binary is build/bin/qasphere.js.

Linting & Formatting

  • Linter: ESLint with typescript-eslint (config: eslint.config.mjs)
  • Formatter: Prettier (config: .prettierrc)
  • Pre-commit hook (Husky): runs lint-staged (Prettier + ESLint on staged files)
  • Commits: Do NOT add Co-Authored-By lines to commit messages