1
0
Fork 0
forked from gitea/nas

Merge branch 'kb_development' into kb_migration

This commit is contained in:
KMY 2023-09-16 13:43:32 +09:00
commit 24ee2fd4d7
26 changed files with 238 additions and 35 deletions

View file

@ -157,6 +157,6 @@ class AccountsIndex < Chewy::Index
field(:domain, type: 'keyword', value: ->(account) { account.domain || '' })
field(:display_name, type: 'text', analyzer: 'verbatim') { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
field(:username, type: 'text', analyzer: 'verbatim', value: ->(account) { [account.username, account.domain].compact.join('@') }) { field :edge_ngram, type: 'text', analyzer: 'edge_ngram', search_analyzer: 'verbatim' }
field(:text, type: 'text', analyzer: 'sudachi_analyzer', value: ->(account) { account.searchable_text }) { field :stemmed, type: 'text', analyzer: 'natural' }
field(:text, type: 'text', analyzer: 'sudachi_analyzer', value: ->(account) { account.searchable_text })
end
end

View file

@ -144,12 +144,12 @@ class PublicStatusesIndex < Chewy::Index
index_scope ::Status.unscoped
.kept
.indexable
.includes(:media_attachments, :preloadable_poll, :preview_cards, :tags)
.includes(:media_attachments, :preloadable_poll, :preview_cards, :tags, :account)
root date_detection: false do
field(:id, type: 'long')
field(:account_id, type: 'long')
field(:text, type: 'text', analyzer: 'sudachi_analyzer', value: ->(status) { status.searchable_text }) { field(:stemmed, type: 'text', analyzer: 'sudachi_analyzer') }
field(:text, type: 'text', analyzer: 'sudachi_analyzer', value: ->(status) { status.searchable_text })
field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) })
field(:language, type: 'keyword')
field(:domain, type: 'keyword', value: ->(status) { status.account.domain || '' })

View file

@ -145,6 +145,7 @@ class StatusesIndex < Chewy::Index
settings index: index_preset(refresh_interval: '30s', number_of_shards: 5), analysis: Rails.env.test? ? DEVELOPMENT_SETTINGS : PRODUCTION_SETTINGS
index_scope ::Status.unscoped.kept.without_reblogs.includes(
:account,
:media_attachments,
:preview_cards,
:local_mentioned,
@ -160,17 +161,26 @@ class StatusesIndex < Chewy::Index
if status.searchability == 'direct'
status.searchable_by.empty?
else
status.searchability == 'limited' ? status.account.domain.present? : false
status.searchability == 'limited' ? !status.local? : false
end
}
root date_detection: false do
field(:id, type: 'long')
field(:account_id, type: 'long')
field(:text, type: 'text', analyzer: 'sudachi_analyzer', value: ->(status) { status.searchable_text }) { field(:stemmed, type: 'text', analyzer: 'sudachi_analyzer') }
field(:text, type: 'text', analyzer: 'sudachi_analyzer', value: ->(status) { status.searchable_text })
field(:tags, type: 'text', analyzer: 'hashtag', value: ->(status) { status.tags.map(&:display_name) })
field(:searchable_by, type: 'long', value: ->(status) { status.searchable_by })
field(:mentioned_by, type: 'long', value: ->(status) { status.mentioned_by })
field(:favourited_by, type: 'long', value: ->(status) { status.favourited_by })
field(:reblogged_by, type: 'long', value: ->(status) { status.reblogged_by })
field(:bookmarked_by, type: 'long', value: ->(status) { status.bookmarked_by })
field(:bookmark_categoried_by, type: 'long', value: ->(status) { status.bookmark_categoried_by })
field(:emoji_reacted_by, type: 'long', value: ->(status) { status.emoji_reacted_by })
field(:referenced_by, type: 'long', value: ->(status) { status.referenced_by })
field(:voted_by, type: 'long', value: ->(status) { status.voted_by })
field(:searchability, type: 'keyword', value: ->(status) { status.compute_searchability })
field(:visibility, type: 'keyword', value: ->(status) { status.searchable_visibility })
field(:language, type: 'keyword')
field(:domain, type: 'keyword', value: ->(status) { status.account.domain || '' })
field(:properties, type: 'keyword', value: ->(status) { status.searchable_properties })

View file

@ -59,13 +59,15 @@ class Search extends PureComponent {
defaultOptions = [
{ label: <><mark>has:</mark> <FormattedList type='disjunction' value={['media', 'poll', 'embed']} /></>, action: e => { e.preventDefault(); this._insertText('has:') } },
{ label: <><mark>is:</mark> <FormattedList type='disjunction' value={['reply', 'sensitive']} /></>, action: e => { e.preventDefault(); this._insertText('is:') } },
{ label: <><mark>my:</mark> <FormattedList type='disjunction' value={['favourited', 'bookmarked', 'boosted']} /></>, action: e => { e.preventDefault(); this._insertText('my:') } },
{ label: <><mark>language:</mark> <FormattedMessage id='search_popout.language_code' defaultMessage='ISO language code' /></>, action: e => { e.preventDefault(); this._insertText('language:') } },
{ label: <><mark>from:</mark> <FormattedMessage id='search_popout.user' defaultMessage='user' /></>, action: e => { e.preventDefault(); this._insertText('from:') } },
{ label: <><mark>domain:</mark> <FormattedMessage id='search_popout.domain' defaultMessage='domain' /></>, action: e => { e.preventDefault(); this._insertText('domain:') } },
{ label: <><mark>before:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('before:') } },
{ label: <><mark>during:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('during:') } },
{ label: <><mark>after:</mark> <FormattedMessage id='search_popout.specific_date' defaultMessage='specific date' /></>, action: e => { e.preventDefault(); this._insertText('after:') } },
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library']} /></>, action: e => { e.preventDefault(); this._insertText('in:') } }
{ label: <><mark>in:</mark> <FormattedList type='disjunction' value={['all', 'library']} /></>, action: e => { e.preventDefault(); this._insertText('in:') } },
{ label: <><mark>order:</mark> <FormattedList type='disjunction' value={['desc', 'asc']} /></>, action: e => { e.preventDefault(); this._insertText('order:') } },
];
setRef = c => {

View file

@ -65,7 +65,10 @@ const appendToBookmarkCategoryStatusesById = (state, bookmarkCategoryId, statuse
};
const removeStatusFromBookmarkCategoryById = (state, bookmarkCategoryId, status) => {
return state.updateIn([bookmarkCategoryId, 'items'], items => items.delete(status));
if (state.getIn([bookmarkCategoryId, 'items'])) {
return state.updateIn([bookmarkCategoryId, 'items'], items => items.delete(status));
}
return state;
};
const removeStatusFromAllBookmarkCategories = (state, status) => {

View file

@ -493,7 +493,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
references = @object['references'].nil? ? [] : ActivityPub::FetchReferencesService.new.call(@status, @object['references'])
quote = @object['quote'] || @object['quoteUrl'] || @object['quoteURL'] || @object['_misskey_quote']
references << quote if quote
ProcessReferencesWorker.perform_async(@status.id, [], references)
ProcessReferencesService.perform_worker_async(@status, [], references)
end
def join_group!

View file

@ -9,7 +9,7 @@ class ActivityPub::Activity::Like < ActivityPub::Activity
return if @original_status.nil? || delete_arrived_first?(@json['id']) || reject_favourite?
if shortcode.nil?
if shortcode.nil? || !Setting.enable_emoji_reaction
process_favourite
else
process_emoji_reaction

View file

@ -3,9 +3,12 @@
class Importer::BaseImporter
# @param [Integer] batch_size
# @param [Concurrent::ThreadPoolExecutor] executor
def initialize(batch_size:, executor:)
def initialize(batch_size:, executor:, full: true, from: nil, to: nil)
@batch_size = batch_size
@executor = executor
@full = full
@from = from.to_date if from.present?
@to = to.to_date if to.present?
@wait_for = Concurrent::Set.new
end

View file

@ -27,6 +27,9 @@ class Importer::PublicStatusesIndexImporter < Importer::BaseImporter
end
def scope
Status.indexable.reorder(nil)
to_index = Status.indexable.reorder(nil)
to_index = to_index.where('statuses.created_at >= ?', @from) if @from.present?
to_index = to_index.where('statuses.created_at < ?', @to) if @to.present?
to_index
end
end

View file

@ -17,11 +17,13 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter
bulk = ActiveRecord::Base.connection_pool.with_connection do
to_index = index.adapter.default_scope.where(id: status_ids)
to_index = to_index.where('created_at >= ?', @from) if @from.present?
to_index = to_index.where('created_at < ?', @to) if @to.present?
crutches = Chewy::Index::Crutch::Crutches.new index, to_index
to_index.map do |object|
# This is unlikely to happen, but the post may have been
# un-interacted with since it was queued for indexing
if object.searchable_by.empty?
if object.searchable_by.empty? && %w(public private).exclude?(object.searchability)
deleted += 1
{ delete: { _id: object.id } }
else
@ -49,13 +51,15 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter
end
def scopes
[
targets = [
local_statuses_scope,
local_mentions_scope,
local_favourites_scope,
local_votes_scope,
local_bookmarks_scope,
]
targets << remote_searchable_scope if @full
targets
end
def local_mentions_scope
@ -77,4 +81,8 @@ class Importer::StatusesIndexImporter < Importer::BaseImporter
def local_statuses_scope
Status.local.select('"statuses"."id", COALESCE("statuses"."reblog_of_id", "statuses"."id") AS status_id')
end
def remote_searchable_scope
Status.remote_dynamic_searchability.select('"statuses"."id", COALESCE("statuses"."reblog_of_id", "statuses"."id") AS status_id')
end
end

View file

@ -4,6 +4,7 @@ class SearchQueryTransformer < Parslet::Transform
SUPPORTED_PREFIXES = %w(
has
is
my
language
from
before
@ -11,6 +12,8 @@ class SearchQueryTransformer < Parslet::Transform
during
in
domain
order
searchability
).freeze
class Query
@ -34,6 +37,18 @@ class SearchQueryTransformer < Parslet::Transform
search
end
def order_by
return @order_by if @order_by
@order_by = 'desc'
order_clauses.each { |clause| @order_by = clause.term }
@order_by
end
def valid
must_clauses.any? || must_not_clauses.any? || filter_clauses.any?
end
private
def clauses_by_operator
@ -56,6 +71,10 @@ class SearchQueryTransformer < Parslet::Transform
clauses_by_operator.fetch(:filter, [])
end
def order_clauses
clauses_by_operator.fetch(:order, [])
end
def indexes
case @flags['in']
when 'library'
@ -214,6 +233,7 @@ class SearchQueryTransformer < Parslet::Transform
if @term.start_with?('#')
{ match: { tags: { query: @term, operator: 'and' } } }
else
# Memo for checking when manually merge
# { multi_match: { type: 'most_fields', query: @term, fields: ['text', 'text.stemmed'], operator: 'and' } }
{ match_phrase: { text: { query: @term } } }
end
@ -236,11 +256,12 @@ class SearchQueryTransformer < Parslet::Transform
class PrefixClause
attr_reader :operator, :prefix, :term
def initialize(prefix, operator, term, options = {})
def initialize(prefix, operator, term, options = {}) # rubocop:disable Metrics/CyclomaticComplexity
@prefix = prefix
@negated = operator == '-'
@options = options
@operator = :filter
@statuses_index_only = false
case prefix
when 'has', 'is'
@ -274,13 +295,67 @@ class SearchQueryTransformer < Parslet::Transform
when 'in'
@operator = :flag
@term = term
when 'my'
@type = :term
@term = @options[:current_account]&.id
@statuses_index_only = true
case term
when 'favourited', 'favorited', 'fav'
@filter = :favourited_by
when 'boosted', 'bt'
@filter = :reblogged_by
when 'replied', 'mentioned', 're'
@filter = :mentioned_by
when 'referenced', 'ref'
@filter = :referenced_by
when 'emoji_reacted', 'stamped', 'stamp'
@filter = :emoji_reacted_by
when 'bookmarked', 'bm'
@filter = :bookmarked_by
when 'categoried', 'bmc'
@filter = :bookmark_categoried_by
when 'voted', 'vote'
@filter = :voted_by
when 'interacted', 'act'
@filter = :searchable_by
else
raise "Unknown prefix: my:#{term}"
end
when 'order'
@operator = :order
@term = case term
when 'asc'
term
else
'desc'
end
when 'searchability'
@filter = :searchablity
@type = :terms
@statuses_index_only = true
@term = case term
when 'public'
%w(public private direct limited)
when 'private'
%w(private direct limited)
when 'direct'
%w(direct limited)
else
%w(limited)
end
else
raise "Unknown prefix: #{prefix}"
end
end
def to_query
if @negated
if @statuses_index_only
if @negated
{ bool: { must_not: [{ term: { _index: StatusesIndex.index_name } }, { @type => { @filter => @term } }] } }
else
{ bool: { must: [{ term: { _index: StatusesIndex.index_name } }, { @type => { @filter => @term } }] } }
end
elsif @negated
{ bool: { must_not: { @type => { @filter => @term } } } }
else
{ @type => { @filter => @term } }
@ -302,7 +377,7 @@ class SearchQueryTransformer < Parslet::Transform
end
def domain_from_term(term)
return '' if %w(local me).include?(term)
return '' if ['local', 'me', Rails.configuration.x.local_domain].include?(term)
term
end

View file

@ -13,6 +13,10 @@
#
class BookmarkCategoryStatus < ApplicationRecord
include Paginable
update_index('statuses', :status) if Chewy.enabled?
belongs_to :bookmark_category
belongs_to :status
belongs_to :bookmark

View file

@ -5,6 +5,7 @@ module StatusSearchConcern
included do
scope :indexable, -> { without_reblogs.where(visibility: [:public, :login], searchability: nil).joins(:account).where(account: { indexable: true }) }
scope :remote_dynamic_searchability, -> { remote.where(searchability: [:public, :private]) }
end
def searchable_by
@ -13,18 +14,52 @@ module StatusSearchConcern
ids << account_id if local?
ids += local_mentioned.pluck(:id)
ids += local_favorited.pluck(:id)
ids += local_reblogged.pluck(:id)
ids += local_bookmarked.pluck(:id)
ids += local_emoji_reacted.pluck(:id)
ids += local_referenced.pluck(:id)
ids += preloadable_poll.local_voters.pluck(:id) if preloadable_poll.present?
ids += mentioned_by
ids += favourited_by
ids += reblogged_by
ids += bookmarked_by
ids += emoji_reacted_by
ids += referenced_by
ids += voted_by if preloadable_poll.present?
ids.uniq
end
end
def mentioned_by
@mentioned_by ||= local_mentioned.pluck(:id)
end
def favourited_by
@favourited_by ||= local_favorited.pluck(:id)
end
def reblogged_by
@reblogged_by ||= local_reblogged.pluck(:id)
end
def bookmarked_by
@bookmarked_by ||= local_bookmarked.pluck(:id)
end
def bookmark_categoried_by
@bookmark_categoried_by ||= local_bookmark_categoried.pluck(:id).uniq
end
def emoji_reacted_by
@emoji_reacted_by ||= local_emoji_reacted.pluck(:id)
end
def referenced_by
@referenced_by ||= local_referenced.pluck(:id)
end
def voted_by
return [] if preloadable_poll.blank?
@voted_by ||= preloadable_poll.local_voters.pluck(:id)
end
def searchable_text
[
spoiler_text,

View file

@ -86,6 +86,7 @@ class Status < ApplicationRecord
has_many :referenced_by_statuses, through: :referenced_by_status_objects, class_name: 'Status', source: :status
has_many :capability_tokens, class_name: 'StatusCapabilityToken', inverse_of: :status, dependent: :destroy
has_many :bookmark_category_relationships, class_name: 'BookmarkCategoryStatus', inverse_of: :status, dependent: :destroy
has_many :bookmark_categories, class_name: 'BookmarkCategory', through: :bookmark_category_relationships, source: :bookmark_category
has_many :joined_bookmark_categories, class_name: 'BookmarkCategory', through: :bookmark_category_relationships, source: :bookmark_category
# Those associations are used for the private search index
@ -93,6 +94,7 @@ class Status < ApplicationRecord
has_many :local_favorited, -> { merge(Account.local) }, through: :favourites, source: :account
has_many :local_reblogged, -> { merge(Account.local) }, through: :reblogs, source: :account
has_many :local_bookmarked, -> { merge(Account.local) }, through: :bookmarks, source: :account
has_many :local_bookmark_categoried, -> { merge(Account.local) }, through: :bookmark_categories, source: :account
has_many :local_emoji_reacted, -> { merge(Account.local) }, through: :emoji_reactions, source: :account
has_many :local_referenced, -> { merge(Account.local) }, through: :referenced_by_statuses, source: :account
@ -435,6 +437,12 @@ class Status < ApplicationRecord
compute_searchability
end
def searchable_visibility
return limited_scope if limited_visibility? && !none_limited?
visibility
end
class << self
def selectable_visibilities
visibilities.keys - %w(direct limited)

View file

@ -48,7 +48,7 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:display_media] = object.current_account.user.setting_display_media
store[:display_media_expand] = object.current_account.user.setting_display_media_expand
store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers
store[:enable_emoji_reaction] = object.current_account.user.setting_enable_emoji_reaction
store[:enable_emoji_reaction] = object.current_account.user.setting_enable_emoji_reaction && Setting.enable_emoji_reaction
store[:show_emoji_reaction_on_timeline] = object.current_account.user.setting_show_emoji_reaction_on_timeline
store[:enable_login_privacy] = object.current_account.user.setting_enable_login_privacy
store[:enable_dtl_menu] = object.current_account.user.setting_enable_dtl_menu
@ -66,6 +66,7 @@ class InitialStateSerializer < ActiveModel::Serializer
store[:reduce_motion] = Setting.reduce_motion
store[:use_blurhash] = Setting.use_blurhash
store[:enable_emoji_reaction] = Setting.enable_emoji_reaction
store[:show_emoji_reaction_on_timeline] = Setting.enable_emoji_reaction
end
store[:disabled_account_id] = object.disabled_account.id.to_s if object.disabled_account

View file

@ -103,7 +103,9 @@ class REST::StatusSerializer < ActiveModel::Serializer
end
def status_references_count
status_reference_ids.size
return status_reference_ids.size if status_reference_ids.any?
Rails.cache.exist?("status_reference:#{object.id}") ? 1 : 0
end
def reblogs_count

View file

@ -254,7 +254,8 @@ class ActivityPub::ProcessStatusUpdateService < BaseService
references = @json['references'].nil? ? [] : ActivityPub::FetchReferencesService.new.call(@status, @json['references'])
quote = @json['quote'] || @json['quoteUrl'] || @json['quoteURL'] || @json['_misskey_quote']
references << quote if quote
ProcessReferencesWorker.perform_async(@status.id, [], references)
ProcessReferencesService.perform_worker_async(@status, [], references)
end
def expected_type?

View file

@ -17,7 +17,7 @@ module Payloadable
payload = ActiveModelSerializers::SerializableResource.new(record, options.merge(serializer: serializer, adapter: ActivityPub::Adapter)).as_json
object = record.respond_to?(:virtual_object) ? record.virtual_object : record
if (object.respond_to?(:sign?) && object.sign?) && signer && (always_sign || signing_enabled?)
if ((object.respond_to?(:sign?) && object.sign?) && signer && (always_sign || signing_enabled?)) || object.is_a?(String)
ActivityPub::LinkedDataSignature.new(payload).sign!(signer, sign_with: sign_with)
else
payload

View file

@ -187,8 +187,8 @@ class PostStatusService < BaseService
@account.user.update!(settings_attributes: { default_privacy: @options[:visibility] }) if @account.user&.setting_stay_privacy && !@status.reply? && %i(public public_unlisted login unlisted private).include?(@status.visibility.to_sym) && @status.visibility.to_s != @account.user&.setting_default_privacy && !@dtl
process_hashtags_service.call(@status)
ProcessReferencesWorker.perform_async(@status.id, @reference_ids, [])
Trends.tags.register(@status)
ProcessReferencesService.perform_worker_async(@status, @reference_ids, [])
LinkCrawlWorker.perform_async(@status.id)
DistributionWorker.perform_async(@status.id)
ActivityPub::DistributionWorker.perform_async(@status.id)

View file

@ -2,6 +2,7 @@
class ProcessReferencesService < BaseService
include Payloadable
include FormattingHelper
DOMAIN = ENV['WEB_DOMAIN'] || ENV.fetch('LOCAL_DOMAIN', nil)
REFURL_EXP = /(RT|QT|BT|RN|RE)((:|;)?\s+|:|;)(#{URI::DEFAULT_PARSER.make_regexp(%w(http https))})/
@ -23,9 +24,22 @@ class ProcessReferencesService < BaseService
@status.save!
end
Rails.cache.delete("status_reference:#{@status.id}")
create_notifications!
end
def self.need_process?(status, reference_parameters, urls)
reference_parameters.any? || (urls || []).any? || FormattingHelper.extract_status_plain_text(status).scan(REFURL_EXP).pluck(3).uniq.any?
end
def self.perform_worker_async(status, reference_parameters, urls)
return unless need_process?(status, reference_parameters, urls)
Rails.cache.write("status_reference:#{status.id}", true, expires_in: 10.minutes)
ProcessReferencesWorker.perform_async(status.id, reference_parameters, urls)
end
private
def references
@ -51,7 +65,7 @@ class ProcessReferencesService < BaseService
def fetch_statuses!(urls)
(urls + @urls)
.map { |url| ResolveURLService.new.call(url) }
.map { |url| ResolveURLService.new.call(url, on_behalf_of: @status.account) }
.filter { |status| status }
end

View file

@ -16,8 +16,11 @@ class StatusesSearchService < BaseService
private
def status_search_results
request = parsed_query.request
results = request.collapse(field: :id).order(id: { order: :desc }).limit(@limit).offset(@offset).objects.compact
query = parsed_query
request = query.request
return [] unless query.valid
results = request.collapse(field: :id).order(id: { order: query.order_by }).limit(@limit).offset(@offset).objects.compact
account_ids = results.map(&:account_id)
account_domains = results.map(&:account_domain)
preloaded_relations = @account.relations_map(account_ids, account_domains)

View file

@ -161,7 +161,8 @@ class UpdateStatusService < BaseService
def update_references!
reference_ids = (@options[:status_reference_ids] || []).map(&:to_i).filter(&:positive?)
ProcessReferencesWorker.perform_async(@status.id, reference_ids, [])
ProcessReferencesService.perform_worker_async(@status, reference_ids, [])
end
def update_metadata!

View file

@ -25,8 +25,8 @@ module Mastodon::CLI
say('Let the WAR begin.', :red)
end
desc 'kokuraan', 'Ohagi is kokuraan'
def kokuraan
desc 'oguraan', 'Ohagi is oguraan'
def oguraan
say('I hate you.', :yellow)
end
end

View file

@ -20,6 +20,9 @@ module Mastodon::CLI
option :import, type: :boolean, default: true, desc: 'Import data from the database to the index'
option :clean, type: :boolean, default: true, desc: 'Remove outdated documents from the index'
option :reset_chewy, type: :boolean, default: false, desc: "Reset Chewy's internal index"
option :full, type: :boolean, default: false, desc: 'Import full data over Mastodon default importer'
option :from, type: :string, default: nil, desc: 'Statuses start date'
option :to, type: :string, default: nil, desc: 'Statuses end date'
desc 'deploy', 'Create or upgrade Elasticsearch indices and populate them'
long_desc <<~LONG_DESC
If Elasticsearch is empty, this command will create the necessary indices
@ -41,7 +44,7 @@ module Mastodon::CLI
end
pool = Concurrent::FixedThreadPool.new(options[:concurrency], max_queue: options[:concurrency] * 10)
importers = indices.index_with { |index| "Importer::#{index.name}Importer".constantize.new(batch_size: options[:batch_size], executor: pool) }
importers = indices.index_with { |index| "Importer::#{index.name}Importer".constantize.new(batch_size: options[:batch_size], executor: pool, full: options[:full], from: options[:from], to: options[:to]) }
progress = ProgressBar.create(total: nil, format: '%t%c/%u |%b%i| %e (%r docs/s)', autofinish: false)
Chewy::Stash::Specification.reset! if options[:reset_chewy]

View file

@ -21,6 +21,19 @@ describe Api::V1::CirclesController do
expect(response).to have_http_status(200)
end
end
describe 'GET #index' do
it 'returns http success' do
circle_id = circle.id.to_s
Fabricate(:circle)
get :index
expect(response).to have_http_status(200)
circle_ids = body_as_json.pluck(:id)
expect(circle_ids.size).to eq 1
expect(circle_ids).to include circle_id
end
end
end
context 'with the wrong user context' do

View file

@ -21,6 +21,19 @@ describe Api::V1::ListsController do
expect(response).to have_http_status(200)
end
end
describe 'GET #index' do
it 'returns http success' do
list_id = list.id.to_s
Fabricate(:list)
get :index
expect(response).to have_http_status(200)
list_ids = body_as_json.pluck(:id)
expect(list_ids.size).to eq 1
expect(list_ids).to include list_id
end
end
end
context 'with the wrong user context' do