Explaining the docs-as-code architecture#

AI-SAI-Generated Summary H-RHuman Reviewed H-EHuman Edited

Once tests depended on shared functions, developers and agents needed a reference for them. The address walkthrough explains how those functions work and how to call them; this chapter follows the address modules into generated developer documentation, local Sphinx presentation, and deprecation guidance.

1. The documentation layout#

This selected view shows the developer guides, function reference, application context, and build support.

src/
├── docs/
│   ├── conf.py
│   ├── index.md
│   ├── PlaywrightTestingSuite.md
│   ├── guides/
│   │   ├── how-to/                 # Environment, execution, coverage
│   │   ├── testing/                # Test patterns and improvement
│   │   ├── sphinx/                 # Documentation build support
│   │   └── doc-generation/         # Recording-to-documentation workflow
│   ├── tests/
│   │   ├── functions.md            # Helper reference navigation
│   │   ├── functions/
│   │   │   ├── address-helper.md
│   │   │   └── helperFunctions/
│   │   │       └── addressComponents.md
│   │   ├── pages.md
│   │   └── pages/                  # Helpers in application context
│   ├── reference/
│   ├── analysis/
│   ├── logs/
│   ├── _ext/                      # Project Sphinx extensions
│   └── _static/                   # CSS, JavaScript, supporting assets
├── extensions/
│   └── sphinx-js/                 # Local extension implementation
└── tests/
    └── HelperFiles/
        └── components/
            ├── address/address-helper.ts
            └── helperFunctions/addressComponents.ts

The layout serves three uses: developer guides describe operating and maintaining the suite; docs/tests/functions/ describes its reusable API; docs/tests/pages/ provides application context. The API source remains under tests/HelperFiles/, alongside the tests that use it.

2. A function and its reference page#

The address-components module provides a concrete connection. This function lives inside the reusable helper layer:

export async function fillCityName(
    page: Page,
    primaryCityName: string
): Promise<void> {
  const cityInput = page.getByLabel('City', { exact: true }).nth(0);
  await cityInput.waitFor({ state: 'visible', timeout: 5000 });
  await cityInput.fill(primaryCityName);
}

Its Markdown reference page asks Sphinx to document the function by name:

## fillCityName

```{js:autofunction} fillCityName
```

The page names the function instead of copying its signature and parameter list. With the TypeScript documentation build configured, Sphinx resolves the function and renders its reference entry. Changing the source signature is reflected when the documentation is successfully rebuilt.

fillCityName has no JSDoc comment, so its generated entry provides the function reference without a detailed description. I would need to add comments or a walkthrough to explain the implementation.

3. The Markdown and build configuration#

The build configuration identifies the TypeScript source for those reference entries:

primary_domain = 'js'
js_language = 'typescript'

# Sphinx-js configuration
# Path(s) to your TypeScript source folder(s), relative to conf.py
js_source_path = ['../tests/HelperFiles']

# Path to tsconfig.docs.json - excludes spec files with TypeScript errors
jsdoc_tsconfig_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../tsconfig.docs.json'))

The documentation project enables both MyST Parser and sphinx-js.

The build connects these inputs:

TypeScript helpers + source comments → TypeDoc/sphinx-js → js:autofunction → Sphinx page

The documentation TypeScript configuration includes tests/HelperFiles/**/*.ts and excludes *.spec.ts files. That makes the helper API the documentation input. It does not mean that the documentation build validates the end-to-end tests.

This produces source-derived reference documentation on rebuild. Descriptions and examples still require maintained source comments, while narrative pages and migration advice require editorial review.

4. Local sphinx-js presentation#

The project explicitly loads its local extension implementation:

# Add local sphinx-js extension to path BEFORE importing
# This uses our customized version at extensions/sphinx-js/
LOCAL_SPHINX_JS = os.path.abspath(os.path.join(os.path.dirname(__file__), '../extensions/sphinx-js'))
if os.path.exists(LOCAL_SPHINX_JS):
    sys.path.insert(0, LOCAL_SPHINX_JS)
    print(f"Using local sphinx-js from: {LOCAL_SPHINX_JS}")

The local shared template renders example content as code blocks:

{% macro examples(items) %}
{% if items -%}
**Examples:**

{% for example in items -%}
.. code-block:: js

   {{ example|indent(3) }}
{% endfor %}
{%- endif %}
{% endmacro %}

The function template places deprecation information, descriptions, parameter and return fields, examples, and related references in each generated entry.

The division of responsibility is explicit: templates determine the structure of generated reference content; site CSS controls its appearance. The configured custom-codeblock.css adds bounded scrolling to code blocks, and deprecated.css adds deprecation styling. This lets the reference fit the rest of the documentation site.

5. Deprecation and API maintenance#

The address-helper page retains an older reference while directing new work toward a replacement:

## fillCity

```{deprecated} 1.0
Use `fillCityAllApproaches` instead.
```

```{js:autofunction} fillCity
```

The source comment also carries migration information for documentation tooling:

/**
 * fillCity
 * A specialized version of safeFill for the "City" field to reduce
 * repeated lines across your test. If you have the same fallback logic
 * for "City," you can unify it here.
 * @deprecated Use safeFillAddress() for complete address filling.
 */

The two examples contain different replacement advice: the Markdown names fillCityAllApproaches, while the source comment names safeFillAddress. That exposes a maintenance gap: generated API entries reduce duplication, but manually authored migration guidance still needs to agree with the source.

The stylesheet gives the deprecation signal a visual treatment:

/* Style the version text in Sphinx deprecated directive */
div.deprecated .versionmodified.deprecated {
  font-weight: 600;
  color: #cc0000;
}

The stylesheet also defines badges, borders, and signature treatments. The rendered appearance depends on the classes emitted by the documentation build.

The local sphinx-js deprecation macro emits a note for source-level deprecation metadata, while the Markdown uses Sphinx’s explicit deprecated directive. These are two documentation paths with different presentation; a source tag does not necessarily produce the same styled notice as the explicit directive.

6. A reference for developers and agents#

The central helper reference gave developers and agents a place to discover existing operations, inspect parameters, and recognize APIs being phased out. That supports the next portfolio stage: generating tests against the suite’s established helper vocabulary, then improving shared implementations as failures reveal gaps.

Helper API documentation and application manual drafts serve different readers. The former explains how to write tests; the latter explains the workflows those tests exercise. The agent workflow and manual-draft workflow follow that progression from recording and planning through testing, generation, and review.