Skip to content

Commit 6143e18

Browse files
committed
Switch to RSpec
We generally use it in our Ruby code. Took the time to write some spec descriptions that may help serve as some documentation as well.
1 parent 794cba3 commit 6143e18

28 files changed

+826
-709
lines changed

Diff for: .codeclimate.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ ratings:
1313
paths:
1414
- "**.rb"
1515
exclude_paths:
16-
- test/
16+
- spec/

Diff for: .rspec

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--color
2+
--require spec_helper

Diff for: Gemfile

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
source "https://rubygems.org"
22

3-
gem "minitest"
4-
gem "mocha"
3+
gem "codeclimate-test-reporter", "1.0.0.pre.rc2"
54
gem "rake"
5+
gem "rspec"
66
gem "simplecov"
7-
gem "codeclimate-test-reporter", "1.0.0.pre.rc2"
87

98
gemspec

Diff for: Rakefile

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
require "bundler/gem_tasks"
2-
require "rake/testtask"
2+
require "rspec/core/rake_task"
33

4-
Rake::TestTask.new do |t|
5-
t.libs.push "lib"
6-
t.ruby_opts = %w[-W0]
7-
t.test_files = FileList["test/*_test.rb"]
8-
t.verbose = true
9-
end
4+
RSpec::Core::RakeTask.new(:spec)
105

11-
task :default => :test
6+
task :default => :spec

Diff for: test/locale/en.yml renamed to spec/locale/en.yml

File renamed without changes.

Diff for: spec/minidoc/associations_spec.rb

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
require "spec_helper"
2+
3+
describe Minidoc::Associations do
4+
class Cat < Minidoc
5+
include Minidoc::Associations
6+
7+
belongs_to :owner, class_name: "User"
8+
end
9+
10+
class Doggie < Minidoc
11+
include Minidoc::Associations
12+
13+
belongs_to :user
14+
end
15+
16+
module Animal
17+
class Armadillo < Minidoc
18+
include Minidoc::Associations
19+
20+
belongs_to :predator
21+
end
22+
23+
class Predator < Minidoc
24+
end
25+
end
26+
27+
describe "dynamically defined association methods" do
28+
it "can load associated documents" do
29+
expect(Cat.new.owner).to be_nil
30+
user = User.create
31+
cat = Cat.new(owner_id: user.id)
32+
expect(cat.owner.id).to eq user.id
33+
cat.save
34+
expect(cat.owner.id).to eq user.id
35+
end
36+
37+
it "caches the association cache rather than go to the database each time" do
38+
user = User.create(name: "Bryan")
39+
cat = Cat.create(owner_id: user.id)
40+
expect(cat.owner.name).to eq "Bryan"
41+
user.set(name: "Noah")
42+
expect(cat.owner.name).to eq "Bryan"
43+
expect(cat.reload.owner.name).to eq "Noah"
44+
end
45+
46+
it "expires the association cache when a new associated document is provided" do
47+
user = User.create(name: "Bryan")
48+
cat = Cat.create(owner_id: user.id)
49+
expect(cat.owner.name).to eq "Bryan"
50+
user.set(name: "Noah")
51+
expect(cat.owner.name).to eq "Bryan"
52+
cat.owner = user
53+
expect(cat.owner.name).to eq "Noah"
54+
end
55+
56+
it "expires the association cache when the related foreign-key id field is updated" do
57+
user = User.create(name: "Bryan")
58+
cat = Cat.create(owner_id: user.id)
59+
expect(cat.owner.name).to eq "Bryan"
60+
user.set(name: "Noah")
61+
expect(cat.owner.name).to eq "Bryan"
62+
cat.owner_id = user.id
63+
expect(cat.owner.name).to eq "Noah"
64+
end
65+
end
66+
67+
context "when the classes are not namespaced" do
68+
it "infers the class name of the association" do
69+
expect(Doggie.new.user).to be_nil
70+
user = User.create
71+
sam = Doggie.new(user_id: user.id)
72+
expect(sam.user.id).to eq user.id
73+
sam.save
74+
expect(sam.user.id).to eq user.id
75+
end
76+
end
77+
78+
context "when the classes are namespaced" do
79+
it "infers the class name of the association" do
80+
expect(Animal::Armadillo.new.predator).to be_nil
81+
predator = Animal::Predator.create
82+
arnie = Animal::Armadillo.new(predator_id: predator.id)
83+
expect(arnie.predator.id).to eq predator.id
84+
arnie.save
85+
expect(arnie.predator.id).to eq predator.id
86+
end
87+
end
88+
end

Diff for: spec/minidoc/connection_spec.rb

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# encoding: utf-8
2+
require "spec_helper"
3+
4+
describe "connection" do
5+
class Company < Minidoc
6+
self.collection_name = "accounts"
7+
end
8+
9+
describe ".collection_name" do
10+
it "is inferred based on the class name" do
11+
expect(User.collection_name).to eq "users"
12+
end
13+
14+
it "can be overridden" do
15+
expect(Company.collection_name).to eq "accounts"
16+
end
17+
end
18+
19+
describe ".collection" do
20+
it "exposes the underlying Mongo object" do
21+
expect(User.collection).to be_a Mongo::Collection
22+
end
23+
24+
it "passes through the collection_name to the underlying Mongo::Collection" do
25+
expect(User.collection.name).to eq "users"
26+
expect(Company.collection.name).to eq "accounts"
27+
end
28+
end
29+
30+
describe ".database" do
31+
it "exposes the underlying Mongo object" do
32+
expect(User.database).to be_a Mongo::DB
33+
end
34+
35+
it "passes through the database name to the underlying Mongo::DB" do
36+
expect(User.database.name).to eq "minidoc_test"
37+
end
38+
end
39+
40+
describe "first run experience" do
41+
it "fails helpfully if you haven't configured the necessary values" do
42+
with_alternative_configuration do
43+
Minidoc.connection = nil
44+
Minidoc.database_name = nil
45+
expect { User.create(name: "Kären") }.to raise_error(Minidoc::MissingConfiguration, "Make sure to set Minidoc.connection")
46+
end
47+
end
48+
49+
it "fails helpfully if you've only neglected the database_name" do
50+
with_alternative_configuration do
51+
Minidoc.database_name = nil
52+
expect { User.create(name: "Kären") }.to raise_error(Minidoc::MissingConfiguration, "Make sure to set Minidoc.database_name")
53+
end
54+
end
55+
end
56+
57+
def with_alternative_configuration
58+
original_connection = Minidoc.connection
59+
original_database_name = Minidoc.database_name
60+
yield
61+
ensure
62+
Minidoc.connection = original_connection
63+
Minidoc.database_name = original_database_name
64+
end
65+
end

Diff for: spec/minidoc/counters_spec.rb

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require "spec_helper"
2+
3+
describe Minidoc::Counters do
4+
class SimpleCounter < Minidoc
5+
include Minidoc::Counters
6+
7+
counter :counter
8+
end
9+
10+
class AdvancedCounter < Minidoc
11+
include Minidoc::Counters
12+
13+
counter :counter, start: 2, step_size: 3
14+
end
15+
16+
describe "#increment_counter" do
17+
it "increments the field" do
18+
x = SimpleCounter.create!
19+
expect(x.counter).to eq 0
20+
expect(x.increment_counter).to eq 1
21+
expect(x.increment_counter).to eq 2
22+
expect(x.increment_counter).to eq 3
23+
expect(x.reload.counter).to eq 3
24+
end
25+
26+
it "can be customized with some options" do
27+
x = AdvancedCounter.create!
28+
expect(x.counter).to eq 2
29+
expect(x.increment_counter).to eq 5
30+
expect(x.increment_counter).to eq 8
31+
expect(x.increment_counter).to eq 11
32+
expect(x.reload.counter).to eq 11
33+
end
34+
35+
it "is thread safe" do
36+
x = SimpleCounter.create!
37+
counters = []
38+
[Thread.new { 5.times { (counters << x.increment_counter) } }, Thread.new { 5.times { (counters << x.increment_counter) } }, Thread.new { 5.times { (counters << x.increment_counter) } }].map(&:join)
39+
expect(counters.uniq.length).to eq 15
40+
end
41+
end
42+
end

Diff for: spec/minidoc/finders_spec.rb

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
require "spec_helper"
2+
3+
describe Minidoc::Finders do
4+
describe ".all" do
5+
it "returns all of the documents in the collection" do
6+
(User.collection << { name: "Joe" })
7+
(User.collection << { name: "Bryan" })
8+
users = User.all
9+
expect(["Bryan", "Joe"]).to match_array(users.map(&:name))
10+
end
11+
end
12+
13+
describe ".count" do
14+
it "counts the documents in the collection" do
15+
(User.collection << { name: "Joe" })
16+
(User.collection << { name: "Bryan" })
17+
expect(User.count).to eq 2
18+
end
19+
20+
it "can be scoped by a query" do
21+
(User.collection << { name: "Joe" })
22+
(User.collection << { name: "Bryan" })
23+
expect(User.count(name: "Bryan")).to eq 1
24+
end
25+
end
26+
27+
describe ".exists?" do
28+
it "tells you if any documents exist that match a query" do
29+
(User.collection << { name: "Joe" })
30+
expect(User.exists?(name: "Joe")).to be(true)
31+
expect(User.exists?(name: "Bryan")).to be(false)
32+
end
33+
end
34+
35+
describe ".first" do
36+
it "returns a document from the collection" do
37+
expect(User.first).to be_nil
38+
user = User.create(name: "Bryan")
39+
expect(User.first.name).to eq "Bryan"
40+
expect(User.first).to eq user
41+
end
42+
end
43+
44+
describe ".find" do
45+
it "querys the collection using the mongodb query language" do
46+
user = User.create(name: "Bryan")
47+
expect(User.find({}).to_a).to eq [user]
48+
expect(User.find(name: "Noah").to_a).to eq []
49+
end
50+
end
51+
52+
describe ".find_one" do
53+
it "returns the first document that matches a query" do
54+
user = User.create(name: "Bryan")
55+
expect(User.find_one({})).to eq user
56+
expect(User.find_one(name: "Noah")).to eq nil
57+
end
58+
end
59+
60+
describe ".find_one!" do
61+
it "returns the first document that matches a query or raises an error" do
62+
user = User.create(name: "Bryan")
63+
expect(User.find_one!(name: "Bryan")).to eq user
64+
expect { User.find_one!(name: "Noah") }.to raise_error(Minidoc::DocumentNotFoundError)
65+
end
66+
end
67+
68+
describe ".find_one_or_initialize" do
69+
it "returns the first document that matches a query or makes a non-persisted document from that query" do
70+
user = User.create(name: "Bryan", age: 1)
71+
expect((user == User.find_one_or_initialize(name: "Bryan"))).to be_truthy
72+
expect(User.find_one_or_initialize(name: "Noah").is_a?(User)).to eq true
73+
expect(User.find_one_or_initialize(name: "Noah").new_record?).to eq true
74+
end
75+
76+
it "allows query options" do
77+
user = User.create(name: "Noah", age: 1)
78+
expect((user == User.find_one_or_initialize({ age: 1 }, sort: { name: -1 }))).to be_truthy
79+
expect { User.find_one_or_initialize("foo") }.to raise_error(ArgumentError)
80+
end
81+
end
82+
end

Diff for: spec/minidoc/grid_spec.rb

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
require "spec_helper"
2+
3+
describe Minidoc::Grid do
4+
let(:grid) { Minidoc::Grid.new(Minidoc.database) }
5+
6+
describe "#put and #get" do
7+
it "can store raw string data" do
8+
doc_id = grid.put "estamos en espana"
9+
expect(doc_id).to be_a BSON::ObjectId
10+
11+
document = grid.get doc_id.to_s
12+
13+
expect(document).to be_a Mongo::GridIO
14+
expect(document.read).to eq "estamos en espana"
15+
end
16+
end
17+
18+
describe "#get_json" do
19+
it "parses the JSON into structured ruby objects" do
20+
hash = { "foo" => { "bar" => 1 } }
21+
doc_id = grid.put(hash.to_json)
22+
23+
value = grid.get_json(doc_id.to_s)
24+
25+
expect(value).to eq hash
26+
end
27+
end
28+
29+
describe "#delete" do
30+
it "removes the 'file' from the database" do
31+
doc_id = grid.put "estamos en espana"
32+
33+
grid.delete doc_id.to_s
34+
35+
expect { grid.get doc_id }.to raise_error(Mongo::GridFileNotFound)
36+
end
37+
end
38+
end

Diff for: spec/minidoc/read_only_spec.rb

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
require "spec_helper"
2+
3+
describe Minidoc::ReadOnly do
4+
class ReadOnlyUser < Minidoc::ReadOnly
5+
self.collection_name = "users"
6+
attribute :name, String
7+
end
8+
9+
it "is read only, meaning it can't change over time" do
10+
expect { ReadOnlyUser.create(name: "Bryan") }.to raise_error(NoMethodError)
11+
12+
rw_user = User.create(name: "Bryan")
13+
user = ReadOnlyUser.first
14+
expect(user.name).to eq "Bryan"
15+
expect(rw_user.id).to eq user.id
16+
expect(user).to eq user.as_value
17+
18+
expect { user.name = "Noah" }.to raise_error(NoMethodError)
19+
end
20+
21+
it "can become a value object" do
22+
user = User.new(name: "Bryan")
23+
user.name = "Noah"
24+
user = user.as_value
25+
26+
expect { user.name = "Noah" }.to raise_error(NoMethodError)
27+
end
28+
end

0 commit comments

Comments
 (0)