Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
fee1014807
commit
65be6f9dd4
21 changed files with 259 additions and 74 deletions
2
Gemfile
2
Gemfile
|
@ -488,7 +488,7 @@ gem 'flipper', '~> 0.17.1'
|
|||
gem 'flipper-active_record', '~> 0.17.1'
|
||||
gem 'flipper-active_support_cache_store', '~> 0.17.1'
|
||||
gem 'unleash', '~> 0.1.5'
|
||||
gem 'gitlab-experiment', '~> 0.5.1'
|
||||
gem 'gitlab-experiment', '~> 0.5.2'
|
||||
|
||||
# Structured logging
|
||||
gem 'lograge', '~> 0.5'
|
||||
|
|
|
@ -443,7 +443,7 @@ GEM
|
|||
numerizer (~> 0.2)
|
||||
gitlab-dangerfiles (1.1.0)
|
||||
danger-gitlab
|
||||
gitlab-experiment (0.5.1)
|
||||
gitlab-experiment (0.5.2)
|
||||
activesupport (>= 3.0)
|
||||
scientist (~> 1.6, >= 1.6.0)
|
||||
gitlab-fog-azure-rm (1.0.1)
|
||||
|
@ -1424,7 +1424,7 @@ DEPENDENCIES
|
|||
github-markup (~> 1.7.0)
|
||||
gitlab-chronic (~> 0.10.5)
|
||||
gitlab-dangerfiles (~> 1.1.0)
|
||||
gitlab-experiment (~> 0.5.1)
|
||||
gitlab-experiment (~> 0.5.2)
|
||||
gitlab-fog-azure-rm (~> 1.0.1)
|
||||
gitlab-fog-google (~> 1.13)
|
||||
gitlab-labkit (~> 0.16.2)
|
||||
|
|
|
@ -110,6 +110,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
@show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs
|
||||
@file_by_file_default = current_user&.view_diffs_file_by_file
|
||||
@coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports?
|
||||
@update_current_user_path = expose_path(api_v4_user_preferences_path)
|
||||
@endpoint_metadata_url = endpoint_metadata_url(@project, @merge_request)
|
||||
|
||||
set_pipeline_variables
|
||||
|
|
20
app/services/user_preferences/update_service.rb
Normal file
20
app/services/user_preferences/update_service.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module UserPreferences
|
||||
class UpdateService < BaseService
|
||||
def initialize(user, params = {})
|
||||
@preferences = user.user_preference
|
||||
@params = params.to_h.dup.with_indifferent_access
|
||||
end
|
||||
|
||||
def execute
|
||||
if @preferences.update(@params)
|
||||
ServiceResponse.success(
|
||||
message: 'Preference was updated',
|
||||
payload: { preferences: @preferences })
|
||||
else
|
||||
ServiceResponse.error(message: 'Could not update preference')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -88,6 +88,7 @@
|
|||
endpoint_coverage: @coverage_path,
|
||||
help_page_path: suggest_changes_help_path,
|
||||
current_user_data: @current_user_data,
|
||||
update_current_user_path: @update_current_user_path,
|
||||
project_path: project_path(@merge_request.project),
|
||||
changes_empty_state_illustration: image_path('illustrations/merge_request_changes_empty.svg'),
|
||||
is_fluid_layout: fluid_layout.to_s,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Create UserPreferences API
|
||||
merge_request: 55033
|
||||
author:
|
||||
type: added
|
|
@ -677,6 +677,28 @@ Example response:
|
|||
}
|
||||
```
|
||||
|
||||
## User preference modification
|
||||
|
||||
Update the current user's preferences.
|
||||
|
||||
```plaintext
|
||||
PUT /user/preferences
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"user_id": 1
|
||||
"view_diffs_file_by_file": true
|
||||
}
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Required | Description |
|
||||
| :--------------------------- | :------- | :---------------------------------------------------------- |
|
||||
| `view_diffs_file_by_file` | Yes | Flag indicating the user sees only one file diff per page. |
|
||||
|
||||
## Set user status
|
||||
|
||||
Set the status of the current user.
|
||||
|
|
|
@ -22,40 +22,50 @@ of the configured mechanisms.
|
|||
|
||||
## Supported Providers
|
||||
|
||||
This is a list of the current supported OmniAuth providers. Before proceeding
|
||||
on each provider's documentation, make sure to first read this document as it
|
||||
contains some settings that are common for all providers.
|
||||
This is a list of the current supported OmniAuth providers. Before proceeding on each provider's documentation,
|
||||
make sure to first read this document as it contains some settings that are common for all providers.
|
||||
|
||||
- [GitHub](github.md)
|
||||
- [Bitbucket](bitbucket.md)
|
||||
- [GitLab.com](gitlab.md)
|
||||
- [Google](google.md)
|
||||
- [Facebook](facebook.md)
|
||||
- [Twitter](twitter.md)
|
||||
- [Shibboleth](shibboleth.md)
|
||||
- [SAML](saml.md)
|
||||
- [Crowd](../administration/auth/crowd.md)
|
||||
- [Azure](azure.md)
|
||||
- [Auth0](auth0.md)
|
||||
- [Authentiq](../administration/auth/authentiq.md)
|
||||
- [OAuth2Generic](oauth2_generic.md)
|
||||
- [JWT](../administration/auth/jwt.md)
|
||||
- [OpenID Connect](../administration/auth/oidc.md)
|
||||
- [Salesforce](salesforce.md)
|
||||
- [AWS Cognito](../administration/auth/cognito.md)
|
||||
|Provider documentation |OmniAuth provider name |
|
||||
|-----------------------------------------------------------------|--------------------------|
|
||||
|[Atlassian Crowd](../administration/auth/crowd.md) |`crowd` |
|
||||
|[Atlassian](../administration/auth/atlassian.md) |`atlassian_oauth2` |
|
||||
|[Auth0](auth0.md) |`auth0` |
|
||||
|[Authentiq](../administration/auth/authentiq.md) |`authentiq` |
|
||||
|[AWS Cognito](../administration/auth/cognito.md) |`cognito` |
|
||||
|[Azure v2](azure.md#microsoft-azure-oauth2-omniauth-provider-v2) |`azure_activedirectory_v2`|
|
||||
|[Azure v1](azure.md) |`azure_oauth2` |
|
||||
|[Bitbucket Cloud](bitbucket.md) |`bitbucket` |
|
||||
|[CAS](cas.md) |`cas3` |
|
||||
|[Facebook](facebook.md) |`facebook` |
|
||||
|[Generic OAuth2](oauth2_generic.md) |`oauth2_generic` |
|
||||
|[GitHub](github.md) |`github` |
|
||||
|[GitLab.com](gitlab.md) |`gitlab` |
|
||||
|[Google](google.md) |`google_oauth2` |
|
||||
|[JWT](../administration/auth/jwt.md) |`jwt` |
|
||||
|[Kerberos](kerberos.md) |`kerberos` |
|
||||
|[OpenID Connect](../administration/auth/oidc.md) |`openid_connect` |
|
||||
|[Salesforce](salesforce.md) |`salesforce` |
|
||||
|[SAML](saml.md) |`saml` |
|
||||
|[Shibboleth](shibboleth.md) |`shibboleth` |
|
||||
|[Twitter](twitter.md) |`twitter` |
|
||||
|
||||
## Initial OmniAuth Configuration
|
||||
|
||||
Before configuring individual OmniAuth providers there are a few global settings
|
||||
that are in common for all providers that we need to consider.
|
||||
The OmniAuth provider names from the table above are needed to configure a few global settings that are in common for all providers.
|
||||
|
||||
NOTE:
|
||||
Starting from GitLab 11.4, OmniAuth is enabled by default. If you're using an
|
||||
earlier version, you must explicitly enable it.
|
||||
|
||||
- `allow_single_sign_on` allows you to specify the providers you want to allow to
|
||||
automatically create an account. It defaults to `false`. If `false` users must
|
||||
be created manually or they can't sign in by using OmniAuth.
|
||||
- `allow_single_sign_on` allows you to specify the providers that automatically
|
||||
create a GitLab account. For example, if you wish to enable Azure (v2) and Google,
|
||||
in Omnibus, specify a list of provider names:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['omniauth_allow_single_sign_on'] = ['azure_activedirectory_v2', 'google_oauth2']
|
||||
```
|
||||
|
||||
The value defaults to `false`. If `false` users must be created manually, or they can't sign in by using OmniAuth.
|
||||
- `auto_link_ldap_user` can be used if you have [LDAP / ActiveDirectory](../administration/auth/ldap/index.md)
|
||||
integration enabled. It defaults to `false`. When enabled, users automatically
|
||||
created through an OmniAuth provider have their LDAP identity created in GitLab as well.
|
||||
|
@ -325,20 +335,20 @@ You can add the `auto_sign_in_with_provider` setting to your GitLab
|
|||
configuration to redirect login requests to your OmniAuth provider for
|
||||
authentication. This removes the need to click a button before actually signing in.
|
||||
|
||||
For example, when using the Azure integration, set the following to enable auto
|
||||
For example, when using the [Azure v2 integration](azure.md#microsoft-azure-oauth2-omniauth-provider-v2), set the following to enable auto
|
||||
sign-in:
|
||||
|
||||
For Omnibus package:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'azure_oauth2'
|
||||
gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'azure_activedirectory_v2'
|
||||
```
|
||||
|
||||
For installations from source:
|
||||
|
||||
```yaml
|
||||
omniauth:
|
||||
auto_sign_in_with_provider: azure_oauth2
|
||||
auto_sign_in_with_provider: azure_activedirectory_v2
|
||||
```
|
||||
|
||||
Keep in mind that every sign-in attempt is redirected to the OmniAuth
|
||||
|
|
9
lib/api/entities/user_preferences.rb
Normal file
9
lib/api/entities/user_preferences.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Entities
|
||||
class UserPreferences < Grape::Entity
|
||||
expose :id, :user_id, :view_diffs_file_by_file
|
||||
end
|
||||
end
|
||||
end
|
|
@ -996,6 +996,29 @@ module API
|
|||
present paginate(current_user.emails), with: Entities::Email
|
||||
end
|
||||
|
||||
desc "Update the current user's preferences" do
|
||||
success Entities::UserPreferences
|
||||
detail 'This feature was introduced in GitLab 13.10.'
|
||||
end
|
||||
params do
|
||||
requires :view_diffs_file_by_file, type: Boolean, desc: 'Flag indicating the user sees only one file diff per page'
|
||||
end
|
||||
put "preferences", feature_category: :users do
|
||||
authenticate!
|
||||
|
||||
preferences = current_user.user_preference
|
||||
|
||||
attrs = declared_params(include_missing: false)
|
||||
|
||||
service = ::UserPreferences::UpdateService.new(current_user, attrs).execute
|
||||
|
||||
if service.success?
|
||||
present preferences, with: Entities::UserPreferences
|
||||
else
|
||||
render_api_error!('400 Bad Request', 400)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Get a single email address owned by the currently authenticated user' do
|
||||
success Entities::Email
|
||||
end
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "1.185.0",
|
||||
"@gitlab/tributejs": "1.0.0",
|
||||
"@gitlab/ui": "28.15.0",
|
||||
"@gitlab/ui": "28.18.2",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "^6.0.3-4",
|
||||
"@rails/ujs": "^6.0.3-4",
|
||||
|
|
|
@ -74,8 +74,9 @@ RSpec.describe Projects::IssuesController do
|
|||
end
|
||||
|
||||
it 'assigns the candidate experience and tracks the event' do
|
||||
expect(experiment(:null_hypothesis)).to track('index').on_any_instance.for(:candidate)
|
||||
expect(experiment(:null_hypothesis)).to track('index').for(:candidate)
|
||||
.with_context(project: project)
|
||||
.on_next_instance
|
||||
|
||||
get :index, params: { namespace_id: project.namespace, project_id: project }
|
||||
end
|
||||
|
@ -218,10 +219,10 @@ RSpec.describe Projects::IssuesController do
|
|||
end
|
||||
|
||||
it 'assigns the candidate experience and tracks the event' do
|
||||
expect(experiment(:invite_member_link)).to track(:view, property: project.root_ancestor.id.to_s)
|
||||
.on_any_instance
|
||||
.for(:invite_member_link)
|
||||
.with_context(namespace: project.root_ancestor)
|
||||
expect(experiment(:invite_members_in_comment)).to track(:view, property: project.root_ancestor.id.to_s)
|
||||
.for(:invite_member_link)
|
||||
.with_context(namespace: project.root_ancestor)
|
||||
.on_next_instance
|
||||
|
||||
get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
|
||||
end
|
||||
|
@ -229,7 +230,7 @@ RSpec.describe Projects::IssuesController do
|
|||
|
||||
context 'when user can not invite' do
|
||||
it 'does not track the event' do
|
||||
expect(experiment(:invite_member_link)).not_to track(:view)
|
||||
expect(experiment(:invite_members_in_comment)).not_to track(:view)
|
||||
|
||||
get :show, params: { namespace_id: project.namespace, project_id: project, id: issue.iid }
|
||||
end
|
||||
|
|
|
@ -48,10 +48,10 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
end
|
||||
|
||||
it 'assigns the candidate experience and tracks the event' do
|
||||
expect(experiment(:invite_member_link)).to track(:view, property: project.root_ancestor.id.to_s)
|
||||
.on_any_instance
|
||||
.for(:invite_member_link)
|
||||
.with_context(namespace: project.root_ancestor)
|
||||
expect(experiment(:invite_members_in_comment)).to track(:view, property: project.root_ancestor.id.to_s)
|
||||
.for(:invite_member_link)
|
||||
.with_context(namespace: project.root_ancestor)
|
||||
.on_next_instance
|
||||
|
||||
go
|
||||
end
|
||||
|
@ -59,7 +59,7 @@ RSpec.describe Projects::MergeRequestsController do
|
|||
|
||||
context 'when user can not invite' do
|
||||
it 'does not track the event' do
|
||||
expect(experiment(:invite_member_link)).not_to track(:view)
|
||||
expect(experiment(:invite_members_in_comment)).not_to track(:view)
|
||||
|
||||
go
|
||||
end
|
||||
|
|
|
@ -221,22 +221,16 @@ RSpec.describe ProjectsController do
|
|||
allow(controller).to receive(:record_experiment_user)
|
||||
end
|
||||
|
||||
context 'when user can push to default branch' do
|
||||
context 'when user can push to default branch', :experiment do
|
||||
let(:user) { empty_project.owner }
|
||||
|
||||
it 'creates an "view_project_show" experiment tracking event', :snowplow do
|
||||
allow_next_instance_of(ApplicationExperiment) do |e|
|
||||
allow(e).to receive(:should_track?).and_return(true)
|
||||
end
|
||||
it 'creates an "view_project_show" experiment tracking event' do
|
||||
expect(experiment(:empty_repo_upload)).to track(
|
||||
:view_project_show,
|
||||
property: 'empty'
|
||||
).on_next_instance
|
||||
|
||||
get :show, params: { namespace_id: empty_project.namespace, id: empty_project }
|
||||
|
||||
expect_snowplow_event(
|
||||
category: 'empty_repo_upload',
|
||||
action: 'view_project_show',
|
||||
property: 'empty',
|
||||
context: [{ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/1-0-0', data: anything }]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -449,7 +443,7 @@ RSpec.describe ProjectsController do
|
|||
:created,
|
||||
property: 'blank',
|
||||
value: 1
|
||||
).on_any_instance.with_context(actor: user)
|
||||
).with_context(actor: user).on_next_instance
|
||||
|
||||
post :create, params: { project: project_params }
|
||||
end
|
||||
|
|
|
@ -7,10 +7,6 @@ RSpec.describe NewProjectReadmeExperiment, :experiment do
|
|||
|
||||
let(:actor) { User.new(id: 42, created_at: Time.current) }
|
||||
|
||||
before do
|
||||
stub_experiments(new_project_readme: :control)
|
||||
end
|
||||
|
||||
describe "exclusions" do
|
||||
let(:threshold) { described_class::MAX_ACCOUNT_AGE }
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { GlAlert, GlButton } from '@gitlab/ui';
|
||||
import { GlAlert } from '@gitlab/ui';
|
||||
import { fireEvent, within } from '@testing-library/dom';
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import LinksInner from '~/pipelines/components/graph_shared/links_inner.vue';
|
||||
import LinksLayer from '~/pipelines/components/graph_shared/links_layer.vue';
|
||||
|
@ -7,8 +8,10 @@ import { generateResponse, mockPipelineResponse } from '../graph/mock_data';
|
|||
describe('links layer component', () => {
|
||||
let wrapper;
|
||||
|
||||
const withinComponent = () => within(wrapper.element);
|
||||
const findAlert = () => wrapper.find(GlAlert);
|
||||
const findShowAnyways = () => findAlert().find(GlButton);
|
||||
const findShowAnyways = () =>
|
||||
withinComponent().getByText(wrapper.vm.$options.i18n.showLinksAnyways);
|
||||
const findLinksInner = () => wrapper.find(LinksInner);
|
||||
|
||||
const pipeline = generateResponse(mockPipelineResponse, 'root/fungi-xoxo');
|
||||
|
@ -103,13 +106,13 @@ describe('links layer component', () => {
|
|||
});
|
||||
|
||||
it('renders the disable button', () => {
|
||||
expect(findShowAnyways().exists()).toBe(true);
|
||||
expect(findShowAnyways().text()).toBe(wrapper.vm.$options.i18n.showLinksAnyways);
|
||||
expect(findShowAnyways()).not.toBe(null);
|
||||
});
|
||||
|
||||
it('shows links when override is clicked', async () => {
|
||||
expect(findLinksInner().exists()).toBe(false);
|
||||
await findShowAnyways().trigger('click');
|
||||
fireEvent(findShowAnyways(), new MouseEvent('click', { bubbles: true }));
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(findLinksInner().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -42,15 +42,17 @@ describe('VueAlerts', () => {
|
|||
|
||||
const findJsHooks = () => document.querySelectorAll('.js-vue-alert');
|
||||
const findAlerts = () => document.querySelectorAll('.gl-alert');
|
||||
const findAlertDismiss = (alert) => alert.querySelector('.gl-alert-dismiss');
|
||||
const findAlertDismiss = (alert) => alert.querySelector('.gl-dismiss-btn');
|
||||
|
||||
const serializeAlert = (alert) => ({
|
||||
title: alert.querySelector('.gl-alert-title').textContent.trim(),
|
||||
html: alert.querySelector('.gl-alert-body div').innerHTML,
|
||||
dismissible: Boolean(alert.querySelector('.gl-alert-dismiss')),
|
||||
dismissible: Boolean(alert.querySelector('.gl-dismiss-btn')),
|
||||
primaryButtonText: alert.querySelector('.gl-alert-action').textContent.trim(),
|
||||
primaryButtonLink: alert.querySelector('.gl-alert-action').href,
|
||||
variant: [...alert.classList].find((x) => x.match('gl-alert-')).replace('gl-alert-', ''),
|
||||
variant: [...alert.classList]
|
||||
.find((x) => x.match(/gl-alert-(?!not-dismissible)/))
|
||||
.replace('gl-alert-', ''),
|
||||
});
|
||||
|
||||
it('starts with only JsHooks', () => {
|
||||
|
|
|
@ -799,14 +799,14 @@ RSpec.describe Notify do
|
|||
is_expected.to have_link('Join now', href: invite_url(project_member.invite_token, invite_type: Members::InviteEmailExperiment::INVITE_TYPE))
|
||||
end
|
||||
|
||||
it 'contains invite link for the avatar', :experiment do
|
||||
it 'contains invite link for the avatar' do
|
||||
stub_experiments('members/invite_email': :avatar)
|
||||
|
||||
is_expected.not_to have_content('You are invited!')
|
||||
is_expected.not_to have_body_text 'What is a GitLab'
|
||||
end
|
||||
|
||||
it 'contains invite link for the avatar', :experiment do
|
||||
it 'contains invite link for the avatar' do
|
||||
stub_experiments('members/invite_email': :permission_info)
|
||||
|
||||
is_expected.not_to have_content('You are invited!')
|
||||
|
|
65
spec/requests/api/users_preferences_spec.rb
Normal file
65
spec/requests/api/users_preferences_spec.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe API::Users do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
describe 'PUT /user/preferences/' do
|
||||
context "with correct attributes and a logged in user" do
|
||||
it 'returns a success status and the value has been changed' do
|
||||
put api("/user/preferences", user), params: { view_diffs_file_by_file: true }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response['view_diffs_file_by_file']).to eq(true)
|
||||
expect(user.reload.view_diffs_file_by_file).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context "missing a preference" do
|
||||
it 'returns a bad request status' do
|
||||
put api("/user/preferences", user), params: {}
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
|
||||
context "without a logged in user" do
|
||||
it 'returns an unauthorized status' do
|
||||
put api("/user/preferences"), params: { view_diffs_file_by_file: true }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
context "with an unsupported preference" do
|
||||
it 'returns a bad parameter' do
|
||||
put api("/user/preferences", user), params: { jawn: true }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
|
||||
context "with an unsupported value" do
|
||||
it 'returns a bad parameter' do
|
||||
put api("/user/preferences", user), params: { view_diffs_file_by_file: 3 }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
|
||||
context "with an update service failure" do
|
||||
it 'returns a bad request' do
|
||||
bad_service = double("Failed Service", success?: false)
|
||||
|
||||
allow_next_instance_of(::UserPreferences::UpdateService) do |instance|
|
||||
allow(instance).to receive(:execute).and_return(bad_service)
|
||||
end
|
||||
|
||||
put api("/user/preferences", user), params: { view_diffs_file_by_file: true }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
33
spec/services/user_preferences/update_service_spec.rb
Normal file
33
spec/services/user_preferences/update_service_spec.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe UserPreferences::UpdateService do
|
||||
let(:user) { create(:user) }
|
||||
let(:params) { { view_diffs_file_by_file: false } }
|
||||
|
||||
describe '#execute' do
|
||||
subject(:service) { described_class.new(user, params) }
|
||||
|
||||
context 'successfully updating the record' do
|
||||
it 'updates the preference and returns a success' do
|
||||
result = service.execute
|
||||
|
||||
expect(result.status).to eq(:success)
|
||||
expect(result.payload[:preferences].view_diffs_file_by_file).to eq(params[:view_diffs_file_by_file])
|
||||
end
|
||||
end
|
||||
|
||||
context 'unsuccessfully updating the record' do
|
||||
before do
|
||||
allow(user.user_preference).to receive(:update).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns an error' do
|
||||
result = service.execute
|
||||
|
||||
expect(result.status).to eq(:error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -907,10 +907,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
||||
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
||||
|
||||
"@gitlab/ui@28.15.0":
|
||||
version "28.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.15.0.tgz#e78a1c0724c7cc8880fcff8161e529ca7bcaf6e8"
|
||||
integrity sha512-muz1tX3nQmu9dMv7GbTNIkWkEwYhvnLPhtwtnrt8eyRGQ0zIUWLEzdoSiwvMNLAqT2JB8kxahoavR5iSFAYtXA==
|
||||
"@gitlab/ui@28.18.2":
|
||||
version "28.18.2"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.18.2.tgz#b840a44d4f3094e838d2f7409ca8b578064e2a6f"
|
||||
integrity sha512-KRd/gtZj0885C0cGZiEK4jV5Cdlss62z4d0ii/p45Q6KjwmAC9au946a8pgbtBMCvDmybGxvsMmH4U2MmjNDvQ==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
"@gitlab/vue-toasted" "^1.3.0"
|
||||
|
|
Loading…
Reference in a new issue