This guide covers all testing procedures for the InfluxData documentation, including code block testing, link validation, and style linting.
- Prerequisites: Install Node.js, Yarn, and Docker
- Install dependencies: Run
yarnto install all dependencies - Build test environment: Run
docker build -t influxdata/docs-pytest:latest -f Dockerfile.pytest . - Run tests: Use any of the test commands below
| Test Type | Purpose | Command |
|---|---|---|
| Code blocks | Validate shell/Python code examples | yarn test:codeblocks:all |
| Link validation | Check internal/external links | yarn test:links |
| Style linting | Enforce writing standards | .ci/vale/vale.sh |
| Markdown generation | Generate LLM-friendly Markdown | yarn build:md |
| E2E tests | UI and functionality testing | yarn test:e2e |
Code block testing validates that shell commands and Python scripts in documentation work correctly using pytest-codeblocks.
# Test all code blocks
yarn test:codeblocks:all
# Test specific products
yarn test:codeblocks:cloud
yarn test:codeblocks:v2
yarn test:codeblocks:telegrafchmod +x ./test/src/*.shCreate databases, buckets, and tokens for the product(s) you're testing. If you don't have access to a Clustered instance, you can use your Cloud Dedicated instance for testing in most cases.
Copy the ./test/env.test.example file into each product directory and rename as .env.test:
# Example locations
./content/influxdb/cloud-dedicated/.env.test
./content/influxdb3/clustered/.env.testInside each product's .env.test file, assign your InfluxDB credentials:
- Include the usual
INFLUX_environment variables - For
cloud-dedicated/.env.testandclustered/.env.test, also define:ACCOUNT_ID,CLUSTER_ID: Found in yourinfluxctl config.tomlMANAGEMENT_TOKEN: Generate withinfluxctl management create
See ./test/src/prepare-content.sh for the full list of variables you may need.
For influxctl commands to run in tests, move or copy your config.toml file to the ./test directory.
Warning
- The database you configure in
.env.testand any written data may be deleted during test runs - Don't add your
.env.testfiles to Git. Git is configured to ignore.env*files to prevent accidentally committing credentials
print("Hello, world!")Hello, world!
For commands that require TTY interaction (like influxctl authentication), wrap the command in a subshell and redirect output:
# Test the preceding command outside of the code block.
# influxctl authentication requires TTY interaction--
# output the auth URL to a file that the host can open.
script -c "influxctl user list " \
/dev/null > /shared/urls.txtTo hide test blocks from users, wrap them in HTML comments. pytest-codeblocks will still collect and run them.
pytest-codeblocks has features for skipping tests and marking blocks as failed. See the pytest-codeblocks README for details.
Potential causes:
- Check test discovery options in
pytest.ini - Use
python(notpy) for Python code block language identifiers:vs# This works# This is ignored
Code block testing can be time-consuming for large documentation sets. Several optimization strategies are available:
Test specific programming languages independently:
# Test only Python code blocks
yarn test:codeblocks:python
# Test only Bash/Shell code blocks
yarn test:codeblocks:bash
# Test only SQL code blocks
yarn test:codeblocks:sqlBenefits:
- Faster feedback for specific language changes
- Easier debugging of language-specific issues
- Enables parallel execution in CI
Cache successful test results to avoid retesting unchanged content:
# Inside test container
./test/scripts/cached-test.sh content/influxdb/cloud/get-started/
# View cache statistics
yarn test:cache:stats
# Clean expired cache entries
yarn test:cache:cleanHow it works:
- Creates content hash for files/directories
- Caches successful test results for 7 days
- Skips tests if content unchanged and cache valid
- Bypasses cache with
TEST_CACHE_BYPASS=1
yarn test:cache:stats # Show cache statistics
yarn test:cache:list # List all cached results
yarn test:cache:clean # Remove expired entries (>7 days)
yarn test:cache:clear # Remove all entriesWithout optimization: ~45 minutes (sequential) With parallel execution: ~18 minutes (59% faster) With caching (2nd run): ~5 seconds (97% faster)
For comprehensive performance optimization documentation, see test/TEST-PERFORMANCE.md.
The Test Code Blocks GitHub Actions workflow
(.github/workflows/test.yml) runs code block tests on demand. Pull
requests trigger a detection-only pass that suggests which products
to test; actual test execution runs via workflow_dispatch.
On pull requests:
- Detects changed content and test-harness files (
content/**/*.md,test/**,Dockerfile.pytest,compose.yaml) - Resolves shared content changes to the consuming products
- Posts a summary with suggested products, partitioned into
"runnable" (products with a pytest service in
compose.yaml) and "not yet runnable" - Does not run tests or block the PR
Manual runs (workflow_dispatch):
- Trigger from the Actions UI or with
gh workflow run:gh workflow run "Test Code Blocks" \ --repo influxdata/docs-v2 \ -f products=core,telegraf \ -f use_default_group=false - The default group is
influxdb3_coreandtelegraf - Content failures surface as
::warning::annotations and in the job summary; they do not fail the matrix job
Products that run against a live server in CI:
| Product | Status | How |
|---|---|---|
influxdb3_core |
Runs live | Started via docker compose up influxdb3-core with a preconfigured offline admin token generated at job start |
influxdb3_enterprise |
Gated on license blob | Requires INFLUXDB3_ENTERPRISE_LICENSE_BLOB repo secret (see below). When unset, Enterprise is skipped with an informational notice |
telegraf, v2, cloud, cloud-dedicated, cloud-serverless, clustered |
Mock credentials | Tests that hit real endpoints may fail; content-only checks still run |
Enterprise trial-license activation requires email verification, which can't complete in a headless CI environment. CI therefore expects a pre-activated license blob stored as a repository secret. Produce it once locally, then upload.
1. Register the verification email.
Choose an email address you control and have InfluxData approve it for
trial licensing. The email is stored in the repo secret
INFLUXDB3_ENTERPRISE_LICENSE_EMAIL.
2. Activate Enterprise locally with that email.
# Create the directory Docker Compose expects
mkdir -p ~/influxdata-docs/.influxdb3/enterprise/data
# Point compose at the verified email
echo "INFLUXDB3_ENTERPRISE_LICENSE_EMAIL=<verified-email>" \
> ~/influxdata-docs/.influxdb3/enterprise/.env
# Generate an admin token file (compose mounts it as a secret)
TOKEN="apiv3_$(openssl rand -hex 32)"
cat > ~/influxdata-docs/.influxdb3/enterprise/admin-token.json <<EOF
{"token":"${TOKEN}","name":"_admin","description":"Local admin token"}
EOF
chmod 0600 ~/influxdata-docs/.influxdb3/enterprise/admin-token.json
# Start Enterprise. Watch the logs until activation completes.
docker compose --profile shared up -d influxdb3-enterprise
docker compose logs -f influxdb3-enterpriseThe first activation with a pre-approved email should skip the
"Waiting for verification..." stall and persist a license file at
~/influxdata-docs/.influxdb3/enterprise/data/cluster0/trial_or_home_license.
After you see activation succeed, stop the server:
docker compose --profile shared down3. Upload the license blob as a repo secret.
LICENSE=~/influxdata-docs/.influxdb3/enterprise/data/cluster0/trial_or_home_license
base64 -i "$LICENSE" | gh secret set INFLUXDB3_ENTERPRISE_LICENSE_BLOB \
--repo influxdata/docs-v24. Verify CI picks it up.
gh workflow run "Test Code Blocks" \
--repo influxdata/docs-v2 \
-f products=enterprise \
-f use_default_group=falseThe Enterprise job should now decode the blob into
/var/lib/influxdb3/data/cluster0/trial_or_home_license, start the
server, and run pytest against it.
Note
Trial licenses have a finite validity window. When the license
encoded in INFLUXDB3_ENTERPRISE_LICENSE_BLOB expires, Enterprise
CI jobs will fail to start. Re-run the activation locally and
upload a fresh blob.
The documentation includes tooling to generate LLM-friendly Markdown versions of documentation pages, both locally via CLI and on-demand via Lambda@Edge in production.
# Prerequisites (run once)
yarn install
yarn build:ts
npx hugo --quiet
# Generate Markdown
node scripts/html-to-markdown.js --path influxdb3/core/get-started --limit 10
# Validate generated Markdown
node cypress/support/run-e2e-specs.js \
--spec "cypress/e2e/content/markdown-content-validation.cy.js"For complete documentation including prerequisites, usage examples, output formats, frontmatter structure, troubleshooting, and architecture details, see the inline documentation:
# Or view the first 150 lines in terminal
head -150 scripts/html-to-markdown.jsThe script documentation includes:
- Prerequisites and setup steps
- Command-line options and examples
- Output file types (single page vs section aggregation)
- Frontmatter structure for both output types
- Testing procedures
- Common issues and solutions
- Architecture overview
- Related files
- CLI tool:
scripts/html-to-markdown.js- Comprehensive inline documentation - Core logic:
scripts/lib/markdown-converter.js- Shared conversion library - Lambda handler:
deploy/llm-markdown/lambda-edge/markdown-generator/index.js- Production deployment - Lambda docs:
deploy/llm-markdown/README.md- Deployment guide - Cypress tests:
cypress/e2e/content/markdown-content-validation.cy.js- Validation tests
All generated markdown files include structured YAML frontmatter:
---
title: Page Title
description: Page description for SEO
url: /influxdb3/core/get-started/
product: InfluxDB 3 Core
version: core
date: 2024-01-15T00:00:00Z
lastmod: 2024-11-20T00:00:00Z
type: page
estimated_tokens: 2500
---Section pages include additional fields:
---
type: section
pages: 4
child_pages:
- title: Set up InfluxDB 3 Core
url: /influxdb3/core/get-started/setup/
- title: Write data
url: /influxdb3/core/get-started/write/
---# Generate markdown with verbose output
node scripts/html-to-markdown.js --path influxdb3/core/get-started --limit 2 --verbose
# Check files were created
ls -la public/influxdb3/core/get-started/*.md
# View generated content
cat public/influxdb3/core/get-started/index.md
# Check frontmatter
head -20 public/influxdb3/core/get-started/index.mdThe repository includes comprehensive Cypress tests for markdown validation:
# Run all markdown validation tests
node cypress/support/run-e2e-specs.js --spec "cypress/e2e/content/markdown-content-validation.cy.js"
# Test specific content file
node cypress/support/run-e2e-specs.js \
--spec "cypress/e2e/content/markdown-content-validation.cy.js" \
content/influxdb3/core/query-data/execute-queries/_index.mdThe Cypress tests validate:
- ✅ No raw Hugo shortcodes (
{{< >}}or{{% %}}) - ✅ No HTML comments
- ✅ Proper YAML frontmatter with required fields
- ✅ UI elements removed (feedback forms, navigation)
- ✅ GitHub-style callouts (Note, Warning, etc.)
- ✅ Properly formatted tables, lists, and code blocks
- ✅ Product context metadata
- ✅ Clean link formatting
Cause: Page doesn't have <article class="article--content"> element (common for index/list pages)
Solution: This is normal behavior. The converter skips pages without article content. To verify:
# Check HTML structure
grep -l 'article--content' public/path/to/page/index.htmlCause: TypeScript not compiled (product-mappings.js missing)
Solution: Build TypeScript first:
yarn build:ts
ls -la dist/utils/product-mappings.jsCause: Attempting to process thousands of pages at once
Solution: Use --limit flag to process in batches:
# Process 1000 files at a time
node scripts/html-to-markdown.js --limit 1000Cause: Product mappings not up to date or path doesn't match known patterns
Solution:
- Rebuild TypeScript:
yarn build:ts - Check product mappings in
assets/js/utils/product-mappings.ts - Add new product paths if needed
Before committing markdown generation changes:
- Run TypeScript build:
yarn build:ts - Build Hugo site:
npx hugo --quiet - Generate markdown for affected paths
- Run Cypress validation tests
- Manually check sample output files:
- Frontmatter is valid YAML
- No shortcode remnants (
{{<,{{%) - No HTML comments (
<!--,-->) - Product context is correct
- Links are properly formatted
- Code blocks have language identifiers
- Tables render correctly
The markdown generation uses a shared library architecture:
docs-v2/
├── scripts/
│ ├── html-to-markdown.js # CLI wrapper (filesystem operations)
│ └── lib/
│ └── markdown-converter.js # Core conversion logic (shared library)
├── dist/
│ └── utils/
│ └── product-mappings.js # Product detection (compiled from TS)
└── public/ # Generated HTML + Markdown files
The shared library (scripts/lib/markdown-converter.js) is:
- Used by local markdown generation scripts
- Imported by docs-tooling Lambda@Edge for on-demand generation
- Tested independently with isolated conversion logic
For deployment details, see deploy/lambda-edge/markdown-generator/README.md.
Link validation uses the link-checker tool to validate internal and external links in documentation files.
Option 1: Build from source (macOS/local development)
For local development on macOS, build the link-checker from source:
# Clone and build link-checker
git clone https://github.com/influxdata/docs-tooling.git
cd docs-tooling/link-checker
cargo build --release
# Copy binary to your PATH or use directly
cp target/release/link-checker /usr/local/bin/
# OR use directly: ./target/release/link-checkerOption 2: Download pre-built binary (GitHub Actions/Linux)
The link-checker binary is distributed via docs-v2 releases for reliable access from GitHub Actions workflows:
# Download Linux binary from docs-v2 releases
curl -L -o link-checker \
https://github.com/influxdata/docs-v2/releases/download/link-checker-v1.0.0/link-checker-linux-x86_64
chmod +x link-checker
# Verify installation
./link-checker --versionNote
Pre-built binaries are currently Linux x86_64 only. For macOS development, use Option 1 to build from source.
# Clone and build link-checker
git clone https://github.com/influxdata/docs-tooling.git
cd docs-tooling/link-checker
cargo build --release
# Copy binary to your PATH or use directly
cp target/release/link-checker /usr/local/bin/For maintainers: To create a new link-checker release in docs-v2:
-
Create release in docs-tooling (builds and releases binary automatically):
cd docs-tooling git tag link-checker-v1.2.x git push origin link-checker-v1.2.x -
Manually distribute to docs-v2 (required due to private repository access):
# Download binary from docs-tooling release curl -L -H "Authorization: Bearer $(gh auth token)" \ -o link-checker-linux-x86_64 \ "https://github.com/influxdata/docs-tooling/releases/download/link-checker-v1.2.x/link-checker-linux-x86_64" curl -L -H "Authorization: Bearer $(gh auth token)" \ -o checksums.txt \ "https://github.com/influxdata/docs-tooling/releases/download/link-checker-v1.2.x/checksums.txt" # Create docs-v2 release gh release create \ --repo influxdata/docs-v2 \ --title "Link Checker Binary v1.2.x" \ --notes "Link validation tooling binary for docs-v2 GitHub Actions workflows." \ link-checker-v1.2.x \ link-checker-linux-x86_64 \ checksums.txt
-
Update workflow reference (if needed):
# Update .github/workflows/pr-link-check.yml line 98 to use new version sed -i 's/link-checker-v[0-9.]*/link-checker-v1.2.x/' .github/workflows/pr-link-check.yml
Note
The manual distribution is required because docs-tooling is a private repository and the default GitHub token doesn't have cross-repository access for private repos.
# Map content files to public HTML files
link-checker map content/path/to/file.md
# Check links in HTML files
link-checker check public/path/to/file.html
# Generate configuration file
link-checker configThe link-checker automatically handles relative link resolution based on the input type:
Local Files → Local Resolution
# When checking local files, relative links resolve to the local filesystem
link-checker check public/influxdb3/core/admin/scale-cluster/index.html
# Relative link /influxdb3/clustered/tags/kubernetes/ becomes:
# → /path/to/public/influxdb3/clustered/tags/kubernetes/index.htmlURLs → Production Resolution
# When checking URLs, relative links resolve to the production site
link-checker check https://docs.influxdata.com/influxdb3/core/admin/scale-cluster/
# Relative link /influxdb3/clustered/tags/kubernetes/ becomes:
# → https://docs.influxdata.com/influxdb3/clustered/tags/kubernetes/Why This Matters
- Testing new content: Tag pages generated locally will be found when testing local files
- Production validation: Production URLs validate against the live site
- No false positives: New content won't appear broken when testing locally before deployment
# Map Markdown files to HTML
link-checker map content/influxdb3/core/get-started/
# Check links in mapped HTML files
link-checker check public/influxdb3/core/get-started/# Map shared content files
link-checker map content/shared/influxdb3-cli/
# Check the mapped output files
# (link-checker map outputs the HTML file paths)
link-checker map content/shared/influxdb3-cli/ | \
xargs link-checker check# Check HTML files directly without mapping
link-checker check public/influxdb3/core/get-started/# Check only files changed in the last commit
git diff --name-only HEAD~1 HEAD | grep '\.md$' | \
xargs link-checker map | \
xargs link-checker check# Uses default settings or test.lycherc.toml if present
link-checker check public/influxdb3/core/get-started/# Use production configuration with comprehensive exclusions
link-checker check \
--config .ci/link-checker/production.lycherc.toml \
public/influxdb3/core/get-started/Automated Integration (docs-v2)
The docs-v2 repository includes automated link checking for pull requests:
- Trigger: Runs automatically on PRs that modify content files
- Binary distribution: Downloads latest pre-built binary from docs-v2 releases
- Smart detection: Only checks files affected by PR changes
- Production config: Uses optimized settings with exclusions for GitHub, social media, etc.
- Results reporting: Broken links reported as GitHub annotations with detailed summaries
The workflow automatically:
- Detects content changes in PRs using GitHub Files API
- Downloads latest link-checker binary from docs-v2 releases
- Builds Hugo site and maps changed content to public HTML files
- Runs link checking with production configuration
- Reports results with annotations and step summaries
Manual Integration (other repositories)
For other repositories, you can integrate link checking manually:
name: Link Check
on:
pull_request:
paths:
- 'content/**/*.md'
jobs:
link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download link-checker
run: |
curl -L -o link-checker \
https://github.com/influxdata/docs-tooling/releases/latest/download/link-checker-linux-x86_64
chmod +x link-checker
cp target/release/link-checker ../../link-checker
cd ../..
- name: Build Hugo site
run: |
npm install
npx hugo --minify
- name: Check changed files
run: |
git diff --name-only origin/main HEAD | \
grep '\.md$' | \
xargs ./link-checker map | \
xargs ./link-checker check \
--config .ci/link-checker/production.lycherc.tomlStyle linting uses Vale to enforce documentation writing standards, branding guidelines, and vocabulary consistency.
- Install Vale locally (recommended):
brew install vale(or see Vale installation guide) - Or use Docker: The
.ci/vale/vale.shwrapper falls back to a pinned Docker image ifvaleisn't installed locally.
# Lint specific files
.ci/vale/vale.sh content/influxdb3/core/**/*.md
# With product config and alert level
.ci/vale/vale.sh --config=content/influxdb/cloud-dedicated/.vale.ini --minAlertLevel=error content/influxdb/cloud-dedicated/write-data/**/*.md- Install the Vale VSCode extension.
- Set
Vale:Vale CLI:Pathtovale(or the full path to the binary).
Vale can raise different alert levels:
- Error: Problems that can cause content to render incorrectly, violations of branding guidelines, rejected vocabulary terms
- Warning: General style guide rules and best practices
- Suggestion: Style preferences that may require refactoring or updates to an exceptions list
- Styles:
.ci/vale/styles/contains configuration for the customInfluxDataDocsstyle - Vocabulary: Add accepted/rejected terms to
.ci/vale/styles/config/vocabularies - Product-specific: Configure per-product styles like
content/influxdb/cloud-dedicated/.vale.ini
For more configuration details, see Vale configuration.
Vale runs automatically on pull requests that modify markdown files. The workflow:
- Detects changed markdown files (content, README, instruction files)
- Resolves shared content to consuming product pages
- Maps files to appropriate Vale configs (matching local Lefthook behavior)
- Runs Vale via
.ci/vale/vale.sh(local binary or Docker fallback) - Reports results as inline annotations and a PR summary comment
Alert levels:
- Errors block merging
- Warnings and suggestions are informational only
Files checked:
content/**/*.mdREADME.md,DOCS-*.md**/AGENTS.md,**/CLAUDE.md.github/**/*.md,.claude/**/*.md
The CI check uses the same product-specific configs as local development, ensuring consistency between local and CI linting.
docs-v2 uses Lefthook to manage Git hooks that run automatically during pre-commit and pre-push.
When you run git commit, Git runs:
- Vale: Style linting (if configured)
- Prettier: Code formatting
- Cypress: Link validation tests
- Pytest: Code block tests
We strongly recommend running linting and tests, but you can skip them:
# Skip with --no-verify flag
git commit -m "<COMMIT_MESSAGE>" --no-verify
# Skip with environment variable
LEFTHOOK=0 git commit# Run all E2E tests
yarn test:e2e
# Run specific E2E specs
node cypress/support/run-e2e-specs.js --spec "cypress/e2e/content/index.cy.js"For JavaScript code in the documentation UI (assets/js):
- In VS Code, select Run > Start Debugging
- Select "Debug Docs (source maps)" configuration
- Set breakpoints in the
assets/js/ns-hugo-imp:namespace
-
Import debug helpers in your JavaScript module:
import { debugLog, debugBreak, debugInspect } from './utils/debug-helpers.js';
-
Insert debug statements:
const data = debugInspect(someData, 'Data'); debugLog('Processing data', 'myFunction'); debugBreak(); // Add breakpoint
-
Start Hugo:
yarn hugo server -
In VS Code, select "Debug JS (debug-helpers)" configuration
Remember to remove debug statements before committing.
Available test services:
# All code block tests
docker compose --profile test up
# Individual product tests
docker compose run --rm cloud-pytest
docker compose run --rm v2-pytest
docker compose run --rm telegraf-pytest
# Stop monitoring services
yarn test:codeblocks:stop-monitors- Always test code examples before committing
- Use realistic data and examples that users would encounter
- Include proper error handling in examples
- Format code to fit within 80 characters
- Use long options in command-line examples (
--optionvs-o)
- Build Hugo site before generating markdown:
npx hugo --quiet - Compile TypeScript before generation:
yarn build:ts - Test on small subsets first using
--limitflag - Use
--verboseflag to debug conversion issues - Always run Cypress validation tests after generation
- Check sample output manually for quality
- Verify shortcodes are evaluated (no
{{<or{{%in output) - Ensure UI elements are removed (no "Copy page", "Was this helpful?")
- Test both single pages (
index.md) and section pages (index.section.md)
- Test links regularly, especially after content restructuring
- Use appropriate cache TTL settings for your validation needs
- Monitor cache hit rates to optimize performance
- Clean up expired cache entries periodically
- Run Vale regularly to catch style issues early
- Add accepted terms to vocabulary files rather than ignoring errors
- Configure product-specific styles for branding consistency
- Review suggestions periodically for content improvement opportunities
- Configuration:
pytest.ini,cypress.config.js,lefthook.yml - Docker:
compose.yaml,Dockerfile.pytest - Scripts:
.github/scripts/directory - Test data:
./test/directory - Vale config:
.ci/vale/styles/ - Markdown generation:
scripts/html-to-markdown.js- CLI wrapperscripts/lib/markdown-converter.js- Core conversion librarydeploy/lambda-edge/markdown-generator/- Lambda deploymentcypress/e2e/content/markdown-content-validation.cy.js- Validation tests
- GitHub Issues: docs-v2 issues
- Good first issues: good-first-issue label
- InfluxData CLA: Sign here for substantial contributions