DEV: Improve flaky time-sensitive specs (#9141)

This commit is contained in:
Jarek Radosz 2020-03-10 22:13:17 +01:00 committed by GitHub
parent f795c1b8e8
commit 29b35aa64c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 334 additions and 331 deletions

View File

@ -11,7 +11,6 @@ describe PostsController do
end
describe "polls" do
it "works" do
post :create, params: {
title: title, raw: "[poll]\n- A\n- B\n[/poll]"
@ -39,7 +38,7 @@ describe PostsController do
it "schedules auto-close job" do
freeze_time
name = "auto_close"
close_date = 1.month.from_now
close_date = 1.month.from_now.round
expect do
post :create, params: {
@ -53,7 +52,7 @@ describe PostsController do
json = ::JSON.parse(response.body)
post_id = json["id"]
expect(Poll.find_by(post_id: post_id).close_at).to be_within_one_second_of(1.month.from_now)
expect(Poll.find_by(post_id: post_id).close_at).to eq_time(close_date)
job = Jobs::ClosePoll.jobs.first
job_args = job["args"].first

View File

@ -267,7 +267,7 @@ RSpec.describe MigratePollsData do
poll = Poll.find_by(name: "poll")
expect(poll.post_id).to eq(post.id)
expect(poll.close_at).to eq("2018-10-08T00:00:00.000Z")
expect(poll.close_at).to eq_time(Time.parse("2018-10-08T00:00:00.000Z"))
expect(poll.regular?).to eq(true)
expect(poll.open?).to eq(true)

View File

@ -411,7 +411,7 @@ describe Auth::DefaultCurrentUserProvider do
provider2 = provider("/", "HTTP_COOKIE" => "_t=#{unhashed_token}")
u = provider2.current_user
u.reload
expect(u.last_seen_at).to eq_time(Time.now)
expect(u.last_seen_at).to eq_time(Time.zone.now)
freeze_time 20.minutes.from_now

View File

@ -157,9 +157,11 @@ describe ComposerMessagesFinder do
SiteSetting.educate_until_posts = 10
user.stubs(:post_count).returns(11)
freeze_time(5.minutes.ago) do
Fabricate(:post, topic: topic, user: user)
Fabricate(:post, topic: topic, user: user)
Fabricate(:post, topic: topic, user: user, post_type: Post.types[:small_action])
end
SiteSetting.sequential_replies_threshold = 2
end

View File

@ -69,7 +69,7 @@ RSpec.describe SecondFactorManager do
token = user.user_second_factors.totps.first.totp_object.now
expect(user.authenticate_totp(token)).to eq(true)
expect(user.user_second_factors.totps.first.last_used).to eq_time(DateTime.now)
expect(user.user_second_factors.totps.first.last_used).to eq_time(Time.zone.now)
expect(user.authenticate_totp(token)).to eq(false)
end
end

View File

@ -1777,14 +1777,14 @@ describe CookedPostProcessor do
small_action = Fabricate(:post, topic: topic, post_type: Post.types[:small_action])
reply = Fabricate(:post, topic: topic, raw: raw)
freeze_time Time.zone.now do
freeze_time do
topic.bumped_at = 1.day.ago
CookedPostProcessor.new(reply).remove_full_quote_on_direct_reply
expect(topic.ordered_posts.pluck(:id))
.to eq([post.id, hidden.id, small_action.id, reply.id])
expect(topic.bumped_at).to eq(1.day.ago)
expect(topic.bumped_at).to eq_time(1.day.ago)
expect(reply.raw).to eq("and this is the third reply")
expect(reply.revisions.count).to eq(1)
expect(reply.revisions.first.modifications["raw"]).to eq([raw, reply.raw])

View File

@ -24,7 +24,8 @@ describe DiscourseUpdates do
context 'a good version check request happened recently' do
context 'and server is up-to-date' do
before { stub_data(Discourse::VERSION::STRING, 0, false, 12.hours.ago) }
let(:time) { 12.hours.ago }
before { stub_data(Discourse::VERSION::STRING, 0, false, time) }
it 'returns all the version fields' do
expect(subject.latest_version).to eq(Discourse::VERSION::STRING)
@ -35,12 +36,13 @@ describe DiscourseUpdates do
end
it 'returns the timestamp of the last version check' do
expect(subject.updated_at).to be_within_one_second_of(12.hours.ago)
expect(subject.updated_at).to eq_time(time)
end
end
context 'and server is not up-to-date' do
before { stub_data('0.9.0', 2, false, 12.hours.ago) }
let(:time) { 12.hours.ago }
before { stub_data('0.9.0', 2, false, time) }
it 'returns all the version fields' do
expect(subject.latest_version).to eq('0.9.0')
@ -50,7 +52,7 @@ describe DiscourseUpdates do
end
it 'returns the timestamp of the last version check' do
expect(subject.updated_at).to be_within_one_second_of(12.hours.ago)
expect(subject.updated_at).to eq_time(time)
end
end
end

View File

@ -99,7 +99,7 @@ describe DistributedMutex do
}.to raise_error(Discourse::ReadOnly)
expect(done).to eq(false)
expect(Time.now - start).to be < (1.second)
expect(Time.now - start).to be <= 1.second
end
end

View File

@ -656,8 +656,11 @@ describe Email::Receiver do
end
it "ensures posts aren't dated in the future" do
# PostCreator doesn't provide sub-second accuracy for created_at
now = freeze_time Time.zone.now.round
expect { process(:from_the_future) }.to change { topic.posts.count }
expect(topic.posts.last.created_at).to be_within(1.minute).of(DateTime.now)
expect(topic.posts.last.created_at).to eq_time(now)
end
it "accepts emails with wrong reply key if the system knows about the forwarded email" do

View File

@ -145,6 +145,7 @@ describe PostActionCreator do
before { reviewable.perform(admin, :ignore) }
it "fails because the post was recently reviewed" do
freeze_time 10.seconds.from_now
result = PostActionCreator.create(user, post, :inappropriate)
expect(result.success?).to eq(false)

View File

@ -145,8 +145,14 @@ describe PostCreator do
_reply = PostCreator.new(admin, raw: "this is my test reply 123 testing", topic_id: created_post.topic_id).create
end
messages.filter! { |m| m.channel != "/distributed_hash" }
channels = messages.map { |m| m.channel }.sort
# 2 for topic, one to notify of new topic another for tracking state
expect(messages.map { |m| m.channel }.sort).to eq([ "/new",
expect(channels).to eq(
[
"/new",
"/u/#{admin.username}",
"/u/#{admin.username}",
"/unread/#{admin.id}",
@ -155,9 +161,10 @@ describe PostCreator do
"/latest",
"/topic/#{created_post.topic_id}",
"/topic/#{created_post.topic_id}"
].sort)
admin_ids = [Group[:admins].id]
].sort
)
admin_ids = [Group[:admins].id]
expect(messages.any? { |m| m.group_ids != admin_ids && m.user_ids != [admin.id] }).to eq(false)
end
@ -312,7 +319,7 @@ describe PostCreator do
first_post = creator.create
topic = first_post.topic.reload
expect(topic.last_posted_at).to be_within(1.seconds).of(first_post.created_at)
expect(topic.last_posted_at).to eq_time(first_post.created_at)
expect(topic.last_post_user_id).to eq(first_post.user_id)
expect(topic.word_count).to eq(4)
end
@ -351,8 +358,8 @@ describe PostCreator do
topic.reload
topic_status_update = TopicTimer.last
expect(topic_status_update.execute_at).to be_within(1.second).of(Time.zone.now + 12.hours)
expect(topic_status_update.created_at).to be_within(1.second).of(Time.zone.now)
expect(topic_status_update.execute_at).to eq_time(12.hours.from_now)
expect(topic_status_update.created_at).to eq_time(Time.zone.now)
end
describe "topic's auto close based on last post" do
@ -484,7 +491,6 @@ describe PostCreator do
fab!(:topic) { Fabricate(:topic, user: user) }
it 'whispers do not mess up the public view' do
# turns out this can fail on leap years if we don't do this
freeze_time DateTime.parse('2010-01-01 12:00')
@ -538,7 +544,7 @@ describe PostCreator do
expect(topic.reply_count).to eq(0)
expect(topic.posts_count).to eq(1)
expect(topic.highest_staff_post_number).to eq(3)
expect(topic.last_posted_at).to be_within(1.seconds).of(first.created_at)
expect(topic.last_posted_at).to eq_time(first.created_at)
expect(topic.last_post_user_id).to eq(first.user_id)
expect(topic.word_count).to eq(5)
@ -554,7 +560,7 @@ describe PostCreator do
topic.reload
expect(topic.highest_post_number).to eq(1)
expect(topic.posts_count).to eq(1)
expect(topic.last_posted_at).to eq(first.created_at)
expect(topic.last_posted_at).to eq_time(first.created_at)
expect(topic.highest_staff_post_number).to eq(3)
end
end
@ -684,7 +690,7 @@ describe PostCreator do
post = creator.create
topic.reload
expect(topic.last_posted_at).to be_within(1.seconds).of(post.created_at)
expect(topic.last_posted_at).to eq_time(post.created_at)
expect(topic.last_post_user_id).to eq(post.user_id)
expect(topic.word_count).to eq(6)
end
@ -695,7 +701,7 @@ describe PostCreator do
post = creator.create
topic.reload
expect(topic.last_posted_at).to be_within(1.seconds).of(post.created_at)
expect(topic.last_posted_at).to eq_time(post.created_at)
expect(topic.last_post_user_id).to eq(post.user_id)
expect(topic.word_count).to eq(6)
end
@ -960,9 +966,9 @@ describe PostCreator do
created_at: 1.week.ago
)
expect(post1.created_at).to be_within(1.second).of(1.week.ago)
expect(post2.created_at).to be_within(1.second).of(1.week.ago)
expect(topic.created_at).to be_within(1.second).of(1.week.ago)
expect(post1.created_at).to eq_time(1.week.ago)
expect(post2.created_at).to eq_time(1.week.ago)
expect(topic.created_at).to eq_time(1.week.ago)
end
it 'supports strings' do
@ -983,9 +989,9 @@ describe PostCreator do
created_at: '2019-09-02 00:00:00 UTC'
)
expect(post1.created_at).to be_within(1.second).of(time)
expect(post2.created_at).to be_within(1.second).of(time)
expect(topic.created_at).to be_within(1.second).of(time)
expect(post1.created_at).to eq_time(time)
expect(post2.created_at).to eq_time(time)
expect(topic.created_at).to eq_time(time)
end
end

View File

@ -138,7 +138,7 @@ describe PostRevisor do
expect(post.version).to eq(1)
expect(post.public_version).to eq(1)
expect(post.revisions.size).to eq(0)
expect(post.last_version_at).to eq(first_version_at)
expect(post.last_version_at).to eq_time(first_version_at)
expect(subject.category_changed).to be_blank
end
@ -209,6 +209,7 @@ describe PostRevisor do
end
it "resets the edit_reason attribute in post model" do
freeze_time
SiteSetting.editing_grace_period = 5
post = Fabricate(:post, raw: 'hello world')
revisor = PostRevisor.new(post)
@ -216,7 +217,7 @@ describe PostRevisor do
post.reload
expect(post.edit_reason).to eq('this is my reason')
revisor.revise!(post.user, { raw: 'hello world4321' }, revised_at: post.updated_at + 6.second)
revisor.revise!(post.user, { raw: 'hello world4321' }, revised_at: post.updated_at + 7.seconds)
post.reload
expect(post.edit_reason).not_to be_present
end

View File

@ -374,9 +374,9 @@ describe Search do
context 'search within topic' do
def new_post(raw, topic = nil)
def new_post(raw, topic = nil, created_at: nil)
topic ||= Fabricate(:topic)
Fabricate(:post, topic: topic, topic_id: topic.id, user: topic.user, raw: raw)
Fabricate(:post, topic: topic, topic_id: topic.id, user: topic.user, raw: raw, created_at: created_at)
end
it 'works in Chinese' do
@ -391,13 +391,13 @@ describe Search do
topic = Fabricate(:topic)
topic2 = Fabricate(:topic)
new_post('this is the other post I am posting', topic2)
new_post('this is my fifth post I am posting', topic2)
new_post('this is the other post I am posting', topic2, created_at: 6.minutes.ago)
new_post('this is my fifth post I am posting', topic2, created_at: 5.minutes.ago)
post1 = new_post('this is the other post I am posting', topic)
post2 = new_post('this is my first post I am posting', topic)
post3 = new_post('this is a real long and complicated bla this is my second post I am Posting birds with more stuff bla bla', topic)
post4 = new_post('this is my fourth post I am posting', topic)
post1 = new_post('this is the other post I am posting', topic, created_at: 4.minutes.ago)
post2 = new_post('this is my first post I am posting', topic, created_at: 3.minutes.ago)
post3 = new_post('this is a real long and complicated bla this is my second post I am Posting birds with more stuff bla bla', topic, created_at: 2.minutes.ago)
post4 = new_post('this is my fourth post I am posting', topic, created_at: 1.minute.ago)
# update posts_count
topic.reload
@ -681,8 +681,8 @@ describe Search do
it "should return posts in the right order" do
raw = "The pure genuine evian"
post = Fabricate(:post, topic: category.topic, raw: raw)
post2 = Fabricate(:post, topic: category2.topic, raw: raw)
post = freeze_time(10.seconds.from_now) { Fabricate(:post, topic: category.topic, raw: raw) }
post2 = freeze_time(20.seconds.from_now) { Fabricate(:post, topic: category2.topic, raw: raw) }
search = Search.execute(raw)
@ -1145,9 +1145,8 @@ describe Search do
it 'can find by latest' do
topic1 = Fabricate(:topic, title: 'I do not like that Sam I am')
post1 = Fabricate(:post, topic: topic1)
post2 = Fabricate(:post, raw: 'that Sam I am, that Sam I am')
post1 = Fabricate(:post, topic: topic1, created_at: 10.minutes.ago)
post2 = Fabricate(:post, raw: 'that Sam I am, that Sam I am', created_at: 5.minutes.ago)
expect(Search.execute('sam').posts.map(&:id)).to eq([post1.id, post2.id])
expect(Search.execute('sam order:latest').posts.map(&:id)).to eq([post2.id, post1.id])
@ -1332,8 +1331,8 @@ describe Search do
cat1 = Fabricate(:category_with_definition, name: 'food')
topic6 = Fabricate(:topic, tags: [tag1, tag2], category: cat1)
topic7 = Fabricate(:topic, tags: [tag1, tag2, tag3], category: cat1)
post7 = Fabricate(:post, topic: topic6, raw: "Wakey, wakey, eggs and bakey.", like_count: 5)
post8 = Fabricate(:post, topic: topic7, raw: "Bakey, bakey, eggs to makey.", like_count: 2)
post7 = Fabricate(:post, topic: topic6, raw: "Wakey, wakey, eggs and bakey.", like_count: 5, created_at: 2.minutes.ago)
post8 = Fabricate(:post, topic: topic7, raw: "Bakey, bakey, eggs to makey.", like_count: 2, created_at: 1.minute.ago)
expect(Search.execute('bakey tags:lunch order:latest').posts.map(&:id))
.to eq([post8.id, post7.id])

View File

@ -246,8 +246,8 @@ describe TopicCreator do
pinned_at: 3.days.ago
))
expect(topic.created_at).to be_within(1.second).of(1.week.ago)
expect(topic.pinned_at).to be_within(1.second).of(3.days.ago)
expect(topic.created_at).to eq_time(1.week.ago)
expect(topic.pinned_at).to eq_time(3.days.ago)
end
it 'supports strings' do
@ -261,8 +261,8 @@ describe TopicCreator do
pinned_at: '2020-03-10 15:17'
))
expect(topic.created_at).to be_within(1.second).of(time1)
expect(topic.pinned_at).to be_within(1.second).of(time2)
expect(topic.created_at).to eq_time(time1)
expect(topic.pinned_at).to eq_time(time2)
end
end
end

View File

@ -33,8 +33,8 @@ describe TopicPublisher do
topic.reload
expect(topic.category).to eq(category)
expect(topic).to be_visible
expect(topic.created_at).to eq(published_at)
expect(topic.updated_at).to eq(published_at)
expect(topic.created_at).to eq_time(published_at)
expect(topic.updated_at).to eq_time(published_at)
expect(topic.shared_draft).to be_blank
expect(UserHistory.where(
@ -48,9 +48,9 @@ describe TopicPublisher do
expect(op.revisions.size).to eq(0)
expect(op.version).to eq(1)
expect(op.public_version).to eq(1)
expect(op.created_at).to eq(published_at)
expect(op.updated_at).to eq(published_at)
expect(op.last_version_at).to eq(published_at)
expect(op.created_at).to eq_time(published_at)
expect(op.updated_at).to eq_time(published_at)
expect(op.last_version_at).to eq_time(published_at)
end
end
end

View File

@ -75,15 +75,13 @@ describe TopicQuery do
end
context "prioritize_pinned_topics" do
it "does the pagination correctly" do
num_topics = 15
per_page = 3
topics = []
(num_topics - 1).downto(0).each do |i|
topics[i] = Fabricate(:topic)
topics[i] = freeze_time(i.seconds.ago) { Fabricate(:topic) }
end
topic_query = TopicQuery.new(user)
@ -99,7 +97,6 @@ describe TopicQuery do
page: 1)
).to eq(topics[per_page...num_topics])
end
end
context 'bookmarks' do
@ -926,7 +923,7 @@ describe TopicQuery do
let!(:user) { group_user }
it 'should return the group topics' do
expect(suggested_topics).to eq([private_group_topic.id, private_message.id])
expect(suggested_topics).to match_array([private_group_topic.id, private_message.id])
end
end

View File

@ -41,7 +41,7 @@ describe Topic do
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
expect(topic.public_topic_timer.execute_at).to be_within_one_second_of(2.hours.from_now)
expect(topic.public_topic_timer.execute_at).to eq_time(2.hours.from_now)
args = job_klass.jobs.last['args'].first
@ -59,7 +59,7 @@ describe Topic do
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(staff_topic)
expect(topic_status_update.execute_at).to be_within_one_second_of(2.hours.from_now)
expect(topic_status_update.execute_at).to eq_time(2.hours.from_now)
expect(topic_status_update.user).to eq(admin)
args = job_klass.jobs.last['args'].first
@ -70,14 +70,12 @@ describe Topic do
context 'topic is closed manually' do
it 'should remove the schedule to auto-close the topic' do
freeze_time
topic_timer_id = staff_topic.public_topic_timer.id
staff_topic.update_status('closed', true, admin)
expect(TopicTimer.with_deleted.find(topic_timer_id).deleted_at)
.to be_within(1.second).of(Time.zone.now)
.to eq_time(Time.zone.now)
end
end
end
@ -92,7 +90,7 @@ describe Topic do
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(regular_user_topic)
expect(topic_status_update.execute_at).to be_within_one_second_of(2.hours.from_now)
expect(topic_status_update.execute_at).to eq_time(2.hours.from_now)
expect(topic_status_update.user).to eq(Discourse.system_user)
args = job_klass.jobs.last['args'].first

View File

@ -3,16 +3,16 @@
require 'rails_helper'
describe 'user api keys integration' do
fab!(:user_api_key) { Fabricate(:readonly_user_api_key) }
it 'updates last used time on use' do
user_api_key.update_columns(last_used_at: 7.days.ago)
freeze_time
user_api_key.update_columns(last_used_at: 7.days.ago)
get '/session/current.json', headers: {
HTTP_USER_API_KEY: user_api_key.key,
}
expect(user_api_key.reload.last_used_at).to eq_time(Time.zone.now)
end
end

View File

@ -1,5 +1,7 @@
# frozen_string_literal: true
require "rails_helper"
def list_files(base_dir, pattern = '*')
Dir[File.join("#{base_dir}", pattern)]
end

View File

@ -7,7 +7,6 @@ RSpec.describe Jobs::AutoExpireUserApiKeys do
fab!(:key2) { Fabricate(:readonly_user_api_key) }
context 'when user api key is unused in last 1 days' do
before do
SiteSetting.expire_user_api_keys_days = 1
end
@ -16,10 +15,9 @@ RSpec.describe Jobs::AutoExpireUserApiKeys do
freeze_time
key1.update!(last_used_at: 2.days.ago)
described_class.new.execute({})
expect(key1.reload.revoked_at).to be_within(1.second).of(Time.zone.now)
expect(key1.reload.revoked_at).to eq_time(Time.zone.now)
expect(key2.reload.revoked_at).to eq(nil)
end
end

View File

@ -33,6 +33,6 @@ describe Jobs::PeriodicalUpdates do
# does not rebake
Jobs::PeriodicalUpdates.new.execute
post.reload
expect(post.baked_at).to eq(baked)
expect(post.baked_at).to eq_time(baked)
end
end

View File

@ -22,7 +22,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
describe 'when topic has been deleted' do
it 'should not publish the topic to the new category' do
freeze_time 1.hour.ago
created_at = freeze_time 1.hour.ago
topic
freeze_time 1.hour.from_now
@ -32,7 +32,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
topic.reload
expect(topic.category).to eq(category)
expect(topic.created_at).to be_within(1.second).of(Time.zone.now - 1.hour)
expect(topic.created_at).to eq_time(created_at)
end
end
@ -41,6 +41,8 @@ RSpec.describe Jobs::PublishTopicToCategory do
topic.update!(visible: false)
end
now = freeze_time
message = MessageBus.track_publish do
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
end.find do |m|
@ -54,19 +56,19 @@ RSpec.describe Jobs::PublishTopicToCategory do
expect(message.channel).to eq("/topic/#{topic.id}")
%w{created_at bumped_at updated_at last_posted_at}.each do |attribute|
expect(topic.public_send(attribute)).to be_within(1.second).of(Time.zone.now)
expect(topic.public_send(attribute)).to eq_time(now)
end
end
describe 'when topic is a private message' do
before do
it 'should publish the topic to the new category' do
freeze_time 1.hour.ago do
expect { topic.convert_to_private_message(Discourse.system_user) }
.to change { topic.private_message? }.to(true)
end
end
it 'should publish the topic to the new category' do
now = freeze_time
message = MessageBus.track_publish do
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
end.last
@ -77,7 +79,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
expect(topic.private_message?).to eq(false)
%w{created_at bumped_at updated_at last_posted_at}.each do |attribute|
expect(topic.public_send(attribute)).to be_within(1.second).of(Time.zone.now)
expect(topic.public_send(attribute)).to eq_time(now)
end
expect(message.data[:reload_topic]).to be_present
@ -86,11 +88,10 @@ RSpec.describe Jobs::PublishTopicToCategory do
end
describe 'when new category has a default auto-close' do
before do
another_category.update!(auto_close_hours: 5)
end
it 'should apply the auto-close timer upon publishing' do
freeze_time
another_category.update!(auto_close_hours: 5)
topic
described_class.new.execute(topic_timer_id: topic.public_topic_timer.id)
@ -99,7 +100,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
topic_timer = topic.public_topic_timer
expect(topic.category).to eq(another_category)
expect(topic_timer.status_type).to eq(TopicTimer.types[:close])
expect(topic_timer.execute_at).to be_within(1.second).of(5.hours.from_now)
expect(topic_timer.execute_at).to eq_time(5.hours.from_now)
end
end
end

View File

@ -44,7 +44,7 @@ describe Jobs::PullHotlinkedImages do
freeze_time 1.week.from_now
Jobs::PullHotlinkedImages.new.execute(post_id: post.id)
expect(orig).to be_within(1.second).of(post.reload.updated_at)
expect(orig).to eq_time(post.reload.updated_at)
end
it 'replaces images' do

View File

@ -37,15 +37,24 @@ describe Jobs::TruncateUserFlagStats do
p2 = Fabricate(:post, user: user)
p3 = Fabricate(:post)
freeze_time 10.minutes.ago
r0 = PostActionCreator.spam(user, p0).reviewable
freeze_time 1.minute.from_now
r1 = PostActionCreator.spam(user, p1).reviewable
freeze_time 1.minute.from_now
r2 = PostActionCreator.spam(user, p2).reviewable
freeze_time 1.minute.from_now
r3 = PostActionCreator.spam(user, p3).reviewable
freeze_time 1.minute.from_now
PostActionCreator.spam(other_user, p3).reviewable
freeze_time 1.minute.from_now
PostActionCreator.spam(other_user, p2).reviewable
freeze_time 1.minute.from_now
PostActionCreator.spam(other_user, p1).reviewable
unfreeze_time
r0.perform(Discourse.system_user, :agree_and_keep)
r1.perform(Discourse.system_user, :disagree)
r2.perform(Discourse.system_user, :ignore)

View File

@ -192,18 +192,21 @@ describe Jobs::UserEmail do
end
context "email_log" do
fab!(:post) { Fabricate(:post) }
fab!(:post) { Fabricate(:post, created_at: 30.seconds.ago) }
before do
SiteSetting.editing_grace_period = 0
post
end
it "creates an email log when the mail is sent (via Email::Sender)" do
last_emailed_at = user.last_emailed_at
freeze_time
last_emailed_at = 7.days.ago
user.update!(last_emailed_at: last_emailed_at)
Topic.last.update(created_at: 1.minute.ago)
expect do
Jobs::UserEmail.new.execute(type: :digest, user_id: user.id,)
Jobs::UserEmail.new.execute(type: :digest, user_id: user.id)
end.to change { EmailLog.count }.by(1)
email_log = EmailLog.last
@ -211,12 +214,17 @@ describe Jobs::UserEmail do
expect(email_log.user).to eq(user)
expect(email_log.post).to eq(nil)
# last_emailed_at should have changed
expect(email_log.user.last_emailed_at).to_not eq(last_emailed_at)
expect(email_log.user.last_emailed_at).to_not eq_time(last_emailed_at)
end
it "creates a skipped email log when the mail is skipped" do
last_emailed_at = user.last_emailed_at
user.update_columns(suspended_till: 1.year.from_now)
freeze_time
last_emailed_at = 7.days.ago
user.update!(
last_emailed_at: last_emailed_at,
suspended_till: 1.year.from_now
)
expect do
Jobs::UserEmail.new.execute(type: :digest, user_id: user.id)
@ -231,7 +239,7 @@ describe Jobs::UserEmail do
)).to eq(true)
# last_emailed_at doesn't change
expect(user.last_emailed_at).to eq(last_emailed_at)
expect(user.last_emailed_at).to eq_time(last_emailed_at)
end
it "creates a skipped email log when the user isn't allowed to see the post" do

View File

@ -535,15 +535,15 @@ describe Category do
describe 'latest' do
it 'should be updated correctly' do
category = Fabricate(:category_with_definition)
post = create_post(category: category.id)
category = freeze_time(1.minute.ago) { Fabricate(:category_with_definition) }
post = create_post(category: category.id, created_at: 15.seconds.ago)
category.reload
expect(category.latest_post_id).to eq(post.id)
expect(category.latest_topic_id).to eq(post.topic_id)
post2 = create_post(category: category.id)
post3 = create_post(topic_id: post.topic_id, category: category.id)
post2 = create_post(category: category.id, created_at: 10.seconds.ago)
post3 = create_post(topic_id: post.topic_id, category: category.id, created_at: 5.seconds.ago)
category.reload
expect(category.latest_post_id).to eq(post3.id)
@ -858,22 +858,18 @@ describe Category do
end
it 'should correctly automatically bump topics' do
freeze_time 1.second.ago
category = Fabricate(:category_with_definition)
freeze_time
category = Fabricate(:category_with_definition, created_at: 1.minute.ago)
category.clear_auto_bump_cache!
freeze_time 1.second.from_now
post1 = create_post(category: category)
freeze_time 1.second.from_now
_post2 = create_post(category: category)
freeze_time 1.second.from_now
_post3 = create_post(category: category)
post1 = create_post(category: category, created_at: 15.seconds.ago)
_post2 = create_post(category: category, created_at: 10.seconds.ago)
_post3 = create_post(category: category, created_at: 5.seconds.ago)
# no limits on post creation or category creation please
RateLimiter.enable
time = 1.month.from_now
freeze_time time
time = freeze_time 1.month.from_now
expect(category.auto_bump_topic!).to eq(false)
expect(Topic.where(bumped_at: time).count).to eq(0)
@ -886,8 +882,7 @@ describe Category do
# our extra bump message
expect(post1.topic.reload.posts_count).to eq(2)
time = time + 13.hours
freeze_time time
time = freeze_time 13.hours.from_now
expect(category.auto_bump_topic!).to eq(true)
expect(Topic.where(bumped_at: time).count).to eq(1)
@ -895,8 +890,7 @@ describe Category do
expect(category.auto_bump_topic!).to eq(false)
expect(Topic.where(bumped_at: time).count).to eq(1)
time = 1.month.from_now
freeze_time time
time = freeze_time 1.month.from_now
category.auto_bump_limiter.clear!
expect(Category.auto_bump_topic!).to eq(true)
@ -909,18 +903,16 @@ describe Category do
end
it 'should not automatically bump topics with a bump scheduled' do
freeze_time 1.second.ago
category = Fabricate(:category_with_definition)
freeze_time
category = Fabricate(:category_with_definition, created_at: 1.second.ago)
category.clear_auto_bump_cache!
freeze_time 1.second.from_now
post1 = create_post(category: category)
# no limits on post creation or category creation please
RateLimiter.enable
time = 1.month.from_now
freeze_time time
time = freeze_time 1.month.from_now
expect(category.auto_bump_topic!).to eq(false)
expect(Topic.where(bumped_at: time).count).to eq(0)

View File

@ -125,13 +125,14 @@ describe Invite do
end
it 'updates timestamp of existing invite' do
freeze_time
invite.update!(created_at: 10.days.ago)
resend_invite = Invite.invite_by_email(
'iceking@adventuretime.ooo', inviter, topic
)
expect(resend_invite.created_at).to be_within(1.minute).of(Time.zone.now)
expect(resend_invite.created_at).to eq_time(Time.zone.now)
end
it 'returns a new invite if the other has expired' do

View File

@ -729,7 +729,7 @@ describe PostAction do
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
expect(topic_status_update.execute_at).to be_within(1.second).of(1.hour.from_now)
expect(topic_status_update.execute_at).to eq_time(1.hour.from_now)
expect(topic_status_update.status_type).to eq(TopicTimer.types[:open])
end
@ -772,7 +772,7 @@ describe PostAction do
Jobs::ToggleTopicClosed.new.execute(topic_timer_id: timer.id, state: false)
expect(topic.reload.closed).to eq(true)
expect(timer.reload.execute_at).to eq(1.hour.from_now)
expect(timer.reload.execute_at).to eq_time(1.hour.from_now)
freeze_time timer.execute_at
SiteSetting.num_flaggers_to_close_topic = 10

View File

@ -24,10 +24,12 @@ describe PostMover do
describe 'move_posts' do
context 'topics' do
before { freeze_time }
fab!(:user) { Fabricate(:user, admin: true) }
fab!(:another_user) { evil_trout }
fab!(:category) { Fabricate(:category, user: user) }
fab!(:topic) { Fabricate(:topic, user: user) }
fab!(:topic) { Fabricate(:topic, user: user, created_at: 4.hours.ago) }
fab!(:p1) { Fabricate(:post, topic: topic, user: user, created_at: 3.hours.ago, reply_count: 2) }
fab!(:p2) do
@ -37,14 +39,15 @@ describe PostMover do
user: another_user,
raw: "Has a link to [evil trout](http://eviltrout.com) which is a cool site.",
reply_to_post_number: p1.post_number,
reply_count: 1
reply_count: 1,
created_at: 2.hours.ago
)
end
fab!(:p3) { Fabricate(:post, topic: topic, reply_to_post_number: p1.post_number, user: user) }
fab!(:p4) { Fabricate(:post, topic: topic, reply_to_post_number: p2.post_number, user: user) }
fab!(:p5) { Fabricate(:post) }
let(:p6) { Fabricate(:post, topic: topic) }
fab!(:p3) { Fabricate(:post, topic: topic, reply_to_post_number: p1.post_number, user: user, created_at: 1.hour.ago) }
fab!(:p4) { Fabricate(:post, topic: topic, reply_to_post_number: p2.post_number, user: user, created_at: 45.minutes.ago) }
fab!(:p5) { Fabricate(:post, created_at: 30.minutes.ago) }
let(:p6) { Fabricate(:post, topic: topic, created_at: 15.minutes.ago) }
before do
SiteSetting.tagging_enabled = true
@ -135,8 +138,6 @@ describe PostMover do
before do
TopicUser.update_last_read(user, topic.id, p4.post_number, p4.post_number, 0)
TopicLink.extract_from(p2)
freeze_time Time.now
end
def create_post_timing(post, user, msecs)
@ -216,7 +217,6 @@ describe PostMover do
end
context "to a new topic" do
it "works correctly" do
topic.expects(:add_moderator_post).once
new_topic = topic.move_posts(user, [p2.id, p4.id], title: "new testing topic name", category_id: category.id, tags: ["tag1", "tag2"])
@ -238,8 +238,8 @@ describe PostMover do
p4.reload
expect(new_topic.last_post_user_id).to eq(p4.user_id)
expect(new_topic.last_posted_at).to eq(p4.created_at)
expect(new_topic.bumped_at).to be_within(1.second).of(Time.now)
expect(new_topic.last_posted_at).to eq_time(p4.created_at)
expect(new_topic.bumped_at).to eq_time(Time.zone.now)
p2.reload
expect(p2.sort_order).to eq(1)
@ -511,8 +511,8 @@ describe PostMover do
expect(moved_to.category_id).to eq(SiteSetting.uncategorized_category_id)
p4.reload
expect(moved_to.last_post_user_id).to eq(p4.user_id)
expect(moved_to.last_posted_at).to eq(p4.created_at)
expect(moved_to.bumped_at).to be_within(1.second).of(Time.now)
expect(moved_to.last_posted_at).to eq_time(p4.created_at)
expect(moved_to.bumped_at).to eq_time(Time.zone.now)
# Posts should be re-ordered
p2.reload
@ -822,8 +822,8 @@ describe PostMover do
p4.reload
expect(new_topic.last_post_user_id).to eq(p4.user_id)
expect(new_topic.last_posted_at).to eq(p4.created_at)
expect(new_topic.bumped_at).to be_within(1.second).of(Time.now)
expect(new_topic.last_posted_at).to eq_time(p4.created_at)
expect(new_topic.bumped_at).to eq_time(Time.zone.now)
p2.reload
expect(p2.sort_order).to eq(1)
@ -920,7 +920,6 @@ describe PostMover do
end
context "moving the first post" do
it "copies the OP, doesn't delete it" do
topic.expects(:add_moderator_post).once
new_topic = topic.move_posts(user, [p1.id, p2.id], title: "new testing topic name")
@ -940,7 +939,7 @@ describe PostMover do
# New first post
new_first = new_topic.posts.where(post_number: 1).first
expect(new_first.reply_count).to eq(1)
expect(new_first.created_at).to be_within(1.second).of(p1.created_at)
expect(new_first.created_at).to eq_time(p1.created_at)
# Second post is in a new topic
p2.reload
@ -1074,13 +1073,12 @@ describe PostMover do
fab!(:user) { Fabricate(:user) }
fab!(:another_user) { Fabricate(:user) }
fab!(:regular_user) { Fabricate(:trust_level_4) }
fab!(:topic) { Fabricate(:topic) }
fab!(:personal_message) { Fabricate(:private_message_topic, user: evil_trout) }
fab!(:p1) { Fabricate(:post, topic: personal_message, user: user) }
fab!(:p2) { Fabricate(:post, topic: personal_message, reply_to_post_number: p1.post_number, user: another_user) }
fab!(:p3) { Fabricate(:post, topic: personal_message, reply_to_post_number: p1.post_number, user: user) }
fab!(:p4) { Fabricate(:post, topic: personal_message, reply_to_post_number: p2.post_number, user: user) }
fab!(:p5) { Fabricate(:post, topic: personal_message, user: evil_trout) }
fab!(:p1) { Fabricate(:post, topic: personal_message, user: user, created_at: 4.hours.ago) }
fab!(:p2) { Fabricate(:post, topic: personal_message, reply_to_post_number: p1.post_number, user: another_user, created_at: 3.hours.ago) }
fab!(:p3) { Fabricate(:post, topic: personal_message, reply_to_post_number: p1.post_number, user: user, created_at: 2.hours.ago) }
fab!(:p4) { Fabricate(:post, topic: personal_message, reply_to_post_number: p2.post_number, user: user, created_at: 1.hour.ago) }
fab!(:p5) { Fabricate(:post, topic: personal_message, user: evil_trout, created_at: 30.minutes.ago) }
let(:another_personal_message) do
Fabricate(:private_message_topic, user: user, topic_allowed_users: [
Fabricate.build(:topic_allowed_user, user: admin)
@ -1181,6 +1179,8 @@ describe PostMover do
end
it "does not allow moving regular topic posts in personal message" do
topic = Fabricate(:topic, created_at: 4.hours.ago)
expect {
personal_message.move_posts(admin, [p2.id, p5.id], destination_topic_id: topic.id)
}.to raise_error(Discourse::InvalidParameters)

View File

@ -1132,7 +1132,7 @@ describe Post do
SiteSetting.newuser_spam_host_threshold = 1
SiteSetting.newuser_max_links = 3
user = Fabricate(:user, staged: true, trust_level: 0)
user.created_at = 1.day.ago
user.created_at = 2.days.ago
user.unstage
post = Fabricate(:post, raw: raw, user: user)
expect(post.has_host_spam?).to eq(false)
@ -1224,7 +1224,7 @@ describe Post do
baked = post.baked_at
Post.rebake_old(100)
post.reload
expect(post.baked_at).to eq(baked)
expect(post.baked_at).to eq_time(baked)
end
it "will rate limit globally" do
@ -1475,10 +1475,7 @@ describe Post do
end
def updates_topic_updated_at
freeze_time 1.day.from_now
time = Time.now
time = freeze_time 1.day.from_now
result = yield
topic.reload

View File

@ -84,7 +84,6 @@ describe QuotedPost do
quote.reload
expect(original_date).to eq_time(quote.created_at)
expect(post2.reply_quoted).to eq(false)
end
end

View File

@ -103,7 +103,7 @@ describe RemoteTheme do
expect(@theme.settings.length).to eq(1)
expect(@theme.settings.first.value).to eq(true)
expect(remote.remote_updated_at).to eq(time)
expect(remote.remote_updated_at).to eq_time(time)
scheme = ColorScheme.find_by(theme_id: @theme.id)
expect(scheme.name).to eq("Amazing")
@ -150,7 +150,7 @@ describe RemoteTheme do
expect(@theme.settings.length).to eq(1)
expect(@theme.settings.first.value).to eq(32)
expect(remote.remote_updated_at).to eq(time)
expect(remote.remote_updated_at).to eq_time(time)
expect(remote.about_url).to eq("https://newsite.com/about")
# It should be able to remove old colors as well

View File

@ -80,9 +80,9 @@ describe ScreenedEmail do
shared_examples "when a ScreenedEmail record matches" do
it "updates statistics" do
freeze_time(Time.zone.now) do
freeze_time do
expect { subject }.to change { screened_email.reload.match_count }.by(1)
expect(screened_email.last_match_at).to be_within_one_second_of(Time.zone.now)
expect(screened_email.last_match_at).to eq_time(Time.zone.now)
end
end
end

View File

@ -988,7 +988,7 @@ describe Topic do
fab!(:topic) { Fabricate(:topic, bumped_at: 1.hour.ago) }
before do
@original_bumped_at = topic.bumped_at.to_f
@original_bumped_at = topic.bumped_at
@user = topic.user
@user.admin = true
end
@ -1000,7 +1000,7 @@ describe Topic do
topic.reload
expect(topic).not_to be_visible
expect(topic.moderator_posts_count).to eq(1)
expect(topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(topic.bumped_at).to eq_time(@original_bumped_at)
end
it 'removes itself as featured topic on user profiles' do
@ -1022,7 +1022,7 @@ describe Topic do
it 'should be visible with correct counts' do
expect(topic).to be_visible
expect(topic.moderator_posts_count).to eq(1)
expect(topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(topic.bumped_at).to eq_time(@original_bumped_at)
end
end
end
@ -1037,7 +1037,7 @@ describe Topic do
it "doesn't have a pinned_at but has correct dates" do
expect(topic.pinned_at).to be_blank
expect(topic.moderator_posts_count).to eq(1)
expect(topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(topic.bumped_at).to eq_time(@original_bumped_at)
end
end
@ -1050,7 +1050,7 @@ describe Topic do
it 'should enable correctly' do
expect(topic.pinned_at).to be_present
expect(topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(topic.bumped_at).to eq_time(@original_bumped_at)
expect(topic.moderator_posts_count).to eq(1)
end
@ -1061,14 +1061,14 @@ describe Topic do
context 'disable' do
before do
@archived_topic = Fabricate(:topic, archived: true, bumped_at: 1.hour.ago)
@original_bumped_at = @archived_topic.bumped_at.to_f
@original_bumped_at = @archived_topic.bumped_at
@archived_topic.update_status('archived', false, @user)
@archived_topic.reload
end
it 'should archive correctly' do
expect(@archived_topic).not_to be_archived
expect(@archived_topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(@archived_topic.bumped_at).to eq_time(@original_bumped_at)
expect(@archived_topic.moderator_posts_count).to eq(1)
end
end
@ -1083,7 +1083,7 @@ describe Topic do
it 'should be archived' do
expect(topic).to be_archived
expect(topic.moderator_posts_count).to eq(1)
expect(topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(topic.bumped_at).to eq_time(@original_bumped_at)
end
end
end
@ -1092,7 +1092,7 @@ describe Topic do
context 'disable' do
before do
@closed_topic = Fabricate(:topic, closed: true, bumped_at: 1.hour.ago)
@original_bumped_at = @closed_topic.bumped_at.to_f
@original_bumped_at = @closed_topic.bumped_at
@closed_topic.update_status(status, false, @user)
@closed_topic.reload
end
@ -1100,7 +1100,7 @@ describe Topic do
it 'should not be pinned' do
expect(@closed_topic).not_to be_closed
expect(@closed_topic.moderator_posts_count).to eq(1)
expect(@closed_topic.bumped_at.to_f).not_to be_within(1e-4).of(@original_bumped_at)
expect(@closed_topic.bumped_at).not_to eq_time(@original_bumped_at)
end
end
@ -1113,7 +1113,7 @@ describe Topic do
it 'should be closed' do
expect(topic).to be_closed
expect(topic.bumped_at.to_f).to be_within(1e-4).of(@original_bumped_at)
expect(topic.bumped_at).to eq_time(@original_bumped_at)
expect(topic.moderator_posts_count).to eq(1)
expect(topic.topic_timers.first).to eq(nil)
end
@ -1473,6 +1473,8 @@ describe Topic do
end
it 'should set a topic timer' do
freeze_time
expect { topic.change_category_to_id(new_category.id) }
.to change { TopicTimer.count }.by(1)
@ -1481,7 +1483,7 @@ describe Topic do
topic_timer = TopicTimer.last
expect(topic_timer.topic).to eq(topic)
expect(topic_timer.execute_at).to be_within(1.second).of(Time.zone.now + 5.hours)
expect(topic_timer.execute_at).to eq_time(5.hours.from_now)
end
describe 'when topic is already closed' do
@ -1506,11 +1508,8 @@ describe Topic do
topic.change_category_to_id(new_category.id)
expect(topic.reload.category).to eq(new_category)
expect(topic.public_topic_timer).to eq(topic_timer)
expect(topic.public_topic_timer.execute_at)
.to be_within(1.second).of(topic_timer.execute_at)
expect(topic.public_topic_timer.execute_at).to eq_time(topic_timer.execute_at)
end
end
end
@ -1628,32 +1627,32 @@ describe Topic do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], 72, by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(3.days.from_now)
expect(topic.topic_timers.first.execute_at).to eq_time(3.days.from_now)
end
it 'can take a number of hours as a string' do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '18', by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
expect(topic.topic_timers.first.execute_at).to eq_time(18.hours.from_now)
end
it 'can take a number of hours as a string and can handle based on last post' do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '18', by_user: admin, based_on_last_post: true)
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
expect(topic.topic_timers.first.execute_at).to eq_time(18.hours.from_now)
end
it "can take a timestamp for a future time" do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-22 5:00', by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013, 11, 22, 5, 0))
expect(topic.topic_timers.first.execute_at).to eq_time(Time.zone.local(2013, 11, 22, 5, 0))
end
it "sets a validation error when given a timestamp in the past" do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-19 5:00', by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013, 11, 19, 5, 0))
expect(topic.topic_timers.first.execute_at).to eq_time(Time.zone.local(2013, 11, 19, 5, 0))
expect(topic.topic_timers.first.errors[:execute_at]).to be_present
end
@ -1672,7 +1671,7 @@ describe Topic do
it "can take a timestamp with timezone" do
freeze_time now
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-25T01:35:00-08:00', by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(Time.utc(2013, 11, 25, 9, 35))
expect(topic.topic_timers.first.execute_at).to eq_time(Time.utc(2013, 11, 25, 9, 35))
end
it 'sets topic status update user to given user if it is a staff or TL4 user' do
@ -1716,7 +1715,7 @@ describe Topic do
it 'updates topic status update execute_at if it was already set to close' do
freeze_time now
closing_topic.set_or_create_timer(TopicTimer.types[:close], 48)
expect(closing_topic.reload.public_topic_timer.execute_at).to eq(2.days.from_now)
expect(closing_topic.reload.public_topic_timer.execute_at).to eq_time(2.days.from_now)
end
it 'should not delete topic_timer of another status_type' do
@ -1735,7 +1734,7 @@ describe Topic do
TopicTimer.types[:publish_to_category], 72, by_user: admin
)
expect(topic_timer.execute_at).to eq(3.days.from_now)
expect(topic_timer.execute_at).to eq_time(3.days.from_now)
end
it "does not update topic's topic status created_at it was already set to close" do
@ -1792,7 +1791,7 @@ describe Topic do
topic.set_or_create_timer(TopicTimer.types[:reminder], 11, by_user: admin)
}.to_not change { TopicTimer.count }
reminder.reload
expect(reminder.execute_at).to eq(11.hours.from_now)
expect(reminder.execute_at).to eq_time(11.hours.from_now)
end
end
end
@ -1810,19 +1809,19 @@ describe Topic do
end
it "doesn't return category topics" do
Fabricate(:category_with_definition)
Fabricate(:category_with_definition, created_at: 1.minute.ago)
expect(Topic.for_digest(user, 1.year.ago, top_order: true)).to be_blank
end
it "returns regular topics" do
topic = Fabricate(:topic)
topic = Fabricate(:topic, created_at: 1.minute.ago)
expect(Topic.for_digest(user, 1.year.ago, top_order: true)).to eq([topic])
end
it "doesn't return topics from muted categories" do
user = Fabricate(:user)
category = Fabricate(:category_with_definition)
Fabricate(:topic, category: category)
category = Fabricate(:category_with_definition, created_at: 2.minutes.ago)
Fabricate(:topic, category: category, created_at: 1.minute.ago)
CategoryUser.set_notification_level_for_category(user, CategoryUser.notification_levels[:muted], category.id)
@ -1830,7 +1829,7 @@ describe Topic do
end
it "doesn't return topics that a user has muted" do
topic = Fabricate(:topic)
topic = Fabricate(:topic, created_at: 1.minute.ago)
user = Fabricate(:user)
Fabricate(:topic_user,
@ -1844,8 +1843,8 @@ describe Topic do
it "doesn't return topics from suppressed categories" do
user = Fabricate(:user)
category = Fabricate(:category_with_definition)
Fabricate(:topic, category: category)
category = Fabricate(:category_with_definition, created_at: 2.minutes.ago)
Fabricate(:topic, category: category, created_at: 1.minute.ago)
SiteSetting.digest_suppress_categories = "#{category.id}"
@ -1854,20 +1853,20 @@ describe Topic do
it "doesn't return topics from TL0 users" do
new_user = Fabricate(:user, trust_level: 0)
Fabricate(:topic, user: new_user)
Fabricate(:topic, user: new_user, created_at: 1.minute.ago)
expect(Topic.for_digest(user, 1.year.ago, top_order: true)).to be_blank
end
it "returns topics from TL0 users if given include_tl0" do
new_user = Fabricate(:user, trust_level: 0)
topic = Fabricate(:topic, user_id: new_user.id)
topic = Fabricate(:topic, user_id: new_user.id, created_at: 1.minute.ago)
expect(Topic.for_digest(user, 1.year.ago, top_order: true, include_tl0: true)).to eq([topic])
end
it "returns topics from TL0 users if enabled in preferences" do
new_user = Fabricate(:user, trust_level: 0)
topic = Fabricate(:topic, user: new_user)
topic = Fabricate(:topic, user: new_user, created_at: 1.minute.ago)
u = Fabricate(:user)
u.user_option.include_tl0_in_digests = true
@ -1879,7 +1878,7 @@ describe Topic do
user = Fabricate(:user)
tag = Fabricate(:tag)
TagUser.change(user.id, tag.id, TagUser.notification_levels[:muted])
Fabricate(:topic, tags: [tag])
Fabricate(:topic, tags: [tag], created_at: 1.minute.ago)
expect(Topic.for_digest(user, 1.year.ago, top_order: true)).to be_blank
end
@ -1888,7 +1887,7 @@ describe Topic do
user = Fabricate(:user)
muted_tag, other_tag = Fabricate(:tag), Fabricate(:tag)
TagUser.change(user.id, muted_tag.id, TagUser.notification_levels[:muted])
topic = Fabricate(:topic, tags: [muted_tag, other_tag])
topic = Fabricate(:topic, tags: [muted_tag, other_tag], created_at: 1.minute.ago)
expect(Topic.for_digest(user, 1.year.ago, top_order: true)).to eq([topic])
end
@ -1897,32 +1896,34 @@ describe Topic do
user = Fabricate(:user)
muted_tag = Fabricate(:tag)
TagUser.change(user.id, muted_tag.id, TagUser.notification_levels[:muted])
_topic1 = Fabricate(:topic, tags: [muted_tag])
topic2 = Fabricate(:topic, tags: [Fabricate(:tag), Fabricate(:tag)])
topic3 = Fabricate(:topic)
_topic1 = Fabricate(:topic, tags: [muted_tag], created_at: 1.minute.ago)
topic2 = Fabricate(:topic, tags: [Fabricate(:tag), Fabricate(:tag)], created_at: 1.minute.ago)
topic3 = Fabricate(:topic, created_at: 1.minute.ago)
topics = Topic.for_digest(user, 1.year.ago, top_order: true)
expect(topics.size).to eq(2)
expect(topics).to contain_exactly(topic2, topic3)
end
it "sorts by category notification levels" do
category1, category2 = Fabricate(:category_with_definition), Fabricate(:category_with_definition)
2.times { |i| Fabricate(:topic, category: category1) }
topic1 = Fabricate(:topic, category: category2)
2.times { |i| Fabricate(:topic, category: category1) }
category1, category2 = Fabricate(:category_with_definition), Fabricate(:category_with_definition, created_at: 2.minutes.ago)
2.times { |i| Fabricate(:topic, category: category1, created_at: 1.minute.ago) }
topic1 = Fabricate(:topic, category: category2, created_at: 1.minute.ago)
2.times { |i| Fabricate(:topic, category: category1, created_at: 1.minute.ago) }
CategoryUser.create(user: user, category: category2, notification_level: CategoryUser.notification_levels[:watching])
for_digest = Topic.for_digest(user, 1.year.ago, top_order: true)
expect(for_digest.first).to eq(topic1)
end
it "sorts by topic notification levels" do
topics = []
3.times { |i| topics << Fabricate(:topic) }
3.times { |i| topics << Fabricate(:topic, created_at: 1.minute.ago) }
user = Fabricate(:user)
TopicUser.create(user_id: user.id, topic_id: topics[0].id, notification_level: TopicUser.notification_levels[:tracking])
TopicUser.create(user_id: user.id, topic_id: topics[2].id, notification_level: TopicUser.notification_levels[:watching])
for_digest = Topic.for_digest(user, 1.year.ago, top_order: true).pluck(:id)
expect(for_digest).to eq([topics[2].id, topics[0].id, topics[1].id])
end
end
@ -2090,7 +2091,7 @@ describe Topic do
topic_embed = TopicEmbed.create!(topic_id: topic.id, embed_url: "https://blog.codinghorror.com/password-rules-are-bullshit", post_id: post.id, deleted_at: 1.day.ago)
topic.recover!
topic_embed.reload
expect(topic_embed.deleted_at).to eq(nil)
expect(topic_embed.deleted_at).to be_nil
end
end
@ -2256,7 +2257,6 @@ describe Topic do
end
it 'allows users to normalize counts' do
topic = Fabricate(:topic, last_posted_at: 1.year.ago)
post1 = Fabricate(:post, topic: topic, post_number: 1)
post2 = Fabricate(:post, topic: topic, post_type: Post.types[:whisper], post_number: 2)
@ -2267,7 +2267,7 @@ describe Topic do
expect(topic.posts_count).to eq(1)
expect(topic.highest_post_number).to eq(post1.post_number)
expect(topic.highest_staff_post_number).to eq(post2.post_number)
expect(topic.last_posted_at).to be_within(1.second).of (post1.created_at)
expect(topic.last_posted_at).to eq_time(post1.created_at)
end
context 'featured link' do

View File

@ -458,6 +458,7 @@ describe TopicTrackingState do
end
it "correctly handles seen categories" do
freeze_time 1.minute.ago
user = Fabricate(:user)
post
@ -473,6 +474,7 @@ describe TopicTrackingState do
report = TopicTrackingState.report(user)
expect(report.length).to eq(0)
unfreeze_time
post.topic.touch(:created_at)
report = TopicTrackingState.report(user)

View File

@ -226,22 +226,19 @@ describe UserAction do
end
describe 'when a user posts a new topic' do
def process_alerts(post)
PostAlerter.post_created(post)
end
before do
@post = create_post(created_at: DateTime.now - 100)
process_alerts(@post)
freeze_time(100.days.ago) do
@post = create_post
PostAlerter.post_created(@post)
end
end
describe 'topic action' do
before do
@action = @post.user.user_actions.find_by(action_type: UserAction::NEW_TOPIC)
end
it 'should exist' do
@action = @post.user.user_actions.find_by(action_type: UserAction::NEW_TOPIC)
expect(@action).not_to eq(nil)
expect(@action.created_at).to be_within(1).of(@post.topic.created_at)
expect(@action.created_at).to eq_time(@post.topic.created_at)
end
end
@ -256,7 +253,7 @@ describe UserAction do
@response = PostCreator.new(@other_user, reply_to_post_number: 1, topic_id: @post.topic_id, raw: "perhaps @#{@mentioned.username} knows how this works?").create
process_alerts(@response)
PostAlerter.post_created(@response)
end
it 'should log user actions correctly' do

View File

@ -83,23 +83,21 @@ describe UserAuthToken do
end
it "expires correctly" do
freeze_time Time.zone.now
user = Fabricate(:user)
user_token = UserAuthToken.generate!(user_id: user.id,
user_agent: "some user agent 2",
client_ip: "1.1.2.3")
UserAuthToken.lookup(user_token.unhashed_auth_token, seen: true)
freeze_time (SiteSetting.maximum_session_age.hours - 1).from_now
freeze_time SiteSetting.maximum_session_age.hours.from_now - 1.second
user_token.reload
user_token.rotate!
UserAuthToken.lookup(user_token.unhashed_auth_token, seen: true)
freeze_time (SiteSetting.maximum_session_age.hours - 1).from_now
freeze_time SiteSetting.maximum_session_age.hours.from_now - 1.second
still_good = UserAuthToken.lookup(user_token.unhashed_auth_token, seen: true)
expect(still_good).not_to eq(nil)
@ -111,7 +109,7 @@ describe UserAuthToken do
end
it "can properly rotate tokens" do
freeze_time 3.days.ago
user = Fabricate(:user)
user_token = UserAuthToken.generate!(user_id: user.id,
@ -126,12 +124,14 @@ describe UserAuthToken do
user_token.update_columns(auth_token_seen: true)
rotation_time = freeze_time 1.day.from_now
rotated = user_token.rotate!(user_agent: "a new user agent", client_ip: "1.1.2.4")
expect(rotated).to eq(true)
user_token.reload
expect(user_token.rotated_at).to be_within(5.second).of(Time.zone.now)
expect(user_token.rotated_at).to eq_time(rotation_time)
expect(user_token.client_ip).to eq("1.1.2.4")
expect(user_token.user_agent).to eq("a new user agent")
expect(user_token.auth_token_seen).to eq(false)
@ -139,17 +139,17 @@ describe UserAuthToken do
expect(user_token.prev_auth_token).to eq(prev_auth_token)
# ability to auth using an old token
freeze_time
seen_at = freeze_time 1.day.from_now
looked_up = UserAuthToken.lookup(user_token.unhashed_auth_token, seen: true)
expect(looked_up.id).to eq(user_token.id)
expect(looked_up.auth_token_seen).to eq(true)
expect(looked_up.seen_at).to be_within(1.second).of(Time.zone.now)
expect(looked_up.seen_at).to eq_time(seen_at)
looked_up = UserAuthToken.lookup(unhashed_prev, seen: true)
expect(looked_up.id).to eq(user_token.id)
freeze_time(2.minute.from_now)
freeze_time 2.minutes.from_now
looked_up = UserAuthToken.lookup(unhashed_prev)
expect(looked_up).not_to eq(nil)

View File

@ -863,7 +863,6 @@ describe User do
end
describe "previous_visit_at" do
let(:user) { Fabricate(:user) }
let!(:first_visit_date) { Time.zone.now }
let!(:second_visit_date) { 2.hours.from_now }
@ -889,12 +888,12 @@ describe User do
# second visit
user.update_last_seen!(second_visit_date)
user.reload
expect(user.previous_visit_at).to be_within_one_second_of(first_visit_date)
expect(user.previous_visit_at).to eq_time(first_visit_date)
# third visit
user.update_last_seen!(third_visit_date)
user.reload
expect(user.previous_visit_at).to be_within_one_second_of(second_visit_date)
expect(user.previous_visit_at).to eq_time(second_visit_date)
end
end
@ -907,18 +906,18 @@ describe User do
it "should update the last seen value" do
expect(user.last_seen_at).to eq nil
user.update_last_seen!(first_visit_date)
expect(user.reload.last_seen_at).to be_within_one_second_of(first_visit_date)
expect(user.reload.last_seen_at).to eq_time(first_visit_date)
end
it "should update the first seen value if it doesn't exist" do
user.update_last_seen!(first_visit_date)
expect(user.reload.first_seen_at).to be_within_one_second_of(first_visit_date)
expect(user.reload.first_seen_at).to eq_time(first_visit_date)
end
it "should not update the first seen value if it doesn't exist" do
user.update_last_seen!(first_visit_date)
user.update_last_seen!(second_visit_date)
expect(user.reload.first_seen_at).to be_within_one_second_of(first_visit_date)
expect(user.reload.first_seen_at).to eq_time(first_visit_date)
end
end
@ -976,58 +975,51 @@ describe User do
end
describe 'with no previous values' do
let!(:date) { Time.zone.now }
before do
freeze_time date
user.update_last_seen!
end
after do
Discourse.redis.flushall
end
it "updates last_seen_at" do
expect(user.last_seen_at).to be_within_one_second_of(date)
date = freeze_time
user.update_last_seen!
expect(user.last_seen_at).to eq_time(date)
end
it "should have 0 for days_visited" do
user.update_last_seen!
user.reload
expect(user.user_stat.days_visited).to eq(1)
end
it "should log a user_visit with the date" do
expect(user.user_visits.first.visited_at).to eq(date.to_date)
date = freeze_time
user.update_last_seen!
expect(user.user_visits.first.visited_at).to eq_time(date.to_date)
end
context "called twice" do
before do
freeze_time date
it "doesn't increase days_visited twice" do
freeze_time
user.update_last_seen!
user.update_last_seen!
user.reload
end
it "doesn't increase days_visited twice" do
expect(user.user_stat.days_visited).to eq(1)
end
end
describe "after 3 days" do
let!(:future_date) { 3.days.from_now }
before do
freeze_time future_date
user.update_last_seen!
end
it "should log a second visited_at record when we log an update later" do
user.update_last_seen!
future_date = freeze_time(3.days.from_now)
user.update_last_seen!
expect(user.user_visits.count).to eq(2)
end
end
end
end

View File

@ -86,7 +86,7 @@ describe UserStat do
UserStat.ensure_consistency!
post.user.user_stat.reload
expect(post.user.user_stat.first_unread_at).to eq_time(Time.now)
expect(post.user.user_stat.first_unread_at).to eq_time(Time.zone.now)
end
end

View File

@ -71,7 +71,7 @@ describe WatchedWord do
expect {
w = described_class.create_or_update_word(word: existing.word, action_key: :flag)
expect(w.id).to eq(existing.id)
expect(w.updated_at).to eq(w.updated_at)
expect(w.updated_at).to eq_time(w.updated_at)
}.to_not change { described_class.count }
end

View File

@ -353,6 +353,8 @@ def freeze_time(now = Time.now)
ensure
unfreeze_time
end
else
time
end
end

View File

@ -90,8 +90,8 @@ describe Admin::EmailController do
describe '#skipped' do
fab!(:user) { Fabricate(:user) }
fab!(:log1) { Fabricate(:skipped_email_log, user: user) }
fab!(:log2) { Fabricate(:skipped_email_log) }
fab!(:log1) { Fabricate(:skipped_email_log, user: user, created_at: 20.minutes.ago) }
fab!(:log2) { Fabricate(:skipped_email_log, created_at: 10.minutes.ago) }
it "succeeds" do
get "/admin/email/skipped.json"

View File

@ -1367,7 +1367,7 @@ describe GroupsController do
expect(response.status).to eq(200)
result = JSON.parse(response.body)["logs"].last
result = JSON.parse(response.body)["logs"].find { |entry| entry["subject"] == "public_exit" }
expect(result["action"]).to eq(GroupHistory.actions[1].to_s)
expect(result["subject"]).to eq('public_exit')

View File

@ -415,12 +415,14 @@ describe PostsController do
end
it "won't update bump date if post is a whisper" do
created_at = freeze_time 1.day.ago
post = Fabricate(:post, post_type: Post.types[:whisper], user: user)
unfreeze_time
put "/posts/#{post.id}.json", params: update_params
expect(response.status).to eq(200)
expect(post.topic.reload.bumped_at).to be < post.created_at
expect(response.status).to eq(200)
expect(post.topic.reload.bumped_at).to eq_time(created_at)
end
end
@ -1314,10 +1316,10 @@ describe PostsController do
context "topic bump" do
shared_examples "it works" do
let(:original_bumped_at) { 1.day.ago }
let!(:topic) { Fabricate(:topic, bumped_at: original_bumped_at) }
it "should be able to skip topic bumping" do
original_bumped_at = 1.day.ago
topic = Fabricate(:topic, bumped_at: original_bumped_at)
post "/posts.json", params: {
raw: 'this is the test content',
topic_id: topic.id,
@ -1325,7 +1327,7 @@ describe PostsController do
}
expect(response.status).to eq(200)
expect(topic.reload.bumped_at).to be_within_one_second_of(original_bumped_at)
expect(topic.reload.bumped_at).to eq_time(original_bumped_at)
end
it "should be able to post with topic bumping" do
@ -1335,7 +1337,7 @@ describe PostsController do
}
expect(response.status).to eq(200)
expect(topic.reload.bumped_at).to eq(topic.posts.last.created_at)
expect(topic.reload.bumped_at).to eq_time(topic.posts.last.created_at)
end
end

View File

@ -577,7 +577,11 @@ RSpec.describe TopicsController do
end
describe 'changing timestamps' do
before { sign_in(moderator) }
before do
freeze_time
sign_in(moderator)
end
let(:old_timestamp) { Time.zone.now }
let(:new_timestamp) { old_timestamp - 1.day }
let!(:topic) { Fabricate(:topic, created_at: old_timestamp) }
@ -594,9 +598,9 @@ RSpec.describe TopicsController do
}
expect(response.status).to eq(200)
expect(topic.reload.created_at).to be_within_one_second_of(new_timestamp)
expect(p1.reload.created_at).to be_within_one_second_of(new_timestamp)
expect(p2.reload.created_at).to be_within_one_second_of(old_timestamp)
expect(topic.reload.created_at).to eq_time(new_timestamp)
expect(p1.reload.created_at).to eq_time(new_timestamp)
expect(p2.reload.created_at).to eq_time(old_timestamp)
end
it 'should create a staff log entry' do
@ -713,7 +717,6 @@ RSpec.describe TopicsController do
end
context 'for last post only' do
it 'should allow you to retain topic timing but remove last post only' do
freeze_time
@ -777,9 +780,7 @@ RSpec.describe TopicsController do
expect(PostTiming.where(topic: topic, user: user, post_number: 1).exists?).to eq(false)
expect(TopicUser.where(topic: topic, user: user, last_read_post_number: nil, highest_seen_post_number: nil).exists?).to eq(true)
end
end
context 'when logged in' do
@ -1694,7 +1695,7 @@ RSpec.describe TopicsController do
sign_in(user)
get "/t/#{topic.slug}/#{topic.id}"
topic_user = TopicUser.where(user: user, topic: topic).first
expect(topic_user.last_visited_at).to eq(topic_user.first_visited_at)
expect(topic_user.last_visited_at).to eq_time(topic_user.first_visited_at)
end
context 'consider for a promotion' do
@ -2072,6 +2073,10 @@ RSpec.describe TopicsController do
let(:post) { Fabricate(:post) }
let(:topic) { post.topic }
after do
Discourse.redis.flushall
end
it 'returns first post of the topic' do
# we need one for suggested
create_post
@ -2594,6 +2599,7 @@ RSpec.describe TopicsController do
context 'when logged in as an admin' do
before do
freeze_time
sign_in(admin)
end
@ -2608,14 +2614,12 @@ RSpec.describe TopicsController do
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
expect(topic_status_update.execute_at)
.to be_within(1.second).of(24.hours.from_now)
expect(topic_status_update.execute_at).to eq_time(24.hours.from_now)
json = JSON.parse(response.body)
expect(DateTime.parse(json['execute_at']))
.to be_within(1.seconds).of(DateTime.parse(topic_status_update.execute_at.to_s))
.to eq_time(DateTime.parse(topic_status_update.execute_at.to_s))
expect(json['duration']).to eq(topic_status_update.duration)
expect(json['closed']).to eq(topic.reload.closed)
@ -2652,10 +2656,7 @@ RSpec.describe TopicsController do
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
expect(topic_status_update.execute_at)
.to be_within(1.second).of(24.hours.from_now)
expect(topic_status_update.execute_at).to eq_time(24.hours.from_now)
expect(topic_status_update.status_type)
.to eq(TopicTimer.types[:publish_to_category])
@ -3134,7 +3135,7 @@ RSpec.describe TopicsController do
put "/t/#{topic.id}/reset-bump-date.json"
expect(response.status).to eq(200)
expect(topic.reload.bumped_at).to be_within_one_second_of(timestamp)
expect(topic.reload.bumped_at).to eq_time(timestamp)
end
end
end

View File

@ -119,21 +119,19 @@ describe BadgeGranter do
describe 'grant' do
it 'allows overriding of granted_at does not notify old bronze' do
freeze_time
badge = Badge.create!(name: 'a badge', badge_type_id: BadgeType::Bronze)
user_badge = BadgeGranter.grant(badge, user, created_at: 1.year.ago)
time = 1.year.ago
user_badge = BadgeGranter.grant(badge, user, created_at: time)
expect(user_badge.granted_at).to eq(time)
expect(user_badge.granted_at).to eq_time(1.year.ago)
expect(Notification.where(user_id: user.id).count).to eq(0)
end
it "doesn't grant disabled badges" do
freeze_time
badge = Fabricate(:badge, badge_type_id: BadgeType::Bronze, enabled: false)
time = 1.year.ago
user_badge = BadgeGranter.grant(badge, user, created_at: time)
user_badge = BadgeGranter.grant(badge, user, created_at: 1.year.ago)
expect(user_badge).to eq(nil)
end
@ -147,11 +145,10 @@ describe BadgeGranter do
end
it 'sets granted_at' do
time = 1.day.ago
freeze_time time
day_ago = freeze_time 1.day.ago
user_badge = BadgeGranter.grant(badge, user)
expect(user_badge.granted_at).to be_within(1.second).of(time)
expect(user_badge.granted_at).to eq_time(day_ago)
end
it 'sets granted_by if the option is present' do
@ -228,7 +225,6 @@ describe BadgeGranter do
describe 'revoke_all' do
it 'deletes every user_badge record associated with that badge' do
described_class.grant(badge, user)
described_class.revoke_all(badge)
expect(UserBadge.exists?(badge: badge, user: user)).to eq(false)

View File

@ -23,16 +23,17 @@ describe PostOwnerChanger do
end
it "changes the user" do
bumped_at = topic.bumped_at
bumped_at = freeze_time topic.bumped_at
old_user = p1.user
PostActionCreator.like(user_a, p1)
p1.reload
expect(p1.topic.like_count).to eq(1)
PostOwnerChanger.new(post_ids: [p1.id], topic_id: topic.id, new_owner: user_a, acting_user: editor).change_owner!
p1.reload
expect(p1.topic.like_count).to eq(0)
expect(p1.topic.bumped_at).to be_within(1.second).of (bumped_at)
expect(p1.topic.bumped_at).to eq_time(bumped_at)
expect(p1.topic.last_post_user_id).to eq(user_a.id)
expect(old_user).not_to eq(p1.user)
expect(p1.user).to eq(user_a)

View File

@ -26,39 +26,32 @@ describe TopicTimestampChanger do
TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change!
topic.reload
[:created_at, :updated_at, :bumped_at].each do |column|
expect(topic.public_send(column)).to be_within(1.second).of(new_timestamp)
end
expect(topic.created_at).to eq_time(new_timestamp)
expect(topic.updated_at).to eq_time(new_timestamp)
expect(topic.bumped_at).to eq_time(new_timestamp)
p1.reload
[:created_at, :updated_at].each do |column|
expect(p1.public_send(column)).to be_within(1.second).of(new_timestamp)
end
expect(p1.created_at).to eq_time(new_timestamp)
expect(p1.updated_at).to eq_time(new_timestamp)
p2.reload
[:created_at, :updated_at].each do |column|
expect(p2.public_send(column)).to be_within(1.second).of(new_timestamp + 1.day)
end
expect(p2.created_at).to eq_time(new_timestamp + 1.day)
expect(p2.updated_at).to eq_time(new_timestamp + 1.day)
expect(topic.last_posted_at).to be_within(1.second).of(p2.reload.created_at)
expect(topic.last_posted_at).to eq_time(p2.reload.created_at)
end
describe 'when posts have timestamps in the future' do
let(:new_timestamp) { Time.zone.now }
let(:p3) { Fabricate(:post, topic: topic, created_at: new_timestamp + 3.day) }
it 'should set the new timestamp as the default timestamp' do
freeze_time
p3
new_timestamp = freeze_time
p3 = Fabricate(:post, topic: topic, created_at: new_timestamp + 3.days)
TopicTimestampChanger.new(topic: topic, timestamp: new_timestamp.to_f).change!
p3.reload
[:created_at, :updated_at].each do |column|
expect(p3.public_send(column)).to be_within(1.second).of(new_timestamp)
end
expect(p3.created_at).to eq_time(new_timestamp)
expect(p3.updated_at).to eq_time(new_timestamp)
end
end
end

View File

@ -16,6 +16,8 @@ describe UserActivator do
end
it 'creates and send new email token if the existing token expired' do
now = freeze_time
SiteSetting.email_token_valid_hours = 24
user = Fabricate(:user)
email_token = user.email_tokens.first
@ -27,7 +29,7 @@ describe UserActivator do
activator.activate
user.reload
expect(user.email_tokens.last.created_at).to be_within_one_second_of(Time.zone.now)
expect(user.email_tokens.last.created_at).to eq_time(now)
end
end