diff options
26 files changed, 192 insertions, 61 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 6be36cd7794..4cc1b2f0acf 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -8cdbdb46b4fa31e0c2f1e2646baaf0ffb271b3a0 +b02caa3eee821fd26374239879fb5f4828c573cc diff --git a/app/assets/javascripts/pages/projects/environments/show/index.js b/app/assets/javascripts/pages/projects/environments/show/index.js index 5d3a153cbd1..a4960037eaa 100644 --- a/app/assets/javascripts/pages/projects/environments/show/index.js +++ b/app/assets/javascripts/pages/projects/environments/show/index.js @@ -1,3 +1,3 @@ import initShowEnvironment from '~/environments/mount_show'; -document.addEventListener('DOMContentLoaded', initShowEnvironment); +initShowEnvironment(); diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 33bd40a488f..fa008a05e11 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -112,7 +112,7 @@ } th { - border-top-color: $gray-light; + border: 0; } td { diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index e3dcd5b0d07..da5f4cc1862 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -7,6 +7,7 @@ module Clusters include EnumWithNil include AfterCommitQueue include ReactiveCaching + include NullifyIfBlank RESERVED_NAMESPACES = %w(gitlab-managed-apps).freeze @@ -25,7 +26,6 @@ module Clusters key: Settings.attr_encrypted_db_key_base_truncated, algorithm: 'aes-256-cbc' - before_validation :nullify_blank_namespace before_validation :enforce_namespace_to_lower_case before_validation :enforce_ca_whitespace_trimming @@ -64,6 +64,8 @@ module Clusters default_value_for :authorization_type, :rbac + nullify_if_blank :namespace + def predefined_variables(project:, environment_name:, kubernetes_namespace: nil) Gitlab::Ci::Variables::Collection.new.tap do |variables| variables.append(key: 'KUBE_URL', value: api_url) @@ -255,10 +257,6 @@ module Clusters true end - def nullify_blank_namespace - self.namespace = nil if namespace.blank? - end - def extract_relevant_pod_data(pods) pods.map do |pod| { diff --git a/app/models/concerns/nullify_if_blank.rb b/app/models/concerns/nullify_if_blank.rb new file mode 100644 index 00000000000..5a5cc51509b --- /dev/null +++ b/app/models/concerns/nullify_if_blank.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +# Helper that sets attributes to nil prior to validation if they +# are blank (are false, empty or contain only whitespace), to avoid +# unnecessarily persisting empty strings. +# +# Model usage: +# +# class User < ApplicationRecord +# include NullifyIfBlank +# +# nullify_if_blank :name, :email +# end +# +# +# Test usage: +# +# RSpec.describe User do +# it { is_expected.to nullify_if_blank(:name) } +# it { is_expected.to nullify_if_blank(:email) } +# end +# +module NullifyIfBlank + extend ActiveSupport::Concern + + class_methods do + def nullify_if_blank(*attributes) + self.attributes_to_nullify += attributes + end + end + + included do + class_attribute :attributes_to_nullify, + instance_accessor: false, + instance_predicate: false, + default: Set.new + + before_validation :nullify_blank_attributes + end + + private + + def nullify_blank_attributes + self.class.attributes_to_nullify.each do |attribute| + assign_attributes(attribute => nil) if read_attribute(attribute).blank? + end + end +end diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index 4fa2fc6fd4d..784f477673a 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -7,15 +7,15 @@ projects: - if can? current_user, :admin_group, @group .controls - = link_to new_project_path(namespace_id: @group.id), class: "btn btn-sm btn-success" do + = link_to new_project_path(namespace_id: @group.id), class: "btn gl-button btn-sm btn-success" do New project %ul.projects-list.content-list.group-settings-projects - @projects.each do |project| %li.project-row{ class: ('no-description' if project.description.blank?) } .controls - = link_to _('Members'), project_project_members_path(project), id: "edit_#{dom_id(project)}", class: "btn" - = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn" - = link_to _('Delete'), project, data: { confirm: remove_project_message(project)}, method: :delete, class: "gl-button btn btn-danger" + = link_to _('Members'), project_project_members_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button" + = link_to _('Edit'), edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn gl-button" + = link_to _('Delete'), project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn gl-button btn-danger" .stats %span.badge.badge-pill diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml index c421a569a14..627807841c5 100644 --- a/app/views/groups/settings/_advanced.html.haml +++ b/app/views/groups/settings/_advanced.html.haml @@ -22,7 +22,7 @@ pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, title: s_('GroupSettings|Please choose a group URL with no special characters.'), "data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}" - = f.submit s_('GroupSettings|Change group URL'), class: 'btn btn-warning' + = f.submit s_('GroupSettings|Change group URL'), class: 'btn gl-button btn-warning' .sub-section %h4.warning-title= s_('GroupSettings|Transfer group') @@ -38,7 +38,7 @@ %li= s_('GroupSettings|You can only transfer the group to a group you manage.') %li= s_('GroupSettings|You will need to update your local repositories to point to the new location.') %li= s_("GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.") - = f.submit s_('GroupSettings|Transfer group'), class: 'btn btn-warning' + = f.submit s_('GroupSettings|Transfer group'), class: 'btn gl-button btn-warning' = render 'groups/settings/remove', group: @group = render_if_exists 'groups/settings/restore', group: @group diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml index 94466b76ac8..f818f45cf53 100644 --- a/app/views/groups/settings/_export.html.haml +++ b/app/views/groups/settings/_export.html.haml @@ -20,9 +20,9 @@ %p= _('Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page.') - if group.export_file_exists? = link_to _('Regenerate export'), export_group_path(group), - method: :post, class: 'btn btn-default', data: { qa_selector: 'regenerate_export_group_link' } + method: :post, class: 'btn gl-button btn-default', data: { qa_selector: 'regenerate_export_group_link' } = link_to _('Download export'), download_export_group_path(group), - rel: 'nofollow', method: :get, class: 'btn btn-default', data: { qa_selector: 'download_export_link' } + rel: 'nofollow', method: :get, class: 'btn gl-button btn-default', data: { qa_selector: 'download_export_link' } - else = link_to _('Export group'), export_group_path(group), - method: :post, class: 'btn btn-default', data: { qa_selector: 'export_group_link' } + method: :post, class: 'btn gl-button btn-default', data: { qa_selector: 'export_group_link' } diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml index 35d82084263..8ad5755fef8 100644 --- a/app/views/groups/settings/_general.html.haml +++ b/app/views/groups/settings/_general.html.haml @@ -29,4 +29,4 @@ = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-link' = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group - = f.submit _('Save changes'), class: 'btn btn-success mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' } + = f.submit _('Save changes'), class: 'btn gl-button btn-success mt-4 js-dirty-submit', data: { qa_selector: 'save_name_visibility_settings_button' } diff --git a/app/views/groups/settings/_pages_settings.html.haml b/app/views/groups/settings/_pages_settings.html.haml index b6cf05d96ab..273714d4dcc 100644 --- a/app/views/groups/settings/_pages_settings.html.haml +++ b/app/views/groups/settings/_pages_settings.html.haml @@ -2,4 +2,4 @@ = render_if_exists 'shared/pages/max_pages_size_input', form: f .gl-mt-3 - = f.submit s_('GitLabPages|Save'), class: 'btn btn-success' + = f.submit s_('GitLabPages|Save'), class: 'btn gl-button btn-success' diff --git a/app/views/groups/settings/_permanent_deletion.html.haml b/app/views/groups/settings/_permanent_deletion.html.haml index 14719200b45..8bd47fbea44 100644 --- a/app/views/groups/settings/_permanent_deletion.html.haml +++ b/app/views/groups/settings/_permanent_deletion.html.haml @@ -5,4 +5,4 @@ = _('Removing this group also removes all child projects, including archived projects, and their resources.') %br %strong= _('Removed group can not be restored!') - = button_to _('Remove group'), '#', class: 'gl-button btn btn-danger js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(group) } + = button_to _('Remove group'), '#', class: 'btn gl-button btn-danger js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(group) } diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml index 21d6a888d7b..6e2c28ba2e8 100644 --- a/app/views/groups/settings/_permissions.html.haml +++ b/app/views/groups/settings/_permissions.html.haml @@ -41,4 +41,4 @@ = render 'groups/settings/two_factor_auth', f: f, group: @group = render_if_exists 'groups/personal_access_token_expiration_policy', f: f, group: @group = render_if_exists 'groups/member_lock_setting', f: f, group: @group - = f.submit _('Save changes'), class: 'btn btn-success gl-mt-3 js-dirty-submit', data: { qa_selector: 'save_permissions_changes_button' } + = f.submit _('Save changes'), class: 'btn gl-button btn-success gl-mt-3 js-dirty-submit', data: { qa_selector: 'save_permissions_changes_button' } diff --git a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml index 8f1ce11ce40..c18fe79be05 100644 --- a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml +++ b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml @@ -12,4 +12,4 @@ .form-text.text-muted = s_('GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found.') = link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank' - = f.submit _('Save changes'), class: 'btn btn-success gl-mt-5' + = f.submit _('Save changes'), class: 'btn gl-button btn-success gl-mt-5' diff --git a/app/views/groups/settings/ci_cd/_form.html.haml b/app/views/groups/settings/ci_cd/_form.html.haml index 635e3b64e39..eb61ecf5536 100644 --- a/app/views/groups/settings/ci_cd/_form.html.haml +++ b/app/views/groups/settings/ci_cd/_form.html.haml @@ -10,4 +10,4 @@ = _("The maximum file size in megabytes for individual job artifacts.") = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank' - = f.submit _('Save changes'), class: "btn btn-success" + = f.submit _('Save changes'), class: "btn gl-button btn-success" diff --git a/app/views/groups/settings/repository/_initial_branch_name.html.haml b/app/views/groups/settings/repository/_initial_branch_name.html.haml index 3ef8dccae08..1881ec31b0c 100644 --- a/app/views/groups/settings/repository/_initial_branch_name.html.haml +++ b/app/views/groups/settings/repository/_initial_branch_name.html.haml @@ -19,4 +19,4 @@ = (_("Changes affect new repositories only. If not specified, either the configured application-wide default or Git's default name %{branch_name_default} will be used.") % { branch_name_default: fallback_branch_name }).html_safe = f.hidden_field :redirect_target, value: "repository_settings" - = f.submit _('Save changes'), class: 'gl-button btn-success' + = f.submit _('Save changes'), class: 'btn gl-button btn-success' diff --git a/changelogs/unreleased/231219-yo-gitlab-ui.yml b/changelogs/unreleased/231219-yo-gitlab-ui.yml new file mode 100644 index 00000000000..c42b88a8d69 --- /dev/null +++ b/changelogs/unreleased/231219-yo-gitlab-ui.yml @@ -0,0 +1,5 @@ +--- +title: Apply GitLab UI button styles to buttons in group settings +merge_request: 51781 +author: Yogi (@yo) +type: other diff --git a/changelogs/unreleased/fix-table-header-space.yml b/changelogs/unreleased/fix-table-header-space.yml new file mode 100644 index 00000000000..8fd2b3a8063 --- /dev/null +++ b/changelogs/unreleased/fix-table-header-space.yml @@ -0,0 +1,5 @@ +--- +title: Fix gap in tree table header +merge_request: 54025 +author: +type: fixed diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index 49adaa7eabf..d269d28d604 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -689,7 +689,7 @@ Pages server. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) in GitLab 13.3. GitLab Pages can use different sources to get domain configuration. -The default value is `nil`. However, GitLab Pages defaults to `auto`. +The default value for Omnibus installations is `nil`. ```ruby gitlab_pages['domain_config_source'] = nil @@ -700,8 +700,33 @@ preferred source is `gitlab`, which uses [API-based configuration](#gitlab-api-b For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/). +### Deprecated domain_config_source + +WARNING: +The flag `gitlab_pages['domain_config_source']` is deprecated for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913), +and is planned for removal in GitLab 14.0. + +GitLab 13.0 introduced the special flag `domain_config_source` to support manual opt-in to +[API-based configuration](#gitlab-api-based-configuration). +GitLab 13.7 introduced the [`auto` value](https://gitlab.com/gitlab-org/gitlab/-/issues/218358) +to support a smoother transition to API-based configuration. + +Starting with GitLab 14.0, GitLab Pages only supports API-based configuration, and +[disk source configuration is removed](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382). +Therefore, GitLab 14.0 also removes `domain_config_source`. + +GitLab Pages fails to start if it can't connect to the GitLab API. For other common issues, see the +[troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api) +or report an issue. + ### GitLab API-based configuration +WARNING: +The flag `gitlab_pages['domain_config_source']` is deprecated for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913), +and is planned for removal in GitLab 14.0. In GitLab 14.0 and later, GitLab Pages attempts to +connect to the API automatically, without requiring the manual configuration steps shown here. Pages +fails to start if this automatic connection fails. + GitLab Pages can use an API-based configuration. This replaces disk source configuration, which was used prior to GitLab 13.0. Follow these steps to enable it: @@ -937,6 +962,11 @@ error="failed to connect to internal Pages API: Get \"https://gitlab.example.com ### Pages cannot communicate with an instance of the GitLab API +WARNING: +The flag `gitlab_pages['domain_config_source']` is [deprecated](#deprecated-domain_config_source) +for use in [GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/issues/217913), +and is planned for removal in GitLab 14.0. + If you use the default value for `domain_config_source=auto` and run multiple instances of GitLab Pages, you may see intermittent 502 error responses while serving Pages content. You may also see the following warning in the Pages logs: diff --git a/doc/api/commits.md b/doc/api/commits.md index a0f313d443c..f4896f75c93 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -7,6 +7,8 @@ type: reference, api # Commits API **(FREE)** +This API operates on [repository commits](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository). Read more about [GitLab-specific information](../user/project/repository/index.md#commits) for commits. + ## List repository commits Get a list of repository commits in a project. diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md index 2eaf18febff..0945471b11b 100644 --- a/doc/user/admin_area/settings/sign_up_restrictions.md +++ b/doc/user/admin_area/settings/sign_up_restrictions.md @@ -53,9 +53,7 @@ To enforce confirmation of the email address used for new sign ups: ## User cap **(FREE SELF)** > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4315) in GitLab 13.7. -> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default. -> - It's recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-user-cap). **(FREE SELF)** +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292600) in GitLab 13.9. When the number of billable users reaches the user cap, any user who is added or requests access must be [approved](../approving_users.md#approving-a-user) by an administrator before they can start using @@ -64,25 +62,6 @@ their account. If an administrator increases or removes the user cap, the users in pending approval state are automatically approved in a background job. -### Enable or disable User cap **(FREE SELF)** - -User cap is under development but ready for production use. -It is deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) -can opt to disable it. - -To disable it: - -```ruby -Feature.disable(:admin_new_user_signups_cap) -``` - -To enable it: - -```ruby -Feature.enable(:admin_new_user_signups_cap) -``` - ## Soft email confirmation > - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47003) in GitLab 12.2. diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index 68e72664280..a9ad2c611bb 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -9,6 +9,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4. +WARNING: +GitLab 14.0 will replace its container scanning engine with Trivy. Currently, GitLab uses the open +source Clair engine for container scanning. GitLab 13.9 deprecates Clair. This is not a hard +breaking change, as customers who wish to continue to use Clair can do so by setting the +`CS_MAJOR_VERSION` variable to version 3 (or earlier) in their `gitlab-ci.yaml` file. Since Clair is +deprecated, however, note that GitLab will no longer update or maintain that scanning engine +beginning in the 14.0 release. We advise customers to use the new default of Trivy beginning in +GitLab 14.0 for regular updates and the latest features. + Your application's Docker image may itself be based on Docker images that contain known vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and displays them in a merge request, you can use GitLab to audit your Docker-based apps. diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md index a60af93a899..7507792bb02 100644 --- a/doc/user/project/integrations/services_templates.md +++ b/doc/user/project/integrations/services_templates.md @@ -6,6 +6,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Service templates +WARNING: +Service templates are [deprecated and scheduled to be removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268032) +in GitLab 14.0. Use [project integration management](#central-administration-of-project-integrations) instead. + Using a service template, GitLab administrators can: - Provide default values for configuring integrations when creating new projects. diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md index 4fa7bef4fb2..5c95665230a 100644 --- a/doc/user/project/issues/csv_export.md +++ b/doc/user/project/issues/csv_export.md @@ -6,8 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Export Issues to CSV -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1126) in [GitLab Starter 9.0](https://about.gitlab.com/releases/2017/03/22/gitlab-9-0-released/#export-issues-ees-eep). -> - Moved to GitLab Free in GitLab 12.10. +> Moved to GitLab Free in 12.10. Issues can be exported as CSV from GitLab and are sent to your default notification email as an attachment. @@ -49,10 +48,6 @@ Exported issues are always sorted by `Issue ID`. ## Format -> **Time Estimate** and **Time Spent** columns were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2627) in GitLab Starter 10.0. -> -> **Weight** and **Locked** columns were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5300) in GitLab Starter 10.8. - Data is encoded with a comma as the column delimiter, with `"` used to quote fields if needed, and newlines to separate rows. The first row contains the headers, which are listed in the following table along with a description of the values: | Column | Description | diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index fb0613187c5..07e64889b93 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -17,6 +17,8 @@ RSpec.describe Clusters::Platforms::Kubernetes do it { is_expected.to delegate_method(:enabled?).to(:cluster) } it { is_expected.to delegate_method(:provided_by_user?).to(:cluster) } + it { is_expected.to nullify_if_blank(:namespace) } + it_behaves_like 'having unique enum values' describe 'before_validation' do @@ -29,14 +31,6 @@ RSpec.describe Clusters::Platforms::Kubernetes do expect(kubernetes.namespace).to eq('abc') end end - - context 'when namespace is blank' do - let(:namespace) { '' } - - it 'nullifies the namespace' do - expect(kubernetes.namespace).to be_nil - end - end end describe 'validation' do diff --git a/spec/models/concerns/nullify_if_blank_spec.rb b/spec/models/concerns/nullify_if_blank_spec.rb new file mode 100644 index 00000000000..2d1bdba39dd --- /dev/null +++ b/spec/models/concerns/nullify_if_blank_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NullifyIfBlank do + let_it_be(:model) do + Class.new(ApplicationRecord) do + include NullifyIfBlank + + nullify_if_blank :name + + self.table_name = 'users' + end + end + + context 'attribute exists' do + let(:instance) { model.new(name: name) } + + subject { instance.name } + + before do + instance.validate + end + + context 'attribute is blank' do + let(:name) { '' } + + it { is_expected.to be_nil } + end + + context 'attribute is nil' do + let(:name) { nil } + + it { is_expected.to be_nil} + end + + context 'attribute is not blank' do + let(:name) { 'name' } + + it { is_expected.to eq('name') } + end + end + + context 'attribute does not exist' do + before do + model.table_name = 'issues' + end + + it { expect { model.new.valid? }.to raise_error(ActiveModel::UnknownAttributeError) } + end +end diff --git a/spec/support/matchers/nullify_if_blank_matcher.rb b/spec/support/matchers/nullify_if_blank_matcher.rb new file mode 100644 index 00000000000..8f6737499cc --- /dev/null +++ b/spec/support/matchers/nullify_if_blank_matcher.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +RSpec::Matchers.define :nullify_if_blank do |attribute| + match do |record| + expect(record.class.attributes_to_nullify).to include(attribute) + end + + failure_message do |record| + "expected nullify_if_blank configuration on #{record.class} to include #{attribute}" + end +end |