Merge commit '391c089d0db58d731765dba730a5e1f2fe8570a6' into glitch-soc/merge-upstream

Conflicts:
- `.github/dependabot.yml`:
  We removed it from glitch-soc.
  Keep it deleted.
This commit is contained in:
Claire 2023-05-28 16:41:14 +02:00
commit 0e7466717f
56 changed files with 362 additions and 315 deletions

View file

@ -379,23 +379,6 @@ RSpec/EmptyExampleGroup:
RSpec/ExampleLength:
Max: 22
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: method_call, block
RSpec/ExpectChange:
Exclude:
- 'spec/controllers/admin/account_moderation_notes_controller_spec.rb'
- 'spec/controllers/admin/custom_emojis_controller_spec.rb'
- 'spec/controllers/admin/invites_controller_spec.rb'
- 'spec/controllers/admin/report_notes_controller_spec.rb'
- 'spec/controllers/concerns/accountable_concern_spec.rb'
- 'spec/controllers/invites_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/webauthn_credentials_controller_spec.rb'
- 'spec/models/admin/account_action_spec.rb'
- 'spec/services/suspend_account_service_spec.rb'
- 'spec/services/unsuspend_account_service_spec.rb'
- 'spec/workers/scheduler/accounts_statuses_cleanup_scheduler_spec.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: implicit, each, example

View file

@ -151,7 +151,7 @@ GEM
bundler-audit (0.9.1)
bundler (>= 1.2.0, < 3)
thor (~> 1.0)
capistrano (3.17.2)
capistrano (3.17.3)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
@ -269,7 +269,7 @@ GEM
faraday-rack (1.0.0)
faraday-retry (1.0.3)
fast_blank (1.0.1)
fastimage (2.2.6)
fastimage (2.2.7)
ffi (1.15.5)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)

View file

@ -1,37 +0,0 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { injectIntl, defineMessages } from 'react-intl';
import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
});
class LoadGap extends PureComponent {
static propTypes = {
disabled: PropTypes.bool,
maxId: PropTypes.string,
onClick: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
handleClick = () => {
this.props.onClick(this.props.maxId);
};
render () {
const { disabled, intl } = this.props;
return (
<button className='load-more load-gap' disabled={disabled} onClick={this.handleClick} aria-label={intl.formatMessage(messages.load_more)}>
<Icon id='ellipsis-h' />
</button>
);
}
}
export default injectIntl(LoadGap);

View file

@ -0,0 +1,36 @@
import { useCallback } from 'react';
import type { InjectedIntl } from 'react-intl';
import { injectIntl, defineMessages } from 'react-intl';
import { Icon } from 'mastodon/components/icon';
const messages = defineMessages({
load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
});
interface Props {
disabled: boolean;
maxId: string;
onClick: (maxId: string) => void;
intl: InjectedIntl;
}
export const LoadGap = injectIntl<Props>(
({ disabled, maxId, onClick, intl }) => {
const handleClick = useCallback(() => {
onClick(maxId);
}, [maxId, onClick]);
return (
<button
className='load-more load-gap'
disabled={disabled}
onClick={handleClick}
aria-label={intl.formatMessage(messages.load_more)}
>
<Icon id='ellipsis-h' />
</button>
);
}
);

View file

@ -114,7 +114,6 @@ class StatusActionBar extends ImmutablePureComponent {
handleShareClick = () => {
navigator.share({
text: this.props.status.get('search_index'),
url: this.props.status.get('url'),
}).catch((e) => {
if (e.name !== 'AbortError') console.error(e);
@ -256,6 +255,10 @@ class StatusActionBar extends ImmutablePureComponent {
menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy });
if (publicStatus && 'share' in navigator) {
menu.push({ text: intl.formatMessage(messages.share), action: this.handleShareClick });
}
if (publicStatus) {
menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed });
}
@ -352,10 +355,6 @@ class StatusActionBar extends ImmutablePureComponent {
reblogTitle = intl.formatMessage(messages.cannot_reblog);
}
const shareButton = ('share' in navigator) && publicStatus && (
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
);
const filterButton = this.props.onFilter && (
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.hide)} icon='eye' onClick={this.handleHideClick} />
);
@ -367,8 +366,6 @@ class StatusActionBar extends ImmutablePureComponent {
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} />
{shareButton}
{filterButton}
<div className='status__action-bar__dropdown'>

View file

@ -9,7 +9,7 @@ import RegenerationIndicator from 'mastodon/components/regeneration_indicator';
import StatusContainer from '../containers/status_container';
import LoadGap from './load_gap';
import { LoadGap } from './load_gap';
import ScrollableList from './scrollable_list';
export default class StatusList extends ImmutablePureComponent {

View file

@ -165,7 +165,6 @@ class Header extends ImmutablePureComponent {
const { account } = this.props;
navigator.share({
text: `${titleFromAccount(account)}\n${account.get('note_plain')}`,
url: account.get('url'),
}).catch((e) => {
if (e.name !== 'AbortError') console.error(e);

View file

@ -28,7 +28,7 @@ import {
} from '../../actions/notifications';
import Column from '../../components/column';
import ColumnHeader from '../../components/column_header';
import LoadGap from '../../components/load_gap';
import { LoadGap } from '../../components/load_gap';
import ScrollableList from '../../components/scrollable_list';
import NotificationsPermissionBanner from './components/notifications_permission_banner';

View file

@ -169,7 +169,6 @@ class ActionBar extends PureComponent {
handleShare = () => {
navigator.share({
text: this.props.status.get('search_index'),
url: this.props.status.get('url'),
});
};
@ -202,6 +201,11 @@ class ActionBar extends PureComponent {
}
menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy });
if ('share' in navigator) {
menu.push({ text: intl.formatMessage(messages.share), action: this.handleShare });
}
menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed });
menu.push(null);
}
@ -260,10 +264,6 @@ class ActionBar extends PureComponent {
}
}
const shareButton = ('share' in navigator) && publicStatus && (
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.share)} icon='share-alt' onClick={this.handleShare} /></div>
);
let replyIcon;
if (status.get('in_reply_to_id', null) === null) {
replyIcon = 'reply';
@ -287,12 +287,10 @@ class ActionBar extends PureComponent {
return (
<div className='detailed-status__action-bar'>
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} onClick={this.handleReplyClick} /></div>
<div className='detailed-status__button' ><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /></div>
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /></div>
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /></div>
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} /></div>
{shareButton}
<div className='detailed-status__action-bar-dropdown'>
<DropdownMenuContainer size={18} icon='ellipsis-h' disabled={!signedIn} status={status} items={menu} direction='left' title={intl.formatMessage(messages.more)} />
</div>

View file

@ -21,7 +21,7 @@ const Account = connect(state => ({
));
const mapStateToProps = (state) => ({
signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], '/auth/sign_up'),
signupUrl: state.getIn(['server', 'server', 'registrations', 'url'], null) || '/auth/sign_up',
});
const mapDispatchToProps = (dispatch) => ({

View file

@ -1,18 +1,10 @@
# frozen_string_literal: true
require 'set'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Accounts < Thor
include Helper
def self.exit_on_failure?
true
end
class Accounts < Base
option :all, type: :boolean
desc 'rotate [USERNAME]', 'Generate and broadcast new keys'
long_desc <<-LONG_DESC

19
lib/mastodon/cli/base.rb Normal file
View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require 'thor'
require_relative 'helper'
module Mastodon
module CLI
class Base < Thor
include CLI::Helper
def self.exit_on_failure?
true
end
end
end
end

View file

@ -1,17 +1,9 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Cache < Thor
include Helper
def self.exit_on_failure?
true
end
class Cache < Base
desc 'clear', 'Clear out the cache storage'
def clear
Rails.cache.clear

View file

@ -1,18 +1,10 @@
# frozen_string_literal: true
require 'concurrent'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class CanonicalEmailBlocks < Thor
include Helper
def self.exit_on_failure?
true
end
class CanonicalEmailBlocks < Base
desc 'find EMAIL', 'Find a given e-mail address in the canonical e-mail blocks'
long_desc <<-LONG_DESC
When suspending a local user, a hash of a "canonical" version of their e-mail

View file

@ -1,18 +1,10 @@
# frozen_string_literal: true
require 'concurrent'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Domains < Thor
include Helper
def self.exit_on_failure?
true
end
class Domains < Base
option :concurrency, type: :numeric, default: 5, aliases: [:c]
option :verbose, type: :boolean, aliases: [:v]
option :dry_run, type: :boolean

View file

@ -1,18 +1,10 @@
# frozen_string_literal: true
require 'concurrent'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class EmailDomainBlocks < Thor
include Helper
def self.exit_on_failure?
true
end
class EmailDomainBlocks < Base
desc 'list', 'List blocked e-mail domains'
def list
EmailDomainBlock.where(parent_id: nil).order(id: 'DESC').find_each do |entry|

View file

@ -1,16 +1,10 @@
# frozen_string_literal: true
require 'rubygems/package'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Emoji < Thor
def self.exit_on_failure?
true
end
class Emoji < Base
option :prefix
option :suffix
option :overwrite, type: :boolean

View file

@ -1,18 +1,11 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Feeds < Thor
include Helper
class Feeds < Base
include Redisable
def self.exit_on_failure?
true
end
option :all, type: :boolean, default: false
option :concurrency, type: :numeric, default: 5, aliases: [:c]
option :verbose, type: :boolean, aliases: [:v]

View file

@ -1,16 +1,10 @@
# frozen_string_literal: true
require 'rubygems/package'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class IpBlocks < Thor
def self.exit_on_failure?
true
end
class IpBlocks < Base
option :severity, required: true, enum: %w(no_access sign_up_requires_approval sign_up_block), desc: 'Severity of the block'
option :comment, aliases: [:c], desc: 'Optional comment'
option :duration, aliases: [:d], type: :numeric, desc: 'Duration of the block in seconds'

View file

@ -1,29 +1,25 @@
# frozen_string_literal: true
require 'thor'
require_relative 'media'
require_relative 'emoji'
require_relative 'base'
require_relative 'accounts'
require_relative 'cache'
require_relative 'canonical_email_blocks'
require_relative 'domains'
require_relative 'email_domain_blocks'
require_relative 'emoji'
require_relative 'feeds'
require_relative 'ip_blocks'
require_relative 'maintenance'
require_relative 'media'
require_relative 'preview_cards'
require_relative 'search'
require_relative 'settings'
require_relative 'statuses'
require_relative 'domains'
require_relative 'preview_cards'
require_relative 'cache'
require_relative 'upgrade'
require_relative 'email_domain_blocks'
require_relative 'canonical_email_blocks'
require_relative 'ip_blocks'
require_relative 'maintenance'
require_relative '../version'
module Mastodon::CLI
class Main < Thor
def self.exit_on_failure?
true
end
class Main < Base
desc 'media SUBCOMMAND ...ARGS', 'Manage media files'
subcommand 'media', Media

View file

@ -1,18 +1,10 @@
# frozen_string_literal: true
require 'tty-prompt'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Maintenance < Thor
include Helper
def self.exit_on_failure?
true
end
class Maintenance < Base
MIN_SUPPORTED_VERSION = 2019_10_01_213028
MAX_SUPPORTED_VERSION = 2022_11_04_133904

View file

@ -1,20 +1,13 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Media < Thor
class Media < Base
include ActionView::Helpers::NumberHelper
include Helper
VALID_PATH_SEGMENTS_SIZE = [7, 10].freeze
def self.exit_on_failure?
true
end
option :days, type: :numeric, default: 7, aliases: [:d]
option :prune_profiles, type: :boolean, default: false
option :remove_headers, type: :boolean, default: false

View file

@ -1,18 +1,11 @@
# frozen_string_literal: true
require 'tty-prompt'
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class PreviewCards < Thor
class PreviewCards < Base
include ActionView::Helpers::NumberHelper
include Helper
def self.exit_on_failure?
true
end
option :days, type: :numeric, default: 180
option :concurrency, type: :numeric, default: 5, aliases: [:c]

View file

@ -1,13 +1,9 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Search < Thor
include Helper
class Search < Base
# Indices are sorted by amount of data to be expected in each, so that
# smaller indices can go online sooner
INDICES = [

View file

@ -1,15 +1,9 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Registrations < Thor
def self.exit_on_failure?
true
end
class Registrations < Base
desc 'open', 'Open registrations'
def open
Setting.registrations_mode = 'open'
@ -37,7 +31,7 @@ module Mastodon::CLI
end
end
class Settings < Thor
class Settings < Base
desc 'registrations SUBCOMMAND ...ARGS', 'Manage state of registrations'
subcommand 'registrations', Registrations
end

View file

@ -1,18 +1,11 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Statuses < Thor
include Helper
class Statuses < Base
include ActionView::Helpers::NumberHelper
def self.exit_on_failure?
true
end
option :days, type: :numeric, default: 90
option :batch_size, type: :numeric, default: 1_000, aliases: [:b], desc: 'Number of records in each batch'
option :continue, type: :boolean, default: false, desc: 'If remove is not completed, execute from the previous continuation'

View file

@ -1,17 +1,9 @@
# frozen_string_literal: true
require_relative '../../../config/boot'
require_relative '../../../config/environment'
require_relative 'helper'
require_relative 'base'
module Mastodon::CLI
class Upgrade < Thor
include Helper
def self.exit_on_failure?
true
end
class Upgrade < Base
CURRENT_STORAGE_SCHEMA_VERSION = 1
option :dry_run, type: :boolean, default: false

View file

@ -100,7 +100,7 @@
"react-motion": "^0.5.2",
"react-notification": "^6.8.5",
"react-overlays": "^5.2.1",
"react-redux": "^7.2.9",
"react-redux": "^8.0.4",
"react-redux-loading-bar": "^5.0.4",
"react-router-dom": "^4.1.1",
"react-router-scroll-4": "^1.0.0-beta.1",
@ -165,7 +165,6 @@
"@types/react-intl": "2.3.18",
"@types/react-motion": "^0.0.33",
"@types/react-overlays": "^3.1.0",
"@types/react-redux": "^7.1.25",
"@types/react-router-dom": "^5.3.3",
"@types/react-select": "^5.0.1",
"@types/react-sparklines": "^1.7.2",
@ -181,12 +180,12 @@
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
"babel-jest": "^29.5.0",
"eslint": "^8.40.0",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"eslint-import-resolver-typescript": "^3.5.5",
"eslint-plugin-formatjs": "^4.10.1",
"eslint-plugin-import": "~2.27.5",
"eslint-plugin-jsdoc": "^44.2.4",
"eslint-plugin-jsdoc": "^44.2.5",
"eslint-plugin-jsx-a11y": "~6.7.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "~6.1.1",

View file

@ -19,7 +19,7 @@ RSpec.describe Admin::AccountModerationNotesController do
let(:params) { { account_moderation_note: { target_account_id: target_account.id, content: 'test content' } } }
it 'successfully creates a note' do
expect { subject }.to change { AccountModerationNote.count }.by(1)
expect { subject }.to change(AccountModerationNote, :count).by(1)
expect(subject).to redirect_to admin_account_path(target_account.id)
end
end
@ -28,7 +28,7 @@ RSpec.describe Admin::AccountModerationNotesController do
let(:params) { { account_moderation_note: { target_account_id: target_account.id, content: '' } } }
it 'falls to create a note' do
expect { subject }.to_not change { AccountModerationNote.count }
expect { subject }.to_not change(AccountModerationNote, :count)
expect(subject).to render_template 'admin/accounts/show'
end
end
@ -41,7 +41,7 @@ RSpec.describe Admin::AccountModerationNotesController do
let(:account) { Fabricate(:account) }
it 'destroys note' do
expect { subject }.to change { AccountModerationNote.count }.by(-1)
expect { subject }.to change(AccountModerationNote, :count).by(-1)
expect(subject).to redirect_to admin_account_path(target_account.id)
end
end

View file

@ -42,7 +42,7 @@ describe Admin::CustomEmojisController do
let(:params) { { shortcode: 'test', image: image } }
it 'creates custom emoji' do
expect { subject }.to change { CustomEmoji.count }.by(1)
expect { subject }.to change(CustomEmoji, :count).by(1)
end
end

View file

@ -26,7 +26,7 @@ describe Admin::InvitesController do
subject { post :create, params: { invite: { max_uses: '10', expires_in: 1800 } } }
it 'succeeds to create a invite' do
expect { subject }.to change { Invite.count }.by(1)
expect { subject }.to change(Invite, :count).by(1)
expect(subject).to redirect_to admin_invites_path
expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
end

View file

@ -25,7 +25,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_resolve: nil } }
it 'creates a report note and resolves report' do
expect { subject }.to change { ReportNote.count }.by(1)
expect { subject }.to change(ReportNote, :count).by(1)
expect(report.reload).to be_action_taken
expect(subject).to redirect_to admin_reports_path
end
@ -35,7 +35,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
it 'creates a report note and does not resolve report' do
expect { subject }.to change { ReportNote.count }.by(1)
expect { subject }.to change(ReportNote, :count).by(1)
expect(report.reload).to_not be_action_taken
expect(subject).to redirect_to admin_report_path(report)
end
@ -50,7 +50,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id }, create_and_unresolve: nil } }
it 'creates a report note and unresolves report' do
expect { subject }.to change { ReportNote.count }.by(1)
expect { subject }.to change(ReportNote, :count).by(1)
expect(report.reload).to_not be_action_taken
expect(subject).to redirect_to admin_report_path(report)
end
@ -60,7 +60,7 @@ describe Admin::ReportNotesController do
let(:params) { { report_note: { content: 'test content', report_id: report.id } } }
it 'creates a report note and does not unresolve report' do
expect { subject }.to change { ReportNote.count }.by(1)
expect { subject }.to change(ReportNote, :count).by(1)
expect(report.reload).to be_action_taken
expect(subject).to redirect_to admin_report_path(report)
end
@ -85,7 +85,7 @@ describe Admin::ReportNotesController do
let!(:report_note) { Fabricate(:report_note) }
it 'deletes note' do
expect { subject }.to change { ReportNote.count }.by(-1)
expect { subject }.to change(ReportNote, :count).by(-1)
expect(subject).to redirect_to admin_report_path(report_note.report)
end
end

View file

@ -22,7 +22,7 @@ RSpec.describe AccountableConcern do
it 'creates Admin::ActionLog' do
expect do
hoge.log_action(:create, target)
end.to change { Admin::ActionLog.count }.by(1)
end.to change(Admin::ActionLog, :count).by(1)
end
end
end

View file

@ -52,7 +52,7 @@ describe InvitesController do
end
it 'succeeds to create a invite' do
expect { subject }.to change { Invite.count }.by(1)
expect { subject }.to change(Invite, :count).by(1)
expect(subject).to redirect_to invites_path
expect(Invite.last).to have_attributes(user_id: user.id, max_uses: 10)
end

View file

@ -134,7 +134,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
end
it 'does not change webauthn_id' do
expect { get :options }.to_not change { user.webauthn_id }
expect { get :options }.to_not change(user, :webauthn_id)
end
it 'includes existing credentials in list of excluded credentials' do
@ -238,7 +238,7 @@ describe Settings::TwoFactorAuthentication::WebauthnCredentialsController do
expect do
post :create, params: { credential: new_webauthn_credential, nickname: nickname }
end.to_not change { user.webauthn_id }
end.to_not change(user, :webauthn_id)
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/accounts'
describe Mastodon::CLI::Accounts do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/cache'
describe Mastodon::CLI::Cache do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/canonical_email_blocks'
describe Mastodon::CLI::CanonicalEmailBlocks do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/domains'
describe Mastodon::CLI::Domains do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/email_domain_blocks'
describe Mastodon::CLI::EmailDomainBlocks do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/emoji'
describe Mastodon::CLI::Emoji do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/feeds'
describe Mastodon::CLI::Feeds do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -3,9 +3,15 @@
require 'rails_helper'
require 'mastodon/cli/ip_blocks'
RSpec.describe Mastodon::CLI::IpBlocks do
describe Mastodon::CLI::IpBlocks do
let(:cli) { described_class.new }
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
describe '#add' do
let(:ip_list) do
[

View file

@ -4,6 +4,12 @@ require 'rails_helper'
require 'mastodon/cli/main'
describe Mastodon::CLI::Main do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
describe 'version' do
it 'returns the Mastodon version' do
expect { described_class.new.invoke(:version) }.to output(

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/maintenance'
describe Mastodon::CLI::Maintenance do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/media'
describe Mastodon::CLI::Media do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/preview_cards'
describe Mastodon::CLI::PreviewCards do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/search'
describe Mastodon::CLI::Search do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -3,7 +3,13 @@
require 'rails_helper'
require 'mastodon/cli/settings'
RSpec.describe Mastodon::CLI::Settings do
describe Mastodon::CLI::Settings do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
describe 'subcommand "registrations"' do
let(:cli) { Mastodon::CLI::Registrations.new }

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/statuses'
describe Mastodon::CLI::Statuses do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'rails_helper'
require 'mastodon/cli/upgrade'
describe Mastodon::CLI::Upgrade do
describe '.exit_on_failure?' do
it 'returns true' do
expect(described_class.exit_on_failure?).to be true
end
end
end

View file

@ -58,7 +58,7 @@ RSpec.describe Admin::AccountAction do
it 'creates Admin::ActionLog' do
expect do
subject
end.to change { Admin::ActionLog.count }.by 1
end.to change(Admin::ActionLog, :count).by 1
end
it 'calls process_email!' do

View file

@ -26,7 +26,7 @@ RSpec.describe SuspendAccountService, type: :service do
end
it 'does not change the “suspended” flag' do
expect { subject }.to_not change { account.suspended? }
expect { subject }.to_not change(account, :suspended?)
end
end

View file

@ -33,7 +33,7 @@ RSpec.describe UnsuspendAccountService, type: :service do
end
it 'does not change the “suspended” flag' do
expect { subject }.to_not change { account.suspended? }
expect { subject }.to_not change(account, :suspended?)
end
include_examples 'with common context' do
@ -86,7 +86,7 @@ RSpec.describe UnsuspendAccountService, type: :service do
end
it 'does not change the “suspended” flag' do
expect { subject }.to_not change { account.suspended? }
expect { subject }.to_not change(account, :suspended?)
end
end
@ -110,7 +110,7 @@ RSpec.describe UnsuspendAccountService, type: :service do
end
it 'marks account as suspended' do
expect { subject }.to change { account.suspended? }.from(false).to(true)
expect { subject }.to change(account, :suspended?).from(false).to(true)
end
end

View file

@ -103,7 +103,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
describe '#perform' do
context 'when the budget is lower than the number of toots to delete' do
it 'deletes as many statuses as the given budget' do
expect { subject.perform }.to change { Status.count }.by(-subject.compute_budget)
expect { subject.perform }.to change(Status, :count).by(-subject.compute_budget)
end
it 'does not delete from accounts with no cleanup policy' do
@ -117,7 +117,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
it 'eventually deletes every deletable toot given enough runs' do
stub_const 'Scheduler::AccountsStatusesCleanupScheduler::MAX_BUDGET', 4
expect { 10.times { subject.perform } }.to change { Status.count }.by(-30)
expect { 10.times { subject.perform } }.to change(Status, :count).by(-30)
end
it 'correctly round-trips between users across several runs' do
@ -125,7 +125,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
stub_const 'Scheduler::AccountsStatusesCleanupScheduler::PER_ACCOUNT_BUDGET', 2
expect { 3.times { subject.perform } }
.to change { Status.count }.by(-3 * 3)
.to change(Status, :count).by(-3 * 3)
.and change { account1.statuses.count }
.and change { account3.statuses.count }
.and change { account5.statuses.count }
@ -140,7 +140,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
it 'correctly handles looping in a single run' do
expect(subject.compute_budget).to eq(400)
expect { subject.perform }.to change { Status.count }.by(-30)
expect { subject.perform }.to change(Status, :count).by(-30)
end
end
@ -154,7 +154,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
it 'does not get stuck' do
expect(subject.compute_budget).to eq(400)
expect { subject.perform }.to_not change { Status.count }
expect { subject.perform }.to_not change(Status, :count)
end
end
end

103
yarn.lock
View file

@ -1062,7 +1062,7 @@
dependencies:
regenerator-runtime "^0.12.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.13.8", "@babel/runtime@^7.15.4", "@babel/runtime@^7.2.0", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.13.8", "@babel/runtime@^7.2.0", "@babel/runtime@^7.20.13", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.21.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200"
integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==
@ -1216,10 +1216,10 @@
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
"@es-joy/jsdoccomment@~0.39.3":
version "0.39.3"
resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.39.3.tgz#76b55203bf447d608e4e299ecb62d7ef14db72bb"
integrity sha512-q6pObzaS+aTA96kl4DF91QILNpSiDE8S89cQdJnhIc7hWzwIHPnfBnsiBVa0Z/R9pLHdZTnXEMnggGMmCq7HmA==
"@es-joy/jsdoccomment@~0.39.4":
version "0.39.4"
resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz#6b8a62e9b3077027837728818d3c4389a898b392"
integrity sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==
dependencies:
comment-parser "1.3.1"
esquery "^1.5.0"
@ -1252,10 +1252,10 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eslint/js@8.40.0":
version "8.40.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.40.0.tgz#3ba73359e11f5a7bd3e407f70b3528abfae69cec"
integrity sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==
"@eslint/js@8.41.0":
version "8.41.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.41.0.tgz#080321c3b68253522f7646b55b577dd99d2950b3"
integrity sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==
"@floating-ui/core@^1.0.1":
version "1.0.1"
@ -2006,7 +2006,7 @@
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
"@types/hoist-non-react-statics@^3.3.0":
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
@ -2222,26 +2222,6 @@
dependencies:
react-overlays "*"
"@types/react-redux@^7.1.20":
version "7.1.20"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.20.tgz#42f0e61ababb621e12c66c96dda94c58423bd7df"
integrity sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react-redux@^7.1.25":
version "7.1.25"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.25.tgz#de841631205b24f9dfb4967dd4a7901e048f9a88"
integrity sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==
dependencies:
"@types/hoist-non-react-statics" "^3.3.0"
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
"@types/react-router-dom@^5.3.3":
version "5.3.3"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
@ -2399,6 +2379,11 @@
dependencies:
source-map "^0.6.1"
"@types/use-sync-external-store@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
"@types/uuid@^9.0.0":
version "9.0.1"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.1.tgz#98586dc36aee8dacc98cc396dbca8d0429647aa6"
@ -5095,12 +5080,12 @@ eslint-plugin-import@~2.27.5:
semver "^6.3.0"
tsconfig-paths "^3.14.1"
eslint-plugin-jsdoc@^44.2.4:
version "44.2.4"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-44.2.4.tgz#0bdc163771504ec7330414eda6a7dbae67156ddb"
integrity sha512-/EMMxCyRh1SywhCb66gAqoGX4Yv6Xzc4bsSkF1AiY2o2+bQmGMQ05QZ5+JjHbdFTPDZY9pfn+DsSNP0a5yQpIg==
eslint-plugin-jsdoc@^44.2.5:
version "44.2.5"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-44.2.5.tgz#f3186f57f112a230b3b7af34bf236d207bc8d5d7"
integrity sha512-KtuhaYy2GmdY2IQE5t+1lup8O4P05c+V4gKcj45PCxFM0OxmRq2uQlfOS1AgYVgPYIBKGE86DxrbKP24HKpORA==
dependencies:
"@es-joy/jsdoccomment" "~0.39.3"
"@es-joy/jsdoccomment" "~0.39.4"
are-docs-informative "^0.0.2"
comment-parser "1.3.1"
debug "^4.3.4"
@ -5198,15 +5183,15 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
eslint@^8.40.0:
version "8.40.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.40.0.tgz#a564cd0099f38542c4e9a2f630fa45bf33bc42a4"
integrity sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==
eslint@^8.41.0:
version "8.41.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.41.0.tgz#3062ca73363b4714b16dbc1e60f035e6134b6f1c"
integrity sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==
dependencies:
"@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.4.0"
"@eslint/eslintrc" "^2.0.3"
"@eslint/js" "8.40.0"
"@eslint/js" "8.41.0"
"@humanwhocodes/config-array" "^0.11.8"
"@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8"
@ -5226,13 +5211,12 @@ eslint@^8.40.0:
find-up "^5.0.0"
glob-parent "^6.0.2"
globals "^13.19.0"
grapheme-splitter "^1.0.4"
graphemer "^1.4.0"
ignore "^5.2.0"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
is-path-inside "^3.0.3"
js-sdsl "^4.1.4"
js-yaml "^4.1.0"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
@ -6023,6 +6007,11 @@ grapheme-splitter@^1.0.4:
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
graphemer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@ -7429,11 +7418,6 @@ jpeg-js@^0.4.2:
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa"
integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==
js-sdsl@^4.1.4:
version "4.3.0"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711"
integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@ -9599,7 +9583,7 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^17.0.1, react-is@^17.0.2:
react-is@^17.0.1:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@ -9652,17 +9636,17 @@ react-redux-loading-bar@^5.0.4:
prop-types "^15.7.2"
react-lifecycles-compat "^3.0.4"
react-redux@^7.2.9:
version "7.2.9"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d"
integrity sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==
react-redux@^8.0.4:
version "8.0.5"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.5.tgz#e5fb8331993a019b8aaf2e167a93d10af469c7bd"
integrity sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==
dependencies:
"@babel/runtime" "^7.15.4"
"@types/react-redux" "^7.1.20"
"@babel/runtime" "^7.12.1"
"@types/hoist-non-react-statics" "^3.3.1"
"@types/use-sync-external-store" "^0.0.3"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^17.0.2"
react-is "^18.0.0"
use-sync-external-store "^1.0.0"
react-router-dom@^4.1.1:
version "4.3.1"
@ -11716,6 +11700,11 @@ use-latest@^1.2.1:
dependencies:
use-isomorphic-layout-effect "^1.1.1"
use-sync-external-store@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
use@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"