Commit 655f8035 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch...

Merge branch '322841-move-dependency-proxy-enable-under-settings-packages-registries-2' into 'master'

Finalise move of dependency proxy enable settings

See merge request gitlab-org/gitlab!71988
parents a49be57c 18a7ce38
...@@ -19,6 +19,7 @@ export default () => { ...@@ -19,6 +19,7 @@ export default () => {
apolloProvider, apolloProvider,
provide: { provide: {
defaultExpanded: parseBoolean(el.dataset.defaultExpanded), defaultExpanded: parseBoolean(el.dataset.defaultExpanded),
dependencyProxyAvailable: parseBoolean(el.dataset.dependencyProxyAvailable),
groupPath: el.dataset.groupPath, groupPath: el.dataset.groupPath,
}, },
render(createElement) { render(createElement) {
......
<script>
import { GlToggle, GlSprintf, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import updateDependencyProxySettings from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_settings.mutation.graphql';
import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update';
import { updateGroupDependencyProxySettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
import {
DEPENDENCY_PROXY_HEADER,
DEPENDENCY_PROXY_SETTINGS_DESCRIPTION,
DEPENDENCY_PROXY_DOCS_PATH,
} from '~/packages_and_registries/settings/group/constants';
export default {
name: 'DependencyProxySettings',
components: {
GlToggle,
GlSprintf,
GlLink,
SettingsBlock,
},
i18n: {
DEPENDENCY_PROXY_HEADER,
DEPENDENCY_PROXY_SETTINGS_DESCRIPTION,
label: s__('DependencyProxy|Enable Proxy'),
},
links: {
DEPENDENCY_PROXY_DOCS_PATH,
},
inject: ['defaultExpanded', 'groupPath'],
props: {
dependencyProxySettings: {
type: Object,
required: true,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
enabled: {
get() {
return this.dependencyProxySettings.enabled;
},
set(enabled) {
this.updateSettings({ enabled });
},
},
},
methods: {
async updateSettings(payload) {
try {
const { data } = await this.$apollo.mutate({
mutation: updateDependencyProxySettings,
variables: {
input: {
groupPath: this.groupPath,
...payload,
},
},
update: updateGroupPackageSettings(this.groupPath),
optimisticResponse: updateGroupDependencyProxySettingsOptimisticResponse({
...this.dependencyProxySettings,
...payload,
}),
});
if (data.updateDependencyProxySettings?.errors?.length > 0) {
throw new Error();
} else {
this.$emit('success');
}
} catch {
this.$emit('error');
}
},
},
};
</script>
<template>
<settings-block
:default-expanded="defaultExpanded"
data-qa-selector="dependency_proxy_settings_content"
>
<template #title> {{ $options.i18n.DEPENDENCY_PROXY_HEADER }} </template>
<template #description>
<span data-testid="description">
<gl-sprintf :message="$options.i18n.DEPENDENCY_PROXY_SETTINGS_DESCRIPTION">
<template #docLink="{ content }">
<gl-link :href="$options.links.DEPENDENCY_PROXY_DOCS_PATH">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
</template>
<template #default>
<div>
<gl-toggle
v-model="enabled"
:disabled="isLoading"
:label="$options.i18n.label"
data-qa-selector="dependency_proxy_setting_toggle"
/>
</div>
</template>
</settings-block>
</template>
...@@ -86,6 +86,7 @@ export default { ...@@ -86,6 +86,7 @@ export default {
:label="$options.i18n.DUPLICATES_TOGGLE_LABEL" :label="$options.i18n.DUPLICATES_TOGGLE_LABEL"
label-position="hidden" label-position="hidden"
:value="duplicatesAllowed" :value="duplicatesAllowed"
:disabled="loading"
@change="update(modelNames.allowed, $event)" @change="update(modelNames.allowed, $event)"
/> />
<div class="gl-ml-5"> <div class="gl-ml-5">
...@@ -108,6 +109,7 @@ export default { ...@@ -108,6 +109,7 @@ export default {
> >
<gl-form-input <gl-form-input
id="maven-duplicated-settings-regex-input" id="maven-duplicated-settings-regex-input"
:disabled="loading"
:value="duplicateExceptionRegex" :value="duplicateExceptionRegex"
@change="update(modelNames.exception, $event)" @change="update(modelNames.exception, $event)"
/> />
......
<script> <script>
import { GlAlert } from '@gitlab/ui'; import { GlAlert } from '@gitlab/ui';
import { import { n__ } from '~/locale';
ERROR_UPDATING_SETTINGS,
SUCCESS_UPDATING_SETTINGS,
} from '~/packages_and_registries/settings/group/constants';
import PackagesSettings from '~/packages_and_registries/settings/group/components/packages_settings.vue'; import PackagesSettings from '~/packages_and_registries/settings/group/components/packages_settings.vue';
import DependencyProxySettings from '~/packages_and_registries/settings/group/components/dependency_proxy_settings.vue';
import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql'; import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
...@@ -13,8 +11,9 @@ export default { ...@@ -13,8 +11,9 @@ export default {
components: { components: {
GlAlert, GlAlert,
PackagesSettings, PackagesSettings,
DependencyProxySettings,
}, },
inject: ['groupPath'], inject: ['groupPath', 'dependencyProxyAvailable'],
apollo: { apollo: {
group: { group: {
query: getGroupPackagesSettingsQuery, query: getGroupPackagesSettingsQuery,
...@@ -35,6 +34,9 @@ export default { ...@@ -35,6 +34,9 @@ export default {
packageSettings() { packageSettings() {
return this.group?.packageSettings || {}; return this.group?.packageSettings || {};
}, },
dependencyProxySettings() {
return this.group?.dependencyProxySetting || {};
},
isLoading() { isLoading() {
return this.$apollo.queries.group.loading; return this.$apollo.queries.group.loading;
}, },
...@@ -43,12 +45,22 @@ export default { ...@@ -43,12 +45,22 @@ export default {
dismissAlert() { dismissAlert() {
this.alertMessage = null; this.alertMessage = null;
}, },
handleSuccess() { handleSuccess(amount = 1) {
this.$toast.show(SUCCESS_UPDATING_SETTINGS); const successMessage = n__(
'Setting saved successfully',
'Settings saved successfully',
amount,
);
this.$toast.show(successMessage);
this.dismissAlert(); this.dismissAlert();
}, },
handleError() { handleError(amount = 1) {
this.alertMessage = ERROR_UPDATING_SETTINGS; const errorMessage = n__(
'An error occurred while saving the setting',
'An error occurred while saving the settings',
amount,
);
this.alertMessage = errorMessage;
}, },
}, },
}; };
...@@ -63,6 +75,14 @@ export default { ...@@ -63,6 +75,14 @@ export default {
<packages-settings <packages-settings
:package-settings="packageSettings" :package-settings="packageSettings"
:is-loading="isLoading" :is-loading="isLoading"
@success="handleSuccess(2)"
@error="handleError(2)"
/>
<dependency-proxy-settings
v-if="dependencyProxyAvailable"
:dependency-proxy-settings="dependencyProxySettings"
:is-loading="isLoading"
@success="handleSuccess" @success="handleSuccess"
@error="handleError" @error="handleError"
/> />
......
...@@ -18,11 +18,6 @@ export const DUPLICATES_SETTINGS_EXCEPTION_LEGEND = s__( ...@@ -18,11 +18,6 @@ export const DUPLICATES_SETTINGS_EXCEPTION_LEGEND = s__(
'PackageRegistry|Publish packages if their name or version matches this regex.', 'PackageRegistry|Publish packages if their name or version matches this regex.',
); );
export const SUCCESS_UPDATING_SETTINGS = s__('PackageRegistry|Settings saved successfully');
export const ERROR_UPDATING_SETTINGS = s__(
'PackageRegistry|An error occurred while saving the settings',
);
export const DEPENDENCY_PROXY_HEADER = s__('DependencyProxy|Dependency Proxy'); export const DEPENDENCY_PROXY_HEADER = s__('DependencyProxy|Dependency Proxy');
export const DEPENDENCY_PROXY_SETTINGS_DESCRIPTION = s__( export const DEPENDENCY_PROXY_SETTINGS_DESCRIPTION = s__(
'DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies.', 'DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies.',
......
mutation updateDependencyProxySettings($input: UpdateDependencyProxySettingsInput!) {
updateDependencyProxySettings(input: $input) {
dependencyProxySetting {
enabled
}
errors
}
}
query getGroupPackagesSettings($fullPath: ID!) { query getGroupPackagesSettings($fullPath: ID!) {
group(fullPath: $fullPath) { group(fullPath: $fullPath) {
dependencyProxySetting {
enabled
}
packageSettings { packageSettings {
mavenDuplicatesAllowed mavenDuplicatesAllowed
mavenDuplicateExceptionRegex mavenDuplicateExceptionRegex
......
...@@ -9,9 +9,16 @@ export const updateGroupPackageSettings = (fullPath) => (client, { data: updated ...@@ -9,9 +9,16 @@ export const updateGroupPackageSettings = (fullPath) => (client, { data: updated
const sourceData = client.readQuery(queryAndParams); const sourceData = client.readQuery(queryAndParams);
const data = produce(sourceData, (draftState) => { const data = produce(sourceData, (draftState) => {
draftState.group.packageSettings = { if (updatedData.updateNamespacePackageSettings) {
...updatedData.updateNamespacePackageSettings.packageSettings, draftState.group.packageSettings = {
}; ...updatedData.updateNamespacePackageSettings.packageSettings,
};
}
if (updatedData.updateDependencyProxySettings) {
draftState.group.dependencyProxySetting = {
...updatedData.updateDependencyProxySettings.dependencyProxySetting,
};
}
}); });
client.writeQuery({ client.writeQuery({
......
...@@ -9,3 +9,15 @@ export const updateGroupPackagesSettingsOptimisticResponse = (changes) => ({ ...@@ -9,3 +9,15 @@ export const updateGroupPackagesSettingsOptimisticResponse = (changes) => ({
}, },
}, },
}); });
export const updateGroupDependencyProxySettingsOptimisticResponse = (changes) => ({
// eslint-disable-next-line @gitlab/require-i18n-strings
__typename: 'Mutation',
updateDependencyProxySettings: {
__typename: 'UpdateDependencyProxySettingsPayload',
errors: [],
dependencyProxySetting: {
...changes,
},
},
});
...@@ -234,6 +234,10 @@ module Types ...@@ -234,6 +234,10 @@ module Types
) )
end end
def dependency_proxy_setting
group.dependency_proxy_setting || group.create_dependency_proxy_setting
end
private private
def group def group
......
...@@ -8,20 +8,9 @@ ...@@ -8,20 +8,9 @@
= _('Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } = _('Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- if Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public? - if Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
- if can?(current_user, :admin_dependency_proxy, @group) - if @dependency_proxy.enabled
= form_for(@dependency_proxy, method: :put, url: group_dependency_proxy_path(@group)) do |f| = render 'groups/dependency_proxies/url'
.form-group
%h5.prepend-top-20= _('Enable proxy')
.js-dependency-proxy-toggle-area
= render "shared/buttons/project_feature_toggle", is_checked: @dependency_proxy.enabled?, label: s_("DependencyProxy|Toggle Dependency Proxy"), data: { qa_selector: 'dependency_proxy_setting_toggle' } do
= f.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
- if @dependency_proxy.enabled
= render 'groups/dependency_proxies/url'
- else
- if @dependency_proxy.enabled
= render 'groups/dependency_proxies/url'
- else - else
.gl-alert.gl-alert-info .gl-alert.gl-alert-info
.gl-alert-container .gl-alert-container
......
- breadcrumb_title _('Packages & Registries') - breadcrumb_title _('Packages & Registries')
- page_title _('Packages & Registries') - page_title _('Packages & Registries')
- @content_class = 'limit-container-width' unless fluid_layout - @content_class = 'limit-container-width' unless fluid_layout
- dependency_proxy_available = Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s, group_path: @group.full_path } } %section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s,
group_path: @group.full_path,
dependency_proxy_available: dependency_proxy_available.to_s } }
...@@ -3827,6 +3827,11 @@ msgstr "" ...@@ -3827,6 +3827,11 @@ msgstr ""
msgid "An error occurred while saving changes: %{error}" msgid "An error occurred while saving changes: %{error}"
msgstr "" msgstr ""
msgid "An error occurred while saving the setting"
msgid_plural "An error occurred while saving the settings"
msgstr[0] ""
msgstr[1] ""
msgid "An error occurred while subscribing to notifications." msgid "An error occurred while subscribing to notifications."
msgstr "" msgstr ""
...@@ -11217,7 +11222,7 @@ msgstr "" ...@@ -11217,7 +11222,7 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy" msgid "DependencyProxy|Dependency Proxy"
msgstr "" msgstr ""
msgid "DependencyProxy|Toggle Dependency Proxy" msgid "DependencyProxy|Enable Proxy"
msgstr "" msgstr ""
msgid "Depends on %d merge request being merged" msgid "Depends on %d merge request being merged"
...@@ -12714,9 +12719,6 @@ msgstr "" ...@@ -12714,9 +12719,6 @@ msgstr ""
msgid "Enable protected paths rate limit" msgid "Enable protected paths rate limit"
msgstr "" msgstr ""
msgid "Enable proxy"
msgstr ""
msgid "Enable reCAPTCHA" msgid "Enable reCAPTCHA"
msgstr "" msgstr ""
...@@ -24230,9 +24232,6 @@ msgstr "" ...@@ -24230,9 +24232,6 @@ msgstr ""
msgid "PackageRegistry|Allow duplicates" msgid "PackageRegistry|Allow duplicates"
msgstr "" msgstr ""
msgid "PackageRegistry|An error occurred while saving the settings"
msgstr ""
msgid "PackageRegistry|App group: %{group}" msgid "PackageRegistry|App group: %{group}"
msgstr "" msgstr ""
...@@ -24464,9 +24463,6 @@ msgstr "" ...@@ -24464,9 +24463,6 @@ msgstr ""
msgid "PackageRegistry|Settings for Maven packages" msgid "PackageRegistry|Settings for Maven packages"
msgstr "" msgstr ""
msgid "PackageRegistry|Settings saved successfully"
msgstr ""
msgid "PackageRegistry|Show Composer commands" msgid "PackageRegistry|Show Composer commands"
msgstr "" msgstr ""
...@@ -31325,6 +31321,11 @@ msgstr "" ...@@ -31325,6 +31321,11 @@ msgstr ""
msgid "Setting enforced" msgid "Setting enforced"
msgstr "" msgstr ""
msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
msgid "Setting this to 0 means using the system default timeout value." msgid "Setting this to 0 means using the system default timeout value."
msgstr "" msgstr ""
......
...@@ -4,19 +4,10 @@ module QA ...@@ -4,19 +4,10 @@ module QA
module Page module Page
module Group module Group
class DependencyProxy < QA::Page::Base class DependencyProxy < QA::Page::Base
view 'app/views/groups/dependency_proxies/show.html.haml' do
element :dependency_proxy_setting_toggle
end
view 'app/views/groups/dependency_proxies/_url.html.haml' do view 'app/views/groups/dependency_proxies/_url.html.haml' do
element :dependency_proxy_count element :dependency_proxy_count
end end
def has_dependency_proxy_enabled?
toggle = find_element(:dependency_proxy_setting_toggle)
toggle[:class].include?('is-checked')
end
def has_blob_count?(blob_text) def has_blob_count?(blob_text)
has_element?(:dependency_proxy_count, text: blob_text) has_element?(:dependency_proxy_count, text: blob_text)
end end
......
...@@ -9,13 +9,15 @@ module QA ...@@ -9,13 +9,15 @@ module QA
view 'app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue' do view 'app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue' do
element :package_registry_settings_content element :package_registry_settings_content
end
view 'app/assets/javascripts/packages_and_registries/settings/group/components/packages_settings.vue' do
element :allow_duplicates_toggle element :allow_duplicates_toggle
element :allow_duplicates_label element :allow_duplicates_label
end end
view 'app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue' do
element :dependency_proxy_settings_content
element :dependency_proxy_setting_toggle
end
def set_allow_duplicates_disabled def set_allow_duplicates_disabled
expand_content :package_registry_settings_content do expand_content :package_registry_settings_content do
click_element(:allow_duplicates_toggle) if duplicates_enabled? click_element(:allow_duplicates_toggle) if duplicates_enabled?
...@@ -35,6 +37,15 @@ module QA ...@@ -35,6 +37,15 @@ module QA
def duplicates_disabled? def duplicates_disabled?
has_element?(:allow_duplicates_label, text: 'Do not allow duplicates') has_element?(:allow_duplicates_label, text: 'Do not allow duplicates')
end end
def has_dependency_proxy_enabled?
expand_content :dependency_proxy_settings_content do
within_element :dependency_proxy_setting_toggle do
toggle = find('button.gl-toggle')
toggle[:class].include?('is-checked')
end
end
end
end end
end end
end end
......
...@@ -28,9 +28,9 @@ module QA ...@@ -28,9 +28,9 @@ module QA
project.group.visit! project.group.visit!
Page::Group::Menu.perform(&:go_to_dependency_proxy) Page::Group::Menu.perform(&:go_to_package_settings)
Page::Group::DependencyProxy.perform do |index| Page::Group::Settings::PackageRegistries.perform do |index|
expect(index).to have_dependency_proxy_enabled expect(index).to have_dependency_proxy_enabled
end end
end end
......
...@@ -3,13 +3,14 @@ ...@@ -3,13 +3,14 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe 'Group Dependency Proxy' do RSpec.describe 'Group Dependency Proxy' do
let(:developer) { create(:user) } let(:owner) { create(:user) }
let(:reporter) { create(:user) } let(:reporter) { create(:user) }
let(:group) { create(:group) } let(:group) { create(:group) }
let(:path) { group_dependency_proxy_path(group) } let(:path) { group_dependency_proxy_path(group) }
let(:settings_path) { group_settings_packages_and_registries_path(group) }
before do before do
group.add_developer(developer) group.add_owner(owner)
group.add_reporter(reporter) group.add_reporter(reporter)
enable_feature enable_feature
...@@ -22,42 +23,46 @@ RSpec.describe 'Group Dependency Proxy' do ...@@ -22,42 +23,46 @@ RSpec.describe 'Group Dependency Proxy' do
visit path visit path
expect(page).not_to have_css('.js-dependency-proxy-toggle-area')
expect(page).not_to have_css('.js-dependency-proxy-url') expect(page).not_to have_css('.js-dependency-proxy-url')
end end
end end
context 'feature is available', :js do context 'feature is available', :js do
context 'when logged in as group developer' do context 'when logged in as group owner' do
before do before do
sign_in(developer) sign_in(owner)
visit path
end end
it 'sidebar menu is open' do it 'sidebar menu is open' do
visit path
sidebar = find('.nav-sidebar') sidebar = find('.nav-sidebar')
expect(sidebar).to have_link _('Dependency Proxy') expect(sidebar).to have_link _('Dependency Proxy')
end end
it 'toggles defaults to enabled' do it 'toggles defaults to enabled' do
page.within('.js-dependency-proxy-toggle-area') do visit path
expect(find('.js-project-feature-toggle-input', visible: false).value).to eq('true')
end expect(page).to have_css('.js-dependency-proxy-url')
end end
it 'shows the proxy URL' do it 'shows the proxy URL' do
page.within('.edit_dependency_proxy_group_setting') do visit path
expect(find('.js-dependency-proxy-url').value).to have_content('/dependency_proxy/containers')
end expect(find('.js-dependency-proxy-url').value).to have_content('/dependency_proxy/containers')
end end
it 'hides the proxy URL when feature is disabled' do it 'hides the proxy URL when feature is disabled' do
page.within('.edit_dependency_proxy_group_setting') do visit settings_path
find('.js-project-feature-toggle').click wait_for_requests
end
click_button 'Enable Proxy'
expect(page).to have_button 'Enable Proxy', class: '!is-checked'
visit path
expect(page).not_to have_css('.js-dependency-proxy-url') expect(page).not_to have_css('.js-dependency-proxy-url')
expect(find('.js-project-feature-toggle-input', visible: false).value).to eq('false')
end end
end end
...@@ -68,7 +73,6 @@ RSpec.describe 'Group Dependency Proxy' do ...@@ -68,7 +73,6 @@ RSpec.describe 'Group Dependency Proxy' do
end end
it 'does not show the feature toggle but shows the proxy URL' do it 'does not show the feature toggle but shows the proxy URL' do
expect(page).not_to have_css('.js-dependency-proxy-toggle-area')
expect(find('.js-dependency-proxy-url').value).to have_content('/dependency_proxy/containers') expect(find('.js-dependency-proxy-url').value).to have_content('/dependency_proxy/containers')
end end
end end
...@@ -76,7 +80,7 @@ RSpec.describe 'Group Dependency Proxy' do ...@@ -76,7 +80,7 @@ RSpec.describe 'Group Dependency Proxy' do
context 'feature is not avaible' do context 'feature is not avaible' do
before do before do
sign_in(developer) sign_in(owner)
end end
context 'feature flag is disabled' do context 'feature flag is disabled' do
......
import { GlSprintf, GlLink, GlToggle } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import component from '~/packages_and_registries/settings/group/components/dependency_proxy_settings.vue';
import {
DEPENDENCY_PROXY_HEADER,
DEPENDENCY_PROXY_SETTINGS_DESCRIPTION,
DEPENDENCY_PROXY_DOCS_PATH,
} from '~/packages_and_registries/settings/group/constants';
import updateDependencyProxySettings from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_settings.mutation.graphql';
import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
import { updateGroupDependencyProxySettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
import {
dependencyProxySettings,
dependencyProxySettingMutationMock,
groupPackageSettingsMock,
dependencyProxySettingMutationErrorMock,
} from '../mock_data';
jest.mock('~/flash');
jest.mock('~/packages_and_registries/settings/group/graphql/utils/optimistic_responses');
const localVue = createLocalVue();
describe('DependencyProxySettings', () => {
let wrapper;
let apolloProvider;
const defaultProvide = {
defaultExpanded: false,
groupPath: 'foo_group_path',
};
localVue.use(VueApollo);
const mountComponent = ({
provide = defaultProvide,
mutationResolver = jest.fn().mockResolvedValue(dependencyProxySettingMutationMock()),
isLoading = false,
} = {}) => {
const requestHandlers = [[updateDependencyProxySettings, mutationResolver]];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
localVue,
apolloProvider,
provide,
propsData: {
dependencyProxySettings: dependencyProxySettings(),
isLoading,
},
stubs: {
GlSprintf,
SettingsBlock,
},
});
};
afterEach(() => {
wrapper.destroy();
});
const findSettingsBlock = () => wrapper.findComponent(SettingsBlock);
const findDescription = () => wrapper.find('[data-testid="description"');
const findLink = () => wrapper.findComponent(GlLink);
const findToggle = () => wrapper.findComponent(GlToggle);
const fillApolloCache = () => {
apolloProvider.defaultClient.cache.writeQuery({
query: getGroupPackagesSettingsQuery,
variables: {
fullPath: defaultProvide.groupPath,
},
...groupPackageSettingsMock,
});
};
const emitSettingsUpdate = (value = false) => {
findToggle().vm.$emit('change', value);
};
it('renders a settings block', () => {
mountComponent();
expect(findSettingsBlock().exists()).toBe(true);
});
it('passes the correct props to settings block', () => {
mountComponent();
expect(findSettingsBlock().props('defaultExpanded')).toBe(false);
});
it('has the correct header text', () => {
mountComponent();
expect(wrapper.text()).toContain(DEPENDENCY_PROXY_HEADER);
});
it('has the correct description text', () => {
mountComponent();
expect(findDescription().text()).toMatchInterpolatedText(DEPENDENCY_PROXY_SETTINGS_DESCRIPTION);
});
it('has the correct link', () => {
mountComponent();
expect(findLink().attributes()).toMatchObject({
href: DEPENDENCY_PROXY_DOCS_PATH,
});
expect(findLink().text()).toBe('Learn more');
});
describe('settings update', () => {
describe('success state', () => {
it('emits a success event', async () => {
mountComponent();
fillApolloCache();
emitSettingsUpdate();
await waitForPromises();
expect(wrapper.emitted('success')).toEqual([[]]);
});
it('has an optimistic response', () => {
mountComponent();
fillApolloCache();
expect(findToggle().props('value')).toBe(true);
emitSettingsUpdate();
expect(updateGroupDependencyProxySettingsOptimisticResponse).toHaveBeenCalledWith({
enabled: false,
});
});
});
describe('errors', () => {
it('mutation payload with root level errors', async () => {
const mutationResolver = jest
.fn()
.mockResolvedValue(dependencyProxySettingMutationErrorMock);
mountComponent({ mutationResolver });
fillApolloCache();
emitSettingsUpdate();
await waitForPromises();
expect(wrapper.emitted('error')).toEqual([[]]);
});
it.each`
type | mutationResolver
${'local'} | ${jest.fn().mockResolvedValue(dependencyProxySettingMutationMock({ errors: ['foo'] }))}
${'network'} | ${jest.fn().mockRejectedValue()}
`('mutation payload with $type error', async ({ mutationResolver }) => {
mountComponent({ mutationResolver });
fillApolloCache();
emitSettingsUpdate();
await waitForPromises();
expect(wrapper.emitted('error')).toEqual([[]]);
});
});
});
describe('when isLoading is true', () => {
it('disables enable toggle', () => {
mountComponent({ isLoading: true });
expect(findToggle().props('disabled')).toBe(true);
});
});
});
...@@ -143,4 +143,18 @@ describe('Duplicates Settings', () => { ...@@ -143,4 +143,18 @@ describe('Duplicates Settings', () => {
expect(findInputGroup().exists()).toBe(false); expect(findInputGroup().exists()).toBe(false);
}); });
}); });
describe('loading', () => {
beforeEach(() => {
mountComponent({ ...defaultProps, loading: true });
});
it('disables the enable toggle', () => {
expect(findToggle().props('disabled')).toBe(true);
});
it('disables the form input', () => {
expect(findInput().attributes('disabled')).toBe('true');
});
});
}); });
...@@ -5,16 +5,12 @@ import { nextTick } from 'vue'; ...@@ -5,16 +5,12 @@ import { nextTick } from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import PackagesSettings from '~/packages_and_registries/settings/group/components/packages_settings.vue'; import PackagesSettings from '~/packages_and_registries/settings/group/components/packages_settings.vue';
import DependencyProxySettings from '~/packages_and_registries/settings/group/components/dependency_proxy_settings.vue';
import component from '~/packages_and_registries/settings/group/components/group_settings_app.vue'; import component from '~/packages_and_registries/settings/group/components/group_settings_app.vue';
import {
ERROR_UPDATING_SETTINGS,
SUCCESS_UPDATING_SETTINGS,
} from '~/packages_and_registries/settings/group/constants';
import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql'; import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
import { groupPackageSettingsMock, packageSettings } from '../mock_data'; import { groupPackageSettingsMock, packageSettings, dependencyProxySettings } from '../mock_data';
jest.mock('~/flash'); jest.mock('~/flash');
...@@ -28,10 +24,12 @@ describe('Group Settings App', () => { ...@@ -28,10 +24,12 @@ describe('Group Settings App', () => {
const defaultProvide = { const defaultProvide = {
defaultExpanded: false, defaultExpanded: false,
groupPath: 'foo_group_path', groupPath: 'foo_group_path',
dependencyProxyAvailable: true,
}; };
const mountComponent = ({ const mountComponent = ({
resolver = jest.fn().mockResolvedValue(groupPackageSettingsMock), resolver = jest.fn().mockResolvedValue(groupPackageSettingsMock),
provide = defaultProvide,
} = {}) => { } = {}) => {
localVue.use(VueApollo); localVue.use(VueApollo);
...@@ -42,7 +40,7 @@ describe('Group Settings App', () => { ...@@ -42,7 +40,7 @@ describe('Group Settings App', () => {
wrapper = shallowMount(component, { wrapper = shallowMount(component, {
localVue, localVue,
apolloProvider, apolloProvider,
provide: defaultProvide, provide,
mocks: { mocks: {
$toast: { $toast: {
show, show,
...@@ -61,6 +59,7 @@ describe('Group Settings App', () => { ...@@ -61,6 +59,7 @@ describe('Group Settings App', () => {
const findAlert = () => wrapper.findComponent(GlAlert); const findAlert = () => wrapper.findComponent(GlAlert);
const findPackageSettings = () => wrapper.findComponent(PackagesSettings); const findPackageSettings = () => wrapper.findComponent(PackagesSettings);
const findDependencyProxySettings = () => wrapper.findComponent(DependencyProxySettings);
const waitForApolloQueryAndRender = async () => { const waitForApolloQueryAndRender = async () => {
await waitForPromises(); await waitForPromises();
...@@ -68,9 +67,10 @@ describe('Group Settings App', () => { ...@@ -68,9 +67,10 @@ describe('Group Settings App', () => {
}; };
describe.each` describe.each`
finder | entityProp | entityValue finder | entityProp | entityValue | successMessage | errorMessage
${findPackageSettings} | ${'packageSettings'} | ${packageSettings()} ${findPackageSettings} | ${'packageSettings'} | ${packageSettings()} | ${'Settings saved successfully'} | ${'An error occurred while saving the settings'}
`('settings blocks', ({ finder, entityProp, entityValue }) => { ${findDependencyProxySettings} | ${'dependencyProxySettings'} | ${dependencyProxySettings()} | ${'Setting saved successfully'} | ${'An error occurred while saving the setting'}
`('settings blocks', ({ finder, entityProp, entityValue, successMessage, errorMessage }) => {
beforeEach(() => { beforeEach(() => {
mountComponent(); mountComponent();
return waitForApolloQueryAndRender(); return waitForApolloQueryAndRender();
...@@ -90,7 +90,7 @@ describe('Group Settings App', () => { ...@@ -90,7 +90,7 @@ describe('Group Settings App', () => {
describe('success event', () => { describe('success event', () => {
it('shows a success toast', () => { it('shows a success toast', () => {
finder().vm.$emit('success'); finder().vm.$emit('success');
expect(show).toHaveBeenCalledWith(SUCCESS_UPDATING_SETTINGS); expect(show).toHaveBeenCalledWith(successMessage);
}); });
it('hides the error alert', async () => { it('hides the error alert', async () => {
...@@ -117,7 +117,7 @@ describe('Group Settings App', () => { ...@@ -117,7 +117,7 @@ describe('Group Settings App', () => {
}); });
it('alert has the right text', () => { it('alert has the right text', () => {
expect(findAlert().text()).toBe(ERROR_UPDATING_SETTINGS); expect(findAlert().text()).toBe(errorMessage);
}); });
it('dismissing the alert removes it', async () => { it('dismissing the alert removes it', async () => {
...@@ -131,4 +131,15 @@ describe('Group Settings App', () => { ...@@ -131,4 +131,15 @@ describe('Group Settings App', () => {
}); });
}); });
}); });
describe('when the dependency proxy is not available', () => {
beforeEach(() => {
mountComponent({ provide: { ...defaultProvide, dependencyProxyAvailable: false } });
return waitForApolloQueryAndRender();
});
it('the setting block is hidden', () => {
expect(findDependencyProxySettings().exists()).toBe(false);
});
});
}); });
...@@ -4,14 +4,16 @@ import { updateGroupPackageSettings } from '~/packages_and_registries/settings/g ...@@ -4,14 +4,16 @@ import { updateGroupPackageSettings } from '~/packages_and_registries/settings/g
describe('Package and Registries settings group cache updates', () => { describe('Package and Registries settings group cache updates', () => {
let client; let client;
const payload = { const updateNamespacePackageSettingsPayload = {
data: { packageSettings: {
updateNamespacePackageSettings: { mavenDuplicatesAllowed: false,
packageSettings: { mavenDuplicateExceptionRegex: 'latest[main]something',
mavenDuplicatesAllowed: false, },
mavenDuplicateExceptionRegex: 'latest[main]something', };
},
}, const updateDependencyProxySettingsPayload = {
dependencyProxySetting: {
enabled: false,
}, },
}; };
...@@ -21,6 +23,9 @@ describe('Package and Registries settings group cache updates', () => { ...@@ -21,6 +23,9 @@ describe('Package and Registries settings group cache updates', () => {
mavenDuplicatesAllowed: true, mavenDuplicatesAllowed: true,
mavenDuplicateExceptionRegex: '', mavenDuplicateExceptionRegex: '',
}, },
dependencyProxySetting: {
enabled: true,
},
}, },
}; };
...@@ -35,22 +40,35 @@ describe('Package and Registries settings group cache updates', () => { ...@@ -35,22 +40,35 @@ describe('Package and Registries settings group cache updates', () => {
writeQuery: jest.fn(), writeQuery: jest.fn(),
}; };
}); });
describe('updateGroupPackageSettings', () => {
it('calls readQuery', () => { describe.each`
updateGroupPackageSettings('foo')(client, payload); updateNamespacePackageSettings | updateDependencyProxySettings
expect(client.readQuery).toHaveBeenCalledWith(queryAndVariables); ${updateNamespacePackageSettingsPayload} | ${updateDependencyProxySettingsPayload}
}); ${undefined} | ${updateDependencyProxySettingsPayload}
${updateNamespacePackageSettingsPayload} | ${undefined}
it('writes the correct result in the cache', () => { ${undefined} | ${undefined}
updateGroupPackageSettings('foo')(client, payload); `(
expect(client.writeQuery).toHaveBeenCalledWith({ 'updateGroupPackageSettings',
...queryAndVariables, ({ updateNamespacePackageSettings, updateDependencyProxySettings }) => {
data: { const payload = { data: { updateNamespacePackageSettings, updateDependencyProxySettings } };
group: { it('calls readQuery', () => {
...payload.data.updateNamespacePackageSettings, updateGroupPackageSettings('foo')(client, payload);
expect(client.readQuery).toHaveBeenCalledWith(queryAndVariables);
});
it('writes the correct result in the cache', () => {
updateGroupPackageSettings('foo')(client, payload);
expect(client.writeQuery).toHaveBeenCalledWith({
...queryAndVariables,
data: {
group: {
...cacheMock.group,
...payload.data.updateNamespacePackageSettings,
...payload.data.updateDependencyProxySettings,
},
}, },
}, });
}); });
}); },
}); );
}); });
import { updateGroupPackagesSettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses'; import {
updateGroupPackagesSettingsOptimisticResponse,
updateGroupDependencyProxySettingsOptimisticResponse,
} from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
describe('Optimistic responses', () => { describe('Optimistic responses', () => {
describe('updateGroupPackagesSettingsOptimisticResponse', () => { describe('updateGroupPackagesSettingsOptimisticResponse', () => {
...@@ -17,4 +20,22 @@ describe('Optimistic responses', () => { ...@@ -17,4 +20,22 @@ describe('Optimistic responses', () => {
`); `);
}); });
}); });
describe('updateGroupDependencyProxySettingsOptimisticResponse', () => {
it('returns the correct structure', () => {
expect(updateGroupDependencyProxySettingsOptimisticResponse({ foo: 'bar' }))
.toMatchInlineSnapshot(`
Object {
"__typename": "Mutation",
"updateDependencyProxySettings": Object {
"__typename": "UpdateDependencyProxySettingsPayload",
"dependencyProxySetting": Object {
"foo": "bar",
},
"errors": Array [],
},
}
`);
});
});
}); });
...@@ -5,11 +5,16 @@ export const packageSettings = () => ({ ...@@ -5,11 +5,16 @@ export const packageSettings = () => ({
genericDuplicateExceptionRegex: '', genericDuplicateExceptionRegex: '',
}); });
export const dependencyProxySettings = () => ({
enabled: true,
});
export const groupPackageSettingsMock = { export const groupPackageSettingsMock = {
data: { data: {
group: { group: {
fullPath: 'foo_group_path', fullPath: 'foo_group_path',
packageSettings: packageSettings(), packageSettings: packageSettings(),
dependencyProxySetting: dependencyProxySettings(),
}, },
}, },
}; };
...@@ -29,6 +34,16 @@ export const groupPackageSettingsMutationMock = (override) => ({ ...@@ -29,6 +34,16 @@ export const groupPackageSettingsMutationMock = (override) => ({
}, },
}); });
export const dependencyProxySettingMutationMock = (override) => ({
data: {
updateDependencyProxySettings: {
dependencyProxySetting: dependencyProxySettings(),
errors: [],
...override,
},
},
});
export const groupPackageSettingsMutationErrorMock = { export const groupPackageSettingsMutationErrorMock = {
errors: [ errors: [
{ {
...@@ -53,3 +68,23 @@ export const groupPackageSettingsMutationErrorMock = { ...@@ -53,3 +68,23 @@ export const groupPackageSettingsMutationErrorMock = {
}, },
], ],
}; };
export const dependencyProxySettingMutationErrorMock = {
errors: [
{
message: 'Some error',
locations: [{ line: 1, column: 41 }],
extensions: {
value: {
enabled: 'gitlab-org',
},
problems: [
{
path: ['enabled'],
explanation: 'explaination',
message: 'message',
},
],
},
},
],
};
...@@ -33,46 +33,59 @@ RSpec.describe 'getting dependency proxy settings for a group' do ...@@ -33,46 +33,59 @@ RSpec.describe 'getting dependency proxy settings for a group' do
before do before do
stub_config(dependency_proxy: { enabled: true }) stub_config(dependency_proxy: { enabled: true })
group.create_dependency_proxy_setting!(enabled: true)
end end
subject { post_graphql(query, current_user: user, variables: variables) } subject { post_graphql(query, current_user: user, variables: variables) }
it_behaves_like 'a working graphql query' do shared_examples 'dependency proxy group setting query' do
before do it_behaves_like 'a working graphql query' do
subject before do
end subject
end end
context 'with different permissions' do
where(:group_visibility, :role, :access_granted) do
:private | :maintainer | true
:private | :developer | true
:private | :reporter | true
:private | :guest | true
:private | :anonymous | false
:public | :maintainer | true
:public | :developer | true
:public | :reporter | true
:public | :guest | true
:public | :anonymous | false
end end
with_them do context 'with different permissions' do
before do where(:group_visibility, :role, :access_granted) do
group.update_column(:visibility_level, Gitlab::VisibilityLevel.const_get(group_visibility.to_s.upcase, false)) :private | :maintainer | true
group.add_user(user, role) unless role == :anonymous :private | :developer | true
:private | :reporter | true
:private | :guest | true
:private | :anonymous | false
:public | :maintainer | true
:public | :developer | true
:public | :reporter | true
:public | :guest | true
:public | :anonymous | false
end end
it 'return the proper response' do with_them do
subject before do
group.update_column(:visibility_level, Gitlab::VisibilityLevel.const_get(group_visibility.to_s.upcase, false))
group.add_user(user, role) unless role == :anonymous
end
it 'return the proper response' do
subject
if access_granted if access_granted
expect(dependency_proxy_group_setting_response).to eq('enabled' => true) expect(dependency_proxy_group_setting_response).to eq('enabled' => true)
else else
expect(dependency_proxy_group_setting_response).to be_blank expect(dependency_proxy_group_setting_response).to be_blank
end
end end
end end
end end
end end
context 'with the settings model created' do
before do
group.create_dependency_proxy_setting!(enabled: true)
end
it_behaves_like 'dependency proxy group setting query'
end
context 'without the settings model created' do
it_behaves_like 'dependency proxy group setting query'
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment