@digital-commons-official/codeceptjs-storyboard

中文文档
3.2.1发布于 2026/11/10EUPL-1.2TypeScriptESM + CJS近 30 天下载 2910

Storyboard plugin for CodeceptJS: one Gherkin sentence = one card = one pixel baseline, with Markdown or SVG reports

原始使用文档
文档目录18 节
  1. Installation 📦
  2. Tested versions
  3. Public API and compatibility
  4. Configuration ⚙️
  5. Choose one format
  6. Read Markdown on a branch or merge request
  7. Markdown layout
  8. Replay commands
  9. Colours and fonts
  10. Usage 🚀
  11. The .feature is the single human-authored source
  12. The step file drives and captures
  13. PNG or WebP frames
  14. Gherkin languages and examples
  15. What you get
  16. API 📚
  17. Development 🛠️
  18. Licence 📜

🎬 codeceptjs-storyboard

pipeline status

A CodeceptJS plugin that turns one Gherkin scenario into one human-readable storyboard, straight from the real screenshots the test captures. Markdown is the default; select SVG explicitly when you want a self-contained picture.

ONE Gherkin sentence = ONE card = ONE pixel baseline, asserted inside its step at tolerance: 0: a visual regression fails on the exact sentence whose image drifted. When the scenario ends, Markdown shows screenshots side by side with readable captions, notes and copyable commands. It links the original screenshots instead of embedding their bytes, so reviewers can open the file directly in GitLab. SVG embeds the screenshots and retains selectable text around them (Chromium/Safari).

Installation 📦

npm install --save-dev codeceptjs playwright @digital-commons-official/codeceptjs-storyboard @digital-commons-official/codeceptjs-visual-helper
npx playwright install chromium

Requires Node.js >= 22.19.0, CodeceptJS ^4.2.0 and @digital-commons-official/codeceptjs-visual-helper >= 1.3.0. The plugin captures and asserts through I.takeScreenshot, I.captureScreenshot and I.assertVisualMatch.

VisualHelper is required: enable it in CodeceptJS as shown below. Keeping it as a peer dependency lets the plugin use your project's helper and CodeceptJS installation.

Tested versions

The browser suite installs the actual packed package into six fresh projects:

Node.jsCodeceptJSVisualHelper
22.23.4, 24.22.1, 26.12.14.2.01.3.0
22.23.4, 24.22.1, 26.12.14.2.02.0.3

Each project imports its own four packages, passes npm audit, records one English journey and three French Rule cases, then reruns with strict pixel comparison. All fourteen baseline hashes must stay unchanged and match across the six combinations. Each project also runs the default Markdown format against those same hashes and checks all four Markdown gallery links.

Node 18 is rejected with --engine-strict; CodeceptJS 4.0 is rejected with --strict-peer-deps. Older CodeceptJS 4.0 consumers also fail the security audit. The declared ranges allow later compatible versions; the table states the exact versions exercised in CI. Use the same Playwright browser and fonts when comparing pictures across machines.

These installation tests use npm pack and real npm commands. They do not authenticate a publication to the registry; only a successful release job provides that separate proof. Releases use GitLab OIDC authentication without a stored npm token and run only on the protected default branch. npm provenance is explicitly disabled because npm rejects attestations from self-hosted runners, so these releases do not include an npm provenance attestation.

Public API and compatibility

The package root exports the CodeceptJS plugin factory and these functions. Their signatures are defined in src/index.d.ts.

FunctionsContract
storyboardStepRegister a literal sentence and its optional note/copy annotation.
capturePageFrame, captureElementFrame, frameOutputPathCapture a real viewport or element and return its frame path.
addStoryboardFrame, assertOrUpdateBaselineAssert pixels strictly; only TASK_E2E_UPDATE_BASELINES=1 outside CI records baselines.
begin, baseDir, panel, frame, annotate, panelsManage a scenario's cards; frame attaches an image without asserting it.
parseScenarioLines, renderRead the original Gherkin sentences and render Markdown or SVG.
tryToRe-export the CodeceptJS effect for an optional action.

The supported plugin options are format, theme, markdown and replayCommand; CodeceptJS owns require and enabled. From 1.0.0, compatible releases preserve this public API and the documented baseline recording behaviour. Removing a public function, changing its required arguments or raising a supported minimum requires a major release. Internal modules under src/ are implementation details; use the package root.

The parser follows Cucumber's Gherkin dialects. Feature and Rule backgrounds, Scenario Outlines and Examples, inherited tags, repeated titles, data tables and doc strings are supported. Real browser journeys cover English, French and German; parser tests cover other dialects, including joined keywords. Tables and doc strings are step arguments, not extra cards. A filtered run with no matching scenario fails. Future dependency versions still need the same compatibility checks; the matrix above identifies the versions verified.

Configuration ⚙️

Register the plugin next to the visual helper in codecept.conf.js, and point Gherkin at your step files:

exports.config = {
  output: './_output',
  noGlobals: true,
  helpers: {
    Playwright: {
      browser: 'chromium',
      url: 'http://localhost:8080',
      show: false,
      windowSize: '1280x720'
    },
    VisualHelper: {
      require: require.resolve('@digital-commons-official/codeceptjs-visual-helper'),
      baselineDir: './screenshots/base/',
      diffDir: './screenshots/diff/',
      actualDir: './_output/',
      tolerance: 0,
      captureBaseline: false
    }
  },
  gherkin: {
    features: './features/**/*.feature',
    steps: ['./steps/first-run.js']
  },
  plugins: {
    storyboard: {
      require: '@digital-commons-official/codeceptjs-storyboard',
      enabled: true
    }
  }
}

Choose one format

Omit format or set format: 'markdown' for Markdown. Set format: 'svg' for SVG:

storyboard: {
  require: '@digital-commons-official/codeceptjs-storyboard',
  enabled: true,
  format: 'svg'
}

Exactly one format is generated per run. Arrays, both, md, null and other values are rejected. Markdown is a breaking default change: add format: 'svg' to retain the earlier SVG files and HTML gallery. Existing standalone render('board.svg', options) calls still render SVG.

Paths are derived from the feature file location. Frames land in _output/storyboard-frames/ and baselines in screenshots/base/<feature-dir>/<scenario-tag>/.

OutputMarkdown (default)SVG
Current scenario_output/<feature-dir>/<scenario-tag>.md_output/<feature-dir>/<scenario-tag>.svg
Reviewed scenariostoryboards/<feature-dir>/<scenario-tag>.mdstoryboards/<feature-dir>/<scenario-tag>.svg
Current-run gallery_output/index.md_output/index.html
Reviewed gallerystoryboards/index.mdstoryboards/index.html

A scenario without captured frames produces no storyboard, so plain Gherkin tests are left untouched.

When the run ends, open the selected gallery to browse its storyboards. It groups scenarios by feature directory, puts failed groups and scenarios first, and shows the failed sentence with its replay command. Links open the selected format.

A filtered run lists only the scenarios it ran. In baseline-update mode, the reviewed gallery lists the passing scenarios from that update; failed scenarios never replace reviewed storyboards. Run the full suite in update mode to rebuild the complete reviewed gallery. Files from earlier runs or another format are not deleted or added to the current gallery.

Read Markdown on a branch or merge request

Commit the generated files under storyboards/ together with their reviewed screenshots under screenshots/base/. Open the Markdown file on the branch being reviewed. Relative image links use that same revision; after merging, opening the file on the target branch uses the merged images. No branch name, GitLab hostname or token is stored in the document. A URL to a deleted source branch is not redirected automatically.

For example, storyboards/login/sign-in.md can link to ../../screenshots/base/login/sign-in/form.png. The paths also work in a local Markdown viewer with the repository layout intact. This applies to repository files; pasting their contents into an MR description uses a different link context.

Runtime Markdown references actual captures and, for a failure, the expected/diff/actual images. Keep _output/ and screenshots/ in their original relative layout when downloading reports. A Markdown file alone does not include its images. SVG is the self-contained option. Repository rendering does not imply that GitLab's CI artifact viewer previews Markdown.

Markdown keeps chapters, sentence order, annotations, multilingual keywords and failure information. The page title is the scenario, with the feature on the line below, named with the keyword of its feature file. The report then gives its recorded outcome and frame/step counts, followed by links to chapters, the result and replay information. A standalone render without an explicit outcome says "Outcome not recorded"; it does not infer success from the absence of a visual failure.

Each chapter starts with a plain Markdown heading. Screenshots sit in two equal-width columns by default. Each card keeps its title, image, note and copyable command together. Each pair has its own table so GitLab does not put an entire chapter inside one scrolling region. A one-line command shows under its note as inline code, which wraps, so both columns keep their width; a command on several lines shows as an open code block. Replay and source details fold at the end. A failed comparison keeps Expected / Diff / Actual and unavailable-image labels visible, regardless of the details setting.

Markdown layout

Configure presentation directly on the plugin; no CSS file is needed:

storyboard: {
  require: '@digital-commons-official/codeceptjs-storyboard',
  enabled: true,
  markdown: {
    columns: 2,
    tableOfContents: true,
    technicalDetails: 'collapsed'
  }
}

The example shows the defaults. Set columns: 1 for full-width cards, especially when reading on narrow screens. GitLab tables do not automatically stack like a responsive HTML grid. Set technicalDetails: 'expanded' to open the replay and source details, or tableOfContents: false to omit navigation. Neither option removes evidence or notes.

Unsupported options and invalid layout values raise a clear error before the plugin registers listeners or the standalone renderer writes artifacts.

GitLab controls the page background, fonts and native alert colours through the reader's preferences. Essential information remains text even when images cannot load. The renderer never recolours screenshots, loads external assets, or applies the SVG-only theme option to Markdown. Explicit format: 'svg' keeps its existing theme behaviour and ignores Markdown presentation settings.

Standalone callers can use render('report.md', { markdown: { columns: 1 }, outcome: 'passed' }). Only provide outcome when it is known; failure evidence always takes precedence over a passed value.

Replay commands

The gallery and storyboard default to npx codeceptjs run --steps --grep "{tag}". {tag} becomes the scenario's last tag. This command works in a standalone CodeceptJS project with a local installation and its default configuration file.

Toolbox projects can set their Task command on the plugin:

storyboard: {
  require: '@digital-commons-official/codeceptjs-storyboard',
  enabled: true,
  replayCommand: 'task test -- --grep "{tag}"'
}

For another configuration file, include its --config argument in the template. Use a unique scenario tag so the command selects the intended journey.

Colours and fonts

In SVG mode, set theme on the storyboard plugin to an object, a CSS file path, or an HTTP(S) URL:

storyboard: {
  require: '@digital-commons-official/codeceptjs-storyboard',
  enabled: true,
  format: 'svg',
  theme: './storyboard.css'
  // Or: theme: 'https://example.org/storyboard.css'
  // Or: theme: { bg: '#f6f8fb', text: '#192b3d', sans: 'Georgia, serif' }
}

Relative paths start at the directory containing codecept.conf.js. The plugin loads the theme once per run, before the first scenario's steps, and embeds its values in every SVG. Remote requests time out after five seconds. A missing, unreachable or invalid theme emits a warning and uses the default dark theme.

:root {
  --sb-bg: #f6f8fb;
  --sb-card: #ffffff;
  --sb-slot: #edf2f8;
  --sb-text: #192b3d;
  --sb-dim: #42576b;
  --sb-accent: #175fa4;
  --sb-code-bg: #e7eef7;
  --sb-given: #356b16;
  --sb-when: #175fa4;
  --sb-then: #7b3990;
  --sb-font-sans: Georgia, serif;
}

Supported object keys are bg, card, slot, text, dim, accent, badge, codeBg, given, when, then, fail, sans and mono. CSS uses --sb-<key>, except codeBg becomes --sb-code-bg, and the fonts use --sb-font-sans and --sb-font-mono. Omitted values keep their defaults. Colours accept hex, named colours, rgb() and hsl() values; fonts accept installed font family names and fallback lists.

Only these properties are read. Imports, external fonts and arbitrary CSS rules are not embedded. The SVG works offline; install the same fonts on machines where matching typography matters. Themes change the labels and cards around captured frames; the screenshot pixels stay unchanged.

Usage 🚀

The .feature is the single human-authored source

Attach structured comments to the sentence just below them. The feature file carries the story, the step file only drives and captures:

  • # Chapter: Title opens a section before that card (a full-width band in SVG).
  • # Note: text is the card's explanation: what to look at, why it matters. Repeat the line to stack paragraphs.
  • # Copy: command is the exact copyable command shown with the card.

The scenario's LAST tag names the baseline directory and the replay command printed on the board.

@e2e @first-run
Feature: A developer opens their new project
  Scenario: The project home shows the framework
    # Chapter: The empty project
    # Note: The project as GitLab shows it, before anything is installed.
    # Copy: http://gitlab/<user>/<project>
    Given a fresh project with only a README on its main branch

The step file drives and captures

/* global inject Given */
const { I } = inject()
const storyboard = require('@digital-commons-official/codeceptjs-storyboard')

storyboard.storyboardStep(Given, 'a fresh project with only a README on its main branch', async () => {
  await I.amOnPage('/my/project')
  await storyboard.addStoryboardFrame(I, await storyboard.capturePageFrame(I, 'project-home'))
})
  • storyboardStep(register, sentence, fn) registers the step and escapes cucumber-expression metacharacters, so CI/CD or (y/N) in a sentence never breaks the match. Cards open automatically for every sentence.
  • capturePageFrame(I, name) captures the full viewport; captureElementFrame(I, name, selector) crops the frame to one element, so a short verdict yields a short card.
  • addStoryboardFrame(I, png) refuses a blank frame, attaches the frame to the open card and asserts it against its own baseline at once. On drift the error names the frame, the pixel diff, the failure storyboard and the command that regenerates the baseline.
  • annotate({ note, copy }) overrides the feature comments for a value only known at runtime.

PNG or WebP frames

Frames keep the format the VisualHelper writes: PNG up to its version 2, lossless WebP by default from its version 3 (imageFormat). Baselines, the Markdown links and the SVG images follow the frame. A WebP frame whose reviewed baseline is still a PNG is refused, because the helper would record it as a new baseline and compare nothing. Convert the reviewed baselines once, with the same pixels:

npx -y -p @digital-commons-official/codeceptjs-storyboard codeceptjs-storyboard-webp tests/e2e/screenshots/base

Gherkin languages and examples

Set # language: fr (or another Cucumber dialect) on the first line of a feature file. Without this header, Gherkin uses English. Storyboards keep the source keywords, accents and scenario title, including keywords joined directly to the sentence. Register the translated sentences in your CodeceptJS step definitions.

Background steps and outline examples appear in execution order. Each example row gets its own storyboard and baseline directory, with an -example-<line> suffix. Repeated sentences keep their own annotations.

# Chapter, # Note and # Copy remain the annotation keys in every language; outline values are substituted in them too. Text inside doc strings and data tables does not become an extra card or annotation.

Invalid syntax or an unknown dialect produces an error naming the feature file. The enabled plugin completes CodeceptJS's Gherkin loader for Rule scenarios, including localized keywords such as Règle. The feature background runs before each case; a rule background runs only for cases in that rule. Outline examples remain separate tests and rule tags can be selected with --grep. Repeated scenario titles in different rules keep their own source annotations. An empty selection fails clearly instead of succeeding with zero tests.

The multilingual storyboard runs English, French and German examples and shows a real visual regression on a French sentence.

The rule storyboard executes two French outline examples and a second rule, checks both backgrounds and the tag filter, and proves the exact sentence of a deliberate visual regression.

What you get

  • On every run the selected storyboard is written under _output/<feature-dir>/<scenario-tag>.md or .svg.
  • In SVG, cards sit two per row, 708 px each. A frame still 1000 px wide or more once fitted to the 1100 px height limit, such as a web page 1440 px wide, takes a full 1440 px row and shows at its real size. A narrower strip stays in its half of a row, shrunk to fit. A card alone on its row is centred in it.
  • On a failed run the storyboard shows the expected image, the changed pixels and the actual image with their paths, then lists the sentences the run never reached. SVG presents the comparison as a red band; Markdown uses a labelled table.
  • In baseline-update mode the plugin asserts first and rewrites a baseline only when its assert fails, then rebuilds the reviewed storyboard under storyboards/ from the reviewed baselines:
TASK_E2E_UPDATE_BASELINES=1 npx codeceptjs run

Only the exact value 1 enables recording. An empty value, 0 or false keeps strict comparison. Every baseline written in recording mode must be inspected by a human, which is why that mode throws when CI is set.

API 📚

FunctionPurpose
storyboardStep(register, sentence, fn)Register a sentence literally through Given, When or Then
capturePageFrame(I, name)Full-viewport frame, returns the PNG or WebP path
captureElementFrame(I, name, selector)Element-cropped frame, returns the PNG or WebP path
addStoryboardFrame(I, png)Attach the frame to the open card and assert it at tolerance: 0
annotate({ note, copy })Runtime override of the open card's note and copyable command
assertOrUpdateBaseline(I, name)The assert-or-rewrite primitive addStoryboardFrame relies on
render(outFile, options)Write Markdown for .md or SVG for .svg; theme applies only to SVG
convertBaselinesToWebp(dir)Convert reviewed PNG baselines to lossless WebP with the same pixels
parseScenarioLines(featureFile, title)Every sentence of a scenario with its # Chapter / # Note / # Copy
begin, panel, frame, panelsThe board primitives the plugin drives (useful for standalone rendering)

Type definitions ship in src/index.d.ts. Standalone rendering uses the output extension independently of plugin configuration and rejects other extensions.

Development 🛠️

task build                              # install dependencies + build the e2e runner image
task test                               # unit tests, then the e2e storyboard suite
task project:test:storyboard            # unit tests only (vitest)
task project:test:storyboard:e2e        # e2e storyboard suite only, inside the pinned Playwright runner
task project:test:storyboard:markdown   # render the four selected review journeys as Markdown
task project:test:storyboard:svg        # render the remaining review journeys as SVG
task project:test:storyboard:e2e -- --grep "@storyboard-happy-path"
TASK_E2E_UPDATE_BASELINES=1 task project:test:storyboard:svg
TASK_E2E_UPDATE_BASELINES=1 task project:test:storyboard:markdown
task code                               # linters (MegaLinter)

The e2e suite is the plugin's own dogfood: every scenario is a storyboard rendered by the plugin under test, committed under tests/e2e/storyboards/.

Open the Markdown gallery on the merge request branch to review installation, Gherkin rules, compatibility and the Markdown consumer with relative screenshot links. Regenerate these reviewed Markdown files with TASK_E2E_UPDATE_BASELINES=1 task project:test:storyboard:markdown. The main suite explicitly selects SVG to retain its existing SVG regression coverage. Use both recording commands above to preserve the reviewed format selection, then inspect the generated boards. The SVG recording task excludes exactly those four Markdown journeys.

The installation storyboard packs the current source, installs the tarball into a fresh project, and runs the README configuration with explicit SVG selection. The Markdown consumer journey exercises the omitted-format default separately. It checks CodeceptJS 4.2.0, Playwright 1.63.0 and VisualHelper 1.3.5 in Chromium. It opens the generated index.html and SVG, repeats the run with strict baselines, then proves that a changed page fails on its exact sentence.

The consumer manifest pins those tools and overrides vulnerable transitive dependencies. Its lockfile makes the test repeatable. The separate version matrix verifies the six combinations listed above. Complete installation and run logs are kept in tests/e2e/_output/consumer-install.log and tests/e2e/_output/matrix/.

The clean-consumer test also copies the replay command from the generated gallery and executes it unchanged, then checks that every strict baseline hash is intact.

Licence 📜

EUPL-1.2

版本与发布记录

@digital-commons-official/codeceptjs-storyboard 共发布 32 个版本,首次发布于 2026/10/04;过去 12 个月发布了 32 个版本。

版本发布日期距今
3.2.1latest2026/11/102 天前
3.2.02026/11/102 天前
3.1.12026/11/047 天前
3.1.02026/11/047 天前
3.0.02026/10/2815 天前
2.0.42026/10/2815 天前

关于 @digital-commons-official/codeceptjs-storyboard 的常见问题

@digital-commons-official/codeceptjs-storyboard 是什么?

Storyboard plugin for CodeceptJS: one Gherkin sentence = one card = one pixel baseline, with Markdown or SVG reports

如何安装 @digital-commons-official/codeceptjs-storyboard?

在项目目录运行 npm install @digital-commons-official/codeceptjs-storyboard,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:codeceptjs(^4.2.0)、@digital-commons-official/codeceptjs-visual-helper(>=1.3.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 codeceptjs-storyboard-webp,可以用 npx codeceptjs-storyboard-webp 直接运行。

@digital-commons-official/codeceptjs-storyboard 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@digital-commons-official/codeceptjs-storyboard 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@digital-commons-official/codeceptjs-storyboard 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.19.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@digital-commons-official/codeceptjs-storyboard 可以商用吗?

@digital-commons-official/codeceptjs-storyboard 使用 EUPL-1.2 许可。声明的许可为 EUPL-1.2,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@digital-commons-official/codeceptjs-storyboard 的下载量有多少?

根据 npm 官方下载统计,@digital-commons-official/codeceptjs-storyboard 在 2026/10/12 – 2026/11/10 这 30 天内被下载 2,910 次,日均约 97 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@digital-commons-official/codeceptjs-storyboard 还在维护吗?

最新版本 3.2.1 发布于 2026/11/10(2 天前);至今共发布 32 个版本,其中过去 12 个月发布了 32 个;首次发布于 2026/10/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。