diff --git a/.github/workflows/crowdin-download.yml b/.github/workflows/crowdin-download.yml index d5023c53e7..bb82f65c75 100644 --- a/.github/workflows/crowdin-download.yml +++ b/.github/workflows/crowdin-download.yml @@ -53,7 +53,7 @@ jobs: # Create or update the pull request - name: Create Pull Request - uses: peter-evans/create-pull-request@v6.0.2 + uses: peter-evans/create-pull-request@v6.0.3 with: commit-message: 'New Crowdin translations' title: 'New Crowdin Translations (automated)' diff --git a/Gemfile.lock b/Gemfile.lock index 3de5ab5c7c..9df16248cf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -646,7 +646,7 @@ GEM rspec-mocks (~> 3.0) sidekiq (>= 5, < 8) rspec-support (3.13.1) - rubocop (1.62.1) + rubocop (1.63.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) diff --git a/app/helpers/theme_helper.rb b/app/helpers/theme_helper.rb index 95fe50bb58..bb8ef4547c 100644 --- a/app/helpers/theme_helper.rb +++ b/app/helpers/theme_helper.rb @@ -5,10 +5,10 @@ module ThemeHelper flavour, theme = flavour_and_skin if theme == 'system' - concat stylesheet_pack_tag("skins/#{flavour}/mastodon-light", media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') - concat stylesheet_pack_tag("skins/#{flavour}/default", media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') + stylesheet_pack_tag("skins/#{flavour}/mastodon-light", media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous') + + stylesheet_pack_tag("skins/#{flavour}/default", media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous') else - concat stylesheet_pack_tag "skins/#{flavour}/#{theme}", media: 'all', crossorigin: 'anonymous' + stylesheet_pack_tag "skins/#{flavour}/#{theme}", media: 'all', crossorigin: 'anonymous' end end @@ -16,8 +16,8 @@ module ThemeHelper _, theme = flavour_and_skin if theme == 'system' - concat tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') - concat tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') + tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:dark], media: '(prefers-color-scheme: dark)') + + tag.meta(name: 'theme-color', content: Themes::THEME_COLORS[:light], media: '(prefers-color-scheme: light)') else tag.meta name: 'theme-color', content: theme_color_for(theme) end diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx index 622ca525c1..e342958480 100644 --- a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx +++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx @@ -107,7 +107,7 @@ class KeyboardShortcuts extends ImmutablePureComponent { - s + s, / diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx index 77f26fed91..c84a2c51a4 100644 --- a/app/javascript/mastodon/features/ui/index.jsx +++ b/app/javascript/mastodon/features/ui/index.jsx @@ -89,7 +89,7 @@ const mapStateToProps = state => ({ const keyMap = { help: '?', new: 'n', - search: 's', + search: ['s', '/'], forceNew: 'option+n', toggleComposeSpoilers: 'option+x', focusColumn: ['1', '2', '3', '4', '5', '6', '7', '8', '9'], diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index 228a16def2..80a3479b46 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -89,6 +89,14 @@ "announcement.announcement": "Announcement", "attachments_list.unprocessed": "(unprocessed)", "audio.hide": "Hide audio", + "block_modal.remote_users_caveat": "We will ask the server {domain} to respect your decision. However, compliance is not guaranteed since some servers may handle blocks differently. Public posts may still be visible to non-logged-in users.", + "block_modal.show_less": "Show less", + "block_modal.show_more": "Show more", + "block_modal.they_cant_mention": "They can't mention or follow you.", + "block_modal.they_cant_see_posts": "They can't see your posts and you won't see theirs.", + "block_modal.they_will_know": "They can see that they're blocked.", + "block_modal.title": "Block user?", + "block_modal.you_wont_see_mentions": "You won't see posts that mention them.", "boost_modal.combo": "You can press {combo} to skip this next time", "bundle_column_error.copy_stacktrace": "Copy error report", "bundle_column_error.error.body": "The requested page could not be rendered. It could be due to a bug in our code, or a browser compatibility issue.", @@ -169,6 +177,7 @@ "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", "confirmations.discard_edit_media.confirm": "Discard", "confirmations.discard_edit_media.message": "You have unsaved changes to the media description or preview, discard them anyway?", + "confirmations.domain_block.confirm": "Block server", "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.", "confirmations.edit.confirm": "Edit", "confirmations.edit.message": "Editing now will overwrite the message you are currently composing. Are you sure you want to proceed?", @@ -431,6 +440,7 @@ "notifications.column_settings.admin.sign_up": "New sign-ups:", "notifications.column_settings.alert": "Desktop notifications", "notifications.column_settings.favourite": "Favourites:", + "notifications.column_settings.filter_bar.category": "Quick filter bar", "notifications.column_settings.follow": "New followers:", "notifications.column_settings.follow_request": "New follow requests:", "notifications.column_settings.mention": "Mentions:", @@ -456,6 +466,15 @@ "notifications.permission_denied": "Desktop notifications are unavailable due to previously denied browser permissions request", "notifications.permission_denied_alert": "Desktop notifications can't be enabled, as browser permission has been denied before", "notifications.permission_required": "Desktop notifications are unavailable because the required permission has not been granted.", + "notifications.policy.filter_new_accounts.hint": "Created within the past {days, plural, one {one day} other {# days}}", + "notifications.policy.filter_new_accounts_title": "New accounts", + "notifications.policy.filter_not_followers_hint": "Including people who have been following you fewer than {days, plural, one {one day} other {# days}}", + "notifications.policy.filter_not_followers_title": "People not following you", + "notifications.policy.filter_not_following_hint": "Until you manually approve them", + "notifications.policy.filter_not_following_title": "People you don't follow", + "notifications.policy.filter_private_mentions_hint": "Filtered unless it's in reply to your own mention or if you follow the sender", + "notifications.policy.filter_private_mentions_title": "Unsolicited private mentions", + "notifications.policy.title": "Filter out notifications from…", "notifications_permission_banner.enable": "Enable desktop notifications", "notifications_permission_banner.how_to_control": "To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled.", "notifications_permission_banner.title": "Never miss a thing", @@ -632,9 +651,11 @@ "status.direct": "Privately mention @{name}", "status.direct_indicator": "Private mention", "status.edit": "Edit", + "status.edited": "Last edited {date}", "status.edited_x_times": "Edited {count, plural, one {{count} time} other {{count} times}}", "status.embed": "Embed", "status.favourite": "Favourite", + "status.favourites": "{count, plural, one {favorite} other {favorites}}", "status.filter": "Filter this post", "status.filtered": "Filtered", "status.hide": "Hide post", @@ -655,6 +676,7 @@ "status.reblog": "Boost", "status.reblog_private": "Boost with original visibility", "status.reblogged_by": "{name} boosted", + "status.reblogs": "{count, plural, one {boost} other {boosts}}", "status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.", "status.redraft": "Delete & re-draft", "status.remove_bookmark": "Remove bookmark", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 40fec4f49c..bc57c4cee5 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -148,7 +148,7 @@ "compose.published.open": "Ireki", "compose.saved.body": "Argitalpena gorde da.", "compose_form.direct_message_warning_learn_more": "Ikasi gehiago", - "compose_form.encryption_warning": "Mastodoneko bidalketak ez daude muturretik muturrera enkriptatuta. Ez partekatu informazio sentikorrik Mastodonen.", + "compose_form.encryption_warning": "Mastodon-go bidalketak ez daude muturretik muturrera enkriptatuta. Ez partekatu informazio sentikorrik Mastodonen.", "compose_form.hashtag_warning": "Tut hau ez da inolako traolatan zerrendatuko, ez baita publikoa. Tut publikoak soilik traolen bitartez bila daitezke.", "compose_form.lock_disclaimer": "Zure kontua ez dago {locked}. Edonork jarraitu zaitzake zure jarraitzaileentzako soilik diren bidalketak ikusteko.", "compose_form.lock_disclaimer.lock": "giltzapetuta", @@ -345,7 +345,7 @@ "home.column_settings.show_reblogs": "Erakutsi bultzadak", "home.column_settings.show_replies": "Erakutsi erantzunak", "home.hide_announcements": "Ezkutatu iragarpenak", - "home.pending_critical_update.body": "Eguneratu zure Mastodoneko zerbitzaria leheinbailehen!", + "home.pending_critical_update.body": "Eguneratu zure Mastodon-go zerbitzaria leheinbailehen!", "home.pending_critical_update.link": "Ikusi eguneraketak", "home.pending_critical_update.title": "Segurtasun eguneraketa kritikoa eskuragarri!", "home.show_announcements": "Erakutsi iragarpenak", @@ -548,7 +548,7 @@ "onboarding.share.message": "{username} naiz #Mastodon-en! Jarrai nazazu hemen: {url}", "onboarding.share.next_steps": "Hurrengo urrats posibleak:", "onboarding.share.title": "Partekatu zure profila", - "onboarding.start.lead": "Mastodonen parte zara orain, bakarra eta deszentralizatua den sare-sozialaren plataforma, non zuk, eta ez algoritmo batek, zeure esperientzia pertsonaliza dezakezun. Igaro ezazu muga soziala:", + "onboarding.start.lead": "Mastodon-en parte zara orain, bakarra eta deszentralizatua den sare sozialaren plataforma, non zuk, eta ez algoritmo batek, zeure esperientzia pertsonaliza dezakezun. Igaro ezazu muga soziala:", "onboarding.start.skip": "Urrats guztiak saltatu nahi dituzu?", "onboarding.start.title": "Lortu duzu!", "onboarding.steps.follow_people.body": "Zure jarioa zuk pertsonalizatzen duzu. Bete dezagun jende interesgarriaz.", @@ -562,7 +562,7 @@ "onboarding.tips.2fa": "Bazenekien? Zure kontua babes dezakezu, bi faktoreko autentifikazioa zure kontuko ezarpenetan ezarriaz. Edozein TOTP aplikaziorekin dabil, ez da telefono-zenbakirik behar!", "onboarding.tips.accounts_from_other_servers": "Badakizu? Mastodon deszentralizatua denez, beste zerbitzarietako profilak topatuko dituzu. Eta, hala ere, arazorik gabe jardun dezakezu haiekin! Haien zerbitzaria erabiltzaile-izenaren bigarren erdian dago!", "onboarding.tips.migration": "Bazenekien? Uste baduzu {domain} ez dela aukera on bat zuretzako etorkizunari begira, beste Mastodon zerbitzari batera alda zaitezke, zure jarraitzaileak galdu gabe. Zure zerbitzaria propioa ere ostata dezakezu!", - "onboarding.tips.verification": "Bazenekien? Zure kontua egiazta dezakezu zure webgunean zure Mastodoneko profilaren esteka jarriz, eta profilean webgunea gehituz. Ordainketa edo dokumenturik gabe!", + "onboarding.tips.verification": "Bazenekien? Zure kontua egiazta dezakezu zure webgunean zure Mastodon-go profilaren esteka jarriz, eta profilean webgunea gehituz. Ordainketa edo dokumenturik gabe!", "password_confirmation.exceeds_maxlength": "Pasahitzaren berrespenak pasahitzaren gehienezko luzera gainditzen du", "password_confirmation.mismatching": "Pasahitzaren berrespena ez dator bat", "picture_in_picture.restore": "Leheneratu", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 249ba6632b..f1e1074ff4 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -701,7 +701,7 @@ "status.direct": "@{name} 님에게 개인적으로 멘션", "status.direct_indicator": "개인적인 멘션", "status.edit": "수정", - "status.edited": "%{date}에 마지막으로 편집됨", + "status.edited": "{date}에 마지막으로 편집됨", "status.edited_x_times": "{count}번 수정됨", "status.embed": "임베드", "status.favourite": "좋아요", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 952ed5adf5..4a7c224395 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -16,12 +16,12 @@ "account.badges.bot": "อัตโนมัติ", "account.badges.group": "กลุ่ม", "account.block": "ปิดกั้น @{name}", - "account.block_domain": "ปิดกั้นโดเมน {domain}", + "account.block_domain": "เลิกปิดกั้นโดเมน {domain} แล้ว", "account.block_short": "ปิดกั้น", "account.blocked": "ปิดกั้นอยู่", "account.browse_more_on_origin_server": "เรียกดูเพิ่มเติมในโปรไฟล์ดั้งเดิม", "account.cancel_follow_request": "ยกเลิกการติดตาม", - "account.copy": "คัดลอกลิงก์ไปยังโปรไฟล์", + "account.copy": "Copy link to profile", "account.direct": "กล่าวถึง @{name} แบบส่วนตัว", "account.disable_notifications": "หยุดแจ้งเตือนฉันเมื่อ @{name} โพสต์", "account.domain_blocked": "ปิดกั้นโดเมนอยู่", diff --git a/app/models/account.rb b/app/models/account.rb index 7b823bd59d..28dfbbe7c7 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -64,6 +64,7 @@ class Account < ApplicationRecord ) BACKGROUND_REFRESH_INTERVAL = 1.week.freeze + DEFAULT_FIELDS_SIZE = (ENV['MAX_PROFILE_FIELDS'] || 4).to_i INSTANCE_ACTOR_ID = -99 USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i @@ -88,7 +89,6 @@ class Account < ApplicationRecord MAX_DISPLAY_NAME_LENGTH = (ENV['MAX_DISPLAY_NAME_CHARS'] || 30).to_i MAX_NOTE_LENGTH = (ENV['MAX_BIO_CHARS'] || 500).to_i - DEFAULT_FIELDS_SIZE = (ENV['MAX_PROFILE_FIELDS'] || 4).to_i enum :protocol, { ostatus: 0, activitypub: 1 } enum :suspension_origin, { local: 0, remote: 1 }, prefix: true diff --git a/config/locales/devise.en-GB.yml b/config/locales/devise.en-GB.yml index 823be9aa6c..3e8a534e1f 100644 --- a/config/locales/devise.en-GB.yml +++ b/config/locales/devise.en-GB.yml @@ -12,6 +12,7 @@ en-GB: last_attempt: You have one more attempt before your account is locked. locked: Your account is locked. not_found_in_database: Invalid %{authentication_keys} or password. + omniauth_user_creation_failure: Error creating an account for this identity. pending: Your account is still under review. timeout: Your session expired. Please log in again to continue. unauthenticated: You need to log in or sign up before continuing. diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index a2f84b0932..df956902a6 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -597,6 +597,9 @@ en-GB: actions_description_html: Decide which action to take to resolve this report. If you take a punitive action against the reported account, an e-mail notification will be sent to them, except when the Spam category is selected. actions_description_remote_html: Decide which action to take to resolve this report. This will only affect how your server communicates with this remote account and handle its content. add_to_report: Add more to report + already_suspended_badges: + local: Already suspended on this server + remote: Already suspended on their server are_you_sure: Are you sure? assign_to_self: Assign to me assigned: Assigned moderator @@ -767,6 +770,7 @@ en-GB: disabled: To no one users: To logged-in local users registrations: + moderation_recommandation: Please make sure you have an adequate and reactive moderation team before you open registrations to everyone! preamble: Control who can create an account on your server. title: Registrations registrations_mode: @@ -774,6 +778,7 @@ en-GB: approved: Approval required for sign up none: Nobody can sign up open: Anyone can sign up + warning_hint: We recommend using “Approval required for sign up” unless you are confident your moderation team can handle spam and malicious registrations in a timely fashion. security: authorized_fetch: Require authentication from federated servers authorized_fetch_hint: Requiring authentication from federated servers enables stricter enforcement of both user-level and server-level blocks. However, this comes at the cost of a performance penalty, reduces the reach of your replies, and may introduce compatibility issues with some federated services. In addition, this will not prevent dedicated actors from fetching your public posts and accounts. @@ -966,6 +971,9 @@ en-GB: title: Webhooks webhook: Webhook admin_mailer: + auto_close_registrations: + body: Due to a lack of recent moderator activity, registrations on %{instance} have been automatically switched to requiring manual review, to prevent %{instance} from being used as a platform for potential bad actors. You can switch it back to open registrations at any time. + subject: Registrations for %{instance} have been automatically switched to requiring approval new_appeal: actions: delete_statuses: to delete their posts @@ -1647,13 +1655,26 @@ en-GB: import: Import import_and_export: Import and export migrate: Account migration + notifications: E-mail notifications preferences: Preferences profile: Profile relationships: Follows and followers + severed_relationships: Severed relationships statuses_cleanup: Automated post deletion strikes: Moderation strikes two_factor_authentication: Two-factor Auth webauthn_authentication: Security keys + severed_relationships: + download: Download (%{count}) + event_type: + account_suspension: Account suspension (%{target_name}) + domain_block: Server suspension (%{target_name}) + user_domain_block: You blocked %{target_name} + lost_followers: Lost followers + lost_follows: Lost follows + preamble: You may lose follows and followers when you block a domain or when your moderators decide to suspend a remote server. When that happens, you will be able to download lists of severed relationships, to be inspected and possibly imported on another server. + purged: Information about this server has been purged by your server's administrators. + type: Event statuses: attached: audio: @@ -1747,6 +1768,7 @@ en-GB: contrast: Mastodon (High contrast) default: Mastodon (Dark) mastodon-light: Mastodon (Light) + system: Automatic (use system theme) time: formats: default: "%b %d, %Y, %H:%M" @@ -1834,7 +1856,44 @@ en-GB: silence: Account limited suspend: Account suspended welcome: + apps_android_action: Get it on Google Play + apps_ios_action: Download on the App Store + apps_step: Download our official apps. + apps_title: Mastodon apps + checklist_subtitle: 'Let''s get you started on this new social frontier:' + checklist_title: Welcome Checklist + edit_profile_action: Personalise + edit_profile_step: Boost your interactions by having a comprehensive profile. + edit_profile_title: Personalise your profile explanation: Here are some tips to get you started + feature_action: Learn more + feature_audience: Mastodon provides you with a unique possibility of managing your audience without middlemen. Mastodon deployed on your own infrastructure allows you to follow and be followed from any other Mastodon server online and is under no one's control but yours. + feature_audience_title: Build your audience in confidence + feature_control: You know best what you want to see on your home feed. No algorithms or ads to waste your time. Follow anyone across any Mastodon server from a single account and receive their posts in chronological order, and make your corner of the Internet a little more like you. + feature_control_title: Stay in control of your own timeline + feature_creativity: Mastodon supports audio, video and picture posts, accessibility descriptions, polls, content warnings, animated avatars, custom emojis, thumbnail crop control, and more, to help you express yourself online. Whether you're publishing your art, your music, or your podcast, Mastodon is there for you. + feature_creativity_title: Unparalleled creativity + feature_moderation: Mastodon puts decision making back in your hands. Each server creates their own rules and regulations, which are enforced locally and not top-down like corporate social media, making it the most flexible in responding to the needs of different groups of people. Join a server with the rules you agree with, or host your own. + feature_moderation_title: Moderating the way it should be + follow_action: Follow + follow_step: Following interesting people is what Mastodon is all about. + follow_title: Personalise your home feed + follows_subtitle: Follow well-known accounts + follows_title: Who to follow + follows_view_more: View more people to follow + hashtags_recent_count: + one: "%{people} person in the past 2 days" + other: "%{people} people in the past 2 days" + hashtags_subtitle: Explore what’s trending since past 2 days + hashtags_title: Trending hashtags + hashtags_view_more: View more trending hashtags + post_action: Compose + post_step: Say hello to the world with text, photos, videos, or polls. + post_title: Make your first post + share_action: Share + share_step: Let your friends know how to find you on Mastodon. + share_title: Share your Mastodon profile + sign_in_action: Sign in subject: Welcome to Mastodon title: Welcome aboard, %{name}! users: diff --git a/config/locales/simple_form.en-GB.yml b/config/locales/simple_form.en-GB.yml index 2ac4508b05..e5c9b1b2b7 100644 --- a/config/locales/simple_form.en-GB.yml +++ b/config/locales/simple_form.en-GB.yml @@ -39,12 +39,14 @@ en-GB: text: You can only appeal a strike once defaults: autofollow: People who sign up through the invite will automatically follow you + avatar: WEBP, PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px bot: Signal to others that the account mainly performs automated actions and might not be monitored context: One or multiple contexts where the filter should apply current_password: For security purposes please enter the password of the current account current_username: To confirm, please enter the username of the current account digest: Only sent after a long period of inactivity and only if you have received any personal messages in your absence email: You will be sent a confirmation e-mail + header: WEBP, PNG, GIF or JPG. At most %{size}. Will be downscaled to %{dimensions}px inbox_url: Copy the URL from the frontpage of the relay you want to use irreversible: Filtered posts will disappear irreversibly, even if filter is later removed locale: The language of the user interface, e-mails and push notifications @@ -114,6 +116,7 @@ en-GB: sign_up_requires_approval: New sign-ups will require your approval severity: Choose what will happen with requests from this IP rule: + hint: Optional. Provide more details about the rule text: Describe a rule or requirement for users on this server. Try to keep it short and simple sessions: otp: 'Enter the two-factor code generated by your phone app or use one of your recovery codes:' @@ -297,6 +300,7 @@ en-GB: patch: Notify on bugfix updates trending_tag: New trend requires review rule: + hint: Additional information text: Rule settings: indexable: Include profile page in search engines diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml index 03ba1aea6c..5ed3b9efa1 100644 --- a/config/locales/simple_form.eu.yml +++ b/config/locales/simple_form.eu.yml @@ -3,7 +3,7 @@ eu: simple_form: hints: account: - discoverable: Zure bidalketa publikoak eta profila nabarmendu edo gomendatu egin daitezke Mastodoneko hainbat eremutan eta zure profila beste erabiltzaile batzuei iradoki dakieke. + discoverable: Zure bidalketa publikoak eta profila nabarmendu edo gomendatu egin daitezke Mastodon-go hainbat eremutan eta zure profila beste erabiltzaile batzuei iradoki dakieke. display_name: Zure izena edo ezizena. fields: Zure webgunea, izenordainak, adina, nahi duzun guztia. indexable: Zure argitalpen publikoak bilaketa-emaitzetan ager daitezke Mastodonen. Zure argitalpenekin elkarregin duten jendeak ikusi ahal izango dituzte, hala ere. diff --git a/config/locales/simple_form.tr.yml b/config/locales/simple_form.tr.yml index 16c23caeb0..758d1dc4de 100644 --- a/config/locales/simple_form.tr.yml +++ b/config/locales/simple_form.tr.yml @@ -228,7 +228,7 @@ tr: title: Başlık type: İçeri aktarma türü username: Kullanıcı adı - username_or_email: Kullanıcı adı ya da e-posta + username_or_email: Kullanıcı adı veya e-posta whole_word: Tam sözcük email_domain_block: with_dns_records: Alan adının MX kayıtlarını ve IP'lerini ekleyin @@ -269,7 +269,7 @@ tr: interactions: must_be_follower: Takipçim olmayan kişilerden gelen bildirimleri engelle must_be_following: Takip etmediğim kişilerden gelen bildirimleri engelle - must_be_following_dm: Takip etmediğiniz kişilerden gelen direkt mesajları engelle + must_be_following_dm: Takip etmediğiniz kişilerden gelen doğrudan iletileri engelle invite: comment: Yorum invite_request: diff --git a/config/locales/th.yml b/config/locales/th.yml index 2a05c892e7..17ff6a5ccb 100644 --- a/config/locales/th.yml +++ b/config/locales/th.yml @@ -1835,6 +1835,7 @@ th: edit_profile_title: ปรับแต่งโปรไฟล์ของคุณ explanation: นี่คือเคล็ดลับบางส่วนที่จะช่วยให้คุณเริ่มต้นใช้งาน feature_action: เรียนรู้เพิ่มเติม + feature_audience: Mastodon มีความพิเศษที่ให้คุณจัดการผู้รับสารของคุณได้โดยไม่มีตัวกลาง นอกจากนี้ การติดตั้ง Mastodon บนโครงสร้างพื้นฐานของคุณจะทำให้คุณสามารถติดตาม (และติดตามโดย) เซิร์ฟเวอร์ Mastodon แห่งไหนก็ได้ที่ทำงานอยู่ โดยไม่มีใครสามารถควบคุมได้นอกจากคุณ follow_action: ติดตาม follow_step: การติดตามผู้คนที่น่าสนใจคือสิ่งที่ Mastodon ให้ความสำคัญ follow_title: ปรับแต่งฟีดหน้าแรกของคุณ diff --git a/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb b/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb index 106717f97b..2b14e6956c 100644 --- a/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/instance_accounts_dimension_spec.rb @@ -3,16 +3,32 @@ require 'rails_helper' describe Admin::Metrics::Dimension::InstanceAccountsDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:limit) { 10 } - let(:params) { ActionController::Parameters.new } + let(:params) { ActionController::Parameters.new(domain: domain) } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + let(:domain) { 'host.example' } + let(:alice) { Fabricate(:account, domain: domain) } + let(:bob) { Fabricate(:account) } + + before do + Fabricate :follow, target_account: alice + Fabricate :follow, target_account: bob + Fabricate :status, account: alice + Fabricate :status, account: bob + end + + it 'returns instances with follow counts' do + expect(subject.data.size) + .to eq(1) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(key: alice.username, value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb b/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb index f9f6430ca0..e4e9fbe2b7 100644 --- a/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/instance_languages_dimension_spec.rb @@ -3,16 +3,30 @@ require 'rails_helper' describe Admin::Metrics::Dimension::InstanceLanguagesDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:limit) { 10 } - let(:params) { ActionController::Parameters.new } + let(:params) { ActionController::Parameters.new(domain: domain) } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + let(:domain) { 'host.example' } + let(:alice) { Fabricate(:account, domain: domain) } + let(:bob) { Fabricate(:account) } + + before do + Fabricate :status, account: alice, language: 'en' + Fabricate :status, account: bob, language: 'es' + end + + it 'returns locales with status counts' do + expect(subject.data.size) + .to eq(1) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(key: 'en', value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb b/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb index 7e2bb9ac0b..5661441d5d 100644 --- a/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/servers_dimension_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Dimension::ServersDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } @@ -11,8 +11,24 @@ describe Admin::Metrics::Dimension::ServersDimension do let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + let(:domain) { 'host.example' } + let(:alice) { Fabricate(:account, domain: domain) } + let(:bob) { Fabricate(:account) } + + before do + Fabricate :status, account: alice, created_at: 1.day.ago + Fabricate :status, account: alice, created_at: 30.days.ago + Fabricate :status, account: bob, created_at: 1.day.ago + end + + it 'returns domains with status counts' do + expect(subject.data.size) + .to eq(2) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(key: domain, value: '1'), + include(key: Rails.configuration.x.local_domain, value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb b/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb index ee14917330..5d31121ab3 100644 --- a/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/software_versions_dimension_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Dimension::SoftwareVersionsDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } @@ -11,8 +11,12 @@ describe Admin::Metrics::Dimension::SoftwareVersionsDimension do let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + it 'reports on the running software' do + expect(subject.data.map(&:symbolize_keys)) + .to include( + include(key: 'mastodon', value: Mastodon::Version.to_s), + include(key: 'ruby', value: include(RUBY_VERSION)) + ) end end end diff --git a/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb b/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb index d6b581a9bb..5fa5aa8af5 100644 --- a/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/sources_dimension_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Dimension::SourcesDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } @@ -11,8 +11,21 @@ describe Admin::Metrics::Dimension::SourcesDimension do let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + let(:app) { Fabricate(:application) } + let(:alice) { Fabricate(:user) } + let(:bob) { Fabricate(:user) } + + before do + alice.update(created_by_application: app) + end + + it 'returns OAuth applications with user counts' do + expect(subject.data.size) + .to eq(1) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(key: app.name, value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb b/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb index 65d04cfedd..96ff9c66dc 100644 --- a/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/space_usage_dimension_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Dimension::SpaceUsageDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } @@ -11,8 +11,13 @@ describe Admin::Metrics::Dimension::SpaceUsageDimension do let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + it 'reports on used storage space' do + expect(subject.data.map(&:symbolize_keys)) + .to include( + include(key: 'media', value: /\d/), + include(key: 'postgresql', value: /\d/), + include(key: 'redis', value: /\d/) + ) end end end diff --git a/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb b/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb index 721d24fa18..c1dfd0eaf4 100644 --- a/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/tag_languages_dimension_spec.rb @@ -3,16 +3,36 @@ require 'rails_helper' describe Admin::Metrics::Dimension::TagLanguagesDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:limit) { 10 } - let(:params) { ActionController::Parameters.new } + let(:params) { ActionController::Parameters.new(id: tag.id) } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + let(:alice) { Fabricate(:account) } + let(:bob) { Fabricate(:account) } + let(:tag) { Fabricate(:tag) } + + before do + alice_status_recent = Fabricate :status, account: alice, created_at: 1.day.ago, language: 'en' + alice_status_older = Fabricate :status, account: alice, created_at: 30.days.ago, language: 'en' + bob_status_recent = Fabricate :status, account: bob, created_at: 1.day.ago, language: 'es' + + alice_status_older.tags << tag + alice_status_recent.tags << tag + bob_status_recent.tags << tag + end + + it 'returns languages with tag usage counts' do + expect(subject.data.size) + .to eq(2) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(key: 'en', value: '1'), + include(key: 'es', value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb b/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb index 3054716816..025cf1b7ec 100644 --- a/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb +++ b/spec/lib/admin/metrics/dimension/tag_servers_dimension_spec.rb @@ -3,16 +3,37 @@ require 'rails_helper' describe Admin::Metrics::Dimension::TagServersDimension do - subject(:dimension) { described_class.new(start_at, end_at, limit, params) } + subject { described_class.new(start_at, end_at, limit, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:limit) { 10 } - let(:params) { ActionController::Parameters.new } + let(:params) { ActionController::Parameters.new(id: tag.id) } describe '#data' do - it 'runs data query without error' do - expect { dimension.data }.to_not raise_error + let(:alice) { Fabricate(:account, domain: domain) } + let(:bob) { Fabricate(:account) } + let(:domain) { 'host.example' } + let(:tag) { Fabricate(:tag) } + + before do + alice_status_recent = Fabricate :status, account: alice, created_at: 1.day.ago + alice_status_older = Fabricate :status, account: alice, created_at: 30.days.ago + bob_status_recent = Fabricate :status, account: bob, created_at: 1.day.ago + + alice_status_older.tags << tag + alice_status_recent.tags << tag + bob_status_recent.tags << tag + end + + it 'returns servers with tag usage counts' do + expect(subject.data.size) + .to eq(2) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(key: domain, value: '1'), + include(key: Rails.configuration.x.local_domain, value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/measure/active_users_measure_spec.rb b/spec/lib/admin/metrics/measure/active_users_measure_spec.rb index 55164ed88a..38ee14075b 100644 --- a/spec/lib/admin/metrics/measure/active_users_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/active_users_measure_spec.rb @@ -3,15 +3,38 @@ require 'rails_helper' describe Admin::Metrics::Measure::ActiveUsersMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with activity tracking records' do + before do + 3.times do + travel_to(2.days.ago) { record_login_activity } + end + 2.times do + travel_to(1.day.ago) { record_login_activity } + end + travel_to(0.days.ago) { record_login_activity } + end + + it 'returns correct activity tracker counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '3'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end + + def record_login_activity + ActivityTracker.record('activity:logins', Fabricate(:user).id) + end end end end diff --git a/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb index 8e414963f3..0d2ad31c39 100644 --- a/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/instance_accounts_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::InstanceAccountsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:domain) { 'example.com' } @@ -20,12 +20,13 @@ describe Admin::Metrics::Measure::InstanceAccountsMeasure do Fabricate(:account, domain: "foo.#{domain}", created_at: 1.year.ago) Fabricate(:account, domain: "foo.#{domain}") Fabricate(:account, domain: "bar.#{domain}") + Fabricate(:account, domain: 'other-host.example') end - describe 'total' do + describe '#total' do context 'without include_subdomains' do it 'returns the expected number of accounts' do - expect(measure.total).to eq 3 + expect(subject.total).to eq 3 end end @@ -33,14 +34,21 @@ describe Admin::Metrics::Measure::InstanceAccountsMeasure do let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } it 'returns the expected number of accounts' do - expect(measure.total).to eq 6 + expect(subject.total).to eq 6 end end end describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + it 'returns correct instance_accounts counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '0'), + include(date: 1.day.ago.midnight.to_time, value: '0'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) end end end diff --git a/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb index c627e6cede..27bf30d17d 100644 --- a/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/instance_followers_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::InstanceFollowersMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:domain) { 'example.com' } @@ -22,12 +22,14 @@ describe Admin::Metrics::Measure::InstanceFollowersMeasure do Fabricate(:account, domain: "foo.#{domain}").follow!(local_account) Fabricate(:account, domain: "foo.#{domain}").follow!(local_account) Fabricate(:account, domain: "bar.#{domain}") + + Fabricate(:account, domain: 'other.example').follow!(local_account) end - describe 'total' do + describe '#total' do context 'without include_subdomains' do it 'returns the expected number of accounts' do - expect(measure.total).to eq 2 + expect(subject.total).to eq 2 end end @@ -35,14 +37,21 @@ describe Admin::Metrics::Measure::InstanceFollowersMeasure do let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } it 'returns the expected number of accounts' do - expect(measure.total).to eq 4 + expect(subject.total).to eq 4 end end end describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + it 'returns correct instance_followers counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '0'), + include(date: 1.day.ago.midnight.to_time, value: '0'), + include(date: 0.days.ago.midnight.to_time, value: '2') + ) end end end diff --git a/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb index 42f33dfc35..9961ea56c4 100644 --- a/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/instance_follows_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::InstanceFollowsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:domain) { 'example.com' } @@ -24,10 +24,10 @@ describe Admin::Metrics::Measure::InstanceFollowsMeasure do Fabricate(:account, domain: "bar.#{domain}") end - describe 'total' do + describe '#total' do context 'without include_subdomains' do it 'returns the expected number of accounts' do - expect(measure.total).to eq 2 + expect(subject.total).to eq 2 end end @@ -35,14 +35,21 @@ describe Admin::Metrics::Measure::InstanceFollowsMeasure do let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } it 'returns the expected number of accounts' do - expect(measure.total).to eq 4 + expect(subject.total).to eq 4 end end end describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + it 'returns correct instance_followers counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '0'), + include(date: 1.day.ago.midnight.to_time, value: '0'), + include(date: 0.days.ago.midnight.to_time, value: '2') + ) end end end diff --git a/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb index c103307f97..3634450930 100644 --- a/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/instance_media_attachments_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:domain) { 'example.com' } @@ -20,11 +20,11 @@ describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do remote_account_on_subdomain.media_attachments.create!(file: attachment_fixture('attachment.jpg')) end - describe 'total' do + describe '#total' do context 'without include_subdomains' do it 'returns the expected number of accounts' do expected_total = remote_account.media_attachments.sum(:file_file_size) + remote_account.media_attachments.sum(:thumbnail_file_size) - expect(measure.total).to eq expected_total + expect(subject.total).to eq expected_total end end @@ -36,14 +36,25 @@ describe Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure do account.media_attachments.sum(:file_file_size) + account.media_attachments.sum(:thumbnail_file_size) end - expect(measure.total).to eq expected_total + expect(subject.total).to eq expected_total end end end describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + it 'returns correct media_attachments counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '0'), + include(date: 1.day.ago.midnight.to_time, value: '0'), + include(date: 0.days.ago.midnight.to_time, value: expected_domain_only_total.to_s) + ) + end + + def expected_domain_only_total + remote_account.media_attachments.sum(:file_file_size) + remote_account.media_attachments.sum(:thumbnail_file_size) end end end diff --git a/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb index 62fcf84ac1..ca64049d92 100644 --- a/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/instance_reports_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::InstanceReportsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:domain) { 'example.com' } @@ -21,10 +21,10 @@ describe Admin::Metrics::Measure::InstanceReportsMeasure do Fabricate(:report, target_account: Fabricate(:account, domain: "bar.#{domain}")) end - describe 'total' do + describe '#total' do context 'without include_subdomains' do it 'returns the expected number of accounts' do - expect(measure.total).to eq 2 + expect(subject.total).to eq 2 end end @@ -32,14 +32,21 @@ describe Admin::Metrics::Measure::InstanceReportsMeasure do let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } it 'returns the expected number of accounts' do - expect(measure.total).to eq 5 + expect(subject.total).to eq 5 end end end describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + it 'returns correct instance_reports counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '0'), + include(date: 1.day.ago.midnight.to_time, value: '0'), + include(date: 0.days.ago.midnight.to_time, value: '2') + ) end end end diff --git a/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb b/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb index df4cfe207b..ac28658ea0 100644 --- a/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/instance_statuses_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::InstanceStatusesMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:domain) { 'example.com' } @@ -21,10 +21,10 @@ describe Admin::Metrics::Measure::InstanceStatusesMeasure do Fabricate(:status, account: Fabricate(:account, domain: "bar.#{domain}")) end - describe 'total' do + describe '#total' do context 'without include_subdomains' do it 'returns the expected number of accounts' do - expect(measure.total).to eq 2 + expect(subject.total).to eq 2 end end @@ -32,14 +32,21 @@ describe Admin::Metrics::Measure::InstanceStatusesMeasure do let(:params) { ActionController::Parameters.new(domain: domain, include_subdomains: 'true') } it 'returns the expected number of accounts' do - expect(measure.total).to eq 5 + expect(subject.total).to eq 5 end end end describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + it 'returns correct instance_statuses counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '0'), + include(date: 1.day.ago.midnight.to_time, value: '0'), + include(date: 0.days.ago.midnight.to_time, value: '2') + ) end end end diff --git a/spec/lib/admin/metrics/measure/interactions_measure_spec.rb b/spec/lib/admin/metrics/measure/interactions_measure_spec.rb index e98c830598..ed333380cf 100644 --- a/spec/lib/admin/metrics/measure/interactions_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/interactions_measure_spec.rb @@ -3,15 +3,38 @@ require 'rails_helper' describe Admin::Metrics::Measure::InteractionsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with activity tracking records' do + before do + 3.times do + travel_to(2.days.ago) { record_interaction_activity } + end + 2.times do + travel_to(1.day.ago) { record_interaction_activity } + end + travel_to(0.days.ago) { record_interaction_activity } + end + + it 'returns correct activity tracker counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '3'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end + + def record_interaction_activity + ActivityTracker.increment('activity:interactions') + end end end end diff --git a/spec/lib/admin/metrics/measure/new_users_measure_spec.rb b/spec/lib/admin/metrics/measure/new_users_measure_spec.rb index fe82f8219b..085acbcede 100644 --- a/spec/lib/admin/metrics/measure/new_users_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/new_users_measure_spec.rb @@ -3,15 +3,30 @@ require 'rails_helper' describe Admin::Metrics::Measure::NewUsersMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with user records' do + before do + 3.times { Fabricate :user, created_at: 2.days.ago } + 2.times { Fabricate :user, created_at: 1.day.ago } + Fabricate :user, created_at: 0.days.ago + end + + it 'returns correct user counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '3'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end end end end diff --git a/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb b/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb index deed64ae88..d5ba78527e 100644 --- a/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/opened_reports_measure_spec.rb @@ -3,15 +3,30 @@ require 'rails_helper' describe Admin::Metrics::Measure::OpenedReportsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with report records' do + before do + 3.times { Fabricate :report, created_at: 2.days.ago } + 2.times { Fabricate :report, created_at: 1.day.ago } + Fabricate :report, created_at: 0.days.ago + end + + it 'returns correct report counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '3'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end end end end diff --git a/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb b/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb index cb98df2dc2..f7b497590d 100644 --- a/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/resolved_reports_measure_spec.rb @@ -3,15 +3,30 @@ require 'rails_helper' describe Admin::Metrics::Measure::ResolvedReportsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let(:start_at) { 2.days.ago } let(:end_at) { Time.now.utc } let(:params) { ActionController::Parameters.new } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with report records' do + before do + 3.times { Fabricate :report, action_taken_at: 2.days.ago } + 2.times { Fabricate :report, action_taken_at: 1.day.ago } + Fabricate :report, action_taken_at: 0.days.ago + end + + it 'returns correct report counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '3'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end end end end diff --git a/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb b/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb index 938b67afa3..b33ae7bb71 100644 --- a/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/tag_accounts_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::TagAccountsMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let!(:tag) { Fabricate(:tag) } @@ -12,8 +12,39 @@ describe Admin::Metrics::Measure::TagAccountsMeasure do let(:params) { ActionController::Parameters.new(id: tag.id) } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with tagged accounts' do + let(:alice) { Fabricate(:account, domain: 'alice.example') } + let(:bob) { Fabricate(:account, domain: 'bob.example') } + + before do + 3.times do + travel_to(2.days.ago) { add_tag_history(alice) } + end + + 2.times do + travel_to(1.day.ago) do + add_tag_history(alice) + add_tag_history(bob) + end + end + + add_tag_history(bob) + end + + it 'returns correct tag_accounts counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '1'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end + + def add_tag_history(account) + tag.history.add(account.id) + end end end end diff --git a/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb b/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb index e09a2b04e5..e1e2ced43a 100644 --- a/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/tag_servers_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::TagServersMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let!(:tag) { Fabricate(:tag) } @@ -12,8 +12,38 @@ describe Admin::Metrics::Measure::TagServersMeasure do let(:params) { ActionController::Parameters.new(id: tag.id) } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with tagged statuses' do + let(:alice) { Fabricate(:account, domain: 'alice.example') } + let(:bob) { Fabricate(:account, domain: 'bob.example') } + + before do + 3.times do + status_alice = Fabricate(:status, account: alice, created_at: 2.days.ago) + status_alice.tags << tag + end + + 2.times do + status_alice = Fabricate(:status, account: alice, created_at: 1.day.ago) + status_alice.tags << tag + + status_bob = Fabricate(:status, account: bob, created_at: 1.day.ago) + status_bob.tags << tag + end + + status_bob = Fabricate(:status, account: bob, created_at: 0.days.ago) + status_bob.tags << tag + end + + it 'returns correct tag counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '1'), + include(date: 1.day.ago.midnight.to_time, value: '2'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end end end end diff --git a/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb b/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb index 869e937445..dd66f00de0 100644 --- a/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb +++ b/spec/lib/admin/metrics/measure/tag_uses_measure_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe Admin::Metrics::Measure::TagUsesMeasure do - subject(:measure) { described_class.new(start_at, end_at, params) } + subject { described_class.new(start_at, end_at, params) } let!(:tag) { Fabricate(:tag) } @@ -12,8 +12,39 @@ describe Admin::Metrics::Measure::TagUsesMeasure do let(:params) { ActionController::Parameters.new(id: tag.id) } describe '#data' do - it 'runs data query without error' do - expect { measure.data }.to_not raise_error + context 'with tagged accounts' do + let(:alice) { Fabricate(:account, domain: 'alice.example') } + let(:bob) { Fabricate(:account, domain: 'bob.example') } + + before do + 3.times do + travel_to(2.days.ago) { add_tag_history(alice) } + end + + 2.times do + travel_to(1.day.ago) do + add_tag_history(alice) + add_tag_history(bob) + end + end + + add_tag_history(bob) + end + + it 'returns correct tag_uses counts' do + expect(subject.data.size) + .to eq(3) + expect(subject.data.map(&:symbolize_keys)) + .to contain_exactly( + include(date: 2.days.ago.midnight.to_time, value: '3'), + include(date: 1.day.ago.midnight.to_time, value: '4'), + include(date: 0.days.ago.midnight.to_time, value: '1') + ) + end + + def add_tag_history(account) + tag.history.add(account.id) + end end end end diff --git a/spec/requests/account_show_page_spec.rb b/spec/requests/account_show_page_spec.rb index e84c46c47f..81e965e6e6 100644 --- a/spec/requests/account_show_page_spec.rb +++ b/spec/requests/account_show_page_spec.rb @@ -9,12 +9,18 @@ describe 'The account show page' do get '/@alice' + expect(head_link_icons.size).to eq(4) # One general favicon and three with sizes + expect(head_meta_content('og:title')).to match alice.display_name expect(head_meta_content('og:type')).to eq 'profile' expect(head_meta_content('og:image')).to match '.+' expect(head_meta_content('og:url')).to match 'http://.+' end + def head_link_icons + head_section.css('link[rel=icon]') + end + def head_meta_content(property) head_section.meta("[@property='#{property}']")[:content] end diff --git a/spec/views/statuses/show.html.haml_spec.rb b/spec/views/statuses/show.html.haml_spec.rb index 779fe6e5f4..de9db1cc4d 100644 --- a/spec/views/statuses/show.html.haml_spec.rb +++ b/spec/views/statuses/show.html.haml_spec.rb @@ -21,12 +21,11 @@ describe 'statuses/show.html.haml', :without_verify_partial_doubles do render - header_tags = view.content_for(:header_tags) - - expect(header_tags).to match(//) - expect(header_tags).to match(//) - expect(header_tags).to match(//) - expect(header_tags).to match(%r{}) + expect(header_tags) + .to match(//) + .and match(//) + .and match(//) + .and match(%r{}) end it 'has twitter player tag' do @@ -40,9 +39,12 @@ describe 'statuses/show.html.haml', :without_verify_partial_doubles do render - header_tags = view.content_for(:header_tags) + expect(header_tags) + .to match(%r{}) + .and match(//) + end - expect(header_tags).to match(%r{}) - expect(header_tags).to match(//) + def header_tags + view.content_for(:header_tags) end end diff --git a/yarn.lock b/yarn.lock index ec2724c834..656532728b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3334,8 +3334,8 @@ __metadata: linkType: hard "@testing-library/react@npm:^14.0.0": - version: 14.2.2 - resolution: "@testing-library/react@npm:14.2.2" + version: 14.3.1 + resolution: "@testing-library/react@npm:14.3.1" dependencies: "@babel/runtime": "npm:^7.12.5" "@testing-library/dom": "npm:^9.0.0" @@ -3343,7 +3343,7 @@ __metadata: peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 - checksum: 10c0/ab36707f6701a4a56dd217e16e00d6326e0f760bb2e716245422c7500a0b94efcd351d0aa89c4fab2916e6ebc68c983cec6b3ae0804de813cafc913a612668f6 + checksum: 10c0/1ccf4eb1510500cc20a805cb0244c9098dca28a8745173a8f71ea1274d63774f0b7898a35c878b43c797b89c13621548909ff37843b835c1a27ee1efbbdd098c languageName: node linkType: hard @@ -3702,13 +3702,13 @@ __metadata: linkType: hard "@types/pg@npm:^8.6.6": - version: 8.11.4 - resolution: "@types/pg@npm:8.11.4" + version: 8.11.5 + resolution: "@types/pg@npm:8.11.5" dependencies: "@types/node": "npm:*" pg-protocol: "npm:*" pg-types: "npm:^4.0.1" - checksum: 10c0/81158ffa9d2f9b2b299a1650756b90fc418e0040e654d7d9ee46734a3c874d07b638af86d765e22e9c8246054c30a0274ee4dea58a0a7ed5c0c4aa01964a09ef + checksum: 10c0/d64d183bee2df96cd0558231190ff629558e8c0fd3203b880f48a7d34b1eaea528d20c09b57b19c0939f369136e6c6941533592eadd71174be78d1ec0ca5e60e languageName: node linkType: hard @@ -3762,11 +3762,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.4": - version: 18.2.24 - resolution: "@types/react-dom@npm:18.2.24" + version: 18.2.25 + resolution: "@types/react-dom@npm:18.2.25" dependencies: "@types/react": "npm:*" - checksum: 10c0/9ec38e5ab4727c56ef17bd8e938ead88748ba19db314b8d9807714a5cae430f5b799514667b221b4f2dc8d9b4ca17dd1c3da8c41c083c2de9eddcc31bec6b8ff + checksum: 10c0/87604407eca6884c5b4d4657cb511dc5ba28ea1cfa5d0ce1fc2d659a7ad1b64ae85dcda60e3f010641f9a52a6a60dfcaa6be3b0d0de9d624475052a13dae01f4 languageName: node linkType: hard @@ -3865,12 +3865,12 @@ __metadata: linkType: hard "@types/react@npm:*, @types/react@npm:16 || 17 || 18, @types/react@npm:>=16.9.11, @types/react@npm:^18.2.7": - version: 18.2.74 - resolution: "@types/react@npm:18.2.74" + version: 18.2.78 + resolution: "@types/react@npm:18.2.78" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10c0/347e38b4c5dc20d50ff71bf04b7caaef490e5ff695e74a0088a13fbb2a0c5d125a5ecfd142adfa30f0176da0e2734942c91ba61d95ce269c43b3265bd7379361 + checksum: 10c0/5eb8e1dd98c29aeddf40b90f466d1a9ce83b113d42a096633d632b834e7ae9821f24ba7999928de9d98cca37764532a7ea35355a8103a377d8baa750f1841b5c languageName: node linkType: hard @@ -13224,9 +13224,9 @@ __metadata: languageName: node linkType: hard -"postcss-custom-properties@npm:^13.3.6": - version: 13.3.6 - resolution: "postcss-custom-properties@npm:13.3.6" +"postcss-custom-properties@npm:^13.3.7": + version: 13.3.7 + resolution: "postcss-custom-properties@npm:13.3.7" dependencies: "@csstools/cascade-layer-name-parser": "npm:^1.0.9" "@csstools/css-parser-algorithms": "npm:^2.6.1" @@ -13235,7 +13235,7 @@ __metadata: postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/faa3b692966314a6dfcba93e74d91f20f2484ea328f88c809b1d0daa8ecc0d8d5125e06d1d7c18b5455ac30cb3501c7069b6e56e5efac61523a6ed75c3d73a30 + checksum: 10c0/5d8767efae956f98d9a62a8f54d913c9ea95eaab1c906679ddeee64d87f0fb37d99c8ac1d16ec199794ed7c13a42d39ca2ea0a98df1056d400d4cbc9f31d6b94 languageName: node linkType: hard @@ -13696,8 +13696,8 @@ __metadata: linkType: hard "postcss-preset-env@npm:^9.5.2": - version: 9.5.4 - resolution: "postcss-preset-env@npm:9.5.4" + version: 9.5.5 + resolution: "postcss-preset-env@npm:9.5.5" dependencies: "@csstools/postcss-cascade-layers": "npm:^4.0.4" "@csstools/postcss-color-function": "npm:^3.0.13" @@ -13740,7 +13740,7 @@ __metadata: postcss-color-hex-alpha: "npm:^9.0.4" postcss-color-rebeccapurple: "npm:^9.0.3" postcss-custom-media: "npm:^10.0.4" - postcss-custom-properties: "npm:^13.3.6" + postcss-custom-properties: "npm:^13.3.7" postcss-custom-selectors: "npm:^7.1.8" postcss-dir-pseudo-class: "npm:^8.0.1" postcss-double-position-gradients: "npm:^5.0.6" @@ -13761,7 +13761,7 @@ __metadata: postcss-selector-not: "npm:^7.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/6af900ad2f46b640339b626317288543ebb7c47b739f4776e4006513b32eceabe0be78109aa58446fa0f50284a433b3e3a9bd48aa5730fd0ac59ef51153e8f7b + checksum: 10c0/afc31fb75bc5e8e223d38fd34b81da08ee340818f5e392df1781728f2ff2a9dbc75e458673ce9f52deafefa90bbc99e0bd1453271498f5e02746c785180bad07 languageName: node linkType: hard @@ -14454,8 +14454,8 @@ __metadata: linkType: hard "react-redux@npm:^9.0.4": - version: 9.1.0 - resolution: "react-redux@npm:9.1.0" + version: 9.1.1 + resolution: "react-redux@npm:9.1.1" dependencies: "@types/use-sync-external-store": "npm:^0.0.3" use-sync-external-store: "npm:^1.0.0" @@ -14471,7 +14471,7 @@ __metadata: optional: true redux: optional: true - checksum: 10c0/53161b5dc4d109020fbc42d26906ace92fed9ba1d7ab6274af60e9c0684583d20d1c8ec6d58601ac7b833c6468a652bbf3d4a102149d1793cb8a28b05b042f73 + checksum: 10c0/40ccdc8d48aefeed02c025f46e4a2e6641a2996fe985feb70d25feaaf8f101f6ef937cd1420909cad4c8869a8c79323ee071f5b090b011b950e5ae09100f5767 languageName: node linkType: hard @@ -15324,15 +15324,15 @@ __metadata: linkType: hard "sass@npm:^1.62.1": - version: 1.74.1 - resolution: "sass@npm:1.74.1" + version: 1.75.0 + resolution: "sass@npm:1.75.0" dependencies: chokidar: "npm:>=3.0.0 <4.0.0" immutable: "npm:^4.0.0" source-map-js: "npm:>=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 10c0/4610257ee27823276ce4998a534b4ee9f313e5a0b3d3899e70e0f87096feeae4cd8dd3c2f765b52f57dd87f5dab22370ef63f95a837a189fbb9401396d5ce717 + checksum: 10c0/1564ab2c8041c99a330cec93127fe8abcf65ac63eecb471610ed7f3126a2599a58b788a3a98eb8719f7f40b9b04e00c92bc9e11a9c2180ad582b8cba9fb030b0 languageName: node linkType: hard @@ -17107,22 +17107,22 @@ __metadata: linkType: hard "typescript@npm:5, typescript@npm:^5.0.4": - version: 5.4.4 - resolution: "typescript@npm:5.4.4" + version: 5.4.5 + resolution: "typescript@npm:5.4.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/4d8de0291204ed61ca97ad0cba2ce064e09c4988ca1c451c787e4653ba76296ba35177a52694e8a00cf4ef899d0ee83338663b926d8b7d55167ff0ba81549999 + checksum: 10c0/2954022ada340fd3d6a9e2b8e534f65d57c92d5f3989a263754a78aba549f7e6529acc1921913560a4b816c46dce7df4a4d29f9f11a3dc0d4213bb76d043251e languageName: node linkType: hard "typescript@patch:typescript@npm%3A5#optional!builtin, typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.4.4 - resolution: "typescript@patch:typescript@npm%3A5.4.4#optional!builtin::version=5.4.4&hash=5adc0c" + version: 5.4.5 + resolution: "typescript@patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/1fa41b9964a9ff0ed913b339c90b46031b2d2da3cb1a192af516610733f7f1d5f7f9754a8e22b9ac7076d3d8aedd2c4f84db3f113bad060eac3a95962443a1bf + checksum: 10c0/db2ad2a16ca829f50427eeb1da155e7a45e598eec7b086d8b4e8ba44e5a235f758e606d681c66992230d3fc3b8995865e5fd0b22a2c95486d0b3200f83072ec9 languageName: node linkType: hard @@ -17643,8 +17643,8 @@ __metadata: linkType: hard "webpack-bundle-analyzer@npm:^4.8.0": - version: 4.10.1 - resolution: "webpack-bundle-analyzer@npm:4.10.1" + version: 4.10.2 + resolution: "webpack-bundle-analyzer@npm:4.10.2" dependencies: "@discoveryjs/json-ext": "npm:0.5.7" acorn: "npm:^8.0.4" @@ -17654,14 +17654,13 @@ __metadata: escape-string-regexp: "npm:^4.0.0" gzip-size: "npm:^6.0.0" html-escaper: "npm:^2.0.2" - is-plain-object: "npm:^5.0.0" opener: "npm:^1.5.2" picocolors: "npm:^1.0.0" sirv: "npm:^2.0.3" ws: "npm:^7.3.1" bin: webpack-bundle-analyzer: lib/bin/analyzer.js - checksum: 10c0/6a94c8f6aa03296fb2eb00d6ad3b27bd5c551590fd253772bc61debf3177414d42701014079d4f85c74ba1ca685ae9f0cb4063812b58c21f294d108e9908e5cd + checksum: 10c0/00603040e244ead15b2d92981f0559fa14216381349412a30070a7358eb3994cd61a8221d34a3b3fb8202dc3d1c5ee1fbbe94c5c52da536e5b410aa1cf279a48 languageName: node linkType: hard