Tests
Want help writing your test steps? Check out the Action Builder prototype.
Tests tell Doc Detective what actions to perform, how, and where. Tests are made of three sets of components:
-
Test specification: The highest-level component, test specifications (or specs) are collection of tests that should run together. Contexts defined in the spec are shared by all tests in the spec. Test specifications are equivalent to test suites in other testing frameworks.
-
Test: A test to run within a spec. Each test has a name, and a set of steps to perform. Tests are equivalent to test cases in other testing frameworks.
-
Steps: A step is a single action to perform within a test. Each individual step acts as an assertion that the step completes as expected. Steps are roughly equivalent to assertions in other testing frameworks.
Each step can perform an action, which is a command that tells Doc Detective what to do. Actions can have additional properties that further define the action.
- checkLink: Check if a URL returns an acceptable status code from a GET request.
- click: Click or tap an element.
- find: Check if an element exists with the specified selector.
- goTo: Navigate to a specified URL.
- httpRequest: Perform a generic HTTP request, for example to an API.
- loadVariables: Load environment variables from a
.env
file. - record and stopRecord: Capture a video of test execution.
- runCode: Assemble and run code.
- runShell: Perform a native shell command.
- screenshot: Take a screenshot in PNG format.
- type: Type keys. To type special keys, begin and end the string with
$
and use the special key’s enum. For example, to type the Escape key, enter$ESCAPE$
. - wait: Pause before performing the next action.
Define a test
You can define test specs in multiple ways:
- Standalone JSON files make it easy to see the entirety of the spec and keep it in a separate, machine-readable format.
- Inline JSON allows you to define tests directly in your documentation source files.
- Detected tests are automatically generated by Doc Detective based on your documentation source files and your configuration.
Standalone JSON or YAML
Test specs in standalone JSON or YAML files use the following basic structure:
- JSON
- YAML
{
"specId": "spec-id",
"description": "Spec Description",
"tests": [
{
"testId": "test-id",
"description": "Test Description",
"steps": [
{
"stepId": "step-id",
"description": "Step description. This object also needs additional step properties like `find`, `goTo`, or `httpRequest`."
}
]
}
]
}
specId: spec-id
description: Spec Description
tests:
- testId: test-id
description: Test Description
steps:
- stepId: step-id
description: Step description. This object also needs additional step properties like `find`, `goTo`, or `httpRequest`.
For comprehensive options, see
specification
.
Here's an example test for performing a Google search and saving a screenshot of the results:
- JSON
- YAML
{
"tests": [
{
"steps": [
{
"goTo": "https://www.google.com"
},
{
"find": {
"selector": "[title=Search]",
"click": true
}
},
{
"type": [
"American Shorthair kittens",
"$ENTER$"
]
},
{
"wait": 5000
},
{
"screenshot": "search-results.png"
}
]
}
]
}
tests:
- steps:
- goTo: https://www.google.com
- find:
selector: "[title=Search]"
click: true
- type:
- American Shorthair kittens
- $ENTER$
- wait: 5000
- screenshot: search-results.png
Inline JSON or YAML
You can define tests directly in your documentation source files using inline JSON or YAML. Inline tests are useful for small, simple tests that you want to keep close to the content they test.
Inline tests are also excellent for maintaining tests because they are easy to update and keep in sync with the content they test as the content changes.
Inline tests depend on your config's
fileType
definitions. This page uses the default Markdown configuration, but you should update your config to match your documentation source files.
Inline tests use specially formatted comments with JSON or YAML objects to declare the tests and steps. Doc Detective reads the input file, line by line, and extracts the tests and steps from the comments. You can declare multiple tests and steps in a single file, using your config's test start, test end, step, and ignore patterns.
All test and step comments must be on a single line. Doc Detective doesn't support multi-line comments.
When you declare a test, you can specify any of the test properties available in the standalone JSON format, though steps
is normally omitted. See test
.
If you declare a new test without closing the previous test, Doc Detective automatically closes the previous test before starting the new one.
When you declare a step, you can specify any of the properties of the action you want to perform. See Actions.
If you declare a step without declaring a test, Doc Detective automatically creates a test to contain the step.
Comment patterns by file type
Doc Detective supports different comment patterns depending on your file type:
Markdown files (.md
, .markdown
, .mdx
):
- JSX-style comments:
{/* test { "testId": "my-test" } */}
- HTML comments:
<!-- test { "testId": "my-test" } -->
- Markdown link comments:
[comment]: # (test { "testId": "my-test" })
- Step comments:
{/* step { "goTo": "https://example.com" } */}
- Test end:
{/* test end */}
or<!-- test end -->
or[comment]: # (test end)
- Ignore blocks:
{/* test ignore start */}
and{/* test ignore end */}
HTML files (.html
, .htm
):
- Test comments:
<!-- test { "testId": "my-test" } -->
- Step comments:
<!-- step { "goTo": "https://example.com" } -->
- Test end:
<!-- test end -->
- Ignore blocks:
<!-- test ignore start -->
and<!-- test ignore end -->
AsciiDoc files (.adoc
, .asciidoc
, .asc
):
- Line comments:
// (test { "testId": "my-test" })
- Step comments:
// (step { "goTo": "https://example.com" })
- Test end:
// (test end)
- Ignore blocks:
// (test ignore start)
and// (test ignore end)
Examples
Here's an example using JSON syntax in Markdown:
[comment]: # 'test {"testId": "kitten-search"}'
To search for American Shorthair kittens,
1. Go to [Google](https://www.google.com).
[comment]: # 'step {"goTo": "https://www.google.com"}'
2. In the search bar, enter "American Shorthair kittens", then press Enter.
[comment]: # 'step { "find": { "selector": "[title=Search]", "click": true } }'
[comment]: # 'step { "type": ["American Shorthair kittens", "$ENTER$"] }'
[comment]: # 'step { "wait": 5000 }'

[comment]: # 'step { "screenshot": "search-results.png" }'
[comment]: # "test end"
Here's the same example using YAML syntax in Markdown:
{/_ test testId: kitten-search _/}
To search for American Shorthair kittens,
1. Go to [Google](https://www.google.com).
{/_ step goTo: https://www.google.com _/}
2. In the search bar, enter "American Shorthair kittens", then press Enter.
{/_ step find: selector: "[title=Search]" click: true _/} {/_ step type: - "American Shorthair kittens" - "$ENTER$" _/} {/_ step wait: 5000 _/}

{/_ step screenshot: search-results.png _/} {/_ test end _/}
HTML example:
<!-- test { "testId": "navigation-test" } -->
<p>Navigate to our homepage:</p>
<!-- step { "goTo": "https://example.com" } -->
<p>Click the menu button:</p>
<!-- step { "click": "Menu" } -->
<!-- test end -->
AsciiDoc example:
// (test { "testId": "doc-test" })
== Getting Started
Navigate to the application:
// (step { "goTo": "https://app.example.com" })
Click the *Start* button:
// (step { "click": "Start" })
// (test end)
Detected tests
Doc Detective can automatically generate tests based on your documentation source files and your fileTypes
configuration. Detected tests are useful for large, complex test suites that you want to keep in sync with your documentation. Test detection works by setting detectSteps
to true
and defining markup patterns and associated actions in the fileTypes.markup
array in your config, which Doc Detective uses to extract steps from your doc source files. You can define multiple test patterns in your config to extract different types of tests from your documentation.
Detected tests are useful for keeping your tests in sync with your documentation. When you update your documentation, Doc Detective automatically updates the tests based on the new content. Detected tests are generated automatically. You can't edit detected tests directly, but you can update your config or documentation source files to change the tests.
You can mix detected tests with inline tests to declare steps that might not be covered in your content, such starting or stopping a recording.
Doc Detective includes several default markup patterns for Markdown files. Here are all the built-in patterns:
{
"fileTypes": [
{
"name": "markdown",
"extensions": ["md", "markdown", "mdx"],
"markup": [
{
"name": "checkHyperlink",
"regex": [
"(?<!\\!)\\[[^\\]]+\\]\\(\\s*(https?:\\/\\/[^\\s)]+)(?:\\s+\"[^\"]*\")?\\s*\\)"
],
"actions": ["checkLink"]
},
{
"name": "clickOnscreenText",
"regex": [
"\\b(?:[Cc]lick|[Tt]ap|[Ll]eft-click|[Cc]hoose|[Ss]elect|[Cc]heck)\\b\\s+\\*\\*((?:(?!\\*\\*).)+)\\*\\*"
],
"actions": ["click"]
},
{
"name": "findOnscreenText",
"regex": ["\\*\\*((?:(?!\\*\\*).)+)\\*\\*"],
"actions": ["find"]
},
{
"name": "goToUrl",
"regex": [
"\\b(?:[Gg]o\\s+to|[Oo]pen|[Nn]avigate\\s+to|[Vv]isit|[Aa]ccess|[Pp]roceed\\s+to|[Ll]aunch)\\b\\s+\\[[^\\]]+\\]\\(\\s*(https?:\\/\\/[^\\s)]+)(?:\\s+\"[^\"]*\")?\\s*\\)"
],
"actions": ["goTo"]
},
{
"name": "screenshotImage",
"regex": [
"!\\[[^\\]]*\\]\\(\\s*([^\\s)]+)(?:\\s+\"[^\"]*\")?\\s*\\)\\s*\\{(?=[^}]*\\.screenshot)[^}]*\\}"
],
"actions": ["screenshot"]
},
{
"name": "typeText",
"regex": ["\\b(?:press|enter|type)\\b\\s+\"([^\"]+)\""],
"actions": ["type"]
},
{
"name": "httpRequestFormat",
"regex": [
"```(?:http)?\\r?\\n([A-Z]+)\\s+([^\\s]+)(?:\\s+HTTP\\/[\\d.]+)?\\r?\\n((?:[^\\s]+:\\s+[^\\s]+\\r?\\n)*)?(?:\\s+([\\s\\S]*?)\\r?\\n+)?```"
],
"actions": [
{
"httpRequest": {
"method": "$1",
"url": "$2",
"request": {
"headers": "$3",
"body": "$4"
}
}
}
]
},
{
"name": "runCode",
"regex": [
"```(bash|python|py|javascript|js)(?![^\\r\\n]*testIgnore)[^\\r\\n]*\\r?\\n([\\s\\S]*?)\\r?\\n```"
],
"actions": [
{
"unsafe": true,
"runCode": {
"language": "$1",
"code": "$2"
}
}
]
}
]
}
]
}
Default markup pattern descriptions
checkHyperlink: Detects standard Markdown links (excluding images) and checks that they return a valid HTTP status code.
- Pattern:
[link text](https://example.com)
- Action: Performs a GET request to verify the link is accessible
clickOnscreenText: Detects action verbs followed by bold text and clicks on that element.
- Pattern:
Click **Button Name**
,Tap **Menu Item**
,Select **Option**
- Action: Clicks on the specified element using its text content
findOnscreenText: Detects any bold text and verifies it exists on the page.
- Pattern:
**Any Bold Text**
- Action: Searches for the text on the current page
goToUrl: Detects navigation instructions with links and opens the URL.
- Pattern:
Go to [Page Name](https://example.com)
,Navigate to [Site](https://example.com)
- Action: Opens the specified URL in the browser
screenshotImage: Detects images with a .screenshot
class or attribute and takes a screenshot.
- Pattern:
{.screenshot}
- Action: Saves a screenshot to the specified path
typeText: Detects typing instructions with quoted text and types the content.
- Pattern:
Type "Hello World"
,Enter "username"
- Action: Types the specified text into the active element
httpRequestFormat: Detects HTTP request code blocks and executes the request.
- Pattern: HTTP request in code blocks with method, URL, headers, and body
- Action: Executes the HTTP request with the specified parameters
runCode: Detects code blocks in supported languages and executes the code.
- Pattern: Code blocks with
bash
,python
,py
,javascript
, orjs
language tags (excluding those marked withtestIgnore
) - Action: Executes the code in the specified language (marked as unsafe)
The regex
property defines the regular expression patterns to match, and the actions
property defines the actions to perform when the pattern is detected. With the default configuration, Doc Detective would take the following Markdown and generate tests automatically:
Markdown:
To get started,
1. Go to [Acme Console](https://console.acme.com).
2. Click **Search**.
3. Type "American Shorthair kittens".
Check out our [documentation](https://docs.example.com) for more information.
{ .screenshot }
Detected tests:
{
"tests": [
{
"steps": [
{
"goTo": "https://console.acme.com"
},
{
"click": "Search"
},
{
"type": "American Shorthair kittens"
},
{
"checkLink": "https://docs.example.com"
},
{
"screenshot": "search-results.png"
}
]
}
]
}
Custom markup patterns
You can extend or override the default patterns by defining custom markup patterns in your configuration:
{
"fileTypes": [
{
"name": "markdown",
"extensions": ["md", "markdown", "mdx"],
"markup": [
{
"name": "customAction",
"regex": ["\\b(?:custom)\\b\\s+\\*\\*(.+?)\\*\\*"],
"actions": [
{
"find": {
"selector": "aria/$1",
"timeout": 10000
}
}
]
}
]
}
]
}
Other file types
Doc Detective also includes default configurations for HTML and AsciiDoc files, though these only include inline statement patterns for test definitions and don't include markup patterns for detected tests:
HTML files (.html
, .htm
):
- Uses HTML comment syntax for inline test statements
- Example:
<!-- test { "testId": "my-test" } -->
AsciiDoc files (.adoc
, .asciidoc
, .asc
):
- Uses AsciiDoc comment syntax for inline test statements
- Example:
// (test { "testId": "my-test" })
To add detected test functionality to HTML or AsciiDoc files, you would need to define custom markup patterns in your configuration similar to the Markdown examples above.
Default actions
If you only need to perform simple steps, you can define actions using a shorthand of only specifying the action name. Doc Detective uses default actions, substituting the first capture group (or if there are no capture groups, the entire match) from the regex pattern into the most common location for the action. In the above example, the config generates a goTo
action for every Markdown hyperlink preceded by a navigation verb.
The default actions are as follows:
checkLink
Check that the match returns a valid status code.
{ "checkLink": "$1" }
click
Click or tap the match.
{ "click": "$1" }
goTo
Open the match as a URL in a browser.
{ "goTo": "$1" }
find
Find an element on the current page that has an ARIA label that equals the match.
{ "find": "$1" }
screenshot
Save a screenshot to a path equalling the match.
{ "screenshot": "$1" }
type
Type the match into the current page.
{ "type": "$1" }
httpRequest
Make an GET request to the match.
{ "httpRequest": "$1" }
runShell
Run the match as a shell command.
{ "runShell": "$1" }
record
Start recording a video to a path equalling the match.
{ "record": "$1" }
stopRecord
Stop recording a video.
{ "stopRecord": true }
wait
Wait for the specified duration.
{ "wait": "$1" }
loadVariables
Load environment variables from an .env
file, where the path is the match.
{ "loadVariables": "$1" }
Run tests
Doc Detective's doc-detective
command runs your tests. Input files are read from your config's input
property, but you can also specify input files directly in the command with the --input
flag.
This example runs all test specs in your config's input
and runTest.input
parameters:
npx doc-detective
This example runs all test specs in a file named doc-content.md
in the samples
directory:
npx doc-detective --input ./samples/doc-content.md
Remotely hosted tests
You can run tests hosted remotely by specifying the URL of the test file with the --input
argument. For example, to run tests from a file hosted at https://doc-detective.com/sample.spec.json
, run the following command:
npx doc-detective --input https://doc-detective.com/sample.spec.json
These tests run the same way as local tests, but Doc Detective fetches the test file from the specified URL and stores it in a temporary directory. The URL must be accessible to the machine running the tests.
Read the results
Doc Detective outputs test results to a testResults-<timestamp>.json
file in your output
directory. You can also specify your output directory with the --output
flag:
npx doc-detective --input ./samples/doc-content.md --output ./samples/