From 88ec5b65074b9fa1ab40b7a8b5591bd418377660 Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Sat, 7 Sep 2024 17:36:47 +0300 Subject: [PATCH 1/5] Add messages implementation for python --- .github/workflows/release-pypi.yaml | 31 + .github/workflows/test-codegen.yml | 5 + .github/workflows/test-python.yml | 82 ++ CHANGELOG.md | 3 + Makefile | 2 +- python/.gitignore | 55 ++ python/.pre-commit-config.yaml | 48 ++ python/Makefile | 35 + python/README.md | 3 + python/pyproject.toml | 136 ++++ python/pytest.ini | 2 + python/src/cucumber_messages/__init__.py | 4 + python/src/cucumber_messages/messages.py | 755 ++++++++++++++++++ python/src/message_samples/__init__.py | 0 .../attachments/attachments.feature | 44 + .../attachments/attachments.feature.ndjson | 87 ++ .../attachments/attachments.feature.ts | 58 ++ .../message_samples/attachments/cucumber.png | Bin 0 -> 1739 bytes .../message_samples/attachments/document.pdf | Bin 0 -> 10061 bytes .../src/message_samples/cdata/cdata.feature | 6 + .../cdata/cdata.feature.ndjson | 12 + .../message_samples/cdata/cdata.feature.ts | 6 + .../data-tables/data-tables.feature | 12 + .../data-tables/data-tables.feature.ndjson | 15 + .../data-tables/data-tables.feature.ts | 11 + .../examples-tables/examples-tables.feature | 28 + .../examples-tables.feature.ndjson | 68 ++ .../examples-tables.feature.ts | 14 + python/src/message_samples/hooks/cucumber.svg | 7 + .../src/message_samples/hooks/hooks.feature | 20 + .../hooks/hooks.feature.ndjson | 77 ++ .../message_samples/hooks/hooks.feature.ts | 30 + .../markdown/markdown.feature.md | 46 ++ .../markdown/markdown.feature.md.ndjson | 35 + .../markdown/markdown.feature.md.ts | 25 + .../message_samples/minimal/minimal.feature | 10 + .../minimal/minimal.feature.ndjson | 12 + .../minimal/minimal.feature.ts | 6 + .../parameter-types/parameter-types.feature | 9 + .../parameter-types.feature.ndjson | 13 + .../parameter-types.feature.ts | 20 + .../message_samples/pending/pending.feature | 19 + .../pending/pending.feature.ndjson | 30 + .../pending/pending.feature.ts | 13 + .../message_samples/retry/retry.arguments.txt | 1 + .../src/message_samples/retry/retry.feature | 22 + .../retry/retry.feature.ndjson | 59 ++ .../message_samples/retry/retry.feature.ts | 25 + .../src/message_samples/rules/rules.feature | 27 + .../rules/rules.feature.ndjson | 45 ++ .../message_samples/rules/rules.feature.ts | 33 + .../message_samples/skipped/skipped.feature | 19 + .../skipped/skipped.feature.ndjson | 33 + .../skipped/skipped.feature.ts | 17 + .../stack-traces/stack-traces.feature | 11 + .../stack-traces/stack-traces.feature.ndjson | 12 + .../stack-traces/stack-traces.feature.ts | 5 + .../undefined/undefined.feature | 17 + .../undefined/undefined.feature.ndjson | 29 + .../undefined/undefined.feature.ts | 9 + .../unknown-parameter-type.feature | 6 + .../unknown-parameter-type.feature.ndjson | 12 + .../unknown-parameter-type.feature.ts | 6 + python/tests/__init__.py | 0 python/tests/conftest.py | 0 python/tests/test_model_load.py | 28 + 66 files changed, 2309 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release-pypi.yaml create mode 100644 .github/workflows/test-python.yml create mode 100644 python/.gitignore create mode 100644 python/.pre-commit-config.yaml create mode 100644 python/Makefile create mode 100644 python/README.md create mode 100644 python/pyproject.toml create mode 100644 python/pytest.ini create mode 100644 python/src/cucumber_messages/__init__.py create mode 100644 python/src/cucumber_messages/messages.py create mode 100644 python/src/message_samples/__init__.py create mode 100644 python/src/message_samples/attachments/attachments.feature create mode 100644 python/src/message_samples/attachments/attachments.feature.ndjson create mode 100644 python/src/message_samples/attachments/attachments.feature.ts create mode 100644 python/src/message_samples/attachments/cucumber.png create mode 100644 python/src/message_samples/attachments/document.pdf create mode 100644 python/src/message_samples/cdata/cdata.feature create mode 100644 python/src/message_samples/cdata/cdata.feature.ndjson create mode 100644 python/src/message_samples/cdata/cdata.feature.ts create mode 100644 python/src/message_samples/data-tables/data-tables.feature create mode 100644 python/src/message_samples/data-tables/data-tables.feature.ndjson create mode 100644 python/src/message_samples/data-tables/data-tables.feature.ts create mode 100644 python/src/message_samples/examples-tables/examples-tables.feature create mode 100644 python/src/message_samples/examples-tables/examples-tables.feature.ndjson create mode 100644 python/src/message_samples/examples-tables/examples-tables.feature.ts create mode 100644 python/src/message_samples/hooks/cucumber.svg create mode 100644 python/src/message_samples/hooks/hooks.feature create mode 100644 python/src/message_samples/hooks/hooks.feature.ndjson create mode 100644 python/src/message_samples/hooks/hooks.feature.ts create mode 100644 python/src/message_samples/markdown/markdown.feature.md create mode 100644 python/src/message_samples/markdown/markdown.feature.md.ndjson create mode 100644 python/src/message_samples/markdown/markdown.feature.md.ts create mode 100644 python/src/message_samples/minimal/minimal.feature create mode 100644 python/src/message_samples/minimal/minimal.feature.ndjson create mode 100644 python/src/message_samples/minimal/minimal.feature.ts create mode 100644 python/src/message_samples/parameter-types/parameter-types.feature create mode 100644 python/src/message_samples/parameter-types/parameter-types.feature.ndjson create mode 100644 python/src/message_samples/parameter-types/parameter-types.feature.ts create mode 100644 python/src/message_samples/pending/pending.feature create mode 100644 python/src/message_samples/pending/pending.feature.ndjson create mode 100644 python/src/message_samples/pending/pending.feature.ts create mode 100644 python/src/message_samples/retry/retry.arguments.txt create mode 100644 python/src/message_samples/retry/retry.feature create mode 100644 python/src/message_samples/retry/retry.feature.ndjson create mode 100644 python/src/message_samples/retry/retry.feature.ts create mode 100644 python/src/message_samples/rules/rules.feature create mode 100644 python/src/message_samples/rules/rules.feature.ndjson create mode 100644 python/src/message_samples/rules/rules.feature.ts create mode 100644 python/src/message_samples/skipped/skipped.feature create mode 100644 python/src/message_samples/skipped/skipped.feature.ndjson create mode 100644 python/src/message_samples/skipped/skipped.feature.ts create mode 100644 python/src/message_samples/stack-traces/stack-traces.feature create mode 100644 python/src/message_samples/stack-traces/stack-traces.feature.ndjson create mode 100644 python/src/message_samples/stack-traces/stack-traces.feature.ts create mode 100644 python/src/message_samples/undefined/undefined.feature create mode 100644 python/src/message_samples/undefined/undefined.feature.ndjson create mode 100644 python/src/message_samples/undefined/undefined.feature.ts create mode 100644 python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature create mode 100644 python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson create mode 100644 python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts create mode 100644 python/tests/__init__.py create mode 100644 python/tests/conftest.py create mode 100644 python/tests/test_model_load.py diff --git a/.github/workflows/release-pypi.yaml b/.github/workflows/release-pypi.yaml new file mode 100644 index 00000000..85692a2a --- /dev/null +++ b/.github/workflows/release-pypi.yaml @@ -0,0 +1,31 @@ +name: Release Python + +on: + push: + branches: [release/*] + +jobs: + release: + name: Release + runs-on: ubuntu-latest + environment: Release + permissions: + id-token: write + defaults: + run: + working-directory: python + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Show Python version + run: python --version + + - uses: cucumber/action-publish-pypi@v3.0.0 + with: + working-directory: "python" diff --git a/.github/workflows/test-codegen.yml b/.github/workflows/test-codegen.yml index 463c12e0..74f2ac8b 100644 --- a/.github/workflows/test-codegen.yml +++ b/.github/workflows/test-codegen.yml @@ -31,6 +31,11 @@ jobs: with: ruby-version: '3.1' + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: generate code for all languages run: | make clean-all diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml new file mode 100644 index 00000000..82f32e48 --- /dev/null +++ b/.github/workflows/test-python.yml @@ -0,0 +1,82 @@ +--- +name: test-python + +on: # yamllint disable-line rule:truthy + push: + branches: + - main + - renovate/** + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + build: + + runs-on: ${{ matrix.os }} + timeout-minutes: 20 + strategy: + matrix: + python-version: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "pypy3.8" + - "pypy3.9" + - "pypy3.10" + os: + - ubuntu-latest + - windows-latest + - macos-latest + exclude: + - python-version: "pypy3.8" + os: macos-latest + - python-version: "pypy3.9" + os: macos-latest + - python-version: "pypy3.10" + os: macos-latest + - python-version: "3.8" + os: macos-latest + - python-version: "3.9" + os: macos-latest + - python-version: "3.10" + os: macos-latest + - python-version: "3.11" + os: macos-latest + - python-version: "pypy3.8" + os: windows-latest + - python-version: "pypy3.9" + os: windows-latest + - python-version: "pypy3.10" + os: windows-latest + - python-version: "3.8" + os: windows-latest + - python-version: "3.9" + os: windows-latest + - python-version: "3.10" + os: windows-latest + - python-version: "3.11" + os: windows-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U setuptools + pip install tox tox-gh-actions codecov + - name: Test with tox + working-directory: ./python + run: | + tox + - name: Gather codecov report + working-directory: ./python + run: | + codecov diff --git a/CHANGELOG.md b/CHANGELOG.md index 03012e6a..24e6e597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - [Go] Switch to Google's UUID module ([#251](https://github.com/cucumber/messages/pull/251)) +### Added +- [Python] Added Python implementation ([#165](https://github.com/cucumber/messages/pull/165)) + ## [26.0.0] - 2024-08-15 ### Added - [Dotnet] Added support classes aligned with what is provided for the Java implementation ([#233](https://github.com/cucumber/messages/pull/233) [clrudolphi](https://github.com/clrudolphi)) diff --git a/Makefile b/Makefile index a540e214..0e58a855 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ schemas = \ ./jsonschema/UndefinedParameterType.json \ ./jsonschema/Envelope.json -languages = cpp go java javascript perl php ruby dotnet +languages = cpp dotnet go java javascript perl php python ruby .DEFAULT_GOAL = help diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 00000000..563dcc08 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1,55 @@ +*.rej +*.py[cod] +/.env +*.orig +**/__pycache__ + +# C extensions +*.so + +# Packages +*.egg +*.egg-info +dist +build +_build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +lib +lib64 + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject +.pytest_cache +.ropeproject + +# Sublime +/*.sublime-* + +#PyCharm +/.idea + +# virtualenv +/.Python +/lib +/include +/share +/local diff --git a/python/.pre-commit-config.yaml b/python/.pre-commit-config.yaml new file mode 100644 index 00000000..d9cd8306 --- /dev/null +++ b/python/.pre-commit-config.yaml @@ -0,0 +1,48 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +--- +repos: + - repo: https://github.com/psf/black + rev: 24.8.0 + hooks: + - id: black + args: + - "python/src" + - "python/tests" + - repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + name: isort (python) + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + - id: check-toml + - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.14.0 + hooks: + - id: pretty-format-toml + args: [--autofix] + - repo: https://github.com/asottile/pyupgrade + rev: v3.17.0 + hooks: + - id: pyupgrade + args: ["--py38-plus"] + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.11.2 + hooks: + - id: mypy + additional_dependencies: [types-setuptools, types-certifi] + - repo: https://github.com/tox-dev/tox-ini-fmt + rev: "1.3.2" + hooks: + - id: tox-ini-fmt + - repo: https://github.com/adrienverge/yamllint.git + rev: v1.35.1 + hooks: + - id: yamllint + args: [--format, parsable, --strict] diff --git a/python/Makefile b/python/Makefile new file mode 100644 index 00000000..75715a3c --- /dev/null +++ b/python/Makefile @@ -0,0 +1,35 @@ +schemas = $(shell find ../jsonschema -name "*.json") + +.DEFAULT_GOAL = help + +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +HERE := $(dir $(MKFILE_PATH)) + +help: ## Show this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \n\nWhere is one of:\n"} /^[$$()% a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +generate: require install-deps + datamodel-codegen \ + --output-model-type "pydantic_v2.BaseModel" \ + --input $(HERE)../jsonschema/Envelope.json \ + --output $(HERE)src/cucumber_messages/messages.py \ + --use-generic-container-types \ + --allow-extra-fields \ + --allow-population-by-field-name \ + --snake-case-field \ + --input-file-type=jsonschema \ + --class-name Envelope \ + --use-double-quotes \ + --use-union-operator \ + --disable-timestamp \ + --target-python-version=3.8 + +require: ## Check requirements for the code generation (python is required) + @python --version >/dev/null 2>&1 || (echo "ERROR: python is required."; exit 1) + +clean: ## Remove automatically generated files and related artifacts + rm -rf $(HERE)src/_messages.py + +install-deps: ## Install generation dependencies + python -m ensurepip --upgrade + pip install $(HERE)[generation] diff --git a/python/README.md b/python/README.md new file mode 100644 index 00000000..0a7e6d51 --- /dev/null +++ b/python/README.md @@ -0,0 +1,3 @@ +# Messages + +Cucumber Messages for Python https://github.com/cucumber/messages diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 00000000..473cc275 --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,136 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = ["setuptools>=61.0", "wheel"] + +[project] +authors = [ + {name = "Cucumber Limited", email = "cukes@googlegroups.com"} +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X", + "Topic :: Software Development :: Testing", + "Topic :: Utilities", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12" +] +dependencies = [ + "eval_type_backport;python_version<'3.10.0'", + "pydantic>=2.0.3" +] +description = "Cucumber Messages is a message protocol for representing results and other information from Cucumber. " +license = {text = "MIT"} +maintainers = [ + {name = "Konstantin Goloveshko", email = "kostya.goloveshko@gmail.com"} +] +name = "cucumber-messages" +readme = {file = "README.md", content-type = "text/markdown"} +requires-python = ">=3.8" +urls = {Repository = "https://github.com/cucumber/messages"} +version = "0.1.0" + +[project.entry-points] + +[project.optional-dependencies] +generation = [ + "datamodel-code-generator" +] +test = [ + # local + "cucumber-messages[test-coverage]", + # external; Must be in sync with tox.ini + "mypy", + "pre-commit", + "tox>=4.2" +] +test-coverage = [ + "coverage", + "importlib_resources", + "pytest" +] + +[project.scripts] + +[tool.black] +line-length = 120 +target-version = ["py38", "py39", "py310", "py311", "py312"] +verbose = true + +[tool.isort] +line_length = 120 +multi_line_output = 3 +profile = "black" + +[tool.mypy] +files = "src/**/*.py" +install_types = true +non_interactive = true +plugins = [ + "pydantic.mypy" +] +show_error_codes = true +warn_return_any = true +warn_unused_configs = true + +[[tool.mypy.overrides]] +ignore_missing_imports = true +module = [ +] + +# Wait until is ready: https://github.com/tox-dev/tox/issues/999 +[tool.tox] +legacy_tox_ini = """ + [tox] + requires = + tox>=4.2 + env_list = + py312-pre-commit-lin + py{312, 311, 310, 39, 38}-mypy-lin + py{py310, py39, py38, 312, 311, 310, 39, 38}-pytest-coverage-lin + py312-pytest-coverage-{win, mac} + distshare = {homedir}/.tox/distshare + + [testenv] + platform = + lin: linux + mac: darwin + win: win32 + + [testenv:py312-pre-commit-lin] + skip_install = true + deps = + pre-commit + commands = + pre-commit run + + [testenv:py{312, 311, 310, 39, 38}-mypy-lin] + deps = + mypy + commands = + python -m mypy + + [testenv:py{py310, py39, py38, 312, 311, 310, 39, 38}-pytest-coverage-{lin, win, mac}] + deps = + .[test-coverage] + commands = + coverage run --append -m pytest -vvl + + [gh-actions] + python = + 3.8: py38 + 3.9: py39 + 3.10: py310 + 3.11: py311 + 3.12: py312 + pypy-3.8: pypy38 + pypy-3.9: pypy39 + pypy-3.10: pypy310 +""" diff --git a/python/pytest.ini b/python/pytest.ini new file mode 100644 index 00000000..5ee64771 --- /dev/null +++ b/python/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests diff --git a/python/src/cucumber_messages/__init__.py b/python/src/cucumber_messages/__init__.py new file mode 100644 index 00000000..58ae9f3a --- /dev/null +++ b/python/src/cucumber_messages/__init__.py @@ -0,0 +1,4 @@ +from .messages import * + +ExpressionType = Type1 +del Type1 diff --git a/python/src/cucumber_messages/messages.py b/python/src/cucumber_messages/messages.py new file mode 100644 index 00000000..da4c1b91 --- /dev/null +++ b/python/src/cucumber_messages/messages.py @@ -0,0 +1,755 @@ +# generated by datamodel-codegen: +# filename: Envelope.json + +from __future__ import annotations + +from enum import Enum +from typing import Optional, Sequence + +from pydantic import BaseModel, ConfigDict, Field + + +class ContentEncoding(Enum): + identity = "IDENTITY" + base64 = "BASE64" + + +class MediaType(Enum): + text_x_cucumber_gherkin_plain = "text/x.cucumber.gherkin+plain" + text_x_cucumber_gherkin_markdown = "text/x.cucumber.gherkin+markdown" + + +class Source(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + uri: str = Field( + ..., + description="*\n The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)\n of the source, typically a file path relative to the root directory", + ) + data: str = Field(..., description="The contents of the file") + media_type: MediaType = Field( + ..., + alias="mediaType", + description="The media type of the file. Can be used to specify custom types, such as\n text/x.cucumber.gherkin+plain", + ) + + +class Location(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + line: int + column: int | None = None + + +class Comment(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the comment") + text: str = Field(..., description="The text of the comment") + + +class DocString(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location + media_type: str | None = Field(None, alias="mediaType") + content: str + delimiter: str + + +class KeywordType(Enum): + unknown = "Unknown" + context = "Context" + action = "Action" + outcome = "Outcome" + conjunction = "Conjunction" + + +class TableCell(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the cell") + value: str = Field(..., description="The value of the cell") + + +class TableRow(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the first cell in the row") + cells: Sequence[TableCell] = Field(..., description="Cells in the row") + id: str + + +class Tag(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="Location of the tag") + name: str = Field(..., description="The name of the tag (including the leading `@`)") + id: str = Field(..., description="Unique ID to be able to reference the Tag from PickleTag") + + +class JavaMethod(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + class_name: str = Field(..., alias="className") + method_name: str = Field(..., alias="methodName") + method_parameter_types: Sequence[str] = Field(..., alias="methodParameterTypes") + + +class JavaStackTraceElement(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + class_name: str = Field(..., alias="className") + file_name: str = Field(..., alias="fileName") + method_name: str = Field(..., alias="methodName") + + +class Git(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + remote: str + revision: str + branch: str | None = None + tag: str | None = None + + +class Product(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + name: str = Field(..., description="The product name") + version: str | None = Field(None, description="The product version") + + +class PickleDocString(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + media_type: str | None = Field(None, alias="mediaType") + content: str + + +class Type(Enum): + unknown = "Unknown" + context = "Context" + action = "Action" + outcome = "Outcome" + + +class PickleTableCell(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + value: str + + +class PickleTableRow(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + cells: Sequence[PickleTableCell] = Field(..., min_length=1) + + +class PickleTag(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + name: str + ast_node_id: str = Field(..., alias="astNodeId", description="Points to the AST node this was created from") + + +class Type1(Enum): + cucumber_expression = "CUCUMBER_EXPRESSION" + regular_expression = "REGULAR_EXPRESSION" + + +class StepDefinitionPattern(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + source: str + type: Type1 + + +class Group(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + children: Sequence[Group] + start: int | None = None + value: str | None = None + + +class StepMatchArgument(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + group: Group = Field( + ..., + description="*\n Represents the outermost capture group of an argument. This message closely matches the\n `Group` class in the `cucumber-expressions` library.", + ) + parameter_type_name: str | None = Field(None, alias="parameterTypeName") + + +class StepMatchArgumentsList(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + step_match_arguments: Sequence[StepMatchArgument] = Field(..., alias="stepMatchArguments") + + +class TestStep(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + hook_id: str | None = Field(None, alias="hookId", description="Pointer to the `Hook` (if derived from a Hook)") + id: str + pickle_step_id: str | None = Field( + None, alias="pickleStepId", description="Pointer to the `PickleStep` (if derived from a `PickleStep`)" + ) + step_definition_ids: Sequence[str] | None = Field( + None, + alias="stepDefinitionIds", + description="Pointer to all the matching `StepDefinition`s (if derived from a `PickleStep`)\n Each element represents a matching step definition. A size of 0 means `UNDEFINED`,\n and a size of 2+ means `AMBIGUOUS`", + ) + step_match_arguments_lists: Sequence[StepMatchArgumentsList] | None = Field( + None, + alias="stepMatchArgumentsLists", + description="A list of list of StepMatchArgument (if derived from a `PickleStep`).", + ) + + +class Timestamp(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + seconds: int = Field( + ..., + description="Represents seconds of UTC time since Unix epoch\n 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to\n 9999-12-31T23:59:59Z inclusive.", + ) + nanos: int = Field( + ..., + description="Non-negative fractions of a second at nanosecond resolution. Negative\n second values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", + ) + + +class TestCaseStarted(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + attempt: int = Field( + ..., + description="*\n The first attempt should have value 0, and for each retry the value\n should increase by 1.", + ) + id: str = Field( + ..., + description="*\n Because a `TestCase` can be run multiple times (in case of a retry),\n we use this field to group messages relating to the same attempt.", + ) + test_case_id: str = Field(..., alias="testCaseId") + worker_id: str | None = Field( + None, + alias="workerId", + description="An identifier for the worker process running this test case, if test cases are being run in parallel. The identifier will be unique per worker, but no particular format is defined - it could be an index, uuid, machine name etc - and as such should be assumed that it's not human readable.", + ) + timestamp: Timestamp + + +class Exception(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + type: str = Field( + ..., + description='The type of the exception that caused this result. E.g. "Error" or "org.opentest4j.AssertionFailedError"', + ) + message: str | None = Field( + None, description='The message of exception that caused this result. E.g. expected: "a" but was: "b"' + ) + stack_trace: str | None = Field( + None, alias="stackTrace", description="The stringified stack trace of the exception that caused this result" + ) + + +class TestRunStarted(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + timestamp: Timestamp + + +class Status(Enum): + unknown = "UNKNOWN" + passed = "PASSED" + skipped = "SKIPPED" + pending = "PENDING" + undefined = "UNDEFINED" + ambiguous = "AMBIGUOUS" + failed = "FAILED" + + +class Duration(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + seconds: int + nanos: int = Field( + ..., + description="Non-negative fractions of a second at nanosecond resolution. Negative\n second values with fractions must still have non-negative nanos values\n that count forward in time. Must be from 0 to 999,999,999\n inclusive.", + ) + + +class TestStepStarted(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + test_case_started_id: str = Field(..., alias="testCaseStartedId") + test_step_id: str = Field(..., alias="testStepId") + timestamp: Timestamp + + +class UndefinedParameterType(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + expression: str + name: str + + +class Attachment(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + body: str = Field( + ..., + description="*\n The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment\n is simply the string. If it's `BASE64`, the string should be Base64 decoded to\n obtain the attachment.", + ) + content_encoding: ContentEncoding = Field( + ..., + alias="contentEncoding", + description='*\n Whether to interpret `body` "as-is" (IDENTITY) or if it needs to be Base64-decoded (BASE64).\n\n Content encoding is *not* determined by the media type, but rather by the type\n of the object being attached:\n\n - string: IDENTITY\n - byte array: BASE64\n - stream: BASE64', + ) + file_name: str | None = Field( + None, + alias="fileName", + description="*\n Suggested file name of the attachment. (Provided by the user as an argument to `attach`)", + ) + media_type: str = Field( + ..., + alias="mediaType", + description="*\n The media type of the data. This can be any valid\n [IANA Media Type](https://www.iana.org/assignments/media-types/media-types.xhtml)\n as well as Cucumber-specific media types such as `text/x.cucumber.gherkin+plain`\n and `text/x.cucumber.stacktrace+plain`", + ) + source: Source | None = None + test_case_started_id: str | None = Field(None, alias="testCaseStartedId") + test_step_id: str | None = Field(None, alias="testStepId") + url: str | None = Field( + None, + description="*\n A URL where the attachment can be retrieved. This field should not be set by Cucumber.\n It should be set by a program that reads a message stream and does the following for\n each Attachment message:\n\n - Writes the body (after base64 decoding if necessary) to a new file.\n - Sets `body` and `contentEncoding` to `null`\n - Writes out the new attachment message\n\n This will result in a smaller message stream, which can improve performance and\n reduce bandwidth of message consumers. It also makes it easier to process and download attachments\n separately from reports.", + ) + + +class DataTable(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location + rows: Sequence[TableRow] + + +class Examples(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the `Examples` keyword") + tags: Sequence[Tag] + keyword: str + name: str + description: str + table_header: TableRow | None = Field(None, alias="tableHeader") + table_body: Sequence[TableRow] = Field(..., alias="tableBody") + id: str + + +class Step(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the steps' `keyword`") + keyword: str = Field(..., description="The actual keyword as it appeared in the source.") + keyword_type: KeywordType | None = Field( + None, + alias="keywordType", + description="The test phase signalled by the keyword: Context definition (Given), Action performance (When), Outcome assertion (Then). Other keywords signal Continuation (And and But) from a prior keyword. Please note that all translations which a dialect maps to multiple keywords (`*` is in this category for all dialects), map to 'Unknown'.", + ) + text: str + doc_string: DocString | None = Field(None, alias="docString") + data_table: DataTable | None = Field(None, alias="dataTable") + id: str = Field(..., description="Unique ID to be able to reference the Step from PickleStep") + + +class SourceReference(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + uri: str | None = None + java_method: JavaMethod | None = Field(None, alias="javaMethod") + java_stack_trace_element: JavaStackTraceElement | None = Field(None, alias="javaStackTraceElement") + location: Location | None = None + + +class Ci(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + name: str = Field(..., description='Name of the CI product, e.g. "Jenkins", "CircleCI" etc.') + url: str | None = Field(None, description="Link to the build") + build_number: str | None = Field( + None, + alias="buildNumber", + description="The build number. Some CI servers use non-numeric build numbers, which is why this is a string", + ) + git: Git | None = None + + +class ParameterType(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + name: str = Field(..., description="The name is unique, so we don't need an id.") + regular_expressions: Sequence[str] = Field(..., alias="regularExpressions", min_length=1) + prefer_for_regular_expression_match: bool = Field(..., alias="preferForRegularExpressionMatch") + use_for_snippets: bool = Field(..., alias="useForSnippets") + id: str + source_reference: SourceReference | None = Field(None, alias="sourceReference") + + +class ParseError(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + source: SourceReference + message: str + + +class PickleTable(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + rows: Sequence[PickleTableRow] + + +class StepDefinition(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + id: str + pattern: StepDefinitionPattern + source_reference: SourceReference = Field(..., alias="sourceReference") + + +class TestCase(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + id: str + pickle_id: str = Field(..., alias="pickleId", description="The ID of the `Pickle` this `TestCase` is derived from.") + test_steps: Sequence[TestStep] = Field(..., alias="testSteps") + + +class TestCaseFinished(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + test_case_started_id: str = Field(..., alias="testCaseStartedId") + timestamp: Timestamp + will_be_retried: bool = Field(..., alias="willBeRetried") + + +class TestRunFinished(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + message: str | None = Field( + None, + description="An informative message about the test run. Typically additional information about failure, but not necessarily.", + ) + success: bool = Field( + ..., + description="A test run is successful if all steps are either passed or skipped, all before/after hooks passed and no other exceptions where thrown.", + ) + timestamp: Timestamp = Field(..., description="Timestamp when the TestRun is finished") + exception: Exception | None = Field( + None, + description="Any exception thrown during the test run, if any. Does not include exceptions thrown while executing steps.", + ) + + +class TestStepResult(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + duration: Duration + message: str | None = Field( + None, + description="An arbitrary bit of information that explains this result. This can be a stack trace of anything else.", + ) + status: Status + exception: Exception | None = Field(None, description="Exception thrown while executing this step, if any.") + + +class Background(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the `Background` keyword") + keyword: str + name: str + description: str + steps: Sequence[Step] + id: str + + +class Scenario(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the `Scenario` keyword") + tags: Sequence[Tag] + keyword: str + name: str + description: str + steps: Sequence[Step] + examples: Sequence[Examples] + id: str + + +class Hook(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + id: str + name: str | None = None + source_reference: SourceReference = Field(..., alias="sourceReference") + tag_expression: str | None = Field(None, alias="tagExpression") + + +class Meta(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + protocol_version: str = Field( + ..., alias="protocolVersion", description="*\n The [SEMVER](https://semver.org/) version number of the protocol" + ) + implementation: Product = Field(..., description="SpecFlow, Cucumber-JVM, Cucumber.js, Cucumber-Ruby, Behat etc.") + runtime: Product = Field(..., description="Java, Ruby, Node.js etc") + os: Product = Field(..., description="Windows, Linux, MacOS etc") + cpu: Product = Field(..., description="386, arm, amd64 etc") + ci: Ci | None = None + + +class PickleStepArgument(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + doc_string: PickleDocString | None = Field(None, alias="docString") + data_table: PickleTable | None = Field(None, alias="dataTable") + + +class TestStepFinished(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + test_case_started_id: str = Field(..., alias="testCaseStartedId") + test_step_id: str = Field(..., alias="testStepId") + test_step_result: TestStepResult = Field(..., alias="testStepResult") + timestamp: Timestamp + + +class RuleChild(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + background: Background | None = None + scenario: Scenario | None = None + + +class PickleStep(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + argument: PickleStepArgument | None = None + ast_node_ids: Sequence[str] = Field( + ..., + alias="astNodeIds", + description="References the IDs of the source of the step. For Gherkin, this can be\n the ID of a Step, and possibly also the ID of a TableRow", + min_length=1, + ) + id: str = Field(..., description="A unique ID for the PickleStep") + type: Type | None = Field( + None, + description="The context in which the step was specified: context (Given), action (When) or outcome (Then).\n\nNote that the keywords `But` and `And` inherit their meaning from prior steps and the `*` 'keyword' doesn't have specific meaning (hence Unknown)", + ) + text: str + + +class Rule(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the `Rule` keyword") + tags: Sequence[Tag] = Field(..., description="All the tags placed above the `Rule` keyword") + keyword: str + name: str + description: str + children: Sequence[RuleChild] + id: str + + +class Pickle(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + id: str = Field(..., description="*\n A unique id for the pickle") + uri: str = Field(..., description="The uri of the source file") + name: str = Field(..., description="The name of the pickle") + language: str = Field(..., description="The language of the pickle") + steps: Sequence[PickleStep] = Field(..., description="One or more steps") + tags: Sequence[PickleTag] = Field( + ..., + description="*\n One or more tags. If this pickle is constructed from a Gherkin document,\n It includes inherited tags from the `Feature` as well.", + ) + ast_node_ids: Sequence[str] = Field( + ..., + alias="astNodeIds", + description="*\n Points to the AST node locations of the pickle. The last one represents the unique\n id of the pickle. A pickle constructed from `Examples` will have the first\n id originating from the `Scenario` AST node, and the second from the `TableRow` AST node.", + min_length=1, + ) + + +class FeatureChild(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + rule: Rule | None = None + background: Background | None = None + scenario: Scenario | None = None + + +class Feature(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + location: Location = Field(..., description="The location of the `Feature` keyword") + tags: Sequence[Tag] = Field(..., description="All the tags placed above the `Feature` keyword") + language: str = Field( + ..., + description="The [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) language code of the Gherkin document", + ) + keyword: str = Field(..., description="The text of the `Feature` keyword (in the language specified by `language`)") + name: str = Field(..., description="The name of the feature (the text following the `keyword`)") + description: str = Field( + ..., description="The line(s) underneath the line with the `keyword` that are used as description" + ) + children: Sequence[FeatureChild] = Field(..., description="Zero or more children") + + +class GherkinDocument(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + uri: str | None = Field( + None, + description="*\n The [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)\n of the source, typically a file path relative to the root directory", + ) + feature: Feature | None = None + comments: Sequence[Comment] = Field(..., description="All the comments in the Gherkin document") + + +class Envelope(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + attachment: Attachment | None = None + gherkin_document: GherkinDocument | None = Field(None, alias="gherkinDocument") + hook: Hook | None = None + meta: Meta | None = None + parameter_type: ParameterType | None = Field(None, alias="parameterType") + parse_error: ParseError | None = Field(None, alias="parseError") + pickle: Pickle | None = None + source: Source | None = None + step_definition: StepDefinition | None = Field(None, alias="stepDefinition") + test_case: TestCase | None = Field(None, alias="testCase") + test_case_finished: TestCaseFinished | None = Field(None, alias="testCaseFinished") + test_case_started: TestCaseStarted | None = Field(None, alias="testCaseStarted") + test_run_finished: TestRunFinished | None = Field(None, alias="testRunFinished") + test_run_started: TestRunStarted | None = Field(None, alias="testRunStarted") + test_step_finished: TestStepFinished | None = Field(None, alias="testStepFinished") + test_step_started: TestStepStarted | None = Field(None, alias="testStepStarted") + undefined_parameter_type: UndefinedParameterType | None = Field(None, alias="undefinedParameterType") + + +Group.model_rebuild() diff --git a/python/src/message_samples/__init__.py b/python/src/message_samples/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/src/message_samples/attachments/attachments.feature b/python/src/message_samples/attachments/attachments.feature new file mode 100644 index 00000000..17aa5bbc --- /dev/null +++ b/python/src/message_samples/attachments/attachments.feature @@ -0,0 +1,44 @@ +Feature: Attachments + It is sometimes useful to take a screenshot while a scenario runs. + Or capture some logs. + + Cucumber lets you `attach` arbitrary files during execution, and you can + specify a content type for the contents. + + Formatters can then render these attachments in reports. + + Attachments must have a body and a content type + + Scenario: Strings can be attached with a media type + Beware that some formatters such as @cucumber/react use the media type + to determine how to display an attachment. + + When the string "hello" is attached as "application/octet-stream" + + Scenario: Log JSON + When the following string is attached as "application/json": + ``` + {"message": "The big question", "foo": "bar"} + ``` + + Scenario: Log text + When the string "hello" is logged + + Scenario: Log ANSI coloured text + When text with ANSI escapes is logged + + Scenario: Byte arrays are base64-encoded regardless of media type + When an array with 10 bytes is attached as "text/plain" + + Scenario: Streams are always base64-encoded + When a JPEG image is attached + + Scenario: Attaching images in examples + When the png is attached + + Examples: + | image | + | cucumber.png | + + Scenario: Attaching a document with a filename + When a PDF document is attached with a filename diff --git a/python/src/message_samples/attachments/attachments.feature.ndjson b/python/src/message_samples/attachments/attachments.feature.ndjson new file mode 100644 index 00000000..66fe2e67 --- /dev/null +++ b/python/src/message_samples/attachments/attachments.feature.ndjson @@ -0,0 +1,87 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type\n\n Scenario: Strings can be attached with a media type\n Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.\n\n When the string \"hello\" is attached as \"application/octet-stream\"\n\n Scenario: Log JSON\n When the following string is attached as \"application/json\":\n ```\n {\"message\": \"The big question\", \"foo\": \"bar\"}\n ```\n\n Scenario: Log text\n When the string \"hello\" is logged\n\n Scenario: Log ANSI coloured text\n When text with ANSI escapes is logged\n\n Scenario: Byte arrays are base64-encoded regardless of media type\n When an array with 10 bytes is attached as \"text/plain\"\n\n Scenario: Streams are always base64-encoded\n When a JPEG image is attached\n\n Scenario: Attaching images in examples\n When the png is attached\n\n Examples:\n | image |\n | cucumber.png |\n\n Scenario: Attaching a document with a filename\n When a PDF document is attached with a filename\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/attachments/attachments.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":" Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.","examples":[],"id":"11","keyword":"Scenario","location":{"column":3,"line":12},"name":"Strings can be attached with a media type","steps":[{"id":"10","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"the string \"hello\" is attached as \"application/octet-stream\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":18},"name":"Log JSON","steps":[{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}","delimiter":"```","location":{"column":8,"line":20}},"id":"12","keyword":"When ","keywordType":"Action","location":{"column":6,"line":19},"text":"the following string is attached as \"application/json\":"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"15","keyword":"Scenario","location":{"column":3,"line":24},"name":"Log text","steps":[{"id":"14","keyword":"When ","keywordType":"Action","location":{"column":5,"line":25},"text":"the string \"hello\" is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"17","keyword":"Scenario","location":{"column":3,"line":27},"name":"Log ANSI coloured text","steps":[{"id":"16","keyword":"When ","keywordType":"Action","location":{"column":6,"line":28},"text":"text with ANSI escapes is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"19","keyword":"Scenario","location":{"column":3,"line":30},"name":"Byte arrays are base64-encoded regardless of media type","steps":[{"id":"18","keyword":"When ","keywordType":"Action","location":{"column":5,"line":31},"text":"an array with 10 bytes is attached as \"text/plain\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"21","keyword":"Scenario","location":{"column":3,"line":33},"name":"Streams are always base64-encoded","steps":[{"id":"20","keyword":"When ","keywordType":"Action","location":{"column":5,"line":34},"text":"a JPEG image is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[{"description":"","id":"25","keyword":"Examples","location":{"column":5,"line":39},"name":"","tableBody":[{"cells":[{"location":{"column":9,"line":41},"value":"cucumber.png"}],"id":"24","location":{"column":7,"line":41}}],"tableHeader":{"cells":[{"location":{"column":9,"line":40},"value":"image"}],"id":"23","location":{"column":7,"line":40}},"tags":[]}],"id":"26","keyword":"Scenario","location":{"column":3,"line":36},"name":"Attaching images in examples","steps":[{"id":"22","keyword":"When ","keywordType":"Action","location":{"column":5,"line":37},"text":"the png is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"28","keyword":"Scenario","location":{"column":3,"line":43},"name":"Attaching a document with a filename","steps":[{"id":"27","keyword":"When ","keywordType":"Action","location":{"column":5,"line":44},"text":"a PDF document is attached with a filename"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Attachments","tags":[]},"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["11"],"id":"30","language":"en","name":"Strings can be attached with a media type","steps":[{"astNodeIds":["10"],"id":"29","text":"the string \"hello\" is attached as \"application/octet-stream\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["13"],"id":"32","language":"en","name":"Log JSON","steps":[{"argument":{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}"}},"astNodeIds":["12"],"id":"31","text":"the following string is attached as \"application/json\":","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["15"],"id":"34","language":"en","name":"Log text","steps":[{"astNodeIds":["14"],"id":"33","text":"the string \"hello\" is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["17"],"id":"36","language":"en","name":"Log ANSI coloured text","steps":[{"astNodeIds":["16"],"id":"35","text":"text with ANSI escapes is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["19"],"id":"38","language":"en","name":"Byte arrays are base64-encoded regardless of media type","steps":[{"astNodeIds":["18"],"id":"37","text":"an array with 10 bytes is attached as \"text/plain\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["21"],"id":"40","language":"en","name":"Streams are always base64-encoded","steps":[{"astNodeIds":["20"],"id":"39","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["26","24"],"id":"42","language":"en","name":"Attaching images in examples","steps":[{"astNodeIds":["22","24"],"id":"41","text":"the cucumber.png png is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"pickle":{"astNodeIds":["28"],"id":"44","language":"en","name":"Attaching a document with a filename","steps":[{"astNodeIds":["27"],"id":"43","text":"a PDF document is attached with a filename","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} +{"stepDefinition":{"id":"1","pattern":{"source":"the string {string} is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"the string {string} is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"text with ANSI escapes is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"4","pattern":{"source":"the following string is attached as {string}:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":22},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"5","pattern":{"source":"an array with {int} bytes is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":26},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"6","pattern":{"source":"a stream with {int} bytes are attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":35},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"7","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":48},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"8","pattern":{"source":"the {word} png is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":52},"uri":"samples/attachments/attachments.feature.ts"}}} +{"stepDefinition":{"id":"9","pattern":{"source":"a PDF document is attached with a filename","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":56},"uri":"samples/attachments/attachments.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":6},"uri":"samples/attachments/attachments.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"47","pickleId":"30","testSteps":[{"hookId":"0","id":"45"},{"id":"46","pickleStepId":"29","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"},{"group":{"children":[{"children":[{"children":[]}],"start":35,"value":"application/octet-stream"},{"children":[{"children":[]}]}],"start":34,"value":"\"application/octet-stream\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"50","pickleId":"32","testSteps":[{"hookId":"0","id":"48"},{"id":"49","pickleStepId":"31","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":37,"value":"application/json"},{"children":[{"children":[]}]}],"start":36,"value":"\"application/json\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"53","pickleId":"34","testSteps":[{"hookId":"0","id":"51"},{"id":"52","pickleStepId":"33","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"56","pickleId":"36","testSteps":[{"hookId":"0","id":"54"},{"id":"55","pickleStepId":"35","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"59","pickleId":"38","testSteps":[{"hookId":"0","id":"57"},{"id":"58","pickleStepId":"37","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[{"children":[{"children":[]}],"start":39,"value":"text/plain"},{"children":[{"children":[]}]}],"start":38,"value":"\"text/plain\""},"parameterTypeName":"string"}]}]}]}} +{"testCase":{"id":"62","pickleId":"40","testSteps":[{"hookId":"0","id":"60"},{"id":"61","pickleStepId":"39","stepDefinitionIds":["7"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"65","pickleId":"42","testSteps":[{"hookId":"0","id":"63"},{"id":"64","pickleStepId":"41","stepDefinitionIds":["8"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":4,"value":"cucumber.png"},"parameterTypeName":"word"}]}]}]}} +{"testCase":{"id":"68","pickleId":"44","testSteps":[{"hookId":"0","id":"66"},{"id":"67","pickleStepId":"43","stepDefinitionIds":["9"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"69","testCaseId":"47","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"69","testStepId":"45","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"69","testStepId":"45","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"69","testStepId":"46","timestamp":{"nanos":4000000,"seconds":0}}} +{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"application/octet-stream","testCaseStartedId":"69","testStepId":"46"}} +{"testStepFinished":{"testCaseStartedId":"69","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"69","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"70","testCaseId":"50","timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"70","testStepId":"48","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"70","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"70","testStepId":"49","timestamp":{"nanos":10000000,"seconds":0}}} +{"attachment":{"body":"{\"message\": \"The big question\", \"foo\": \"bar\"}","contentEncoding":"IDENTITY","mediaType":"application/json","testCaseStartedId":"70","testStepId":"49"}} +{"testStepFinished":{"testCaseStartedId":"70","testStepId":"49","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"70","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"71","testCaseId":"53","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"71","testStepId":"51","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"71","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"71","testStepId":"52","timestamp":{"nanos":16000000,"seconds":0}}} +{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"71","testStepId":"52"}} +{"testStepFinished":{"testCaseStartedId":"71","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"71","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"72","testCaseId":"56","timestamp":{"nanos":19000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"72","testStepId":"54","timestamp":{"nanos":20000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"72","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"72","testStepId":"55","timestamp":{"nanos":22000000,"seconds":0}}} +{"attachment":{"body":"This displays a \u001b[31mr\u001b[0m\u001b[91ma\u001b[0m\u001b[33mi\u001b[0m\u001b[32mn\u001b[0m\u001b[34mb\u001b[0m\u001b[95mo\u001b[0m\u001b[35mw\u001b[0m","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"72","testStepId":"55"}} +{"testStepFinished":{"testCaseStartedId":"72","testStepId":"55","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"72","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"73","testCaseId":"59","timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"73","testStepId":"57","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"73","testStepId":"57","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"73","testStepId":"58","timestamp":{"nanos":28000000,"seconds":0}}} +{"attachment":{"body":"AAECAwQFBgcICQ==","contentEncoding":"BASE64","mediaType":"text/plain","testCaseStartedId":"73","testStepId":"58"}} +{"testStepFinished":{"testCaseStartedId":"73","testStepId":"58","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"73","timestamp":{"nanos":30000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"74","testCaseId":"62","timestamp":{"nanos":31000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"74","testStepId":"60","timestamp":{"nanos":32000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"74","testStepId":"60","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"74","testStepId":"61","timestamp":{"nanos":34000000,"seconds":0}}} +{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"74","testStepId":"61"}} +{"testStepFinished":{"testCaseStartedId":"74","testStepId":"61","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"74","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"75","testCaseId":"65","timestamp":{"nanos":37000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"75","testStepId":"63","timestamp":{"nanos":38000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"75","testStepId":"63","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":39000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"75","testStepId":"64","timestamp":{"nanos":40000000,"seconds":0}}} +{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"75","testStepId":"64"}} +{"testStepFinished":{"testCaseStartedId":"75","testStepId":"64","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":41000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"75","timestamp":{"nanos":42000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"76","testCaseId":"68","timestamp":{"nanos":43000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"76","testStepId":"66","timestamp":{"nanos":44000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"76","testStepId":"66","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"76","testStepId":"67","timestamp":{"nanos":46000000,"seconds":0}}} +{"attachment":{"body":"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RmlsZTIgOCAwIFI+PgplbmRvYmoKMTAgMCBvYmoKPDwvVHlwZSAvRm9udAovRm9udERlc2NyaXB0b3IgOSAwIFIKL0Jhc2VGb250IC9BQUFBQUErQXJpYWxNVAovU3VidHlwZSAvQ0lERm9udFR5cGUyCi9DSURUb0dJRE1hcCAvSWRlbnRpdHkKL0NJRFN5c3RlbUluZm8gPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKElkZW50aXR5KQovU3VwcGxlbWVudCAwPj4KL1cgWzAgWzc1MF0gNTUgWzYxMC44Mzk4NF0gNzIgWzU1Ni4xNTIzNF0gODcgWzI3Ny44MzIwM11dCi9EVyA1MDA+PgplbmRvYmoKMTEgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDI1MD4+IHN0cmVhbQp4nF2Qy2rEIBSG9z7FWU4Xg0lmMtNFEMqUQha90LQPYPQkFRoVYxZ5+3pJU6ig8PP/n+dCb+1jq5UH+uaM6NDDoLR0OJvFCYQeR6VJWYFUwm8qvWLiltAAd+vscWr1YEjTAND34M7erXB4kKbHO0JfnUSn9AiHz1sXdLdY+40Tag8FYQwkDuGnZ25f+IRAE3ZsZfCVX4+B+Ut8rBahSrrM3QgjcbZcoON6RNIU4TBonsJhBLX851eZ6gfxxV1Mn64hXRT1mUV1vk/qUid2S5W/zF6ivmQos9fTls5+LBqXs08kFufCMGmDaYrYv9K4L9kaG6l4fwAdQH9hCmVuZHN0cmVhbQplbmRvYmoKNCAwIG9iago8PC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMAovQmFzZUZvbnQgL0FBQUFBQStBcmlhbE1UCi9FbmNvZGluZyAvSWRlbnRpdHktSAovRGVzY2VuZGFudEZvbnRzIFsxMCAwIFJdCi9Ub1VuaWNvZGUgMTEgMCBSPj4KZW5kb2JqCnhyZWYKMCAxMgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDM4MiAwMDAwMCBuIAowMDAwMDAwMTA4IDAwMDAwIG4gCjAwMDAwMDk2MDYgMDAwMDAgbiAKMDAwMDAwMDE0NSAwMDAwMCBuIAowMDAwMDAwNTkwIDAwMDAwIG4gCjAwMDAwMDA2NDUgMDAwMDAgbiAKMDAwMDAwMDY5MiAwMDAwMCBuIAowMDAwMDA4Nzg3IDAwMDAwIG4gCjAwMDAwMDkwMjEgMDAwMDAgbiAKMDAwMDAwOTI4NSAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgMTIKL1Jvb3QgNyAwIFIKL0luZm8gMSAwIFI+PgpzdGFydHhyZWYKOTc0NQolJUVPRgo=","contentEncoding":"BASE64","fileName":"document.pdf","mediaType":"application/pdf","testCaseStartedId":"76","testStepId":"67"}} +{"testStepFinished":{"testCaseStartedId":"76","testStepId":"67","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":47000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"76","timestamp":{"nanos":48000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":49000000,"seconds":0}}} diff --git a/python/src/message_samples/attachments/attachments.feature.ts b/python/src/message_samples/attachments/attachments.feature.ts new file mode 100644 index 00000000..c1e9c6bd --- /dev/null +++ b/python/src/message_samples/attachments/attachments.feature.ts @@ -0,0 +1,58 @@ +import { Before, When } from '@cucumber/fake-cucumber' +import { ReadableStreamBuffer } from 'stream-buffers' +import fs from 'fs' + +// Cucumber-JVM needs to use a Before hook in order to create attachments +Before(() => undefined) + +When('the string {string} is attached as {string}', function (text: string, mediaType: string) { + this.attach(text, mediaType) +}) + +When('the string {string} is logged', function (text: string) { + this.log(text) +}) + +When('text with ANSI escapes is logged', function () { + this.log( + 'This displays a \x1b[31mr\x1b[0m\x1b[91ma\x1b[0m\x1b[33mi\x1b[0m\x1b[32mn\x1b[0m\x1b[34mb\x1b[0m\x1b[95mo\x1b[0m\x1b[35mw\x1b[0m' + ) +}) + +When('the following string is attached as {string}:', function (mediaType: string, text: string) { + this.attach(text, mediaType) +}) + +When( + 'an array with {int} bytes is attached as {string}', + function (size: number, mediaType: string) { + const data = [...Array(size).keys()] + const buffer = Buffer.from(data) + this.attach(buffer, mediaType) + } +) + +When( + 'a stream with {int} bytes are attached as {string}', + async function (size: number, mediaType: string) { + const data = [...Array(size).keys()] + const buffer = Buffer.from(data) + const stream = new ReadableStreamBuffer({ chunkSize: 1, frequency: 1 }) + stream.put(buffer) + stream.stop() + + await this.attach(stream, mediaType) + } +) + +When('a JPEG image is attached', async function () { + await this.attach(fs.createReadStream(__dirname + '/cucumber.png'), 'image/png') +}) + +When('the {word} png is attached', async function (filename) { + await this.attach(fs.createReadStream(__dirname + `/${filename}`), 'image/png') +}) + +When('a PDF document is attached with a filename', async function () { + await this.attach(fs.createReadStream(__dirname + '/document.pdf'), 'application/pdf', 'document.pdf') +}) diff --git a/python/src/message_samples/attachments/cucumber.png b/python/src/message_samples/attachments/cucumber.png new file mode 100644 index 0000000000000000000000000000000000000000..2760899aa0ce16aeaaea93d3118a32e7ac5bec8d GIT binary patch literal 1739 zcmV;+1~mDJP)G+r@kQ0VOJz1t=x5=pe3owlM@Ei<#*ZtpGI zgKd}Iv=WU6L@O5L5Qs#)gFvk*7OQ`VCsjOx5<>9^RV-lQA0`qL#Hi6fjMC@#y`7oe zS+={g-EDP}m+f}vz4x2%_`Ec`caU@Gwv+u9&;ebh;EPxToe6TQSS7$RIEHqf|0i z0O+ z#n5`Lu?_+l5a?76FBT_ov)oVPu)W&2iyqQk6q$E2`kQlqo37e8-)c+O?QiP<=H+=W zgC{tLKe`UI8wSZ$`}IIZS7^VP!&SQ9uqqj{=4V~1HP0i=kNxUV+pBnmxV8-q#Bxu7a+-a2h-P!vK`Neu>T>`ydm{x2F*T=U zFja;RD&fUT?=ygOHKmEIjm9$XXg4i$m^A1Td}8TX_oouO^1 zftu}jxiw*Sqct@^-zMG^t)7q>c1_O=)^$NOakew|C1vwbb(rq-=>$Sb3W6-RZHa~m zCJ-n2XtkjN1C$hf07a9cuvH0K135T-J;#nfDUID~Sv*Yz!r1hE3|a|Q4_9AFEWLHK zWz~oq!$8|OVjZ(mf6Y*Z+@G&h%4HXA<`4i@t!XO}{GYwU7nxru-K+|Xtu%RHv$V5t zB%F}kxeBctB<7atq+W_2XaHsIuS|aaB@`qli21Zmg1ge~X)cg!Z$@+@T2Kf6wH3yz z&3Yvsd2vMF!t&A=G!b@&(o#XX>H~4DCJ(w*r-TNAhSk2Rta1dYR_3O9WK; zw#R~odmNn4Rrysbu1(x67Wr<38~#FiG1`n}wO&7`@#)Xk3f`-e^xfhbRWBNCp0aZ6 zG7j-w;#H4aR;4%|7`O;-+)Hl;uEM%I>mVnijiapH>2)nQ~8L|KJMiw<@G*t1yFW9;lFYc#uS`DwjogG)sqA zR1ZXz{)UVWQ#sGl0$Aj@M%qBOs8U>G?P+&{nu~!`wccEicA`NtKbHn#g?=au3r^~) z3?!GiqlV-fJj2A0p}mr}21v220F29iQ1fLV>-W%pUD-_S!;=aJIQ+*`W9=9^HPvL{ z0;-_op8_N*ciN&xk6wP@c=5J5d#{rWB-U?ag_zePQ!sYV&o8}(nae94B=$6zwdRg$ z{h^gdI-K$AkW4|MJIzg%@h!p>_RSE#rObbMsUUTO7bj4~!21~&^MANd_d&CC2wth| hfX@)Vpvv|h{{nxzjlgvW5(5AL002ovPDHLkV1gBrLk9o= literal 0 HcmV?d00001 diff --git a/python/src/message_samples/attachments/document.pdf b/python/src/message_samples/attachments/document.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4647f3c9d70173713ad061f405a1aa9146615677 GIT binary patch literal 10061 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∨WEz|Va{bk-|&;_RAeM9+J zUnh0UX026ZO7^YamIZ5tFXz1xw3~EOReU=#MGVLU&?oU#=?!Q&VOGMa9g3{|}-(rTcEVg5D)DI{a z2GWDRGn4V{waEAz^x84pWqc%zrU@5vy=C+T^*opZy{sEeGZf(2bRQ7&>;3n3xehtByZm`RwV*79njVs~e!)Ed` z;YH~-tZ&NoXtbHSzJwFj7w*SIi)C%{Z8`Yu97yZ~Sa9T+txx2H)bjqO(lY!JZ9$Wd z?q>Zu#8Mn;b2b@_2~w}=Ym!RS<3n-cI9 zwjH50Myt%cFL0csJ&^^?GTKnrwi)*kO{uyhF(kR-koS?7m80R(c zIKR7oLwk9?hVqQyn)s}&`*Z`ke0eNnCvq*jB#li^lS_Wwa*V!tmKv21n> zIWRmXIB*O$9CN=2MaFzX^}(gDA^Pdq3=-`OpZdO+JS|#VtZN9tHt-cWHTu>u-?F#k zg|~2l_XW@B=IvR%<3*oH%%q4gQvvODblS~06nfp|{k(t{nm$Q>+P@j-Oauu{)-!d1p-7KZuoz;VzBBwu( zGi;S^D}Nr}uHT)sBb(kg=cqeOjYzwL|Arc%fB!xIC)99<9!MY@;SLsdNLzul+F$c0JmcRloYIBFCpvZ;0 zrxE)DdEkIRcsapfEub zk(E%lm6nxIgxR484--`O7Ra}MnAP4oqEeT&F}1xzI#dy67AUUdEr3}R#n~WGfR3^Q zioLP0F#|CFV;ah+=45AQg}6g_09<$M$Ll-jLzfTCr4Imu0lE+n7biats*w5sK5l?6 z7!2VAfw_55xBPr4WP^_nHHs>zKB^!RuK{4LyBPnd!@pod{~vUCCq~vXRzqlXO#k@lV>sE{OE+1y!pwuC+l-%Lw!84+cXP;}JYhW}G195Vmt850;vz9?0pz?(k=tBTq|bz2P^i#wnS0J__|f6=t71Hu#+ z)d1YMs6P1X06@TC9x%WZ@J|~E#Rc6R0Gof>c=%CR&wtoJT&RxucN-MKg~ECM-Npst z{qJ~SD5|^u!w>Sm_(7omwJtv&O0xek7s|zr%JkpkLAm+=WnH8L4AtZgckG**g&V3e ns1{VUwMD&4{_NjB+U+0Jazw%$kbl$)%Et@FWnhq0mcsoXXWVEI literal 0 HcmV?d00001 diff --git a/python/src/message_samples/cdata/cdata.feature b/python/src/message_samples/cdata/cdata.feature new file mode 100644 index 00000000..9983c41a --- /dev/null +++ b/python/src/message_samples/cdata/cdata.feature @@ -0,0 +1,6 @@ +Feature: cdata + + Cucumber xml formatters should be able to handle xml cdata elements + + Scenario: cdata + Given I have 42 in my belly diff --git a/python/src/message_samples/cdata/cdata.feature.ndjson b/python/src/message_samples/cdata/cdata.feature.ndjson new file mode 100644 index 00000000..3c2a89c9 --- /dev/null +++ b/python/src/message_samples/cdata/cdata.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: cdata\n \n Cucumber xml formatters should be able to handle xml cdata elements\n\n Scenario: cdata\n Given I have 42 in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/cdata/cdata.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":5},"name":"cdata","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":6},"text":"I have 42 in my belly"}],"tags":[]}}],"description":" Cucumber xml formatters should be able to handle xml cdata elements","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"cdata","tags":[]},"uri":"samples/cdata/cdata.feature"}} +{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cdata","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 in my belly","type":"Context"}],"tags":[],"uri":"samples/cdata/cdata.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/cdata/cdata.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"6","pickleId":"4","testSteps":[{"id":"5","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/cdata/cdata.feature.ts b/python/src/message_samples/cdata/cdata.feature.ts new file mode 100644 index 00000000..4d8af61a --- /dev/null +++ b/python/src/message_samples/cdata/cdata.feature.ts @@ -0,0 +1,6 @@ +import assert from 'assert' +import { Given } from '@cucumber/fake-cucumber' + +Given('I have {int} in my belly', function (cukeCount: number) { + assert(cukeCount) +}) diff --git a/python/src/message_samples/data-tables/data-tables.feature b/python/src/message_samples/data-tables/data-tables.feature new file mode 100644 index 00000000..c5ae8059 --- /dev/null +++ b/python/src/message_samples/data-tables/data-tables.feature @@ -0,0 +1,12 @@ +Feature: Data Tables + Data Tables can be places underneath a step and will be passed as the last + argument to the step definition. They can be used to represent richer data + structures, and can also be transformed to other types. + + Scenario: transposed table + When the following table is transposed: + | a | b | + | 1 | 2 | + Then it should be: + | a | 1 | + | b | 2 | diff --git a/python/src/message_samples/data-tables/data-tables.feature.ndjson b/python/src/message_samples/data-tables/data-tables.feature.ndjson new file mode 100644 index 00000000..f21c8180 --- /dev/null +++ b/python/src/message_samples/data-tables/data-tables.feature.ndjson @@ -0,0 +1,15 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Data Tables\n Data Tables can be places underneath a step and will be passed as the last\n argument to the step definition. They can be used to represent richer data\n structures, and can also be transformed to other types.\n\n Scenario: transposed table\n When the following table is transposed:\n | a | b |\n | 1 | 2 |\n Then it should be:\n | a | 1 |\n | b | 2 |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/data-tables/data-tables.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"8","keyword":"Scenario","location":{"column":3,"line":6},"name":"transposed table","steps":[{"dataTable":{"location":{"column":7,"line":8},"rows":[{"cells":[{"location":{"column":9,"line":8},"value":"a"},{"location":{"column":13,"line":8},"value":"b"}],"id":"2","location":{"column":7,"line":8}},{"cells":[{"location":{"column":9,"line":9},"value":"1"},{"location":{"column":13,"line":9},"value":"2"}],"id":"3","location":{"column":7,"line":9}}]},"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":7},"text":"the following table is transposed:"},{"dataTable":{"location":{"column":7,"line":11},"rows":[{"cells":[{"location":{"column":9,"line":11},"value":"a"},{"location":{"column":13,"line":11},"value":"1"}],"id":"5","location":{"column":7,"line":11}},{"cells":[{"location":{"column":9,"line":12},"value":"b"},{"location":{"column":13,"line":12},"value":"2"}],"id":"6","location":{"column":7,"line":12}}]},"id":"7","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":10},"text":"it should be:"}],"tags":[]}}],"description":" Data Tables can be places underneath a step and will be passed as the last\n argument to the step definition. They can be used to represent richer data\n structures, and can also be transformed to other types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Data Tables","tags":[]},"uri":"samples/data-tables/data-tables.feature"}} +{"pickle":{"astNodeIds":["8"],"id":"11","language":"en","name":"transposed table","steps":[{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"b"}]},{"cells":[{"value":"1"},{"value":"2"}]}]}},"astNodeIds":["4"],"id":"9","text":"the following table is transposed:","type":"Action"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"1"}]},{"cells":[{"value":"b"},{"value":"2"}]}]}},"astNodeIds":["7"],"id":"10","text":"it should be:","type":"Outcome"}],"tags":[],"uri":"samples/data-tables/data-tables.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"the following table is transposed:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":5},"uri":"samples/data-tables/data-tables.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"it should be:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/data-tables/data-tables.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"14","pickleId":"11","testSteps":[{"id":"12","pickleStepId":"9","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"13","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"15","testCaseId":"14","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"15","testStepId":"12","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"15","testStepId":"12","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"15","testStepId":"13","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"15","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"15","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":7000000,"seconds":0}}} diff --git a/python/src/message_samples/data-tables/data-tables.feature.ts b/python/src/message_samples/data-tables/data-tables.feature.ts new file mode 100644 index 00000000..b6c71dc1 --- /dev/null +++ b/python/src/message_samples/data-tables/data-tables.feature.ts @@ -0,0 +1,11 @@ +import { When, Then } from '@cucumber/fake-cucumber' +// TODO: Figure out a better way to export this +import DataTable from '@cucumber/fake-cucumber/dist/src/DataTable' + +When('the following table is transposed:', function (table: DataTable) { + this.transposed = table.transpose() +}) + +Then('it should be:', function (expected: DataTable) { + this.transposed.diff(expected) +}) diff --git a/python/src/message_samples/examples-tables/examples-tables.feature b/python/src/message_samples/examples-tables/examples-tables.feature new file mode 100644 index 00000000..ed82f0f3 --- /dev/null +++ b/python/src/message_samples/examples-tables/examples-tables.feature @@ -0,0 +1,28 @@ +Feature: Examples Tables + Sometimes it can be desireable to run the same scenario multiple times + with different data each time. This can be done by placing an Examples + section with an Examples Table underneath a Scenario, and use + in the Scenario, matching the table headers. + + Scenario Outline: eating cucumbers + Given there are cucumbers + When I eat cucumbers + Then I should have cucumbers + + @passing + Examples: These are passing + | start | eat | left | + | 12 | 5 | 7 | + | 20 | 5 | 15 | + + @failing + Examples: These are failing + | start | eat | left | + | 12 | 20 | 0 | + | 0 | 1 | 0 | + + @undefined + Examples: These are undefined because the value is not an {int} + | start | eat | left | + | 12 | banana | 12 | + | 0 | 1 | apple | diff --git a/python/src/message_samples/examples-tables/examples-tables.feature.ndjson b/python/src/message_samples/examples-tables/examples-tables.feature.ndjson new file mode 100644 index 00000000..5dbd02d0 --- /dev/null +++ b/python/src/message_samples/examples-tables/examples-tables.feature.ndjson @@ -0,0 +1,68 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Examples Tables\n Sometimes it can be desireable to run the same scenario multiple times\n with different data each time. This can be done by placing an Examples\n section with an Examples Table underneath a Scenario, and use \n in the Scenario, matching the table headers.\n\n Scenario Outline: eating cucumbers\n Given there are cucumbers\n When I eat cucumbers\n Then I should have cucumbers\n\n @passing\n Examples: These are passing\n | start | eat | left |\n | 12 | 5 | 7 |\n | 20 | 5 | 15 |\n\n @failing\n Examples: These are failing\n | start | eat | left |\n | 12 | 20 | 0 |\n | 0 | 1 | 0 |\n\n @undefined\n Examples: These are undefined because the value is not an {int}\n | start | eat | left |\n | 12 | banana | 12 |\n | 0 | 1 | apple |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables/examples-tables.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"10","keyword":"Examples","location":{"column":5,"line":13},"name":"These are passing","tableBody":[{"cells":[{"location":{"column":12,"line":15},"value":"12"},{"location":{"column":19,"line":15},"value":"5"},{"location":{"column":26,"line":15},"value":"7"}],"id":"7","location":{"column":7,"line":15}},{"cells":[{"location":{"column":12,"line":16},"value":"20"},{"location":{"column":19,"line":16},"value":"5"},{"location":{"column":25,"line":16},"value":"15"}],"id":"8","location":{"column":7,"line":16}}],"tableHeader":{"cells":[{"location":{"column":9,"line":14},"value":"start"},{"location":{"column":17,"line":14},"value":"eat"},{"location":{"column":23,"line":14},"value":"left"}],"id":"6","location":{"column":7,"line":14}},"tags":[{"id":"9","location":{"column":5,"line":12},"name":"@passing"}]},{"description":"","id":"15","keyword":"Examples","location":{"column":5,"line":19},"name":"These are failing","tableBody":[{"cells":[{"location":{"column":12,"line":21},"value":"12"},{"location":{"column":18,"line":21},"value":"20"},{"location":{"column":26,"line":21},"value":"0"}],"id":"12","location":{"column":7,"line":21}},{"cells":[{"location":{"column":13,"line":22},"value":"0"},{"location":{"column":19,"line":22},"value":"1"},{"location":{"column":26,"line":22},"value":"0"}],"id":"13","location":{"column":7,"line":22}}],"tableHeader":{"cells":[{"location":{"column":9,"line":20},"value":"start"},{"location":{"column":17,"line":20},"value":"eat"},{"location":{"column":23,"line":20},"value":"left"}],"id":"11","location":{"column":7,"line":20}},"tags":[{"id":"14","location":{"column":5,"line":18},"name":"@failing"}]},{"description":"","id":"20","keyword":"Examples","location":{"column":5,"line":25},"name":"These are undefined because the value is not an {int}","tableBody":[{"cells":[{"location":{"column":12,"line":27},"value":"12"},{"location":{"column":17,"line":27},"value":"banana"},{"location":{"column":29,"line":27},"value":"12"}],"id":"17","location":{"column":7,"line":27}},{"cells":[{"location":{"column":13,"line":28},"value":"0"},{"location":{"column":22,"line":28},"value":"1"},{"location":{"column":26,"line":28},"value":"apple"}],"id":"18","location":{"column":7,"line":28}}],"tableHeader":{"cells":[{"location":{"column":9,"line":26},"value":"start"},{"location":{"column":17,"line":26},"value":"eat"},{"location":{"column":26,"line":26},"value":"left"}],"id":"16","location":{"column":7,"line":26}},"tags":[{"id":"19","location":{"column":5,"line":24},"name":"@undefined"}]}],"id":"21","keyword":"Scenario Outline","location":{"column":3,"line":7},"name":"eating cucumbers","steps":[{"id":"3","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":8},"text":"there are cucumbers"},{"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":9},"text":"I eat cucumbers"},{"id":"5","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":10},"text":"I should have cucumbers"}],"tags":[]}}],"description":" Sometimes it can be desireable to run the same scenario multiple times\n with different data each time. This can be done by placing an Examples\n section with an Examples Table underneath a Scenario, and use \n in the Scenario, matching the table headers.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables","tags":[]},"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["21","7"],"id":"25","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","7"],"id":"22","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["4","7"],"id":"23","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["5","7"],"id":"24","text":"I should have 7 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"9","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["21","8"],"id":"29","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","8"],"id":"26","text":"there are 20 cucumbers","type":"Context"},{"astNodeIds":["4","8"],"id":"27","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["5","8"],"id":"28","text":"I should have 15 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"9","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["21","12"],"id":"33","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","12"],"id":"30","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["4","12"],"id":"31","text":"I eat 20 cucumbers","type":"Action"},{"astNodeIds":["5","12"],"id":"32","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"14","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["21","13"],"id":"37","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","13"],"id":"34","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["4","13"],"id":"35","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["5","13"],"id":"36","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"14","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["21","17"],"id":"41","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","17"],"id":"38","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["4","17"],"id":"39","text":"I eat banana cucumbers","type":"Action"},{"astNodeIds":["5","17"],"id":"40","text":"I should have 12 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"19","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"pickle":{"astNodeIds":["21","18"],"id":"45","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","18"],"id":"42","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["4","18"],"id":"43","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["5","18"],"id":"44","text":"I should have apple cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"19","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"there are {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"I eat {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"I should have {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"49","pickleId":"25","testSteps":[{"id":"46","pickleStepId":"22","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"47","pickleStepId":"23","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"48","pickleStepId":"24","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"7"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"53","pickleId":"29","testSteps":[{"id":"50","pickleStepId":"26","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"51","pickleStepId":"27","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"52","pickleStepId":"28","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"15"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"57","pickleId":"33","testSteps":[{"id":"54","pickleStepId":"30","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"55","pickleStepId":"31","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"56","pickleStepId":"32","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"61","pickleId":"37","testSteps":[{"id":"58","pickleStepId":"34","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"59","pickleStepId":"35","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"60","pickleStepId":"36","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"65","pickleId":"41","testSteps":[{"id":"62","pickleStepId":"38","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"63","pickleStepId":"39","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"64","pickleStepId":"40","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"12"},"parameterTypeName":"int"}]}]}]}} +{"testCase":{"id":"69","pickleId":"45","testSteps":[{"id":"66","pickleStepId":"42","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"67","pickleStepId":"43","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"68","pickleStepId":"44","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCaseStarted":{"attempt":0,"id":"70","testCaseId":"49","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"70","testStepId":"46","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"70","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"70","testStepId":"47","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"70","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"70","testStepId":"48","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"70","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"70","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"71","testCaseId":"53","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"71","testStepId":"50","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"71","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"71","testStepId":"51","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"71","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"71","testStepId":"52","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"71","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"71","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"72","testCaseId":"57","timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"72","testStepId":"54","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"72","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"72","testStepId":"55","timestamp":{"nanos":20000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"72","testStepId":"55","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"72","testStepId":"56","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"72","testStepId":"56","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-8 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-8 !== 0\n\nsamples/examples-tables/examples-tables.feature:10\nsamples/examples-tables/examples-tables.feature:21","status":"FAILED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"72","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"73","testCaseId":"61","timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"73","testStepId":"58","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"73","testStepId":"58","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"73","testStepId":"59","timestamp":{"nanos":28000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"73","testStepId":"59","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"73","testStepId":"60","timestamp":{"nanos":30000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"73","testStepId":"60","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-1 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-1 !== 0\n\nsamples/examples-tables/examples-tables.feature:10\nsamples/examples-tables/examples-tables.feature:22","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"73","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"74","testCaseId":"65","timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"74","testStepId":"62","timestamp":{"nanos":34000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"74","testStepId":"62","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"74","testStepId":"63","timestamp":{"nanos":36000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"74","testStepId":"63","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":37000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"74","testStepId":"64","timestamp":{"nanos":38000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"74","testStepId":"64","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":39000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"74","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"75","testCaseId":"69","timestamp":{"nanos":41000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"75","testStepId":"66","timestamp":{"nanos":42000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"75","testStepId":"66","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":43000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"75","testStepId":"67","timestamp":{"nanos":44000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"75","testStepId":"67","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"75","testStepId":"68","timestamp":{"nanos":46000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"75","testStepId":"68","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":47000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"75","timestamp":{"nanos":48000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":49000000,"seconds":0}}} diff --git a/python/src/message_samples/examples-tables/examples-tables.feature.ts b/python/src/message_samples/examples-tables/examples-tables.feature.ts new file mode 100644 index 00000000..336cd24b --- /dev/null +++ b/python/src/message_samples/examples-tables/examples-tables.feature.ts @@ -0,0 +1,14 @@ +import assert from 'assert' +import { Given, When, Then } from '@cucumber/fake-cucumber' + +Given('there are {int} cucumbers', function (initialCount) { + this.count = initialCount +}) + +When('I eat {int} cucumbers', function (eatCount) { + this.count -= eatCount +}) + +Then('I should have {int} cucumbers', function (expectedCount) { + assert.strictEqual(this.count, expectedCount) +}) diff --git a/python/src/message_samples/hooks/cucumber.svg b/python/src/message_samples/hooks/cucumber.svg new file mode 100644 index 00000000..537ee11d --- /dev/null +++ b/python/src/message_samples/hooks/cucumber.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/python/src/message_samples/hooks/hooks.feature b/python/src/message_samples/hooks/hooks.feature new file mode 100644 index 00000000..cf6a6b3c --- /dev/null +++ b/python/src/message_samples/hooks/hooks.feature @@ -0,0 +1,20 @@ +Feature: Hooks + Hooks are special steps that run before or after each scenario's steps. + They can also conditionally target specific scenarios, using tag expressions + + Scenario: no tags, passed step + When a step passes + + Scenario: no tags, failed step + When a step throws an exception + + Scenario: no tags, undefined step + When a step throws an exception + + @some-tag + Scenario: with a tag, passed step + When a step passes + + @with-attachment + Scenario: with an attachment in the hook + When a step passes diff --git a/python/src/message_samples/hooks/hooks.feature.ndjson b/python/src/message_samples/hooks/hooks.feature.ndjson new file mode 100644 index 00000000..36b2db13 --- /dev/null +++ b/python/src/message_samples/hooks/hooks.feature.ndjson @@ -0,0 +1,77 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Hooks\n Hooks are special steps that run before or after each scenario's steps.\n They can also conditionally target specific scenarios, using tag expressions\n\n Scenario: no tags, passed step\n When a step passes\n\n Scenario: no tags, failed step\n When a step throws an exception\n\n Scenario: no tags, undefined step\n When a step throws an exception\n\n @some-tag\n Scenario: with a tag, passed step\n When a step passes\n\n @with-attachment\n Scenario: with an attachment in the hook\n When a step passes","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks/hooks.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"8","keyword":"Scenario","location":{"column":3,"line":5},"name":"no tags, passed step","steps":[{"id":"7","keyword":"When ","keywordType":"Action","location":{"column":5,"line":6},"text":"a step passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":8},"name":"no tags, failed step","steps":[{"id":"9","keyword":"When ","keywordType":"Action","location":{"column":5,"line":9},"text":"a step throws an exception"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":11},"name":"no tags, undefined step","steps":[{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":12},"text":"a step throws an exception"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"15","keyword":"Scenario","location":{"column":3,"line":15},"name":"with a tag, passed step","steps":[{"id":"13","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"a step passes"}],"tags":[{"id":"14","location":{"column":3,"line":14},"name":"@some-tag"}]}},{"scenario":{"description":"","examples":[],"id":"18","keyword":"Scenario","location":{"column":3,"line":19},"name":"with an attachment in the hook","steps":[{"id":"16","keyword":"When ","keywordType":"Action","location":{"column":5,"line":20},"text":"a step passes"}],"tags":[{"id":"17","location":{"column":3,"line":18},"name":"@with-attachment"}]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n They can also conditionally target specific scenarios, using tag expressions","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks","tags":[]},"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["8"],"id":"20","language":"en","name":"no tags, passed step","steps":[{"astNodeIds":["7"],"id":"19","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["10"],"id":"22","language":"en","name":"no tags, failed step","steps":[{"astNodeIds":["9"],"id":"21","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["12"],"id":"24","language":"en","name":"no tags, undefined step","steps":[{"astNodeIds":["11"],"id":"23","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["15"],"id":"26","language":"en","name":"with a tag, passed step","steps":[{"astNodeIds":["13"],"id":"25","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"14","name":"@some-tag"}],"uri":"samples/hooks/hooks.feature"}} +{"pickle":{"astNodeIds":["18"],"id":"28","language":"en","name":"with an attachment in the hook","steps":[{"astNodeIds":["16"],"id":"27","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"17","name":"@with-attachment"}],"uri":"samples/hooks/hooks.feature"}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/hooks/hooks.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/hooks/hooks.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":4},"uri":"samples/hooks/hooks.feature.ts"}}} +{"hook":{"id":"1","name":"A named hook","sourceReference":{"location":{"line":8},"uri":"samples/hooks/hooks.feature.ts"}}} +{"hook":{"id":"4","sourceReference":{"location":{"line":20},"uri":"samples/hooks/hooks.feature.ts"}}} +{"hook":{"id":"5","sourceReference":{"location":{"line":24},"uri":"samples/hooks/hooks.feature.ts"},"tagExpression":"@some-tag or @some-other-tag"}} +{"hook":{"id":"6","sourceReference":{"location":{"line":28},"uri":"samples/hooks/hooks.feature.ts"},"tagExpression":"@with-attachment"}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"33","pickleId":"20","testSteps":[{"hookId":"0","id":"29"},{"hookId":"1","id":"30"},{"id":"31","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"32"}]}} +{"testCase":{"id":"38","pickleId":"22","testSteps":[{"hookId":"0","id":"34"},{"hookId":"1","id":"35"},{"id":"36","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"37"}]}} +{"testCase":{"id":"43","pickleId":"24","testSteps":[{"hookId":"0","id":"39"},{"hookId":"1","id":"40"},{"id":"41","pickleStepId":"23","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"42"}]}} +{"testCase":{"id":"49","pickleId":"26","testSteps":[{"hookId":"0","id":"44"},{"hookId":"1","id":"45"},{"id":"46","pickleStepId":"25","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"5","id":"47"},{"hookId":"4","id":"48"}]}} +{"testCase":{"id":"55","pickleId":"28","testSteps":[{"hookId":"0","id":"50"},{"hookId":"1","id":"51"},{"id":"52","pickleStepId":"27","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"6","id":"53"},{"hookId":"4","id":"54"}]}} +{"testCaseStarted":{"attempt":0,"id":"56","testCaseId":"33","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"29","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"30","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"31","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"56","testStepId":"32","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"56","testStepId":"32","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:5","status":"FAILED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"56","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"57","testCaseId":"38","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"34","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"34","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"35","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"35","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"36","timestamp":{"nanos":16000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"36","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/hooks/hooks.feature:9","status":"FAILED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"57","testStepId":"37","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"57","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:8","status":"FAILED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"57","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"58","testCaseId":"43","timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"58","testStepId":"39","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"58","testStepId":"39","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"58","testStepId":"40","timestamp":{"nanos":24000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"58","testStepId":"40","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"58","testStepId":"41","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"58","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/hooks/hooks.feature:12","status":"FAILED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"58","testStepId":"42","timestamp":{"nanos":28000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"58","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:11","status":"FAILED"},"timestamp":{"nanos":29000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"58","timestamp":{"nanos":30000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"59","testCaseId":"49","timestamp":{"nanos":31000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"59","testStepId":"44","timestamp":{"nanos":32000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"59","testStepId":"44","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"59","testStepId":"45","timestamp":{"nanos":34000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"59","testStepId":"45","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"59","testStepId":"46","timestamp":{"nanos":36000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"59","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":37000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"59","testStepId":"47","timestamp":{"nanos":38000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"59","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in conditional hook","type":"Error"},"message":"Exception in conditional hook\nsamples/hooks/hooks.feature:15","status":"FAILED"},"timestamp":{"nanos":39000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"59","testStepId":"48","timestamp":{"nanos":40000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"59","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:15","status":"FAILED"},"timestamp":{"nanos":41000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"59","timestamp":{"nanos":42000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"60","testCaseId":"55","timestamp":{"nanos":43000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"60","testStepId":"50","timestamp":{"nanos":44000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"60","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"60","testStepId":"51","timestamp":{"nanos":46000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"60","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":47000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"60","testStepId":"52","timestamp":{"nanos":48000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"60","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":49000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"60","testStepId":"53","timestamp":{"nanos":50000000,"seconds":0}}} +{"attachment":{"body":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJtbC0zIG1sLW1kLTAiIHZpZXdCb3g9IjAgMCA0MC41OSA0Ni4zMSIgd2lkdGg9IjQwLjU5IiBoZWlnaHQ9IjQ2LjMxIj4KICAgIDxnPgogICAgICAgIDxwYXRoIGZpbGw9IiMyM2Q5NmMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLjI4MyAzLjY0NXEtLjUyOC0uMzE3LTEuMDgtLjU5M2ExNi4xNjQgMTYuMTY0IDAgMDAtMS4xNTQtLjUxOGMtLjEyNC0uMDUyLS4yNDctLjEtLjM3Mi0uMTQ5LS4zNDMtLjEyNy0uNjg5LS4yNjgtMS4wNDItLjM3MWExOS40MjcgMTkuNDI3IDAgMTAtOS43OTIgMzcuNTF2NS41NmMxMS42NzYtMS43NTMgMjIuMDE2LTEwLjk3OSAyMi43ODctMjMuMDkzLjQ1OS03LjI4OS0zLjE5My0xNC43My05LjM0Ny0xOC4zNDZ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZD0iTTE1Ljc4NyA0Ni4zMDd2LTUuOTM1QTIwLjQ3MiAyMC40NzIgMCAxMTI2Ljk1OSAxLjAxNWMuMjc0LjA4LjU1Ny4xODcuODMyLjI5MWwuMjQ4LjA5M2MuMTY1LjA2NC4yOTEuMTEzLjQxNy4xNjcuMzQ4LjEzNy43MzkuMzEzIDEuMjA4LjU0M3EuNTg5LjI5NSAxLjE1My42MzNjNi4zOTMgMy43NTYgMTAuMzU0IDExLjUxOCA5Ljg1NyAxOS4zMTYtLjc2MyAxMi0xMC43MjIgMjIuMTIyLTIzLjY3OSAyNC4wNjd6bTQuOC00NC4yMTRoLS4wMjZhMTguMzY2IDE4LjM2NiAwIDAwLTMuNTI0IDM2LjQwOGwuODUuMTY1djUuMThjMTEuMzkyLTIuMjI0IDIwLjAwOS0xMS4yNzIgMjAuNjg2LTIxLjkyMi40NDgtNy4wMzMtMy4xLTE0LjAxOC04LjgzLTE3LjM4M2wtLjAwOC0uMDA1QTE0LjY5MSAxNC42OTEgMCAwMDI3LjY1NCAzLjVhNS43NCA1Ljc0IDAgMDAtLjM0NC0uMTM4bC0uMjctLjFhOS40OSA5LjQ5IDAgMDAtLjcwOC0uMjQ5IDE4LjQyNSAxOC40MjUgMCAwMC01Ljc0My0uOTJ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTYuNjY2IDEwLjU4YTEuOCAxLjggMCAwMTEuNTgzLjYwOCA0LjE4NCA0LjE4NCAwIDAxLjcyOCAxLjEwN2MuNjQ1IDEuNDIyIDEuMDI3IDMuNDYxLjIzIDQuNjA1YTYuMzM0IDYuMzM0IDAgMDEtMy45ODEtMy4wODcgMy4yMzYgMy4yMzYgMCAwMS0uMzQ3LTEuMzM5IDEuOTU3IDEuOTU3IDAgMDExLjc4Ny0xLjg5NHptLTUuNjgzIDguMDI1YTcuNzQyIDcuNzQyIDAgMDAxLjIxOC43MzcgNS43ODkgNS43ODkgMCAwMDQuODgzLS4xMzggNi4xMTYgNi4xMTYgMCAwMC0zLjM0NS0zLjQ1IDMuNjY0IDMuNjY0IDAgMDAtMS40NDItLjMyMSAxLjg4NCAxLjg4NCAwIDAwLS4zMTkgMCAxLjc2NiAxLjc2NiAwIDAwLS45OTUgMy4xNzJ6bTYuMSAzLjQzM2MtLjc3Ny0uNTE4LTIuMzc5LS4zMDktMy4zMTItLjI5MmE0LjQxNiA0LjQxNiAwIDAwLTEuNjY2LjM1MiAzLjUgMy41IDAgMDAtMS4yMTguNzM4IDEuODE3IDEuODE3IDAgMDAxLjQwOSAzLjE3MSAzLjMgMy4zIDAgMDAxLjQ0Mi0uMzIxYzEuNDM2LS42MiAzLjE0MS0yLjMyIDMuMzQ2LTMuNjQ4em0yLjYxIDJhNi41NTYgNi41NTYgMCAwMC0zLjcyNCAzLjUwNiAzLjA5MSAzLjA5MSAwIDAwLS4zMjEgMS4zMTQgMS45MDcgMS45MDcgMCAwMDMuMyAxLjM0NiA3LjQyMiA3LjQyMiAwIDAwLjctMS4yMThjLjYyMS0xLjMzMy44NjYtMy43Mi4wNDYtNC45NDh6bTIuNTU3LTcuMTY3YTUuOTQxIDUuOTQxIDAgMDAzLjctMy4xNjcgMy4yNDMgMy4yNDMgMCAwMC4zMTktMS4zNDYgMS45MTUgMS45MTUgMCAwMC0xLjc5NC0xLjk1NCAxLjgzMiAxLjgzMiAwIDAwLTEuNi42NDEgNy4zODIgNy4zODIgMCAwMC0uNzA1IDEuMjE4Yy0uNjIgMS40MzQtLjg0MiAzLjQ4LjA4MSA0LjYwM3ptNC4yMDggMTIuMTE1YTMuMjQ0IDMuMjQ0IDAgMDAtLjMyMS0xLjM0NSA1Ljg2OSA1Ljg2OSAwIDAwLTMuNTU0LTMuMjY5IDUuMzg2IDUuMzg2IDAgMDAtLjIyNiA0LjcxMSA0LjE0NyA0LjE0NyAwIDAwLjcgMS4xMjFjMS4xMzMgMS4yMyAzLjUwNS4zMiAzLjQwMi0xLjIxOHptNC4yLTYuMjhhNy40NjYgNy40NjYgMCAwMC0xLjIxNy0uNyA0LjQyNSA0LjQyNSAwIDAwLTEuNjY2LS4zNTIgNi40IDYuNCAwIDAwLTMuMTg4LjU1NSA1Ljk1OSA1Ljk1OSAwIDAwMy4zMTYgMy4zODYgMy42NzIgMy42NzIgMCAwMDEuNDQyLjMyIDEuOCAxLjggMCAwMDEuMzEtMy4yMDl6Ii8+CiAgICA8L2c+Cjwvc3ZnPg==","contentEncoding":"BASE64","mediaType":"image/svg+xml","testCaseStartedId":"60","testStepId":"53"}} +{"testStepFinished":{"testCaseStartedId":"60","testStepId":"53","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":51000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"60","testStepId":"54","timestamp":{"nanos":52000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"60","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:19","status":"FAILED"},"timestamp":{"nanos":53000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"60","timestamp":{"nanos":54000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":55000000,"seconds":0}}} diff --git a/python/src/message_samples/hooks/hooks.feature.ts b/python/src/message_samples/hooks/hooks.feature.ts new file mode 100644 index 00000000..632190cf --- /dev/null +++ b/python/src/message_samples/hooks/hooks.feature.ts @@ -0,0 +1,30 @@ +import { When, Before, After } from '@cucumber/fake-cucumber' +import fs from 'fs' + +Before(function () { + // no-op +}) + +Before({name: 'A named hook'}, function () { + // no-op +}) + +When('a step passes', function () { + // no-op +}) + +When('a step throws an exception', function () { + throw new Error('Exception in step') +}) + +After(function () { + throw new Error('Exception in hook') +}) + +After('@some-tag or @some-other-tag', function () { + throw new Error('Exception in conditional hook') +}) + +After('@with-attachment', async function () { + await this.attach(fs.createReadStream(__dirname + '/cucumber.svg'), 'image/svg+xml') +}) diff --git a/python/src/message_samples/markdown/markdown.feature.md b/python/src/message_samples/markdown/markdown.feature.md new file mode 100644 index 00000000..e0cdec5b --- /dev/null +++ b/python/src/message_samples/markdown/markdown.feature.md @@ -0,0 +1,46 @@ +# Feature: Cheese + +This table is not picked up by Gherkin (not indented 2+ spaces) + +| foo | bar | +| --- | --- | +| boz | boo | + + +## Rule: Nom nom nom + +I love cheese, especially fromage macaroni cheese. Rubber cheese ricotta caerphilly blue castello who moved my cheese queso bavarian bergkase melted cheese. + +### Scenario Outline: Ylajali! + +* Given some TypeScript code: + ```typescript + type Cheese = 'reblochon' | 'roquefort' | 'rocamadour' + ``` +* And some classic Gherkin: + ```gherkin + Given there are 24 apples in Mary's basket + ``` +* When we use a data table and attach something and then + | name | age | + | ---- | --: | + | Bill | 3 | + | Jane | 6 | + | Isla | 5 | +* Then this might or might not run + +#### Examples: because we need more tables + +This table is indented 2 spaces, so Gherkin will pick it up + + | what | + | ---- | + | fail | + | pass | + +And oh by the way, this table is also ignored by Gherkin because it doesn't have 2+ space indent: + +| cheese | +| -------- | +| gouda | +| gamalost | diff --git a/python/src/message_samples/markdown/markdown.feature.md.ndjson b/python/src/message_samples/markdown/markdown.feature.md.ndjson new file mode 100644 index 00000000..c4afc018 --- /dev/null +++ b/python/src/message_samples/markdown/markdown.feature.md.ndjson @@ -0,0 +1,35 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"# Feature: Cheese\n\nThis table is not picked up by Gherkin (not indented 2+ spaces)\n\n| foo | bar |\n| --- | --- |\n| boz | boo |\n\n\n## Rule: Nom nom nom\n\nI love cheese, especially fromage macaroni cheese. Rubber cheese ricotta caerphilly blue castello who moved my cheese queso bavarian bergkase melted cheese.\n\n### Scenario Outline: Ylajali!\n\n* Given some TypeScript code:\n ```typescript\n type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'\n ```\n* And some classic Gherkin:\n ```gherkin\n Given there are 24 apples in Mary's basket\n ```\n* When we use a data table and attach something and then \n | name | age |\n | ---- | --: |\n | Bill | 3 |\n | Jane | 6 |\n | Isla | 5 |\n* Then this might or might not run\n\n#### Examples: because we need more tables\n\nThis table is indented 2 spaces, so Gherkin will pick it up\n\n | what |\n | ---- |\n | fail |\n | pass |\n\nAnd oh by the way, this table is also ignored by Gherkin because it doesn't have 2+ space indent:\n\n| cheese |\n| -------- |\n| gouda |\n| gamalost |\n","mediaType":"text/x.cucumber.gherkin+markdown","uri":"samples/markdown/markdown.feature.md"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"15","keyword":"Examples","location":{"column":6,"line":32},"name":"because we need more tables","tableBody":[{"cells":[{"location":{"column":5,"line":38},"value":"fail"}],"id":"13","location":{"column":3,"line":38}},{"cells":[{"location":{"column":5,"line":39},"value":"pass"}],"id":"14","location":{"column":3,"line":39}}],"tableHeader":{"cells":[{"location":{"column":5,"line":36},"value":"what"}],"id":"12","location":{"column":3,"line":36}},"tags":[]}],"id":"16","keyword":"Scenario Outline","location":{"column":5,"line":14},"name":"Ylajali!","steps":[{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","delimiter":"```","location":{"column":3,"line":17},"mediaType":"typescript"},"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":3,"line":16},"text":"some TypeScript code:"},{"docString":{"content":"Given there are 24 apples in Mary's basket","delimiter":"```","location":{"column":3,"line":21},"mediaType":"gherkin"},"id":"5","keyword":"And ","keywordType":"Conjunction","location":{"column":3,"line":20},"text":"some classic Gherkin:"},{"dataTable":{"location":{"column":3,"line":25},"rows":[{"cells":[{"location":{"column":5,"line":25},"value":"name"},{"location":{"column":12,"line":25},"value":"age"}],"id":"6","location":{"column":3,"line":25}},{"cells":[{"location":{"column":5,"line":27},"value":"Bill"},{"location":{"column":14,"line":27},"value":"3"}],"id":"7","location":{"column":3,"line":27}},{"cells":[{"location":{"column":5,"line":28},"value":"Jane"},{"location":{"column":14,"line":28},"value":"6"}],"id":"8","location":{"column":3,"line":28}},{"cells":[{"location":{"column":5,"line":29},"value":"Isla"},{"location":{"column":14,"line":29},"value":"5"}],"id":"9","location":{"column":3,"line":29}}]},"id":"10","keyword":"When ","keywordType":"Action","location":{"column":3,"line":24},"text":"we use a data table and attach something and then "},{"id":"11","keyword":"Then ","keywordType":"Outcome","location":{"column":3,"line":30},"text":"this might or might not run"}],"tags":[]}}],"description":"","id":"17","keyword":"Rule","location":{"column":4,"line":10},"name":"Nom nom nom","tags":[]}}],"description":"","keyword":"Feature","language":"en","location":{"column":3,"line":1},"name":"Cheese","tags":[]},"uri":"samples/markdown/markdown.feature.md"}} +{"pickle":{"astNodeIds":["16","13"],"id":"22","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","13"],"id":"18","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","13"],"id":"19","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","13"],"id":"20","text":"we use a data table and attach something and then fail","type":"Action"},{"astNodeIds":["11","13"],"id":"21","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} +{"pickle":{"astNodeIds":["16","14"],"id":"27","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","14"],"id":"23","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","14"],"id":"24","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","14"],"id":"25","text":"we use a data table and attach something and then pass","type":"Action"},{"astNodeIds":["11","14"],"id":"26","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} +{"stepDefinition":{"id":"0","pattern":{"source":"some TypeScript code:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"some classic Gherkin:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"we use a data table and attach something and then {word}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"this might or might not run","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/markdown/markdown.feature.md.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"32","pickleId":"22","testSteps":[{"id":"28","pickleStepId":"18","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"29","pickleStepId":"19","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"30","pickleStepId":"20","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"fail"},"parameterTypeName":"word"}]}]},{"id":"31","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"37","pickleId":"27","testSteps":[{"id":"33","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"34","pickleStepId":"24","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"35","pickleStepId":"25","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"pass"},"parameterTypeName":"word"}]}]},{"id":"36","pickleStepId":"26","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"38","testCaseId":"32","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"38","testStepId":"28","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"38","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"38","testStepId":"29","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"38","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"38","testStepId":"30","timestamp":{"nanos":6000000,"seconds":0}}} +{"attachment":{"body":"We are logging some plain text (fail)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"38","testStepId":"30"}} +{"testStepFinished":{"testCaseStartedId":"38","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"You asked me to fail","type":"Error"},"message":"You asked me to fail\nsamples/markdown/markdown.feature.md:24\nsamples/markdown/markdown.feature.md:38","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"38","testStepId":"31","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"38","testStepId":"31","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"38","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"39","testCaseId":"37","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"33","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"33","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"34","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"34","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"35","timestamp":{"nanos":16000000,"seconds":0}}} +{"attachment":{"body":"We are logging some plain text (pass)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"39","testStepId":"35"}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"35","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"36","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"36","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":21000000,"seconds":0}}} diff --git a/python/src/message_samples/markdown/markdown.feature.md.ts b/python/src/message_samples/markdown/markdown.feature.md.ts new file mode 100644 index 00000000..de8bbdc5 --- /dev/null +++ b/python/src/message_samples/markdown/markdown.feature.md.ts @@ -0,0 +1,25 @@ +import assert from 'assert' +import { Given, When, Then } from '@cucumber/fake-cucumber' + +Given('some TypeScript code:', function (dataTable: string[][]) { + assert(dataTable) +}) + +Given('some classic Gherkin:', function (gherkin: string) { + assert(gherkin) +}) + +When( + 'we use a data table and attach something and then {word}', + function (word: string, dataTable: string[][]) { + assert(dataTable) + this.log(`We are logging some plain text (${word})`) + if (word === 'fail') { + throw new Error('You asked me to fail') + } + } +) + +Then('this might or might not run', function () { + // no-op +}) diff --git a/python/src/message_samples/minimal/minimal.feature b/python/src/message_samples/minimal/minimal.feature new file mode 100644 index 00000000..9bc37141 --- /dev/null +++ b/python/src/message_samples/minimal/minimal.feature @@ -0,0 +1,10 @@ +Feature: minimal + + Cucumber doesn't execute this markdown, but @cucumber/react renders it + + * This is + * a bullet + * list + + Scenario: cukes + Given I have 42 cukes in my belly diff --git a/python/src/message_samples/minimal/minimal.feature.ndjson b/python/src/message_samples/minimal/minimal.feature.ndjson new file mode 100644 index 00000000..da9d4f22 --- /dev/null +++ b/python/src/message_samples/minimal/minimal.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: minimal\n \n Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list\n \n Scenario: cukes\n Given I have 42 cukes in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/minimal/minimal.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":9},"name":"cukes","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"I have 42 cukes in my belly"}],"tags":[]}}],"description":" Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"minimal","tags":[]},"uri":"samples/minimal/minimal.feature"}} +{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cukes","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 cukes in my belly","type":"Context"}],"tags":[],"uri":"samples/minimal/minimal.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} cukes in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/minimal/minimal.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"6","pickleId":"4","testSteps":[{"id":"5","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/minimal/minimal.feature.ts b/python/src/message_samples/minimal/minimal.feature.ts new file mode 100644 index 00000000..941b5ebf --- /dev/null +++ b/python/src/message_samples/minimal/minimal.feature.ts @@ -0,0 +1,6 @@ +import assert from 'assert' +import { Given } from '@cucumber/fake-cucumber' + +Given('I have {int} cukes in my belly', function (cukeCount: number) { + assert(cukeCount) +}) diff --git a/python/src/message_samples/parameter-types/parameter-types.feature b/python/src/message_samples/parameter-types/parameter-types.feature new file mode 100644 index 00000000..5b1422f4 --- /dev/null +++ b/python/src/message_samples/parameter-types/parameter-types.feature @@ -0,0 +1,9 @@ +Feature: Parameter Types + Cucumber lets you define your own parameter types, which can be used + in Cucumber Expressions. This lets you define a precise domain-specific + vocabulary which can be used to generate a glossary with examples taken + from your scenarios. They also let you transform strings and tables into + rich types. + + Scenario: flights + Given LHR-CDG has been delayed 45 minutes diff --git a/python/src/message_samples/parameter-types/parameter-types.feature.ndjson b/python/src/message_samples/parameter-types/parameter-types.feature.ndjson new file mode 100644 index 00000000..61a88074 --- /dev/null +++ b/python/src/message_samples/parameter-types/parameter-types.feature.ndjson @@ -0,0 +1,13 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Parameter Types\n Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions. This lets you define a precise domain-specific\n vocabulary which can be used to generate a glossary with examples taken\n from your scenarios. They also let you transform strings and tables into\n rich types.\n\n Scenario: flights\n Given LHR-CDG has been delayed 45 minutes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/parameter-types/parameter-types.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":8},"name":"flights","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":9},"text":"LHR-CDG has been delayed 45 minutes"}],"tags":[]}}],"description":" Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions. This lets you define a precise domain-specific\n vocabulary which can be used to generate a glossary with examples taken\n from your scenarios. They also let you transform strings and tables into\n rich types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/parameter-types/parameter-types.feature"}} +{"pickle":{"astNodeIds":["3"],"id":"5","language":"en","name":"flights","steps":[{"astNodeIds":["2"],"id":"4","text":"LHR-CDG has been delayed 45 minutes","type":"Context"}],"tags":[],"uri":"samples/parameter-types/parameter-types.feature"}} +{"parameterType":{"id":"0","name":"flight","preferForRegularExpressionMatch":false,"regularExpressions":["([A-Z]{3})-([A-Z]{3})"],"sourceReference":{"location":{"line":8},"uri":"samples/parameter-types/parameter-types.feature.ts"},"useForSnippets":true}} +{"stepDefinition":{"id":"1","pattern":{"source":"{flight} has been delayed {int} minutes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/parameter-types/parameter-types.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"7","pickleId":"5","testSteps":[{"id":"6","pickleStepId":"4","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[],"start":0,"value":"LHR"},{"children":[],"start":4,"value":"CDG"}],"start":0,"value":"LHR-CDG"},"parameterTypeName":"flight"},{"group":{"children":[],"start":25,"value":"45"},"parameterTypeName":"int"}]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/parameter-types/parameter-types.feature.ts b/python/src/message_samples/parameter-types/parameter-types.feature.ts new file mode 100644 index 00000000..ece172c3 --- /dev/null +++ b/python/src/message_samples/parameter-types/parameter-types.feature.ts @@ -0,0 +1,20 @@ +import assert from 'assert' +import { Given, ParameterType } from '@cucumber/fake-cucumber' + +class Flight { + constructor(public readonly from: string, public readonly to: string) {} +} + +ParameterType({ + name: 'flight', + regexp: /([A-Z]{3})-([A-Z]{3})/, + transformer(from: string, to: string) { + return new Flight(from, to) + }, +}) + +Given('{flight} has been delayed {int} minutes', function (flight: Flight, delay: number) { + assert.strictEqual(flight.from, 'LHR') + assert.strictEqual(flight.to, 'CDG') + assert.strictEqual(delay, 45) +}) diff --git a/python/src/message_samples/pending/pending.feature b/python/src/message_samples/pending/pending.feature new file mode 100644 index 00000000..cc5ea421 --- /dev/null +++ b/python/src/message_samples/pending/pending.feature @@ -0,0 +1,19 @@ +Feature: Pending steps + + During development, step definitions can signal at runtime that they are + not yet implemented (or "pending") by returning or throwing a particular + value. + + This causes subsequent steps in the scenario to be skipped, and the overall + result to be treated as a failure. + + Scenario: Unimplemented step signals pending status + Given a step that isnt implemented yet + + Scenario: Steps before unimplemented steps are executed + Given an implemented step + When a step that isnt implemented yet + + Scenario: Steps after unimplemented steps are skipped + Given a step that isnt implemented yet + Then a step that we expect to be skipped diff --git a/python/src/message_samples/pending/pending.feature.ndjson b/python/src/message_samples/pending/pending.feature.ndjson new file mode 100644 index 00000000..e95ebb87 --- /dev/null +++ b/python/src/message_samples/pending/pending.feature.ndjson @@ -0,0 +1,30 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Pending steps\n\n During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.\n\n Scenario: Unimplemented step signals pending status\n Given a step that isnt implemented yet\n\n Scenario: Steps before unimplemented steps are executed\n Given an implemented step\n When a step that isnt implemented yet\n\n Scenario: Steps after unimplemented steps are skipped\n Given a step that isnt implemented yet\n Then a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/pending/pending.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":10},"name":"Unimplemented step signals pending status","steps":[{"id":"3","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":13},"name":"Steps before unimplemented steps are executed","steps":[{"id":"5","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":14},"text":"an implemented step"},{"id":"6","keyword":"When ","keywordType":"Action","location":{"column":5,"line":15},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":17},"name":"Steps after unimplemented steps are skipped","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"a step that isnt implemented yet"},{"id":"9","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":19},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Pending steps","tags":[]},"uri":"samples/pending/pending.feature"}} +{"pickle":{"astNodeIds":["4"],"id":"12","language":"en","name":"Unimplemented step signals pending status","steps":[{"astNodeIds":["3"],"id":"11","text":"a step that isnt implemented yet","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} +{"pickle":{"astNodeIds":["7"],"id":"15","language":"en","name":"Steps before unimplemented steps are executed","steps":[{"astNodeIds":["5"],"id":"13","text":"an implemented step","type":"Context"},{"astNodeIds":["6"],"id":"14","text":"a step that isnt implemented yet","type":"Action"}],"tags":[],"uri":"samples/pending/pending.feature"}} +{"pickle":{"astNodeIds":["10"],"id":"18","language":"en","name":"Steps after unimplemented steps are skipped","steps":[{"astNodeIds":["8"],"id":"16","text":"a step that isnt implemented yet","type":"Context"},{"astNodeIds":["9"],"id":"17","text":"a step that we expect to be skipped","type":"Outcome"}],"tags":[],"uri":"samples/pending/pending.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/pending/pending.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step that isnt implemented yet","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/pending/pending.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/pending/pending.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"20","pickleId":"12","testSteps":[{"id":"19","pickleStepId":"11","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"23","pickleId":"15","testSteps":[{"id":"21","pickleStepId":"13","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"22","pickleStepId":"14","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"26","pickleId":"18","testSteps":[{"id":"24","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"25","pickleStepId":"17","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"20","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"27","testStepId":"19","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"27","testStepId":"19","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PENDING"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"23","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"21","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"22","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PENDING"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"26","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"24","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PENDING"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"29","testStepId":"25","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"29","testStepId":"25","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/python/src/message_samples/pending/pending.feature.ts b/python/src/message_samples/pending/pending.feature.ts new file mode 100644 index 00000000..7f66ae22 --- /dev/null +++ b/python/src/message_samples/pending/pending.feature.ts @@ -0,0 +1,13 @@ +import { Given } from '@cucumber/fake-cucumber' + +Given('an implemented step', function () { + // no-op +}) + +Given('a step that isnt implemented yet', function () { + return 'pending' +}) + +Given('a step that we expect to be skipped', function () { + // no-op +}) diff --git a/python/src/message_samples/retry/retry.arguments.txt b/python/src/message_samples/retry/retry.arguments.txt new file mode 100644 index 00000000..cf83a555 --- /dev/null +++ b/python/src/message_samples/retry/retry.arguments.txt @@ -0,0 +1 @@ +--retry 2 diff --git a/python/src/message_samples/retry/retry.feature b/python/src/message_samples/retry/retry.feature new file mode 100644 index 00000000..79f9188d --- /dev/null +++ b/python/src/message_samples/retry/retry.feature @@ -0,0 +1,22 @@ +Feature: Retry + + Some Cucumber implementations support a Retry mechanism, where test cases that fail + can be retried up to a limited number of attempts in the same test run. + + Non-passing statuses other than FAILED don't trigger a retry - they are not going to pass + however many times we attempt them. + + Scenario: test case passes on the first attempt + Given a step that always passes + + Scenario: test case passes on the second attempt + Given a step that passes the second time + + Scenario: test case passes on the final attempt + Given a step that passes the third time + + Scenario: test case fails on every attempt + Given a step that always fails + + Scenario: don't retry on UNDEFINED + Given a non-existent step diff --git a/python/src/message_samples/retry/retry.feature.ndjson b/python/src/message_samples/retry/retry.feature.ndjson new file mode 100644 index 00000000..3f01aaf9 --- /dev/null +++ b/python/src/message_samples/retry/retry.feature.ndjson @@ -0,0 +1,59 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Retry\n\n Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED don't trigger a retry - they are not going to pass\n however many times we attempt them.\n\n Scenario: test case passes on the first attempt\n Given a step that always passes\n\n Scenario: test case passes on the second attempt\n Given a step that passes the second time\n\n Scenario: test case passes on the final attempt\n Given a step that passes the third time\n\n Scenario: test case fails on every attempt\n Given a step that always fails\n\n Scenario: don't retry on UNDEFINED\n Given a non-existent step\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/retry/retry.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"5","keyword":"Scenario","location":{"column":3,"line":9},"name":"test case passes on the first attempt","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"a step that always passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":12},"name":"test case passes on the second attempt","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":13},"text":"a step that passes the second time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":15},"name":"test case passes on the final attempt","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":16},"text":"a step that passes the third time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"11","keyword":"Scenario","location":{"column":3,"line":18},"name":"test case fails on every attempt","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":19},"text":"a step that always fails"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":21},"name":"don't retry on UNDEFINED","steps":[{"id":"12","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":22},"text":"a non-existent step"}],"tags":[]}}],"description":" Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED don't trigger a retry - they are not going to pass\n however many times we attempt them.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Retry","tags":[]},"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["5"],"id":"15","language":"en","name":"test case passes on the first attempt","steps":[{"astNodeIds":["4"],"id":"14","text":"a step that always passes","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["7"],"id":"17","language":"en","name":"test case passes on the second attempt","steps":[{"astNodeIds":["6"],"id":"16","text":"a step that passes the second time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"19","language":"en","name":"test case passes on the final attempt","steps":[{"astNodeIds":["8"],"id":"18","text":"a step that passes the third time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["11"],"id":"21","language":"en","name":"test case fails on every attempt","steps":[{"astNodeIds":["10"],"id":"20","text":"a step that always fails","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"pickle":{"astNodeIds":["13"],"id":"23","language":"en","name":"don't retry on UNDEFINED","steps":[{"astNodeIds":["12"],"id":"22","text":"a non-existent step","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"a step that always passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/retry/retry.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step that passes the second time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/retry/retry.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step that passes the third time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/retry/retry.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"a step that always fails","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/retry/retry.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"25","pickleId":"15","testSteps":[{"id":"24","pickleStepId":"14","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"27","pickleId":"17","testSteps":[{"id":"26","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"29","pickleId":"19","testSteps":[{"id":"28","pickleStepId":"18","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"31","pickleId":"21","testSteps":[{"id":"30","pickleStepId":"20","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"33","pickleId":"23","testSteps":[{"id":"32","pickleStepId":"22","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCaseStarted":{"attempt":0,"id":"34","testCaseId":"25","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"34","testStepId":"24","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"34","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"34","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"35","testCaseId":"27","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"35","testStepId":"26","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"35","testStepId":"26","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:13","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"35","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":1,"id":"36","testCaseId":"27","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"36","testStepId":"26","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"36","testStepId":"26","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"36","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"37","testCaseId":"29","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"37","testStepId":"28","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"37","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:16","status":"FAILED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"37","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":1,"id":"38","testCaseId":"29","timestamp":{"nanos":17000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"38","testStepId":"28","timestamp":{"nanos":18000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"38","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:16","status":"FAILED"},"timestamp":{"nanos":19000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"38","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":2,"id":"39","testCaseId":"29","timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"39","testStepId":"28","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"39","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"40","testCaseId":"31","timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"40","testStepId":"30","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"40","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:19","status":"FAILED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"40","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":1,"id":"41","testCaseId":"31","timestamp":{"nanos":29000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"41","testStepId":"30","timestamp":{"nanos":30000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"41","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:19","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"41","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":true}} +{"testCaseStarted":{"attempt":2,"id":"42","testCaseId":"31","timestamp":{"nanos":33000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"42","testStepId":"30","timestamp":{"nanos":34000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"42","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:19","status":"FAILED"},"timestamp":{"nanos":35000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"42","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"43","testCaseId":"33","timestamp":{"nanos":37000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"43","testStepId":"32","timestamp":{"nanos":38000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"43","testStepId":"32","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":39000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"43","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":41000000,"seconds":0}}} diff --git a/python/src/message_samples/retry/retry.feature.ts b/python/src/message_samples/retry/retry.feature.ts new file mode 100644 index 00000000..077e37cd --- /dev/null +++ b/python/src/message_samples/retry/retry.feature.ts @@ -0,0 +1,25 @@ +import { Given } from '@cucumber/fake-cucumber' + +Given('a step that always passes', function () { + // no-op +}) + +let secondTimePass = 0 +Given('a step that passes the second time', function () { + secondTimePass++ + if (secondTimePass < 2) { + throw new Error('Exception in step') + } +}) + +let thirdTimePass = 0 +Given('a step that passes the third time', function () { + thirdTimePass++ + if (thirdTimePass < 3) { + throw new Error('Exception in step') + } +}) + +Given('a step that always fails', function () { + throw new Error('Exception in step') +}) diff --git a/python/src/message_samples/rules/rules.feature b/python/src/message_samples/rules/rules.feature new file mode 100644 index 00000000..c45c9ed3 --- /dev/null +++ b/python/src/message_samples/rules/rules.feature @@ -0,0 +1,27 @@ +Feature: Rules + You can place scenarios inside rules. This makes is possible to structure + Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/). + You can also use the Examples synonym for Scenario to make them even more similar. + + Rule: a sale cannot happen if change cannot be returned + # sad path + Example: no change + Given there are 5 0.20 coins inside + When the customer tries to buy a 0.85 chocolate with a 1 coin + Then the sale should not happen + + # happy path + Example: exact change + Given there are 5 0.20 coins inside + And there are 3 chocolates inside + When the customer tries to buy a 0.80 chocolate with a 1 coin + Then the customer's change should be 1 0.20 coin + + @some-tag + Rule: a sale cannot happen if we're out of stock + # sad path + Example: no chocolates left + Given there are no chocolates inside + But there are 10 0.5 coins inside + When the customer tries to buy a 0.85 chocolate with a 1 coin + Then the sale should not happen diff --git a/python/src/message_samples/rules/rules.feature.ndjson b/python/src/message_samples/rules/rules.feature.ndjson new file mode 100644 index 00000000..574b52b5 --- /dev/null +++ b/python/src/message_samples/rules/rules.feature.ndjson @@ -0,0 +1,45 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Rules\n You can place scenarios inside rules. This makes is possible to structure\n Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n You can also use the Examples synonym for Scenario to make them even more similar.\n\n Rule: a sale cannot happen if change cannot be returned\n # sad path\n Example: no change\n Given there are 5 0.20 coins inside\n When the customer tries to buy a 0.85 chocolate with a 1 coin\n Then the sale should not happen\n\n # happy path\n Example: exact change\n Given there are 5 0.20 coins inside\n And there are 3 chocolates inside\n When the customer tries to buy a 0.80 chocolate with a 1 coin\n Then the customer's change should be 1 0.20 coin\n\n @some-tag\n Rule: a sale cannot happen if we're out of stock\n # sad path\n Example: no chocolates left\n Given there are no chocolates inside\n But there are 10 0.5 coins inside\n When the customer tries to buy a 0.85 chocolate with a 1 coin\n Then the sale should not happen\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/rules/rules.feature"}} +{"gherkinDocument":{"comments":[{"location":{"column":1,"line":7},"text":" # sad path"},{"location":{"column":1,"line":13},"text":" # happy path"},{"location":{"column":1,"line":22},"text":" # sad path"}],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"9","keyword":"Example","location":{"column":5,"line":8},"name":"no change","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":9},"text":"there are 5 0.20 coins inside"},{"id":"7","keyword":"When ","keywordType":"Action","location":{"column":7,"line":10},"text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"id":"8","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":11},"text":"the sale should not happen"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"14","keyword":"Example","location":{"column":5,"line":14},"name":"exact change","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":15},"text":"there are 5 0.20 coins inside"},{"id":"11","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":16},"text":"there are 3 chocolates inside"},{"id":"12","keyword":"When ","keywordType":"Action","location":{"column":7,"line":17},"text":"the customer tries to buy a 0.80 chocolate with a 1 coin"},{"id":"13","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":18},"text":"the customer's change should be 1 0.20 coin"}],"tags":[]}}],"description":"","id":"15","keyword":"Rule","location":{"column":3,"line":6},"name":"a sale cannot happen if change cannot be returned","tags":[]}},{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"20","keyword":"Example","location":{"column":5,"line":23},"name":"no chocolates left","steps":[{"id":"16","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":24},"text":"there are no chocolates inside"},{"id":"17","keyword":"But ","keywordType":"Conjunction","location":{"column":7,"line":25},"text":"there are 10 0.5 coins inside"},{"id":"18","keyword":"When ","keywordType":"Action","location":{"column":7,"line":26},"text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"id":"19","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":27},"text":"the sale should not happen"}],"tags":[]}}],"description":"","id":"22","keyword":"Rule","location":{"column":3,"line":21},"name":"a sale cannot happen if we're out of stock","tags":[{"id":"21","location":{"column":3,"line":20},"name":"@some-tag"}]}}],"description":" You can place scenarios inside rules. This makes is possible to structure\n Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n You can also use the Examples synonym for Scenario to make them even more similar.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Rules","tags":[]},"uri":"samples/rules/rules.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"26","language":"en","name":"no change","steps":[{"astNodeIds":["6"],"id":"23","text":"there are 5 0.20 coins inside","type":"Context"},{"astNodeIds":["7"],"id":"24","text":"the customer tries to buy a 0.85 chocolate with a 1 coin","type":"Action"},{"astNodeIds":["8"],"id":"25","text":"the sale should not happen","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} +{"pickle":{"astNodeIds":["14"],"id":"31","language":"en","name":"exact change","steps":[{"astNodeIds":["10"],"id":"27","text":"there are 5 0.20 coins inside","type":"Context"},{"astNodeIds":["11"],"id":"28","text":"there are 3 chocolates inside","type":"Context"},{"astNodeIds":["12"],"id":"29","text":"the customer tries to buy a 0.80 chocolate with a 1 coin","type":"Action"},{"astNodeIds":["13"],"id":"30","text":"the customer's change should be 1 0.20 coin","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} +{"pickle":{"astNodeIds":["20"],"id":"36","language":"en","name":"no chocolates left","steps":[{"astNodeIds":["16"],"id":"32","text":"there are no chocolates inside","type":"Context"},{"astNodeIds":["17"],"id":"33","text":"there are 10 0.5 coins inside","type":"Context"},{"astNodeIds":["18"],"id":"34","text":"the customer tries to buy a 0.85 chocolate with a 1 coin","type":"Action"},{"astNodeIds":["19"],"id":"35","text":"the sale should not happen","type":"Outcome"}],"tags":[{"astNodeId":"21","name":"@some-tag"}],"uri":"samples/rules/rules.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"there are {int} {float} coins inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"there are no chocolates inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":10},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"there are {int} chocolates inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":14},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"the customer tries to buy a {float} chocolate with a {float} coin","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":19},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"4","pattern":{"source":"the sale should not happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":25},"uri":"samples/rules/rules.feature.ts"}}} +{"stepDefinition":{"id":"5","pattern":{"source":"the customer's change should be {int} {float} coin(s)","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":29},"uri":"samples/rules/rules.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"40","pickleId":"26","testSteps":[{"id":"37","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"5"},"parameterTypeName":"int"},{"group":{"children":[],"start":12,"value":"0.20"},"parameterTypeName":"float"}]}]},{"id":"38","pickleStepId":"24","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.85"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"39","pickleStepId":"25","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"45","pickleId":"31","testSteps":[{"id":"41","pickleStepId":"27","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"5"},"parameterTypeName":"int"},{"group":{"children":[],"start":12,"value":"0.20"},"parameterTypeName":"float"}]}]},{"id":"42","pickleStepId":"28","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"3"},"parameterTypeName":"int"}]}]},{"id":"43","pickleStepId":"29","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.80"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"44","pickleStepId":"30","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":32,"value":"1"},"parameterTypeName":"int"},{"group":{"children":[],"start":34,"value":"0.20"},"parameterTypeName":"float"}]}]}]}} +{"testCase":{"id":"50","pickleId":"36","testSteps":[{"id":"46","pickleStepId":"32","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"47","pickleStepId":"33","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[],"start":13,"value":"0.5"},"parameterTypeName":"float"}]}]},{"id":"48","pickleStepId":"34","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.85"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"49","pickleStepId":"35","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"51","testCaseId":"40","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"51","testStepId":"37","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"51","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"51","testStepId":"38","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"51","testStepId":"38","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"51","testStepId":"39","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"51","testStepId":"39","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"51","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"52","testCaseId":"45","timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"52","testStepId":"41","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"52","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"52","testStepId":"42","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"52","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"52","testStepId":"43","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"52","testStepId":"43","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"52","testStepId":"44","timestamp":{"nanos":16000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"52","testStepId":"44","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"52","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"53","testCaseId":"50","timestamp":{"nanos":19000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"53","testStepId":"46","timestamp":{"nanos":20000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"53","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"53","testStepId":"47","timestamp":{"nanos":22000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"53","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"53","testStepId":"48","timestamp":{"nanos":24000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"53","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"53","testStepId":"49","timestamp":{"nanos":26000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"53","testStepId":"49","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"53","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":29000000,"seconds":0}}} diff --git a/python/src/message_samples/rules/rules.feature.ts b/python/src/message_samples/rules/rules.feature.ts new file mode 100644 index 00000000..0688d16a --- /dev/null +++ b/python/src/message_samples/rules/rules.feature.ts @@ -0,0 +1,33 @@ +import assert from 'assert' +import { Given, When, Then } from '@cucumber/fake-cucumber' + +Given('there are {int} {float} coins inside', function (count, denomination) { + // TODO: implement this + assert(count) + assert(denomination) +}) + +Given('there are no chocolates inside', function () { + // TODO: implement this +}) + +Given('there are {int} chocolates inside', function (chocolateCount) { + // TODO: implement this + assert(chocolateCount) +}) + +When('the customer tries to buy a {float} chocolate with a {float} coin', function (price, paid) { + // TODO: implement this + assert(price) + assert(paid) +}) + +Then('the sale should not happen', function () { + // TODO: implement this +}) + +Then("the customer's change should be {int} {float} coin(s)", function (count, denomination) { + // TODO: implement this + assert(count) + assert(denomination) +}) diff --git a/python/src/message_samples/skipped/skipped.feature b/python/src/message_samples/skipped/skipped.feature new file mode 100644 index 00000000..c9982b48 --- /dev/null +++ b/python/src/message_samples/skipped/skipped.feature @@ -0,0 +1,19 @@ +Feature: Skipping scenarios + + Hooks and step definitions are able to signal at runtime that the scenario should + be skipped by returning or throwing a particular value. + + This can be useful when e.g. the current environment doesn't have the right conditions + for running the scenario. + + @skip + Scenario: Skipping from a Before hook + Given a step that we expect to be skipped + + Scenario: Skipping from a step doesn't affect the previous steps + Given an implemented step + When a step that skips + + Scenario: Skipping from a step causes the rest of the scenario to be skipped + Given a step that skips + When a step that we expect to be skipped diff --git a/python/src/message_samples/skipped/skipped.feature.ndjson b/python/src/message_samples/skipped/skipped.feature.ndjson new file mode 100644 index 00000000..6ed59723 --- /dev/null +++ b/python/src/message_samples/skipped/skipped.feature.ndjson @@ -0,0 +1,33 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Skipping scenarios\n\n Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by returning or throwing a particular value.\n\n This can be useful when e.g. the current environment doesn't have the right conditions\n for running the scenario.\n\n @skip\n Scenario: Skipping from a Before hook\n Given a step that we expect to be skipped\n\n Scenario: Skipping from a step doesn't affect the previous steps\n Given an implemented step\n When a step that skips\n\n Scenario: Skipping from a step causes the rest of the scenario to be skipped\n Given a step that skips\n When a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/skipped/skipped.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Skipping from a Before hook","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"a step that we expect to be skipped"}],"tags":[{"id":"5","location":{"column":3,"line":9},"name":"@skip"}]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":13},"name":"Skipping from a step doesn't affect the previous steps","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":14},"text":"an implemented step"},{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":5,"line":15},"text":"a step that skips"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":17},"name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"a step that skips"},{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":19},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by returning or throwing a particular value.\n\n This can be useful when e.g. the current environment doesn't have the right conditions\n for running the scenario.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Skipping scenarios","tags":[]},"uri":"samples/skipped/skipped.feature"}} +{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Skipping from a Before hook","steps":[{"astNodeIds":["4"],"id":"13","text":"a step that we expect to be skipped","type":"Context"}],"tags":[{"astNodeId":"5","name":"@skip"}],"uri":"samples/skipped/skipped.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Skipping from a step doesn't affect the previous steps","steps":[{"astNodeIds":["7"],"id":"15","text":"an implemented step","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"a step that skips","type":"Action"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} +{"pickle":{"astNodeIds":["12"],"id":"20","language":"en","name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"astNodeIds":["10"],"id":"18","text":"a step that skips","type":"Context"},{"astNodeIds":["11"],"id":"19","text":"a step that we expect to be skipped","type":"Action"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} +{"stepDefinition":{"id":"1","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/skipped/skipped.feature.ts"}}} +{"stepDefinition":{"id":"2","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/skipped/skipped.feature.ts"}}} +{"stepDefinition":{"id":"3","pattern":{"source":"a step that skips","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":15},"uri":"samples/skipped/skipped.feature.ts"}}} +{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/skipped/skipped.feature.ts"},"tagExpression":"@skip"}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"23","pickleId":"14","testSteps":[{"hookId":"0","id":"21"},{"id":"22","pickleStepId":"13","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"26","pickleId":"17","testSteps":[{"id":"24","pickleStepId":"15","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"25","pickleStepId":"16","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCase":{"id":"29","pickleId":"20","testSteps":[{"id":"27","pickleStepId":"18","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"28","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"23","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"21","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"30","testStepId":"22","timestamp":{"nanos":4000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"30","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"26","timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"24","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"31","testStepId":"25","timestamp":{"nanos":10000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"31","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":11000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"29","timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"32","testStepId":"27","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"32","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"32","testStepId":"28","timestamp":{"nanos":16000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"32","testStepId":"28","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":17000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":true,"timestamp":{"nanos":19000000,"seconds":0}}} diff --git a/python/src/message_samples/skipped/skipped.feature.ts b/python/src/message_samples/skipped/skipped.feature.ts new file mode 100644 index 00000000..9d0bd595 --- /dev/null +++ b/python/src/message_samples/skipped/skipped.feature.ts @@ -0,0 +1,17 @@ +import { Before, Given } from '@cucumber/fake-cucumber' + +Before('@skip', function () { + return 'skipped' +}) + +Given('an implemented step', function () { + // no-op +}) + +Given('a step that we expect to be skipped', function () { + // no-op +}) + +Given('a step that skips', function () { + return 'skipped' +}) diff --git a/python/src/message_samples/stack-traces/stack-traces.feature b/python/src/message_samples/stack-traces/stack-traces.feature new file mode 100644 index 00000000..5c981df5 --- /dev/null +++ b/python/src/message_samples/stack-traces/stack-traces.feature @@ -0,0 +1,11 @@ +Feature: Stack traces + Nothing beats stack traces when it comes to diagnosing the source of a bug. + Cucumber provides helpful stack traces that: + + - Include a stack frame from the Gherkin document + - Remove uninteresting frames by default + + The first line of the stack trace must contain the feature file. + + Scenario: A failing step + When a step throws an exception diff --git a/python/src/message_samples/stack-traces/stack-traces.feature.ndjson b/python/src/message_samples/stack-traces/stack-traces.feature.ndjson new file mode 100644 index 00000000..3d165072 --- /dev/null +++ b/python/src/message_samples/stack-traces/stack-traces.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Stack traces\n Nothing beats stack traces when it comes to diagnosing the source of a bug.\n Cucumber provides helpful stack traces that:\n \n - Include a stack frame from the Gherkin document\n - Remove uninteresting frames by default\n\n The first line of the stack trace must contain the feature file.\n\n Scenario: A failing step\n When a step throws an exception\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/stack-traces/stack-traces.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":10},"name":"A failing step","steps":[{"id":"1","keyword":"When ","keywordType":"Action","location":{"column":5,"line":11},"text":"a step throws an exception"}],"tags":[]}}],"description":" Nothing beats stack traces when it comes to diagnosing the source of a bug.\n Cucumber provides helpful stack traces that:\n \n - Include a stack frame from the Gherkin document\n - Remove uninteresting frames by default\n\n The first line of the stack trace must contain the feature file.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Stack traces","tags":[]},"uri":"samples/stack-traces/stack-traces.feature"}} +{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"A failing step","steps":[{"astNodeIds":["1"],"id":"3","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/stack-traces/stack-traces.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/stack-traces/stack-traces.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"6","pickleId":"4","testSteps":[{"id":"5","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"BOOM","type":"Error"},"message":"BOOM\nsamples/stack-traces/stack-traces.feature:11","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/stack-traces/stack-traces.feature.ts b/python/src/message_samples/stack-traces/stack-traces.feature.ts new file mode 100644 index 00000000..2ffd339b --- /dev/null +++ b/python/src/message_samples/stack-traces/stack-traces.feature.ts @@ -0,0 +1,5 @@ +import { When } from '@cucumber/fake-cucumber' + +When('a step throws an exception', function () { + throw new Error('BOOM') +}) diff --git a/python/src/message_samples/undefined/undefined.feature b/python/src/message_samples/undefined/undefined.feature new file mode 100644 index 00000000..2abcf5c0 --- /dev/null +++ b/python/src/message_samples/undefined/undefined.feature @@ -0,0 +1,17 @@ +Feature: Undefined steps + + At runtime, Cucumber may encounter a step in a scenario that it cannot match to a + step definition. In these cases, the scenario cannot run and so the step status + will be UNDEFINED, with subsequent steps being skipped and the overall result treated + as a failure. + + Scenario: Undefined step causes failure + Given a step that isnt implemented yet + + Scenario: Steps before undefined steps are executed + Given an implemented step + When a step that isnt implemented yet + + Scenario: Steps after undefined steps are skipped + Given a step that isnt implemented yet + Then a step that we expect to be skipped diff --git a/python/src/message_samples/undefined/undefined.feature.ndjson b/python/src/message_samples/undefined/undefined.feature.ndjson new file mode 100644 index 00000000..44d00265 --- /dev/null +++ b/python/src/message_samples/undefined/undefined.feature.ndjson @@ -0,0 +1,29 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Undefined steps\n\n At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario cannot run and so the step status\n will be UNDEFINED, with subsequent steps being skipped and the overall result treated\n as a failure.\n\n Scenario: Undefined step causes failure\n Given a step that isnt implemented yet\n\n Scenario: Steps before undefined steps are executed\n Given an implemented step\n When a step that isnt implemented yet\n\n Scenario: Steps after undefined steps are skipped\n Given a step that isnt implemented yet\n Then a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/undefined/undefined.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":8},"name":"Undefined step causes failure","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":9},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":11},"name":"Steps before undefined steps are executed","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":12},"text":"an implemented step"},{"id":"5","keyword":"When ","keywordType":"Action","location":{"column":5,"line":13},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":15},"name":"Steps after undefined steps are skipped","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":16},"text":"a step that isnt implemented yet"},{"id":"8","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":17},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario cannot run and so the step status\n will be UNDEFINED, with subsequent steps being skipped and the overall result treated\n as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Undefined steps","tags":[]},"uri":"samples/undefined/undefined.feature"}} +{"pickle":{"astNodeIds":["3"],"id":"11","language":"en","name":"Undefined step causes failure","steps":[{"astNodeIds":["2"],"id":"10","text":"a step that isnt implemented yet","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} +{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Steps before undefined steps are executed","steps":[{"astNodeIds":["4"],"id":"12","text":"an implemented step","type":"Context"},{"astNodeIds":["5"],"id":"13","text":"a step that isnt implemented yet","type":"Action"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} +{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Steps after undefined steps are skipped","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that isnt implemented yet","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"a step that we expect to be skipped","type":"Outcome"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} +{"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/undefined/undefined.feature.ts"}}} +{"stepDefinition":{"id":"1","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/undefined/undefined.feature.ts"}}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"19","pickleId":"11","testSteps":[{"id":"18","pickleStepId":"10","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCase":{"id":"22","pickleId":"14","testSteps":[{"id":"20","pickleStepId":"12","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"21","pickleStepId":"13","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCase":{"id":"25","pickleId":"17","testSteps":[{"id":"23","pickleStepId":"15","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"24","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} +{"testCaseStarted":{"attempt":0,"id":"26","testCaseId":"19","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"26","testStepId":"18","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"26","testStepId":"18","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"26","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"22","timestamp":{"nanos":5000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"27","testStepId":"20","timestamp":{"nanos":6000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"27","testStepId":"20","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"27","testStepId":"21","timestamp":{"nanos":8000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"27","testStepId":"21","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":9000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} +{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"25","timestamp":{"nanos":11000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"23","timestamp":{"nanos":12000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"23","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":13000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"28","testStepId":"24","timestamp":{"nanos":14000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"28","testStepId":"24","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/python/src/message_samples/undefined/undefined.feature.ts b/python/src/message_samples/undefined/undefined.feature.ts new file mode 100644 index 00000000..09d8898f --- /dev/null +++ b/python/src/message_samples/undefined/undefined.feature.ts @@ -0,0 +1,9 @@ +import { Given } from '@cucumber/fake-cucumber' + +Given('an implemented step', function () { + // no-op +}) + +Given('a step that we expect to be skipped', function () { + // no-op +}) diff --git a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature new file mode 100644 index 00000000..4ce05c97 --- /dev/null +++ b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature @@ -0,0 +1,6 @@ +Feature: Parameter Types + Cucumber will generate an error message if a step definition registers + an unknown parameter type, but the suite will run. + + Scenario: undefined parameter type + Given CDG is closed because of a strike diff --git a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson new file mode 100644 index 00000000..19efe139 --- /dev/null +++ b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson @@ -0,0 +1,12 @@ +{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} +{"source":{"data":"Feature: Parameter Types\n Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.\n\n Scenario: undefined parameter type\n Given CDG is closed because of a strike","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} +{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"1","keyword":"Scenario","location":{"column":3,"line":5},"name":"undefined parameter type","steps":[{"id":"0","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":6},"text":"CDG is closed because of a strike"}],"tags":[]}}],"description":" Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} +{"pickle":{"astNodeIds":["1"],"id":"3","language":"en","name":"undefined parameter type","steps":[{"astNodeIds":["0"],"id":"2","text":"CDG is closed because of a strike","type":"Context"}],"tags":[],"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} +{"undefinedParameterType":{"expression":"{airport} is closed because of a strike","name":"airport"}} +{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} +{"testCase":{"id":"5","pickleId":"3","testSteps":[{"id":"4","pickleStepId":"2","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} +{"testCaseStarted":{"attempt":0,"id":"6","testCaseId":"5","timestamp":{"nanos":1000000,"seconds":0}}} +{"testStepStarted":{"testCaseStartedId":"6","testStepId":"4","timestamp":{"nanos":2000000,"seconds":0}}} +{"testStepFinished":{"testCaseStartedId":"6","testStepId":"4","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} +{"testCaseFinished":{"testCaseStartedId":"6","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} +{"testRunFinished":{"success":false,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts new file mode 100644 index 00000000..4f3e0c4d --- /dev/null +++ b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts @@ -0,0 +1,6 @@ +import { Given } from '@cucumber/fake-cucumber' + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +Given('{airport} is closed because of a strike', function (airport) { + throw new Error('Should not be called because airport type not defined') +}) diff --git a/python/tests/__init__.py b/python/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/tests/conftest.py b/python/tests/conftest.py new file mode 100644 index 00000000..e69de29b diff --git a/python/tests/test_model_load.py b/python/tests/test_model_load.py new file mode 100644 index 00000000..70205244 --- /dev/null +++ b/python/tests/test_model_load.py @@ -0,0 +1,28 @@ +import json +from itertools import chain +from pathlib import Path + +from importlib_resources import files +from pytest import mark, param + +from cucumber_messages import Envelope + + +@mark.parametrize( + "ast_path", + map( + lambda file: param(file, id=file.name), # type: ignore[no-any-return] + chain.from_iterable(map(lambda p: p.glob("*.ndjson"), files("message_samples").iterdir())), + ), +) +def test_simple_load_model(ast_path: Path): + with ast_path.open(mode="r") as ast_file: + for ast_line in ast_file: + model_datum = json.loads(ast_line) + model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] + + assert isinstance(model, Envelope) + + dumped_ast_datum = json.loads(model.model_dump_json(by_alias=True, exclude_none=True)) # type: ignore[attr-defined] # migration to pydantic2 + + assert model_datum == dumped_ast_datum From 3389a62dbe81d12bd95d1526a427aa01609d9d14 Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Sat, 7 Sep 2024 17:30:16 +0300 Subject: [PATCH 2/5] Use CCK examples load on test --- python/tests/test_model_load.py | 60 +++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/python/tests/test_model_load.py b/python/tests/test_model_load.py index 70205244..0bd959f3 100644 --- a/python/tests/test_model_load.py +++ b/python/tests/test_model_load.py @@ -1,28 +1,52 @@ import json -from itertools import chain +import re from pathlib import Path -from importlib_resources import files -from pytest import mark, param +from git import Repo +from packaging import version +from pytest import fixture from cucumber_messages import Envelope -@mark.parametrize( - "ast_path", - map( - lambda file: param(file, id=file.name), # type: ignore[no-any-return] - chain.from_iterable(map(lambda p: p.glob("*.ndjson"), files("message_samples").iterdir())), - ), -) -def test_simple_load_model(ast_path: Path): - with ast_path.open(mode="r") as ast_file: - for ast_line in ast_file: - model_datum = json.loads(ast_line) - model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] +@fixture +def compatibility_kit_repo(tmpdir): + repo_path = Path(tmpdir) / "compatibility-kit" + repo = Repo.clone_from( + "https://github.com/cucumber/compatibility-kit.git", + str(repo_path), + branch="main", + ) + repo_tags = list(filter(lambda tag: tag is not None, map(lambda tag: getattr(tag.tag, "tag", None), repo.tags))) - assert isinstance(model, Envelope) + version_pattern = re.compile(r"((.*/)?)v(\d+\.\d+\.\d+)") + last_version = sorted( + map( + version.parse, + map( + lambda match: match.groups()[-1], + filter(lambda match: match is not None, map(lambda tag: re.match(version_pattern, tag), repo_tags)), + ), + ) + )[-1] - dumped_ast_datum = json.loads(model.model_dump_json(by_alias=True, exclude_none=True)) # type: ignore[attr-defined] # migration to pydantic2 + last_version_tag = next(filter(lambda tag: re.search(re.escape(str(last_version)), tag), repo_tags)) - assert model_datum == dumped_ast_datum + repo.git.checkout(last_version_tag) + + return repo_path + + +def test_simple_load_model(compatibility_kit_repo): + for ast_path in (compatibility_kit_repo / "devkit" / "samples").rglob("*.ndjson"): + print(f"Checking ${ast_path}") + with ast_path.open(mode="r") as ast_file: + for ast_line in ast_file: + model_datum = json.loads(ast_line) + model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] + + assert isinstance(model, Envelope) + + dumped_ast_datum = json.loads(model.model_dump_json(by_alias=True, exclude_none=True)) # type: ignore[attr-defined] # migration to pydantic2 + + assert model_datum == dumped_ast_datum From 3da9e8f4a47a2a93eee6606b1463a9e3128f6ba9 Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Thu, 5 Sep 2024 01:05:48 +0300 Subject: [PATCH 3/5] Bare minimum tests for python model --- python/pyproject.toml | 1 - .../attachments/attachments.feature | 44 --------- .../attachments/attachments.feature.ndjson | 87 ------------------ .../attachments/attachments.feature.ts | 58 ------------ .../message_samples/attachments/cucumber.png | Bin 1739 -> 0 bytes .../message_samples/attachments/document.pdf | Bin 10061 -> 0 bytes .../src/message_samples/cdata/cdata.feature | 6 -- .../cdata/cdata.feature.ndjson | 12 --- .../message_samples/cdata/cdata.feature.ts | 6 -- .../data-tables/data-tables.feature | 12 --- .../data-tables/data-tables.feature.ndjson | 15 --- .../data-tables/data-tables.feature.ts | 11 --- .../examples-tables/examples-tables.feature | 28 ------ .../examples-tables.feature.ndjson | 68 -------------- .../examples-tables.feature.ts | 14 --- python/src/message_samples/hooks/cucumber.svg | 7 -- .../src/message_samples/hooks/hooks.feature | 20 ---- .../hooks/hooks.feature.ndjson | 77 ---------------- .../message_samples/hooks/hooks.feature.ts | 30 ------ .../markdown/markdown.feature.md | 46 --------- .../markdown/markdown.feature.md.ndjson | 35 ------- .../markdown/markdown.feature.md.ts | 25 ----- .../parameter-types/parameter-types.feature | 9 -- .../parameter-types.feature.ndjson | 13 --- .../parameter-types.feature.ts | 20 ---- .../message_samples/pending/pending.feature | 19 ---- .../pending/pending.feature.ndjson | 30 ------ .../pending/pending.feature.ts | 13 --- .../message_samples/retry/retry.arguments.txt | 1 - .../src/message_samples/retry/retry.feature | 22 ----- .../retry/retry.feature.ndjson | 59 ------------ .../message_samples/retry/retry.feature.ts | 25 ----- .../src/message_samples/rules/rules.feature | 27 ------ .../rules/rules.feature.ndjson | 45 --------- .../message_samples/rules/rules.feature.ts | 33 ------- .../message_samples/skipped/skipped.feature | 19 ---- .../skipped/skipped.feature.ndjson | 33 ------- .../skipped/skipped.feature.ts | 17 ---- .../stack-traces/stack-traces.feature | 11 --- .../stack-traces/stack-traces.feature.ndjson | 12 --- .../stack-traces/stack-traces.feature.ts | 5 - .../undefined/undefined.feature | 17 ---- .../undefined/undefined.feature.ndjson | 29 ------ .../undefined/undefined.feature.ts | 9 -- .../unknown-parameter-type.feature | 6 -- .../unknown-parameter-type.feature.ndjson | 12 --- .../unknown-parameter-type.feature.ts | 6 -- .../data}/message_samples/__init__.py | 0 .../message_samples/minimal/minimal.feature | 0 .../minimal/minimal.feature.ndjson | 0 .../minimal/minimal.feature.ts | 0 python/tests/test_model_load.py | 58 ++++-------- 52 files changed, 17 insertions(+), 1135 deletions(-) delete mode 100644 python/src/message_samples/attachments/attachments.feature delete mode 100644 python/src/message_samples/attachments/attachments.feature.ndjson delete mode 100644 python/src/message_samples/attachments/attachments.feature.ts delete mode 100644 python/src/message_samples/attachments/cucumber.png delete mode 100644 python/src/message_samples/attachments/document.pdf delete mode 100644 python/src/message_samples/cdata/cdata.feature delete mode 100644 python/src/message_samples/cdata/cdata.feature.ndjson delete mode 100644 python/src/message_samples/cdata/cdata.feature.ts delete mode 100644 python/src/message_samples/data-tables/data-tables.feature delete mode 100644 python/src/message_samples/data-tables/data-tables.feature.ndjson delete mode 100644 python/src/message_samples/data-tables/data-tables.feature.ts delete mode 100644 python/src/message_samples/examples-tables/examples-tables.feature delete mode 100644 python/src/message_samples/examples-tables/examples-tables.feature.ndjson delete mode 100644 python/src/message_samples/examples-tables/examples-tables.feature.ts delete mode 100644 python/src/message_samples/hooks/cucumber.svg delete mode 100644 python/src/message_samples/hooks/hooks.feature delete mode 100644 python/src/message_samples/hooks/hooks.feature.ndjson delete mode 100644 python/src/message_samples/hooks/hooks.feature.ts delete mode 100644 python/src/message_samples/markdown/markdown.feature.md delete mode 100644 python/src/message_samples/markdown/markdown.feature.md.ndjson delete mode 100644 python/src/message_samples/markdown/markdown.feature.md.ts delete mode 100644 python/src/message_samples/parameter-types/parameter-types.feature delete mode 100644 python/src/message_samples/parameter-types/parameter-types.feature.ndjson delete mode 100644 python/src/message_samples/parameter-types/parameter-types.feature.ts delete mode 100644 python/src/message_samples/pending/pending.feature delete mode 100644 python/src/message_samples/pending/pending.feature.ndjson delete mode 100644 python/src/message_samples/pending/pending.feature.ts delete mode 100644 python/src/message_samples/retry/retry.arguments.txt delete mode 100644 python/src/message_samples/retry/retry.feature delete mode 100644 python/src/message_samples/retry/retry.feature.ndjson delete mode 100644 python/src/message_samples/retry/retry.feature.ts delete mode 100644 python/src/message_samples/rules/rules.feature delete mode 100644 python/src/message_samples/rules/rules.feature.ndjson delete mode 100644 python/src/message_samples/rules/rules.feature.ts delete mode 100644 python/src/message_samples/skipped/skipped.feature delete mode 100644 python/src/message_samples/skipped/skipped.feature.ndjson delete mode 100644 python/src/message_samples/skipped/skipped.feature.ts delete mode 100644 python/src/message_samples/stack-traces/stack-traces.feature delete mode 100644 python/src/message_samples/stack-traces/stack-traces.feature.ndjson delete mode 100644 python/src/message_samples/stack-traces/stack-traces.feature.ts delete mode 100644 python/src/message_samples/undefined/undefined.feature delete mode 100644 python/src/message_samples/undefined/undefined.feature.ndjson delete mode 100644 python/src/message_samples/undefined/undefined.feature.ts delete mode 100644 python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature delete mode 100644 python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson delete mode 100644 python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts rename python/{src => tests/data}/message_samples/__init__.py (100%) rename python/{src => tests/data}/message_samples/minimal/minimal.feature (100%) rename python/{src => tests/data}/message_samples/minimal/minimal.feature.ndjson (100%) rename python/{src => tests/data}/message_samples/minimal/minimal.feature.ts (100%) diff --git a/python/pyproject.toml b/python/pyproject.toml index 473cc275..5c5aa264 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -53,7 +53,6 @@ test = [ ] test-coverage = [ "coverage", - "importlib_resources", "pytest" ] diff --git a/python/src/message_samples/attachments/attachments.feature b/python/src/message_samples/attachments/attachments.feature deleted file mode 100644 index 17aa5bbc..00000000 --- a/python/src/message_samples/attachments/attachments.feature +++ /dev/null @@ -1,44 +0,0 @@ -Feature: Attachments - It is sometimes useful to take a screenshot while a scenario runs. - Or capture some logs. - - Cucumber lets you `attach` arbitrary files during execution, and you can - specify a content type for the contents. - - Formatters can then render these attachments in reports. - - Attachments must have a body and a content type - - Scenario: Strings can be attached with a media type - Beware that some formatters such as @cucumber/react use the media type - to determine how to display an attachment. - - When the string "hello" is attached as "application/octet-stream" - - Scenario: Log JSON - When the following string is attached as "application/json": - ``` - {"message": "The big question", "foo": "bar"} - ``` - - Scenario: Log text - When the string "hello" is logged - - Scenario: Log ANSI coloured text - When text with ANSI escapes is logged - - Scenario: Byte arrays are base64-encoded regardless of media type - When an array with 10 bytes is attached as "text/plain" - - Scenario: Streams are always base64-encoded - When a JPEG image is attached - - Scenario: Attaching images in examples - When the png is attached - - Examples: - | image | - | cucumber.png | - - Scenario: Attaching a document with a filename - When a PDF document is attached with a filename diff --git a/python/src/message_samples/attachments/attachments.feature.ndjson b/python/src/message_samples/attachments/attachments.feature.ndjson deleted file mode 100644 index 66fe2e67..00000000 --- a/python/src/message_samples/attachments/attachments.feature.ndjson +++ /dev/null @@ -1,87 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Attachments\n It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type\n\n Scenario: Strings can be attached with a media type\n Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.\n\n When the string \"hello\" is attached as \"application/octet-stream\"\n\n Scenario: Log JSON\n When the following string is attached as \"application/json\":\n ```\n {\"message\": \"The big question\", \"foo\": \"bar\"}\n ```\n\n Scenario: Log text\n When the string \"hello\" is logged\n\n Scenario: Log ANSI coloured text\n When text with ANSI escapes is logged\n\n Scenario: Byte arrays are base64-encoded regardless of media type\n When an array with 10 bytes is attached as \"text/plain\"\n\n Scenario: Streams are always base64-encoded\n When a JPEG image is attached\n\n Scenario: Attaching images in examples\n When the png is attached\n\n Examples:\n | image |\n | cucumber.png |\n\n Scenario: Attaching a document with a filename\n When a PDF document is attached with a filename\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/attachments/attachments.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":" Beware that some formatters such as @cucumber/react use the media type\n to determine how to display an attachment.","examples":[],"id":"11","keyword":"Scenario","location":{"column":3,"line":12},"name":"Strings can be attached with a media type","steps":[{"id":"10","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"the string \"hello\" is attached as \"application/octet-stream\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":18},"name":"Log JSON","steps":[{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}","delimiter":"```","location":{"column":8,"line":20}},"id":"12","keyword":"When ","keywordType":"Action","location":{"column":6,"line":19},"text":"the following string is attached as \"application/json\":"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"15","keyword":"Scenario","location":{"column":3,"line":24},"name":"Log text","steps":[{"id":"14","keyword":"When ","keywordType":"Action","location":{"column":5,"line":25},"text":"the string \"hello\" is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"17","keyword":"Scenario","location":{"column":3,"line":27},"name":"Log ANSI coloured text","steps":[{"id":"16","keyword":"When ","keywordType":"Action","location":{"column":6,"line":28},"text":"text with ANSI escapes is logged"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"19","keyword":"Scenario","location":{"column":3,"line":30},"name":"Byte arrays are base64-encoded regardless of media type","steps":[{"id":"18","keyword":"When ","keywordType":"Action","location":{"column":5,"line":31},"text":"an array with 10 bytes is attached as \"text/plain\""}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"21","keyword":"Scenario","location":{"column":3,"line":33},"name":"Streams are always base64-encoded","steps":[{"id":"20","keyword":"When ","keywordType":"Action","location":{"column":5,"line":34},"text":"a JPEG image is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[{"description":"","id":"25","keyword":"Examples","location":{"column":5,"line":39},"name":"","tableBody":[{"cells":[{"location":{"column":9,"line":41},"value":"cucumber.png"}],"id":"24","location":{"column":7,"line":41}}],"tableHeader":{"cells":[{"location":{"column":9,"line":40},"value":"image"}],"id":"23","location":{"column":7,"line":40}},"tags":[]}],"id":"26","keyword":"Scenario","location":{"column":3,"line":36},"name":"Attaching images in examples","steps":[{"id":"22","keyword":"When ","keywordType":"Action","location":{"column":5,"line":37},"text":"the png is attached"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"28","keyword":"Scenario","location":{"column":3,"line":43},"name":"Attaching a document with a filename","steps":[{"id":"27","keyword":"When ","keywordType":"Action","location":{"column":5,"line":44},"text":"a PDF document is attached with a filename"}],"tags":[]}}],"description":" It is sometimes useful to take a screenshot while a scenario runs.\n Or capture some logs.\n\n Cucumber lets you `attach` arbitrary files during execution, and you can\n specify a content type for the contents.\n\n Formatters can then render these attachments in reports.\n\n Attachments must have a body and a content type","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Attachments","tags":[]},"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["11"],"id":"30","language":"en","name":"Strings can be attached with a media type","steps":[{"astNodeIds":["10"],"id":"29","text":"the string \"hello\" is attached as \"application/octet-stream\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["13"],"id":"32","language":"en","name":"Log JSON","steps":[{"argument":{"docString":{"content":"{\"message\": \"The big question\", \"foo\": \"bar\"}"}},"astNodeIds":["12"],"id":"31","text":"the following string is attached as \"application/json\":","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["15"],"id":"34","language":"en","name":"Log text","steps":[{"astNodeIds":["14"],"id":"33","text":"the string \"hello\" is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["17"],"id":"36","language":"en","name":"Log ANSI coloured text","steps":[{"astNodeIds":["16"],"id":"35","text":"text with ANSI escapes is logged","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["19"],"id":"38","language":"en","name":"Byte arrays are base64-encoded regardless of media type","steps":[{"astNodeIds":["18"],"id":"37","text":"an array with 10 bytes is attached as \"text/plain\"","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["21"],"id":"40","language":"en","name":"Streams are always base64-encoded","steps":[{"astNodeIds":["20"],"id":"39","text":"a JPEG image is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["26","24"],"id":"42","language":"en","name":"Attaching images in examples","steps":[{"astNodeIds":["22","24"],"id":"41","text":"the cucumber.png png is attached","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"pickle":{"astNodeIds":["28"],"id":"44","language":"en","name":"Attaching a document with a filename","steps":[{"astNodeIds":["27"],"id":"43","text":"a PDF document is attached with a filename","type":"Action"}],"tags":[],"uri":"samples/attachments/attachments.feature"}} -{"stepDefinition":{"id":"1","pattern":{"source":"the string {string} is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"the string {string} is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"text with ANSI escapes is logged","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"4","pattern":{"source":"the following string is attached as {string}:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":22},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"5","pattern":{"source":"an array with {int} bytes is attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":26},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"6","pattern":{"source":"a stream with {int} bytes are attached as {string}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":35},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"7","pattern":{"source":"a JPEG image is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":48},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"8","pattern":{"source":"the {word} png is attached","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":52},"uri":"samples/attachments/attachments.feature.ts"}}} -{"stepDefinition":{"id":"9","pattern":{"source":"a PDF document is attached with a filename","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":56},"uri":"samples/attachments/attachments.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":6},"uri":"samples/attachments/attachments.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"47","pickleId":"30","testSteps":[{"hookId":"0","id":"45"},{"id":"46","pickleStepId":"29","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"},{"group":{"children":[{"children":[{"children":[]}],"start":35,"value":"application/octet-stream"},{"children":[{"children":[]}]}],"start":34,"value":"\"application/octet-stream\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"50","pickleId":"32","testSteps":[{"hookId":"0","id":"48"},{"id":"49","pickleStepId":"31","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":37,"value":"application/json"},{"children":[{"children":[]}]}],"start":36,"value":"\"application/json\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"53","pickleId":"34","testSteps":[{"hookId":"0","id":"51"},{"id":"52","pickleStepId":"33","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[{"children":[]}],"start":12,"value":"hello"},{"children":[{"children":[]}]}],"start":11,"value":"\"hello\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"56","pickleId":"36","testSteps":[{"hookId":"0","id":"54"},{"id":"55","pickleStepId":"35","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"59","pickleId":"38","testSteps":[{"hookId":"0","id":"57"},{"id":"58","pickleStepId":"37","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[{"children":[{"children":[]}],"start":39,"value":"text/plain"},{"children":[{"children":[]}]}],"start":38,"value":"\"text/plain\""},"parameterTypeName":"string"}]}]}]}} -{"testCase":{"id":"62","pickleId":"40","testSteps":[{"hookId":"0","id":"60"},{"id":"61","pickleStepId":"39","stepDefinitionIds":["7"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"65","pickleId":"42","testSteps":[{"hookId":"0","id":"63"},{"id":"64","pickleStepId":"41","stepDefinitionIds":["8"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":4,"value":"cucumber.png"},"parameterTypeName":"word"}]}]}]}} -{"testCase":{"id":"68","pickleId":"44","testSteps":[{"hookId":"0","id":"66"},{"id":"67","pickleStepId":"43","stepDefinitionIds":["9"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"69","testCaseId":"47","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"69","testStepId":"45","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"69","testStepId":"45","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"69","testStepId":"46","timestamp":{"nanos":4000000,"seconds":0}}} -{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"application/octet-stream","testCaseStartedId":"69","testStepId":"46"}} -{"testStepFinished":{"testCaseStartedId":"69","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"69","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"70","testCaseId":"50","timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"70","testStepId":"48","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"70","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"70","testStepId":"49","timestamp":{"nanos":10000000,"seconds":0}}} -{"attachment":{"body":"{\"message\": \"The big question\", \"foo\": \"bar\"}","contentEncoding":"IDENTITY","mediaType":"application/json","testCaseStartedId":"70","testStepId":"49"}} -{"testStepFinished":{"testCaseStartedId":"70","testStepId":"49","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"70","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"71","testCaseId":"53","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"71","testStepId":"51","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"71","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"71","testStepId":"52","timestamp":{"nanos":16000000,"seconds":0}}} -{"attachment":{"body":"hello","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"71","testStepId":"52"}} -{"testStepFinished":{"testCaseStartedId":"71","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"71","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"72","testCaseId":"56","timestamp":{"nanos":19000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"72","testStepId":"54","timestamp":{"nanos":20000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"72","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"72","testStepId":"55","timestamp":{"nanos":22000000,"seconds":0}}} -{"attachment":{"body":"This displays a \u001b[31mr\u001b[0m\u001b[91ma\u001b[0m\u001b[33mi\u001b[0m\u001b[32mn\u001b[0m\u001b[34mb\u001b[0m\u001b[95mo\u001b[0m\u001b[35mw\u001b[0m","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"72","testStepId":"55"}} -{"testStepFinished":{"testCaseStartedId":"72","testStepId":"55","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"72","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"73","testCaseId":"59","timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"73","testStepId":"57","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"73","testStepId":"57","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"73","testStepId":"58","timestamp":{"nanos":28000000,"seconds":0}}} -{"attachment":{"body":"AAECAwQFBgcICQ==","contentEncoding":"BASE64","mediaType":"text/plain","testCaseStartedId":"73","testStepId":"58"}} -{"testStepFinished":{"testCaseStartedId":"73","testStepId":"58","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"73","timestamp":{"nanos":30000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"74","testCaseId":"62","timestamp":{"nanos":31000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"74","testStepId":"60","timestamp":{"nanos":32000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"74","testStepId":"60","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"74","testStepId":"61","timestamp":{"nanos":34000000,"seconds":0}}} -{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"74","testStepId":"61"}} -{"testStepFinished":{"testCaseStartedId":"74","testStepId":"61","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"74","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"75","testCaseId":"65","timestamp":{"nanos":37000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"75","testStepId":"63","timestamp":{"nanos":38000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"75","testStepId":"63","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":39000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"75","testStepId":"64","timestamp":{"nanos":40000000,"seconds":0}}} -{"attachment":{"body":"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","contentEncoding":"BASE64","mediaType":"image/png","testCaseStartedId":"75","testStepId":"64"}} -{"testStepFinished":{"testCaseStartedId":"75","testStepId":"64","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":41000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"75","timestamp":{"nanos":42000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"76","testCaseId":"68","timestamp":{"nanos":43000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"76","testStepId":"66","timestamp":{"nanos":44000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"76","testStepId":"66","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"76","testStepId":"67","timestamp":{"nanos":46000000,"seconds":0}}} -{"attachment":{"body":"JVBERi0xLjQKJdPr6eEKMSAwIG9iago8PC9UaXRsZSAoVW50aXRsZWQgZG9jdW1lbnQpCi9Qcm9kdWNlciAoU2tpYS9QREYgbTExNiBHb29nbGUgRG9jcyBSZW5kZXJlcik+PgplbmRvYmoKMyAwIG9iago8PC9jYSAxCi9CTSAvTm9ybWFsPj4KZW5kb2JqCjUgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDE2Nz4+IHN0cmVhbQp4nF2P0QrCMAxF3/MV+YF1TdM2LYgPgu5Z6R+oGwg+bP4/mK64gU1Jw73cQ0potTrSlrzD+xtmMBJW9feqSFjrNmAblgn6gXH6QPUleyRyjMsTRrj+EcTVqwy7Sspow844FegvivAm1iNYRqB9L+MlJxLOWCqkIzZOhD0nLA88WMtyxPICMexijoE10wyfViMZCkRW0maEuCUSubDrjXQu+osv96M5GgplbmRzdHJlYW0KZW5kb2JqCjIgMCBvYmoKPDwvVHlwZSAvUGFnZQovUmVzb3VyY2VzIDw8L1Byb2NTZXQgWy9QREYgL1RleHQgL0ltYWdlQiAvSW1hZ2VDIC9JbWFnZUldCi9FeHRHU3RhdGUgPDwvRzMgMyAwIFI+PgovRm9udCA8PC9GNCA0IDAgUj4+Pj4KL01lZGlhQm94IFswIDAgNTk2IDg0Ml0KL0NvbnRlbnRzIDUgMCBSCi9TdHJ1Y3RQYXJlbnRzIDAKL1BhcmVudCA2IDAgUj4+CmVuZG9iago2IDAgb2JqCjw8L1R5cGUgL1BhZ2VzCi9Db3VudCAxCi9LaWRzIFsyIDAgUl0+PgplbmRvYmoKNyAwIG9iago8PC9UeXBlIC9DYXRhbG9nCi9QYWdlcyA2IDAgUj4+CmVuZG9iago4IDAgb2JqCjw8L0xlbmd0aDEgMTY5OTYKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbmd0aCA4MDA5Pj4gc3RyZWFtCnic7XoJeFRF9u+pureXrN0J2TrppG+nkw6kA4EECEtMOhugkT1gwiSSAJGAIEtAQVGaGVCJKI4LDuiI+6CO0lnADi4wMjojLjDquAsIjOLMIOgoruS+X1V3gIj65sv7z3uf75u+Ob86derUqapTp869N93EiKgPQKWBo8srRtFH9C4R80Pad/SE8ZN9g357HRE/gvrq0ZOnlIY/Y1qH9rdQHzh+cm7esjHbj6F9Ner1U8vHVk+4Ze4XaNpHFHPbzPkNCxlny9DuRXv5zMuXaPfa3/wHkXEXqOqShbPnv7S8ZhNRVBzql81uaF5ISRQG+4XQt86et/ySu6oLu4jsOUTmQ02z5i97puTkEkwY45m3NDU2zDoY9zzscTP0hzZBEJsf5kR/zJEymuYvWRa/nu0nMtRDVj9vwcyGRE885qc0ob1tfsOyhYb2KB/aLkRdu6xhfmNi/aD34Qw7ZOULFzQv0bNpA/h5on3h4saFmW+M3UmUaSWKeAYyhczEKYaYroMXvqymz6iQfksmyK2US1Nh7ffQNaCukPzoWcLmD3zQ31TUNY7KrPTN1m+utEpJj0+1lESGahy7FuxXgIvRGFwMI14EFHrhNACXoWFxwwzSZi5fPI+02YsbLyWtqXHGYtLmNSy5jLQzY5PBtmmRI6Z9uqXwC3OKWYrvO5yVLcoXJ4zc/s3WU7OtZBajh501My79QBQX8kCciCWUZukboipqpCXwT5Br1nX9sLjOsqAo17Ob4SGzYZMhH1NJCZbKX+gSHms28AijysVHpe95ZOz4cePJC7tLDK91TWT5piLW5hWbgdFUt+FJsWuYTdAXpVRLivRCTtALcv1xQR+iB+v2p+TZWTymcmnjYuiejaG5CD2OlTJJkRScY6y0UICWMXoqTQURxf9fvTb87y52549fylPqIulgE00Tu6riTNJc8oV4Bm9eHuI5RVNTiFewF31DvHqWjoGSoRXkjeCISmgxzaEGmkdjsXtTEReLqRmSBSQicgiidhBiqAGtQrKAltByWggtjc6n+ZDPhu5lQI36g85Y02gStGbTUvANkPasndF7GJp5GGEQLg0zaJK2zx2tDLXF4AU2QB6c4QA55rzQeHMwQhPamkOjN8vVXA6cRQOM5xzh/38+6mF5zv/PbDRTZa/6ERXz4ZRh2EE2ULLhd2RT3bh7kP4R6Kgou+boR0W7KPnf0SkQIqIt9BibQ4/RTnqWnUCvrdRJHfRnSqRyuotW0G10HSJ1GiRrsaeTEMHldBuz6R3I6Pciku+ll6F7EV1DOyiBJekf00pao7yGXmsoitIRHRMQKTeyC/WlyDoH1F8hF1yIyFnIfHq1fpN+i/4APUidyp/1UxSB0zET18v6J4a39PcQ0bV0O22kA+yWsG04URfh3HUqv0VMbVLqVKbP1r/BDJx0BeagImZfZru4B9Yb6SOWxFYoZbByv+7X/wgtO9UhNjfRDjaEjeZOQ60+Vn+ZEjDGMljdSG20HVeAnqZ3WKThhP6AfoJslINTthL+eIXtUrpOreoqhscM8FI/Go6WBfQM/Yn2MRf7A19giDTkGbyGK/XXkREH0RTM9nfo+SH7kl+Da6XyvDpKL8WZX0O/Ft6m5+gDlsxy2Xg2lffjC/jdymJkzhx5EmfhLK2l38D6fuZh23kk36vcrz6qfmtM7TqoR2NH3HQn7q1/YFFYqcaa2S/ZG+wwL+PT+Z38kHKb+rD6qqkBq74YWeJGepS+ZLFsGJvIfsGa2Ap2Hfs128heZvvYUV7Cq/il/LjSpCxSnlZLcU1Wm9VfGa413GA82lXd9ceuv3R9qefp19JExMMqzP52uhsr66S99DauA3SIGVgEi8alMSebwq7CdQ27kd3HtrCHWQdG2ccOsY/ZZ+wL9i1HouRGnsKdPB2Xiy/mV/Db+F18L659/J/8ayVRSVc8yhClUKlRFmBW1yk349qmfKAmq3tVHX7OM2wwbDZsMTxqeNZwwhhp+iVusS99d/+p7FP7u6jr+q4NXW1dHfoHyP42xJSdHHgSmYi81YDcvQw5/0HE+WssEr5LZtmsiF0Iz0xnc9kitgyeXM02sQfl3B9nT8FLb7LjmHMUt8s5D+BDeCkfj+ti3sgX8Zv5LbyDv8G/UUxKhGJR4pVsZbRSpzQqS5TlygbFr7ykvK8cUk4q3+HS1XDVoaarbtWjjlanq0vVu9WP1I8MtYYXDX8zhhvnG681BoyfmoaaikwTTBNNdab1pu2m1831iM7dtI2eOPvss4PKKqVC2UY38XzVxl/hryCep9MsZSxHpPIt7Hp+NevgGYZlxpF8JBtHJ1Q3fP0838xP8pHKWFbJJtNcPihozRinPoKiUN1Nx9SnsLZXYHmZMZJdw48bI6kNjwXDMeZzykDVo7xI7ygHmEm9l95Vw1kiO8Z/p0xAFDytFhmqyancRY8ri9jVtI1X4JHjW/M6xPE49gjyQhXLY18peErk4xBFBcph+hVdyt+iYzjH19MdbJY6m26ifLYCT+AP4VT0M1xmzDbGsxf4HLWF92EdxNWHsbrhLIMphjhazeqUTcbj/G3c3faq4bRf+T1mv5c/roxVTxgmsSacgKvpWlqkr6Llhmr1VTabFDaVMtWDyG4rlDzViXIlskotctp2nO4dyAMlylhIkhA5FyIupiBDbML1G+QJFRE0B2f8ImSxV6jDWMUDNNsQzZB1kI1f7JpE0/SHaKM+my7Tb6H+yAfX6StgcQv9jdbTFram6yrcR9NwcvazCw2j+F7DKL0/b+Fv88l8Q8/9hbczWRL9HdfjqBThOa5FfZMmU7G+Tv8rorsvMuxGmkEX0BGs8hOMMEbZRfld43irPkpZiPUeoIn673QHC6cmfR6Np6foQZOBGkwe7LGfvYr1XkWNfJK+RGnsmgM/rIcXvPDWUuSftd6yKVUl3uKi8wpHjhg+rGDI4Py8QQNzB/TP8WT365vlzsxwpTs1R1qqPSXZlpSYEB/XJzbGaomOiowIDzObjAZV4YxyKlyj6jW/u96vul1jxvQXdVcDBA1nCer9GkSjeur4tXqppvXU9ELzku9peoOa3tOazKoVUmH/HK3CpflfLndpATZtYjX4G8tdNZr/mOTHSv5myUeBdzrRQatIairX/Kxeq/CPuryppaK+HOZaI8LLXGWN4f1zqDU8AmwEOH+ia2ErSyxikuGJFSNa8QQchUn5k13lFX6bq1zMwK9kVjTM8k+YWF1RnuJ01vTP8bOyma4ZfnKV+i0eqUJlchi/scxvksNoc8Rq6AatNWdXy7qAlWbUeyJnuWY11Fb7lYYaMUaMB+OW+xOvPJJ0pgrjsWXV153dmqK0VCTN0US1peU6zX/PxOqzW50Ca2pgA3155qj6llEYeh2cWDlZw2h8TU21n63BkJpYiVhVcH2NrgohqZ+r+cNcpa6mlrn12JrkFj9NWu5sS072duoHKblCa6mqdjn9xSmumoZye2sctUxa3m7zaraeLf1zWq0xQce2RltCTGTU2Uzj6TbJSXXBVU467VkmZuQ6HwHh12ZqmEm1C2saJqBxGLXMHAY1fGoYevlnYUfm+MPK6lusI4Rc9PcbMq0ureULQgS4jv2zp6QhJDFmWr8gwYo4OR1qaO/m/R6PPztbhIipDHuKORbJ+pD+OZcHuMu10KqhgPtoAnzbUDMiF+53OsUG3xDw0gxU/L6J1cG6RjNS2sib66nx83rRsqu7JX6KaPF1t5zuXu9CJHfIJ+54v9l9+s9iTehT0TTCzxJ+orkx2F452VU5cVq1VtFSH/JtZVWPWrB92Om2EOfvU1atpPAQx1MU2YqgrD2tLCrVkX41E39GGdSzAiYzolJKmDbKb60fE8SacKfz3+wU0E+IXrI40y00Tf8IT8/6yB71HtOLbFEwYdwqK6umtbSE92hDqAUHPD9UIOKpqtqplflpCk5mJv4C+q5hgmpS/F64rEwoIP6ColC1h2JKiK/BR0Rn/5xRSHQtLaNc2qiW+paGgO6b4dKsrpZO/ix/tmVhRX134AT0HTek+Eetq4GvmtgIHApOpa0udv3EVi+7fvK06k4r3vyvr6pu44yX1ZfWtGagrbpTI/JKKRdSIRQVTVSokmGRbdws9VM6vUQ+2apKgazPDDCSMnO3jNHMAA/KrN0yDpkalHmlTHxEjimrqj47euSRrOkvb3h4b6HaCLO5N69CeIT5aYFRIYoMC+udbdNPC0ywHRUe/p+xjZc8S0RE72yfs9yevjXDtjUy8vtKvbTdUyBsx0RF/cds94mO7p3tc5bb07fhBiRGq/V/yHZPQQRCMik2tne2z1luT99GImxS4uJ6Z/uc5Vp6Do2wSU1I6J3tPj89mAW2taSk/yHbMT1HQtg4bbbe2Y7/adsxsJ1pt/fOduL3BT33LRapJFvTemc7+acHi0NIDnC5emf7nOX2HCwRIZnndvfOtuOnB7Mh/of269c7287vC9J61FIQ7iNycnpnO+P7Aq1HLRXhXpaX1zvb5yw3s0ctHfFfOWxY72z3/74gu0fNjfifXFTUO9uDvy8Y0HMkhGRtRUXvbA//viC/50gIyVmVvfp3Kt6yvy/o6ds8EZJcfkmEixRxq3bGOGMyAeIrkO80Zdd3XgN9S5q6S3wDMpBI3WHYAb39XpuRR0aWTjFJNJoiIsBLZAH96w7BEBhvjOCMhsgoNEtE87cdgkHzt94YwRl4Gl6vSb5mhwV4c7umMjXA2BNGjfFchSngtzGmYQYB/ag3wmrlU8hssXBh47OOyEjJHOqIipLMd5AYBdMFiWBg0bx9Y5LHetIjP3WF1s9Bp47UfWgttBZScXHhqcJBA5nn9AcOGOKMd8bwPl2paktXiiHqsce++ReeAiv1o2qaWoRsmsru9iY6yB7Ppyh1hrqwKRGNyqWGBWGNEeb4gH5EDh0DxjtJcKl2gVmxbxu+iTuZrA6KHWEbZC+JHZtcYp8YW2ubZG+InZ/cYF9mXBZ/kp9MslICs0QlJk5IqE9YmKAk2C03W++xcqtVTbGHm2gHf4SYvqtDOAL+3OWNtlqNU6yMsdv72NWIRLw3dIhtSRTuERsA5qvtUXB1ojcqoL8nPQXmEzlLMH+XLosSpsKysgf7o1hUsgO19kz3YFE+keYaPNDBHAnwrrdWGErIt5rFENZoYd9qFjJrhsmbkT3YYSo2jTcppkgZH5GixaRFRPAppiSxVSa7GN2EfkbwYlxTgpiGyZY2uCDJM876efcu1HnGnkJxBLJFHs/JRUI29hiAio+dqkND8bHY4bl1hacWFbKY2OHDY4djE+sILR62aDFLNBpd6RRjpfw8iokzORMS8vOGMqc7y+1KNyoX78j5pPPjruMs7r2/smj23dHwtjUz1516h0+MHDZ17YqH2dTE+zuYgykskvXt2t/1tVXbuqOJ3X5tWdND4iwU60eVVkTCQKXV2ydReiFJok1i34D+udyDrG7G3c1kdjMZ3Yyrm0nvZpzdjAbGu1Jwanpc+oiwC8LKM6amN6avCLspbHXGQ30ezXlWiQpLTE5KHFiZ80aiIYVP4dyax8KTas21YbXhtRG1kbVRc81zw+aGz42YGzk3qsPdkWXJcmdkZfQbmjEtvCZilntW3yWuJRm+jFvD74q8pe8dObcPfCD84cj7sx7o2+5+zp0g1yK2KL2bcXUzGd1MaL3G7iUYuxdl7F4mDkFA3++NTRs+zZyVGRmuJmvueDViQGpygD/iTbfliBBx2Ipt423TbVtte21Gi81hW2A7YFMdtvU2bnsapxtZPBj73jihbmVexq1sH+PErIyLs9AelzBYnglrdMxgxgbUps5L5an2eJMqpiE6gfmwQxwYwXj7WCzg7AMiHMksOcPm7ZM0OE90HyLyiy0piCJibQkiem2a6GnTRC+bVazKJqNXtGLvd/BfkEn/bLtMhxnZMLTNPnxfNssWY4r+YI52CKOSEf2zxfETJsB8vl1YyU6WM3DiJNbn7crjxXm+PJ4njncGyamQVSY2Leh8LoNErkhGi0PMTZNRqGVYrGLJFjl3iyaULQH9G69bTMESLca3RApjFqMY2ZJ+gFgxjUemsw0Knca6RWO7T6Q4ex4rysXjrHWLPMF0ukicyc/P5M5ji3E8URYfW4TTiVO8aLHniPWULHBK8YfDmoijWrbc683qn+YyxOW4Y6yx1j5WxZgepaVQWF9TCjP0B6TFoeqMdqVQuisq0twvPIX1zQoLN3rUFHJYU1MYYT5I4UGQCTzbs2rVKjo9m7pFrG7xorozAqHUp0DmgiGDs9xZA/iQwUMLhg7Nz0tISDS5RW6Ij0tMwJXG4+NECnEXt1nWXrVi2ZDMW5/fOL5kWPavJ1/99LQYf2TznBVzExJyU1bvvGPqnOev3vs2O89+6eLG8vNcSZl5568aN3p5X4dnzFWzkybVTipw2VP7hGfkl6yonbb5ot+LDJKhf8azDRspkTk6KRJ3K7EDEYEQY+5mTN2MsZsJF2Hucg8OE1EyGYzPxohFRoUzhRKsYR5LuDHBrkRYrOmUzqJiZW6OlfEQGy76x2ZGMt1krgirqDctNPlMN+Ol3KSZ7jH5TbtM+0xGk7gziHuLScSViBSTuJFER0vmKxlykpHpHOEkYw/MCW+EiD2TUWZ1EeAyse/gcymJDW295MwtWO7M50esxwpFhi+0Hvkct+Fj4j4cgzQek59vfUHk8pBqZqLYBveQGNeQ/JiCmPx4V0yc2EFuTb6wcMa8nNWr27dt6+Ppm3bvZmtR43185jpmmtd147pTt47NwfNTJ1UpyGRJjn1PKf3oIIgr/do8qY5OJUtJbRvp8AYUV3tsfJ6lpL8injJyJWrABaCtoJ2K+M3JdCUNcitwJcgH2graCdoHwtswULRqoAWgzaCDokVJVextmsNakqXY0NeG82VREuk4SAcp5ADmgsaDpoPWgzaDjFJPSBaAVoJ2gk7IFq+S2HZLPuae2HaDLNrnzsuT1YZgtbZOVtsvqgmWYycGy/Lzg2ojgmqDBgfFA0qDZVZOsIzNzPOJMjwqb1cJHkKwyARMfCGQ8T+ShTG85NyjxJMfxBVjSOJVYtsz3HmbdyoqMYUrjGaRQ9+lsLaomLyScK7z4xRLDv4JPxZs4cfao2PyNpdcwA/RVtBOkMIP4fqAf0Ar+UHhc2AxaDNoJ2gv6DjIyA/iOoBrP99PFv4+5YKKQdNBm0E7QcdBJv4+0MrfE/8rlij4YhDn7wGt/F0s612ghb8D7h3+Dqb2WlvB8LxOyXhyQ4wjM8QkpoSY2IS8AH+17et+iCg3dhoR9aSSjsfvfCW9LXOQI6AktRXOcQT44XbN47inZCB/nfwgjpm8jpFfJw00AVQPWggygnsD3BvkA90MugfkByHKgFaQxveAXgK9QQNBXtAEkJnva8MwAb63zV3qKEngr/A/4a3ZwV/mf5blS/x5Wb7In5PlCyjTUO7hz7elOagkAu2EPlaUVpS5aDfwP7RnxDr0khi+E75zAHNBxaDxoOmg9SAj38nT22Y5YmHkSdpjxnswb6OPZfkQ3Wcm71yH112GANQEuEecBw6wWdvs5l73ho2oCnDfdAs4Ae7V68AJcF+5CpwA97zLwQlwz5oLToB72nRwAtzjq8ABAvzuJzKyHAXjL2VaiYVfAS9dAS9dAS9dQSq/Qlz0tSrmdmdbdjY8tsnr6Zft8O1gvqeYbxLz3cd8jcx3DfOtYr5C5ruY+TzMZ2e+NObzMt+TbBhc4WPejh7V4d4k5tvDfI8xXzPzuZkvk/kymE9jBd4Ad7adny+LClm0l4hDh/K8ImQfC3fCo07EvBM5YSdwL0iXNS+UtPSgsi1NlOnt2cXB+oAReQtKxvDd6Lgb27CbDoBUbNBuhNFuGNkNAxZgMWg6aBfoOEgHGaGdjomvl2gB5oKKQdNBK0HHQUY5neMgTgtCU9wqJ5YbmvR4UeO7cYkfQzi505tqtVs91jHKejuzpLHxaXoaLyD5f7fYGHNMgEVt/zLqqy+jKKwkjN/E11MqNuLmULm+7etUR4D9ps39pKMknt1BaSqijg0nN8tEOYyaZX0I2c2iHEx2/ijKvDb7VHSztLlzHDtYtOi13fG1/YjjY3uAgz1qf9LxphZQWZvjr5A8ut3xun2t44XcgBmSp9x40Wxz7NCkaqd9mOOxPVJ1FRo2tTmuEcV2x9X20Y5L7bKhMdhwcTNqXotjknuaYwzsldtnOLzNsLndUWy/2FEY1Boi+mx3DMQUPEE2G5PtZ5eDutKkwSkFAdbkzTFtMFXjHWqoKc+UY3KaHKZUU4opzhxrtpqjzZHmcLPZbDSrZm4mc1xAP+j1iOeJOKP8calRlT9glLyVk/wJpPxZI2dmTheQv49SySsnl7JK/66ZVDlD85+c7Aqw8InT/AZXKfPHVlJlVal/mKcyYNIn+Qs8lX7ThF9UtzJ2Uw2kfn59gFFVdYDpQrQmRXxH20mMxay5MUWUfdfcWFNDSQmXFycVxxbFDB9V/gNQH8Izj42epB58qn9D5eRq/yOpNf48weipNZX+W8WXuJ3sM3aioryTfSqKmupOpYh9VjFJyJWi8pqaygCbKvVIY59CDxHzqdQz48Ys9EgzpwX1NgX1MtEfehmigF5YGGVKvcywMKmnMqHX2pxRUd6akSF1EjVqljrNidrZOnsyoZOZKXUSfLRH6uxJ8Akdf5FUsduhkmaXKiyZ7FLFzpKlytQzKrkhlbWnVdbKkRR2Rsce1Ik62K0TdRA6nn/301iK5+H2kTUza8UX4PWuikZQvf+Gy5uS/L4ZmtY6syb0zbi7fsbMJlE2NPprXI3l/pmucq11ZO0PNNeK5pGu8laqraiqbq31Npa3jfSOrHA1lNe0j54wuKDHWGtPjzV4wg8YmyCMDRZjjS74geYC0TxajFUgxioQY432jpZjkYzxCdWtZiqtKasNlu08IhzxWp/irClNsC4sksE70pl0TcoOPK1soQhPjT/SVeqPAomm/iX9S0QTzpRoiha/cgg1JV0z0pmyg20JNVkhjnGVkmfJ0uallFQxpzz414wPREuWCocH0dP8Yx+0Vfi9DeXNS4gq/dmTK/3FE6dVt5pMkNaLJflHdMsiIirw+B8UDoBwhBAqymlFISsUsrCwkOK5+780VJaJU+DjT7YzbxpbQs01ij+tsoojFVSFvk7egWcpcXtorsECm5mHNXfbCE3b4wm9YpFYczctWRriQr5YEiqDPdGludslpz/CWZ7THlsCg+KjkMLEx6AoeM1nlGT4Z8Qu+sqsi1+k610URmH6KQqncPnbywhgJF6pTlEURQGjJVooGmglCzAG+B0eQ2OAfSgWGEd9gPHAbymB4oCJFA9MAn5DNkoEn0w28CmUDLRLTKUUYBrZ9a/x6CtQo1SgEw+2X1M6aUAX8CvKICcwk9KBbuCXlEUuYF+8B35J/cgNzJbooSz9JOVQX2B/iQMoG5hLHuBA6g8cBPyC8mgAMJ9ygYNpoP45DZE4lAYBCygfOIwG6/+i4RJH0BDgSImFNBR4HhUAi2gYsJiG65+Rl0YAS2gksJQKgWXAT6mczgNWUBFwFBXrJ2g0eYFjqAR4PpUCL5BYSWXAC6kcOJZG6cdpnMTxNBo4gcYAJ9L5+ic0SeJkugBYRZX6MZpCY4FTJV5E44DVNF7/J9XQBOA04DH6BU0EX0uTgXVUBbxY4nSaov+D6mkqsIEuAs4A/p1mUg1wFk0DNtIvgJdQrf4xzZbYRHXAOXSxfpTmUj34SyXOowbgfJoB+WU0E7hA4kKapX9Ei6gRuJhmA5slLqEm/UNaSnOAl9Nc4BXAv9EyuhS4nOYDr6TLgFdJXEELgFfTQuA1tEg/Qisl+qgZuIqWAH9JS3Xxm8LLgaslrqEr9EN0LS0DXkfLgdfTlcC1dJX+AbXQCuANdDUk64Af0I10DfAmWglcT6uANwMP0q/pl8Bb6FfAW2m1foBuk3g7rQFuoOuAd9D1aP0N8ABtpLXATdSi76c76QbgXbQO+FuJd9NNwM20HngP3Qy8F/g+3Ue/Bt5PtwAfoFuBD9Jt+nv0EN2uv0u/ow3ALXQH8GGJj9BvgI/SRuDv6U7gYxIfp7uAW+m3QD/dDWwFvkNttBnYTvcAO+g+/W3aRvfrb9F2iU/QA8AAPQjspIeAOyQ+SVuAT9HD+pv0ND0CfEbiTnoUuIt+D/wDPQZ8lh4H7qat+hv0R/IDn6NW/a/0vMQ/URvwz9Suv04vUAdwD20DvkjbgS/RE8CXKQB8hTqBeyXuox3Av9BTwFfpaf01eg34Kr1OzwD/SjuBb9Au/S/0psS36Fng27Qb+A79EfiuxPfoOeD79DxwP/1J30cHJB6kF/S99AHtAR6iF4GHJR6hl4B/o5eBH9IrwI9on/4KHZX4Mf0F+Hd6VX+Z/kGvAf8p8Ri9DvyE3tBfouP0JvCExE/pLeBn9DbwX/QO8HOJX9B7+ot0kt4Hfkn7gV8B99DXdAD4DR0EfksfAL+TeIoO6y9QFx0B6vQ34H9z+n8+p3/6M8/p//i3c/rHP5LTPz4npx/9kZz+0Tk5/cN/I6cfOZ3TF/fI6Yd/JKcfljn98Dk5/ZDM6YfOyumHZE4/JHP6obNy+gfn5PSDMqcflDn94M8wp7/9/yinv/7fnP7fnP6zy+k/9+f0n29O/7Hn9P/m9P/m9B/O6X/++ef0/wVVj3DwCmVuZHN0cmVhbQplbmRvYmoKOSAwIG9iago8PC9UeXBlIC9Gb250RGVzY3JpcHRvcgovRm9udE5hbWUgL0FBQUFBQStBcmlhbE1UCi9GbGFncyA0Ci9Bc2NlbnQgOTA1LjI3MzQ0Ci9EZXNjZW50IC0yMTEuOTE0MDYKL1N0ZW1WIDQ1Ljg5ODQzOAovQ2FwSGVpZ2h0IDcxNS44MjAzMQovSXRhbGljQW5nbGUgMAovRm9udEJCb3ggWy02NjQuNTUwNzggLTMyNC43MDcwMyAyMDAwIDEwMDUuODU5MzhdCi9Gb250RmlsZTIgOCAwIFI+PgplbmRvYmoKMTAgMCBvYmoKPDwvVHlwZSAvRm9udAovRm9udERlc2NyaXB0b3IgOSAwIFIKL0Jhc2VGb250IC9BQUFBQUErQXJpYWxNVAovU3VidHlwZSAvQ0lERm9udFR5cGUyCi9DSURUb0dJRE1hcCAvSWRlbnRpdHkKL0NJRFN5c3RlbUluZm8gPDwvUmVnaXN0cnkgKEFkb2JlKQovT3JkZXJpbmcgKElkZW50aXR5KQovU3VwcGxlbWVudCAwPj4KL1cgWzAgWzc1MF0gNTUgWzYxMC44Mzk4NF0gNzIgWzU1Ni4xNTIzNF0gODcgWzI3Ny44MzIwM11dCi9EVyA1MDA+PgplbmRvYmoKMTEgMCBvYmoKPDwvRmlsdGVyIC9GbGF0ZURlY29kZQovTGVuZ3RoIDI1MD4+IHN0cmVhbQp4nF2Qy2rEIBSG9z7FWU4Xg0lmMtNFEMqUQha90LQPYPQkFRoVYxZ5+3pJU6ig8PP/n+dCb+1jq5UH+uaM6NDDoLR0OJvFCYQeR6VJWYFUwm8qvWLiltAAd+vscWr1YEjTAND34M7erXB4kKbHO0JfnUSn9AiHz1sXdLdY+40Tag8FYQwkDuGnZ25f+IRAE3ZsZfCVX4+B+Ut8rBahSrrM3QgjcbZcoON6RNIU4TBonsJhBLX851eZ6gfxxV1Mn64hXRT1mUV1vk/qUid2S5W/zF6ivmQos9fTls5+LBqXs08kFufCMGmDaYrYv9K4L9kaG6l4fwAdQH9hCmVuZHN0cmVhbQplbmRvYmoKNCAwIG9iago8PC9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMAovQmFzZUZvbnQgL0FBQUFBQStBcmlhbE1UCi9FbmNvZGluZyAvSWRlbnRpdHktSAovRGVzY2VuZGFudEZvbnRzIFsxMCAwIFJdCi9Ub1VuaWNvZGUgMTEgMCBSPj4KZW5kb2JqCnhyZWYKMCAxMgowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTUgMDAwMDAgbiAKMDAwMDAwMDM4MiAwMDAwMCBuIAowMDAwMDAwMTA4IDAwMDAwIG4gCjAwMDAwMDk2MDYgMDAwMDAgbiAKMDAwMDAwMDE0NSAwMDAwMCBuIAowMDAwMDAwNTkwIDAwMDAwIG4gCjAwMDAwMDA2NDUgMDAwMDAgbiAKMDAwMDAwMDY5MiAwMDAwMCBuIAowMDAwMDA4Nzg3IDAwMDAwIG4gCjAwMDAwMDkwMjEgMDAwMDAgbiAKMDAwMDAwOTI4NSAwMDAwMCBuIAp0cmFpbGVyCjw8L1NpemUgMTIKL1Jvb3QgNyAwIFIKL0luZm8gMSAwIFI+PgpzdGFydHhyZWYKOTc0NQolJUVPRgo=","contentEncoding":"BASE64","fileName":"document.pdf","mediaType":"application/pdf","testCaseStartedId":"76","testStepId":"67"}} -{"testStepFinished":{"testCaseStartedId":"76","testStepId":"67","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":47000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"76","timestamp":{"nanos":48000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"timestamp":{"nanos":49000000,"seconds":0}}} diff --git a/python/src/message_samples/attachments/attachments.feature.ts b/python/src/message_samples/attachments/attachments.feature.ts deleted file mode 100644 index c1e9c6bd..00000000 --- a/python/src/message_samples/attachments/attachments.feature.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Before, When } from '@cucumber/fake-cucumber' -import { ReadableStreamBuffer } from 'stream-buffers' -import fs from 'fs' - -// Cucumber-JVM needs to use a Before hook in order to create attachments -Before(() => undefined) - -When('the string {string} is attached as {string}', function (text: string, mediaType: string) { - this.attach(text, mediaType) -}) - -When('the string {string} is logged', function (text: string) { - this.log(text) -}) - -When('text with ANSI escapes is logged', function () { - this.log( - 'This displays a \x1b[31mr\x1b[0m\x1b[91ma\x1b[0m\x1b[33mi\x1b[0m\x1b[32mn\x1b[0m\x1b[34mb\x1b[0m\x1b[95mo\x1b[0m\x1b[35mw\x1b[0m' - ) -}) - -When('the following string is attached as {string}:', function (mediaType: string, text: string) { - this.attach(text, mediaType) -}) - -When( - 'an array with {int} bytes is attached as {string}', - function (size: number, mediaType: string) { - const data = [...Array(size).keys()] - const buffer = Buffer.from(data) - this.attach(buffer, mediaType) - } -) - -When( - 'a stream with {int} bytes are attached as {string}', - async function (size: number, mediaType: string) { - const data = [...Array(size).keys()] - const buffer = Buffer.from(data) - const stream = new ReadableStreamBuffer({ chunkSize: 1, frequency: 1 }) - stream.put(buffer) - stream.stop() - - await this.attach(stream, mediaType) - } -) - -When('a JPEG image is attached', async function () { - await this.attach(fs.createReadStream(__dirname + '/cucumber.png'), 'image/png') -}) - -When('the {word} png is attached', async function (filename) { - await this.attach(fs.createReadStream(__dirname + `/${filename}`), 'image/png') -}) - -When('a PDF document is attached with a filename', async function () { - await this.attach(fs.createReadStream(__dirname + '/document.pdf'), 'application/pdf', 'document.pdf') -}) diff --git a/python/src/message_samples/attachments/cucumber.png b/python/src/message_samples/attachments/cucumber.png deleted file mode 100644 index 2760899aa0ce16aeaaea93d3118a32e7ac5bec8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1739 zcmV;+1~mDJP)G+r@kQ0VOJz1t=x5=pe3owlM@Ei<#*ZtpGI zgKd}Iv=WU6L@O5L5Qs#)gFvk*7OQ`VCsjOx5<>9^RV-lQA0`qL#Hi6fjMC@#y`7oe zS+={g-EDP}m+f}vz4x2%_`Ec`caU@Gwv+u9&;ebh;EPxToe6TQSS7$RIEHqf|0i z0O+ z#n5`Lu?_+l5a?76FBT_ov)oVPu)W&2iyqQk6q$E2`kQlqo37e8-)c+O?QiP<=H+=W zgC{tLKe`UI8wSZ$`}IIZS7^VP!&SQ9uqqj{=4V~1HP0i=kNxUV+pBnmxV8-q#Bxu7a+-a2h-P!vK`Neu>T>`ydm{x2F*T=U zFja;RD&fUT?=ygOHKmEIjm9$XXg4i$m^A1Td}8TX_oouO^1 zftu}jxiw*Sqct@^-zMG^t)7q>c1_O=)^$NOakew|C1vwbb(rq-=>$Sb3W6-RZHa~m zCJ-n2XtkjN1C$hf07a9cuvH0K135T-J;#nfDUID~Sv*Yz!r1hE3|a|Q4_9AFEWLHK zWz~oq!$8|OVjZ(mf6Y*Z+@G&h%4HXA<`4i@t!XO}{GYwU7nxru-K+|Xtu%RHv$V5t zB%F}kxeBctB<7atq+W_2XaHsIuS|aaB@`qli21Zmg1ge~X)cg!Z$@+@T2Kf6wH3yz z&3Yvsd2vMF!t&A=G!b@&(o#XX>H~4DCJ(w*r-TNAhSk2Rta1dYR_3O9WK; zw#R~odmNn4Rrysbu1(x67Wr<38~#FiG1`n}wO&7`@#)Xk3f`-e^xfhbRWBNCp0aZ6 zG7j-w;#H4aR;4%|7`O;-+)Hl;uEM%I>mVnijiapH>2)nQ~8L|KJMiw<@G*t1yFW9;lFYc#uS`DwjogG)sqA zR1ZXz{)UVWQ#sGl0$Aj@M%qBOs8U>G?P+&{nu~!`wccEicA`NtKbHn#g?=au3r^~) z3?!GiqlV-fJj2A0p}mr}21v220F29iQ1fLV>-W%pUD-_S!;=aJIQ+*`W9=9^HPvL{ z0;-_op8_N*ciN&xk6wP@c=5J5d#{rWB-U?ag_zePQ!sYV&o8}(nae94B=$6zwdRg$ z{h^gdI-K$AkW4|MJIzg%@h!p>_RSE#rObbMsUUTO7bj4~!21~&^MANd_d&CC2wth| hfX@)Vpvv|h{{nxzjlgvW5(5AL002ovPDHLkV1gBrLk9o= diff --git a/python/src/message_samples/attachments/document.pdf b/python/src/message_samples/attachments/document.pdf deleted file mode 100644 index 4647f3c9d70173713ad061f405a1aa9146615677..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10061 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∨WEz|Va{bk-|&;_RAeM9+J zUnh0UX026ZO7^YamIZ5tFXz1xw3~EOReU=#MGVLU&?oU#=?!Q&VOGMa9g3{|}-(rTcEVg5D)DI{a z2GWDRGn4V{waEAz^x84pWqc%zrU@5vy=C+T^*opZy{sEeGZf(2bRQ7&>;3n3xehtByZm`RwV*79njVs~e!)Ed` z;YH~-tZ&NoXtbHSzJwFj7w*SIi)C%{Z8`Yu97yZ~Sa9T+txx2H)bjqO(lY!JZ9$Wd z?q>Zu#8Mn;b2b@_2~w}=Ym!RS<3n-cI9 zwjH50Myt%cFL0csJ&^^?GTKnrwi)*kO{uyhF(kR-koS?7m80R(c zIKR7oLwk9?hVqQyn)s}&`*Z`ke0eNnCvq*jB#li^lS_Wwa*V!tmKv21n> zIWRmXIB*O$9CN=2MaFzX^}(gDA^Pdq3=-`OpZdO+JS|#VtZN9tHt-cWHTu>u-?F#k zg|~2l_XW@B=IvR%<3*oH%%q4gQvvODblS~06nfp|{k(t{nm$Q>+P@j-Oauu{)-!d1p-7KZuoz;VzBBwu( zGi;S^D}Nr}uHT)sBb(kg=cqeOjYzwL|Arc%fB!xIC)99<9!MY@;SLsdNLzul+F$c0JmcRloYIBFCpvZ;0 zrxE)DdEkIRcsapfEub zk(E%lm6nxIgxR484--`O7Ra}MnAP4oqEeT&F}1xzI#dy67AUUdEr3}R#n~WGfR3^Q zioLP0F#|CFV;ah+=45AQg}6g_09<$M$Ll-jLzfTCr4Imu0lE+n7biats*w5sK5l?6 z7!2VAfw_55xBPr4WP^_nHHs>zKB^!RuK{4LyBPnd!@pod{~vUCCq~vXRzqlXO#k@lV>sE{OE+1y!pwuC+l-%Lw!84+cXP;}JYhW}G195Vmt850;vz9?0pz?(k=tBTq|bz2P^i#wnS0J__|f6=t71Hu#+ z)d1YMs6P1X06@TC9x%WZ@J|~E#Rc6R0Gof>c=%CR&wtoJT&RxucN-MKg~ECM-Npst z{qJ~SD5|^u!w>Sm_(7omwJtv&O0xek7s|zr%JkpkLAm+=WnH8L4AtZgckG**g&V3e ns1{VUwMD&4{_NjB+U+0Jazw%$kbl$)%Et@FWnhq0mcsoXXWVEI diff --git a/python/src/message_samples/cdata/cdata.feature b/python/src/message_samples/cdata/cdata.feature deleted file mode 100644 index 9983c41a..00000000 --- a/python/src/message_samples/cdata/cdata.feature +++ /dev/null @@ -1,6 +0,0 @@ -Feature: cdata - - Cucumber xml formatters should be able to handle xml cdata elements - - Scenario: cdata - Given I have 42 in my belly diff --git a/python/src/message_samples/cdata/cdata.feature.ndjson b/python/src/message_samples/cdata/cdata.feature.ndjson deleted file mode 100644 index 3c2a89c9..00000000 --- a/python/src/message_samples/cdata/cdata.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: cdata\n \n Cucumber xml formatters should be able to handle xml cdata elements\n\n Scenario: cdata\n Given I have 42 in my belly\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/cdata/cdata.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":5},"name":"cdata","steps":[{"id":"1","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":6},"text":"I have 42 in my belly"}],"tags":[]}}],"description":" Cucumber xml formatters should be able to handle xml cdata elements","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"cdata","tags":[]},"uri":"samples/cdata/cdata.feature"}} -{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"cdata","steps":[{"astNodeIds":["1"],"id":"3","text":"I have 42 in my belly","type":"Context"}],"tags":[],"uri":"samples/cdata/cdata.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"I have {int} in my belly","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/cdata/cdata.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"6","pickleId":"4","testSteps":[{"id":"5","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":7,"value":"42"},"parameterTypeName":"int"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/cdata/cdata.feature.ts b/python/src/message_samples/cdata/cdata.feature.ts deleted file mode 100644 index 4d8af61a..00000000 --- a/python/src/message_samples/cdata/cdata.feature.ts +++ /dev/null @@ -1,6 +0,0 @@ -import assert from 'assert' -import { Given } from '@cucumber/fake-cucumber' - -Given('I have {int} in my belly', function (cukeCount: number) { - assert(cukeCount) -}) diff --git a/python/src/message_samples/data-tables/data-tables.feature b/python/src/message_samples/data-tables/data-tables.feature deleted file mode 100644 index c5ae8059..00000000 --- a/python/src/message_samples/data-tables/data-tables.feature +++ /dev/null @@ -1,12 +0,0 @@ -Feature: Data Tables - Data Tables can be places underneath a step and will be passed as the last - argument to the step definition. They can be used to represent richer data - structures, and can also be transformed to other types. - - Scenario: transposed table - When the following table is transposed: - | a | b | - | 1 | 2 | - Then it should be: - | a | 1 | - | b | 2 | diff --git a/python/src/message_samples/data-tables/data-tables.feature.ndjson b/python/src/message_samples/data-tables/data-tables.feature.ndjson deleted file mode 100644 index f21c8180..00000000 --- a/python/src/message_samples/data-tables/data-tables.feature.ndjson +++ /dev/null @@ -1,15 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Data Tables\n Data Tables can be places underneath a step and will be passed as the last\n argument to the step definition. They can be used to represent richer data\n structures, and can also be transformed to other types.\n\n Scenario: transposed table\n When the following table is transposed:\n | a | b |\n | 1 | 2 |\n Then it should be:\n | a | 1 |\n | b | 2 |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/data-tables/data-tables.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"8","keyword":"Scenario","location":{"column":3,"line":6},"name":"transposed table","steps":[{"dataTable":{"location":{"column":7,"line":8},"rows":[{"cells":[{"location":{"column":9,"line":8},"value":"a"},{"location":{"column":13,"line":8},"value":"b"}],"id":"2","location":{"column":7,"line":8}},{"cells":[{"location":{"column":9,"line":9},"value":"1"},{"location":{"column":13,"line":9},"value":"2"}],"id":"3","location":{"column":7,"line":9}}]},"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":7},"text":"the following table is transposed:"},{"dataTable":{"location":{"column":7,"line":11},"rows":[{"cells":[{"location":{"column":9,"line":11},"value":"a"},{"location":{"column":13,"line":11},"value":"1"}],"id":"5","location":{"column":7,"line":11}},{"cells":[{"location":{"column":9,"line":12},"value":"b"},{"location":{"column":13,"line":12},"value":"2"}],"id":"6","location":{"column":7,"line":12}}]},"id":"7","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":10},"text":"it should be:"}],"tags":[]}}],"description":" Data Tables can be places underneath a step and will be passed as the last\n argument to the step definition. They can be used to represent richer data\n structures, and can also be transformed to other types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Data Tables","tags":[]},"uri":"samples/data-tables/data-tables.feature"}} -{"pickle":{"astNodeIds":["8"],"id":"11","language":"en","name":"transposed table","steps":[{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"b"}]},{"cells":[{"value":"1"},{"value":"2"}]}]}},"astNodeIds":["4"],"id":"9","text":"the following table is transposed:","type":"Action"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"a"},{"value":"1"}]},{"cells":[{"value":"b"},{"value":"2"}]}]}},"astNodeIds":["7"],"id":"10","text":"it should be:","type":"Outcome"}],"tags":[],"uri":"samples/data-tables/data-tables.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"the following table is transposed:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":5},"uri":"samples/data-tables/data-tables.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"it should be:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":9},"uri":"samples/data-tables/data-tables.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"14","pickleId":"11","testSteps":[{"id":"12","pickleStepId":"9","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"13","pickleStepId":"10","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"15","testCaseId":"14","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"15","testStepId":"12","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"15","testStepId":"12","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"15","testStepId":"13","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"15","testStepId":"13","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"15","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"timestamp":{"nanos":7000000,"seconds":0}}} diff --git a/python/src/message_samples/data-tables/data-tables.feature.ts b/python/src/message_samples/data-tables/data-tables.feature.ts deleted file mode 100644 index b6c71dc1..00000000 --- a/python/src/message_samples/data-tables/data-tables.feature.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { When, Then } from '@cucumber/fake-cucumber' -// TODO: Figure out a better way to export this -import DataTable from '@cucumber/fake-cucumber/dist/src/DataTable' - -When('the following table is transposed:', function (table: DataTable) { - this.transposed = table.transpose() -}) - -Then('it should be:', function (expected: DataTable) { - this.transposed.diff(expected) -}) diff --git a/python/src/message_samples/examples-tables/examples-tables.feature b/python/src/message_samples/examples-tables/examples-tables.feature deleted file mode 100644 index ed82f0f3..00000000 --- a/python/src/message_samples/examples-tables/examples-tables.feature +++ /dev/null @@ -1,28 +0,0 @@ -Feature: Examples Tables - Sometimes it can be desireable to run the same scenario multiple times - with different data each time. This can be done by placing an Examples - section with an Examples Table underneath a Scenario, and use - in the Scenario, matching the table headers. - - Scenario Outline: eating cucumbers - Given there are cucumbers - When I eat cucumbers - Then I should have cucumbers - - @passing - Examples: These are passing - | start | eat | left | - | 12 | 5 | 7 | - | 20 | 5 | 15 | - - @failing - Examples: These are failing - | start | eat | left | - | 12 | 20 | 0 | - | 0 | 1 | 0 | - - @undefined - Examples: These are undefined because the value is not an {int} - | start | eat | left | - | 12 | banana | 12 | - | 0 | 1 | apple | diff --git a/python/src/message_samples/examples-tables/examples-tables.feature.ndjson b/python/src/message_samples/examples-tables/examples-tables.feature.ndjson deleted file mode 100644 index 5dbd02d0..00000000 --- a/python/src/message_samples/examples-tables/examples-tables.feature.ndjson +++ /dev/null @@ -1,68 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Examples Tables\n Sometimes it can be desireable to run the same scenario multiple times\n with different data each time. This can be done by placing an Examples\n section with an Examples Table underneath a Scenario, and use \n in the Scenario, matching the table headers.\n\n Scenario Outline: eating cucumbers\n Given there are cucumbers\n When I eat cucumbers\n Then I should have cucumbers\n\n @passing\n Examples: These are passing\n | start | eat | left |\n | 12 | 5 | 7 |\n | 20 | 5 | 15 |\n\n @failing\n Examples: These are failing\n | start | eat | left |\n | 12 | 20 | 0 |\n | 0 | 1 | 0 |\n\n @undefined\n Examples: These are undefined because the value is not an {int}\n | start | eat | left |\n | 12 | banana | 12 |\n | 0 | 1 | apple |\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/examples-tables/examples-tables.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"10","keyword":"Examples","location":{"column":5,"line":13},"name":"These are passing","tableBody":[{"cells":[{"location":{"column":12,"line":15},"value":"12"},{"location":{"column":19,"line":15},"value":"5"},{"location":{"column":26,"line":15},"value":"7"}],"id":"7","location":{"column":7,"line":15}},{"cells":[{"location":{"column":12,"line":16},"value":"20"},{"location":{"column":19,"line":16},"value":"5"},{"location":{"column":25,"line":16},"value":"15"}],"id":"8","location":{"column":7,"line":16}}],"tableHeader":{"cells":[{"location":{"column":9,"line":14},"value":"start"},{"location":{"column":17,"line":14},"value":"eat"},{"location":{"column":23,"line":14},"value":"left"}],"id":"6","location":{"column":7,"line":14}},"tags":[{"id":"9","location":{"column":5,"line":12},"name":"@passing"}]},{"description":"","id":"15","keyword":"Examples","location":{"column":5,"line":19},"name":"These are failing","tableBody":[{"cells":[{"location":{"column":12,"line":21},"value":"12"},{"location":{"column":18,"line":21},"value":"20"},{"location":{"column":26,"line":21},"value":"0"}],"id":"12","location":{"column":7,"line":21}},{"cells":[{"location":{"column":13,"line":22},"value":"0"},{"location":{"column":19,"line":22},"value":"1"},{"location":{"column":26,"line":22},"value":"0"}],"id":"13","location":{"column":7,"line":22}}],"tableHeader":{"cells":[{"location":{"column":9,"line":20},"value":"start"},{"location":{"column":17,"line":20},"value":"eat"},{"location":{"column":23,"line":20},"value":"left"}],"id":"11","location":{"column":7,"line":20}},"tags":[{"id":"14","location":{"column":5,"line":18},"name":"@failing"}]},{"description":"","id":"20","keyword":"Examples","location":{"column":5,"line":25},"name":"These are undefined because the value is not an {int}","tableBody":[{"cells":[{"location":{"column":12,"line":27},"value":"12"},{"location":{"column":17,"line":27},"value":"banana"},{"location":{"column":29,"line":27},"value":"12"}],"id":"17","location":{"column":7,"line":27}},{"cells":[{"location":{"column":13,"line":28},"value":"0"},{"location":{"column":22,"line":28},"value":"1"},{"location":{"column":26,"line":28},"value":"apple"}],"id":"18","location":{"column":7,"line":28}}],"tableHeader":{"cells":[{"location":{"column":9,"line":26},"value":"start"},{"location":{"column":17,"line":26},"value":"eat"},{"location":{"column":26,"line":26},"value":"left"}],"id":"16","location":{"column":7,"line":26}},"tags":[{"id":"19","location":{"column":5,"line":24},"name":"@undefined"}]}],"id":"21","keyword":"Scenario Outline","location":{"column":3,"line":7},"name":"eating cucumbers","steps":[{"id":"3","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":8},"text":"there are cucumbers"},{"id":"4","keyword":"When ","keywordType":"Action","location":{"column":5,"line":9},"text":"I eat cucumbers"},{"id":"5","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":10},"text":"I should have cucumbers"}],"tags":[]}}],"description":" Sometimes it can be desireable to run the same scenario multiple times\n with different data each time. This can be done by placing an Examples\n section with an Examples Table underneath a Scenario, and use \n in the Scenario, matching the table headers.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Examples Tables","tags":[]},"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["21","7"],"id":"25","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","7"],"id":"22","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["4","7"],"id":"23","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["5","7"],"id":"24","text":"I should have 7 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"9","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["21","8"],"id":"29","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","8"],"id":"26","text":"there are 20 cucumbers","type":"Context"},{"astNodeIds":["4","8"],"id":"27","text":"I eat 5 cucumbers","type":"Action"},{"astNodeIds":["5","8"],"id":"28","text":"I should have 15 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"9","name":"@passing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["21","12"],"id":"33","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","12"],"id":"30","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["4","12"],"id":"31","text":"I eat 20 cucumbers","type":"Action"},{"astNodeIds":["5","12"],"id":"32","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"14","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["21","13"],"id":"37","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","13"],"id":"34","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["4","13"],"id":"35","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["5","13"],"id":"36","text":"I should have 0 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"14","name":"@failing"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["21","17"],"id":"41","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","17"],"id":"38","text":"there are 12 cucumbers","type":"Context"},{"astNodeIds":["4","17"],"id":"39","text":"I eat banana cucumbers","type":"Action"},{"astNodeIds":["5","17"],"id":"40","text":"I should have 12 cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"19","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"pickle":{"astNodeIds":["21","18"],"id":"45","language":"en","name":"eating cucumbers","steps":[{"astNodeIds":["3","18"],"id":"42","text":"there are 0 cucumbers","type":"Context"},{"astNodeIds":["4","18"],"id":"43","text":"I eat 1 cucumbers","type":"Action"},{"astNodeIds":["5","18"],"id":"44","text":"I should have apple cucumbers","type":"Outcome"}],"tags":[{"astNodeId":"19","name":"@undefined"}],"uri":"samples/examples-tables/examples-tables.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"there are {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"I eat {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"I should have {int} cucumbers","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/examples-tables/examples-tables.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"49","pickleId":"25","testSteps":[{"id":"46","pickleStepId":"22","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"47","pickleStepId":"23","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"48","pickleStepId":"24","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"7"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"53","pickleId":"29","testSteps":[{"id":"50","pickleStepId":"26","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"51","pickleStepId":"27","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"5"},"parameterTypeName":"int"}]}]},{"id":"52","pickleStepId":"28","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"15"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"57","pickleId":"33","testSteps":[{"id":"54","pickleStepId":"30","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"55","pickleStepId":"31","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"20"},"parameterTypeName":"int"}]}]},{"id":"56","pickleStepId":"32","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"61","pickleId":"37","testSteps":[{"id":"58","pickleStepId":"34","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"59","pickleStepId":"35","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"60","pickleStepId":"36","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"0"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"65","pickleId":"41","testSteps":[{"id":"62","pickleStepId":"38","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"12"},"parameterTypeName":"int"}]}]},{"id":"63","pickleStepId":"39","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"64","pickleStepId":"40","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":14,"value":"12"},"parameterTypeName":"int"}]}]}]}} -{"testCase":{"id":"69","pickleId":"45","testSteps":[{"id":"66","pickleStepId":"42","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"0"},"parameterTypeName":"int"}]}]},{"id":"67","pickleStepId":"43","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":6,"value":"1"},"parameterTypeName":"int"}]}]},{"id":"68","pickleStepId":"44","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCaseStarted":{"attempt":0,"id":"70","testCaseId":"49","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"70","testStepId":"46","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"70","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"70","testStepId":"47","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"70","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"70","testStepId":"48","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"70","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"70","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"71","testCaseId":"53","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"71","testStepId":"50","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"71","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"71","testStepId":"51","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"71","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"71","testStepId":"52","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"71","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"71","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"72","testCaseId":"57","timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"72","testStepId":"54","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"72","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"72","testStepId":"55","timestamp":{"nanos":20000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"72","testStepId":"55","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"72","testStepId":"56","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"72","testStepId":"56","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-8 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-8 !== 0\n\nsamples/examples-tables/examples-tables.feature:10\nsamples/examples-tables/examples-tables.feature:21","status":"FAILED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"72","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"73","testCaseId":"61","timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"73","testStepId":"58","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"73","testStepId":"58","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"73","testStepId":"59","timestamp":{"nanos":28000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"73","testStepId":"59","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":29000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"73","testStepId":"60","timestamp":{"nanos":30000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"73","testStepId":"60","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Expected values to be strictly equal:\n\n-1 !== 0\n","type":"AssertionError"},"message":"Expected values to be strictly equal:\n\n-1 !== 0\n\nsamples/examples-tables/examples-tables.feature:10\nsamples/examples-tables/examples-tables.feature:22","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"73","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"74","testCaseId":"65","timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"74","testStepId":"62","timestamp":{"nanos":34000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"74","testStepId":"62","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"74","testStepId":"63","timestamp":{"nanos":36000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"74","testStepId":"63","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":37000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"74","testStepId":"64","timestamp":{"nanos":38000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"74","testStepId":"64","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":39000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"74","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"75","testCaseId":"69","timestamp":{"nanos":41000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"75","testStepId":"66","timestamp":{"nanos":42000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"75","testStepId":"66","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":43000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"75","testStepId":"67","timestamp":{"nanos":44000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"75","testStepId":"67","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"75","testStepId":"68","timestamp":{"nanos":46000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"75","testStepId":"68","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":47000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"75","timestamp":{"nanos":48000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":49000000,"seconds":0}}} diff --git a/python/src/message_samples/examples-tables/examples-tables.feature.ts b/python/src/message_samples/examples-tables/examples-tables.feature.ts deleted file mode 100644 index 336cd24b..00000000 --- a/python/src/message_samples/examples-tables/examples-tables.feature.ts +++ /dev/null @@ -1,14 +0,0 @@ -import assert from 'assert' -import { Given, When, Then } from '@cucumber/fake-cucumber' - -Given('there are {int} cucumbers', function (initialCount) { - this.count = initialCount -}) - -When('I eat {int} cucumbers', function (eatCount) { - this.count -= eatCount -}) - -Then('I should have {int} cucumbers', function (expectedCount) { - assert.strictEqual(this.count, expectedCount) -}) diff --git a/python/src/message_samples/hooks/cucumber.svg b/python/src/message_samples/hooks/cucumber.svg deleted file mode 100644 index 537ee11d..00000000 --- a/python/src/message_samples/hooks/cucumber.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/python/src/message_samples/hooks/hooks.feature b/python/src/message_samples/hooks/hooks.feature deleted file mode 100644 index cf6a6b3c..00000000 --- a/python/src/message_samples/hooks/hooks.feature +++ /dev/null @@ -1,20 +0,0 @@ -Feature: Hooks - Hooks are special steps that run before or after each scenario's steps. - They can also conditionally target specific scenarios, using tag expressions - - Scenario: no tags, passed step - When a step passes - - Scenario: no tags, failed step - When a step throws an exception - - Scenario: no tags, undefined step - When a step throws an exception - - @some-tag - Scenario: with a tag, passed step - When a step passes - - @with-attachment - Scenario: with an attachment in the hook - When a step passes diff --git a/python/src/message_samples/hooks/hooks.feature.ndjson b/python/src/message_samples/hooks/hooks.feature.ndjson deleted file mode 100644 index 36b2db13..00000000 --- a/python/src/message_samples/hooks/hooks.feature.ndjson +++ /dev/null @@ -1,77 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Hooks\n Hooks are special steps that run before or after each scenario's steps.\n They can also conditionally target specific scenarios, using tag expressions\n\n Scenario: no tags, passed step\n When a step passes\n\n Scenario: no tags, failed step\n When a step throws an exception\n\n Scenario: no tags, undefined step\n When a step throws an exception\n\n @some-tag\n Scenario: with a tag, passed step\n When a step passes\n\n @with-attachment\n Scenario: with an attachment in the hook\n When a step passes","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/hooks/hooks.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"8","keyword":"Scenario","location":{"column":3,"line":5},"name":"no tags, passed step","steps":[{"id":"7","keyword":"When ","keywordType":"Action","location":{"column":5,"line":6},"text":"a step passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":8},"name":"no tags, failed step","steps":[{"id":"9","keyword":"When ","keywordType":"Action","location":{"column":5,"line":9},"text":"a step throws an exception"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":11},"name":"no tags, undefined step","steps":[{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":12},"text":"a step throws an exception"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"15","keyword":"Scenario","location":{"column":3,"line":15},"name":"with a tag, passed step","steps":[{"id":"13","keyword":"When ","keywordType":"Action","location":{"column":5,"line":16},"text":"a step passes"}],"tags":[{"id":"14","location":{"column":3,"line":14},"name":"@some-tag"}]}},{"scenario":{"description":"","examples":[],"id":"18","keyword":"Scenario","location":{"column":3,"line":19},"name":"with an attachment in the hook","steps":[{"id":"16","keyword":"When ","keywordType":"Action","location":{"column":5,"line":20},"text":"a step passes"}],"tags":[{"id":"17","location":{"column":3,"line":18},"name":"@with-attachment"}]}}],"description":" Hooks are special steps that run before or after each scenario's steps.\n They can also conditionally target specific scenarios, using tag expressions","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Hooks","tags":[]},"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["8"],"id":"20","language":"en","name":"no tags, passed step","steps":[{"astNodeIds":["7"],"id":"19","text":"a step passes","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["10"],"id":"22","language":"en","name":"no tags, failed step","steps":[{"astNodeIds":["9"],"id":"21","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["12"],"id":"24","language":"en","name":"no tags, undefined step","steps":[{"astNodeIds":["11"],"id":"23","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["15"],"id":"26","language":"en","name":"with a tag, passed step","steps":[{"astNodeIds":["13"],"id":"25","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"14","name":"@some-tag"}],"uri":"samples/hooks/hooks.feature"}} -{"pickle":{"astNodeIds":["18"],"id":"28","language":"en","name":"with an attachment in the hook","steps":[{"astNodeIds":["16"],"id":"27","text":"a step passes","type":"Action"}],"tags":[{"astNodeId":"17","name":"@with-attachment"}],"uri":"samples/hooks/hooks.feature"}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/hooks/hooks.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/hooks/hooks.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":4},"uri":"samples/hooks/hooks.feature.ts"}}} -{"hook":{"id":"1","name":"A named hook","sourceReference":{"location":{"line":8},"uri":"samples/hooks/hooks.feature.ts"}}} -{"hook":{"id":"4","sourceReference":{"location":{"line":20},"uri":"samples/hooks/hooks.feature.ts"}}} -{"hook":{"id":"5","sourceReference":{"location":{"line":24},"uri":"samples/hooks/hooks.feature.ts"},"tagExpression":"@some-tag or @some-other-tag"}} -{"hook":{"id":"6","sourceReference":{"location":{"line":28},"uri":"samples/hooks/hooks.feature.ts"},"tagExpression":"@with-attachment"}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"33","pickleId":"20","testSteps":[{"hookId":"0","id":"29"},{"hookId":"1","id":"30"},{"id":"31","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"32"}]}} -{"testCase":{"id":"38","pickleId":"22","testSteps":[{"hookId":"0","id":"34"},{"hookId":"1","id":"35"},{"id":"36","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"37"}]}} -{"testCase":{"id":"43","pickleId":"24","testSteps":[{"hookId":"0","id":"39"},{"hookId":"1","id":"40"},{"id":"41","pickleStepId":"23","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"4","id":"42"}]}} -{"testCase":{"id":"49","pickleId":"26","testSteps":[{"hookId":"0","id":"44"},{"hookId":"1","id":"45"},{"id":"46","pickleStepId":"25","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"5","id":"47"},{"hookId":"4","id":"48"}]}} -{"testCase":{"id":"55","pickleId":"28","testSteps":[{"hookId":"0","id":"50"},{"hookId":"1","id":"51"},{"id":"52","pickleStepId":"27","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"hookId":"6","id":"53"},{"hookId":"4","id":"54"}]}} -{"testCaseStarted":{"attempt":0,"id":"56","testCaseId":"33","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"29","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"30","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"31","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"31","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"56","testStepId":"32","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"56","testStepId":"32","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:5","status":"FAILED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"56","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"57","testCaseId":"38","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"34","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"34","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"35","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"35","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"36","timestamp":{"nanos":16000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"36","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/hooks/hooks.feature:9","status":"FAILED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"57","testStepId":"37","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"57","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:8","status":"FAILED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"57","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"58","testCaseId":"43","timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"58","testStepId":"39","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"58","testStepId":"39","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"58","testStepId":"40","timestamp":{"nanos":24000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"58","testStepId":"40","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"58","testStepId":"41","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"58","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/hooks/hooks.feature:12","status":"FAILED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"58","testStepId":"42","timestamp":{"nanos":28000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"58","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:11","status":"FAILED"},"timestamp":{"nanos":29000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"58","timestamp":{"nanos":30000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"59","testCaseId":"49","timestamp":{"nanos":31000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"59","testStepId":"44","timestamp":{"nanos":32000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"59","testStepId":"44","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"59","testStepId":"45","timestamp":{"nanos":34000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"59","testStepId":"45","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"59","testStepId":"46","timestamp":{"nanos":36000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"59","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":37000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"59","testStepId":"47","timestamp":{"nanos":38000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"59","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in conditional hook","type":"Error"},"message":"Exception in conditional hook\nsamples/hooks/hooks.feature:15","status":"FAILED"},"timestamp":{"nanos":39000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"59","testStepId":"48","timestamp":{"nanos":40000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"59","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:15","status":"FAILED"},"timestamp":{"nanos":41000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"59","timestamp":{"nanos":42000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"60","testCaseId":"55","timestamp":{"nanos":43000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"60","testStepId":"50","timestamp":{"nanos":44000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"60","testStepId":"50","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":45000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"60","testStepId":"51","timestamp":{"nanos":46000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"60","testStepId":"51","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":47000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"60","testStepId":"52","timestamp":{"nanos":48000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"60","testStepId":"52","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":49000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"60","testStepId":"53","timestamp":{"nanos":50000000,"seconds":0}}} -{"attachment":{"body":"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGNsYXNzPSJtbC0zIG1sLW1kLTAiIHZpZXdCb3g9IjAgMCA0MC41OSA0Ni4zMSIgd2lkdGg9IjQwLjU5IiBoZWlnaHQ9IjQ2LjMxIj4KICAgIDxnPgogICAgICAgIDxwYXRoIGZpbGw9IiMyM2Q5NmMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTMwLjI4MyAzLjY0NXEtLjUyOC0uMzE3LTEuMDgtLjU5M2ExNi4xNjQgMTYuMTY0IDAgMDAtMS4xNTQtLjUxOGMtLjEyNC0uMDUyLS4yNDctLjEtLjM3Mi0uMTQ5LS4zNDMtLjEyNy0uNjg5LS4yNjgtMS4wNDItLjM3MWExOS40MjcgMTkuNDI3IDAgMTAtOS43OTIgMzcuNTF2NS41NmMxMS42NzYtMS43NTMgMjIuMDE2LTEwLjk3OSAyMi43ODctMjMuMDkzLjQ1OS03LjI4OS0zLjE5My0xNC43My05LjM0Ny0xOC4zNDZ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZD0iTTE1Ljc4NyA0Ni4zMDd2LTUuOTM1QTIwLjQ3MiAyMC40NzIgMCAxMTI2Ljk1OSAxLjAxNWMuMjc0LjA4LjU1Ny4xODcuODMyLjI5MWwuMjQ4LjA5M2MuMTY1LjA2NC4yOTEuMTEzLjQxNy4xNjcuMzQ4LjEzNy43MzkuMzEzIDEuMjA4LjU0M3EuNTg5LjI5NSAxLjE1My42MzNjNi4zOTMgMy43NTYgMTAuMzU0IDExLjUxOCA5Ljg1NyAxOS4zMTYtLjc2MyAxMi0xMC43MjIgMjIuMTIyLTIzLjY3OSAyNC4wNjd6bTQuOC00NC4yMTRoLS4wMjZhMTguMzY2IDE4LjM2NiAwIDAwLTMuNTI0IDM2LjQwOGwuODUuMTY1djUuMThjMTEuMzkyLTIuMjI0IDIwLjAwOS0xMS4yNzIgMjAuNjg2LTIxLjkyMi40NDgtNy4wMzMtMy4xLTE0LjAxOC04LjgzLTE3LjM4M2wtLjAwOC0uMDA1QTE0LjY5MSAxNC42OTEgMCAwMDI3LjY1NCAzLjVhNS43NCA1Ljc0IDAgMDAtLjM0NC0uMTM4bC0uMjctLjFhOS40OSA5LjQ5IDAgMDAtLjcwOC0uMjQ5IDE4LjQyNSAxOC40MjUgMCAwMC01Ljc0My0uOTJ6Ii8+CiAgICAgICAgPHBhdGggZmlsbD0iIzE3MzY0NyIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTYuNjY2IDEwLjU4YTEuOCAxLjggMCAwMTEuNTgzLjYwOCA0LjE4NCA0LjE4NCAwIDAxLjcyOCAxLjEwN2MuNjQ1IDEuNDIyIDEuMDI3IDMuNDYxLjIzIDQuNjA1YTYuMzM0IDYuMzM0IDAgMDEtMy45ODEtMy4wODcgMy4yMzYgMy4yMzYgMCAwMS0uMzQ3LTEuMzM5IDEuOTU3IDEuOTU3IDAgMDExLjc4Ny0xLjg5NHptLTUuNjgzIDguMDI1YTcuNzQyIDcuNzQyIDAgMDAxLjIxOC43MzcgNS43ODkgNS43ODkgMCAwMDQuODgzLS4xMzggNi4xMTYgNi4xMTYgMCAwMC0zLjM0NS0zLjQ1IDMuNjY0IDMuNjY0IDAgMDAtMS40NDItLjMyMSAxLjg4NCAxLjg4NCAwIDAwLS4zMTkgMCAxLjc2NiAxLjc2NiAwIDAwLS45OTUgMy4xNzJ6bTYuMSAzLjQzM2MtLjc3Ny0uNTE4LTIuMzc5LS4zMDktMy4zMTItLjI5MmE0LjQxNiA0LjQxNiAwIDAwLTEuNjY2LjM1MiAzLjUgMy41IDAgMDAtMS4yMTguNzM4IDEuODE3IDEuODE3IDAgMDAxLjQwOSAzLjE3MSAzLjMgMy4zIDAgMDAxLjQ0Mi0uMzIxYzEuNDM2LS42MiAzLjE0MS0yLjMyIDMuMzQ2LTMuNjQ4em0yLjYxIDJhNi41NTYgNi41NTYgMCAwMC0zLjcyNCAzLjUwNiAzLjA5MSAzLjA5MSAwIDAwLS4zMjEgMS4zMTQgMS45MDcgMS45MDcgMCAwMDMuMyAxLjM0NiA3LjQyMiA3LjQyMiAwIDAwLjctMS4yMThjLjYyMS0xLjMzMy44NjYtMy43Mi4wNDYtNC45NDh6bTIuNTU3LTcuMTY3YTUuOTQxIDUuOTQxIDAgMDAzLjctMy4xNjcgMy4yNDMgMy4yNDMgMCAwMC4zMTktMS4zNDYgMS45MTUgMS45MTUgMCAwMC0xLjc5NC0xLjk1NCAxLjgzMiAxLjgzMiAwIDAwLTEuNi42NDEgNy4zODIgNy4zODIgMCAwMC0uNzA1IDEuMjE4Yy0uNjIgMS40MzQtLjg0MiAzLjQ4LjA4MSA0LjYwM3ptNC4yMDggMTIuMTE1YTMuMjQ0IDMuMjQ0IDAgMDAtLjMyMS0xLjM0NSA1Ljg2OSA1Ljg2OSAwIDAwLTMuNTU0LTMuMjY5IDUuMzg2IDUuMzg2IDAgMDAtLjIyNiA0LjcxMSA0LjE0NyA0LjE0NyAwIDAwLjcgMS4xMjFjMS4xMzMgMS4yMyAzLjUwNS4zMiAzLjQwMi0xLjIxOHptNC4yLTYuMjhhNy40NjYgNy40NjYgMCAwMC0xLjIxNy0uNyA0LjQyNSA0LjQyNSAwIDAwLTEuNjY2LS4zNTIgNi40IDYuNCAwIDAwLTMuMTg4LjU1NSA1Ljk1OSA1Ljk1OSAwIDAwMy4zMTYgMy4zODYgMy42NzIgMy42NzIgMCAwMDEuNDQyLjMyIDEuOCAxLjggMCAwMDEuMzEtMy4yMDl6Ii8+CiAgICA8L2c+Cjwvc3ZnPg==","contentEncoding":"BASE64","mediaType":"image/svg+xml","testCaseStartedId":"60","testStepId":"53"}} -{"testStepFinished":{"testCaseStartedId":"60","testStepId":"53","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":51000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"60","testStepId":"54","timestamp":{"nanos":52000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"60","testStepId":"54","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in hook","type":"Error"},"message":"Exception in hook\nsamples/hooks/hooks.feature:19","status":"FAILED"},"timestamp":{"nanos":53000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"60","timestamp":{"nanos":54000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":55000000,"seconds":0}}} diff --git a/python/src/message_samples/hooks/hooks.feature.ts b/python/src/message_samples/hooks/hooks.feature.ts deleted file mode 100644 index 632190cf..00000000 --- a/python/src/message_samples/hooks/hooks.feature.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { When, Before, After } from '@cucumber/fake-cucumber' -import fs from 'fs' - -Before(function () { - // no-op -}) - -Before({name: 'A named hook'}, function () { - // no-op -}) - -When('a step passes', function () { - // no-op -}) - -When('a step throws an exception', function () { - throw new Error('Exception in step') -}) - -After(function () { - throw new Error('Exception in hook') -}) - -After('@some-tag or @some-other-tag', function () { - throw new Error('Exception in conditional hook') -}) - -After('@with-attachment', async function () { - await this.attach(fs.createReadStream(__dirname + '/cucumber.svg'), 'image/svg+xml') -}) diff --git a/python/src/message_samples/markdown/markdown.feature.md b/python/src/message_samples/markdown/markdown.feature.md deleted file mode 100644 index e0cdec5b..00000000 --- a/python/src/message_samples/markdown/markdown.feature.md +++ /dev/null @@ -1,46 +0,0 @@ -# Feature: Cheese - -This table is not picked up by Gherkin (not indented 2+ spaces) - -| foo | bar | -| --- | --- | -| boz | boo | - - -## Rule: Nom nom nom - -I love cheese, especially fromage macaroni cheese. Rubber cheese ricotta caerphilly blue castello who moved my cheese queso bavarian bergkase melted cheese. - -### Scenario Outline: Ylajali! - -* Given some TypeScript code: - ```typescript - type Cheese = 'reblochon' | 'roquefort' | 'rocamadour' - ``` -* And some classic Gherkin: - ```gherkin - Given there are 24 apples in Mary's basket - ``` -* When we use a data table and attach something and then - | name | age | - | ---- | --: | - | Bill | 3 | - | Jane | 6 | - | Isla | 5 | -* Then this might or might not run - -#### Examples: because we need more tables - -This table is indented 2 spaces, so Gherkin will pick it up - - | what | - | ---- | - | fail | - | pass | - -And oh by the way, this table is also ignored by Gherkin because it doesn't have 2+ space indent: - -| cheese | -| -------- | -| gouda | -| gamalost | diff --git a/python/src/message_samples/markdown/markdown.feature.md.ndjson b/python/src/message_samples/markdown/markdown.feature.md.ndjson deleted file mode 100644 index c4afc018..00000000 --- a/python/src/message_samples/markdown/markdown.feature.md.ndjson +++ /dev/null @@ -1,35 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"# Feature: Cheese\n\nThis table is not picked up by Gherkin (not indented 2+ spaces)\n\n| foo | bar |\n| --- | --- |\n| boz | boo |\n\n\n## Rule: Nom nom nom\n\nI love cheese, especially fromage macaroni cheese. Rubber cheese ricotta caerphilly blue castello who moved my cheese queso bavarian bergkase melted cheese.\n\n### Scenario Outline: Ylajali!\n\n* Given some TypeScript code:\n ```typescript\n type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'\n ```\n* And some classic Gherkin:\n ```gherkin\n Given there are 24 apples in Mary's basket\n ```\n* When we use a data table and attach something and then \n | name | age |\n | ---- | --: |\n | Bill | 3 |\n | Jane | 6 |\n | Isla | 5 |\n* Then this might or might not run\n\n#### Examples: because we need more tables\n\nThis table is indented 2 spaces, so Gherkin will pick it up\n\n | what |\n | ---- |\n | fail |\n | pass |\n\nAnd oh by the way, this table is also ignored by Gherkin because it doesn't have 2+ space indent:\n\n| cheese |\n| -------- |\n| gouda |\n| gamalost |\n","mediaType":"text/x.cucumber.gherkin+markdown","uri":"samples/markdown/markdown.feature.md"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[{"description":"","id":"15","keyword":"Examples","location":{"column":6,"line":32},"name":"because we need more tables","tableBody":[{"cells":[{"location":{"column":5,"line":38},"value":"fail"}],"id":"13","location":{"column":3,"line":38}},{"cells":[{"location":{"column":5,"line":39},"value":"pass"}],"id":"14","location":{"column":3,"line":39}}],"tableHeader":{"cells":[{"location":{"column":5,"line":36},"value":"what"}],"id":"12","location":{"column":3,"line":36}},"tags":[]}],"id":"16","keyword":"Scenario Outline","location":{"column":5,"line":14},"name":"Ylajali!","steps":[{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","delimiter":"```","location":{"column":3,"line":17},"mediaType":"typescript"},"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":3,"line":16},"text":"some TypeScript code:"},{"docString":{"content":"Given there are 24 apples in Mary's basket","delimiter":"```","location":{"column":3,"line":21},"mediaType":"gherkin"},"id":"5","keyword":"And ","keywordType":"Conjunction","location":{"column":3,"line":20},"text":"some classic Gherkin:"},{"dataTable":{"location":{"column":3,"line":25},"rows":[{"cells":[{"location":{"column":5,"line":25},"value":"name"},{"location":{"column":12,"line":25},"value":"age"}],"id":"6","location":{"column":3,"line":25}},{"cells":[{"location":{"column":5,"line":27},"value":"Bill"},{"location":{"column":14,"line":27},"value":"3"}],"id":"7","location":{"column":3,"line":27}},{"cells":[{"location":{"column":5,"line":28},"value":"Jane"},{"location":{"column":14,"line":28},"value":"6"}],"id":"8","location":{"column":3,"line":28}},{"cells":[{"location":{"column":5,"line":29},"value":"Isla"},{"location":{"column":14,"line":29},"value":"5"}],"id":"9","location":{"column":3,"line":29}}]},"id":"10","keyword":"When ","keywordType":"Action","location":{"column":3,"line":24},"text":"we use a data table and attach something and then "},{"id":"11","keyword":"Then ","keywordType":"Outcome","location":{"column":3,"line":30},"text":"this might or might not run"}],"tags":[]}}],"description":"","id":"17","keyword":"Rule","location":{"column":4,"line":10},"name":"Nom nom nom","tags":[]}}],"description":"","keyword":"Feature","language":"en","location":{"column":3,"line":1},"name":"Cheese","tags":[]},"uri":"samples/markdown/markdown.feature.md"}} -{"pickle":{"astNodeIds":["16","13"],"id":"22","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","13"],"id":"18","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","13"],"id":"19","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","13"],"id":"20","text":"we use a data table and attach something and then fail","type":"Action"},{"astNodeIds":["11","13"],"id":"21","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} -{"pickle":{"astNodeIds":["16","14"],"id":"27","language":"en","name":"Ylajali!","steps":[{"argument":{"docString":{"content":"type Cheese = 'reblochon' | 'roquefort' | 'rocamadour'","mediaType":"typescript"}},"astNodeIds":["4","14"],"id":"23","text":"some TypeScript code:","type":"Context"},{"argument":{"docString":{"content":"Given there are 24 apples in Mary's basket","mediaType":"gherkin"}},"astNodeIds":["5","14"],"id":"24","text":"some classic Gherkin:","type":"Context"},{"argument":{"dataTable":{"rows":[{"cells":[{"value":"name"},{"value":"age"}]},{"cells":[{"value":"Bill"},{"value":"3"}]},{"cells":[{"value":"Jane"},{"value":"6"}]},{"cells":[{"value":"Isla"},{"value":"5"}]}]}},"astNodeIds":["10","14"],"id":"25","text":"we use a data table and attach something and then pass","type":"Action"},{"astNodeIds":["11","14"],"id":"26","text":"this might or might not run","type":"Outcome"}],"tags":[],"uri":"samples/markdown/markdown.feature.md"}} -{"stepDefinition":{"id":"0","pattern":{"source":"some TypeScript code:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"some classic Gherkin:","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"we use a data table and attach something and then {word}","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":12},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"this might or might not run","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/markdown/markdown.feature.md.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"32","pickleId":"22","testSteps":[{"id":"28","pickleStepId":"18","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"29","pickleStepId":"19","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"30","pickleStepId":"20","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"fail"},"parameterTypeName":"word"}]}]},{"id":"31","pickleStepId":"21","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"37","pickleId":"27","testSteps":[{"id":"33","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"34","pickleStepId":"24","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"35","pickleStepId":"25","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":50,"value":"pass"},"parameterTypeName":"word"}]}]},{"id":"36","pickleStepId":"26","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"38","testCaseId":"32","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"38","testStepId":"28","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"38","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"38","testStepId":"29","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"38","testStepId":"29","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"38","testStepId":"30","timestamp":{"nanos":6000000,"seconds":0}}} -{"attachment":{"body":"We are logging some plain text (fail)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"38","testStepId":"30"}} -{"testStepFinished":{"testCaseStartedId":"38","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"You asked me to fail","type":"Error"},"message":"You asked me to fail\nsamples/markdown/markdown.feature.md:24\nsamples/markdown/markdown.feature.md:38","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"38","testStepId":"31","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"38","testStepId":"31","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"38","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"39","testCaseId":"37","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"33","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"33","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"34","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"34","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"35","timestamp":{"nanos":16000000,"seconds":0}}} -{"attachment":{"body":"We are logging some plain text (pass)","contentEncoding":"IDENTITY","mediaType":"text/x.cucumber.log+plain","testCaseStartedId":"39","testStepId":"35"}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"35","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"36","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"36","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":21000000,"seconds":0}}} diff --git a/python/src/message_samples/markdown/markdown.feature.md.ts b/python/src/message_samples/markdown/markdown.feature.md.ts deleted file mode 100644 index de8bbdc5..00000000 --- a/python/src/message_samples/markdown/markdown.feature.md.ts +++ /dev/null @@ -1,25 +0,0 @@ -import assert from 'assert' -import { Given, When, Then } from '@cucumber/fake-cucumber' - -Given('some TypeScript code:', function (dataTable: string[][]) { - assert(dataTable) -}) - -Given('some classic Gherkin:', function (gherkin: string) { - assert(gherkin) -}) - -When( - 'we use a data table and attach something and then {word}', - function (word: string, dataTable: string[][]) { - assert(dataTable) - this.log(`We are logging some plain text (${word})`) - if (word === 'fail') { - throw new Error('You asked me to fail') - } - } -) - -Then('this might or might not run', function () { - // no-op -}) diff --git a/python/src/message_samples/parameter-types/parameter-types.feature b/python/src/message_samples/parameter-types/parameter-types.feature deleted file mode 100644 index 5b1422f4..00000000 --- a/python/src/message_samples/parameter-types/parameter-types.feature +++ /dev/null @@ -1,9 +0,0 @@ -Feature: Parameter Types - Cucumber lets you define your own parameter types, which can be used - in Cucumber Expressions. This lets you define a precise domain-specific - vocabulary which can be used to generate a glossary with examples taken - from your scenarios. They also let you transform strings and tables into - rich types. - - Scenario: flights - Given LHR-CDG has been delayed 45 minutes diff --git a/python/src/message_samples/parameter-types/parameter-types.feature.ndjson b/python/src/message_samples/parameter-types/parameter-types.feature.ndjson deleted file mode 100644 index 61a88074..00000000 --- a/python/src/message_samples/parameter-types/parameter-types.feature.ndjson +++ /dev/null @@ -1,13 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Parameter Types\n Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions. This lets you define a precise domain-specific\n vocabulary which can be used to generate a glossary with examples taken\n from your scenarios. They also let you transform strings and tables into\n rich types.\n\n Scenario: flights\n Given LHR-CDG has been delayed 45 minutes\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/parameter-types/parameter-types.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":8},"name":"flights","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":9},"text":"LHR-CDG has been delayed 45 minutes"}],"tags":[]}}],"description":" Cucumber lets you define your own parameter types, which can be used\n in Cucumber Expressions. This lets you define a precise domain-specific\n vocabulary which can be used to generate a glossary with examples taken\n from your scenarios. They also let you transform strings and tables into\n rich types.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/parameter-types/parameter-types.feature"}} -{"pickle":{"astNodeIds":["3"],"id":"5","language":"en","name":"flights","steps":[{"astNodeIds":["2"],"id":"4","text":"LHR-CDG has been delayed 45 minutes","type":"Context"}],"tags":[],"uri":"samples/parameter-types/parameter-types.feature"}} -{"parameterType":{"id":"0","name":"flight","preferForRegularExpressionMatch":false,"regularExpressions":["([A-Z]{3})-([A-Z]{3})"],"sourceReference":{"location":{"line":8},"uri":"samples/parameter-types/parameter-types.feature.ts"},"useForSnippets":true}} -{"stepDefinition":{"id":"1","pattern":{"source":"{flight} has been delayed {int} minutes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/parameter-types/parameter-types.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"7","pickleId":"5","testSteps":[{"id":"6","pickleStepId":"4","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[{"children":[],"start":0,"value":"LHR"},{"children":[],"start":4,"value":"CDG"}],"start":0,"value":"LHR-CDG"},"parameterTypeName":"flight"},{"group":{"children":[],"start":25,"value":"45"},"parameterTypeName":"int"}]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"8","testCaseId":"7","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"8","testStepId":"6","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"8","testStepId":"6","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"8","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/parameter-types/parameter-types.feature.ts b/python/src/message_samples/parameter-types/parameter-types.feature.ts deleted file mode 100644 index ece172c3..00000000 --- a/python/src/message_samples/parameter-types/parameter-types.feature.ts +++ /dev/null @@ -1,20 +0,0 @@ -import assert from 'assert' -import { Given, ParameterType } from '@cucumber/fake-cucumber' - -class Flight { - constructor(public readonly from: string, public readonly to: string) {} -} - -ParameterType({ - name: 'flight', - regexp: /([A-Z]{3})-([A-Z]{3})/, - transformer(from: string, to: string) { - return new Flight(from, to) - }, -}) - -Given('{flight} has been delayed {int} minutes', function (flight: Flight, delay: number) { - assert.strictEqual(flight.from, 'LHR') - assert.strictEqual(flight.to, 'CDG') - assert.strictEqual(delay, 45) -}) diff --git a/python/src/message_samples/pending/pending.feature b/python/src/message_samples/pending/pending.feature deleted file mode 100644 index cc5ea421..00000000 --- a/python/src/message_samples/pending/pending.feature +++ /dev/null @@ -1,19 +0,0 @@ -Feature: Pending steps - - During development, step definitions can signal at runtime that they are - not yet implemented (or "pending") by returning or throwing a particular - value. - - This causes subsequent steps in the scenario to be skipped, and the overall - result to be treated as a failure. - - Scenario: Unimplemented step signals pending status - Given a step that isnt implemented yet - - Scenario: Steps before unimplemented steps are executed - Given an implemented step - When a step that isnt implemented yet - - Scenario: Steps after unimplemented steps are skipped - Given a step that isnt implemented yet - Then a step that we expect to be skipped diff --git a/python/src/message_samples/pending/pending.feature.ndjson b/python/src/message_samples/pending/pending.feature.ndjson deleted file mode 100644 index e95ebb87..00000000 --- a/python/src/message_samples/pending/pending.feature.ndjson +++ /dev/null @@ -1,30 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Pending steps\n\n During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.\n\n Scenario: Unimplemented step signals pending status\n Given a step that isnt implemented yet\n\n Scenario: Steps before unimplemented steps are executed\n Given an implemented step\n When a step that isnt implemented yet\n\n Scenario: Steps after unimplemented steps are skipped\n Given a step that isnt implemented yet\n Then a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/pending/pending.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"4","keyword":"Scenario","location":{"column":3,"line":10},"name":"Unimplemented step signals pending status","steps":[{"id":"3","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":13},"name":"Steps before unimplemented steps are executed","steps":[{"id":"5","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":14},"text":"an implemented step"},{"id":"6","keyword":"When ","keywordType":"Action","location":{"column":5,"line":15},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"10","keyword":"Scenario","location":{"column":3,"line":17},"name":"Steps after unimplemented steps are skipped","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"a step that isnt implemented yet"},{"id":"9","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":19},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" During development, step definitions can signal at runtime that they are\n not yet implemented (or \"pending\") by returning or throwing a particular\n value.\n\n This causes subsequent steps in the scenario to be skipped, and the overall\n result to be treated as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Pending steps","tags":[]},"uri":"samples/pending/pending.feature"}} -{"pickle":{"astNodeIds":["4"],"id":"12","language":"en","name":"Unimplemented step signals pending status","steps":[{"astNodeIds":["3"],"id":"11","text":"a step that isnt implemented yet","type":"Context"}],"tags":[],"uri":"samples/pending/pending.feature"}} -{"pickle":{"astNodeIds":["7"],"id":"15","language":"en","name":"Steps before unimplemented steps are executed","steps":[{"astNodeIds":["5"],"id":"13","text":"an implemented step","type":"Context"},{"astNodeIds":["6"],"id":"14","text":"a step that isnt implemented yet","type":"Action"}],"tags":[],"uri":"samples/pending/pending.feature"}} -{"pickle":{"astNodeIds":["10"],"id":"18","language":"en","name":"Steps after unimplemented steps are skipped","steps":[{"astNodeIds":["8"],"id":"16","text":"a step that isnt implemented yet","type":"Context"},{"astNodeIds":["9"],"id":"17","text":"a step that we expect to be skipped","type":"Outcome"}],"tags":[],"uri":"samples/pending/pending.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/pending/pending.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step that isnt implemented yet","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/pending/pending.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/pending/pending.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"20","pickleId":"12","testSteps":[{"id":"19","pickleStepId":"11","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"23","pickleId":"15","testSteps":[{"id":"21","pickleStepId":"13","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"22","pickleStepId":"14","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"26","pickleId":"18","testSteps":[{"id":"24","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"25","pickleStepId":"17","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"20","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"27","testStepId":"19","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"27","testStepId":"19","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PENDING"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"23","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"21","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"22","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"22","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PENDING"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"29","testCaseId":"26","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"24","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PENDING"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"29","testStepId":"25","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"29","testStepId":"25","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"29","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/python/src/message_samples/pending/pending.feature.ts b/python/src/message_samples/pending/pending.feature.ts deleted file mode 100644 index 7f66ae22..00000000 --- a/python/src/message_samples/pending/pending.feature.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Given } from '@cucumber/fake-cucumber' - -Given('an implemented step', function () { - // no-op -}) - -Given('a step that isnt implemented yet', function () { - return 'pending' -}) - -Given('a step that we expect to be skipped', function () { - // no-op -}) diff --git a/python/src/message_samples/retry/retry.arguments.txt b/python/src/message_samples/retry/retry.arguments.txt deleted file mode 100644 index cf83a555..00000000 --- a/python/src/message_samples/retry/retry.arguments.txt +++ /dev/null @@ -1 +0,0 @@ ---retry 2 diff --git a/python/src/message_samples/retry/retry.feature b/python/src/message_samples/retry/retry.feature deleted file mode 100644 index 79f9188d..00000000 --- a/python/src/message_samples/retry/retry.feature +++ /dev/null @@ -1,22 +0,0 @@ -Feature: Retry - - Some Cucumber implementations support a Retry mechanism, where test cases that fail - can be retried up to a limited number of attempts in the same test run. - - Non-passing statuses other than FAILED don't trigger a retry - they are not going to pass - however many times we attempt them. - - Scenario: test case passes on the first attempt - Given a step that always passes - - Scenario: test case passes on the second attempt - Given a step that passes the second time - - Scenario: test case passes on the final attempt - Given a step that passes the third time - - Scenario: test case fails on every attempt - Given a step that always fails - - Scenario: don't retry on UNDEFINED - Given a non-existent step diff --git a/python/src/message_samples/retry/retry.feature.ndjson b/python/src/message_samples/retry/retry.feature.ndjson deleted file mode 100644 index 3f01aaf9..00000000 --- a/python/src/message_samples/retry/retry.feature.ndjson +++ /dev/null @@ -1,59 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Retry\n\n Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED don't trigger a retry - they are not going to pass\n however many times we attempt them.\n\n Scenario: test case passes on the first attempt\n Given a step that always passes\n\n Scenario: test case passes on the second attempt\n Given a step that passes the second time\n\n Scenario: test case passes on the final attempt\n Given a step that passes the third time\n\n Scenario: test case fails on every attempt\n Given a step that always fails\n\n Scenario: don't retry on UNDEFINED\n Given a non-existent step\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/retry/retry.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"5","keyword":"Scenario","location":{"column":3,"line":9},"name":"test case passes on the first attempt","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":10},"text":"a step that always passes"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"7","keyword":"Scenario","location":{"column":3,"line":12},"name":"test case passes on the second attempt","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":13},"text":"a step that passes the second time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":15},"name":"test case passes on the final attempt","steps":[{"id":"8","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":16},"text":"a step that passes the third time"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"11","keyword":"Scenario","location":{"column":3,"line":18},"name":"test case fails on every attempt","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":19},"text":"a step that always fails"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"13","keyword":"Scenario","location":{"column":3,"line":21},"name":"don't retry on UNDEFINED","steps":[{"id":"12","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":22},"text":"a non-existent step"}],"tags":[]}}],"description":" Some Cucumber implementations support a Retry mechanism, where test cases that fail\n can be retried up to a limited number of attempts in the same test run.\n\n Non-passing statuses other than FAILED don't trigger a retry - they are not going to pass\n however many times we attempt them.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Retry","tags":[]},"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["5"],"id":"15","language":"en","name":"test case passes on the first attempt","steps":[{"astNodeIds":["4"],"id":"14","text":"a step that always passes","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["7"],"id":"17","language":"en","name":"test case passes on the second attempt","steps":[{"astNodeIds":["6"],"id":"16","text":"a step that passes the second time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"19","language":"en","name":"test case passes on the final attempt","steps":[{"astNodeIds":["8"],"id":"18","text":"a step that passes the third time","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["11"],"id":"21","language":"en","name":"test case fails on every attempt","steps":[{"astNodeIds":["10"],"id":"20","text":"a step that always fails","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"pickle":{"astNodeIds":["13"],"id":"23","language":"en","name":"don't retry on UNDEFINED","steps":[{"astNodeIds":["12"],"id":"22","text":"a non-existent step","type":"Context"}],"tags":[],"uri":"samples/retry/retry.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"a step that always passes","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/retry/retry.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step that passes the second time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":8},"uri":"samples/retry/retry.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step that passes the third time","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":16},"uri":"samples/retry/retry.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"a step that always fails","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":23},"uri":"samples/retry/retry.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"25","pickleId":"15","testSteps":[{"id":"24","pickleStepId":"14","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"27","pickleId":"17","testSteps":[{"id":"26","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"29","pickleId":"19","testSteps":[{"id":"28","pickleStepId":"18","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"31","pickleId":"21","testSteps":[{"id":"30","pickleStepId":"20","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"33","pickleId":"23","testSteps":[{"id":"32","pickleStepId":"22","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCaseStarted":{"attempt":0,"id":"34","testCaseId":"25","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"34","testStepId":"24","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"34","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"34","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"35","testCaseId":"27","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"35","testStepId":"26","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"35","testStepId":"26","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:13","status":"FAILED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"35","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":1,"id":"36","testCaseId":"27","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"36","testStepId":"26","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"36","testStepId":"26","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"36","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"37","testCaseId":"29","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"37","testStepId":"28","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"37","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:16","status":"FAILED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"37","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":1,"id":"38","testCaseId":"29","timestamp":{"nanos":17000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"38","testStepId":"28","timestamp":{"nanos":18000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"38","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:16","status":"FAILED"},"timestamp":{"nanos":19000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"38","timestamp":{"nanos":20000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":2,"id":"39","testCaseId":"29","timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"39","testStepId":"28","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"39","testStepId":"28","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"39","timestamp":{"nanos":24000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"40","testCaseId":"31","timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"40","testStepId":"30","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"40","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:19","status":"FAILED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"40","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":1,"id":"41","testCaseId":"31","timestamp":{"nanos":29000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"41","testStepId":"30","timestamp":{"nanos":30000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"41","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:19","status":"FAILED"},"timestamp":{"nanos":31000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"41","timestamp":{"nanos":32000000,"seconds":0},"willBeRetried":true}} -{"testCaseStarted":{"attempt":2,"id":"42","testCaseId":"31","timestamp":{"nanos":33000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"42","testStepId":"30","timestamp":{"nanos":34000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"42","testStepId":"30","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"Exception in step","type":"Error"},"message":"Exception in step\nsamples/retry/retry.feature:19","status":"FAILED"},"timestamp":{"nanos":35000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"42","timestamp":{"nanos":36000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"43","testCaseId":"33","timestamp":{"nanos":37000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"43","testStepId":"32","timestamp":{"nanos":38000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"43","testStepId":"32","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":39000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"43","timestamp":{"nanos":40000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":41000000,"seconds":0}}} diff --git a/python/src/message_samples/retry/retry.feature.ts b/python/src/message_samples/retry/retry.feature.ts deleted file mode 100644 index 077e37cd..00000000 --- a/python/src/message_samples/retry/retry.feature.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Given } from '@cucumber/fake-cucumber' - -Given('a step that always passes', function () { - // no-op -}) - -let secondTimePass = 0 -Given('a step that passes the second time', function () { - secondTimePass++ - if (secondTimePass < 2) { - throw new Error('Exception in step') - } -}) - -let thirdTimePass = 0 -Given('a step that passes the third time', function () { - thirdTimePass++ - if (thirdTimePass < 3) { - throw new Error('Exception in step') - } -}) - -Given('a step that always fails', function () { - throw new Error('Exception in step') -}) diff --git a/python/src/message_samples/rules/rules.feature b/python/src/message_samples/rules/rules.feature deleted file mode 100644 index c45c9ed3..00000000 --- a/python/src/message_samples/rules/rules.feature +++ /dev/null @@ -1,27 +0,0 @@ -Feature: Rules - You can place scenarios inside rules. This makes is possible to structure - Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/). - You can also use the Examples synonym for Scenario to make them even more similar. - - Rule: a sale cannot happen if change cannot be returned - # sad path - Example: no change - Given there are 5 0.20 coins inside - When the customer tries to buy a 0.85 chocolate with a 1 coin - Then the sale should not happen - - # happy path - Example: exact change - Given there are 5 0.20 coins inside - And there are 3 chocolates inside - When the customer tries to buy a 0.80 chocolate with a 1 coin - Then the customer's change should be 1 0.20 coin - - @some-tag - Rule: a sale cannot happen if we're out of stock - # sad path - Example: no chocolates left - Given there are no chocolates inside - But there are 10 0.5 coins inside - When the customer tries to buy a 0.85 chocolate with a 1 coin - Then the sale should not happen diff --git a/python/src/message_samples/rules/rules.feature.ndjson b/python/src/message_samples/rules/rules.feature.ndjson deleted file mode 100644 index 574b52b5..00000000 --- a/python/src/message_samples/rules/rules.feature.ndjson +++ /dev/null @@ -1,45 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Rules\n You can place scenarios inside rules. This makes is possible to structure\n Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n You can also use the Examples synonym for Scenario to make them even more similar.\n\n Rule: a sale cannot happen if change cannot be returned\n # sad path\n Example: no change\n Given there are 5 0.20 coins inside\n When the customer tries to buy a 0.85 chocolate with a 1 coin\n Then the sale should not happen\n\n # happy path\n Example: exact change\n Given there are 5 0.20 coins inside\n And there are 3 chocolates inside\n When the customer tries to buy a 0.80 chocolate with a 1 coin\n Then the customer's change should be 1 0.20 coin\n\n @some-tag\n Rule: a sale cannot happen if we're out of stock\n # sad path\n Example: no chocolates left\n Given there are no chocolates inside\n But there are 10 0.5 coins inside\n When the customer tries to buy a 0.85 chocolate with a 1 coin\n Then the sale should not happen\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/rules/rules.feature"}} -{"gherkinDocument":{"comments":[{"location":{"column":1,"line":7},"text":" # sad path"},{"location":{"column":1,"line":13},"text":" # happy path"},{"location":{"column":1,"line":22},"text":" # sad path"}],"feature":{"children":[{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"9","keyword":"Example","location":{"column":5,"line":8},"name":"no change","steps":[{"id":"6","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":9},"text":"there are 5 0.20 coins inside"},{"id":"7","keyword":"When ","keywordType":"Action","location":{"column":7,"line":10},"text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"id":"8","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":11},"text":"the sale should not happen"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"14","keyword":"Example","location":{"column":5,"line":14},"name":"exact change","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":15},"text":"there are 5 0.20 coins inside"},{"id":"11","keyword":"And ","keywordType":"Conjunction","location":{"column":7,"line":16},"text":"there are 3 chocolates inside"},{"id":"12","keyword":"When ","keywordType":"Action","location":{"column":7,"line":17},"text":"the customer tries to buy a 0.80 chocolate with a 1 coin"},{"id":"13","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":18},"text":"the customer's change should be 1 0.20 coin"}],"tags":[]}}],"description":"","id":"15","keyword":"Rule","location":{"column":3,"line":6},"name":"a sale cannot happen if change cannot be returned","tags":[]}},{"rule":{"children":[{"scenario":{"description":"","examples":[],"id":"20","keyword":"Example","location":{"column":5,"line":23},"name":"no chocolates left","steps":[{"id":"16","keyword":"Given ","keywordType":"Context","location":{"column":7,"line":24},"text":"there are no chocolates inside"},{"id":"17","keyword":"But ","keywordType":"Conjunction","location":{"column":7,"line":25},"text":"there are 10 0.5 coins inside"},{"id":"18","keyword":"When ","keywordType":"Action","location":{"column":7,"line":26},"text":"the customer tries to buy a 0.85 chocolate with a 1 coin"},{"id":"19","keyword":"Then ","keywordType":"Outcome","location":{"column":7,"line":27},"text":"the sale should not happen"}],"tags":[]}}],"description":"","id":"22","keyword":"Rule","location":{"column":3,"line":21},"name":"a sale cannot happen if we're out of stock","tags":[{"id":"21","location":{"column":3,"line":20},"name":"@some-tag"}]}}],"description":" You can place scenarios inside rules. This makes is possible to structure\n Gherkin documents in the same way as [example maps](https://cucumber.io/blog/bdd/example-mapping-introduction/).\n You can also use the Examples synonym for Scenario to make them even more similar.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Rules","tags":[]},"uri":"samples/rules/rules.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"26","language":"en","name":"no change","steps":[{"astNodeIds":["6"],"id":"23","text":"there are 5 0.20 coins inside","type":"Context"},{"astNodeIds":["7"],"id":"24","text":"the customer tries to buy a 0.85 chocolate with a 1 coin","type":"Action"},{"astNodeIds":["8"],"id":"25","text":"the sale should not happen","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} -{"pickle":{"astNodeIds":["14"],"id":"31","language":"en","name":"exact change","steps":[{"astNodeIds":["10"],"id":"27","text":"there are 5 0.20 coins inside","type":"Context"},{"astNodeIds":["11"],"id":"28","text":"there are 3 chocolates inside","type":"Context"},{"astNodeIds":["12"],"id":"29","text":"the customer tries to buy a 0.80 chocolate with a 1 coin","type":"Action"},{"astNodeIds":["13"],"id":"30","text":"the customer's change should be 1 0.20 coin","type":"Outcome"}],"tags":[],"uri":"samples/rules/rules.feature"}} -{"pickle":{"astNodeIds":["20"],"id":"36","language":"en","name":"no chocolates left","steps":[{"astNodeIds":["16"],"id":"32","text":"there are no chocolates inside","type":"Context"},{"astNodeIds":["17"],"id":"33","text":"there are 10 0.5 coins inside","type":"Context"},{"astNodeIds":["18"],"id":"34","text":"the customer tries to buy a 0.85 chocolate with a 1 coin","type":"Action"},{"astNodeIds":["19"],"id":"35","text":"the sale should not happen","type":"Outcome"}],"tags":[{"astNodeId":"21","name":"@some-tag"}],"uri":"samples/rules/rules.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"there are {int} {float} coins inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":4},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"there are no chocolates inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":10},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"there are {int} chocolates inside","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":14},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"the customer tries to buy a {float} chocolate with a {float} coin","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":19},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"4","pattern":{"source":"the sale should not happen","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":25},"uri":"samples/rules/rules.feature.ts"}}} -{"stepDefinition":{"id":"5","pattern":{"source":"the customer's change should be {int} {float} coin(s)","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":29},"uri":"samples/rules/rules.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"40","pickleId":"26","testSteps":[{"id":"37","pickleStepId":"23","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"5"},"parameterTypeName":"int"},{"group":{"children":[],"start":12,"value":"0.20"},"parameterTypeName":"float"}]}]},{"id":"38","pickleStepId":"24","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.85"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"39","pickleStepId":"25","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"45","pickleId":"31","testSteps":[{"id":"41","pickleStepId":"27","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"5"},"parameterTypeName":"int"},{"group":{"children":[],"start":12,"value":"0.20"},"parameterTypeName":"float"}]}]},{"id":"42","pickleStepId":"28","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"3"},"parameterTypeName":"int"}]}]},{"id":"43","pickleStepId":"29","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.80"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"44","pickleStepId":"30","stepDefinitionIds":["5"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":32,"value":"1"},"parameterTypeName":"int"},{"group":{"children":[],"start":34,"value":"0.20"},"parameterTypeName":"float"}]}]}]}} -{"testCase":{"id":"50","pickleId":"36","testSteps":[{"id":"46","pickleStepId":"32","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"47","pickleStepId":"33","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":10,"value":"10"},"parameterTypeName":"int"},{"group":{"children":[],"start":13,"value":"0.5"},"parameterTypeName":"float"}]}]},{"id":"48","pickleStepId":"34","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[{"group":{"children":[],"start":28,"value":"0.85"},"parameterTypeName":"float"},{"group":{"children":[],"start":50,"value":"1"},"parameterTypeName":"float"}]}]},{"id":"49","pickleStepId":"35","stepDefinitionIds":["4"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"51","testCaseId":"40","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"51","testStepId":"37","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"51","testStepId":"37","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"51","testStepId":"38","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"51","testStepId":"38","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"51","testStepId":"39","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"51","testStepId":"39","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"51","timestamp":{"nanos":8000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"52","testCaseId":"45","timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"52","testStepId":"41","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"52","testStepId":"41","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"52","testStepId":"42","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"52","testStepId":"42","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"52","testStepId":"43","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"52","testStepId":"43","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"52","testStepId":"44","timestamp":{"nanos":16000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"52","testStepId":"44","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"52","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"53","testCaseId":"50","timestamp":{"nanos":19000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"53","testStepId":"46","timestamp":{"nanos":20000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"53","testStepId":"46","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":21000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"53","testStepId":"47","timestamp":{"nanos":22000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"53","testStepId":"47","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":23000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"53","testStepId":"48","timestamp":{"nanos":24000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"53","testStepId":"48","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":25000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"53","testStepId":"49","timestamp":{"nanos":26000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"53","testStepId":"49","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":27000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"53","timestamp":{"nanos":28000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"timestamp":{"nanos":29000000,"seconds":0}}} diff --git a/python/src/message_samples/rules/rules.feature.ts b/python/src/message_samples/rules/rules.feature.ts deleted file mode 100644 index 0688d16a..00000000 --- a/python/src/message_samples/rules/rules.feature.ts +++ /dev/null @@ -1,33 +0,0 @@ -import assert from 'assert' -import { Given, When, Then } from '@cucumber/fake-cucumber' - -Given('there are {int} {float} coins inside', function (count, denomination) { - // TODO: implement this - assert(count) - assert(denomination) -}) - -Given('there are no chocolates inside', function () { - // TODO: implement this -}) - -Given('there are {int} chocolates inside', function (chocolateCount) { - // TODO: implement this - assert(chocolateCount) -}) - -When('the customer tries to buy a {float} chocolate with a {float} coin', function (price, paid) { - // TODO: implement this - assert(price) - assert(paid) -}) - -Then('the sale should not happen', function () { - // TODO: implement this -}) - -Then("the customer's change should be {int} {float} coin(s)", function (count, denomination) { - // TODO: implement this - assert(count) - assert(denomination) -}) diff --git a/python/src/message_samples/skipped/skipped.feature b/python/src/message_samples/skipped/skipped.feature deleted file mode 100644 index c9982b48..00000000 --- a/python/src/message_samples/skipped/skipped.feature +++ /dev/null @@ -1,19 +0,0 @@ -Feature: Skipping scenarios - - Hooks and step definitions are able to signal at runtime that the scenario should - be skipped by returning or throwing a particular value. - - This can be useful when e.g. the current environment doesn't have the right conditions - for running the scenario. - - @skip - Scenario: Skipping from a Before hook - Given a step that we expect to be skipped - - Scenario: Skipping from a step doesn't affect the previous steps - Given an implemented step - When a step that skips - - Scenario: Skipping from a step causes the rest of the scenario to be skipped - Given a step that skips - When a step that we expect to be skipped diff --git a/python/src/message_samples/skipped/skipped.feature.ndjson b/python/src/message_samples/skipped/skipped.feature.ndjson deleted file mode 100644 index 6ed59723..00000000 --- a/python/src/message_samples/skipped/skipped.feature.ndjson +++ /dev/null @@ -1,33 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Skipping scenarios\n\n Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by returning or throwing a particular value.\n\n This can be useful when e.g. the current environment doesn't have the right conditions\n for running the scenario.\n\n @skip\n Scenario: Skipping from a Before hook\n Given a step that we expect to be skipped\n\n Scenario: Skipping from a step doesn't affect the previous steps\n Given an implemented step\n When a step that skips\n\n Scenario: Skipping from a step causes the rest of the scenario to be skipped\n Given a step that skips\n When a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/skipped/skipped.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":10},"name":"Skipping from a Before hook","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":11},"text":"a step that we expect to be skipped"}],"tags":[{"id":"5","location":{"column":3,"line":9},"name":"@skip"}]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":13},"name":"Skipping from a step doesn't affect the previous steps","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":14},"text":"an implemented step"},{"id":"8","keyword":"When ","keywordType":"Action","location":{"column":5,"line":15},"text":"a step that skips"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"12","keyword":"Scenario","location":{"column":3,"line":17},"name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"id":"10","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":18},"text":"a step that skips"},{"id":"11","keyword":"When ","keywordType":"Action","location":{"column":5,"line":19},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" Hooks and step definitions are able to signal at runtime that the scenario should\n be skipped by returning or throwing a particular value.\n\n This can be useful when e.g. the current environment doesn't have the right conditions\n for running the scenario.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Skipping scenarios","tags":[]},"uri":"samples/skipped/skipped.feature"}} -{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Skipping from a Before hook","steps":[{"astNodeIds":["4"],"id":"13","text":"a step that we expect to be skipped","type":"Context"}],"tags":[{"astNodeId":"5","name":"@skip"}],"uri":"samples/skipped/skipped.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Skipping from a step doesn't affect the previous steps","steps":[{"astNodeIds":["7"],"id":"15","text":"an implemented step","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"a step that skips","type":"Action"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} -{"pickle":{"astNodeIds":["12"],"id":"20","language":"en","name":"Skipping from a step causes the rest of the scenario to be skipped","steps":[{"astNodeIds":["10"],"id":"18","text":"a step that skips","type":"Context"},{"astNodeIds":["11"],"id":"19","text":"a step that we expect to be skipped","type":"Action"}],"tags":[],"uri":"samples/skipped/skipped.feature"}} -{"stepDefinition":{"id":"1","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/skipped/skipped.feature.ts"}}} -{"stepDefinition":{"id":"2","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":11},"uri":"samples/skipped/skipped.feature.ts"}}} -{"stepDefinition":{"id":"3","pattern":{"source":"a step that skips","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":15},"uri":"samples/skipped/skipped.feature.ts"}}} -{"hook":{"id":"0","sourceReference":{"location":{"line":3},"uri":"samples/skipped/skipped.feature.ts"},"tagExpression":"@skip"}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"23","pickleId":"14","testSteps":[{"hookId":"0","id":"21"},{"id":"22","pickleStepId":"13","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"26","pickleId":"17","testSteps":[{"id":"24","pickleStepId":"15","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"25","pickleStepId":"16","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCase":{"id":"29","pickleId":"20","testSteps":[{"id":"27","pickleStepId":"18","stepDefinitionIds":["3"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"28","pickleStepId":"19","stepDefinitionIds":["2"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"30","testCaseId":"23","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"21","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"21","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"30","testStepId":"22","timestamp":{"nanos":4000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"30","testStepId":"22","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":5000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"30","timestamp":{"nanos":6000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"31","testCaseId":"26","timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"24","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"24","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"31","testStepId":"25","timestamp":{"nanos":10000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"31","testStepId":"25","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":11000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"31","timestamp":{"nanos":12000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"32","testCaseId":"29","timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"32","testStepId":"27","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"32","testStepId":"27","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"32","testStepId":"28","timestamp":{"nanos":16000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"32","testStepId":"28","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":17000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"32","timestamp":{"nanos":18000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":true,"timestamp":{"nanos":19000000,"seconds":0}}} diff --git a/python/src/message_samples/skipped/skipped.feature.ts b/python/src/message_samples/skipped/skipped.feature.ts deleted file mode 100644 index 9d0bd595..00000000 --- a/python/src/message_samples/skipped/skipped.feature.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Before, Given } from '@cucumber/fake-cucumber' - -Before('@skip', function () { - return 'skipped' -}) - -Given('an implemented step', function () { - // no-op -}) - -Given('a step that we expect to be skipped', function () { - // no-op -}) - -Given('a step that skips', function () { - return 'skipped' -}) diff --git a/python/src/message_samples/stack-traces/stack-traces.feature b/python/src/message_samples/stack-traces/stack-traces.feature deleted file mode 100644 index 5c981df5..00000000 --- a/python/src/message_samples/stack-traces/stack-traces.feature +++ /dev/null @@ -1,11 +0,0 @@ -Feature: Stack traces - Nothing beats stack traces when it comes to diagnosing the source of a bug. - Cucumber provides helpful stack traces that: - - - Include a stack frame from the Gherkin document - - Remove uninteresting frames by default - - The first line of the stack trace must contain the feature file. - - Scenario: A failing step - When a step throws an exception diff --git a/python/src/message_samples/stack-traces/stack-traces.feature.ndjson b/python/src/message_samples/stack-traces/stack-traces.feature.ndjson deleted file mode 100644 index 3d165072..00000000 --- a/python/src/message_samples/stack-traces/stack-traces.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Stack traces\n Nothing beats stack traces when it comes to diagnosing the source of a bug.\n Cucumber provides helpful stack traces that:\n \n - Include a stack frame from the Gherkin document\n - Remove uninteresting frames by default\n\n The first line of the stack trace must contain the feature file.\n\n Scenario: A failing step\n When a step throws an exception\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/stack-traces/stack-traces.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"2","keyword":"Scenario","location":{"column":3,"line":10},"name":"A failing step","steps":[{"id":"1","keyword":"When ","keywordType":"Action","location":{"column":5,"line":11},"text":"a step throws an exception"}],"tags":[]}}],"description":" Nothing beats stack traces when it comes to diagnosing the source of a bug.\n Cucumber provides helpful stack traces that:\n \n - Include a stack frame from the Gherkin document\n - Remove uninteresting frames by default\n\n The first line of the stack trace must contain the feature file.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Stack traces","tags":[]},"uri":"samples/stack-traces/stack-traces.feature"}} -{"pickle":{"astNodeIds":["2"],"id":"4","language":"en","name":"A failing step","steps":[{"astNodeIds":["1"],"id":"3","text":"a step throws an exception","type":"Action"}],"tags":[],"uri":"samples/stack-traces/stack-traces.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"a step throws an exception","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/stack-traces/stack-traces.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"6","pickleId":"4","testSteps":[{"id":"5","pickleStepId":"3","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"7","testCaseId":"6","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"7","testStepId":"5","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"7","testStepId":"5","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"exception":{"message":"BOOM","type":"Error"},"message":"BOOM\nsamples/stack-traces/stack-traces.feature:11","status":"FAILED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"7","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/stack-traces/stack-traces.feature.ts b/python/src/message_samples/stack-traces/stack-traces.feature.ts deleted file mode 100644 index 2ffd339b..00000000 --- a/python/src/message_samples/stack-traces/stack-traces.feature.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { When } from '@cucumber/fake-cucumber' - -When('a step throws an exception', function () { - throw new Error('BOOM') -}) diff --git a/python/src/message_samples/undefined/undefined.feature b/python/src/message_samples/undefined/undefined.feature deleted file mode 100644 index 2abcf5c0..00000000 --- a/python/src/message_samples/undefined/undefined.feature +++ /dev/null @@ -1,17 +0,0 @@ -Feature: Undefined steps - - At runtime, Cucumber may encounter a step in a scenario that it cannot match to a - step definition. In these cases, the scenario cannot run and so the step status - will be UNDEFINED, with subsequent steps being skipped and the overall result treated - as a failure. - - Scenario: Undefined step causes failure - Given a step that isnt implemented yet - - Scenario: Steps before undefined steps are executed - Given an implemented step - When a step that isnt implemented yet - - Scenario: Steps after undefined steps are skipped - Given a step that isnt implemented yet - Then a step that we expect to be skipped diff --git a/python/src/message_samples/undefined/undefined.feature.ndjson b/python/src/message_samples/undefined/undefined.feature.ndjson deleted file mode 100644 index 44d00265..00000000 --- a/python/src/message_samples/undefined/undefined.feature.ndjson +++ /dev/null @@ -1,29 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Undefined steps\n\n At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario cannot run and so the step status\n will be UNDEFINED, with subsequent steps being skipped and the overall result treated\n as a failure.\n\n Scenario: Undefined step causes failure\n Given a step that isnt implemented yet\n\n Scenario: Steps before undefined steps are executed\n Given an implemented step\n When a step that isnt implemented yet\n\n Scenario: Steps after undefined steps are skipped\n Given a step that isnt implemented yet\n Then a step that we expect to be skipped\n","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/undefined/undefined.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"3","keyword":"Scenario","location":{"column":3,"line":8},"name":"Undefined step causes failure","steps":[{"id":"2","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":9},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"6","keyword":"Scenario","location":{"column":3,"line":11},"name":"Steps before undefined steps are executed","steps":[{"id":"4","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":12},"text":"an implemented step"},{"id":"5","keyword":"When ","keywordType":"Action","location":{"column":5,"line":13},"text":"a step that isnt implemented yet"}],"tags":[]}},{"scenario":{"description":"","examples":[],"id":"9","keyword":"Scenario","location":{"column":3,"line":15},"name":"Steps after undefined steps are skipped","steps":[{"id":"7","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":16},"text":"a step that isnt implemented yet"},{"id":"8","keyword":"Then ","keywordType":"Outcome","location":{"column":5,"line":17},"text":"a step that we expect to be skipped"}],"tags":[]}}],"description":" At runtime, Cucumber may encounter a step in a scenario that it cannot match to a\n step definition. In these cases, the scenario cannot run and so the step status\n will be UNDEFINED, with subsequent steps being skipped and the overall result treated\n as a failure.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Undefined steps","tags":[]},"uri":"samples/undefined/undefined.feature"}} -{"pickle":{"astNodeIds":["3"],"id":"11","language":"en","name":"Undefined step causes failure","steps":[{"astNodeIds":["2"],"id":"10","text":"a step that isnt implemented yet","type":"Context"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} -{"pickle":{"astNodeIds":["6"],"id":"14","language":"en","name":"Steps before undefined steps are executed","steps":[{"astNodeIds":["4"],"id":"12","text":"an implemented step","type":"Context"},{"astNodeIds":["5"],"id":"13","text":"a step that isnt implemented yet","type":"Action"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} -{"pickle":{"astNodeIds":["9"],"id":"17","language":"en","name":"Steps after undefined steps are skipped","steps":[{"astNodeIds":["7"],"id":"15","text":"a step that isnt implemented yet","type":"Context"},{"astNodeIds":["8"],"id":"16","text":"a step that we expect to be skipped","type":"Outcome"}],"tags":[],"uri":"samples/undefined/undefined.feature"}} -{"stepDefinition":{"id":"0","pattern":{"source":"an implemented step","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":3},"uri":"samples/undefined/undefined.feature.ts"}}} -{"stepDefinition":{"id":"1","pattern":{"source":"a step that we expect to be skipped","type":"CUCUMBER_EXPRESSION"},"sourceReference":{"location":{"line":7},"uri":"samples/undefined/undefined.feature.ts"}}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"19","pickleId":"11","testSteps":[{"id":"18","pickleStepId":"10","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCase":{"id":"22","pickleId":"14","testSteps":[{"id":"20","pickleStepId":"12","stepDefinitionIds":["0"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]},{"id":"21","pickleStepId":"13","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCase":{"id":"25","pickleId":"17","testSteps":[{"id":"23","pickleStepId":"15","stepDefinitionIds":[],"stepMatchArgumentsLists":[]},{"id":"24","pickleStepId":"16","stepDefinitionIds":["1"],"stepMatchArgumentsLists":[{"stepMatchArguments":[]}]}]}} -{"testCaseStarted":{"attempt":0,"id":"26","testCaseId":"19","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"26","testStepId":"18","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"26","testStepId":"18","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"26","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"27","testCaseId":"22","timestamp":{"nanos":5000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"27","testStepId":"20","timestamp":{"nanos":6000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"27","testStepId":"20","testStepResult":{"duration":{"nanos":1000000,"seconds":0},"status":"PASSED"},"timestamp":{"nanos":7000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"27","testStepId":"21","timestamp":{"nanos":8000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"27","testStepId":"21","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":9000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"27","timestamp":{"nanos":10000000,"seconds":0},"willBeRetried":false}} -{"testCaseStarted":{"attempt":0,"id":"28","testCaseId":"25","timestamp":{"nanos":11000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"23","timestamp":{"nanos":12000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"23","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":13000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"28","testStepId":"24","timestamp":{"nanos":14000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"28","testStepId":"24","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"SKIPPED"},"timestamp":{"nanos":15000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"28","timestamp":{"nanos":16000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":17000000,"seconds":0}}} diff --git a/python/src/message_samples/undefined/undefined.feature.ts b/python/src/message_samples/undefined/undefined.feature.ts deleted file mode 100644 index 09d8898f..00000000 --- a/python/src/message_samples/undefined/undefined.feature.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Given } from '@cucumber/fake-cucumber' - -Given('an implemented step', function () { - // no-op -}) - -Given('a step that we expect to be skipped', function () { - // no-op -}) diff --git a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature deleted file mode 100644 index 4ce05c97..00000000 --- a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature +++ /dev/null @@ -1,6 +0,0 @@ -Feature: Parameter Types - Cucumber will generate an error message if a step definition registers - an unknown parameter type, but the suite will run. - - Scenario: undefined parameter type - Given CDG is closed because of a strike diff --git a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson deleted file mode 100644 index 19efe139..00000000 --- a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ndjson +++ /dev/null @@ -1,12 +0,0 @@ -{"meta":{"ci":{"buildNumber":"154666429","git":{"remote":"https://github.com/cucumber-ltd/shouty.rb.git","revision":"99684bcacf01d95875834d87903dcb072306c9ad"},"name":"GitHub Actions","url":"https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429"},"cpu":{"name":"x64"},"implementation":{"name":"fake-cucumber","version":"16.3.0"},"os":{"name":"darwin","version":"22.4.0"},"protocolVersion":"22.0.0","runtime":{"name":"node.js","version":"19.7.0"}}} -{"source":{"data":"Feature: Parameter Types\n Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.\n\n Scenario: undefined parameter type\n Given CDG is closed because of a strike","mediaType":"text/x.cucumber.gherkin+plain","uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} -{"gherkinDocument":{"comments":[],"feature":{"children":[{"scenario":{"description":"","examples":[],"id":"1","keyword":"Scenario","location":{"column":3,"line":5},"name":"undefined parameter type","steps":[{"id":"0","keyword":"Given ","keywordType":"Context","location":{"column":5,"line":6},"text":"CDG is closed because of a strike"}],"tags":[]}}],"description":" Cucumber will generate an error message if a step definition registers\n an unknown parameter type, but the suite will run.","keyword":"Feature","language":"en","location":{"column":1,"line":1},"name":"Parameter Types","tags":[]},"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} -{"pickle":{"astNodeIds":["1"],"id":"3","language":"en","name":"undefined parameter type","steps":[{"astNodeIds":["0"],"id":"2","text":"CDG is closed because of a strike","type":"Context"}],"tags":[],"uri":"samples/unknown-parameter-type/unknown-parameter-type.feature"}} -{"undefinedParameterType":{"expression":"{airport} is closed because of a strike","name":"airport"}} -{"testRunStarted":{"timestamp":{"nanos":0,"seconds":0}}} -{"testCase":{"id":"5","pickleId":"3","testSteps":[{"id":"4","pickleStepId":"2","stepDefinitionIds":[],"stepMatchArgumentsLists":[]}]}} -{"testCaseStarted":{"attempt":0,"id":"6","testCaseId":"5","timestamp":{"nanos":1000000,"seconds":0}}} -{"testStepStarted":{"testCaseStartedId":"6","testStepId":"4","timestamp":{"nanos":2000000,"seconds":0}}} -{"testStepFinished":{"testCaseStartedId":"6","testStepId":"4","testStepResult":{"duration":{"nanos":0,"seconds":0},"status":"UNDEFINED"},"timestamp":{"nanos":3000000,"seconds":0}}} -{"testCaseFinished":{"testCaseStartedId":"6","timestamp":{"nanos":4000000,"seconds":0},"willBeRetried":false}} -{"testRunFinished":{"success":false,"timestamp":{"nanos":5000000,"seconds":0}}} diff --git a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts b/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts deleted file mode 100644 index 4f3e0c4d..00000000 --- a/python/src/message_samples/unknown-parameter-type/unknown-parameter-type.feature.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Given } from '@cucumber/fake-cucumber' - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -Given('{airport} is closed because of a strike', function (airport) { - throw new Error('Should not be called because airport type not defined') -}) diff --git a/python/src/message_samples/__init__.py b/python/tests/data/message_samples/__init__.py similarity index 100% rename from python/src/message_samples/__init__.py rename to python/tests/data/message_samples/__init__.py diff --git a/python/src/message_samples/minimal/minimal.feature b/python/tests/data/message_samples/minimal/minimal.feature similarity index 100% rename from python/src/message_samples/minimal/minimal.feature rename to python/tests/data/message_samples/minimal/minimal.feature diff --git a/python/src/message_samples/minimal/minimal.feature.ndjson b/python/tests/data/message_samples/minimal/minimal.feature.ndjson similarity index 100% rename from python/src/message_samples/minimal/minimal.feature.ndjson rename to python/tests/data/message_samples/minimal/minimal.feature.ndjson diff --git a/python/src/message_samples/minimal/minimal.feature.ts b/python/tests/data/message_samples/minimal/minimal.feature.ts similarity index 100% rename from python/src/message_samples/minimal/minimal.feature.ts rename to python/tests/data/message_samples/minimal/minimal.feature.ts diff --git a/python/tests/test_model_load.py b/python/tests/test_model_load.py index 0bd959f3..1c4fe31c 100644 --- a/python/tests/test_model_load.py +++ b/python/tests/test_model_load.py @@ -1,52 +1,28 @@ import json -import re from pathlib import Path -from git import Repo -from packaging import version -from pytest import fixture +from pytest import mark, param from cucumber_messages import Envelope +resource_path = Path(__file__).parent.absolute() -@fixture -def compatibility_kit_repo(tmpdir): - repo_path = Path(tmpdir) / "compatibility-kit" - repo = Repo.clone_from( - "https://github.com/cucumber/compatibility-kit.git", - str(repo_path), - branch="main", - ) - repo_tags = list(filter(lambda tag: tag is not None, map(lambda tag: getattr(tag.tag, "tag", None), repo.tags))) - version_pattern = re.compile(r"((.*/)?)v(\d+\.\d+\.\d+)") - last_version = sorted( - map( - version.parse, - map( - lambda match: match.groups()[-1], - filter(lambda match: match is not None, map(lambda tag: re.match(version_pattern, tag), repo_tags)), - ), - ) - )[-1] +@mark.parametrize( + "ast_path", + map( + lambda file: param(file, id=file.name), # type: ignore[no-any-return] + resource_path.rglob("*.ndjson"), + ), +) +def test_simple_load_model(ast_path: Path): + with ast_path.open(mode="r") as ast_file: + for ast_line in ast_file: + model_datum = json.loads(ast_line) + model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] - last_version_tag = next(filter(lambda tag: re.search(re.escape(str(last_version)), tag), repo_tags)) + assert isinstance(model, Envelope) - repo.git.checkout(last_version_tag) + dumped_ast_datum = json.loads(model.model_dump_json(by_alias=True, exclude_none=True)) - return repo_path - - -def test_simple_load_model(compatibility_kit_repo): - for ast_path in (compatibility_kit_repo / "devkit" / "samples").rglob("*.ndjson"): - print(f"Checking ${ast_path}") - with ast_path.open(mode="r") as ast_file: - for ast_line in ast_file: - model_datum = json.loads(ast_line) - model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] - - assert isinstance(model, Envelope) - - dumped_ast_datum = json.loads(model.model_dump_json(by_alias=True, exclude_none=True)) # type: ignore[attr-defined] # migration to pydantic2 - - assert model_datum == dumped_ast_datum + assert model_datum == dumped_ast_datum From af36ce366b79be351af29e1fe59e79a41160d46b Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Sat, 21 Sep 2024 20:26:45 +0300 Subject: [PATCH 4/5] Move out code generation from general flow --- .github/workflows/release-pypi.yaml | 6 ++++++ .github/workflows/test-codegen.yml | 5 ----- .github/workflows/test-python.yml | 5 +++++ python/Makefile | 10 ++++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-pypi.yaml b/.github/workflows/release-pypi.yaml index 85692a2a..4b13db3a 100644 --- a/.github/workflows/release-pypi.yaml +++ b/.github/workflows/release-pypi.yaml @@ -26,6 +26,12 @@ jobs: - name: Show Python version run: python --version + - name: Generate code + working-directory: ./python + run: | + make clean-real + make generate-real + - uses: cucumber/action-publish-pypi@v3.0.0 with: working-directory: "python" diff --git a/.github/workflows/test-codegen.yml b/.github/workflows/test-codegen.yml index 74f2ac8b..463c12e0 100644 --- a/.github/workflows/test-codegen.yml +++ b/.github/workflows/test-codegen.yml @@ -31,11 +31,6 @@ jobs: with: ruby-version: '3.1' - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - name: generate code for all languages run: | make clean-all diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index 82f32e48..83461859 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -67,6 +67,11 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} + - name: Generate code + working-directory: ./python + run: | + make clean-real + make generate-real - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/python/Makefile b/python/Makefile index 75715a3c..f7dc8997 100644 --- a/python/Makefile +++ b/python/Makefile @@ -8,7 +8,10 @@ HERE := $(dir $(MKFILE_PATH)) help: ## Show this help @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \n\nWhere is one of:\n"} /^[$$()% a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) -generate: require install-deps +generate: ## Stub for the ancestor Makefile + echo "Skipping code generation - code is generated by Python" + +generate-real: require install-deps datamodel-codegen \ --output-model-type "pydantic_v2.BaseModel" \ --input $(HERE)../jsonschema/Envelope.json \ @@ -27,7 +30,10 @@ generate: require install-deps require: ## Check requirements for the code generation (python is required) @python --version >/dev/null 2>&1 || (echo "ERROR: python is required."; exit 1) -clean: ## Remove automatically generated files and related artifacts +clean: ## Stub for the ancestor Makefile + echo "Skipping code cleanup - code cleanup is done by Python" + +clean-real: ## Remove automatically generated files and related artifacts rm -rf $(HERE)src/_messages.py install-deps: ## Install generation dependencies From 614d55c0b7e70a0ef8c85787f588cecf461814a4 Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Sat, 21 Sep 2024 20:54:52 +0300 Subject: [PATCH 5/5] Rework of test for minimal Feature --- .../message_samples/minimal/minimal.feature | 10 - .../minimal/minimal.feature.ts | 6 - python/tests/test_model_load.py | 216 ++++++++++++++++-- 3 files changed, 198 insertions(+), 34 deletions(-) delete mode 100644 python/tests/data/message_samples/minimal/minimal.feature delete mode 100644 python/tests/data/message_samples/minimal/minimal.feature.ts diff --git a/python/tests/data/message_samples/minimal/minimal.feature b/python/tests/data/message_samples/minimal/minimal.feature deleted file mode 100644 index 9bc37141..00000000 --- a/python/tests/data/message_samples/minimal/minimal.feature +++ /dev/null @@ -1,10 +0,0 @@ -Feature: minimal - - Cucumber doesn't execute this markdown, but @cucumber/react renders it - - * This is - * a bullet - * list - - Scenario: cukes - Given I have 42 cukes in my belly diff --git a/python/tests/data/message_samples/minimal/minimal.feature.ts b/python/tests/data/message_samples/minimal/minimal.feature.ts deleted file mode 100644 index 941b5ebf..00000000 --- a/python/tests/data/message_samples/minimal/minimal.feature.ts +++ /dev/null @@ -1,6 +0,0 @@ -import assert from 'assert' -import { Given } from '@cucumber/fake-cucumber' - -Given('I have {int} cukes in my belly', function (cukeCount: number) { - assert(cukeCount) -}) diff --git a/python/tests/test_model_load.py b/python/tests/test_model_load.py index 1c4fe31c..e1ded6e5 100644 --- a/python/tests/test_model_load.py +++ b/python/tests/test_model_load.py @@ -1,28 +1,208 @@ import json from pathlib import Path -from pytest import mark, param +from pytest import mark -from cucumber_messages import Envelope - -resource_path = Path(__file__).parent.absolute() +from cucumber_messages import ( + Ci, + Duration, + Envelope, + ExpressionType, + Feature, + FeatureChild, + GherkinDocument, + Git, + Group, + KeywordType, + Location, + MediaType, + Meta, + Pickle, + PickleStep, + Product, + Scenario, + Source, + SourceReference, + Status, + Step, + StepDefinition, + StepDefinitionPattern, + StepMatchArgument, + StepMatchArgumentsList, + TestCase, + TestCaseFinished, + TestCaseStarted, + TestRunFinished, + TestRunStarted, + TestStep, + TestStepFinished, + TestStepResult, + TestStepStarted, + Timestamp, + Type, +) +resource_path = Path(__file__).parent.absolute() / "data" -@mark.parametrize( - "ast_path", - map( - lambda file: param(file, id=file.name), # type: ignore[no-any-return] - resource_path.rglob("*.ndjson"), +with (resource_path / "message_samples/minimal/minimal.feature.ndjson").open(mode="r") as ast_file: + model_data = [*map(json.loads, ast_file)] +oracle_models = [ + Envelope( + meta=Meta( + protocol_version="22.0.0", + implementation=Product(name="fake-cucumber", version="16.3.0"), + runtime=Product(name="node.js", version="19.7.0"), + os=Product(name="darwin", version="22.4.0"), + cpu=Product(name="x64", version=None), + ci=Ci( + name="GitHub Actions", + url="https://github.com/cucumber-ltd/shouty.rb/actions/runs/154666429", + build_number="154666429", + git=Git( + remote="https://github.com/cucumber-ltd/shouty.rb.git", + revision="99684bcacf01d95875834d87903dcb072306c9ad", + tag=None, + ), + ), + ), + undefined_parameter_type=None, ), -) -def test_simple_load_model(ast_path: Path): - with ast_path.open(mode="r") as ast_file: - for ast_line in ast_file: - model_datum = json.loads(ast_line) - model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] + Envelope( + source=Source( + uri="samples/minimal/minimal.feature", + data="Feature: minimal\n \n Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list\n \n Scenario: cukes\n Given I have 42 cukes in my belly\n", + media_type=MediaType.text_x_cucumber_gherkin_plain, + ), + undefined_parameter_type=None, + ), + Envelope( + gherkin_document=GherkinDocument( + uri="samples/minimal/minimal.feature", + feature=Feature( + location=Location(line=1, column=1), + tags=[], + language="en", + keyword="Feature", + name="minimal", + description=" Cucumber doesn't execute this markdown, but @cucumber/react renders it\n \n * This is\n * a bullet\n * list", + children=[ + FeatureChild( + scenario=Scenario( + location=Location(line=9, column=3), + tags=[], + keyword="Scenario", + name="cukes", + description="", + steps=[ + Step( + location=Location(line=10, column=5), + keyword="Given ", + keyword_type=KeywordType.context, + text="I have 42 cukes in my belly", + id="1", + ) + ], + examples=[], + id="2", + ) + ) + ], + ), + comments=[], + ), + undefined_parameter_type=None, + ), + Envelope( + pickle=Pickle( + id="4", + uri="samples/minimal/minimal.feature", + name="cukes", + language="en", + steps=[PickleStep(ast_node_ids=["1"], id="3", type=Type.context, text="I have 42 cukes in my belly")], + tags=[], + ast_node_ids=["2"], + ), + undefined_parameter_type=None, + ), + Envelope( + step_definition=StepDefinition( + id="0", + pattern=StepDefinitionPattern( + source="I have {int} cukes in my belly", type=ExpressionType.cucumber_expression + ), + source_reference=SourceReference( + uri="samples/minimal/minimal.feature.ts", location=Location(line=4, column=None) + ), + ), + undefined_parameter_type=None, + ), + Envelope(test_run_started=TestRunStarted(timestamp=Timestamp(seconds=0, nanos=0)), undefined_parameter_type=None), + Envelope( + test_case=TestCase( + id="6", + pickle_id="4", + test_steps=[ + TestStep( + id="5", + pickle_step_id="3", + step_definition_ids=["0"], + step_match_arguments_lists=[ + StepMatchArgumentsList( + step_match_arguments=[ + StepMatchArgument( + group=Group(children=[], start=7, value="42"), parameter_type_name="int" + ) + ] + ) + ], + ) + ], + ), + undefined_parameter_type=None, + ), + Envelope( + test_case_started=TestCaseStarted( + attempt=0, id="7", test_case_id="6", timestamp=Timestamp(seconds=0, nanos=1000000) + ), + undefined_parameter_type=None, + ), + Envelope( + test_step_started=TestStepStarted( + test_case_started_id="7", test_step_id="5", timestamp=Timestamp(seconds=0, nanos=2000000) + ), + undefined_parameter_type=None, + ), + Envelope( + test_step_finished=TestStepFinished( + test_case_started_id="7", + test_step_id="5", + test_step_result=TestStepResult( + duration=Duration(seconds=0, nanos=1000000), status=Status.passed, exception=None + ), + timestamp=Timestamp(seconds=0, nanos=3000000), + ), + undefined_parameter_type=None, + ), + Envelope( + test_case_finished=TestCaseFinished( + test_case_started_id="7", timestamp=Timestamp(seconds=0, nanos=4000000), will_be_retried=False + ), + undefined_parameter_type=None, + ), + Envelope( + test_run_finished=TestRunFinished(success=True, timestamp=Timestamp(seconds=0, nanos=5000000), exception=None), + undefined_parameter_type=None, + ), +] + + +@mark.parametrize("model_datum, oracle_model", zip(model_data, oracle_models)) +def test_simple_load_model(model_datum, oracle_model): + model = Envelope.model_validate(model_datum) # type: ignore[attr-defined] - assert isinstance(model, Envelope) + assert isinstance(model, Envelope) + assert oracle_model == model - dumped_ast_datum = json.loads(model.model_dump_json(by_alias=True, exclude_none=True)) + dumped_ast_datum = json.loads(oracle_model.model_dump_json(by_alias=True, exclude_none=True)) - assert model_datum == dumped_ast_datum + assert model_datum == dumped_ast_datum