Testing: Fix false positive and cover edge case for Channel::Driver::Twitter#fetch

Originally, a spec for race condition handling
in Channel::Driver::Twitter#fetch
used a `travel_back` call in the wrong place:
it needed to be called _after_ `subject!(:channel)` was created,
but since it was placed in an `around` block,
it ran before all preceding setup blocks.

Moving it to a `before` block changed the order in which it was called,
thus fixing a false positive in the test.

An additional expectation was added
to prevent this false positive in the future,
and a new test case was added to capture yet another edge case.
This commit is contained in:
Ryan Lue 2020-04-23 16:16:55 +08:00 committed by Thorsten Eckel
parent 3f28c5f54e
commit 29670cd05a
2 changed files with 107 additions and 14 deletions

View file

@ -934,12 +934,25 @@ RSpec.describe Channel::Driver::Twitter do
search_term: 'zammadzammadzammad',
custom_options: {
user: {
# Must match outgoing tweet author Twitter user ID
# "outgoing" tweets = authored by this Twitter user ID
id: '1205290247124217856',
},
})
end
# This test case requires the use_vcr: :time_sensitive option
# to travel_to(when the VCR cassette was recorded).
#
# This ensures that #fetch doesn't ignore
# the "older" tweets stored in the VCR cassette,
# but it also freezes time,
# which breaks this test expectation logic:
#
# expect { channel.fetch }.to change(Time, :current).by_at_least(5)
#
# So, we unfreeze time here.
before { travel_back }
let!(:tweet) { create(:twitter_article, body: 'zammadzammadzammad') }
context '(i.e., after the BG job has posted the article to Twitter…' do
@ -954,19 +967,6 @@ RSpec.describe Channel::Driver::Twitter do
YML
around do |example|
# This test case requires the use_vcr: :time_sensitive option
# to travel_to(when the VCR cassette was recorded).
#
# This ensures that #fetch doesn't ignore
# the "older" tweets stored in the VCR cassette,
# but it also freezes time,
# which breaks this race condition handling logic:
#
# break if Delayed::Job.where('created_at < ?', Time.current).none?
#
# So, we unfreeze time here.
travel_back
# Run BG job (Why not use Scheduler.worker?
# It led to hangs & failures elsewhere in test suite.)
Thread.new do
@ -978,9 +978,18 @@ RSpec.describe Channel::Driver::Twitter do
it 'does not import the duplicate tweet (waits up to 60s for BG job to finish)' do
expect { channel.fetch }
.to not_change(Ticket::Article, :count)
.and change(Time, :current).by_at_least(5)
end
end
end
# To reproduce this test case, the VCR cassette has been modified
# so that the fetched tweet has a different ("incoming") author user ID.
it 'skips race condition handling for incoming tweets' do
expect { channel.fetch }
.to change(Ticket::Article, :count)
.and change(Time, :current).by_at_most(1)
end
end
end

View file

@ -0,0 +1,84 @@
---
http_interactions:
- request:
method: get
uri: https://api.twitter.com/1.1/search/tweets.json?count=100&q=zammadzammadzammad&result_type=mixed
body:
encoding: UTF-8
string: ''
headers:
User-Agent:
- TwitterRubyGem/6.2.0
Authorization:
- OAuth oauth_consumer_key="REDACTED", oauth_nonce="37876a49fa0c474bd7732dea70083056",
oauth_signature="f159trPoyOipHcp%2BPlL33Kh2nO4%3D", oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1583840887", oauth_token="REDACTED",
oauth_version="1.0"
Connection:
- close
Host:
- api.twitter.com
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- no-cache, no-store, must-revalidate, pre-check=0, post-check=0
Connection:
- close
Content-Disposition:
- attachment; filename=json.json
Content-Length:
- '2346'
Content-Type:
- application/json;charset=utf-8
Date:
- Tue, 10 Mar 2020 11:48:07 GMT
Expires:
- Tue, 31 Mar 1981 05:00:00 GMT
Last-Modified:
- Tue, 10 Mar 2020 11:48:07 GMT
Pragma:
- no-cache
Server:
- tsa_m
Set-Cookie:
- guest_id=v1%3A158384088754038008; Max-Age=63072000; Expires=Thu, 10 Mar 2022
11:48:07 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
- lang=en; Path=/
- personalization_id="v1_N5oIKIuBSmkhNAVvuM7dWQ=="; Max-Age=63072000; Expires=Thu,
10 Mar 2022 11:48:07 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
Status:
- 200 OK
Strict-Transport-Security:
- max-age=631138519
X-Access-Level:
- read-write-directmessages
X-Connection-Hash:
- a615db05b45fdf48368de9e967c599c2
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Rate-Limit-Limit:
- '180'
X-Rate-Limit-Remaining:
- '177'
X-Rate-Limit-Reset:
- '1583841131'
X-Response-Time:
- '134'
X-Transaction:
- '004926c000957504'
X-Twitter-Response-Tags:
- BouncerCompliant
X-Xss-Protection:
- '0'
body:
encoding: UTF-8
string: '{"statuses":[{"created_at":"Tue Mar 10 11:48:05 +0000 2020","id":1237344473199153152,"id_str":"1237344473199153152","text":"zammadzammadzammad","truncated":false,"entities":{"hashtags":[],"symbols":[],"user_mentions":[],"urls":[]},"metadata":{"iso_language_code":"lv","result_type":"recent"},"source":"\u003ca
href=\"https:\/\/zammad.com\/\" rel=\"nofollow\"\u003ezammad\u003c\/a\u003e","in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1205290247124217857,"id_str":"1205290247124217857","name":"pennbrooke","screen_name":"pennbrooke1","location":"","description":"","url":null,"entities":{"description":{"urls":[]}},"protected":false,"followers_count":0,"friends_count":1,"listed_count":0,"created_at":"Fri
Dec 13 00:56:10 +0000 2019","favourites_count":0,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":19,"lang":null,"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"F5F8FA","profile_background_image_url":null,"profile_background_image_url_https":null,"profile_background_tile":false,"profile_image_url":"http:\/\/abs.twimg.com\/sticky\/default_profile_images\/default_profile_normal.png","profile_image_url_https":"https:\/\/abs.twimg.com\/sticky\/default_profile_images\/default_profile_normal.png","profile_link_color":"1DA1F2","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"has_extended_profile":false,"default_profile":true,"default_profile_image":true,"following":false,"follow_request_sent":false,"notifications":false,"translator_type":"none"},"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"favorited":false,"retweeted":false,"lang":"lv"}],"search_metadata":{"completed_in":0.017,"max_id":1237344473199153152,"max_id_str":"1237344473199153152","next_results":"?max_id=1237344473199153151&q=zammadzammadzammad&count=100&include_entities=1&result_type=mixed","query":"zammadzammadzammad","refresh_url":"?since_id=1237344473199153152&q=zammadzammadzammad&result_type=mixed&include_entities=1","count":100,"since_id":0,"since_id_str":"0"}}'
http_version:
recorded_at: Tue, 10 Mar 2020 11:48:07 GMT