Module: Kensho

Defined in:
lib/kensho/rspec/state.rb,
lib/kensho/rspec.rb,
lib/kensho/_schema.rb,
lib/kensho/rspec/helpers.rb,
lib/kensho/rspec/helpers.rb,
lib/kensho/rspec/version.rb,
lib/kensho/rspec/formatter.rb

Overview

Hook into RSpec’s example-group definition so we can track the currently-defining group. RSpec calls ‘subclass` for every nested describe; we wrap it to push/pop a stack on the State module.

Defined Under Namespace

Modules: RSpec, Schema

Class Method Summary collapse

Class Method Details

.apply_behavior(key, value) ⇒ Object



260
261
262
263
264
265
266
# File 'lib/kensho/rspec/helpers.rb', line 260

def self.apply_behavior(key, value)
  group = Kensho::RSpec::State.current_group
  return unless group

  group.[key] = value.to_s
  nil
end

.attach(path, kind: nil, name: nil, mime_type: nil) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/kensho/rspec/helpers.rb', line 65

def attach(path, kind: nil, name: nil, mime_type: nil)
  scratch = Kensho::RSpec::State.current
  formatter = Kensho::RSpec::State.formatter
  return nil unless scratch && formatter

  record = formatter.register_attachment(
    scratch,
    path.to_s,
    kind: kind,
    name: name,
    mime_type: mime_type
  )
  return nil unless record

  if scratch.step_stack.last
    (scratch.step_stack.last['attachments'] ||= []) << record
  else
    scratch.attachments << record
  end
  record
end

.current_case_idObject



206
207
208
209
# File 'lib/kensho/rspec/helpers.rb', line 206

def current_case_id
  scratch = Kensho::RSpec::State.current
  scratch ? scratch.case_id : nil
end

.description(text) ⇒ Object

Set case.description.



149
150
151
152
153
154
155
# File 'lib/kensho/rspec/helpers.rb', line 149

def description(text)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil? || text.nil?

  scratch.description = text.to_s
  nil
end

.epic(name) ⇒ Object

behavior.epic + labels.epic



114
115
116
# File 'lib/kensho/rspec/helpers.rb', line 114

def epic(name)
  apply_behavior_runtime('epic', 'epic', name)
end

.Epic(name) ⇒ Object



252
253
254
# File 'lib/kensho/rspec/helpers.rb', line 252

def self.Epic(name)
  apply_behavior(:kensho_epic, name)
end

.feature(name) ⇒ Object

behavior.feature + labels.feature



119
120
121
# File 'lib/kensho/rspec/helpers.rb', line 119

def feature(name)
  apply_behavior_runtime('feature', 'feature', name)
end

.Feature(name) ⇒ Object

Top-level sugar so spec authors can write ‘Kensho::Feature(’Cart’)‘ etc. inside a describe block. These are module methods (uppercase method names are legal in Ruby) that walk the binding to find the example group whose `describe` block is currently executing and set metadata on it.



248
249
250
# File 'lib/kensho/rspec/helpers.rb', line 248

def self.Feature(name)
  apply_behavior(:kensho_feature, name)
end

.flakyObject

Mark the running case as flaky.



179
180
181
182
183
184
185
# File 'lib/kensho/rspec/helpers.rb', line 179

def flaky
  scratch = Kensho::RSpec::State.current
  return if scratch.nil?

  scratch.flaky = true
  nil
end

A Jira/issue link. ‘id_or_url` may be a bare ticket id (’PROJ-1’) or a full URL. Kind ‘issue’.



104
105
106
# File 'lib/kensho/rspec/helpers.rb', line 104

def jira_link(id_or_url, label = nil)
  add_link(id_or_url, kind: 'issue', label: label || id_or_url)
end

.known_issue(id_or_url, label = nil) ⇒ Object

A known issue: mutes the case and records an ‘issue’ link.



197
198
199
200
201
202
203
204
# File 'lib/kensho/rspec/helpers.rb', line 197

def known_issue(id_or_url, label = nil)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil?

  scratch.muted = true
  jira_link(id_or_url, label)
  nil
end

.label(key, value) ⇒ Object



87
88
89
90
91
92
93
# File 'lib/kensho/rspec/helpers.rb', line 87

def label(key, value)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil? || key.nil? || key.to_s.empty?

  scratch.labels[key.to_s] = value.to_s
  nil
end

Add a hyperlink to the running case. Positional ‘name` is the human label (legacy `label:`/`kind:` keywords still work). Default kind is ’link’.



98
99
100
# File 'lib/kensho/rspec/helpers.rb', line 98

def link(url, name = nil, kind: nil, label: nil)
  add_link(url, kind: kind || 'link', label: name || label)
end

.mutedObject

Mark the running case as muted (known failure not counted by the gate).



188
189
190
191
192
193
194
# File 'lib/kensho/rspec/helpers.rb', line 188

def muted
  scratch = Kensho::RSpec::State.current
  return if scratch.nil?

  scratch.muted = true
  nil
end

.owner(value) ⇒ Object

Set case.owner.



140
141
142
143
144
145
146
# File 'lib/kensho/rspec/helpers.rb', line 140

def owner(value)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil? || value.nil?

  scratch.owner = value.to_s
  nil
end

.parameter(name, value) ⇒ Object

Add a parameter (name/value) to the running case. No kind.



170
171
172
173
174
175
176
# File 'lib/kensho/rspec/helpers.rb', line 170

def parameter(name, value)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil? || name.nil? || name.to_s.empty?

  scratch.parameters << { 'name' => name.to_s, 'value' => value.to_s }
  nil
end

A reference/documentation link. Kind ‘reference’.



109
110
111
# File 'lib/kensho/rspec/helpers.rb', line 109

def reference_link(url, label = nil)
  add_link(url, kind: 'reference', label: label)
end

.severity(value) ⇒ Object

Set case.severity. Only the five canonical names are accepted; anything else is ignored.



130
131
132
133
134
135
136
137
# File 'lib/kensho/rspec/helpers.rb', line 130

def severity(value)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil? || value.nil?

  v = value.to_s
  scratch.severity = v if Kensho::Schema::SEVERITY.include?(v)
  nil
end

.step(title, action: nil) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/kensho/rspec/helpers.rb', line 23

def step(title, action: nil)
  scratch = Kensho::RSpec::State.current
  unless scratch
    return yield({}) if block_given?

    return {}
  end

  started_perf = monotonic_now
  step_obj = {
    'id'        => "step_#{SecureRandom.hex(5)}",
    'title'     => title.to_s,
    'status'    => 'pass',
    'startedAt' => Kensho::Schema.iso_now,
    'duration'  => 0,
    '_started_perf' => started_perf
  }
  step_obj['action'] = action.to_s if action

  parent = scratch.step_stack.last
  if parent
    (parent['children'] ||= []) << step_obj
  else
    scratch.steps << step_obj
  end
  scratch.step_stack << step_obj

  result = nil
  begin
    result = block_given? ? yield(step_obj) : nil
  rescue StandardError, ::RSpec::Expectations::ExpectationNotMetError => e
    step_obj['status'] = 'fail'
    close_step!(step_obj, started_perf)
    scratch.step_stack.pop if scratch.step_stack.last.equal?(step_obj)
    raise e
  end

  close_step!(step_obj, started_perf)
  scratch.step_stack.pop if scratch.step_stack.last.equal?(step_obj)
  result
end

.story(name) ⇒ Object

behavior.scenario + labels.story



124
125
126
# File 'lib/kensho/rspec/helpers.rb', line 124

def story(name)
  apply_behavior_runtime('scenario', 'story', name)
end

.Story(name) ⇒ Object



256
257
258
# File 'lib/kensho/rspec/helpers.rb', line 256

def self.Story(name)
  apply_behavior(:kensho_story, name)
end

.tag(name) ⇒ Object

Add a tag to the running case. Strips a leading ‘@’ and de-dupes.



158
159
160
161
162
163
164
165
166
167
# File 'lib/kensho/rspec/helpers.rb', line 158

def tag(name)
  scratch = Kensho::RSpec::State.current
  return if scratch.nil? || name.nil?

  t = name.to_s.sub(/\A@/, '')
  return if t.empty?

  scratch.tags << t unless scratch.tags.include?(t)
  nil
end