I'm having this class method on my Post model for getting archives
def self.archives
Post.unscoped.select("YEAR(created_at) AS year, MONTHNAME(created_at) AS month, COUNT(id) AS total")
.group("year, month, MONTH(created_at)")
.order("year DESC, MONTH(created_at) DESC")
end
This is the test I have wrote for my method
context '.archives' do
first = FactoryGirl.create(:post, published_at: Time.zone.now)
second = FactoryGirl.create(:post, published_at: 1.month.ago)
it 'returns articles archived' do
archives = Post.archives()
expect(
[{
year: first.published_at.strftime("%Y"),
month: first.published_at.strftime("%B"),
published: 1
},
{
year: second.published_at.strftime("%Y"),
month: second.published_at.strftime("%B"),
published: 1
}]
).to match_array(archives)
end
end
However I get the following error
expected collection contained: [#<Post id: nil>, #<Post id: nil>]
actual collection contained: [{:year=>"2017", :month=>"October", :published=>1}, {:year=>"2017", :month=>"September", :total=>1}]
the missing elements were: [#<Post id: nil>, #<Post id: nil>]
the extra elements were: [{:year=>"2017", :month=>"October", :total=>1}, {:year=>"2017", :month=>"September", :total=>1}]
So although I have created 2 factories, the archives
array is empty. What am I doing wrong?
Rspec standard is to use the let
syntax for defining variables within a context or describe block. The test should look something like this:
describe '.archives' do
let!(:first) { FactoryGirl.create(:post, published_at: Time.zone.now) }
let!(:second) { FactoryGirl.create(:post, published_at: 1.month.ago) }
it 'returns year, month, and total for articles archived' do
actual_attributes = Post.archives.map { |post| [post.year, post.month, post.total] }
expected_total = 1 # I don't know why the query is returning 1 for total, but including this for completeness
expected_attributes = [first, second].map { |post| [post.created_at.year, post.created_at.strftime("%B"), expected_total] }
expect(actual_attributes).to match_array(expected_attributes)
end
end
The issue here is that you are comparing records pulled with only a few attributes (the result of your SQL query) with fully-formed records (created by your test). This test pulls the applicable attributes from both groups and compares them.