stimulus_spec 0.4.0 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed3850b553fca15bb450d8ad6e0f50d37593c90bd440d26c6cbf0a8eb99882ea
4
- data.tar.gz: a0b96c0888a87a93ef3db2e783d747642f09f863003c3f9a8fc43cc04ca4f392
3
+ metadata.gz: f9f2064cf807ad376e2e9098aa7a400986c40f2fff504d7e4f2db7450ef02154
4
+ data.tar.gz: 0c221ae06953f2ce8e74663b2500ee452e30fee9acfbf08edf02a35c99ea4cb5
5
5
  SHA512:
6
- metadata.gz: 0ee41b07ee4796f9670ec0a805ff0b6f52179fddc5cec9169f8272d65bc1bf6c7b114fc173093a091e2f468b42c1a6e06d1d0d3bd6b7c837ceb2b47686c96388
7
- data.tar.gz: fe153dd036e2c7ab6d27b9e22a3bdc88f30f9d16b73cae11d7fbd146bb7b5567faa4f0331e83bb3f1fb2fde8bba94d9674b45ce99011b3cf6e84d7ee02ad711c
6
+ metadata.gz: c06ffeb2e5a16290a59ee122a7dd40a7933a840dd1899e006755184c172a92ff472260976b0fc08f29522bd78c961d5315ab98471867785342099aef49503646
7
+ data.tar.gz: a6d8f79f021f954e00c7c2aec8e5c14c972ced90b1e143324fc47b75bc8b5d6f641e9d33efdf95e348600573df5271a43586f4bdaed3145ac567ff0b24b24672
data/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.0] - 2026-06-23
11
+
12
+ ### Added
13
+
14
+ - Capybara `have_stimulus_class` matcher (existence and equality modes) for system/feature specs
15
+ - Capybara `have_stimulus_outlet` matcher (existence and selector modes) for system/feature specs
16
+
10
17
  ## [0.4.0] - 2026-06-22
11
18
 
12
19
  ### Added
@@ -39,7 +46,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
39
46
  - `have_stimulus_action(descriptor)` matcher — full descriptor (`~=`) and shorthand without event (`*=`)
40
47
  - `have_stimulus_target(controller, target)` matcher — asserts `[data-{controller}-target~="target"]`
41
48
 
42
- [Unreleased]: https://github.com/eclectic-coding/stimulus_spec/compare/v0.4.0...HEAD
49
+ [Unreleased]: https://github.com/eclectic-coding/stimulus_spec/compare/v0.5.0...HEAD
50
+ [0.5.0]: https://github.com/eclectic-coding/stimulus_spec/releases/tag/v0.5.0
43
51
  [0.4.0]: https://github.com/eclectic-coding/stimulus_spec/releases/tag/v0.4.0
44
52
  [0.3.0]: https://github.com/eclectic-coding/stimulus_spec/releases/tag/v0.3.0
45
53
  [0.1.0]: https://github.com/eclectic-coding/stimulus_spec/releases/tag/v0.1.0
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  Drop-in RSpec matchers for [hotwired/stimulus-rails](https://github.com/hotwired/stimulus-rails) — stop hand-rolling `data-controller` assertions and test your Stimulus wiring with expressive, purpose-built matchers.
10
10
 
11
11
  - **Request/controller specs** — `have_stimulus_controller`, `have_stimulus_action`, `have_stimulus_target`, `have_stimulus_value`, `have_stimulus_class`, `have_stimulus_outlet`
12
- - **System/feature specs** — Capybara matchers: `have_stimulus_controller`, `have_stimulus_action`, `have_stimulus_target`, `have_stimulus_value`
12
+ - **System/feature specs** — Capybara matchers: `have_stimulus_controller`, `have_stimulus_action`, `have_stimulus_target`, `have_stimulus_value`, `have_stimulus_class`, `have_stimulus_outlet`
13
13
  - **Auto-included** — zero setup required when `stimulus-rails` is in your bundle
14
14
  - **Configurable** — disable auto-include when you need manual control
15
15
 
data/ROADMAP.md CHANGED
@@ -11,7 +11,14 @@ RSpec matchers for [Stimulus](https://github.com/hotwired/stimulus-rails): contr
11
11
 
12
12
  ---
13
13
 
14
- ## 0.5.0 — Documentation and Polish
14
+ ## 0.6.0 — Multi-Controller and Scoped Matching
15
+
16
+ - `have_stimulus_controller("hello", "clipboard")` — assert multiple controllers on a single element
17
+ - Scoped matching — assert Stimulus attributes within a specific CSS selector (e.g., within a form or component root)
18
+
19
+ ---
20
+
21
+ ## 0.7.0 — Documentation and Polish
15
22
 
16
23
  - Full YARD documentation on all public methods and classes
17
24
  - `docs/cookbook.md` — common patterns: request specs, system specs, multi-controller elements, typed values, outlets
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusSpec
4
+ module Capybara
5
+ module Matchers
6
+ class HaveStimulusClass
7
+ def initialize(controller, name, expected = nil)
8
+ @controller = controller.to_s
9
+ @name = name.to_s
10
+ @expected = expected
11
+ @attr = "data-#{@controller}-#{@name}-class"
12
+ end
13
+
14
+ def matches?(page)
15
+ @page = page
16
+ element = page.first("[#{@attr}]", minimum: 0, wait: 0)
17
+ return false unless element
18
+
19
+ if @expected
20
+ @actual = element[@attr]
21
+ @actual == @expected.to_s
22
+ else
23
+ true
24
+ end
25
+ end
26
+
27
+ def does_not_match?(page)
28
+ !matches?(page)
29
+ end
30
+
31
+ def failure_message
32
+ if @expected && @actual
33
+ "expected #{@attr} to be \"#{@expected}\" but was \"#{@actual}\""
34
+ else
35
+ "expected to find an element with #{@attr} on the page"
36
+ end
37
+ end
38
+
39
+ def failure_message_when_negated
40
+ "expected not to find an element with #{@attr} on the page"
41
+ end
42
+
43
+ def description
44
+ if @expected
45
+ "have Stimulus class \"#{@name}\" with \"#{@expected}\" for controller \"#{@controller}\""
46
+ else
47
+ "have Stimulus class \"#{@name}\" for controller \"#{@controller}\""
48
+ end
49
+ end
50
+ end
51
+
52
+ def have_stimulus_class(controller, name, expected = nil)
53
+ HaveStimulusClass.new(controller, name, expected)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StimulusSpec
4
+ module Capybara
5
+ module Matchers
6
+ class HaveStimulusOutlet
7
+ def initialize(controller, outlet, selector = nil)
8
+ @controller = controller.to_s
9
+ @outlet = outlet.to_s
10
+ @selector = selector
11
+ @attr = "data-#{@controller}-#{@outlet}-outlet"
12
+ end
13
+
14
+ def matches?(page)
15
+ @page = page
16
+ element = page.first("[#{@attr}]", minimum: 0, wait: 0)
17
+ return false unless element
18
+
19
+ if @selector
20
+ @actual = element[@attr]
21
+ @actual == @selector.to_s
22
+ else
23
+ true
24
+ end
25
+ end
26
+
27
+ def does_not_match?(page)
28
+ !matches?(page)
29
+ end
30
+
31
+ def failure_message
32
+ if @selector && @actual
33
+ "expected #{@attr} to be \"#{@selector}\" but was \"#{@actual}\""
34
+ else
35
+ "expected to find an element with #{@attr} on the page"
36
+ end
37
+ end
38
+
39
+ def failure_message_when_negated
40
+ "expected not to find an element with #{@attr} on the page"
41
+ end
42
+
43
+ def description
44
+ if @selector
45
+ "have Stimulus outlet \"#{@outlet}\" with \"#{@selector}\" for controller \"#{@controller}\""
46
+ else
47
+ "have Stimulus outlet \"#{@outlet}\" for controller \"#{@controller}\""
48
+ end
49
+ end
50
+ end
51
+
52
+ def have_stimulus_outlet(controller, outlet, selector = nil)
53
+ HaveStimulusOutlet.new(controller, outlet, selector)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -4,6 +4,8 @@ require_relative "matchers/have_stimulus_controller"
4
4
  require_relative "matchers/have_stimulus_action"
5
5
  require_relative "matchers/have_stimulus_target"
6
6
  require_relative "matchers/have_stimulus_value"
7
+ require_relative "matchers/have_stimulus_class"
8
+ require_relative "matchers/have_stimulus_outlet"
7
9
 
8
10
  module StimulusSpec
9
11
  module Capybara
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StimulusSpec
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -81,6 +81,8 @@ module StimulusSpec
81
81
  def have_stimulus_action: (String descriptor) -> HaveStimulusAction
82
82
  def have_stimulus_target: (String controller, String target) -> HaveStimulusTarget
83
83
  def have_stimulus_value: (String controller, String name, ?String? expected) -> HaveStimulusValue
84
+ def have_stimulus_class: (String controller, String name, ?String? expected) -> HaveStimulusClass
85
+ def have_stimulus_outlet: (String controller, String outlet, ?String? selector) -> HaveStimulusOutlet
84
86
 
85
87
  class HaveStimulusController
86
88
  def initialize: (String name) -> void
@@ -117,6 +119,24 @@ module StimulusSpec
117
119
  def failure_message_when_negated: () -> String
118
120
  def description: () -> String
119
121
  end
122
+
123
+ class HaveStimulusClass
124
+ def initialize: (String controller, String name, ?String? expected) -> void
125
+ def matches?: (untyped page) -> bool
126
+ def does_not_match?: (untyped page) -> bool
127
+ def failure_message: () -> String
128
+ def failure_message_when_negated: () -> String
129
+ def description: () -> String
130
+ end
131
+
132
+ class HaveStimulusOutlet
133
+ def initialize: (String controller, String outlet, ?String? selector) -> void
134
+ def matches?: (untyped page) -> bool
135
+ def does_not_match?: (untyped page) -> bool
136
+ def failure_message: () -> String
137
+ def failure_message_when_negated: () -> String
138
+ def description: () -> String
139
+ end
120
140
  end
121
141
  end
122
142
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuck Smith
@@ -46,7 +46,9 @@ files:
46
46
  - lib/stimulus_spec.rb
47
47
  - lib/stimulus_spec/capybara/matchers.rb
48
48
  - lib/stimulus_spec/capybara/matchers/have_stimulus_action.rb
49
+ - lib/stimulus_spec/capybara/matchers/have_stimulus_class.rb
49
50
  - lib/stimulus_spec/capybara/matchers/have_stimulus_controller.rb
51
+ - lib/stimulus_spec/capybara/matchers/have_stimulus_outlet.rb
50
52
  - lib/stimulus_spec/capybara/matchers/have_stimulus_target.rb
51
53
  - lib/stimulus_spec/capybara/matchers/have_stimulus_value.rb
52
54
  - lib/stimulus_spec/configuration.rb