decidim-core 0.26.2 → 0.27.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/cells/decidim/amendable/announcement_cell.rb +3 -8
- data/app/cells/decidim/announcement_cell.rb +1 -1
- data/app/cells/decidim/author_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/footer_sub_hero/show.erb +1 -1
- data/app/cells/decidim/content_blocks/hero/show.erb +1 -1
- data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +3 -3
- data/app/cells/decidim/content_blocks/highlighted_elements_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/how_to_participate/show.erb +1 -1
- data/app/cells/decidim/content_blocks/last_activity/show.erb +1 -1
- data/app/cells/decidim/content_blocks/last_activity_cell.rb +3 -3
- data/app/cells/decidim/content_blocks/stats_cell.rb +4 -4
- data/app/cells/decidim/content_blocks/sub_hero/show.erb +1 -1
- data/app/cells/decidim/data_consent/category.erb +64 -0
- data/app/cells/decidim/data_consent/dialog.erb +29 -0
- data/app/cells/decidim/data_consent/modal.erb +39 -0
- data/app/cells/decidim/data_consent/show.erb +3 -0
- data/app/cells/decidim/data_consent_cell.rb +21 -0
- data/app/cells/decidim/follow_button_cell.rb +5 -7
- data/app/cells/decidim/profile_sidebar_cell.rb +1 -1
- data/app/cells/decidim/search_results_cell.rb +1 -1
- data/app/cells/decidim/tos_page/refuse_btn_modal.erb +1 -1
- data/app/cells/decidim/upload_modal/files.erb +52 -0
- data/app/cells/decidim/upload_modal/modal.erb +49 -0
- data/app/cells/decidim/upload_modal/show.erb +3 -0
- data/app/cells/decidim/upload_modal_cell.rb +205 -0
- data/app/cells/decidim/user_conversation/reply.erb +1 -1
- data/app/cells/decidim/user_conversations/add_conversation_users.erb +5 -3
- data/app/cells/decidim/version_cell.rb +2 -13
- data/app/cells/decidim/versions_list_cell.rb +2 -13
- data/app/cells/decidim/versions_list_item_cell.rb +2 -13
- data/app/commands/decidim/accept_group_invitation.rb +1 -1
- data/app/commands/decidim/accept_user_group_join_request.rb +1 -1
- data/app/commands/decidim/amendable/accept.rb +1 -1
- data/app/commands/decidim/amendable/create_draft.rb +1 -1
- data/app/commands/decidim/amendable/destroy_draft.rb +1 -1
- data/app/commands/decidim/amendable/promote.rb +1 -1
- data/app/commands/decidim/amendable/publish_draft.rb +1 -1
- data/app/commands/decidim/amendable/reject.rb +1 -1
- data/app/commands/decidim/amendable/update_draft.rb +1 -1
- data/app/commands/decidim/amendable/withdraw.rb +1 -1
- data/app/commands/decidim/attachment_methods.rb +3 -2
- data/app/commands/decidim/create_editor_image.rb +1 -1
- data/app/commands/decidim/create_follow.rb +1 -1
- data/app/commands/decidim/create_omniauth_registration.rb +2 -3
- data/app/commands/decidim/create_registration.rb +1 -2
- data/app/commands/decidim/create_report.rb +1 -1
- data/app/commands/decidim/create_user_group.rb +2 -2
- data/app/commands/decidim/create_user_report.rb +5 -3
- data/app/commands/decidim/delete_follow.rb +1 -1
- data/app/commands/decidim/demote_membership.rb +1 -1
- data/app/commands/decidim/destroy_account.rb +1 -1
- data/app/commands/decidim/endorse_resource.rb +1 -1
- data/app/commands/decidim/gallery_methods.rb +45 -10
- data/app/commands/decidim/invite_user.rb +1 -3
- data/app/commands/decidim/invite_user_again.rb +1 -1
- data/app/commands/decidim/invite_user_to_group.rb +1 -1
- data/app/commands/decidim/join_user_group.rb +1 -1
- data/app/commands/decidim/leave_user_group.rb +8 -2
- data/app/commands/decidim/messaging/reply_to_conversation.rb +2 -2
- data/app/commands/decidim/messaging/start_conversation.rb +2 -2
- data/app/commands/decidim/multiple_attachments_methods.rb +44 -5
- data/app/commands/decidim/promote_membership.rb +1 -1
- data/app/commands/decidim/reject_group_invitation.rb +1 -1
- data/app/commands/decidim/reject_user_group_join_request.rb +1 -1
- data/app/commands/decidim/remove_user_from_group.rb +1 -1
- data/app/commands/decidim/resend_confirmation_instructions.rb +18 -0
- data/app/commands/decidim/search.rb +10 -9
- data/app/commands/decidim/unendorse_resource.rb +1 -1
- data/app/commands/decidim/unsubscribe_settings.rb +1 -1
- data/app/commands/decidim/update_account.rb +2 -2
- data/app/commands/decidim/update_notifications_settings.rb +3 -2
- data/app/commands/decidim/update_password.rb +31 -0
- data/app/commands/decidim/update_user_group.rb +2 -2
- data/app/commands/decidim/update_user_interests.rb +1 -1
- data/app/commands/decidim/validate_upload.rb +15 -0
- data/app/controllers/concerns/decidim/devise_controllers.rb +0 -1
- data/app/controllers/concerns/decidim/filter_resource.rb +23 -24
- data/app/controllers/concerns/decidim/force_authentication.rb +1 -2
- data/app/controllers/concerns/decidim/http_caching_disabler.rb +1 -1
- data/app/controllers/concerns/decidim/needs_password_change.rb +43 -0
- data/app/controllers/concerns/decidim/needs_tos_accepted.rb +3 -3
- data/app/controllers/concerns/decidim/orderable.rb +1 -1
- data/app/controllers/concerns/decidim/participatory_space_context.rb +2 -2
- data/app/controllers/decidim/account_controller.rb +45 -0
- data/app/controllers/decidim/application_controller.rb +1 -1
- data/app/controllers/decidim/devise/invitations_controller.rb +2 -0
- data/app/controllers/decidim/devise/passwords_controller.rb +33 -0
- data/app/controllers/decidim/devise/registrations_controller.rb +2 -0
- data/app/controllers/decidim/devise/sessions_controller.rb +2 -0
- data/app/controllers/decidim/{data_portability_controller.rb → download_your_data_controller.rb} +8 -8
- data/app/controllers/decidim/groups_controller.rb +5 -0
- data/app/controllers/decidim/last_activities_controller.rb +7 -9
- data/app/controllers/decidim/manifests_controller.rb +11 -0
- data/app/controllers/decidim/newsletters_controller.rb +1 -1
- data/app/controllers/decidim/notifications_subscriptions_controller.rb +16 -0
- data/app/controllers/decidim/offline_controller.rb +7 -0
- data/app/controllers/decidim/profiles_controller.rb +1 -1
- data/app/controllers/decidim/searches_controller.rb +4 -3
- data/app/controllers/decidim/short_links_controller.rb +35 -0
- data/app/controllers/decidim/upload_validations_controller.rb +44 -0
- data/app/controllers/decidim/user_activities_controller.rb +32 -16
- data/app/controllers/decidim/user_interests_controller.rb +0 -2
- data/app/controllers/decidim/user_timeline_controller.rb +6 -8
- data/app/events/decidim/change_nickname_event.rb +21 -0
- data/app/forms/decidim/account_form.rb +7 -6
- data/app/forms/decidim/form.rb +1 -1
- data/app/forms/decidim/messaging/conversation_form.rb +1 -1
- data/app/forms/decidim/notifications_settings_form.rb +8 -2
- data/app/forms/decidim/password_form.rb +10 -0
- data/app/forms/decidim/registration_form.rb +10 -4
- data/app/forms/decidim/upload_validation_form.rb +54 -0
- data/app/forms/decidim/user_group_form.rb +1 -1
- data/app/forms/decidim/user_interest_scope_form.rb +1 -1
- data/app/forms/decidim/user_interests_form.rb +1 -1
- data/app/forms/translatable_presence_validator.rb +2 -2
- data/app/forms/url_validator.rb +1 -1
- data/app/helpers/decidim/application_helper.rb +2 -2
- data/app/helpers/decidim/attachments_helper.rb +1 -1
- data/app/helpers/decidim/cells_paginate_helper.rb +1 -1
- data/app/helpers/decidim/datalist_select_helper.rb +40 -0
- data/app/helpers/decidim/decidim_form_helper.rb +1 -1
- data/app/helpers/decidim/followable_helper.rb +1 -1
- data/app/helpers/decidim/icon_helper.rb +1 -1
- data/app/helpers/decidim/layout_helper.rb +15 -1
- data/app/helpers/decidim/map_helper.rb +12 -8
- data/app/helpers/decidim/meta_tags_helper.rb +0 -2
- data/app/helpers/decidim/notifications_settings_helper.rb +15 -0
- data/app/helpers/decidim/passwords_helper.rb +41 -0
- data/app/helpers/decidim/sanitize_helper.rb +1 -0
- data/app/helpers/decidim/searches_helper.rb +6 -6
- data/app/helpers/decidim/short_link_helper.rb +28 -0
- data/app/helpers/decidim/translations_helper.rb +2 -2
- data/app/jobs/decidim/{data_portability_export_job.rb → download_your_data_export_job.rb} +5 -5
- data/app/jobs/decidim/email_notifications_digest_generator_job.rb +21 -0
- data/app/jobs/decidim/notification_generator_for_recipient_job.rb +5 -3
- data/app/jobs/decidim/reminder_generator_job.rb +12 -0
- data/app/jobs/decidim/resend_confirmation_instructions_job.rb +11 -0
- data/app/jobs/decidim/user_report_job.rb +2 -2
- data/app/mailers/concerns/decidim/multitenant_asset_host.rb +11 -3
- data/app/mailers/decidim/application_mailer.rb +1 -1
- data/app/mailers/decidim/block_user_mailer.rb +8 -7
- data/app/mailers/decidim/export_mailer.rb +2 -2
- data/app/mailers/decidim/newsletter_mailer.rb +2 -2
- data/app/mailers/decidim/newsletters_opt_in_mailer.rb +7 -5
- data/app/mailers/decidim/notifications_digest_mailer.rb +23 -0
- data/app/mailers/decidim/user_report_mailer.rb +10 -11
- data/app/models/decidim/action_log.rb +86 -2
- data/app/models/decidim/amendment.rb +0 -1
- data/app/models/decidim/area.rb +1 -2
- data/app/models/decidim/area_type.rb +5 -0
- data/app/models/decidim/attachment.rb +6 -0
- data/app/models/decidim/attachment_collection.rb +5 -0
- data/app/models/decidim/category.rb +9 -4
- data/app/models/decidim/coauthorship.rb +0 -2
- data/app/models/decidim/contextual_help_section.rb +5 -1
- data/app/models/decidim/follow.rb +2 -2
- data/app/models/decidim/gamification/badge_score.rb +0 -1
- data/app/models/decidim/identity.rb +2 -2
- data/app/models/decidim/messaging/conversation.rb +4 -4
- data/app/models/decidim/messaging/message.rb +1 -2
- data/app/models/decidim/messaging/participation.rb +0 -2
- data/app/models/decidim/messaging/receipt.rb +0 -2
- data/app/models/decidim/notification.rb +5 -2
- data/app/models/decidim/oauth_application.rb +12 -1
- data/app/models/decidim/organization.rb +7 -7
- data/app/models/decidim/participatory_space_private_user.rb +4 -2
- data/app/models/decidim/permission_action.rb +1 -0
- data/app/models/decidim/reminder.rb +10 -0
- data/app/models/decidim/reminder_delivery.rb +7 -0
- data/app/models/decidim/reminder_record.rb +29 -0
- data/app/models/decidim/report.rb +2 -2
- data/app/models/decidim/scope.rb +3 -4
- data/app/models/decidim/scope_type.rb +5 -0
- data/app/models/decidim/share_token.rb +0 -2
- data/app/models/decidim/short_link.rb +162 -0
- data/app/models/decidim/user.rb +34 -6
- data/app/models/decidim/user_base_entity.rb +1 -1
- data/app/models/decidim/user_group.rb +3 -3
- data/app/models/decidim/user_moderation.rb +0 -2
- data/app/models/decidim/user_report.rb +2 -2
- data/app/packs/entrypoints/decidim_core.js +2 -2
- data/app/packs/entrypoints/decidim_sw.js +1 -0
- data/app/packs/src/decidim/autocomplete.js +298 -0
- data/app/packs/src/decidim/cookie_consent/consent_manager.js +133 -0
- data/app/packs/src/decidim/cookie_consent/cookie_consent.js +103 -0
- data/app/packs/src/decidim/datalist_select.js +36 -0
- data/app/packs/src/decidim/direct_uploads/upload_field.js +117 -0
- data/app/packs/src/decidim/direct_uploads/upload_modal.js +264 -0
- data/app/packs/src/decidim/direct_uploads/upload_utility.js +49 -0
- data/app/packs/src/decidim/direct_uploads/uploader.js +89 -0
- data/app/packs/src/decidim/external_domain_warning.js +1 -1
- data/app/packs/src/decidim/external_link.js +14 -3
- data/app/packs/src/decidim/external_link.test.js +64 -0
- data/app/packs/src/decidim/geocoding.js +10 -35
- data/app/packs/src/decidim/identity_selector_dialog.js +1 -1
- data/app/packs/src/decidim/impersonation.js +3 -3
- data/app/packs/src/decidim/input_character_counter.js +177 -7
- data/app/packs/src/decidim/input_multiple_mentions.js +87 -187
- data/app/packs/src/decidim/map/factory.js +3 -1
- data/app/packs/src/decidim/map/icon.js +2 -1
- data/app/packs/src/decidim/map/legacy.js +2 -2
- data/app/packs/src/decidim/map/svg-icon.js +248 -0
- data/app/packs/src/decidim/map.js +2 -2
- data/app/packs/src/decidim/security/selfxss_warning.js +5 -1
- data/app/packs/src/decidim/session_timeouter.js +15 -15
- data/app/packs/src/decidim/sw/a2hs.js +28 -0
- data/app/packs/src/decidim/sw/index.js +3 -0
- data/app/packs/src/decidim/sw/loader.js +18 -0
- data/app/packs/src/decidim/sw/push-permissions.js +87 -0
- data/app/packs/src/decidim/sw/sw.js +80 -0
- data/app/packs/src/decidim/vizzs/areachart.js +33 -28
- data/app/packs/src/decidim/vizzs/{metrics.js → index.js} +0 -0
- data/app/packs/src/decidim/vizzs/linechart.js +23 -18
- data/app/packs/src/decidim/vizzs/rowchart.js +15 -11
- data/app/packs/stylesheets/decidim/email.scss +66 -0
- data/app/packs/stylesheets/decidim/layouts/_user.scss +8 -0
- data/app/packs/stylesheets/decidim/modules/_autocomplete.scss +99 -0
- data/app/packs/stylesheets/decidim/modules/_cookie-consent.scss +115 -0
- data/app/packs/stylesheets/decidim/modules/_footer.scss +4 -0
- data/app/packs/stylesheets/decidim/modules/_input-multiple-mentions.scss +29 -2
- data/app/packs/stylesheets/decidim/modules/_modules.scss +3 -1
- data/app/packs/stylesheets/decidim/modules/_reveal.scss +15 -0
- data/app/packs/stylesheets/decidim/modules/_upload_modal.scss +143 -0
- data/app/packs/stylesheets/decidim/utils/_fontface.scss +3 -0
- data/app/permissions/decidim/permissions.rb +2 -4
- data/app/presenters/decidim/admin_log/area_type_presenter.rb +34 -0
- data/app/presenters/decidim/admin_log/attachment_collection_presenter.rb +35 -0
- data/app/presenters/decidim/admin_log/attachment_presenter.rb +27 -0
- data/app/presenters/decidim/admin_log/category_presenter.rb +36 -0
- data/app/presenters/decidim/admin_log/component_presenter.rb +35 -3
- data/app/presenters/decidim/admin_log/contextual_help_section_presenter.rb +33 -0
- data/app/presenters/decidim/admin_log/organization_presenter.rb +9 -4
- data/app/presenters/decidim/admin_log/scope_type_presenter.rb +34 -0
- data/app/presenters/decidim/home_stats_presenter.rb +4 -2
- data/app/presenters/decidim/log/base_presenter.rb +1 -1
- data/app/presenters/decidim/menu_item_presenter.rb +1 -1
- data/app/presenters/decidim/metric_charts_presenter.rb +7 -1
- data/app/presenters/decidim/nil_presenter.rb +3 -1
- data/app/presenters/decidim/notification_to_mailer_presenter.rb +39 -0
- data/app/presenters/decidim/notifications_digest_presenter.rb +42 -0
- data/app/presenters/decidim/official_author_presenter.rb +4 -0
- data/app/presenters/decidim/organization_presenter.rb +22 -0
- data/app/presenters/decidim/push_notification_presenter.rb +24 -0
- data/app/presenters/decidim/stats_presenter.rb +1 -1
- data/app/presenters/decidim/validation_errors_presenter.rb +1 -1
- data/app/queries/decidim/messaging/user_conversations.rb +1 -1
- data/app/queries/decidim/metric_manage.rb +1 -1
- data/app/queries/decidim/own_activities.rb +11 -0
- data/app/queries/decidim/participatory_processes_with_user_role.rb +1 -1
- data/app/{services/decidim/activity_search.rb → queries/decidim/public_activities.rb} +35 -77
- data/app/queries/decidim/public_components.rb +1 -1
- data/app/queries/decidim/similar_emendations.rb +1 -1
- data/app/queries/decidim/stats_users_count.rb +1 -1
- data/app/queries/decidim/user_groups/accepted_memberships.rb +1 -1
- data/app/queries/decidim/user_groups/accepted_user_groups.rb +1 -1
- data/app/queries/decidim/user_groups/accepted_users.rb +1 -1
- data/app/queries/decidim/user_groups/admin_memberships.rb +1 -1
- data/app/queries/decidim/user_groups/invited_memberships.rb +1 -1
- data/app/queries/decidim/user_groups/manageable_user_groups.rb +1 -1
- data/app/queries/decidim/user_groups/member_memberships.rb +1 -1
- data/app/services/decidim/{data_portability_exporter.rb → download_your_data_exporter.rb} +6 -6
- data/app/services/decidim/email_notification_generator.rb +2 -2
- data/app/services/decidim/engine_resolver.rb +66 -0
- data/app/services/decidim/events_manager.rb +1 -1
- data/app/services/decidim/iframe_disabler.rb +31 -0
- data/app/services/decidim/notification_generator_for_recipient.rb +1 -1
- data/app/services/decidim/notifications_digest_sending_decider.rb +18 -0
- data/app/services/decidim/notifications_subscriptions_persistor.rb +37 -0
- data/app/services/decidim/open_data_exporter.rb +1 -1
- data/app/services/decidim/resource_search.rb +17 -164
- data/app/services/decidim/send_push_notification.rb +59 -0
- data/app/services/decidim/traceability.rb +1 -1
- data/app/uploaders/decidim/application_uploader.rb +2 -12
- data/app/uploaders/decidim/cw/attachment_uploader.rb +1 -1
- data/app/uploaders/decidim/cw/{data_portability_uploader.rb → download_your_data_uploader.rb} +3 -3
- data/app/uploaders/decidim/cw/image_uploader.rb +2 -2
- data/app/uploaders/decidim/organization_favicon_uploader.rb +3 -2
- data/app/validators/passthru_validator.rb +29 -21
- data/app/validators/password_validator.rb +25 -4
- data/app/validators/uploader_image_dimensions_validator.rb +1 -1
- data/app/views/decidim/account/_account_notification.js.erb +20 -0
- data/app/views/decidim/account/_password_fields.html.erb +2 -2
- data/app/views/decidim/account/cancel_email_change.js.erb +6 -0
- data/app/views/decidim/account/resend_confirmation_instructions.erb +1 -0
- data/app/views/decidim/account/show.html.erb +19 -6
- data/app/views/decidim/application/{_attachments.html.erb → _attachments.erb} +2 -2
- data/app/views/decidim/application/_collection.html.erb +1 -1
- data/app/views/decidim/application/{_document.html.erb → _document.erb} +0 -0
- data/app/views/decidim/application/{_documents.html.erb → _documents.erb} +2 -2
- data/app/views/decidim/application/{_photos.html.erb → _photos.erb} +0 -0
- data/app/views/decidim/devise/confirmations/new.html.erb +1 -1
- data/app/views/decidim/devise/invitations/edit.html.erb +3 -4
- data/app/views/decidim/devise/omniauth_registrations/new.html.erb +3 -3
- data/app/views/decidim/devise/passwords/edit.html.erb +7 -5
- data/app/views/decidim/devise/passwords/new.html.erb +1 -1
- data/app/views/decidim/devise/registrations/edit.html.erb +5 -5
- data/app/views/decidim/devise/registrations/new.html.erb +5 -5
- data/app/views/decidim/devise/sessions/new.html.erb +2 -2
- data/app/views/decidim/{data_portability → download_your_data}/export.html.erb +0 -0
- data/app/views/decidim/{data_portability → download_your_data}/show.html.erb +2 -2
- data/app/views/decidim/export_mailer/download_your_data_export.html.erb +7 -0
- data/app/views/decidim/last_activities/index.html.erb +1 -1
- data/app/views/decidim/manifests/show.json.erb +31 -0
- data/app/views/decidim/messaging/conversations/_add_conversation_users.html.erb +5 -3
- data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/_start.html.erb +1 -3
- data/app/views/decidim/messaging/conversations/create.js.erb +1 -0
- data/app/views/decidim/notifications_digest_mailer/_email_content.html.erb +11 -0
- data/app/views/decidim/notifications_digest_mailer/digest_mail.erb +27 -0
- data/app/views/decidim/notifications_settings/show.html.erb +34 -9
- data/app/views/decidim/offline/show.html.erb +9 -0
- data/app/views/decidim/pages/_standalone.html.erb +1 -1
- data/app/views/decidim/reported_mailer/hide.html.erb +1 -1
- data/app/views/decidim/reported_mailer/report.html.erb +1 -1
- data/app/views/decidim/scopes/picker.html.erb +1 -1
- data/app/views/decidim/searches/_filters.html.erb +2 -2
- data/app/views/decidim/shared/participatory_space_filters/_filters.html.erb +3 -3
- data/app/views/decidim/user_report_mailer/notify.html.erb +10 -3
- data/app/views/devise/mailer/confirmation_instructions.html.erb +3 -1
- data/app/views/layouts/decidim/_application.html.erb +6 -3
- data/app/views/layouts/decidim/_cookie_warning.html.erb +8 -8
- data/app/views/layouts/decidim/_decidim_javascript.html.erb +12 -0
- data/app/views/layouts/decidim/_head.html.erb +4 -2
- data/app/views/layouts/decidim/_js_configuration.html.erb +5 -1
- data/app/views/layouts/decidim/_main_footer.html.erb +1 -0
- data/app/views/layouts/decidim/_offline_banner.html.erb +11 -0
- data/app/views/layouts/decidim/widget.html.erb +2 -2
- data/config/assets.rb +1 -0
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +48 -36
- data/config/locales/bg.yml +15 -30
- data/config/locales/ca.yml +186 -35
- data/config/locales/cs.yml +186 -33
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +25 -36
- data/config/locales/el.yml +15 -30
- data/config/locales/en.yml +183 -32
- data/config/locales/eo.yml +4 -6
- data/config/locales/es-MX.yml +185 -34
- data/config/locales/es-PY.yml +185 -34
- data/config/locales/es.yml +185 -34
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +15 -36
- data/config/locales/fi-plain.yml +184 -33
- data/config/locales/fi.yml +184 -33
- data/config/locales/fr-CA.yml +170 -33
- data/config/locales/fr.yml +170 -33
- data/config/locales/ga-IE.yml +5 -7
- data/config/locales/gl.yml +47 -30
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +65 -35
- data/config/locales/id-ID.yml +15 -29
- data/config/locales/is-IS.yml +6 -15
- data/config/locales/it.yml +22 -38
- data/config/locales/ja.yml +173 -34
- data/config/locales/ko.yml +1 -0
- data/config/locales/lb.yml +16 -32
- data/config/locales/lt.yml +1 -0
- data/config/locales/lv.yml +15 -28
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +25 -33
- data/config/locales/no.yml +24 -35
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +113 -32
- data/config/locales/pt-BR.yml +17 -32
- data/config/locales/pt.yml +16 -32
- data/config/locales/ro-RO.yml +20 -36
- data/config/locales/ru.yml +15 -27
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk.yml +15 -30
- data/config/locales/sl.yml +1 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +1 -0
- data/config/locales/sv.yml +69 -34
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +15 -29
- data/config/locales/uk.yml +15 -26
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +15 -28
- data/config/locales/zh-TW.yml +1 -0
- data/config/routes.rb +17 -2
- data/db/migrate/20180508111710_add_accepted_tos_version_field_to_users.rb +1 -0
- data/db/migrate/20181030090144_destroy_deleted_users_follows.rb +1 -0
- data/db/migrate/20190412131728_fix_user_names.rb +4 -4
- data/db/migrate/20210831181634_add_service_name_to_active_storage_blobs.active_storage.rb +22 -0
- data/db/migrate/20210831181635_create_active_storage_variant_records.active_storage.rb +14 -0
- data/db/migrate/20211208155453_create_decidim_reminders.rb +11 -0
- data/db/migrate/20211209121025_create_decidim_reminder_records.rb +11 -0
- data/db/migrate/20211209121040_create_decidim_reminder_deliveries.rb +10 -0
- data/db/migrate/20220118121921_change_required_description_categories.rb +7 -0
- data/db/migrate/20220127113419_add_notification_settings_to_users.rb +7 -0
- data/db/migrate/20220203121137_add_notifications_sending_frequency_to_users.rb +7 -0
- data/db/migrate/20220215172439_add_digest_sent_at_to_users.rb +7 -0
- data/db/migrate/20220323195258_add_index_to_decidim_users_notifications_sending_frequency.rb +7 -0
- data/db/migrate/20220427142214_drop_emails_on_notifications_flag_from_user.rb +15 -0
- data/db/migrate/20220518094535_add_previous_passwords_to_users.rb +20 -0
- data/db/migrate/20220524195530_create_decidim_short_links.rb +23 -0
- data/db/seeds.rb +17 -18
- data/lib/decidim/acts_as_tree.rb +47 -0
- data/lib/decidim/api/input_sorts/component_input_sort.rb +2 -1
- data/lib/decidim/api/interfaces/authorable_interface.rb +6 -5
- data/lib/decidim/asset_router.rb +80 -0
- data/lib/decidim/attachment_attributes.rb +8 -8
- data/lib/decidim/attribute_object/form.rb +174 -0
- data/lib/decidim/attribute_object/model.rb +148 -0
- data/lib/decidim/attribute_object/nested_validator.rb +22 -0
- data/lib/decidim/attribute_object/type_map.rb +14 -0
- data/lib/decidim/attribute_object/type_resolver.rb +91 -0
- data/lib/decidim/attribute_object.rb +26 -0
- data/lib/decidim/attributes/array.rb +62 -0
- data/lib/decidim/attributes/blob.rb +20 -0
- data/lib/decidim/attributes/clean_string.rb +12 -6
- data/lib/decidim/attributes/hash.rb +36 -0
- data/lib/decidim/attributes/integer.rb +17 -0
- data/lib/decidim/attributes/localized_date.rb +9 -7
- data/lib/decidim/attributes/model.rb +24 -0
- data/lib/decidim/attributes/object.rb +28 -0
- data/lib/decidim/attributes/symbol.rb +23 -0
- data/lib/decidim/attributes/time_with_zone.rb +9 -7
- data/lib/decidim/attributes.rb +29 -0
- data/lib/decidim/authorable.rb +21 -6
- data/lib/decidim/authorization_form_builder.rb +9 -11
- data/lib/decidim/carrier_wave_migrator_service.rb +15 -15
- data/lib/decidim/coauthorable.rb +22 -4
- data/lib/decidim/command.rb +44 -0
- data/lib/decidim/common_passwords.rb +1 -1
- data/lib/decidim/component_manifest.rb +5 -5
- data/lib/decidim/component_validator.rb +2 -2
- data/lib/decidim/content_block_manifest.rb +1 -1
- data/lib/decidim/content_parsers/hashtag_parser.rb +2 -2
- data/lib/decidim/content_parsers/resource_parser.rb +1 -1
- data/lib/decidim/content_parsers/user_group_parser.rb +1 -1
- data/lib/decidim/content_parsers/user_parser.rb +4 -4
- data/lib/decidim/content_renderers/hashtag_renderer.rb +1 -1
- data/lib/decidim/content_renderers/link_renderer.rb +2 -2
- data/lib/decidim/content_renderers/user_group_renderer.rb +1 -1
- data/lib/decidim/content_renderers/user_renderer.rb +1 -1
- data/lib/decidim/controller_helpers.rb +41 -0
- data/lib/decidim/core/engine.rb +29 -18
- data/lib/decidim/core/test/factories.rb +48 -8
- data/lib/decidim/core/test/shared_examples/admin_resource_gallery_examples.rb +16 -4
- data/lib/decidim/core/test/shared_examples/amendable/amendment_form_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/authorable_interface_examples.rb +15 -2
- data/lib/decidim/core/test/shared_examples/coauthorable_interface_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +203 -0
- data/lib/decidim/core/test/shared_examples/localised_email.rb +1 -1
- data/lib/decidim/core/test/shared_examples/logo_email.rb +1 -1
- data/lib/decidim/core/test/shared_examples/map_examples.rb +2 -2
- data/lib/decidim/core/test/shared_examples/preview_component_with_share_token_examples.rb +0 -6
- data/lib/decidim/core/test/shared_examples/resource_search_examples.rb +120 -40
- data/lib/decidim/core/test/shared_examples/resourceable.rb +0 -6
- data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +1 -1
- data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +1 -1
- data/lib/decidim/core/test/shared_examples/system_endorse_resource_examples.rb +3 -3
- data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +2 -2
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +108 -14
- data/lib/decidim/{data_portability.rb → download_your_data.rb} +3 -3
- data/lib/decidim/{data_portability_serializers/data_portability_conversation_serializer.rb → download_your_data_serializers/download_your_data_conversation_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_follow_serializer.rb → download_your_data_serializers/download_your_data_follow_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_identity_serializer.rb → download_your_data_serializers/download_your_data_identity_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_notification_serializer.rb → download_your_data_serializers/download_your_data_notification_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_participatory_space_private_user_serializer.rb → download_your_data_serializers/download_your_data_participatory_space_private_user_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_report_serializer.rb → download_your_data_serializers/download_your_data_report_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_user_group_serializer.rb → download_your_data_serializers/download_your_data_user_group_serializer.rb} +2 -2
- data/lib/decidim/{data_portability_serializers/data_portability_user_serializer.rb → download_your_data_serializers/download_your_data_user_serializer.rb} +3 -3
- data/lib/decidim/download_your_data_serializers.rb +23 -0
- data/lib/decidim/engine_router.rb +7 -1
- data/lib/decidim/env.rb +56 -0
- data/lib/decidim/event_recorder.rb +25 -0
- data/lib/decidim/events/base_event.rb +10 -14
- data/lib/decidim/events/simple_event.rb +12 -4
- data/lib/decidim/exporters/export_data.rb +1 -1
- data/lib/decidim/exporters/export_manifest.rb +2 -1
- data/lib/decidim/file_validator_humanizer.rb +24 -1
- data/lib/decidim/filterable_resource.rb +55 -0
- data/lib/decidim/fingerprint_calculator.rb +2 -4
- data/lib/decidim/form_builder.rb +158 -130
- data/lib/decidim/gamification/badge.rb +2 -3
- data/lib/decidim/gamification/badge_scorer.rb +1 -0
- data/lib/decidim/has_area.rb +27 -0
- data/lib/decidim/has_attachments.rb +2 -2
- data/lib/decidim/has_category.rb +36 -0
- data/lib/decidim/importers/import_manifest.rb +3 -21
- data/lib/decidim/jsonb_attributes.rb +6 -4
- data/lib/decidim/manifest_messages.rb +23 -0
- data/lib/decidim/map/autocomplete.rb +6 -4
- data/lib/decidim/map/frontend.rb +2 -2
- data/lib/decidim/map/provider/geocoding/here.rb +5 -5
- data/lib/decidim/map/provider/here.rb +3 -0
- data/lib/decidim/map/provider/osm.rb +3 -0
- data/lib/decidim/map.rb +4 -4
- data/lib/decidim/menu.rb +1 -1
- data/lib/decidim/metric_manifest.rb +2 -2
- data/lib/decidim/nicknamizable.rb +1 -1
- data/lib/decidim/notification_setting_manifest.rb +19 -0
- data/lib/decidim/organization_settings.rb +8 -7
- data/lib/decidim/participatory_space_context_manifest.rb +2 -2
- data/lib/decidim/participatory_space_manifest.rb +2 -2
- data/lib/decidim/processes_file_locally.rb +31 -0
- data/lib/decidim/query.rb +84 -0
- data/lib/decidim/record_encryptor.rb +29 -8
- data/lib/decidim/reminder_manifest.rb +75 -0
- data/lib/decidim/reminder_registry.rb +67 -0
- data/lib/decidim/resource_manifest.rb +1 -1
- data/lib/decidim/resourceable.rb +11 -0
- data/lib/decidim/scopable.rb +15 -0
- data/lib/decidim/settings_manifest.rb +4 -4
- data/lib/decidim/spring.rb +16 -0
- data/lib/decidim/translatable_attributes.rb +12 -8
- data/lib/decidim/url_option_resolver.rb +50 -0
- data/lib/decidim/view_hooks.rb +1 -1
- data/lib/decidim/view_model.rb +5 -1
- data/lib/decidim/webpacker/thread_safe_compiler.rb +30 -0
- data/lib/decidim/webpacker/webpack/custom.js +15 -3
- data/lib/decidim/webpacker/webpacker.yml +1 -1
- data/lib/decidim/webpacker.rb +2 -0
- data/lib/devise/models/decidim_validatable.rb +1 -1
- data/lib/tasks/decidim_active_storage_migration_tasks.rake +1 -3
- data/lib/tasks/{decidim_data_portability_tasks.rake → decidim_download_your_data_tasks.rake} +9 -9
- data/lib/tasks/decidim_mailers_tasks.rake +23 -0
- data/lib/tasks/decidim_metrics_tasks.rake +1 -1
- data/lib/tasks/decidim_pwa_tasks.rake +18 -0
- data/lib/tasks/decidim_reminders_tasks.rake +17 -0
- data/lib/tasks/decidim_tasks.rake +6 -1
- data/lib/tasks/decidim_webpacker_tasks.rake +1 -1
- data/lib/tasks/upgrade/decidim_fix_nickname_uniqueness.rake +51 -0
- metadata +184 -83
- data/app/controllers/decidim/cookie_policy_controller.rb +0 -24
- data/app/helpers/decidim/cookies_helper.rb +0 -11
- data/app/packs/src/decidim/vizzs/renders.js +0 -9
- data/app/packs/src/decidim/vizzs.js +0 -1
- data/app/packs/stylesheets/decidim/modules/_cookie-bar.scss +0 -26
- data/app/services/decidim/home_activity_search.rb +0 -80
- data/app/services/decidim/participatory_space_search.rb +0 -54
- data/app/views/decidim/cookie_policy/accept.js.erb +0 -3
- data/app/views/decidim/export_mailer/data_portability_export.html.erb +0 -7
- data/lib/decidim/data_portability_serializers.rb +0 -23
- data/lib/decidim/middleware/rails_cookies.rb +0 -23
|
@@ -121,6 +121,209 @@ shared_examples "comments" do
|
|
|
121
121
|
end
|
|
122
122
|
end
|
|
123
123
|
|
|
124
|
+
it "updates the numbers of characters left correctly" do
|
|
125
|
+
within ".add-comment form" do
|
|
126
|
+
fill_in "add-comment-#{commentable.commentable_type.demodulize}-#{commentable.id}", with: "This is a new comment."
|
|
127
|
+
expect(page).to have_content("1978 characters left")
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context "when working with the screen reader character counter" do
|
|
132
|
+
let(:field_id) { "add-comment-#{commentable.commentable_type.demodulize}-#{commentable.id}" }
|
|
133
|
+
let(:field) { page.find("##{field_id}") }
|
|
134
|
+
|
|
135
|
+
before do
|
|
136
|
+
# Make sure the focus stays in the comment form during these tests
|
|
137
|
+
# because only then the screen reader
|
|
138
|
+
page.execute_script("document.getElementById('#{field_id}').focus()")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "updates the numbers of characters left correctly for screen reader" do
|
|
142
|
+
within ".add-comment form" do
|
|
143
|
+
fill_in field_id, with: "This is a new comment."
|
|
144
|
+
|
|
145
|
+
# The screen reader character counter should update only when the user
|
|
146
|
+
# reaches 10% interval of the total characters available not to
|
|
147
|
+
# announce the remaining characters after every keystroke.
|
|
148
|
+
field.native.send_keys " Sending some new text."
|
|
149
|
+
within ".remaining-character-count" do
|
|
150
|
+
expect(page).to have_content("1955 characters left") # Normal
|
|
151
|
+
end
|
|
152
|
+
within ".remaining-character-count-sr" do
|
|
153
|
+
expect(page).to have_content("2000 characters left") # Screen reader
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# After 10% of the total characters is reached, it should be updated
|
|
157
|
+
# to the screen reader section to announce it.
|
|
158
|
+
field.native.send_keys "a" * 155
|
|
159
|
+
within ".remaining-character-count" do
|
|
160
|
+
expect(page).to have_content("1800 characters left") # Normal
|
|
161
|
+
end
|
|
162
|
+
within ".remaining-character-count-sr" do
|
|
163
|
+
expect(page).to have_content("1800 characters left") # Screen reader
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# After continuing typing after the announcement, the screen reader
|
|
167
|
+
# characters should stay the same (announced on the next 10%
|
|
168
|
+
# interval).
|
|
169
|
+
field.native.send_keys "b"
|
|
170
|
+
within ".remaining-character-count" do
|
|
171
|
+
expect(page).to have_content("1799 characters left") # Normal
|
|
172
|
+
end
|
|
173
|
+
within ".remaining-character-count-sr" do
|
|
174
|
+
expect(page).to have_content("1800 characters left") # Screen reader
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# When text is removed at the interval, the screen reader should
|
|
178
|
+
# update back to the previous interval.
|
|
179
|
+
field.native.send_keys [:backspace, :backspace, :backspace, :backspace]
|
|
180
|
+
within ".remaining-character-count" do
|
|
181
|
+
expect(page).to have_content("1803 characters left") # Normal
|
|
182
|
+
end
|
|
183
|
+
within ".remaining-character-count-sr" do
|
|
184
|
+
expect(page).to have_content("1800 characters left") # Screen reader
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# After continuing typing after the removal of characters, we should
|
|
188
|
+
# stay in the "latest announcement" not to confuse the user as
|
|
189
|
+
# - "1800 characters left" (actual 1803)
|
|
190
|
+
# - Type in one character
|
|
191
|
+
# - "1900 characters left" (actual 1802)
|
|
192
|
+
field.native.send_keys "b"
|
|
193
|
+
within ".remaining-character-count" do
|
|
194
|
+
expect(page).to have_content("1802 characters left") # Normal
|
|
195
|
+
end
|
|
196
|
+
within ".remaining-character-count-sr" do
|
|
197
|
+
expect(page).to have_content("1800 characters left") # Screen reader
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# After the input is blurred, the screen reader character counter
|
|
201
|
+
# should show the actual amount of characters left.
|
|
202
|
+
page.execute_script("document.getElementById('#{field_id}').blur()")
|
|
203
|
+
within ".remaining-character-count" do
|
|
204
|
+
expect(page).to have_content("1802 characters left") # Normal
|
|
205
|
+
end
|
|
206
|
+
within ".remaining-character-count-sr" do
|
|
207
|
+
expect(page).to have_content("1802 characters left") # Screen reader
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
context "when reaching the announce after every threshold" do
|
|
213
|
+
it "updates the numbers of characters left correctly for screen reader" do
|
|
214
|
+
within ".add-comment form" do
|
|
215
|
+
# Test that when reaching the "announce after every" threshold, the
|
|
216
|
+
# characters are announced after every keystroke.
|
|
217
|
+
fill_in field_id, with: "a" * 1989
|
|
218
|
+
within ".remaining-character-count" do
|
|
219
|
+
expect(page).to have_content("11 characters left") # Normal
|
|
220
|
+
end
|
|
221
|
+
within ".remaining-character-count-sr" do
|
|
222
|
+
expect(page).to have_content("200 characters left") # Screen reader
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
(2..10).reverse_each do |remaining|
|
|
226
|
+
field.native.send_keys "b"
|
|
227
|
+
within ".remaining-character-count-sr" do
|
|
228
|
+
expect(page).to have_content("#{remaining} characters left")
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
field.native.send_keys "b"
|
|
233
|
+
within ".remaining-character-count-sr" do
|
|
234
|
+
expect(page).to have_content("1 character left")
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
field.native.send_keys "c"
|
|
238
|
+
within ".remaining-character-count-sr" do
|
|
239
|
+
expect(page).to have_content("0 characters left")
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Test that the SR counter will stick at the last announced
|
|
243
|
+
# threshold if the next threshold is not hit and text is removed.
|
|
244
|
+
# This prevents weird announcements such as:
|
|
245
|
+
# - 0 characters left
|
|
246
|
+
# - Remove 10 characters
|
|
247
|
+
# - 10 characters left
|
|
248
|
+
# - Remove 1 character
|
|
249
|
+
# - 200 characters left
|
|
250
|
+
page.execute_script("document.getElementById('#{field_id}').setSelectionRange(1850, 2000)")
|
|
251
|
+
field.native.send_keys [:backspace]
|
|
252
|
+
within ".remaining-character-count" do
|
|
253
|
+
expect(page).to have_content("150 characters left") # Normal
|
|
254
|
+
end
|
|
255
|
+
within ".remaining-character-count-sr" do
|
|
256
|
+
expect(page).to have_content("0 characters left") # Screen reader
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
field.native.send_keys "d"
|
|
260
|
+
within ".remaining-character-count-sr" do
|
|
261
|
+
expect(page).to have_content("0 characters left")
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context "when deleting text the announce after every threshold" do
|
|
268
|
+
it "updates the numbers of characters left correctly for screen reader" do
|
|
269
|
+
within ".add-comment form" do
|
|
270
|
+
fill_in field_id, with: "a" * 2000
|
|
271
|
+
within ".remaining-character-count" do
|
|
272
|
+
expect(page).to have_content("0 characters left") # Normal
|
|
273
|
+
end
|
|
274
|
+
within ".remaining-character-count-sr" do
|
|
275
|
+
expect(page).to have_content("0 characters left") # Screen reader
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Test that the SR counter updates correctly after hitting the
|
|
279
|
+
# next threshold.
|
|
280
|
+
page.execute_script("document.getElementById('#{field_id}').setSelectionRange(1800, 2000)")
|
|
281
|
+
field.native.send_keys [:backspace]
|
|
282
|
+
within ".remaining-character-count" do
|
|
283
|
+
expect(page).to have_content("200 characters left") # Normal
|
|
284
|
+
end
|
|
285
|
+
within ".remaining-character-count-sr" do
|
|
286
|
+
expect(page).to have_content("200 characters left") # Screen reader
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# The SR counter should stay at the correct boundary.
|
|
290
|
+
field.native.send_keys [:backspace, :backspace]
|
|
291
|
+
within ".remaining-character-count" do
|
|
292
|
+
expect(page).to have_content("202 characters left") # Normal
|
|
293
|
+
end
|
|
294
|
+
within ".remaining-character-count-sr" do
|
|
295
|
+
expect(page).to have_content("200 characters left") # Screen reader
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# It stays at the correct boundary when starting to type again.
|
|
299
|
+
field.native.send_keys "b"
|
|
300
|
+
within ".remaining-character-count" do
|
|
301
|
+
expect(page).to have_content("201 characters left") # Normal
|
|
302
|
+
end
|
|
303
|
+
within ".remaining-character-count-sr" do
|
|
304
|
+
expect(page).to have_content("200 characters left") # Screen reader
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
field.native.send_keys "c"
|
|
308
|
+
within ".remaining-character-count" do
|
|
309
|
+
expect(page).to have_content("200 characters left") # Normal
|
|
310
|
+
end
|
|
311
|
+
within ".remaining-character-count-sr" do
|
|
312
|
+
expect(page).to have_content("200 characters left") # Screen reader
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
field.native.send_keys "d"
|
|
316
|
+
within ".remaining-character-count" do
|
|
317
|
+
expect(page).to have_content("199 characters left") # Normal
|
|
318
|
+
end
|
|
319
|
+
within ".remaining-character-count-sr" do
|
|
320
|
+
expect(page).to have_content("200 characters left") # Screen reader
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
124
327
|
context "when component is present and has a default comments length params" do
|
|
125
328
|
it "displays the numbers of characters left" do
|
|
126
329
|
if component.present?
|
|
@@ -15,7 +15,7 @@ shared_examples "email with logo" do
|
|
|
15
15
|
|
|
16
16
|
it "includes organization logo with full link" do
|
|
17
17
|
expect(mail.body).to include("alt=\"#{organization.name}\"")
|
|
18
|
-
expect(mail.body).to match(%r{https{0,1}://#{organization.host}#{logo_path}})
|
|
18
|
+
expect(mail.body).to match(%r{https{0,1}://#{organization.host}:#{Capybara.server_port}#{logo_path}})
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -24,7 +24,7 @@ shared_context "with frontend map builder" do
|
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
let(:organization) { create(:organization) }
|
|
27
|
-
let(:template) { template_class.new(ActionView::LookupContext.new(
|
|
27
|
+
let(:template) { template_class.new(ActionView::LookupContext.new(ActionController::Base.view_paths), {}, []) }
|
|
28
28
|
let(:options) { {} }
|
|
29
29
|
let(:js_options) { options.transform_keys { |k| k.to_s.camelize(:lower) }.to_h }
|
|
30
30
|
|
|
@@ -103,6 +103,7 @@ shared_context "with frontend map elements" do
|
|
|
103
103
|
final_html = html_document
|
|
104
104
|
Rails.application.routes.draw do
|
|
105
105
|
get "test_dynamic_map", to: ->(_) { [200, {}, [final_html]] }
|
|
106
|
+
get "offline", to: ->(_) { [200, {}, [""]] }
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
visit "/test_dynamic_map"
|
|
@@ -180,7 +181,6 @@ shared_examples "a record with front-end geocoding address field" do |geocoded_m
|
|
|
180
181
|
it "calls the front-end geocoder when an address is written", :slow do
|
|
181
182
|
within view_options[:within_selector] do
|
|
182
183
|
fill_in_geocoding view_options[:address_field], with: geocoded_address_value
|
|
183
|
-
find(".tribute-container ul#results li", match: :first).click
|
|
184
184
|
find("*[type=submit]").click
|
|
185
185
|
end
|
|
186
186
|
|
|
@@ -15,9 +15,7 @@ shared_examples_for "preview component with share_token" do
|
|
|
15
15
|
|
|
16
16
|
it "does not allow visiting component" do
|
|
17
17
|
expect(page).to have_content "You are not authorized"
|
|
18
|
-
# rubocop:disable Capybara/CurrentPathExpectation
|
|
19
18
|
expect(page.current_path).not_to match main_component_path(component)
|
|
20
|
-
# rubocop:enable Capybara/CurrentPathExpectation
|
|
21
19
|
end
|
|
22
20
|
end
|
|
23
21
|
|
|
@@ -34,9 +32,7 @@ shared_examples_for "preview component with share_token" do
|
|
|
34
32
|
context "when a valid share_token is provided" do
|
|
35
33
|
it "allows visiting component" do
|
|
36
34
|
expect(page).not_to have_content "You are not authorized"
|
|
37
|
-
# rubocop:disable Capybara/CurrentPathExpectation
|
|
38
35
|
expect(page.current_path).to match main_component_path(component)
|
|
39
|
-
# rubocop:enable Capybara/CurrentPathExpectation
|
|
40
36
|
end
|
|
41
37
|
end
|
|
42
38
|
|
|
@@ -45,9 +41,7 @@ shared_examples_for "preview component with share_token" do
|
|
|
45
41
|
|
|
46
42
|
it "does not allow visiting component" do
|
|
47
43
|
expect(page).to have_content "You are not authorized"
|
|
48
|
-
# rubocop:disable Capybara/CurrentPathExpectation
|
|
49
44
|
expect(page.current_path).not_to match main_component_path(component)
|
|
50
|
-
# rubocop:enable Capybara/CurrentPathExpectation
|
|
51
45
|
end
|
|
52
46
|
end
|
|
53
47
|
end
|
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
5
|
shared_examples_for "a resource search" do |factory_name|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
describe "component_id" do
|
|
7
|
+
before do
|
|
8
|
+
get(
|
|
9
|
+
request_path,
|
|
10
|
+
headers: { "HOST" => component.organization.host }
|
|
11
|
+
)
|
|
11
12
|
end
|
|
12
|
-
end
|
|
13
13
|
|
|
14
|
-
describe "component_id" do
|
|
15
14
|
it "only returns resources from the given component" do
|
|
16
15
|
external_resource = create(factory_name)
|
|
17
16
|
|
|
18
|
-
expect(subject).not_to
|
|
17
|
+
expect(subject).not_to have_escaped_html(translated(external_resource.try(:title) || external_resource.try(:name)))
|
|
19
18
|
end
|
|
20
19
|
end
|
|
21
20
|
end
|
|
@@ -28,7 +27,7 @@ shared_examples_for "a resource search with scopes" do |factory_name|
|
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
describe "scope_id filter" do
|
|
31
|
-
let(:
|
|
30
|
+
let(:filter_params) { { with_any_scope: scope_ids } }
|
|
32
31
|
|
|
33
32
|
let(:scope1) { create :scope, organization: component.organization }
|
|
34
33
|
let(:scope2) { create :scope, organization: component.organization }
|
|
@@ -38,11 +37,21 @@ shared_examples_for "a resource search with scopes" do |factory_name|
|
|
|
38
37
|
let!(:resource2) { create(factory_name, { component: component, scope: scope2 }.merge(factory_params)) }
|
|
39
38
|
let!(:resource3) { create(factory_name, { component: component, scope: subscope1 }.merge(factory_params)) }
|
|
40
39
|
|
|
40
|
+
before do
|
|
41
|
+
get(
|
|
42
|
+
request_path,
|
|
43
|
+
params: { filter: filter_params },
|
|
44
|
+
headers: { "HOST" => component.organization.host }
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
41
48
|
context "when a parent scope id is being sent" do
|
|
42
49
|
let(:scope_ids) { [scope1.id] }
|
|
43
50
|
|
|
44
51
|
it "filters resources by scope" do
|
|
45
|
-
expect(subject).to
|
|
52
|
+
expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
53
|
+
expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
54
|
+
expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
46
55
|
end
|
|
47
56
|
end
|
|
48
57
|
|
|
@@ -50,7 +59,9 @@ shared_examples_for "a resource search with scopes" do |factory_name|
|
|
|
50
59
|
let(:scope_ids) { [subscope1.id] }
|
|
51
60
|
|
|
52
61
|
it "filters resources by scope" do
|
|
53
|
-
expect(subject).
|
|
62
|
+
expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
63
|
+
expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
64
|
+
expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
54
65
|
end
|
|
55
66
|
end
|
|
56
67
|
|
|
@@ -58,7 +69,9 @@ shared_examples_for "a resource search with scopes" do |factory_name|
|
|
|
58
69
|
let(:scope_ids) { [scope2.id, scope1.id] }
|
|
59
70
|
|
|
60
71
|
it "filters resources by scope" do
|
|
61
|
-
expect(subject).to
|
|
72
|
+
expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
73
|
+
expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
74
|
+
expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
62
75
|
end
|
|
63
76
|
end
|
|
64
77
|
|
|
@@ -66,8 +79,19 @@ shared_examples_for "a resource search with scopes" do |factory_name|
|
|
|
66
79
|
let!(:resource_without_scope) { create(factory_name, { component: component, scope: nil }.merge(factory_params)) }
|
|
67
80
|
let(:scope_ids) { ["global"] }
|
|
68
81
|
|
|
82
|
+
before do
|
|
83
|
+
get(
|
|
84
|
+
request_path,
|
|
85
|
+
params: { filter: filter_params },
|
|
86
|
+
headers: { "HOST" => component.organization.host }
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
69
90
|
it "returns resources without a scope" do
|
|
70
|
-
expect(subject).
|
|
91
|
+
expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
92
|
+
expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
93
|
+
expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
94
|
+
expect(subject).to have_escaped_html(translated(resource_without_scope.try(:title) || resource_without_scope.try(:name)))
|
|
71
95
|
end
|
|
72
96
|
end
|
|
73
97
|
|
|
@@ -75,16 +99,34 @@ shared_examples_for "a resource search with scopes" do |factory_name|
|
|
|
75
99
|
let!(:resource_without_scope) { create(factory_name, { component: component, scope: nil }.merge(factory_params)) }
|
|
76
100
|
let(:scope_ids) { ["global", scope2.id, scope1.id] }
|
|
77
101
|
|
|
102
|
+
before do
|
|
103
|
+
get(
|
|
104
|
+
request_path,
|
|
105
|
+
params: { filter: filter_params },
|
|
106
|
+
headers: { "HOST" => component.organization.host }
|
|
107
|
+
)
|
|
108
|
+
end
|
|
109
|
+
|
|
78
110
|
it "returns resources without a scope and with selected scopes" do
|
|
79
|
-
expect(subject).to
|
|
111
|
+
expect(subject).to have_escaped_html(translated(resource_without_scope.try(:title) || resource_without_scope.try(:name)))
|
|
112
|
+
expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
113
|
+
expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
114
|
+
expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
80
115
|
end
|
|
81
116
|
end
|
|
82
117
|
end
|
|
83
118
|
end
|
|
84
119
|
|
|
85
|
-
shared_examples_for "a resource search with categories" do |factory_name|
|
|
86
|
-
let(:
|
|
87
|
-
let(:
|
|
120
|
+
shared_examples_for "a resource search with categories" do |factory_name, category_mode = :multi|
|
|
121
|
+
let(:participatory_space) { component.participatory_space }
|
|
122
|
+
let(:filter_params) do
|
|
123
|
+
case category_mode
|
|
124
|
+
when :single
|
|
125
|
+
{ with_category: category_ids }
|
|
126
|
+
else
|
|
127
|
+
{ with_any_category: category_ids }
|
|
128
|
+
end
|
|
129
|
+
end
|
|
88
130
|
let(:factory_params) do
|
|
89
131
|
resource_params
|
|
90
132
|
rescue StandardError
|
|
@@ -92,19 +134,30 @@ shared_examples_for "a resource search with categories" do |factory_name|
|
|
|
92
134
|
end
|
|
93
135
|
|
|
94
136
|
describe "results" do
|
|
95
|
-
let(:category1) { create :category, participatory_space:
|
|
96
|
-
let(:category2) { create :category, participatory_space:
|
|
97
|
-
let(:child_category) { create :category, participatory_space:
|
|
137
|
+
let(:category1) { create :category, participatory_space: participatory_space }
|
|
138
|
+
let(:category2) { create :category, participatory_space: participatory_space }
|
|
139
|
+
let(:child_category) { create :category, participatory_space: participatory_space, parent: category2 }
|
|
98
140
|
let!(:resource) { create(factory_name, { component: component }.merge(factory_params)) }
|
|
99
141
|
let!(:resource2) { create(factory_name, { component: component, category: category1 }.merge(factory_params)) }
|
|
100
142
|
let!(:resource3) { create(factory_name, { component: component, category: category2 }.merge(factory_params)) }
|
|
101
143
|
let!(:resource4) { create(factory_name, { component: component, category: child_category }.merge(factory_params)) }
|
|
102
144
|
|
|
145
|
+
before do
|
|
146
|
+
get(
|
|
147
|
+
request_path,
|
|
148
|
+
params: { filter: filter_params },
|
|
149
|
+
headers: { "HOST" => component.organization.host }
|
|
150
|
+
)
|
|
151
|
+
end
|
|
152
|
+
|
|
103
153
|
context "when no category filter is present" do
|
|
104
154
|
let(:category_ids) { nil }
|
|
105
155
|
|
|
106
156
|
it "includes all resources" do
|
|
107
|
-
expect(subject).to
|
|
157
|
+
expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
158
|
+
expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
159
|
+
expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
160
|
+
expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
|
|
108
161
|
end
|
|
109
162
|
end
|
|
110
163
|
|
|
@@ -112,7 +165,10 @@ shared_examples_for "a resource search with categories" do |factory_name|
|
|
|
112
165
|
let(:category_ids) { [category2.id] }
|
|
113
166
|
|
|
114
167
|
it "includes only resources for that category and its children" do
|
|
115
|
-
expect(subject).
|
|
168
|
+
expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
169
|
+
expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
170
|
+
expect(subject).to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
171
|
+
expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
|
|
116
172
|
end
|
|
117
173
|
end
|
|
118
174
|
|
|
@@ -120,7 +176,10 @@ shared_examples_for "a resource search with categories" do |factory_name|
|
|
|
120
176
|
let(:category_ids) { [child_category.id] }
|
|
121
177
|
|
|
122
178
|
it "includes only resources for that category" do
|
|
123
|
-
expect(subject).
|
|
179
|
+
expect(subject).not_to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
180
|
+
expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
181
|
+
expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
182
|
+
expect(subject).to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
|
|
124
183
|
end
|
|
125
184
|
end
|
|
126
185
|
|
|
@@ -128,15 +187,23 @@ shared_examples_for "a resource search with categories" do |factory_name|
|
|
|
128
187
|
let(:category_ids) { ["without"] }
|
|
129
188
|
|
|
130
189
|
it "returns resources without a category" do
|
|
131
|
-
expect(subject).to
|
|
190
|
+
expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
191
|
+
expect(subject).not_to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
192
|
+
expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
193
|
+
expect(subject).not_to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
|
|
132
194
|
end
|
|
133
195
|
end
|
|
134
196
|
|
|
135
|
-
|
|
136
|
-
|
|
197
|
+
if category_mode == :multi
|
|
198
|
+
context "when `without` and some category id is being sent" do
|
|
199
|
+
let(:category_ids) { ["without", category1.id] }
|
|
137
200
|
|
|
138
|
-
|
|
139
|
-
|
|
201
|
+
it "returns resources without a category and with the selected category" do
|
|
202
|
+
expect(subject).to have_escaped_html(translated(resource.try(:title) || resource.try(:name)))
|
|
203
|
+
expect(subject).to have_escaped_html(translated(resource2.try(:title) || resource2.try(:name)))
|
|
204
|
+
expect(subject).not_to have_escaped_html(translated(resource3.try(:title) || resource3.try(:name)))
|
|
205
|
+
expect(subject).not_to have_escaped_html(translated(resource4.try(:title) || resource4.try(:name)))
|
|
206
|
+
end
|
|
140
207
|
end
|
|
141
208
|
end
|
|
142
209
|
end
|
|
@@ -148,32 +215,42 @@ shared_examples_for "a resource search with origin" do |factory_name|
|
|
|
148
215
|
rescue StandardError
|
|
149
216
|
{}
|
|
150
217
|
end
|
|
151
|
-
let(:
|
|
218
|
+
let(:filter_params) { { with_any_origin: origins } }
|
|
152
219
|
|
|
153
220
|
describe "results" do
|
|
154
221
|
let!(:official_resource) { create(factory_name, :official, { component: component }.merge(factory_params)) }
|
|
155
222
|
let!(:user_group_resource) { create(factory_name, :user_group_author, { component: component }.merge(factory_params)) }
|
|
156
|
-
let!(:
|
|
223
|
+
let!(:participant_resource) { create(factory_name, :participant_author, { component: component }.merge(factory_params)) }
|
|
157
224
|
|
|
158
225
|
if FactoryBot.factory_by_name(factory_name).defined_traits.map(&:name).include?(:meeting_resource)
|
|
159
226
|
let!(:meeting_resource) { create(factory_name, :official_meeting, { component: component }.merge(factory_params)) }
|
|
160
227
|
end
|
|
161
228
|
|
|
229
|
+
before do
|
|
230
|
+
get(
|
|
231
|
+
request_path,
|
|
232
|
+
params: { filter: filter_params },
|
|
233
|
+
headers: { "HOST" => component.organization.host }
|
|
234
|
+
)
|
|
235
|
+
end
|
|
236
|
+
|
|
162
237
|
context "when filtering official resources" do
|
|
163
238
|
let(:origins) { %w(official) }
|
|
164
239
|
|
|
165
240
|
it "returns only official resources" do
|
|
166
|
-
expect(subject
|
|
167
|
-
expect(subject).
|
|
241
|
+
expect(subject).to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
|
|
242
|
+
expect(subject).not_to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
|
|
243
|
+
expect(subject).not_to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
|
|
168
244
|
end
|
|
169
245
|
end
|
|
170
246
|
|
|
171
|
-
context "when filtering
|
|
172
|
-
let(:origins) { %w(
|
|
247
|
+
context "when filtering participants resources" do
|
|
248
|
+
let(:origins) { %w(participants) }
|
|
173
249
|
|
|
174
250
|
it "returns only citizen resources" do
|
|
175
|
-
expect(subject
|
|
176
|
-
expect(subject).to
|
|
251
|
+
expect(subject).not_to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
|
|
252
|
+
expect(subject).to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
|
|
253
|
+
expect(subject).not_to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
|
|
177
254
|
end
|
|
178
255
|
end
|
|
179
256
|
|
|
@@ -181,8 +258,9 @@ shared_examples_for "a resource search with origin" do |factory_name|
|
|
|
181
258
|
let(:origins) { %w(user_group) }
|
|
182
259
|
|
|
183
260
|
it "returns only user groups resources" do
|
|
184
|
-
expect(subject
|
|
185
|
-
expect(subject).
|
|
261
|
+
expect(subject).not_to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
|
|
262
|
+
expect(subject).not_to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
|
|
263
|
+
expect(subject).to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
|
|
186
264
|
end
|
|
187
265
|
end
|
|
188
266
|
|
|
@@ -191,8 +269,10 @@ shared_examples_for "a resource search with origin" do |factory_name|
|
|
|
191
269
|
let(:origins) { %w(meeting) }
|
|
192
270
|
|
|
193
271
|
it "returns only meeting resources" do
|
|
194
|
-
expect(subject
|
|
195
|
-
expect(subject).
|
|
272
|
+
expect(subject).not_to have_escaped_html(translated(official_resource.try(:title) || official_resource.try(:name)))
|
|
273
|
+
expect(subject).not_to have_escaped_html(translated(participant_resource.try(:title) || participant_resource.try(:name)))
|
|
274
|
+
expect(subject).not_to have_escaped_html(translated(user_group_resource.try(:title) || user_group_resource.try(:name)))
|
|
275
|
+
expect(subject).to have_escaped_html(translated(meeting_resource.try(:title) || meeting_resource.try(:name)))
|
|
196
276
|
end
|
|
197
277
|
end
|
|
198
278
|
end
|
|
@@ -83,7 +83,7 @@ shared_examples "global search of participatory spaces" do
|
|
|
83
83
|
describe "Search" do
|
|
84
84
|
# trick to force creating participatory_space2 declared in users of this shared_examples
|
|
85
85
|
let!(:spaces) { [participatory_space, participatory_space2] }
|
|
86
|
-
let(:
|
|
86
|
+
let(:description2) do
|
|
87
87
|
msg = "Chewie, I'll be waiting for your signal. Take care, you two. May the Force be with you. Ow!"
|
|
88
88
|
{ ca: "CA:#{msg}", en: "EN:#{msg}", es: "ES:#{msg}" }
|
|
89
89
|
end
|
|
@@ -6,7 +6,7 @@ RSpec.shared_context "when a resource is ready for global search" do
|
|
|
6
6
|
let!(:scope1) { create :scope, organization: organization }
|
|
7
7
|
|
|
8
8
|
let(:test_locales) { [:ca, :en, :es] }
|
|
9
|
-
let(:
|
|
9
|
+
let(:description1) do
|
|
10
10
|
Decidim::Faker::Localized.prefixed("Poemes als terrats de l'Empordà, Ow!", test_locales)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -6,11 +6,11 @@ shared_context "with resources to be endorsed or not" do
|
|
|
6
6
|
include_context "with a component"
|
|
7
7
|
|
|
8
8
|
# Should be overriden and create one main resource
|
|
9
|
-
let!(:resource) {}
|
|
9
|
+
let!(:resource) { nil }
|
|
10
10
|
# the name of the resource to be clicked from the component view
|
|
11
|
-
let(:resource_name) {}
|
|
11
|
+
let(:resource_name) { nil }
|
|
12
12
|
# Should be overriden and create 3 extra resources in the current component
|
|
13
|
-
let!(:resources) {}
|
|
13
|
+
let!(:resources) { nil }
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
shared_examples "Endorse resource system specs" do
|
|
@@ -56,7 +56,7 @@ shared_examples_for "a translated event" do
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
context "when translation is not available" do
|
|
59
|
-
let(:body) { {
|
|
59
|
+
let(:body) { { en: en_body } }
|
|
60
60
|
|
|
61
61
|
it "does perform translation" do
|
|
62
62
|
expect(subject.perform_translation?).to eq(translatable)
|
|
@@ -104,7 +104,7 @@ shared_examples_for "a translated event" do
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
context "when translation is not available" do
|
|
107
|
-
let(:body) { {
|
|
107
|
+
let(:body) { { en: en_body } }
|
|
108
108
|
|
|
109
109
|
it "does perform translation" do
|
|
110
110
|
expect(subject.perform_translation?).to eq(translatable)
|