Skip to content

Commit 79e722d

Browse files
committed
Add let! and subject! to RSpec adapter
- Implement let! for eagerly-evaluated memoized helpers - Implement subject! for eagerly-evaluated subjects - Support inheritance of eager lets from parent describe blocks - Reorganize tests into folders (one describe per file)
1 parent e3f67f1 commit 79e722d

5 files changed

Lines changed: 193 additions & 1 deletion

File tree

lib/quickdraw/rspec/spec.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,15 @@ def it(description, &)
3232
end
3333

3434
def subject(name = nil, &)
35-
let("subject", &)
35+
let(:subject, &)
3636
let(name, &) if name
3737
end
3838

39+
def subject!(name = nil, &)
40+
let!(:subject, &)
41+
let!(name, &) if name
42+
end
43+
3944
def let(name, &block)
4045
instance_variable = :"@#{name}"
4146

@@ -47,12 +52,31 @@ def let(name, &block)
4752
end
4853
end
4954
end
55+
56+
def let!(name, &)
57+
let(name, &)
58+
own_eager_lets << name
59+
end
60+
61+
def eager_lets
62+
parent = superclass.respond_to?(:eager_lets) ? superclass.eager_lets : []
63+
parent + own_eager_lets
64+
end
65+
66+
def own_eager_lets
67+
@eager_lets ||= []
68+
end
5069
end
5170

5271
def described_class
5372
self.class.described_class
5473
end
5574

75+
def setup
76+
super
77+
self.class.eager_lets.each { |name| send(name) }
78+
end
79+
5680
def expect(subject)
5781
Quickdraw::RSpec::Expectation.new(subject, context: self)
5882
end

test/rspec/let/let.test.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# frozen_string_literal: true
2+
3+
require "quickdraw/rspec"
4+
5+
Quickdraw::RSpec.describe "let" do
6+
let(:value) { "hello" }
7+
8+
it "provides the value" do
9+
expect(value).to eq("hello")
10+
end
11+
12+
it "memoizes the value" do
13+
expect(value).to equal(value)
14+
end
15+
16+
describe "with a counter" do
17+
let(:counter) { @count ||= 0; @count += 1 }
18+
19+
it "is lazy - not evaluated until called" do
20+
# counter not called yet, so @count should be nil
21+
expect(@count).to be_nil
22+
expect(counter).to eq(1)
23+
end
24+
25+
it "memoizes across multiple calls in same test" do
26+
expect(counter).to eq(1)
27+
expect(counter).to eq(1)
28+
expect(counter).to eq(1)
29+
end
30+
end
31+
32+
describe "inheritance" do
33+
let(:inherited) { "parent" }
34+
35+
describe "nested" do
36+
it "inherits let from parent" do
37+
expect(inherited).to eq("parent")
38+
end
39+
end
40+
41+
describe "override" do
42+
let(:inherited) { "child" }
43+
44+
it "can override parent let" do
45+
expect(inherited).to eq("child")
46+
end
47+
end
48+
end
49+
50+
describe "referencing other lets" do
51+
let(:first) { "hello" }
52+
let(:second) { "#{first} world" }
53+
54+
it "can reference other let values" do
55+
expect(second).to eq("hello world")
56+
end
57+
end
58+
end

test/rspec/let/let_bang.test.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
require "quickdraw/rspec"
4+
5+
Quickdraw::RSpec.describe "let!" do
6+
let!(:eager_value) { @evaluated = true; "eager" }
7+
8+
it "is evaluated before the test runs" do
9+
expect(@evaluated).to eq(true)
10+
end
11+
12+
it "provides the value" do
13+
expect(eager_value).to eq("eager")
14+
end
15+
16+
it "memoizes the value" do
17+
expect(eager_value).to equal(eager_value)
18+
end
19+
20+
describe "inheritance" do
21+
let!(:parent_eager) { @parent_evaluated = true; "parent" }
22+
23+
describe "nested" do
24+
it "inherits let! from parent and evaluates it" do
25+
expect(@parent_evaluated).to eq(true)
26+
expect(parent_eager).to eq("parent")
27+
end
28+
end
29+
end
30+
end

test/rspec/subject/subject.test.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# frozen_string_literal: true
2+
3+
require "quickdraw/rspec"
4+
5+
Quickdraw::RSpec.describe "subject" do
6+
subject { "the subject" }
7+
8+
it "provides the subject" do
9+
expect(subject).to eq("the subject")
10+
end
11+
12+
it "memoizes the subject" do
13+
expect(subject).to equal(subject)
14+
end
15+
16+
describe "named subject" do
17+
subject(:my_string) { "named" }
18+
19+
it "provides subject" do
20+
expect(subject).to eq("named")
21+
end
22+
23+
it "provides named accessor" do
24+
expect(my_string).to eq("named")
25+
end
26+
27+
it "named accessor equals subject" do
28+
expect(my_string).to equal(subject)
29+
end
30+
end
31+
32+
describe "inheritance" do
33+
subject { "parent subject" }
34+
35+
describe "nested" do
36+
it "inherits subject from parent" do
37+
expect(subject).to eq("parent subject")
38+
end
39+
end
40+
41+
describe "override" do
42+
subject { "child subject" }
43+
44+
it "can override parent subject" do
45+
expect(subject).to eq("child subject")
46+
end
47+
end
48+
end
49+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require "quickdraw/rspec"
4+
5+
Quickdraw::RSpec.describe "subject!" do
6+
subject! { @evaluated = true; "eager subject" }
7+
8+
it "is evaluated before the test runs" do
9+
expect(@evaluated).to eq(true)
10+
end
11+
12+
it "provides the subject" do
13+
expect(subject).to eq("eager subject")
14+
end
15+
16+
describe "named subject!" do
17+
subject!(:my_eager) { @named_evaluated = true; "named eager" }
18+
19+
it "is evaluated before the test runs" do
20+
expect(@named_evaluated).to eq(true)
21+
end
22+
23+
it "provides subject" do
24+
expect(subject).to eq("named eager")
25+
end
26+
27+
it "provides named accessor" do
28+
expect(my_eager).to eq("named eager")
29+
end
30+
end
31+
end

0 commit comments

Comments
 (0)