gherkin_system 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/command"
4
+ require "gherkin_system"
5
+
6
+ module Rails
7
+ module Command
8
+ # Facade over `bin/rails test`. Subcommands are methods, matching `test:system`.
9
+ class GherkinCommand < Base
10
+ class_option :tags, type: :string, desc: "Cucumber tag expression"
11
+
12
+ desc "gherkin [PATH]", "Run Gherkin system tests"
13
+ def perform(*args)
14
+ prepare!(args)
15
+ Rails::Command.invoke("test", [GherkinSystem::Cli.test_file, *args])
16
+ end
17
+
18
+ desc "check [PATH]", "Validate Gherkin features without a browser"
19
+ def check(*args)
20
+ prepare!(args)
21
+ load_definitions
22
+ report(GherkinSystem::Checker.call)
23
+ end
24
+
25
+ desc "list [PATH]", "List compiled Gherkin scenarios"
26
+ def list(*args)
27
+ prepare!(args)
28
+ scenarios.each { |scenario| puts scenario_line(scenario) }
29
+ end
30
+
31
+ private
32
+
33
+ def prepare!(args)
34
+ GherkinSystem::Cli.prepare_test_env!
35
+ GherkinSystem::Cli.apply_filters!(args, tags: options[:tags])
36
+ boot_application!
37
+ end
38
+
39
+ def load_definitions
40
+ test_dir = Rails.root.join("test").to_s
41
+ $LOAD_PATH.unshift(test_dir) unless $LOAD_PATH.include?(test_dir)
42
+ path = GherkinSystem::Cli.test_file
43
+ raise GherkinSystem::ConfigurationError, "Missing #{path}" unless File.exist?(path)
44
+
45
+ require path
46
+ rescue GherkinSystem::Error => e
47
+ warn e.message
48
+ exit!(1)
49
+ end
50
+
51
+ def report(result)
52
+ io = result.ok? ? $stdout : $stderr
53
+ io.puts(result.ok? ? "Gherkin check passed" : result.report)
54
+ io.flush
55
+ exit!(result.ok? ? 0 : 1)
56
+ end
57
+
58
+ def scenarios
59
+ loaded = GherkinSystem::FeatureLoader.load
60
+ GherkinSystem::TagFilter.apply(loaded, GherkinSystem.config.tags)
61
+ end
62
+
63
+ def scenario_line(scenario)
64
+ "#{scenario.uri}:#{scenario.line} #{scenario.test_name}"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,64 @@
1
+ module GherkinSystem
2
+ VERSION: String
3
+
4
+ def self.config: () -> Configuration
5
+ def self.configure: () { (Configuration) -> void } -> void
6
+ def self.reset_configuration!: () -> void
7
+ def self.load!: (?String glob, ?base: Class?) -> Array[Class]
8
+ def self.step_registry: () -> StepRegistry
9
+ def self.parameter_registry: () -> ParameterRegistry
10
+ def self.hook_registry: () -> HookRegistry
11
+
12
+ class Configuration
13
+ attr_reader step_modules: Array[Module]
14
+ attr_writer features: String
15
+ attr_writer base_test_class: Class?
16
+ attr_writer strict: bool
17
+ attr_writer test_file: String
18
+
19
+ def features: () -> String
20
+ def base_test_class: () -> Class?
21
+ def strict: () -> bool
22
+ def test_file: () -> String
23
+ def tags: () -> String?
24
+ def tags=: (String?) -> void
25
+ def include_steps: (Module) -> void
26
+ end
27
+
28
+ class Error < StandardError
29
+ end
30
+
31
+ class ConfigurationError < Error
32
+ end
33
+
34
+ class CompilationError < Error
35
+ end
36
+
37
+ class DuplicateStep < Error
38
+ end
39
+
40
+ class UndefinedStep < Error
41
+ end
42
+
43
+ class AmbiguousStep < Error
44
+ end
45
+
46
+ class StepFailure < Error
47
+ attr_reader cause: Exception
48
+ end
49
+
50
+ class DataTable
51
+ def initialize: (Array[Array[String]]) -> void
52
+ def raw: () -> Array[Array[String]]
53
+ def hashes: () -> Array[Hash[String, String]]
54
+ end
55
+
56
+ class Checker
57
+ def self.call: (?String? glob) -> Result
58
+
59
+ class Result
60
+ def ok?: () -> bool
61
+ def report: () -> String
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,128 @@
1
+ ---
2
+ name: gherkin-system
3
+ description: >-
4
+ Write and run Rails system tests as Gherkin features with the gherkin_system
5
+ gem. Use when adding or changing user-facing Rails behavior, acceptance
6
+ tests, .feature files, step definitions, or bin/rails gherkin commands.
7
+ ---
8
+
9
+ # gherkin_system
10
+
11
+ Gherkin describes the behavior. Rails runs it. Each scenario becomes a Minitest method on the app's `ApplicationSystemTestCase`.
12
+
13
+ Do not add cucumber-rails, a Cucumber World, or a second test runner. Do not use this skill to change the gem's own compiler. Gem development follows `AGENTS.md`.
14
+
15
+ ## Add a scenario
16
+
17
+ 1. Write the feature under `features/system/**/*.feature`.
18
+ 2. Bind steps in `test/support/gherkin/*_steps.rb`.
19
+ 3. Require that file from `test/system/gherkin_test.rb` before `GherkinSystem.load!`.
20
+ 4. Run `bin/rails gherkin:check`.
21
+ 5. Run the scenario with `bin/rails gherkin path/to/file.feature:LINE`.
22
+
23
+ Create the loader once if it is missing:
24
+
25
+ ```ruby
26
+ # test/system/gherkin_test.rb
27
+ require "application_system_test_case"
28
+ require_relative "../support/gherkin/checkout_steps"
29
+ require "gherkin_system/rails"
30
+
31
+ GherkinSystem.configure do |config|
32
+ config.include_steps CheckoutSteps
33
+ end
34
+
35
+ GherkinSystem.load!(base: ApplicationSystemTestCase)
36
+ ```
37
+
38
+ `base:` must be the application's system test class. The generated tests subclass it.
39
+
40
+ ## Write behavior
41
+
42
+ One scenario proves one outcome. Name it for the condition and the result.
43
+
44
+ ```gherkin
45
+ Feature: Subscription purchase
46
+
47
+ Scenario: Customer purchases Pro
48
+ Given I am signed in
49
+ When I purchase the "Pro" plan
50
+ Then my subscription should be active
51
+ ```
52
+
53
+ Use a Scenario Outline only when each row is the same rule with different data. Each row becomes its own test.
54
+
55
+ Assert the outcome the user was promised. Drive it through the browser and the real application. Do not mock models, controllers, jobs, or mailers to make the scenario pass.
56
+
57
+ ## Bind steps
58
+
59
+ ```ruby
60
+ module CheckoutSteps
61
+ extend GherkinSystem::Steps
62
+
63
+ Given("I am signed in") do
64
+ sign_in users(:customer)
65
+ end
66
+
67
+ When("I purchase the {string} plan") do |plan|
68
+ visit plans_path
69
+ click_on plan
70
+ end
71
+
72
+ Then("my subscription should be active") do
73
+ assert_text "Purchase complete"
74
+ assert_predicate users(:customer).reload.subscription, :active?
75
+ end
76
+ end
77
+ ```
78
+
79
+ - `Given`, `When`, `Then`, `And`, and `But` share one registry.
80
+ - Blocks run with `instance_exec` on the system test. `visit`, fixtures, routes, assertions, and `@ivars` are that test instance.
81
+ - Call `config.include_steps` when the module also defines helper methods.
82
+ - Prefer Cucumber Expressions (`{string}`, `{int}`). Use a regex only to match an existing definition.
83
+ - Data tables arrive as an object with `#hashes` (string keys) and `#raw`. Doc strings arrive as the content string.
84
+
85
+ ## Hooks
86
+
87
+ ```ruby
88
+ module CheckoutHooks
89
+ extend GherkinSystem::Hooks
90
+
91
+ Before("@admin") do
92
+ end
93
+
94
+ After do |scenario|
95
+ end
96
+
97
+ Around("@external") do |scenario|
98
+ scenario.run
99
+ end
100
+ end
101
+ ```
102
+
103
+ Require the hook file before `load!`. Rails `setup` runs before these hooks. Rails `teardown` and failure screenshots run after them. An `Around` hook must call `scenario.run`.
104
+
105
+ ## Commands
106
+
107
+ | Command | Use |
108
+ | --- | --- |
109
+ | `bin/rails gherkin:check` | Parse and resolve steps. No browser. Run this before executing a scenario. |
110
+ | `bin/rails gherkin PATH:LINE` | Run the scenario at that line. |
111
+ | `bin/rails gherkin --tags "@critical and not @slow"` | Cucumber tag expression. |
112
+ | `bin/rails gherkin:list` | Show compiled scenarios. |
113
+ | `bin/rails test:system` | Run every system test, including compiled scenarios. |
114
+
115
+ `GHERKIN_TAGS` left set in the environment also filters `bin/rails test:system`. Unset it to compile every scenario.
116
+
117
+ ## When check fails
118
+
119
+ - Undefined step: add the suggested definition, then re-run check.
120
+ - Ambiguous step: delete or narrow one of the matching definitions.
121
+ - Duplicate pattern: the same string or regex is registered twice.
122
+ - Invalid Gherkin or tag expression: the message includes the feature path.
123
+
124
+ A missing step fails that scenario before the driver starts. Other scenarios still run.
125
+
126
+ ## Done
127
+
128
+ `gherkin:check` exits 0, and the scenario exits 0 through `bin/rails gherkin` or `bin/rails test:system`. A check or execution that cannot run is a failure, not a skipped acceptance test.
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gherkin_system
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - David Paluy
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: cucumber-cucumber-expressions
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '17'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '21'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '17'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '21'
32
+ - !ruby/object:Gem::Dependency
33
+ name: cucumber-gherkin
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '28'
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '40'
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '28'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '40'
52
+ - !ruby/object:Gem::Dependency
53
+ name: cucumber-tag-expressions
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '6'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '12'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '6'
69
+ - - "<"
70
+ - !ruby/object:Gem::Version
71
+ version: '12'
72
+ description: gherkin_system turns Gherkin scenarios into Minitest methods on the application's
73
+ ApplicationSystemTestCase. Rails owns execution. Gherkin describes behavior.
74
+ email:
75
+ - dpaluy@users.noreply.github.com
76
+ executables: []
77
+ extensions: []
78
+ extra_rdoc_files:
79
+ - CHANGELOG.md
80
+ - LICENSE.txt
81
+ - README.md
82
+ files:
83
+ - CHANGELOG.md
84
+ - LICENSE
85
+ - LICENSE.txt
86
+ - README.md
87
+ - lib/gherkin_system.rb
88
+ - lib/gherkin_system/checker.rb
89
+ - lib/gherkin_system/cli.rb
90
+ - lib/gherkin_system/configuration.rb
91
+ - lib/gherkin_system/data_table.rb
92
+ - lib/gherkin_system/errors.rb
93
+ - lib/gherkin_system/executor.rb
94
+ - lib/gherkin_system/feature_loader.rb
95
+ - lib/gherkin_system/hooks.rb
96
+ - lib/gherkin_system/parameter_registry.rb
97
+ - lib/gherkin_system/parser.rb
98
+ - lib/gherkin_system/rails.rb
99
+ - lib/gherkin_system/railtie.rb
100
+ - lib/gherkin_system/scenario.rb
101
+ - lib/gherkin_system/scenario_run.rb
102
+ - lib/gherkin_system/snippet.rb
103
+ - lib/gherkin_system/step_definition.rb
104
+ - lib/gherkin_system/step_registry.rb
105
+ - lib/gherkin_system/steps.rb
106
+ - lib/gherkin_system/tag_filter.rb
107
+ - lib/gherkin_system/test_class_builder.rb
108
+ - lib/gherkin_system/version.rb
109
+ - lib/rails/commands/gherkin/gherkin_command.rb
110
+ - sig/gherkin_system.rbs
111
+ - skills/gherkin-system/SKILL.md
112
+ homepage: https://github.com/dpaluy/gherkin_system
113
+ licenses:
114
+ - MIT
115
+ metadata:
116
+ rubygems_mfa_required: 'true'
117
+ homepage_uri: https://github.com/dpaluy/gherkin_system
118
+ documentation_uri: https://rubydoc.info/gems/gherkin_system
119
+ source_code_uri: https://github.com/dpaluy/gherkin_system
120
+ changelog_uri: https://github.com/dpaluy/gherkin_system/blob/master/CHANGELOG.md
121
+ bug_tracker_uri: https://github.com/dpaluy/gherkin_system/issues
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: 3.2.0
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubygems_version: 4.0.20
137
+ specification_version: 4
138
+ summary: Compile Gherkin features into Rails system tests.
139
+ test_files: []