zenspec 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +637 -0
- data/Rakefile +12 -0
- data/examples/progress_loader_demo.rb +113 -0
- data/lib/zenspec/formatters/progress_bar_formatter.rb +433 -0
- data/lib/zenspec/formatters/progress_formatter.rb +146 -0
- data/lib/zenspec/helpers/graphql_helpers.rb +103 -0
- data/lib/zenspec/helpers.rb +10 -0
- data/lib/zenspec/matchers/graphql_matchers.rb +358 -0
- data/lib/zenspec/matchers/graphql_type_matchers.rb +554 -0
- data/lib/zenspec/matchers/interactor_matchers.rb +216 -0
- data/lib/zenspec/matchers.rb +12 -0
- data/lib/zenspec/progress_loader.rb +155 -0
- data/lib/zenspec/railtie.rb +26 -0
- data/lib/zenspec/shoulda_config.rb +17 -0
- data/lib/zenspec/version.rb +5 -0
- data/lib/zenspec.rb +14 -0
- data/sig/zenspec.rbs +4 -0
- metadata +121 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rspec/expectations"
|
|
4
|
+
|
|
5
|
+
module Zenspec
|
|
6
|
+
module Matchers
|
|
7
|
+
module InteractorMatchers
|
|
8
|
+
# Matcher for checking if an interactor succeeds
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# expect(result).to succeed
|
|
12
|
+
# expect(result).to succeed.with_data(expected_value)
|
|
13
|
+
# expect(result).to succeed.with_context(:key, value)
|
|
14
|
+
# expect(MyInteractor).to succeed.with_context(:user, user)
|
|
15
|
+
#
|
|
16
|
+
RSpec::Matchers.define :succeed do
|
|
17
|
+
match do |actual|
|
|
18
|
+
@result = get_result(actual)
|
|
19
|
+
return false if @result.failure?
|
|
20
|
+
|
|
21
|
+
return false if @expected_data && @result.data != @expected_data
|
|
22
|
+
|
|
23
|
+
if @context_checks
|
|
24
|
+
@context_checks.all? do |key, value|
|
|
25
|
+
@result.public_send(key) == value
|
|
26
|
+
end
|
|
27
|
+
else
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
chain :with_data do |expected_data|
|
|
33
|
+
@expected_data = expected_data
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
chain :with_context do |key, value|
|
|
37
|
+
@context_checks ||= {}
|
|
38
|
+
@context_checks[key] = value
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
failure_message do
|
|
42
|
+
if @result.failure?
|
|
43
|
+
"expected interactor to succeed, but it failed with errors: #{@result.errors}"
|
|
44
|
+
elsif @expected_data && @result.data != @expected_data
|
|
45
|
+
"expected data to be #{@expected_data.inspect}, got #{@result.data.inspect}"
|
|
46
|
+
elsif @context_checks
|
|
47
|
+
failed_checks = @context_checks.reject { |key, value| @result.public_send(key) == value }
|
|
48
|
+
"expected context to match #{@context_checks.inspect}, but #{failed_checks.inspect} did not match"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def get_result(actual)
|
|
55
|
+
if actual.is_a?(Class) && actual.ancestors.include?(Interactor)
|
|
56
|
+
actual.call
|
|
57
|
+
else
|
|
58
|
+
actual
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Matcher for checking if an interactor fails
|
|
64
|
+
#
|
|
65
|
+
# @example
|
|
66
|
+
# expect(result).to fail_interactor
|
|
67
|
+
# expect(result).to fail_interactor.with_error("invalid_input")
|
|
68
|
+
# expect(result).to fail_interactor.with_errors("error1", "error2")
|
|
69
|
+
# expect(MyInteractor).to fail_interactor.with_error("not_found")
|
|
70
|
+
#
|
|
71
|
+
RSpec::Matchers.define :fail_interactor do
|
|
72
|
+
match do |actual|
|
|
73
|
+
@result = get_result(actual)
|
|
74
|
+
return false if @result.success?
|
|
75
|
+
|
|
76
|
+
if @expected_error_codes && !@expected_error_codes.empty?
|
|
77
|
+
actual_codes = error_codes(@result)
|
|
78
|
+
@expected_error_codes.all? { |code| actual_codes.include?(code) }
|
|
79
|
+
else
|
|
80
|
+
true
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
chain :with_error do |error_code|
|
|
85
|
+
@expected_error_codes ||= []
|
|
86
|
+
@expected_error_codes << error_code
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
chain :with_errors do |*error_codes|
|
|
90
|
+
@expected_error_codes ||= []
|
|
91
|
+
@expected_error_codes.concat(error_codes)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
failure_message do
|
|
95
|
+
if @result.success?
|
|
96
|
+
"expected interactor to fail, but it succeeded"
|
|
97
|
+
else
|
|
98
|
+
actual_codes = error_codes(@result)
|
|
99
|
+
"expected errors to include #{@expected_error_codes.inspect}, got #{actual_codes.inspect}"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def get_result(actual)
|
|
104
|
+
if actual.is_a?(Class) && actual.ancestors.include?(Interactor)
|
|
105
|
+
actual.call
|
|
106
|
+
else
|
|
107
|
+
actual
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def error_codes(result)
|
|
112
|
+
return [] unless result.errors
|
|
113
|
+
|
|
114
|
+
if result.errors.is_a?(Array)
|
|
115
|
+
result.errors.map { |e| e.is_a?(Hash) ? e[:code] : e.to_s }.compact
|
|
116
|
+
else
|
|
117
|
+
[]
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Matcher for checking if a result has a specific error code
|
|
123
|
+
#
|
|
124
|
+
# @example
|
|
125
|
+
# expect(result).to have_error_code("invalid_input")
|
|
126
|
+
#
|
|
127
|
+
RSpec::Matchers.define :have_error_code do |expected_code|
|
|
128
|
+
match do |result|
|
|
129
|
+
error_codes(result).include?(expected_code)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
failure_message do |result|
|
|
133
|
+
"expected errors to include #{expected_code.inspect}, got #{error_codes(result).inspect}"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def error_codes(result)
|
|
137
|
+
return [] unless result.errors
|
|
138
|
+
|
|
139
|
+
if result.errors.is_a?(Array)
|
|
140
|
+
result.errors.map { |e| e.is_a?(Hash) ? e[:code] : e.to_s }.compact
|
|
141
|
+
else
|
|
142
|
+
[]
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Matcher for checking if a result has multiple error codes
|
|
148
|
+
#
|
|
149
|
+
# @example
|
|
150
|
+
# expect(result).to have_error_codes("error1", "error2")
|
|
151
|
+
#
|
|
152
|
+
RSpec::Matchers.define :have_error_codes do |*expected_codes|
|
|
153
|
+
match do |result|
|
|
154
|
+
actual_codes = error_codes(result)
|
|
155
|
+
expected_codes.all? { |code| actual_codes.include?(code) }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
failure_message do |result|
|
|
159
|
+
"expected errors to include #{expected_codes.inspect}, got #{error_codes(result).inspect}"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def error_codes(result)
|
|
163
|
+
return [] unless result.errors
|
|
164
|
+
|
|
165
|
+
if result.errors.is_a?(Array)
|
|
166
|
+
result.errors.map { |e| e.is_a?(Hash) ? e[:code] : e.to_s }.compact
|
|
167
|
+
else
|
|
168
|
+
[]
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Matcher for checking if context has a specific key/value
|
|
174
|
+
#
|
|
175
|
+
# @example
|
|
176
|
+
# expect(result).to set_context(:data)
|
|
177
|
+
# expect(result).to set_context(:data, expected_value)
|
|
178
|
+
# expect(result).to set_context(:user).to(user)
|
|
179
|
+
#
|
|
180
|
+
RSpec::Matchers.define :set_context do |key, value = nil|
|
|
181
|
+
match do |result|
|
|
182
|
+
return false unless result.respond_to?(key)
|
|
183
|
+
|
|
184
|
+
actual_value = result.public_send(key)
|
|
185
|
+
|
|
186
|
+
if @expected_value
|
|
187
|
+
actual_value == @expected_value
|
|
188
|
+
elsif !value.nil?
|
|
189
|
+
actual_value == value
|
|
190
|
+
else
|
|
191
|
+
!actual_value.nil?
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
chain :to do |expected_value|
|
|
196
|
+
@expected_value = expected_value
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
failure_message do |result|
|
|
200
|
+
if !result.respond_to?(key)
|
|
201
|
+
"expected context to have key #{key.inspect}"
|
|
202
|
+
elsif @expected_value || !value.nil?
|
|
203
|
+
expected = @expected_value || value
|
|
204
|
+
"expected context[#{key.inspect}] to be #{expected.inspect}, got #{result.public_send(key).inspect}"
|
|
205
|
+
else
|
|
206
|
+
"expected context[#{key.inspect}] to be set"
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
RSpec.configure do |config|
|
|
215
|
+
config.include Zenspec::Matchers::InteractorMatchers
|
|
216
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "matchers/interactor_matchers"
|
|
4
|
+
require_relative "matchers/graphql_matchers"
|
|
5
|
+
require_relative "matchers/graphql_type_matchers"
|
|
6
|
+
|
|
7
|
+
module Zenspec
|
|
8
|
+
module Matchers
|
|
9
|
+
# This module serves as a namespace for all Zenspec matchers
|
|
10
|
+
# Individual matcher modules are loaded from their respective files
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Zenspec
|
|
4
|
+
# Docker-style progress loader for displaying progress in terminal
|
|
5
|
+
# Displays progress bars similar to Docker's layer download progress
|
|
6
|
+
#
|
|
7
|
+
# @example Basic usage
|
|
8
|
+
# loader = Zenspec::ProgressLoader.new(total: 10, description: "Running tests")
|
|
9
|
+
# 10.times do |i|
|
|
10
|
+
# loader.update(i + 1)
|
|
11
|
+
# sleep(0.1)
|
|
12
|
+
# end
|
|
13
|
+
# loader.finish
|
|
14
|
+
#
|
|
15
|
+
# @example With custom width
|
|
16
|
+
# loader = Zenspec::ProgressLoader.new(total: 100, width: 50)
|
|
17
|
+
# loader.update(50, description: "Processing files 50/100")
|
|
18
|
+
#
|
|
19
|
+
class ProgressLoader
|
|
20
|
+
attr_reader :current, :total, :width
|
|
21
|
+
|
|
22
|
+
# Default width for the progress bar
|
|
23
|
+
DEFAULT_WIDTH = 40
|
|
24
|
+
|
|
25
|
+
# @param total [Integer] Total number of items to process
|
|
26
|
+
# @param width [Integer] Width of the progress bar in characters
|
|
27
|
+
# @param description [String] Initial description text
|
|
28
|
+
# @param output [IO] Output stream (defaults to STDERR)
|
|
29
|
+
def initialize(total:, width: DEFAULT_WIDTH, description: nil, output: $stderr)
|
|
30
|
+
@total = total
|
|
31
|
+
@width = width
|
|
32
|
+
@current = 0
|
|
33
|
+
@description = description
|
|
34
|
+
@output = output
|
|
35
|
+
@finished = false
|
|
36
|
+
@start_time = Time.now
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Update the progress
|
|
40
|
+
# @param current [Integer] Current progress value
|
|
41
|
+
# @param description [String, nil] Optional description to display
|
|
42
|
+
def update(current, description: nil)
|
|
43
|
+
@current = current
|
|
44
|
+
@description = description if description
|
|
45
|
+
render unless @finished
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Increment progress by one
|
|
49
|
+
# @param description [String, nil] Optional description to display
|
|
50
|
+
def increment(description: nil)
|
|
51
|
+
update(@current + 1, description: description)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Mark the progress as finished
|
|
55
|
+
# @param description [String, nil] Final description to display
|
|
56
|
+
def finish(description: nil)
|
|
57
|
+
@current = @total
|
|
58
|
+
@description = description if description
|
|
59
|
+
@finished = true
|
|
60
|
+
render
|
|
61
|
+
@output.puts # New line after completion
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Calculate current percentage
|
|
65
|
+
# @return [Integer] Percentage (0-100)
|
|
66
|
+
def percentage
|
|
67
|
+
return 100 if @total.zero?
|
|
68
|
+
|
|
69
|
+
((@current.to_f / @total) * 100).round
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Calculate elapsed time
|
|
73
|
+
# @return [Float] Elapsed time in seconds
|
|
74
|
+
def elapsed_time
|
|
75
|
+
Time.now - @start_time
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Calculate estimated time remaining
|
|
79
|
+
# @return [Float, nil] Estimated time remaining in seconds, or nil if cannot estimate
|
|
80
|
+
def estimated_time_remaining
|
|
81
|
+
return nil if @current.zero?
|
|
82
|
+
|
|
83
|
+
elapsed = elapsed_time
|
|
84
|
+
rate = @current.to_f / elapsed
|
|
85
|
+
remaining_items = @total - @current
|
|
86
|
+
remaining_items / rate
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Format time duration
|
|
90
|
+
# @param seconds [Float] Time in seconds
|
|
91
|
+
# @return [String] Formatted time string
|
|
92
|
+
def format_time(seconds)
|
|
93
|
+
return "0s" if seconds.nil? || seconds.zero?
|
|
94
|
+
|
|
95
|
+
if seconds < 60
|
|
96
|
+
"#{seconds.round}s"
|
|
97
|
+
elsif seconds < 3600
|
|
98
|
+
minutes = (seconds / 60).round
|
|
99
|
+
"#{minutes}m"
|
|
100
|
+
else
|
|
101
|
+
hours = (seconds / 3600).round
|
|
102
|
+
"#{hours}h"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# Render the progress bar
|
|
109
|
+
def render
|
|
110
|
+
bar = build_progress_bar
|
|
111
|
+
counter = "#{@current}/#{@total}"
|
|
112
|
+
percent = "#{percentage}%"
|
|
113
|
+
time_info = build_time_info
|
|
114
|
+
|
|
115
|
+
# Build the complete line
|
|
116
|
+
parts = [bar, percent, counter]
|
|
117
|
+
parts << @description if @description
|
|
118
|
+
parts << time_info if time_info && !@finished
|
|
119
|
+
|
|
120
|
+
line = parts.join(" ")
|
|
121
|
+
|
|
122
|
+
# Clear the line and print
|
|
123
|
+
@output.print "\r\e[K#{line}"
|
|
124
|
+
@output.flush
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Build the progress bar string
|
|
128
|
+
# @return [String] Progress bar visualization
|
|
129
|
+
def build_progress_bar
|
|
130
|
+
return "[#{' ' * @width}]" if @total.zero?
|
|
131
|
+
|
|
132
|
+
filled_width = ((@current.to_f / @total) * @width).round
|
|
133
|
+
empty_width = @width - filled_width
|
|
134
|
+
|
|
135
|
+
filled = "=" * [filled_width - 1, 0].max
|
|
136
|
+
arrow = filled_width.positive? ? ">" : ""
|
|
137
|
+
empty = " " * empty_width
|
|
138
|
+
|
|
139
|
+
"[#{filled}#{arrow}#{empty}]"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Build time information string
|
|
143
|
+
# @return [String, nil] Time information or nil
|
|
144
|
+
def build_time_info
|
|
145
|
+
elapsed = elapsed_time
|
|
146
|
+
remaining = estimated_time_remaining
|
|
147
|
+
|
|
148
|
+
if remaining && remaining.positive?
|
|
149
|
+
"#{format_time(elapsed)}/#{format_time(remaining + elapsed)}"
|
|
150
|
+
elsif elapsed > 1 # Only show elapsed if more than 1 second
|
|
151
|
+
format_time(elapsed)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Zenspec
|
|
4
|
+
class Railtie < Rails::Railtie
|
|
5
|
+
railtie_name :zenspec
|
|
6
|
+
|
|
7
|
+
rake_tasks do
|
|
8
|
+
# Add rake tasks if needed in the future
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
initializer "zenspec.configure_rspec" do
|
|
12
|
+
# Automatically configure zenspec matchers and helpers when Rails loads
|
|
13
|
+
if defined?(RSpec)
|
|
14
|
+
RSpec.configure do |config|
|
|
15
|
+
# Include matchers
|
|
16
|
+
config.include Zenspec::Matchers::InteractorMatchers
|
|
17
|
+
config.include Zenspec::Matchers::GraphQLMatchers
|
|
18
|
+
config.include Zenspec::Matchers::GraphQLTypeMatchers
|
|
19
|
+
|
|
20
|
+
# Include helpers
|
|
21
|
+
config.include Zenspec::Helpers::GraphQLHelpers
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Configure Shoulda Matchers if available
|
|
4
|
+
begin
|
|
5
|
+
require "shoulda/matchers"
|
|
6
|
+
|
|
7
|
+
Shoulda::Matchers.configure do |config|
|
|
8
|
+
config.integrate do |with|
|
|
9
|
+
with.test_framework :rspec
|
|
10
|
+
with.library :active_record if defined?(ActiveRecord)
|
|
11
|
+
with.library :active_model if defined?(ActiveModel)
|
|
12
|
+
with.library :action_controller if defined?(ActionController)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
rescue LoadError
|
|
16
|
+
# Shoulda matchers not available, skip configuration
|
|
17
|
+
end
|
data/lib/zenspec.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "zenspec/version"
|
|
4
|
+
require_relative "zenspec/matchers"
|
|
5
|
+
require_relative "zenspec/helpers"
|
|
6
|
+
require_relative "zenspec/shoulda_config"
|
|
7
|
+
require_relative "zenspec/progress_loader"
|
|
8
|
+
|
|
9
|
+
# Load Railtie if Rails is available
|
|
10
|
+
require_relative "zenspec/railtie" if defined?(Rails::Railtie)
|
|
11
|
+
|
|
12
|
+
module Zenspec
|
|
13
|
+
class Error < StandardError; end
|
|
14
|
+
end
|
data/sig/zenspec.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: zenspec
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Wilson Anciro
|
|
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: graphql
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.12'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.12'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: interactor
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '3.0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '3.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rspec
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: shoulda-matchers
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '6.0'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '6.0'
|
|
68
|
+
description: A collection of RSpec matchers for testing GraphQL queries and Interactor
|
|
69
|
+
service objects.
|
|
70
|
+
email:
|
|
71
|
+
- konekred@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- CHANGELOG.md
|
|
77
|
+
- CODE_OF_CONDUCT.md
|
|
78
|
+
- LICENSE.txt
|
|
79
|
+
- README.md
|
|
80
|
+
- Rakefile
|
|
81
|
+
- examples/progress_loader_demo.rb
|
|
82
|
+
- lib/zenspec.rb
|
|
83
|
+
- lib/zenspec/formatters/progress_bar_formatter.rb
|
|
84
|
+
- lib/zenspec/formatters/progress_formatter.rb
|
|
85
|
+
- lib/zenspec/helpers.rb
|
|
86
|
+
- lib/zenspec/helpers/graphql_helpers.rb
|
|
87
|
+
- lib/zenspec/matchers.rb
|
|
88
|
+
- lib/zenspec/matchers/graphql_matchers.rb
|
|
89
|
+
- lib/zenspec/matchers/graphql_type_matchers.rb
|
|
90
|
+
- lib/zenspec/matchers/interactor_matchers.rb
|
|
91
|
+
- lib/zenspec/progress_loader.rb
|
|
92
|
+
- lib/zenspec/railtie.rb
|
|
93
|
+
- lib/zenspec/shoulda_config.rb
|
|
94
|
+
- lib/zenspec/version.rb
|
|
95
|
+
- sig/zenspec.rbs
|
|
96
|
+
homepage: https://github.com/zyxzen/zenspec
|
|
97
|
+
licenses:
|
|
98
|
+
- MIT
|
|
99
|
+
metadata:
|
|
100
|
+
homepage_uri: https://github.com/zyxzen/zenspec
|
|
101
|
+
source_code_uri: https://github.com/zyxzen/zenspec
|
|
102
|
+
changelog_uri: https://github.com/zyxzen/zenspec/blob/main/CHANGELOG.md
|
|
103
|
+
rubygems_mfa_required: 'true'
|
|
104
|
+
rdoc_options: []
|
|
105
|
+
require_paths:
|
|
106
|
+
- lib
|
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: 3.2.0
|
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
requirements: []
|
|
118
|
+
rubygems_version: 3.6.9
|
|
119
|
+
specification_version: 4
|
|
120
|
+
summary: RSpec matchers for GraphQL, Interactor, and other common testing patterns
|
|
121
|
+
test_files: []
|