Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-03-02 21:16:54 +00:00
parent ad4dfa2eb4
commit bd091da6d5
41 changed files with 321 additions and 231 deletions

View File

@ -398,7 +398,7 @@ group :development, :test do
end
group :development, :test, :danger do
gem 'gitlab-dangerfiles', '~> 2.10.1', require: false
gem 'gitlab-dangerfiles', '~> 2.10.2', require: false
end
group :development, :test, :coverage do

View File

@ -463,7 +463,7 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
gitlab-dangerfiles (2.10.1)
gitlab-dangerfiles (2.10.2)
danger (>= 8.3.1)
danger-gitlab (>= 8.0.0)
gitlab-experiment (0.7.0)
@ -1478,7 +1478,7 @@ DEPENDENCIES
gitaly (~> 14.8.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 2.10.1)
gitlab-dangerfiles (~> 2.10.2)
gitlab-experiment (~> 0.7.0)
gitlab-fog-azure-rm (~> 1.2.0)
gitlab-labkit (~> 0.22.0)

View File

@ -1,6 +1,7 @@
import { s__, __ } from '~/locale';
export const integrationLevels = {
PROJECT: 'project',
GROUP: 'group',
INSTANCE: 'instance',
};

View File

@ -3,6 +3,7 @@ import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml, GlForm } f
import axios from 'axios';
import * as Sentry from '@sentry/browser';
import { mapState, mapActions, mapGetters } from 'vuex';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
@ -41,10 +42,8 @@ export default {
SafeHtml,
},
mixins: [glFeatureFlagsMixin()],
props: {
inject: {
helpHtml: {
type: String,
required: false,
default: '',
},
},
@ -81,28 +80,28 @@ export default {
disableButtons() {
return Boolean(this.isSaving || this.isResetting || this.isTesting);
},
form() {
return this.$refs.integrationForm.$el;
},
},
methods: {
...mapActions(['setOverride', 'requestJiraIssueTypes']),
form() {
return this.$refs.integrationForm.$el;
},
setIsValidated() {
this.isValidated = true;
},
onSaveClick() {
this.isSaving = true;
if (this.integrationActive && !this.form.checkValidity()) {
if (this.integrationActive && !this.form().checkValidity()) {
this.isSaving = false;
this.setIsValidated();
return;
}
this.form.submit();
this.form().submit();
},
onTestClick() {
if (!this.form.checkValidity()) {
if (!this.form().checkValidity()) {
this.setIsValidated();
return;
}
@ -147,7 +146,7 @@ export default {
this.requestJiraIssueTypes(this.getFormData());
},
getFormData() {
return new FormData(this.form);
return new FormData(this.form());
},
onToggleIntegrationState(integrationActive) {
this.integrationActive = integrationActive;

View File

@ -116,13 +116,13 @@ export default function initIntegrationSettingsForm() {
return new Vue({
el: customSettingsEl,
name: 'IntegrationEditRoot',
store: createStore(initialState),
render(createElement) {
return createElement(IntegrationForm, {
props: {
provide: {
helpHtml,
},
});
render(createElement) {
return createElement(IntegrationForm);
},
});
}

View File

@ -1,5 +1,10 @@
import { integrationLevels } from '~/integrations/constants';
export const isInheriting = (state) => (state.defaultState === null ? false : !state.override);
export const isProjectLevel = (state) =>
state.customState.integrationLevel === integrationLevels.PROJECT;
export const propsSource = (state, getters) =>
getters.isInheriting ? state.defaultState : state.customState;

View File

@ -1,4 +1,4 @@
import setupToggleButtons from '~/toggle_buttons';
import { initToggle } from '~/toggles';
function updateVisibility(selector, isVisible) {
Array.from(document.querySelectorAll(selector)).forEach((el) => {
@ -11,12 +11,12 @@ function updateVisibility(selector, isVisible) {
}
export default () => {
const toggleContainer = document.querySelector('.js-auto-ssl-toggle-container');
const sslToggle = initToggle(document.querySelector('.js-enable-ssl-gl-toggle'));
const sslToggleInput = document.querySelector('.js-project-feature-toggle-input');
if (toggleContainer) {
const onToggleButtonClicked = (isAutoSslEnabled) => {
if (sslToggle) {
sslToggle.$on('change', (isAutoSslEnabled) => {
updateVisibility('.js-shown-unless-auto-ssl', !isAutoSslEnabled);
updateVisibility('.js-shown-if-auto-ssl', isAutoSslEnabled);
Array.from(document.querySelectorAll('.js-enabled-unless-auto-ssl')).forEach((el) => {
@ -26,8 +26,9 @@ export default () => {
el.removeAttribute('disabled');
}
});
};
setupToggleButtons(toggleContainer, onToggleButtonClicked);
sslToggleInput.setAttribute('value', isAutoSslEnabled);
});
}
return sslToggle;
};

View File

@ -3,6 +3,7 @@ import { EDITOR_READY_EVENT } from '~/editor/constants';
import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
import SourceEditor from '~/vue_shared/components/source_editor.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SOURCE_EDITOR_DEBOUNCE } from '../../constants';
export default {
editorOptions: {
@ -10,6 +11,7 @@ export default {
// autocomplete for keywords
quickSuggestions: true,
},
debounceValue: SOURCE_EDITOR_DEBOUNCE,
components: {
SourceEditor,
},
@ -34,6 +36,7 @@ export default {
<div class="gl-border-solid gl-border-gray-100 gl-border-1 gl-border-t-none!">
<source-editor
ref="editor"
:debounce-value="$options.debounceValue"
:editor-options="$options.editorOptions"
:file-name="ciConfigPath"
v-bind="$attrs"

View File

@ -47,6 +47,7 @@ export const DRAWER_EXPANDED_KEY = 'pipeline_editor_drawer_expanded';
export const BRANCH_PAGINATION_LIMIT = 20;
export const BRANCH_SEARCH_DEBOUNCE = '500';
export const SOURCE_EDITOR_DEBOUNCE = 500;
export const STARTER_TEMPLATE_NAME = 'Getting-Started';

View File

@ -8,16 +8,12 @@ export const initToggle = (el) => {
return false;
}
const {
name,
isChecked,
disabled,
isLoading,
label,
help,
labelPosition,
...dataset
} = el.dataset;
const { name, id, isChecked, disabled, isLoading, label, help, labelPosition, ...dataset } =
el.dataset || {};
const dataAttrs = Object.fromEntries(
Object.entries(dataset).map(([key, value]) => [`data-${kebabCase(key)}`, value]),
);
return new Vue({
el,
@ -50,9 +46,7 @@ export const initToggle = (el) => {
labelPosition,
},
class: el.className,
attrs: Object.fromEntries(
Object.entries(dataset).map(([key, value]) => [`data-${kebabCase(key)}`, value]),
),
attrs: { id, ...dataAttrs },
on: {
change: (newValue) => {
this.value = newValue;

View File

@ -46,6 +46,11 @@ export default {
required: false,
default: () => ({}),
},
debounceValue: {
type: Number,
required: false,
default: CONTENT_UPDATE_DEBOUNCE,
},
},
data() {
return {
@ -73,9 +78,7 @@ export default {
...this.editorOptions,
});
this.editor.onDidChangeModelContent(
debounce(this.onFileChange.bind(this), CONTENT_UPDATE_DEBOUNCE),
);
this.editor.onDidChangeModelContent(debounce(this.onFileChange.bind(this), this.debounceValue));
},
beforeDestroy() {
this.editor.dispose();

View File

@ -14,14 +14,14 @@
- lets_encrypt_link_start = "<a href=\"%{lets_encrypt_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { lets_encrypt_link_url: lets_encrypt_link_url }
- lets_encrypt_link_end = "</a>".html_safe
= _("Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}").html_safe % { lets_encrypt_link_start: lets_encrypt_link_start, lets_encrypt_link_end: lets_encrypt_link_end }
%button{ type: "button", id: "pages_domain_auto_ssl_enabled_button",
class: "js-project-feature-toggle project-feature-toggle mt-2 #{"is-checked" if auto_ssl_available_and_enabled}",
"aria-label": _("Automatic certificate management using Let's Encrypt") }
= render "shared/gl_toggle",
id: "pages_domain_auto_ssl_enabled_button",
is_checked: auto_ssl_available_and_enabled,
classes: "js-project-feature-toggle js-enable-ssl-gl-toggle mt-2",
label: _("Automatic certificate management using Let's Encrypt"),
label_position: 'hidden'
= f.hidden_field :auto_ssl_enabled?, class: "js-project-feature-toggle-input"
%span.toggle-icon
= sprite_icon("status_success_borderless", size: 18, css_class: "gl-text-blue-500 toggle-status-checked")
= sprite_icon("status_failed_borderless", size: 18, css_class: "gl-text-gray-400 toggle-status-unchecked")
%p.text-secondary.mt-3
%p.gl-text-secondary.gl-mt-1
- docs_link_url = help_page_path("user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md")
- docs_link_start = "<a href=\"%{docs_link_url}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-nowrap\">".html_safe % { docs_link_url: docs_link_url }
- docs_link_end = "</a>".html_safe

View File

@ -3,6 +3,7 @@
- classes = local_assigns.fetch(:classes)
- name = local_assigns.fetch(:name, nil)
- id = local_assigns.fetch(:id, nil)
- is_checked = local_assigns.fetch(:is_checked, false).to_s
- disabled = local_assigns.fetch(:disabled, false).to_s
- is_loading = local_assigns.fetch(:is_loading, false).to_s
@ -13,6 +14,7 @@
%span{ class: classes,
data: { name: name,
id: id,
is_checked: is_checked,
disabled: disabled,
is_loading: is_loading,

View File

@ -19,4 +19,4 @@ return if product_intelligence_paths_to_review.empty? || product_intelligence.sk
warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(product_intelligence_paths_to_review)) unless product_intelligence.has_approved_label?
helper.labels_to_add.merge(labels_to_add) unless labels_to_add.empty?
helper.labels_to_add.concat(labels_to_add) unless labels_to_add.empty?

View File

@ -26,4 +26,4 @@ labels_to_add = helper.changes_by_category.each_with_object([]) do |(category, _
memo << label
end
helper.labels_to_add.merge(labels_to_add) if labels_to_add.any?
helper.labels_to_add.concat(labels_to_add) if labels_to_add.any?

View File

@ -80,4 +80,3 @@
image_url: https://about.gitlab.com/images/home/kubernetes.png
published_at: 2021-01-22
release: 13.8

View File

@ -120,4 +120,3 @@
image_url: https://about.gitlab.com/images/13_9/deploy_keys.png
published_at: 2021-02-22
release: 13.9

View File

@ -57,4 +57,3 @@
image_url: https://about.gitlab.com/images/14_4/monitor-integrated-error-tracking.png
published_at: 2021-10-22
release: 14.4

View File

@ -39,4 +39,3 @@
image_url: https://about.gitlab.com/images/14_7/group_access_token.png
published_at: 2022-01-22
release: 14.7

View File

@ -89,4 +89,3 @@
image_url: 'https://about.gitlab.com/images/14_8/rp_roadmap_settings.png'
published_at: 2022-02-22
release: 14.8

View File

@ -124,8 +124,8 @@ NOTE:
This is applicable to all the projects that use the [`gitlab-dangerfiles` gem](https://rubygems.org/gems/gitlab-dangerfiles).
Danger is often used to improve MR hygiene by adding labels. Instead of calling the
API directly in your `Dangerfile`, add the labels to `helper.labels_to_add` set (with `helper.labels_to_add << label`
or `helper.labels_to_add.merge(array_of_labels)`.
API directly in your `Dangerfile`, add the labels to `helper.labels_to_add` array (with `helper.labels_to_add << label`
or `helper.labels_to_add.concat(array_of_labels)`.
`gitlab-dangerfiles` will then take care of adding the labels to the MR with a single API call after all the rules
have had the chance to add to `helper.labels_to_add`.

View File

@ -4,43 +4,50 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Microsoft Azure OAuth 2.0 OmniAuth Provider **(FREE SELF)**
# Use Microsoft Azure as an authentication provider **(FREE SELF)**
You can enable the Microsoft Azure OAuth 2.0 OmniAuth provider and sign in to
GitLab with your Microsoft Azure credentials. You can configure the provider that uses
[the earlier Azure Active Directory v1.0 endpoint](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-protocols-oauth-code),
or the provider that uses the v2.0 endpoint.
NOTE:
Per Microsoft, this provider uses the [older Azure Active Directory v1.0 endpoint](https://docs.microsoft.com/en-us/azure/active-directory/azuread-dev/v1-protocols-oauth-code).
Microsoft documentation suggests that you should use the [OpenID Connect protocol to use the v2 endpoints](../administration/auth/oidc.md#microsoft-azure) for new projects.
To use v2 endpoints via OmniAuth, please follow [Microsoft Azure OAuth 2.0 OmniAuth Provider v2 instructions](#microsoft-azure-oauth-20-omniauth-provider-v2).
For new projects, Microsoft suggests you use the
[OpenID Connect protocol](../administration/auth/oidc.md#microsoft-azure),
which uses the Microsoft identity platform (v2.0) endpoint.
## Register an Azure application
To enable the Microsoft Azure OAuth 2.0 OmniAuth provider, you must register
your application with Azure. Azure generates a client ID and secret key for you
to use.
an Azure application and get a client ID and secret key.
Sign in to the [Azure Portal](https://portal.azure.com), and follow the
instructions in the [Microsoft Quickstart documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app).
As you go through the Microsoft procedure, keep the following in mind:
- If you have multiple instances of Azure Active Directory, you can switch to the desired tenant.
- You're setting up a Web application.
- The redirect URI requires the URL of the Azure OAuth callback of your GitLab
1. Sign in to the [Azure portal](https://portal.azure.com).
1. If you have multiple Azure Active Directory tenants, switch to the desired tenant.
1. [Register an application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app)
and provide the following information:
- The redirect URI, which requires the URL of the Azure OAuth callback of your GitLab
installation. For example, `https://gitlab.mycompany.com/users/auth/azure_oauth2/callback`.
The type dropdown should be set to **Web**.
- The `client ID` and `client secret` are terms associated with OAuth 2.0. In some Microsoft documentation,
the terms may be listed as `Application ID` and `Application Secret`.
- If you have to generate a new client secret, follow the Microsoft documentation
for [creating a new application secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#create-a-new-application-secret).
- Save the client ID and client secret for your new app, as the client secret is only
displayed one time.
- The application type, which must be set to **Web**.
1. Save the client ID and client secret. The client secret is only
displayed once.
If required, you can [create a new application secret](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal#option-2-create-a-new-application-secret).
`client ID` and `client secret` are terms associated with OAuth 2.0.
In some Microsoft documentation, the terms are named `Application ID` and
`Application Secret`.
## Enable Microsoft OAuth in GitLab
1. On your GitLab server, open the configuration file.
For Omnibus GitLab:
- **For Omnibus installations**
```shell
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
- **For installations from source**
```shell
cd /home/git/gitlab
@ -48,12 +55,12 @@ As you go through the Microsoft procedure, keep the following in mind:
sudo -u git -H editor config/gitlab.yml
```
1. Refer to [Configure initial settings](omniauth.md#configure-initial-settings)
for initial settings.
1. [Configure the initial settings](omniauth.md#configure-initial-settings).
1. Add the provider configuration:
1. Add the provider configuration. Replace `CLIENT ID`, `CLIENT SECRET`, and `TENANT ID`
with the values you got when you registered the Azure application.
For Omnibus GitLab:
- **For Omnibus installations**
```ruby
gitlab_rails['omniauth_providers'] = [
@ -69,7 +76,7 @@ As you go through the Microsoft procedure, keep the following in mind:
]
```
For installations from source:
- **For installations from source**
```yaml
- { name: 'azure_oauth2',
@ -79,27 +86,22 @@ As you go through the Microsoft procedure, keep the following in mind:
tenant_id: 'TENANT ID' } }
```
The `base_azure_url` is optional and can be added for different locales;
such as `base_azure_url: "https://login.microsoftonline.de"`.
1. Replace `CLIENT ID`, `CLIENT SECRET` and `TENANT ID` with the values you got above.
You can optionally add `base_azure_url` for different locales,
for example, `base_azure_url: "https://login.microsoftonline.de"`.
1. Save the configuration file.
1. Reconfigure or restart GitLab, depending on your installation method:
1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
if you installed using Omnibus, or [restart GitLab](../administration/restart_gitlab.md#installations-from-source)
if you installed from source.
- *If you installed from Omnibus GitLab,*
[reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
- *If you installed from source,*
[restart GitLab](../administration/restart_gitlab.md#installations-from-source).
1. Refresh the GitLab sign-in page. A Microsoft icon should display below the
sign-in form.
On the sign-in page, you should now see a Microsoft icon below the regular
sign-in form. Click the icon to begin the authentication process. Microsoft then
asks you to sign in and authorize the GitLab application. If successful, you are
returned to GitLab and signed in.
1. Select the icon. Sign in to Microsoft and authorize the GitLab application.
Read [Enable OmniAuth for an Existing User](omniauth.md#enable-omniauth-for-an-existing-user)
for information on how existing GitLab users can connect to their newly-available Azure AD accounts.
Read [Enable OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user)
for information on how existing GitLab users can connect to their new Azure AD accounts.
## Microsoft Azure OAuth 2.0 OmniAuth Provider v2

View File

@ -217,13 +217,3 @@ add a to-do item:
![Alert Details Add a to do](img/alert_detail_add_todo_v13_9.png)
To view your To-Do List, on the top bar, select **To-Do List** (**{todo-done}**).
## View the environment that generated the alert
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232492) in GitLab 13.5 behind a feature flag, disabled by default.
> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/232492) in GitLab 13.6.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
The environment information and the link are displayed in the [Alert Details tab](#alert-details-tab).

View File

@ -95,7 +95,7 @@ RSpec.describe 'User adds pages domain', :js do
fill_in 'Domain', with: 'my.test.domain.com'
find('.js-auto-ssl-toggle-container .project-feature-toggle').click
find('.js-auto-ssl-toggle-container .js-project-feature-toggle').click
fill_in 'Certificate (PEM)', with: certificate_pem
fill_in 'Key (PEM)', with: certificate_key

View File

@ -50,7 +50,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
expect(page).to have_selector '.card-header', text: 'Certificate'
expect(page).to have_text domain.subject
find('.js-auto-ssl-toggle-container .project-feature-toggle').click
find('.js-auto-ssl-toggle-container .js-project-feature-toggle').click
expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
expect(page).not_to have_selector '.card-header', text: 'Certificate'
@ -74,7 +74,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
find('.js-auto-ssl-toggle-container .project-feature-toggle').click
find('.js-auto-ssl-toggle-container .js-project-feature-toggle').click
expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
expect(page).to have_field 'Certificate (PEM)', type: 'textarea'

View File

@ -37,7 +37,7 @@ describe('IntegrationForm', () => {
const createComponent = ({
customStateProps = {},
initialState = {},
props = {},
provide = {},
mountFn = shallowMountExtended,
} = {}) => {
const store = createStore({
@ -47,7 +47,7 @@ describe('IntegrationForm', () => {
dispatch = jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = mountFn(IntegrationForm, {
propsData: { ...props },
provide,
store,
stubs: {
OverrideDropdown,
@ -300,7 +300,7 @@ describe('IntegrationForm', () => {
});
});
describe('with `helpHtml` prop', () => {
describe('with `helpHtml` provided', () => {
const mockTestId = 'jest-help-html-test';
setHTMLFixture(`
@ -316,7 +316,7 @@ describe('IntegrationForm', () => {
const mockHelpHtml = document.querySelector(`[data-testid="${mockTestId}"]`);
createComponent({
props: {
provide: {
helpHtml: mockHelpHtml.outerHTML,
},
});

View File

@ -13,6 +13,7 @@ export const mockIntegrationProps = {
fields: [],
type: '',
inheritFromId: 25,
integrationLevel: 'project',
};
export const mockJiraIssueTypes = [

View File

@ -1,5 +1,12 @@
import { currentKey, isInheriting, propsSource } from '~/integrations/edit/store/getters';
import {
currentKey,
isInheriting,
isProjectLevel,
propsSource,
} from '~/integrations/edit/store/getters';
import createState from '~/integrations/edit/store/state';
import { integrationLevels } from '~/integrations/constants';
import { mockIntegrationProps } from '../mock_data';
describe('Integration form store getters', () => {
@ -45,6 +52,18 @@ describe('Integration form store getters', () => {
});
});
describe('isProjectLevel', () => {
it.each`
integrationLevel | expected
${integrationLevels.PROJECT} | ${true}
${integrationLevels.GROUP} | ${false}
${integrationLevels.INSTANCE} | ${false}
`('when integrationLevel is `$integrationLevel`', ({ integrationLevel, expected }) => {
state.customState.integrationLevel = integrationLevel;
expect(isProjectLevel(state)).toBe(expected);
});
});
describe('propsSource', () => {
beforeEach(() => {
state.defaultState = defaultState;

View File

@ -58,7 +58,6 @@ describe('Incident Tabs component', () => {
const findTabs = () => wrapper.findAll(GlTab);
const findSummaryTab = () => findTabs().at(0);
const findMetricsTab = () => wrapper.find('[data-testid="metrics-tab"]');
const findTimelineTab = () => wrapper.find('[data-testid="timeline-events-tab"]');
const findAlertDetailsTab = () => wrapper.find('[data-testid="alert-details-tab"]');
const findAlertDetailsComponent = () => wrapper.find(AlertDetailsTable);
const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
@ -74,29 +73,6 @@ describe('Incident Tabs component', () => {
});
});
describe('incident timeline tab', () => {
beforeEach(() => {
mountComponent();
});
it('renders the timeline tab when feature flag is enabled', () => {
expect(findTimelineTab().exists()).toBe(true);
expect(findTimelineTab().attributes('title')).toBe('Timeline');
});
it('does not render timeline tab when feature flag is disabled', () => {
mountComponent({}, { provide: { glFeatures: { incidentTimelineEventTab: false } } });
expect(findTimelineTab().exists()).toBe(false);
});
it('does not render timeline tab when not available in license', () => {
mountComponent({}, { provide: { glFeatures: { incidentTimelineEvents: false } } });
expect(findTimelineTab().exists()).toBe(false);
});
});
describe('with an alert present', () => {
beforeEach(() => {
mountComponent();

View File

@ -0,0 +1,82 @@
import initForm from '~/pages/projects/pages_domains/form';
const ENABLED_UNLESS_AUTO_SSL_CLASS = 'js-enabled-unless-auto-ssl';
const SSL_TOGGLE_CLASS = 'js-enable-ssl-gl-toggle';
const SSL_TOGGLE_INPUT_CLASS = 'js-project-feature-toggle-input';
const SHOW_IF_AUTO_SSL_CLASS = 'js-shown-if-auto-ssl';
const SHOW_UNLESS_AUTO_SSL_CLASS = 'js-shown-unless-auto-ssl';
const D_NONE_CLASS = 'd-none';
describe('Page domains form', () => {
let toggle;
const findEnabledUnless = () => document.querySelector(`.${ENABLED_UNLESS_AUTO_SSL_CLASS}`);
const findSslToggle = () => document.querySelector(`.${SSL_TOGGLE_CLASS} button`);
const findSslToggleInput = () => document.querySelector(`.${SSL_TOGGLE_INPUT_CLASS}`);
const findIfAutoSsl = () => document.querySelector(`.${SHOW_IF_AUTO_SSL_CLASS}`);
const findUnlessAutoSsl = () => document.querySelector(`.${SHOW_UNLESS_AUTO_SSL_CLASS}`);
const create = () => {
setFixtures(`
<form>
<span
class="${SSL_TOGGLE_CLASS}"
data-label="SSL toggle"
></span>
<input class="${SSL_TOGGLE_INPUT_CLASS}" type="hidden" />
<span class="${SHOW_UNLESS_AUTO_SSL_CLASS}"></span>
<span class="${SHOW_IF_AUTO_SSL_CLASS}"></span>
<button class="${ENABLED_UNLESS_AUTO_SSL_CLASS}"></button>
</form>
`);
};
it('instantiates the toggle', () => {
create();
initForm();
expect(findSslToggle()).not.toBe(null);
});
describe('when auto SSL is enabled', () => {
beforeEach(() => {
create();
toggle = initForm();
toggle.$emit('change', true);
});
it('sets the correct classes', () => {
expect(Array.from(findIfAutoSsl().classList)).not.toContain(D_NONE_CLASS);
expect(Array.from(findUnlessAutoSsl().classList)).toContain(D_NONE_CLASS);
});
it('sets the correct disabled value', () => {
expect(findEnabledUnless().getAttribute('disabled')).toBe('disabled');
});
it('sets the correct value for the input', () => {
expect(findSslToggleInput().getAttribute('value')).toBe('true');
});
});
describe('when auto SSL is not enabled', () => {
beforeEach(() => {
create();
toggle = initForm();
toggle.$emit('change', false);
});
it('sets the correct classes', () => {
expect(Array.from(findIfAutoSsl().classList)).toContain(D_NONE_CLASS);
expect(Array.from(findUnlessAutoSsl().classList)).not.toContain(D_NONE_CLASS);
});
it('sets the correct disabled value', () => {
expect(findUnlessAutoSsl().getAttribute('disabled')).toBe(null);
});
it('sets the correct value for the input', () => {
expect(findSslToggleInput().getAttribute('value')).toBe('false');
});
});
});

View File

@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { EDITOR_READY_EVENT } from '~/editor/constants';
import { SOURCE_EDITOR_DEBOUNCE } from '~/pipeline_editor/constants';
import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
import {
mockCiConfigPath,
@ -22,7 +23,7 @@ describe('Pipeline Editor | Text editor component', () => {
const MockSourceEditor = {
template: '<div/>',
props: ['value', 'fileName'],
props: ['value', 'fileName', 'editorOptions', 'debounceValue'],
};
const createComponent = (glFeatures = {}, mountFn = shallowMount) => {
@ -90,6 +91,14 @@ describe('Pipeline Editor | Text editor component', () => {
expect(findEditor().props('fileName')).toBe(mockCiConfigPath);
});
it('passes down editor configs options', () => {
expect(findEditor().props('editorOptions')).toEqual({ quickSuggestions: true });
});
it('passes down editor debounce value', () => {
expect(findEditor().props('debounceValue')).toBe(SOURCE_EDITOR_DEBOUNCE);
});
it('bubbles up events', () => {
findEditor().vm.$emit(EDITOR_READY_EVENT, editorInstanceDetail);

View File

@ -14,6 +14,7 @@ exports[`Snippet Blob Edit component with loaded blob matches snapshot 1`] = `
/>
<source-editor-stub
debouncevalue="250"
editoroptions="[object Object]"
fileglobalid="blob_local_7"
filename="foo/bar/test.md"

View File

@ -99,10 +99,12 @@ describe('toggles/index.js', () => {
const name = 'toggle-name';
const help = 'Help text';
const foo = 'bar';
const id = 'an-id';
beforeEach(() => {
initToggleWithOptions({
name,
id,
isChecked: true,
disabled: true,
isLoading: true,
@ -144,6 +146,10 @@ describe('toggles/index.js', () => {
it('passes custom dataset to the wrapper', () => {
expect(toggleWrapper.dataset.foo).toBe('bar');
});
it('passes an id to the wrapper', () => {
expect(toggleWrapper.id).toBe(id);
});
});
});
});