diff --git a/app/controllers/test_controller.rb b/app/controllers/test_controller.rb
index efc12a92a..69ec29733 100644
--- a/app/controllers/test_controller.rb
+++ b/app/controllers/test_controller.rb
@@ -225,6 +225,39 @@ def suggest_similarity_item
render_success 'suggest_similarity', pm1
end
+ def create_imported_standalone_fact_check
+ team = Team.current = Team.find(params[:team_id])
+ user = User.where(email: params[:email]).last
+ description = params[:description]
+ context = params[:context]
+ title = params[:title]
+ summary = params[:summary]
+ url = params[:url]
+ language = params[:language] || 'en'
+
+ # Create ClaimDescription
+ claim_description = ClaimDescription.create!(
+ description: description,
+ context: context,
+ user: user,
+ team: team
+ )
+
+ # Set up FactCheck
+ fact_check = FactCheck.new(
+ claim_description: claim_description,
+ title: title,
+ summary: summary,
+ url: url,
+ language: language,
+ user: user,
+ publish_report: true,
+ report_status: 'published'
+ )
+ fact_check.save!
+ render_success 'fact_check', fact_check
+ end
+
def random
render html: "
Test #{rand(100000).to_i}Test".html_safe
end
diff --git a/app/graph/types/project_media_type.rb b/app/graph/types/project_media_type.rb
index 794c03326..986cd4097 100644
--- a/app/graph/types/project_media_type.rb
+++ b/app/graph/types/project_media_type.rb
@@ -394,4 +394,16 @@ def articles_count
count += 1 if object.fact_check
count
end
+
+ field :relevant_articles, ::ArticleUnion.connection_type, null: true
+
+ def relevant_articles
+ object.get_similar_articles
+ end
+
+ field :relevant_articles_count, GraphQL::Types::Int, null: true
+
+ def relevant_articles_count
+ object.get_similar_articles.count
+ end
end
diff --git a/app/models/bot/alegre.rb b/app/models/bot/alegre.rb
index a1d05d895..e2b9b393b 100644
--- a/app/models/bot/alegre.rb
+++ b/app/models/bot/alegre.rb
@@ -256,11 +256,12 @@ def self.merge_suggested_and_confirmed(suggested_or_confirmed, confirmed, pm)
end
end
- def self.get_matching_key_value(pm, media_type, similarity_method, automatic, model_name)
+ def self.get_threshold_given_model_settings(team_id, media_type, similarity_method, automatic, model_name)
+ tbi = nil
+ tbi = self.get_alegre_tbi(team_id) unless team_id.nil?
similarity_level = automatic ? 'matching' : 'suggestion'
generic_key = "#{media_type}_#{similarity_method}_#{similarity_level}_threshold"
specific_key = "#{media_type}_#{similarity_method}_#{model_name}_#{similarity_level}_threshold"
- tbi = self.get_alegre_tbi(pm&.team_id)
settings = tbi.alegre_settings unless tbi.nil?
outkey = ""
value = nil
@@ -274,17 +275,25 @@ def self.get_matching_key_value(pm, media_type, similarity_method, automatic, mo
return [outkey, value]
end
- def self.get_threshold_for_query(media_type, pm, automatic = false)
+ def self.get_matching_key_value(pm, media_type, similarity_method, automatic, model_name)
+ self.get_threshold_given_model_settings(pm&.team_id, media_type, similarity_method, automatic, model_name)
+ end
+
+ def self.get_similarity_methods_and_models_given_media_type_and_team_id(media_type, team_id, get_vector_settings)
similarity_methods = media_type == 'text' ? ['elasticsearch'] : ['hash']
models = similarity_methods.dup
- if media_type == 'text' && !pm.nil?
- models_to_use = [self.matching_model_to_use(pm.team_id)].flatten-[Bot::Alegre::ELASTICSEARCH_MODEL]
+ if media_type == 'text' && get_vector_settings
+ models_to_use = [self.matching_model_to_use(team_id)].flatten-[Bot::Alegre::ELASTICSEARCH_MODEL]
models_to_use.each do |model|
similarity_methods << 'vector'
models << model
end
end
- similarity_methods.zip(models).collect do |similarity_method, model_name|
+ return similarity_methods.zip(models)
+ end
+
+ def self.get_threshold_for_query(media_type, pm, automatic = false)
+ self.get_similarity_methods_and_models_given_media_type_and_team_id(media_type, pm&.team_id, !pm.nil?).collect do |similarity_method, model_name|
key, value = self.get_matching_key_value(pm, media_type, similarity_method, automatic, model_name)
{ value: value.to_f, key: key, automatic: automatic, model: model_name}
end
diff --git a/app/models/concerns/smooch_search.rb b/app/models/concerns/smooch_search.rb
index ca6941093..b306a4dc4 100644
--- a/app/models/concerns/smooch_search.rb
+++ b/app/models/concerns/smooch_search.rb
@@ -9,21 +9,22 @@ module ClassMethods
def search(app_id, uid, language, message, team_id, workflow, provider = nil)
platform = self.get_platform_from_message(message)
begin
+ limit = CheckConfig.get('most_relevant_team_limit', 3, :integer)
sm = CheckStateMachine.new(uid)
self.get_installation(self.installation_setting_id_keys, app_id) if self.config.blank?
RequestStore.store[:smooch_bot_provider] = provider unless provider.blank?
query = self.get_search_query(uid, message)
- results = self.get_search_results(uid, query, team_id, language).collect{ |pm| Relationship.confirmed_parent(pm) }.uniq
+ results = self.get_search_results(uid, query, team_id, language, limit).collect{ |pm| Relationship.confirmed_parent(pm) }.uniq
reports = results.select{ |pm| pm.report_status == 'published' }.collect{ |pm| pm.get_dynamic_annotation('report_design') }.reject{ |r| r.nil? }.collect{ |r| r.report_design_to_tipline_search_result }.select{ |r| r.should_send_in_language?(language) }
# Extract explainers from matched media if they don't have published fact-checks but they have explainers
- reports = results.collect{ |pm| pm.explainers.to_a }.flatten.uniq.first(3).map(&:as_tipline_search_result) if !results.empty? && reports.empty?
+ reports = results.collect{ |pm| pm.explainers.to_a }.flatten.uniq.first(limit).map(&:as_tipline_search_result) if !results.empty? && reports.empty?
# Search for explainers if fact-checks were not found
if reports.empty? && query['type'] == 'text'
- explainers = self.search_for_explainers(uid, query['text'], team_id, language).first(3).select{ |explainer| explainer.as_tipline_search_result.should_send_in_language?(language) }
+ explainers = self.search_for_explainers(uid, query['text'], team_id, limit, language).select{ |explainer| explainer.as_tipline_search_result.should_send_in_language?(language) }
Rails.logger.info "[Smooch Bot] Text similarity search got #{explainers.count} explainers while looking for '#{query['text']}' for team #{team_id}"
- results = explainers.collect{ |explainer| explainer.project_medias.to_a }.flatten.uniq.reject{ |pm| pm.blank? }.first(3)
+ results = explainers.collect{ |explainer| explainer.project_medias.to_a }.flatten.uniq.reject{ |pm| pm.blank? }.first(limit)
reports = explainers.map(&:as_tipline_search_result)
end
@@ -100,9 +101,9 @@ def reject_temporary_results(results)
end
end
- def parse_search_results_from_alegre(results, after = nil, feed_id = nil, team_ids = nil)
+ def parse_search_results_from_alegre(results, limit, after = nil, feed_id = nil, team_ids = nil)
pms = reject_temporary_results(results).sort_by{ |a| [a[1][:model] != Bot::Alegre::ELASTICSEARCH_MODEL ? 1 : 0, a[1][:score]] }.to_h.keys.reverse.collect{ |id| Relationship.confirmed_parent(ProjectMedia.find_by_id(id)) }
- filter_search_results(pms, after, feed_id, team_ids).uniq(&:id).sort_by{ |pm| pm.report_status == 'published' ? 0 : 1 }.first(3)
+ filter_search_results(pms, after, feed_id, team_ids).uniq(&:id).first(limit)
end
def date_filter(team_id)
@@ -127,14 +128,14 @@ def get_search_query(uid, last_message)
self.bundle_list_of_messages(list, last_message, true)
end
- def get_search_results(uid, message, team_id, language)
+ def get_search_results(uid, message, team_id, language, limit)
results = []
begin
type = message['type']
after = self.date_filter(team_id)
query = message['text']
query = CheckS3.rewrite_url(message['mediaUrl']) unless type == 'text'
- results = self.search_for_similar_published_fact_checks(type, query, [team_id], after, nil, language).select{ |pm| is_a_valid_search_result(pm) }
+ results = self.search_for_similar_published_fact_checks(type, query, [team_id], limit, after, nil, language).select{ |pm| is_a_valid_search_result(pm) }
rescue StandardError => e
self.handle_search_error(uid, e, language)
end
@@ -148,19 +149,19 @@ def normalized_query_hash(type, query, team_ids, after, feed_id, language)
# "type" is text, video, audio or image
# "query" is either a piece of text of a media URL
- def search_for_similar_published_fact_checks(type, query, team_ids, after = nil, feed_id = nil, language = nil, skip_cache = false)
+ def search_for_similar_published_fact_checks(type, query, team_ids, limit, after = nil, feed_id = nil, language = nil, skip_cache = false)
if skip_cache
- self.search_for_similar_published_fact_checks_no_cache(type, query, team_ids, after, feed_id, language)
+ self.search_for_similar_published_fact_checks_no_cache(type, query, team_ids, limit, after, feed_id, language)
else
Rails.cache.fetch("smooch:search_results:#{self.normalized_query_hash(type, query, team_ids, after, feed_id, language)}", expires_in: 2.hours) do
- self.search_for_similar_published_fact_checks_no_cache(type, query, team_ids, after, feed_id, language)
+ self.search_for_similar_published_fact_checks_no_cache(type, query, team_ids, limit, after, feed_id, language)
end
end
end
# "type" is text, video, audio or image
# "query" is either a piece of text of a media URL
- def search_for_similar_published_fact_checks_no_cache(type, query, team_ids, after = nil, feed_id = nil, language = nil)
+ def search_for_similar_published_fact_checks_no_cache(type, query, team_ids, limit, after = nil, feed_id = nil, language = nil)
results = []
pm = nil
pm = ProjectMedia.new(team_id: team_ids[0]) if team_ids.size == 1 # We'll use the settings of a team instead of global settings when there is only one team
@@ -179,10 +180,10 @@ def search_for_similar_published_fact_checks_no_cache(type, query, team_ids, aft
words = text.split(/\s+/)
Rails.logger.info "[Smooch Bot] Search query (text): #{text}"
if Bot::Alegre.get_number_of_words(text) <= self.max_number_of_words_for_keyword_search
- results = self.search_by_keywords_for_similar_published_fact_checks(words, after, team_ids, feed_id, language)
+ results = self.search_by_keywords_for_similar_published_fact_checks(words, after, team_ids, limit, feed_id, language)
else
alegre_results = Bot::Alegre.get_merged_similar_items(pm, [{ value: self.get_text_similarity_threshold }], Bot::Alegre::ALL_TEXT_SIMILARITY_FIELDS, text, team_ids)
- results = self.parse_search_results_from_alegre(alegre_results, after, feed_id, team_ids)
+ results = self.parse_search_results_from_alegre(alegre_results, limit, after, feed_id, team_ids)
Rails.logger.info "[Smooch Bot] Text similarity search got #{results.count} results while looking for '#{text}' after date #{after.inspect} for teams #{team_ids}"
end
else
@@ -192,7 +193,7 @@ def search_for_similar_published_fact_checks_no_cache(type, query, team_ids, aft
media_url = self.save_locally_and_return_url(media_url, type, feed_id)
threshold = Bot::Alegre.get_threshold_for_query(type, pm)[0][:value]
alegre_results = Bot::Alegre.get_items_with_similar_media_v2(media_url: media_url, threshold: [{ value: threshold }], team_ids: team_ids, type: type)
- results = self.parse_search_results_from_alegre(alegre_results, after, feed_id, team_ids)
+ results = self.parse_search_results_from_alegre(alegre_results, limit, after, feed_id, team_ids)
Rails.logger.info "[Smooch Bot] Media similarity search got #{results.count} results while looking for '#{query}' after date #{after.inspect} for teams #{team_ids}"
end
results
@@ -245,11 +246,11 @@ def should_restrict_by_language?(team_ids)
!!tbi&.alegre_settings&.dig('single_language_fact_checks_enabled')
end
- def search_by_keywords_for_similar_published_fact_checks(words, after, team_ids, feed_id = nil, language = nil)
+ def search_by_keywords_for_similar_published_fact_checks(words, after, team_ids, limit, feed_id = nil, language = nil)
types = CheckSearch::MEDIA_TYPES.clone.push('blank')
search_fields = %w(title description fact_check_title fact_check_summary extracted_text url claim_description_content)
- filters = { keyword: words.join('+'), keyword_fields: { fields: search_fields }, sort: 'recent_activity', eslimit: 3, show: types }
- filters.merge!({ fc_language: [language] }) if should_restrict_by_language?(team_ids)
+ filters = { keyword: words.join('+'), keyword_fields: { fields: search_fields }, sort: 'recent_activity', eslimit: limit, show: types }
+ filters.merge!({ fc_language: [language] }) if !language.blank? && should_restrict_by_language?(team_ids)
filters.merge!({ sort: 'score' }) if words.size > 1 # We still want to be able to return the latest fact-checks if a meaninful query is not passed
feed_id.blank? ? filters.merge!({ report_status: ['published'] }) : filters.merge!({ feed_id: feed_id })
filters.merge!({ range: { updated_at: { start_time: after.strftime('%Y-%m-%dT%H:%M:%S.%LZ') } } }) unless after.blank?
@@ -304,19 +305,19 @@ def ask_for_feedback_when_all_search_results_are_received(app_id, language, work
end
end
- def search_for_explainers(uid, query, team_id, language)
+ def search_for_explainers(uid, query, team_id, limit, language = nil)
results = nil
begin
text = ::Bot::Smooch.extract_claim(query)
if Bot::Alegre.get_number_of_words(text) == 1
results = Explainer.where(team_id: team_id).where('description ILIKE ? OR title ILIKE ?', "%#{text}%", "%#{text}%")
- results = results.where(language: language) if should_restrict_by_language?([team_id])
+ results = results.where(language: language) if !language.nil? && should_restrict_by_language?([team_id])
results = results.order('updated_at DESC')
else
- results = Explainer.search_by_similarity(text, language, team_id)
+ results = Explainer.search_by_similarity(text, language, team_id, limit)
end
rescue StandardError => e
- self.handle_search_error(uid, e, language)
+ self.handle_search_error(uid, e, language) unless uid.blank?
end
results.joins(:project_medias)
end
diff --git a/app/models/explainer.rb b/app/models/explainer.rb
index aa25ea9e4..6303c157e 100644
--- a/app/models/explainer.rb
+++ b/app/models/explainer.rb
@@ -1,12 +1,6 @@
class Explainer < ApplicationRecord
include Article
- # FIXME: Read from workspace settings
- ALEGRE_MODELS_AND_THRESHOLDS = {
- # Bot::Alegre::ELASTICSEARCH_MODEL => 0.8 # Sometimes this is easier for local development
- Bot::Alegre::PARAPHRASE_MULTILINGUAL_MODEL => 0.7
- }
-
belongs_to :team
has_annotations
@@ -71,13 +65,14 @@ def self.update_paragraphs_in_alegre(id, previous_paragraphs_count, timestamp)
explainer_id: explainer.id
}
+ models_thresholds = Explainer.get_alegre_models_and_thresholds(explainer.team_id).keys
# Index title
params = {
content_hash: Bot::Alegre.content_hash_for_value(explainer.title),
doc_id: Digest::MD5.hexdigest(['explainer', explainer.id, 'title'].join(':')),
context: base_context.merge({ field: 'title' }),
text: explainer.title,
- models: ALEGRE_MODELS_AND_THRESHOLDS.keys,
+ models: models_thresholds,
}
Bot::Alegre.index_async_with_params(params, "text")
@@ -90,7 +85,7 @@ def self.update_paragraphs_in_alegre(id, previous_paragraphs_count, timestamp)
doc_id: Digest::MD5.hexdigest(['explainer', explainer.id, 'paragraph', count].join(':')),
context: base_context.merge({ paragraph: count }),
text: paragraph.strip,
- models: ALEGRE_MODELS_AND_THRESHOLDS.keys,
+ models: models_thresholds,
}
Bot::Alegre.index_async_with_params(params, "text")
end
@@ -107,23 +102,35 @@ def self.update_paragraphs_in_alegre(id, previous_paragraphs_count, timestamp)
end
end
- def self.search_by_similarity(text, language, team_id)
+ def self.search_by_similarity(text, language, team_id, limit)
+ models_thresholds = Explainer.get_alegre_models_and_thresholds(team_id)
+ context = {
+ type: 'explainer',
+ team: Team.find(team_id).slug
+ }
+ context[:language] = language unless language.nil?
params = {
text: text,
- models: ALEGRE_MODELS_AND_THRESHOLDS.keys,
- per_model_threshold: ALEGRE_MODELS_AND_THRESHOLDS,
- context: {
- type: 'explainer',
- team: Team.find(team_id).slug,
- language: language
- }
+ models: models_thresholds.keys,
+ per_model_threshold: models_thresholds,
+ context: context
+
}
response = Bot::Alegre.query_sync_with_params(params, "text")
results = response['result'].to_a.sort_by{ |result| result['_score'] }
- explainer_ids = results.collect{ |result| result.dig('context', 'explainer_id').to_i }.uniq.first(3)
+ explainer_ids = results.collect{ |result| result.dig('context', 'explainer_id').to_i }.uniq.first(limit)
explainer_ids.empty? ? Explainer.none : Explainer.where(team_id: team_id, id: explainer_ids)
end
+ def self.get_alegre_models_and_thresholds(team_id)
+ models_thresholds = {}
+ Bot::Alegre.get_similarity_methods_and_models_given_media_type_and_team_id("text", team_id, true).map do |similarity_method, model_name|
+ _, value = Bot::Alegre.get_threshold_given_model_settings(team_id, "text", similarity_method, true, model_name)
+ models_thresholds[model_name] = value
+ end
+ models_thresholds
+ end
+
private
def set_team
diff --git a/app/models/project_media.rb b/app/models/project_media.rb
index ab169298d..e29adddb8 100644
--- a/app/models/project_media.rb
+++ b/app/models/project_media.rb
@@ -455,6 +455,22 @@ def replace_with_blank_media
self.save!
end
+ def get_similar_articles
+ # Get search query based on Media type
+ # Quote for Claim
+ # Transcription for UploadedVideo , UploadedAudio and UploadedImage
+ # Title and/or description for Link
+ media = self.media
+ search_query = case media.type
+ when 'Claim'
+ media.quote
+ when 'UploadedVideo', 'UploadedAudio', 'UploadedImage'
+ self.transcription
+ end
+ search_query ||= self.title
+ self.team.search_for_similar_articles(search_query, self)
+ end
+
protected
def add_extra_elasticsearch_data(ms)
diff --git a/app/models/team.rb b/app/models/team.rb
index 329b044e6..8b9e76274 100644
--- a/app/models/team.rb
+++ b/app/models/team.rb
@@ -563,6 +563,30 @@ def filter_by_keywords(query, filters, type = 'FactCheck')
query.where(Arel.sql("#{tsvector} @@ #{tsquery}"))
end
+ def search_for_similar_articles(query, pm = nil)
+ # query: expected to be text
+ # pm: to request a most relevant to specific item and also include both FactCheck & Explainer
+ limit = pm.nil? ? CheckConfig.get('most_relevant_team_limit', 3, :integer) : CheckConfig.get('most_relevant_item_limit', 10, :integer)
+ result_ids = Bot::Smooch.search_for_similar_published_fact_checks_no_cache('text', query, [self.id], limit).map(&:id)
+ items = []
+ unless result_ids.blank?
+ # I depend on FactCheck to filter result instead of report_design
+ items = FactCheck.where(report_status: 'published')
+ .joins(claim_description: :project_media)
+ .where('project_medias.id': result_ids)
+ # Exclude the ones already applied to a target item if exsits
+ items = items.where.not('fact_checks.id' => pm.fact_check_id) unless pm&.fact_check_id.nil?
+ end
+ if items.blank? || !pm.nil?
+ # Get Explainers if no fact-check returned or get similar_articles for a ProjectMedia
+ ex_items = Bot::Smooch.search_for_explainers(nil, query, self.id, limit)
+ # Exclude the ones already applied to a target item
+ ex_items = ex_items.where.not(id: pm.explainer_ids) unless pm&.explainer_ids.blank?
+ items = items + ex_items
+ end
+ items
+ end
+
# private
#
# Please add private methods to app/models/concerns/team_private.rb
diff --git a/app/resources/api/v2/feed_resource.rb b/app/resources/api/v2/feed_resource.rb
index ffabf372a..83f4c0212 100644
--- a/app/resources/api/v2/feed_resource.rb
+++ b/app/resources/api/v2/feed_resource.rb
@@ -38,26 +38,27 @@ def self.records(options = {}, skip_save_request = false, skip_cache = false)
skip_cache = skip_cache || filters.dig(:skip_cache, 0) == 'true'
return ProjectMedia.none if team_ids.blank? || query.blank?
-
+ limit = CheckConfig.get('most_relevant_team_limit', 3, :integer)
if feed_id > 0
- return get_results_from_feed_teams(team_ids, feed_id, query, type, after, webhook_url, skip_save_request, skip_cache)
+ return get_results_from_feed_teams(team_ids, feed_id, query, type, after, webhook_url, skip_save_request, skip_cache, limit)
elsif ApiKey.current
- return get_results_from_api_key_teams(type, query, after, skip_cache)
+ return get_results_from_api_key_teams(type, query, after, skip_cache, limit)
end
end
- def self.get_results_from_api_key_teams(type, query, after, skip_cache)
+ def self.get_results_from_api_key_teams(type, query, after, skip_cache, limit)
RequestStore.store[:pause_database_connection] = true # Release database connection during Bot::Alegre.request_api
team_ids = ApiKey.current.bot_user.team_ids
- Bot::Smooch.search_for_similar_published_fact_checks(type, query, team_ids, after, skip_cache)
+ limit = CheckConfig.get('most_relevant_team_limit', 3, :integer)
+ Bot::Smooch.search_for_similar_published_fact_checks(type, query, team_ids, limit, after, skip_cache)
end
- def self.get_results_from_feed_teams(team_ids, feed_id, query, type, after, webhook_url, skip_save_request, skip_cache)
+ def self.get_results_from_feed_teams(team_ids, feed_id, query, type, after, webhook_url, skip_save_request, skip_cache, limit)
return ProjectMedia.none unless can_read_feed?(feed_id, team_ids)
feed = Feed.find(feed_id)
RequestStore.store[:pause_database_connection] = true # Release database connection during Bot::Alegre.request_api
RequestStore.store[:smooch_bot_settings] = feed.get_smooch_bot_settings.to_h
- results = Bot::Smooch.search_for_similar_published_fact_checks(type, query, feed.team_ids, after, feed_id, skip_cache)
+ results = Bot::Smooch.search_for_similar_published_fact_checks(type, query, feed.team_ids, limit, after, feed_id, skip_cache)
Feed.delay({ retry: 0, queue: 'feed' }).save_request(feed_id, type, query, webhook_url, results.to_a.map(&:id)) unless skip_save_request
results
end
diff --git a/config/routes.rb b/config/routes.rb
index e4bc0fa4e..e2c6f3d51 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -79,5 +79,6 @@
match '/test/suggest_similarity' => 'test#suggest_similarity_item', via: :get
match '/test/install_bot' => 'test#install_bot', via: :get
match '/test/add_team_user' => 'test#add_team_user', via: :get
+ match '/test/create_imported_standalone_fact_check' => 'test#create_imported_standalone_fact_check', via: :get
match '/test/random' => 'test#random', via: :get
end
diff --git a/lib/relay.idl b/lib/relay.idl
index b672574b3..f65bcb1b2 100644
--- a/lib/relay.idl
+++ b/lib/relay.idl
@@ -11666,6 +11666,28 @@ type ProjectMedia implements Node {
published: String
pusher_channel: String
quote: String
+ relevant_articles(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): ArticleUnionConnection
+ relevant_articles_count: Int
report_status: String
report_type: String
requests(
diff --git a/public/relay.json b/public/relay.json
index 2fc923085..c2387c828 100644
--- a/public/relay.json
+++ b/public/relay.json
@@ -61591,6 +61591,81 @@
"isDeprecated": false,
"deprecationReason": null
},
+ {
+ "name": "relevant_articles",
+ "description": null,
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ArticleUnionConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "relevant_articles_count",
+ "description": null,
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
{
"name": "report_status",
"description": null,
diff --git a/test/controllers/feeds_controller_test.rb b/test/controllers/feeds_controller_test.rb
index bced9ac47..534872db7 100644
--- a/test/controllers/feeds_controller_test.rb
+++ b/test/controllers/feeds_controller_test.rb
@@ -26,7 +26,7 @@ def setup
@f = create_feed published: true
@f.teams = [@t1, @t2]
FeedTeam.update_all(shared: true)
- Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false).returns([@pm1, @pm2])
+ Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false).returns([@pm1, @pm2])
end
def teardown
@@ -44,7 +44,7 @@ def teardown
b.api_key = a
b.save!
create_team_user team: @t1, user: b
- Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id], nil, false).returns([@pm1])
+ Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id], 3, nil, false).returns([@pm1])
authenticate_with_token a
get :index, params: { filter: { type: 'text', query: 'Foo' } }
@@ -55,7 +55,7 @@ def teardown
test "should request feed data" do
Bot::Smooch.stubs(:search_for_similar_published_fact_checks)
- .with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false)
+ .with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false)
.returns([@pm1, @pm2])
authenticate_with_token @a
get :index, params: { filter: { type: 'text', query: 'Foo', feed_id: @f.id } }
@@ -68,13 +68,13 @@ def teardown
Sidekiq::Testing.fake! do
authenticate_with_token @a
- Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false).returns([@pm1, @pm2])
+ Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false).returns([@pm1, @pm2])
get :index, params: { filter: { type: 'text', query: 'Foo', feed_id: @f.id } }
assert_response :success
assert_equal 'Foo', json_response['data'][0]['attributes']['organization']
assert_equal 'Bar', json_response['data'][1]['attributes']['organization']
- Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false).returns([@pm2, @pm1])
+ Bot::Smooch.stubs(:search_for_similar_published_fact_checks).with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false).returns([@pm2, @pm1])
get :index, params: { filter: { type: 'text', query: 'Foo', feed_id: @f.id } }
assert_response :success
assert_equal 'Bar', json_response['data'][0]['attributes']['organization']
@@ -111,7 +111,7 @@ def teardown
test "should save request query" do
Bot::Alegre.stubs(:request).returns({})
Bot::Smooch.stubs(:search_for_similar_published_fact_checks)
- .with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false)
+ .with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false)
.returns([@pm1, @pm2])
Sidekiq::Testing.inline!
authenticate_with_token @a
@@ -129,7 +129,7 @@ def teardown
test "should save relationship between request and results" do
Bot::Alegre.stubs(:request).returns({})
Bot::Smooch.stubs(:search_for_similar_published_fact_checks)
- .with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false)
+ .with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false)
.returns([@pm1, @pm2])
Sidekiq::Testing.inline!
authenticate_with_token @a
@@ -143,7 +143,7 @@ def teardown
test "should not save request when skip_save_request is true" do
Bot::Alegre.stubs(:request).returns({})
Bot::Smooch.stubs(:search_for_similar_published_fact_checks)
- .with('text', 'Foo', [@t1.id, @t2.id], nil, @f.id, false)
+ .with('text', 'Foo', [@t1.id, @t2.id], 3, nil, @f.id, false)
.returns([@pm1, @pm2])
Sidekiq::Testing.inline!
authenticate_with_token @a
diff --git a/test/controllers/graphql_controller_5_test.rb b/test/controllers/graphql_controller_5_test.rb
index e85a1918b..78e778827 100644
--- a/test/controllers/graphql_controller_5_test.rb
+++ b/test/controllers/graphql_controller_5_test.rb
@@ -405,6 +405,25 @@ def setup
assert_equal 'Test', JSON.parse(@response.body)['data']['createTag']['tag_text_object']['text']
end
+ test "should get relevant articles for ProjectMedia item" do
+ t = create_team
+ pm = create_project_media quote: 'Foo Bar', team: t
+ ex = create_explainer language: 'en', team: t, title: 'Foo Bar'
+ pm.explainers << ex
+ cd = create_claim_description description: pm.title, project_media: pm
+ fc = create_fact_check claim_description: cd, title: pm.title
+ items = FactCheck.where(id: fc.id) + Explainer.where(id: ex.id)
+ ProjectMedia.any_instance.stubs(:get_similar_articles).returns(items)
+ query = "query { project_media(ids: \"#{pm.id}\") { relevant_articles_count, relevant_articles { edges { node { ... on FactCheck { dbid }, ... on Explainer { dbid } } } } } }"
+ post :create, params: { query: query, team: t.slug }
+ assert_response :success
+ data = JSON.parse(@response.body)['data']['project_media']
+ assert_equal 2, data['relevant_articles_count']
+ item_ids = data['relevant_articles']['edges'].collect{ |i| i['node']['dbid'] }
+ assert_equal items.map(&:id).sort, item_ids.sort
+ ProjectMedia.any_instance.unstub(:get_similar_articles)
+ end
+
protected
def assert_error_message(expected)
diff --git a/test/controllers/test_controller_test.rb b/test/controllers/test_controller_test.rb
index eb9fef1b8..94eaed620 100644
--- a/test/controllers/test_controller_test.rb
+++ b/test/controllers/test_controller_test.rb
@@ -493,6 +493,53 @@ class TestControllerTest < ActionController::TestCase
Rails.unstub(:env)
end
+ test "should create standalone fact check and associate with the team" do
+ # Test setup
+ team = create_team
+ user = create_user
+ create_team_user(user: user, team: team)
+
+ assert_difference 'FactCheck.count' do
+ get :create_imported_standalone_fact_check, params: {
+ team_id: team.id,
+ email: user.email,
+ description: 'Test description',
+ context: 'Test context',
+ title: 'Test title',
+ summary: 'Test summary',
+ url: 'http://example.com',
+ language: 'en'
+ }
+ end
+
+ assert_response :success
+ end
+
+ test "should not create standalone fact check and associate with the team" do
+ Rails.stubs(:env).returns('development')
+
+ # Test setup
+ team = create_team
+ user = create_user
+ create_team_user(user: user, team: team)
+
+ assert_no_difference 'FactCheck.count' do
+ get :create_imported_standalone_fact_check, params: {
+ team_id: team.id,
+ email: user.email,
+ description: 'Test description',
+ context: 'Test context',
+ title: 'Test title',
+ summary: 'Test summary',
+ url: 'http://example.com',
+ language: 'en'
+ }
+ end
+
+ assert_response 400
+ Rails.unstub(:env)
+ end
+
test "should get a random number in HTML" do
get :random
assert_response :success
diff --git a/test/models/bot/smooch_3_test.rb b/test/models/bot/smooch_3_test.rb
index 843b40602..f3cb76cdd 100644
--- a/test/models/bot/smooch_3_test.rb
+++ b/test/models/bot/smooch_3_test.rb
@@ -691,10 +691,10 @@ def teardown
'Segurança das urna',
'Seguranca das urnas'
].each do |query|
- assert_equal [pm1.id], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id]).to_a.map(&:id)
+ assert_equal [pm1.id], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], 3).to_a.map(&:id)
end
- assert_equal [], Bot::Smooch.search_for_similar_published_fact_checks('text', 'Segurando', [t.id]).to_a.map(&:id)
+ assert_equal [], Bot::Smooch.search_for_similar_published_fact_checks('text', 'Segurando', [t.id], 3).to_a.map(&:id)
end
test "should get turn.io installation" do
diff --git a/test/models/bot/smooch_4_test.rb b/test/models/bot/smooch_4_test.rb
index 34167fa5f..611b0b07a 100644
--- a/test/models/bot/smooch_4_test.rb
+++ b/test/models/bot/smooch_4_test.rb
@@ -671,10 +671,10 @@ def teardown
uid = random_string
query = Bot::Smooch.get_search_query(uid, {})
- assert_equal [pm2], Bot::Smooch.get_search_results(uid, query, t.id, 'en')
+ assert_equal [pm2], Bot::Smooch.get_search_results(uid, query, t.id, 'en', 3)
Bot::Smooch.stubs(:bundle_list_of_messages).returns({ 'type' => 'text', 'text' => "Test #{url}" })
query = Bot::Smooch.get_search_query(uid, {})
- assert_equal [pm1], Bot::Smooch.get_search_results(uid, query, t.id, 'en')
+ assert_equal [pm1], Bot::Smooch.get_search_results(uid, query, t.id, 'en', 3)
ProjectMedia.any_instance.unstub(:report_status)
CheckSearch.any_instance.unstub(:medias)
@@ -694,7 +694,7 @@ def teardown
assert_nothing_raised do
with_current_user_and_team(nil, t) do
- Bot::Smooch.search_for_similar_published_fact_checks('text', 'https://projetocomprova.com.br/publicações/tuite-engana-ao-dizer-que-o-stf-decidiu-que-voto-impresso-e-inconstitucional/ ', [t.id], nil, f.id)
+ Bot::Smooch.search_for_similar_published_fact_checks('text', 'https://projetocomprova.com.br/publicações/tuite-engana-ao-dizer-que-o-stf-decidiu-que-voto-impresso-e-inconstitucional/ ', [t.id], 3, nil, f.id)
end
end
end
diff --git a/test/models/bot/smooch_5_test.rb b/test/models/bot/smooch_5_test.rb
index 93eef03af..49f90522d 100644
--- a/test/models/bot/smooch_5_test.rb
+++ b/test/models/bot/smooch_5_test.rb
@@ -68,16 +68,16 @@ def teardown
# and for each team participating in the feed
with_current_user_and_team(u, t1) do
# Keyword search
- result = Bot::Smooch.search_for_similar_published_fact_checks('text', 'Test', [t1.id, t2.id, t3.id, t4.id], nil, f1.id).map(&:id)
+ result = Bot::Smooch.search_for_similar_published_fact_checks('text', 'Test', [t1.id, t2.id, t3.id, t4.id], 3, nil, f1.id).map(&:id)
assert_equal [pm1a.id, pm1f.id, pm2a.id].sort, result.sort
# Text similarity search
- result = Bot::Smooch.search_for_similar_published_fact_checks('text', 'This is a test', [t1.id, t2.id, t3.id, t4.id], nil, f1.id).map(&:id)
+ result = Bot::Smooch.search_for_similar_published_fact_checks('text', 'This is a test', [t1.id, t2.id, t3.id, t4.id], 3, nil, f1.id).map(&:id)
assert_equal [pm1a.id, pm1d.id, pm2a.id].sort, result.sort
# Media similarity search
- result = Bot::Smooch.search_for_similar_published_fact_checks('image', random_url, [t1.id, t2.id, t3.id, t4.id], nil, f1.id).map(&:id)
+ result = Bot::Smooch.search_for_similar_published_fact_checks('image', random_url, [t1.id, t2.id, t3.id, t4.id], 3, nil, f1.id).map(&:id)
assert_equal [pm1a.id, pm1d.id, pm2a.id], result.sort
# URL search
- result = Bot::Smooch.search_for_similar_published_fact_checks('text', "Test with URL: #{url}", [t1.id, t2.id, t3.id, t4.id], nil, f1.id).map(&:id)
+ result = Bot::Smooch.search_for_similar_published_fact_checks('text', "Test with URL: #{url}", [t1.id, t2.id, t3.id, t4.id], 3, nil, f1.id).map(&:id)
assert_equal [pm1g.id, pm2b.id].sort, result.sort
end
diff --git a/test/models/bot/smooch_7_test.rb b/test/models/bot/smooch_7_test.rb
index 8aee9c2af..10217674c 100644
--- a/test/models/bot/smooch_7_test.rb
+++ b/test/models/bot/smooch_7_test.rb
@@ -219,7 +219,7 @@ def teardown
uid = random_string
query = Bot::Smooch.get_search_query(uid, {})
- assert_equal [pm], Bot::Smooch.get_search_results(uid, query, pm.team_id, 'en')
+ assert_equal [pm], Bot::Smooch.get_search_results(uid, query, pm.team_id, 'en', 3)
Bot::Smooch.unstub(:bundle_list_of_messages)
CheckSearch.any_instance.unstub(:medias)
@@ -242,7 +242,7 @@ def teardown
uid = random_string
query = Bot::Smooch.get_search_query(uid, {})
- assert_equal [pm], Bot::Smooch.get_search_results(uid, query, pm.team_id, 'en')
+ assert_equal [pm], Bot::Smooch.get_search_results(uid, query, pm.team_id, 'en', 3)
Bot::Smooch.unstub(:bundle_list_of_messages)
ProjectMedia.any_instance.unstub(:report_status)
@@ -266,7 +266,7 @@ def teardown
Bot::Alegre.stubs(:get_items_with_similar_media_v2).returns({ pm.id => { score: 0.9, model: 'elasticsearch', context: {foo: :bar} } })
CheckS3.stubs(:rewrite_url).returns(random_url)
- assert_equal [pm], Bot::Smooch.get_search_results(random_string, {}, pm.team_id, 'en')
+ assert_equal [pm], Bot::Smooch.get_search_results(random_string, {}, pm.team_id, 'en', 3)
Bot::Smooch.unstub(:bundle_list_of_messages)
ProjectMedia.any_instance.unstub(:report_status)
@@ -316,7 +316,7 @@ def teardown
# Create more project media if needed
results = { pm1.id => { model: 'elasticsearch', score: 10.8, context: {foo: :bar}}, pm2.id => { model: 'elasticsearch', score: 15.2, context: {foo: :bar}},
pm3.id => { model: 'anything-else', score: 1.98, context: {foo: :bar}}, pm4.id => { model: 'anything-else', score: 1.8, context: {foo: :bar}}}
- assert_equal [pm3, pm4, pm2], Bot::Smooch.parse_search_results_from_alegre(results, t.id)
+ assert_equal [pm3, pm4, pm2], Bot::Smooch.parse_search_results_from_alegre(results, 3, t.id)
ProjectMedia.any_instance.unstub(:report_status)
end
@@ -330,7 +330,7 @@ def teardown
# Create more project media if needed
results = { pm1.id => { model: 'elasticsearch', score: 10.8, context: {blah: 1} }, pm2.id => { model: 'elasticsearch', score: 15.2, context: {blah: 1} },
pm3.id => { model: 'anything-else', score: 1.98, context: {temporary_media: true} }, pm4.id => { model: 'anything-else', score: 1.8, context: {temporary_media: false}}}
- assert_equal [pm4, pm2, pm1], Bot::Smooch.parse_search_results_from_alegre(results, t.id)
+ assert_equal [pm4, pm2, pm1], Bot::Smooch.parse_search_results_from_alegre(results, 3, t.id)
ProjectMedia.any_instance.unstub(:report_status)
end
@@ -346,7 +346,7 @@ def teardown
Bot::Smooch.stubs(:bundle_list_of_messages).returns({ 'type' => 'text', 'text' => url })
CheckSearch.any_instance.stubs(:medias).returns([pm])
- assert_equal [], Bot::Smooch.get_search_results(random_string, {}, pm.team_id, 'en')
+ assert_equal [], Bot::Smooch.get_search_results(random_string, {}, pm.team_id, 'en', 3)
ProjectMedia.any_instance.unstub(:report_status)
CheckSearch.any_instance.unstub(:medias)
@@ -362,11 +362,11 @@ def teardown
query = 'foo bar'
assert_queries '>', 1 do
- assert_equal [pm], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], nil)
+ assert_equal [pm], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], 3, nil)
end
assert_queries '=', 0 do
- assert_equal [pm], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], nil)
+ assert_equal [pm], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], 3, nil)
end
ProjectMedia.any_instance.unstub(:report_status)
@@ -389,7 +389,7 @@ def teardown
'ward', #Fuzzy match (non-emoji)
'🤣 ward', #Fuzzy match (non-emoji)
].each do |query|
- assert_equal [pm.id], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id]).to_a.map(&:id)
+ assert_equal [pm.id], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], 3).to_a.map(&:id)
end
[
@@ -397,7 +397,7 @@ def teardown
'🌞', #No match
'🤣 🌞' #No match (we only perform AND)
].each do |query|
- assert_equal [], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id]).to_a.map(&:id)
+ assert_equal [], Bot::Smooch.search_for_similar_published_fact_checks('text', query, [t.id], 3).to_a.map(&:id)
end
end
@@ -412,9 +412,9 @@ def teardown
[pm1, pm2, pm3].each { |pm| publish_report(pm) }
sleep 2 # Wait for ElasticSearch to index content
- assert_equal [pm1.id, pm2.id, pm3.id], Bot::Smooch.search_for_similar_published_fact_checks('text', 'Foo Bar', [t.id]).to_a.map(&:id)
+ assert_equal [pm1.id, pm2.id, pm3.id], Bot::Smooch.search_for_similar_published_fact_checks('text', 'Foo Bar', [t.id], 3).to_a.map(&:id)
# Calling wiht skip_cache true
- assert_equal [pm1.id, pm2.id, pm3.id], Bot::Smooch.search_for_similar_published_fact_checks('text', 'Foo Bar', [t.id], nil, nil, nil, true).to_a.map(&:id)
+ assert_equal [pm1.id, pm2.id, pm3.id], Bot::Smooch.search_for_similar_published_fact_checks('text', 'Foo Bar', [t.id], 3, nil, nil, nil, true).to_a.map(&:id)
end
test "should store media" do
@@ -441,7 +441,7 @@ def teardown
test "should not return cache search result if report is not published anymore" do
pm = create_project_media
Bot::Smooch.stubs(:search_for_similar_published_fact_checks).returns([pm])
- assert_equal [], Bot::Smooch.get_search_results(random_string, {}, pm.team_id, 'en')
+ assert_equal [], Bot::Smooch.get_search_results(random_string, {}, pm.team_id, 'en', 3)
end
test "should store sent tipline message in background" do
@@ -609,12 +609,12 @@ def teardown
m = create_uploaded_image
pm = create_project_media team: t, media: m, disable_es_callbacks: false
query = "Claim content"
- results = Bot::Smooch.search_by_keywords_for_similar_published_fact_checks(query.split(), nil, [t.id])
+ results = Bot::Smooch.search_by_keywords_for_similar_published_fact_checks(query.split(), nil, [t.id], 3)
assert_empty results
cd = create_claim_description project_media: pm, description: query
publish_report(pm)
assert_equal query, pm.claim_description_content
- results = Bot::Smooch.search_by_keywords_for_similar_published_fact_checks(query.split(), nil, [t.id])
+ results = Bot::Smooch.search_by_keywords_for_similar_published_fact_checks(query.split(), nil, [t.id], 3)
assert_equal [pm.id], results.map(&:id)
end
diff --git a/test/models/explainer_test.rb b/test/models/explainer_test.rb
index 7d191e1e7..c694152dd 100644
--- a/test/models/explainer_test.rb
+++ b/test/models/explainer_test.rb
@@ -153,4 +153,10 @@ def setup
end
end
end
+
+ test "should get alegre models_and_thresholds in hash format" do
+ ex = create_explainer
+ models_thresholds = Explainer.get_alegre_models_and_thresholds(ex.team_id)
+ assert_kind_of Hash, models_thresholds
+ end
end
diff --git a/test/models/project_media_7_test.rb b/test/models/project_media_7_test.rb
index 73553e8b8..d83e68c18 100644
--- a/test/models/project_media_7_test.rb
+++ b/test/models/project_media_7_test.rb
@@ -115,4 +115,52 @@ def setup
2.times { create_project_media(team: t, set_original_claim: 'This is a claim.') }
end
end
+
+ test "should search for item similar articles" do
+ RequestStore.store[:skip_cached_field_update] = false
+ setup_elasticsearch
+ t = create_team
+ pm1 = create_project_media quote: 'Foo Bar', team: t
+ pm2 = create_project_media quote: 'Foo Bar Test', team: t
+ pm3 = create_project_media quote: 'Foo Bar Test Testing', team: t
+ ex1 = create_explainer language: 'en', team: t, title: 'Foo Bar'
+ ex2 = create_explainer language: 'en', team: t, title: 'Foo Bar Test'
+ ex3 = create_explainer language: 'en', team: t, title: 'Foo Bar Test Testing'
+ pm1.explainers << ex1
+ pm2.explainers << ex2
+ pm3.explainers << ex3
+ ex_ids = [ex1.id, ex2.id, ex3.id]
+ Bot::Smooch.stubs(:search_for_explainers).returns(Explainer.where(id: ex_ids))
+ # Should get explainer
+ assert_equal [ex2.id, ex3.id], pm1.get_similar_articles.map(&:id).sort
+ fact_checks = []
+ [pm1, pm2, pm3].each do |pm|
+ cd = create_claim_description description: pm.title, project_media: pm
+ fc = create_fact_check claim_description: cd, title: pm.title
+ fact_checks << fc.id
+ end
+ [pm1, pm2, pm3].each { |pm| publish_report(pm) }
+ sleep 1
+ fact_checks.delete(pm1.fact_check_id)
+ # Should get both explainer and FactCheck
+ assert_equal fact_checks.concat([ex2.id, ex3.id]).sort, pm1.get_similar_articles.map(&:id).sort
+ Bot::Smooch.unstub(:search_for_explainers)
+ # Test with media item
+ json_schema = {
+ type: 'object',
+ required: ['job_name'],
+ properties: {
+ text: { type: 'string' },
+ job_name: { type: 'string' },
+ last_response: { type: 'object' }
+ }
+ }
+ create_annotation_type_and_fields('Transcription', {}, json_schema)
+ img = create_uploaded_image
+ pm_i = create_project_media team: t, media: img
+ data = { 'job_status' => 'COMPLETED', 'transcription' => 'Foo Bar'}
+ a = create_dynamic_annotation annotation_type: 'transcription', annotated: pm_i, set_fields: { text: 'Foo Bar', job_name: '0c481e87f2774b1bd41a0a70d9b70d11', last_response: data }.to_json
+ sleep 1
+ assert_equal [pm1.fact_check_id, pm2.fact_check_id, pm3.fact_check_id].sort, pm_i.get_similar_articles.map(&:id).sort
+ end
end
diff --git a/test/models/team_2_test.rb b/test/models/team_2_test.rb
index 5b2df9544..82a0f237f 100644
--- a/test/models/team_2_test.rb
+++ b/test/models/team_2_test.rb
@@ -1549,4 +1549,38 @@ def setup
assert_equal 1, t.filtered_explainers(text: 'Foo Bar Alpha').count
assert_equal 0, t.filtered_fact_checks(text: 'Foo Bar Delta').count
end
+
+ test "should search for similar articles" do
+ RequestStore.store[:skip_cached_field_update] = false
+ setup_elasticsearch
+ t = create_team
+ pm1 = create_project_media quote: 'Foo Bar', team: t
+ pm2 = create_project_media quote: 'Foo Bar Test', team: t
+ pm3 = create_project_media quote: 'Foo Bar Test Testing', team: t
+ ex1 = create_explainer language: 'en', team: t, title: 'Foo Bar'
+ ex2 = create_explainer language: 'en', team: t, title: 'Foo Bar Test'
+ ex3 = create_explainer language: 'en', team: t, title: 'Foo Bar Test Testing'
+ pm1.explainers << ex1
+ pm2.explainers << ex2
+ pm3.explainers << ex3
+ ex_ids = [ex1.id, ex2.id, ex3.id]
+ Bot::Smooch.stubs(:search_for_explainers).returns(Explainer.where(id: ex_ids))
+ # Return Explainer if no FactCheck exists
+ assert_equal ex_ids, t.search_for_similar_articles('Foo Bar').map(&:id).sort
+ fact_checks = []
+ [pm1, pm2, pm3].each do |pm|
+ cd = create_claim_description description: pm.title, project_media: pm
+ fc = create_fact_check claim_description: cd, title: pm.title
+ fact_checks << fc.id
+ end
+ [pm1, pm2, pm3].each { |pm| publish_report(pm) }
+ sleep 2
+ # Should return FactCheck even there is an Explainer exists
+ assert_equal fact_checks.sort, t.search_for_similar_articles('Foo Bar').map(&:id).sort
+ # Verirfy limit option
+ stub_configs({ 'most_relevant_team_limit' => 1 }) do
+ assert_equal [fact_checks.first], t.search_for_similar_articles('Foo Bar').map(&:id).sort
+ end
+ Bot::Smooch.unstub(:search_for_explainers)
+ end
end