Commit cd5225bb authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 575f3788 cca5bbda
...@@ -701,3 +701,11 @@ RSpec/TopLevelDescribePath: ...@@ -701,3 +701,11 @@ RSpec/TopLevelDescribePath:
Exclude: Exclude:
- 'spec/fixtures/**/*.rb' - 'spec/fixtures/**/*.rb'
- 'ee/spec/fixtures/**/*.rb' - 'ee/spec/fixtures/**/*.rb'
QA/SelectorUsage:
Enabled: true
Include:
- 'spec/**/*.rb'
- 'ee/spec/**/*.rb'
Exclude:
- 'spec/rubocop/**/*_spec.rb'
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
featureAccessLevel, featureAccessLevel,
featureAccessLevelNone, featureAccessLevelNone,
CVE_ID_REQUEST_BUTTON_I18N, CVE_ID_REQUEST_BUTTON_I18N,
featureAccessLevelDescriptions,
} from '../constants'; } from '../constants';
import { toggleHiddenClassBySelector } from '../external'; import { toggleHiddenClassBySelector } from '../external';
import projectFeatureSetting from './project_feature_setting.vue'; import projectFeatureSetting from './project_feature_setting.vue';
...@@ -176,7 +177,7 @@ export default { ...@@ -176,7 +177,7 @@ export default {
requirementsAccessLevel: featureAccessLevel.EVERYONE, requirementsAccessLevel: featureAccessLevel.EVERYONE,
securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS, securityAndComplianceAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
operationsAccessLevel: featureAccessLevel.EVERYONE, operationsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true, containerRegistryAccessLevel: featureAccessLevel.EVERYONE,
lfsEnabled: true, lfsEnabled: true,
requestAccessEnabled: true, requestAccessEnabled: true,
highlightChangesClass: false, highlightChangesClass: false,
...@@ -184,6 +185,8 @@ export default { ...@@ -184,6 +185,8 @@ export default {
cveIdRequestEnabled: true, cveIdRequestEnabled: true,
featureAccessLevelEveryone, featureAccessLevelEveryone,
featureAccessLevelMembers, featureAccessLevelMembers,
featureAccessLevel,
featureAccessLevelDescriptions,
}; };
return { ...defaults, ...this.currentSettings }; return { ...defaults, ...this.currentSettings };
...@@ -248,7 +251,10 @@ export default { ...@@ -248,7 +251,10 @@ export default {
}, },
showContainerRegistryPublicNote() { showContainerRegistryPublicNote() {
return this.visibilityLevel === visibilityOptions.PUBLIC; return (
this.visibilityLevel === visibilityOptions.PUBLIC &&
this.containerRegistryAccessLevel === featureAccessLevel.EVERYONE
);
}, },
repositoryHelpText() { repositoryHelpText() {
...@@ -310,6 +316,10 @@ export default { ...@@ -310,6 +316,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS, featureAccessLevel.PROJECT_MEMBERS,
this.operationsAccessLevel, this.operationsAccessLevel,
); );
this.containerRegistryAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.containerRegistryAccessLevel,
);
if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) { if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) {
// When from Internal->Private narrow access for only members // When from Internal->Private narrow access for only members
this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS; this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS;
...@@ -339,6 +349,8 @@ export default { ...@@ -339,6 +349,8 @@ export default {
this.requirementsAccessLevel = featureAccessLevel.EVERYONE; this.requirementsAccessLevel = featureAccessLevel.EVERYONE;
if (this.operationsAccessLevel === featureAccessLevel.PROJECT_MEMBERS) if (this.operationsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.operationsAccessLevel = featureAccessLevel.EVERYONE; this.operationsAccessLevel = featureAccessLevel.EVERYONE;
if (this.containerRegistryAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.containerRegistryAccessLevel = featureAccessLevel.EVERYONE;
this.highlightChanges(); this.highlightChanges();
} }
...@@ -521,19 +533,24 @@ export default { ...@@ -521,19 +533,24 @@ export default {
" "
> >
<div v-if="showContainerRegistryPublicNote" class="text-muted"> <div v-if="showContainerRegistryPublicNote" class="text-muted">
{{ <gl-sprintf
:message="
s__( s__(
'ProjectSettings|Note: the container registry is always visible when a project is public', `ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'`,
) )
}} "
>
<template #access_level_description>{{
featureAccessLevelDescriptions[featureAccessLevel.EVERYONE]
}}</template>
</gl-sprintf>
</div> </div>
<gl-toggle <project-feature-setting
v-model="containerRegistryEnabled" v-model="containerRegistryAccessLevel"
class="gl-my-2" :options="repoFeatureAccessLevelOptions"
:disabled="!repositoryEnabled" :disabled-input="!repositoryEnabled"
:label="$options.i18n.containerRegistryLabel" :label="$options.i18n.containerRegistryLabel"
label-position="hidden" name="project[project_feature_attributes][container_registry_access_level]"
name="project[container_registry_enabled]"
/> />
</project-setting-row> </project-setting-row>
<project-setting-row <project-setting-row
......
...@@ -22,7 +22,7 @@ export const featureAccessLevel = { ...@@ -22,7 +22,7 @@ export const featureAccessLevel = {
EVERYONE: 20, EVERYONE: 20,
}; };
const featureAccessLevelDescriptions = { export const featureAccessLevelDescriptions = {
[featureAccessLevel.NOT_ENABLED]: __('Enable feature to choose access level'), [featureAccessLevel.NOT_ENABLED]: __('Enable feature to choose access level'),
[featureAccessLevel.PROJECT_MEMBERS]: __('Only Project Members'), [featureAccessLevel.PROJECT_MEMBERS]: __('Only Project Members'),
[featureAccessLevel.EVERYONE]: __('Everyone With Access'), [featureAccessLevel.EVERYONE]: __('Everyone With Access'),
......
...@@ -480,7 +480,7 @@ body { ...@@ -480,7 +480,7 @@ body {
.btn:active, .btn:active,
.btn.active { .btn.active {
background-color: #444; background-color: #444;
border-color: #fafafa; border-color: #4f4f4f;
color: #fafafa; color: #fafafa;
} }
.btn svg { .btn svg {
......
...@@ -186,8 +186,7 @@ body.gl-dark { ...@@ -186,8 +186,7 @@ body.gl-dark {
} }
} }
$border-white-light: $gray-900; $border-white-normal: $border-color;
$border-white-normal: $gray-900;
$body-bg: $gray-10; $body-bg: $gray-10;
$input-bg: $white; $input-bg: $white;
......
...@@ -51,7 +51,7 @@ module Git ...@@ -51,7 +51,7 @@ module Git
change: change, change: change,
push_options: params[:push_options], push_options: params[:push_options],
merge_request_branches: merge_request_branches, merge_request_branches: merge_request_branches,
create_pipelines: change[:index] < PIPELINE_PROCESS_LIMIT || Feature.enabled?(:git_push_create_all_pipelines, project), create_pipelines: under_process_limit?(change),
execute_project_hooks: execute_project_hooks, execute_project_hooks: execute_project_hooks,
create_push_event: !create_bulk_push_event create_push_event: !create_bulk_push_event
).execute ).execute
...@@ -60,6 +60,10 @@ module Git ...@@ -60,6 +60,10 @@ module Git
create_bulk_push_event(ref_type, action, changes) if create_bulk_push_event create_bulk_push_event(ref_type, action, changes) if create_bulk_push_event
end end
def under_process_limit?(change)
change[:index] < PIPELINE_PROCESS_LIMIT || Feature.enabled?(:git_push_create_all_pipelines, project)
end
def create_bulk_push_event(ref_type, action, changes) def create_bulk_push_event(ref_type, action, changes)
EventCreateService.new.bulk_push( EventCreateService.new.bulk_push(
project, project,
......
...@@ -20,7 +20,7 @@ if gitlab.mr_body.size < 5 ...@@ -20,7 +20,7 @@ if gitlab.mr_body.size < 5
end end
if (THROUGHPUT_LABELS & gitlab.mr_labels).empty? if (THROUGHPUT_LABELS & gitlab.mr_labels).empty?
warn 'Please add a [merge request type](https://about.gitlab.com/handbook/engineering/metrics/#data-classification) to this merge request.' warn 'Please add a [merge request type](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) to this merge request.'
end end
unless gitlab.mr_json["assignee"] unless gitlab.mr_json["assignee"]
......
...@@ -40,9 +40,9 @@ There are no reviewer and maintainer suggestions for the changes in this MR. ...@@ -40,9 +40,9 @@ There are no reviewer and maintainer suggestions for the changes in this MR.
MARKDOWN MARKDOWN
UNKNOWN_FILES_MESSAGE = <<MARKDOWN UNKNOWN_FILES_MESSAGE = <<MARKDOWN
### Uncategorised files ### Uncategorized files
These files couldn't be categorised, so Danger was unable to suggest a reviewer. These files couldn't be categorized, so Danger was unable to suggest a reviewer.
Please consider creating a merge request to Please consider creating a merge request to
[add support](https://gitlab.com/gitlab-org/gitlab/blob/master/tooling/danger/project_helper.rb) [add support](https://gitlab.com/gitlab-org/gitlab/blob/master/tooling/danger/project_helper.rb)
for them. for them.
......
...@@ -839,7 +839,7 @@ We include guidance for links in these categories: ...@@ -839,7 +839,7 @@ We include guidance for links in these categories:
### Basic link criteria ### Basic link criteria
- Use inline link Markdown markup `[Text](https://example.com)`. - Use inline link Markdown markup `[Text](https://example.com)`.
It's easier to read, review, and maintain. _Do not_ use `[Text][identifier]`. It's easier to read, review, and maintain. _Do not_ use `[Text][identifier]` reference-style links.
- Use [meaningful anchor texts](https://www.futurehosting.com/blog/links-should-have-meaningful-anchor-text-heres-why/). - Use [meaningful anchor texts](https://www.futurehosting.com/blog/links-should-have-meaningful-anchor-text-heres-why/).
For example, instead of writing something like `Read more about GitLab Issue Boards [here](LINK)`, For example, instead of writing something like `Read more about GitLab Issue Boards [here](LINK)`,
......
...@@ -745,6 +745,25 @@ You can, however, remove the Container Registry for a project: ...@@ -745,6 +745,25 @@ You can, however, remove the Container Registry for a project:
The **Packages & Registries > Container Registry** entry is removed from the project's sidebar. The **Packages & Registries > Container Registry** entry is removed from the project's sidebar.
## Set visibility of the Container Registry
By default, the Container Registry is visible to everyone with access to the project.
You can, however, change the visibility of the Container Registry for a project:
1. Go to your project's **Settings > General** page.
1. Expand the section **Visibility, project features, permissions**.
1. Under **Container Registry**, select an option from the dropdown:
- **Everyone With Access** (Default): The Container Registry is visible to everyone with access
to the project. If the project is public, the Container Registry is also public. If the project
is internal or private, the Container Registry is also internal or private.
- **Only Project Members**: The Container Registry is visible only to project members with
Reporter role or higher. This is similar to the behavior of a private project with Container
Registry visibility set to **Everyone With Access**.
1. Select **Save changes**.
## Manifest lists and garbage collection ## Manifest lists and garbage collection
Manifest lists are commonly used for creating multi-architecture images. If you rely on manifest Manifest lists are commonly used for creating multi-architecture images. If you rely on manifest
......
...@@ -480,7 +480,7 @@ body { ...@@ -480,7 +480,7 @@ body {
.btn:active, .btn:active,
.btn.active { .btn.active {
background-color: #444; background-color: #444;
border-color: #fafafa; border-color: #4f4f4f;
color: #fafafa; color: #fafafa;
} }
.btn svg { .btn svg {
......
...@@ -38,5 +38,11 @@ module EE ...@@ -38,5 +38,11 @@ module EE
current_user.can?(:admin_namespace, namespace.root_ancestor) current_user.can?(:admin_namespace, namespace.root_ancestor)
end end
def link_to_buy_additional_minutes_path(namespace)
return EE::SUBSCRIPTIONS_MORE_MINUTES_URL if ::Feature.disabled?(:new_route_ci_minutes_purchase, default_enabled: :yaml)
buy_minutes_subscriptions_path(selected_group: namespace.id)
end
end end
end end
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
.col-sm-6.offset-sm-6 .col-sm-6.offset-sm-6
- if ::Gitlab.com? - if ::Gitlab.com?
= link_to s_('UsageQuota|Buy additional minutes'), = link_to s_('UsageQuota|Buy additional minutes'),
EE::SUBSCRIPTIONS_MORE_MINUTES_URL, link_to_buy_additional_minutes_path(namespace),
target: '_blank', target: '_blank',
class: 'gl-button btn btn-confirm float-right', class: 'gl-button btn btn-confirm float-right',
data: { track_event: 'click_buy_ci_minutes', track_label: namespace.actual_plan_name, track_property: 'pipeline_quota_page' } data: { track_event: 'click_buy_ci_minutes', track_label: namespace.actual_plan_name, track_property: 'pipeline_quota_page' }
......
...@@ -190,7 +190,7 @@ RSpec.describe 'Admin::AuditLogs', :js do ...@@ -190,7 +190,7 @@ RSpec.describe 'Admin::AuditLogs', :js do
click_link 'Impersonate' click_link 'Impersonate'
visit(new_project_path) visit(new_project_path)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
fill_in(:project_name, with: 'Gotham City') fill_in(:project_name, with: 'Gotham City')
......
...@@ -31,7 +31,7 @@ RSpec.describe 'Delete Epic', :js do ...@@ -31,7 +31,7 @@ RSpec.describe 'Delete Epic', :js do
end end
it 'deletes the issue and redirect to epic list' do it 'deletes the issue and redirect to epic list' do
find('.qa-delete-button').click find('.qa-delete-button').click # rubocop:disable QA/SelectorUsage
wait_for_requests wait_for_requests
find('.js-modal-action-primary').click find('.js-modal-action-primary').click
......
...@@ -75,13 +75,13 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -75,13 +75,13 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
end end
it 'has disabled the remove button' do it 'has disabled the remove button' do
within '[data-qa-selector="remove_billable_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do # rubocop:disable QA/SelectorUsage
expect(page).to have_button('Remove user', disabled: true) expect(page).to have_button('Remove user', disabled: true)
end end
end end
it 'enables the remove button when user enters valid username' do it 'enables the remove button when user enters valid username' do
within '[data-qa-selector="remove_billable_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do # rubocop:disable QA/SelectorUsage
find('input').fill_in(with: maintainer.username) find('input').fill_in(with: maintainer.username)
find('input').send_keys(:tab) find('input').send_keys(:tab)
...@@ -90,7 +90,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -90,7 +90,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
end end
it 'does not enable button when user enters invalid username' do it 'does not enable button when user enters invalid username' do
within '[data-qa-selector="remove_billable_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do # rubocop:disable QA/SelectorUsage
find('input').fill_in(with: 'invalid username') find('input').fill_in(with: 'invalid username')
find('input').send_keys(:tab) find('input').send_keys(:tab)
...@@ -112,7 +112,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -112,7 +112,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
end end
it 'shows a flash message' do it 'shows a flash message' do
within '[data-qa-selector="remove_billable_member_modal"]' do within '[data-qa-selector="remove_billable_member_modal"]' do # rubocop:disable QA/SelectorUsage
find('input').fill_in(with: maintainer.username) find('input').fill_in(with: maintainer.username)
find('input').send_keys(:tab) find('input').send_keys(:tab)
...@@ -138,7 +138,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do ...@@ -138,7 +138,7 @@ RSpec.describe 'Groups > Billing > Seat Usage', :js do
click_button('Remove member') click_button('Remove member')
within '[data-qa-selector="remove_member_modal_content"]' do within '[data-qa-selector="remove_member_modal_content"]' do # rubocop:disable QA/SelectorUsage
click_button('Remove member') click_button('Remove member')
end end
......
...@@ -70,7 +70,7 @@ RSpec.describe 'Group navbar' do ...@@ -70,7 +70,7 @@ RSpec.describe 'Group navbar' do
it 'redirects to value stream when Analytics item is clicked' do it 'redirects to value stream when Analytics item is clicked' do
page.within('.sidebar-top-level-items') do page.within('.sidebar-top-level-items') do
find('[data-qa-selector=analytics_anchor]').click find('[data-qa-selector=analytics_anchor]').click # rubocop:disable QA/SelectorUsage
end end
wait_for_requests wait_for_requests
......
...@@ -144,8 +144,6 @@ RSpec.describe 'Groups > Usage Quotas' do ...@@ -144,8 +144,6 @@ RSpec.describe 'Groups > Usage Quotas' do
it 'has correct tracking setup and shows correct group quota and projects info' do it 'has correct tracking setup and shows correct group quota and projects info' do
visit_pipeline_quota_page visit_pipeline_quota_page
expect(page).to have_link('Buy additional minutes', href: EE::SUBSCRIPTIONS_MORE_MINUTES_URL)
page.within('.pipeline-quota') do page.within('.pipeline-quota') do
expect(page).to have_content("1000 / 500 minutes") expect(page).to have_content("1000 / 500 minutes")
expect(page).to have_content("200% used") expect(page).to have_content("200% used")
...@@ -188,6 +186,28 @@ RSpec.describe 'Groups > Usage Quotas' do ...@@ -188,6 +186,28 @@ RSpec.describe 'Groups > Usage Quotas' do
end end
end end
describe 'new_route_ci_minutes_purchase feature flag' do
context 'when is disabled' do
before do
stub_feature_flags(new_route_ci_minutes_purchase: false)
end
it 'points to Customers Portal purchase flow' do
visit_pipeline_quota_page
expect(page).to have_link('Buy additional minutes', href: EE::SUBSCRIPTIONS_MORE_MINUTES_URL)
end
end
context 'when is enabled' do
it 'points to GitLab purchase flow' do
visit_pipeline_quota_page
expect(page).to have_link('Buy additional minutes', href: buy_minutes_subscriptions_path(selected_group: group.id))
end
end
end
def visit_pipeline_quota_page def visit_pipeline_quota_page
visit group_usage_quotas_path(group) visit group_usage_quotas_path(group)
end end
......
...@@ -43,7 +43,7 @@ RSpec.describe 'Project' do ...@@ -43,7 +43,7 @@ RSpec.describe 'Project' do
new_path = 'example-custom-project-template' new_path = 'example-custom-project-template'
new_name = 'Example Custom Project Template' new_name = 'Example Custom Project Template'
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
find('.project-template .custom-instance-project-templates-tab').click find('.project-template .custom-instance-project-templates-tab').click
find("label[for='#{projects.first.name}']").click find("label[for='#{projects.first.name}']").click
...@@ -68,7 +68,7 @@ RSpec.describe 'Project' do ...@@ -68,7 +68,7 @@ RSpec.describe 'Project' do
new_path = 'example-custom-project-template' new_path = 'example-custom-project-template'
new_name = 'Example Custom Project Template' new_name = 'Example Custom Project Template'
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
find('.project-template .custom-instance-project-templates-tab').click find('.project-template .custom-instance-project-templates-tab').click
find("label[for='#{projects.first.name}']").click find("label[for='#{projects.first.name}']").click
...@@ -90,7 +90,7 @@ RSpec.describe 'Project' do ...@@ -90,7 +90,7 @@ RSpec.describe 'Project' do
new_path = 'example-custom-project-template' new_path = 'example-custom-project-template'
new_name = 'Example Custom Project Template' new_name = 'Example Custom Project Template'
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
find('.project-template .custom-instance-project-templates-tab').click find('.project-template .custom-instance-project-templates-tab').click
find("label[for='#{projects.first.name}']").click find("label[for='#{projects.first.name}']").click
...@@ -111,7 +111,7 @@ RSpec.describe 'Project' do ...@@ -111,7 +111,7 @@ RSpec.describe 'Project' do
it 'has a working pagination', :js do it 'has a working pagination', :js do
last_project = "label[for='#{projects.last.name}']" last_project = "label[for='#{projects.last.name}']"
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
find('.project-template .custom-instance-project-templates-tab').click find('.project-template .custom-instance-project-templates-tab').click
expect(page).to have_css('.custom-project-templates .gl-pagination') expect(page).to have_css('.custom-project-templates .gl-pagination')
......
...@@ -69,7 +69,7 @@ RSpec.describe 'Project mirror', :js do ...@@ -69,7 +69,7 @@ RSpec.describe 'Project mirror', :js do
import_state.update!(next_execution_timestamp: timestamp - 1.minute) import_state.update!(next_execution_timestamp: timestamp - 1.minute)
end end
let(:disabled_updating_button) { '[data-qa-selector="updating_button"].disabled' } let(:disabled_updating_button) { '[data-qa-selector="updating_button"].disabled' } # rubocop:disable QA/SelectorUsage
it 'disables Update now button' do it 'disables Update now button' do
travel_to(timestamp) do travel_to(timestamp) do
...@@ -81,7 +81,7 @@ RSpec.describe 'Project mirror', :js do ...@@ -81,7 +81,7 @@ RSpec.describe 'Project mirror', :js do
end end
context 'when the project is archived' do context 'when the project is archived' do
let(:disabled_update_now_button) { '[data-qa-selector="update_now_button"].disabled' } let(:disabled_update_now_button) { '[data-qa-selector="update_now_button"].disabled' } # rubocop:disable QA/SelectorUsage
before do before do
project.update!(archived: true) project.update!(archived: true)
......
...@@ -17,7 +17,7 @@ RSpec.describe 'New project', :js do ...@@ -17,7 +17,7 @@ RSpec.describe 'New project', :js do
it 'shows mirror repository checkbox enabled', :js do it 'shows mirror repository checkbox enabled', :js do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
first('.js-import-git-toggle-button').click first('.js-import-git-toggle-button').click
expect(page).to have_unchecked_field('Mirror repository', disabled: false) expect(page).to have_unchecked_field('Mirror repository', disabled: false)
...@@ -31,7 +31,7 @@ RSpec.describe 'New project', :js do ...@@ -31,7 +31,7 @@ RSpec.describe 'New project', :js do
it 'does not show mirror repository option' do it 'does not show mirror repository option' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
first('.js-import-git-toggle-button').click first('.js-import-git-toggle-button').click
expect(page).not_to have_content('Mirror repository') expect(page).not_to have_content('Mirror repository')
...@@ -60,16 +60,16 @@ RSpec.describe 'New project', :js do ...@@ -60,16 +60,16 @@ RSpec.describe 'New project', :js do
it 'shows CI/CD tab and pane' do it 'shows CI/CD tab and pane' do
visit new_project_path visit new_project_path
expect(page).to have_css('[data-qa-panel-name="cicd_for_external_repo"]') expect(page).to have_css('[data-qa-panel-name="cicd_for_external_repo"]') # rubocop:disable QA/SelectorUsage
find('[data-qa-panel-name="cicd_for_external_repo"]').click find('[data-qa-panel-name="cicd_for_external_repo"]').click # rubocop:disable QA/SelectorUsage
expect(page).to have_css('#ci-cd-project-pane') expect(page).to have_css('#ci-cd-project-pane')
end end
it '"Import project" tab creates projects with features enabled' do it '"Import project" tab creates projects with features enabled' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
page.within '#import-project-pane' do page.within '#import-project-pane' do
first('.js-import-git-toggle-button').click first('.js-import-git-toggle-button').click
...@@ -89,7 +89,7 @@ RSpec.describe 'New project', :js do ...@@ -89,7 +89,7 @@ RSpec.describe 'New project', :js do
it 'creates CI/CD project from repo URL', :sidekiq_might_not_need_inline do it 'creates CI/CD project from repo URL', :sidekiq_might_not_need_inline do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="cicd_for_external_repo"]').click find('[data-qa-panel-name="cicd_for_external_repo"]').click # rubocop:disable QA/SelectorUsage
page.within '#ci-cd-project-pane' do page.within '#ci-cd-project-pane' do
find('.js-import-git-toggle-button').click find('.js-import-git-toggle-button').click
...@@ -109,7 +109,7 @@ RSpec.describe 'New project', :js do ...@@ -109,7 +109,7 @@ RSpec.describe 'New project', :js do
it 'creates CI/CD project from GitHub' do it 'creates CI/CD project from GitHub' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="cicd_for_external_repo"]').click find('[data-qa-panel-name="cicd_for_external_repo"]').click # rubocop:disable QA/SelectorUsage
page.within '#ci-cd-project-pane' do page.within '#ci-cd-project-pane' do
find('.js-import-github').click find('.js-import-github').click
...@@ -146,7 +146,7 @@ RSpec.describe 'New project', :js do ...@@ -146,7 +146,7 @@ RSpec.describe 'New project', :js do
it 'stays on GitHub import page after access token failure' do it 'stays on GitHub import page after access token failure' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="cicd_for_external_repo"]').click find('[data-qa-panel-name="cicd_for_external_repo"]').click # rubocop:disable QA/SelectorUsage
page.within '#ci-cd-project-pane' do page.within '#ci-cd-project-pane' do
find('.js-import-github').click find('.js-import-github').click
...@@ -170,7 +170,7 @@ RSpec.describe 'New project', :js do ...@@ -170,7 +170,7 @@ RSpec.describe 'New project', :js do
it 'does not show CI/CD only tab' do it 'does not show CI/CD only tab' do
visit new_project_path visit new_project_path
expect(page).not_to have_css('[data-qa-panel-name="cicd_for_external_repo"]') expect(page).not_to have_css('[data-qa-panel-name="cicd_for_external_repo"]') # rubocop:disable QA/SelectorUsage
end end
end end
end end
...@@ -458,7 +458,7 @@ RSpec.describe 'New project', :js do ...@@ -458,7 +458,7 @@ RSpec.describe 'New project', :js do
def visit_create_from_built_in_templates_tab def visit_create_from_built_in_templates_tab
visit new_project_path visit new_project_path
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
end end
end end
end end
...@@ -19,7 +19,7 @@ RSpec.describe 'Project', :js do ...@@ -19,7 +19,7 @@ RSpec.describe 'Project', :js do
it "defaults to correct namespace" do it "defaults to correct namespace" do
visit new_project_path visit new_project_path
find('[data-qa-selector="create_from_template_link"]').click find('[data-qa-selector="create_from_template_link"]').click # rubocop:disable QA/SelectorUsage
find('.custom-group-project-templates-tab').click find('.custom-group-project-templates-tab').click
find("label[for=#{template.name}]").click find("label[for=#{template.name}]").click
...@@ -28,7 +28,7 @@ RSpec.describe 'Project', :js do ...@@ -28,7 +28,7 @@ RSpec.describe 'Project', :js do
it "uses supplied namespace" do it "uses supplied namespace" do
visit new_project_path(namespace_id: other_subgroup.id) visit new_project_path(namespace_id: other_subgroup.id)
find('[data-qa-selector="create_from_template_link"]').click find('[data-qa-selector="create_from_template_link"]').click # rubocop:disable QA/SelectorUsage
find('.custom-group-project-templates-tab').click find('.custom-group-project-templates-tab').click
find("label[for=#{template.name}]").click find("label[for=#{template.name}]").click
......
...@@ -98,7 +98,7 @@ RSpec.describe 'Protected Branches', :js do ...@@ -98,7 +98,7 @@ RSpec.describe 'Protected Branches', :js do
it 'displays toggle off' do it 'displays toggle off' do
visit project_settings_repository_path(project) visit project_settings_repository_path(project)
page.within '.qa-protected-branches-list' do page.within '.qa-protected-branches-list' do # rubocop:disable QA/SelectorUsage
expect(page).not_to have_css('.js-code-owner-toggle.is-checked') expect(page).not_to have_css('.js-code-owner-toggle.is-checked')
end end
end end
......
...@@ -172,4 +172,24 @@ RSpec.describe EE::NamespacesHelper do ...@@ -172,4 +172,24 @@ RSpec.describe EE::NamespacesHelper do
end end
end end
end end
describe '#link_to_buy_additional_minutes_path' do
subject { helper.link_to_buy_additional_minutes_path(namespace) }
let_it_be(:namespace) { create(:namespace_with_plan) }
context 'new_route_ci_minutes_purchase' do
context 'when is disabled' do
before do
stub_feature_flags(new_route_ci_minutes_purchase: false)
end
it { is_expected.to be EE::SUBSCRIPTIONS_MORE_MINUTES_URL }
end
context 'when is enabled' do
it { is_expected.to eq buy_minutes_subscriptions_path(selected_group: namespace.id) }
end
end
end
end end
...@@ -179,9 +179,9 @@ RSpec.shared_examples "protected branches > access control > EE" do ...@@ -179,9 +179,9 @@ RSpec.shared_examples "protected branches > access control > EE" do
it 'unprotect/delete can be performed by a maintainer' do it 'unprotect/delete can be performed by a maintainer' do
visit project_protected_branches_path(project) visit project_protected_branches_path(project)
expect(page).to have_selector('.qa-protected-branch') expect(page).to have_selector('.qa-protected-branch') # rubocop:disable QA/SelectorUsage
accept_alert { click_on 'Unprotect' } accept_alert { click_on 'Unprotect' }
expect(page).not_to have_selector('.qa-protected-branch') expect(page).not_to have_selector('.qa-protected-branch') # rubocop:disable QA/SelectorUsage
end end
context 'with unprotect access levels' do context 'with unprotect access levels' do
......
...@@ -9,8 +9,8 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do ...@@ -9,8 +9,8 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do
it 'enables the Select parent group dropdown and does not show an alert for a group' do it 'enables the Select parent group dropdown and does not show an alert for a group' do
render 'groups/settings/transfer', group: group render 'groups/settings/transfer', group: group
expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]' expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]'
end end
...@@ -19,7 +19,7 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do ...@@ -19,7 +19,7 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do
render 'groups/settings/transfer', group: group render 'groups/settings/transfer', group: group
expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' # rubocop:disable QA/SelectorUsage
expect(rendered).to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]' expect(rendered).to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]'
end end
...@@ -29,8 +29,8 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do ...@@ -29,8 +29,8 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do
render 'groups/settings/transfer', group: subgroup render 'groups/settings/transfer', group: subgroup
expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]' expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]'
end end
end end
......
...@@ -26022,7 +26022,7 @@ msgstr "" ...@@ -26022,7 +26022,7 @@ msgstr ""
msgid "ProjectSettings|No merge commits are created." msgid "ProjectSettings|No merge commits are created."
msgstr "" msgstr ""
msgid "ProjectSettings|Note: the container registry is always visible when a project is public" msgid "ProjectSettings|Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'"
msgstr "" msgstr ""
msgid "ProjectSettings|Only signed commits can be pushed to this repository." msgid "ProjectSettings|Only signed commits can be pushed to this repository."
......
...@@ -57,7 +57,7 @@ module QA ...@@ -57,7 +57,7 @@ module QA
install: install:
stage: install stage: install
script: script:
- "pip install mypypipackage --no-deps --index-url http://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}" - "pip install mypypipackage --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
tags: tags:
- "runner-for-#{project.name}" - "runner-for-#{project.name}"
......
# frozen_string_literal: true
require_relative '../../qa_helpers'
require_relative '../../code_reuse_helpers'
module RuboCop
module Cop
module QA
# This cop checks for the usage of data-qa-selectors or .qa-* classes in non-QA files
#
# @example
# # bad
# find('[data-qa-selector="the_selector"]')
# find('.qa-selector')
#
# # good
# find('[data-testid="the_selector"]')
# find('#selector')
class SelectorUsage < RuboCop::Cop::Cop
include QAHelpers
include CodeReuseHelpers
SELECTORS = /\.qa-\w+|data-qa-\w+/.freeze
MESSAGE = %(Do not use `%s` as this is reserved for the end-to-end specs. Use a different selector or a data-testid instead.)
def on_str(node)
return if in_qa_file?(node)
return unless in_spec?(node)
add_offense(node, message: MESSAGE % node.value) if SELECTORS =~ node.value
rescue StandardError
# catch all errors and ignore them.
# without this catch-all rescue, rubocop will fail
# because of non-UTF-8 characters in some Strings
end
end
end
end
end
...@@ -90,7 +90,7 @@ RSpec.describe 'Admin Appearance' do ...@@ -90,7 +90,7 @@ RSpec.describe 'Admin Appearance' do
sign_in(admin) sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin) gitlab_enable_admin_mode_sign_in(admin)
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
expect_custom_new_project_appearance(appearance) expect_custom_new_project_appearance(appearance)
end end
......
...@@ -256,7 +256,7 @@ RSpec.describe 'Admin Groups' do ...@@ -256,7 +256,7 @@ RSpec.describe 'Admin Groups' do
visit group_group_members_path(group) visit group_group_members_path(group)
page.within '[data-qa-selector="members_list"]' do page.within '[data-qa-selector="members_list"]' do # rubocop:disable QA/SelectorUsage
expect(page).to have_content(current_user.name) expect(page).to have_content(current_user.name)
expect(page).to have_content('Developer') expect(page).to have_content('Developer')
end end
...@@ -265,7 +265,7 @@ RSpec.describe 'Admin Groups' do ...@@ -265,7 +265,7 @@ RSpec.describe 'Admin Groups' do
visit group_group_members_path(group) visit group_group_members_path(group)
page.within '[data-qa-selector="members_list"]' do page.within '[data-qa-selector="members_list"]' do # rubocop:disable QA/SelectorUsage
expect(page).not_to have_content(current_user.name) expect(page).not_to have_content(current_user.name)
expect(page).not_to have_content('Developer') expect(page).not_to have_content('Developer')
end end
......
...@@ -184,7 +184,7 @@ RSpec.describe 'Admin::Users::User' do ...@@ -184,7 +184,7 @@ RSpec.describe 'Admin::Users::User' do
it 'logs in as the user when impersonate is clicked' do it 'logs in as the user when impersonate is clicked' do
subject subject
find('[data-qa-selector="user_menu"]').click find('[data-qa-selector="user_menu"]').click # rubocop:disable QA/SelectorUsage
expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eql(another_user.username) expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eql(another_user.username)
end end
...@@ -220,7 +220,7 @@ RSpec.describe 'Admin::Users::User' do ...@@ -220,7 +220,7 @@ RSpec.describe 'Admin::Users::User' do
it 'logs out of impersonated user back to original user' do it 'logs out of impersonated user back to original user' do
subject subject
find('[data-qa-selector="user_menu"]').click find('[data-qa-selector="user_menu"]').click # rubocop:disable QA/SelectorUsage
expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eq(current_user.username) expect(page.find(:css, '[data-testid="user-profile-link"]')['data-user']).to eq(current_user.username)
end end
......
...@@ -33,7 +33,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j ...@@ -33,7 +33,7 @@ RSpec.describe 'Resolving all open threads in a merge request from an issue', :j
context 'resolving the thread' do context 'resolving the thread' do
before do before do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
it 'hides the link for creating a new issue' do it 'hides the link for creating a new issue' do
......
...@@ -35,7 +35,7 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue', ...@@ -35,7 +35,7 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue',
context 'resolving the thread' do context 'resolving the thread' do
before do before do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
it 'hides the link for creating a new issue' do it 'hides the link for creating a new issue' do
......
...@@ -408,7 +408,7 @@ RSpec.describe 'Issue Sidebar' do ...@@ -408,7 +408,7 @@ RSpec.describe 'Issue Sidebar' do
context 'sidebar', :js do context 'sidebar', :js do
it 'finds issue copy forwarding email' do it 'finds issue copy forwarding email' do
expect(find('[data-qa-selector="copy-forward-email"]').text).to eq "Issue email: #{issue.creatable_note_email_address(user)}" expect(find('[data-qa-selector="copy-forward-email"]').text).to eq "Issue email: #{issue.creatable_note_email_address(user)}" # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -444,7 +444,7 @@ RSpec.describe 'Issue Sidebar' do ...@@ -444,7 +444,7 @@ RSpec.describe 'Issue Sidebar' do
end end
it 'does not find issue email' do it 'does not find issue email' do
expect(page).not_to have_selector('[data-qa-selector="copy-forward-email"]') expect(page).not_to have_selector('[data-qa-selector="copy-forward-email"]') # rubocop:disable QA/SelectorUsage
end end
end end
end end
......
...@@ -182,7 +182,7 @@ RSpec.describe "User creates issue" do ...@@ -182,7 +182,7 @@ RSpec.describe "User creates issue" do
end end
it 'does not hide the milestone select' do it 'does not hide the milestone select' do
expect(page).to have_selector('.qa-issuable-milestone-dropdown') expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -202,11 +202,11 @@ RSpec.describe "User creates issue" do ...@@ -202,11 +202,11 @@ RSpec.describe "User creates issue" do
end end
it 'shows the milestone select' do it 'shows the milestone select' do
expect(page).to have_selector('.qa-issuable-milestone-dropdown') expect(page).to have_selector('.qa-issuable-milestone-dropdown') # rubocop:disable QA/SelectorUsage
end end
it 'hides the weight input' do it 'hides the weight input' do
expect(page).not_to have_selector('.qa-issuable-weight-input') expect(page).not_to have_selector('.qa-issuable-weight-input') # rubocop:disable QA/SelectorUsage
end end
it 'shows the incident help text' do it 'shows the incident help text' do
......
...@@ -63,7 +63,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -63,7 +63,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark thread as resolved' do it 'allows user to mark thread as resolved' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
expect(page).to have_selector('.discussion-body', visible: false) expect(page).to have_selector('.discussion-body', visible: false)
...@@ -80,7 +80,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -80,7 +80,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to unresolve thread' do it 'allows user to unresolve thread' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
click_button 'Unresolve thread' click_button 'Unresolve thread'
end end
...@@ -92,7 +92,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -92,7 +92,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
describe 'resolved thread' do describe 'resolved thread' do
before do before do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
visit_merge_request visit_merge_request
...@@ -193,7 +193,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -193,7 +193,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to resolve from reply form without a comment' do it 'allows user to resolve from reply form without a comment' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
page.within '.line-resolve-all-container' do page.within '.line-resolve-all-container' do
...@@ -230,7 +230,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -230,7 +230,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'hides jump to next button when all resolved' do it 'hides jump to next button when all resolved' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
expect(page).to have_selector('.discussion-next-btn', visible: false) expect(page).to have_selector('.discussion-next-btn', visible: false)
...@@ -326,7 +326,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -326,7 +326,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark all threads as resolved' do it 'allows user to mark all threads as resolved' do
page.all('.discussion-reply-holder', count: 2).each do |reply_holder| page.all('.discussion-reply-holder', count: 2).each do |reply_holder|
page.within reply_holder do page.within reply_holder do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -338,7 +338,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -338,7 +338,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to quickly scroll to next unresolved thread' do it 'allows user to quickly scroll to next unresolved thread' do
page.within('.discussion-reply-holder', match: :first) do page.within('.discussion-reply-holder', match: :first) do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
page.within '.line-resolve-all-container' do page.within '.line-resolve-all-container' do
...@@ -410,7 +410,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -410,7 +410,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to mark thread as resolved' do it 'allows user to mark thread as resolved' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
end end
page.within '.diff-content .note' do page.within '.diff-content .note' do
...@@ -425,7 +425,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -425,7 +425,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to unresolve thread' do it 'allows user to unresolve thread' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
click_button 'Unresolve thread' click_button 'Unresolve thread'
end end
...@@ -453,7 +453,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do ...@@ -453,7 +453,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
it 'allows user to comment & unresolve thread' do it 'allows user to comment & unresolve thread' do
page.within '.diff-content' do page.within '.diff-content' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
find_field('Reply…').click find_field('Reply…').click
......
...@@ -21,7 +21,7 @@ RSpec.describe 'Project variables', :js do ...@@ -21,7 +21,7 @@ RSpec.describe 'Project variables', :js do
click_button('Add variable') click_button('Add variable')
page.within('#add-ci-variable') do page.within('#add-ci-variable') do
find('[data-qa-selector="ci_variable_key_field"] input').set('akey') find('[data-qa-selector="ci_variable_key_field"] input').set('akey') # rubocop:disable QA/SelectorUsage
find('#ci-variable-value').set('akey_value') find('#ci-variable-value').set('akey_value')
find('[data-testid="environment-scope"]').click find('[data-testid="environment-scope"]').click
find('[data-testid="ci-environment-search"]').set('review/*') find('[data-testid="ci-environment-search"]').set('review/*')
......
...@@ -137,7 +137,7 @@ RSpec.describe 'File blob', :js do ...@@ -137,7 +137,7 @@ RSpec.describe 'File blob', :js do
context 'when ref switch' do context 'when ref switch' do
def switch_ref_to(ref_name) def switch_ref_to(ref_name)
first('.qa-branches-select').click first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
page.within '.project-refs-form' do page.within '.project-refs-form' do
click_link ref_name click_link ref_name
......
...@@ -30,9 +30,9 @@ RSpec.describe 'Environment > Metrics' do ...@@ -30,9 +30,9 @@ RSpec.describe 'Environment > Metrics' do
click_link 'Monitoring' click_link 'Monitoring'
expect(page).to have_current_path(project_metrics_dashboard_path(project, environment: environment.id)) expect(page).to have_current_path(project_metrics_dashboard_path(project, environment: environment.id))
expect(page).to have_css('[data-qa-selector="environments_dropdown"]') expect(page).to have_css('[data-qa-selector="environments_dropdown"]') # rubocop:disable QA/SelectorUsage
within('[data-qa-selector="environments_dropdown"]') do within('[data-qa-selector="environments_dropdown"]') do # rubocop:disable QA/SelectorUsage
# Click on the dropdown # Click on the dropdown
click_on(environment.name) click_on(environment.name)
...@@ -58,7 +58,7 @@ RSpec.describe 'Environment > Metrics' do ...@@ -58,7 +58,7 @@ RSpec.describe 'Environment > Metrics' do
it 'shows metrics', :js do it 'shows metrics', :js do
click_link 'Monitoring' click_link 'Monitoring'
expect(page).to have_css('[data-qa-selector="prometheus_graphs"]') expect(page).to have_css('[data-qa-selector="prometheus_graphs"]') # rubocop:disable QA/SelectorUsage
end end
it_behaves_like 'has environment selector' it_behaves_like 'has environment selector'
......
...@@ -455,10 +455,10 @@ RSpec.describe 'Environments page', :js do ...@@ -455,10 +455,10 @@ RSpec.describe 'Environments page', :js do
expect(page).to have_content 'review-1' expect(page).to have_content 'review-1'
expect(page).to have_content 'review-2' expect(page).to have_content 'review-2'
within('.ci-table') do within('.ci-table') do
within('[data-qa-selector="environment_item"]', text: 'review-1') do within('[data-qa-selector="environment_item"]', text: 'review-1') do # rubocop:disable QA/SelectorUsage
expect(find('.js-auto-stop').text).not_to be_empty expect(find('.js-auto-stop').text).not_to be_empty
end end
within('[data-qa-selector="environment_item"]', text: 'review-2') do within('[data-qa-selector="environment_item"]', text: 'review-2') do # rubocop:disable QA/SelectorUsage
expect(find('.js-auto-stop').text).not_to be_empty expect(find('.js-auto-stop').text).not_to be_empty
end end
end end
......
...@@ -50,7 +50,7 @@ RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do ...@@ -50,7 +50,7 @@ RSpec.describe 'Environment > Pod Logs', :js, :kubeclient do
wait_for_requests wait_for_requests
page.within('.qa-pods-dropdown') do page.within('.qa-pods-dropdown') do # rubocop:disable QA/SelectorUsage
find(".dropdown-toggle:not([disabled])").click find(".dropdown-toggle:not([disabled])").click
dropdown_items = find(".dropdown-menu").all(".dropdown-item:not([disabled])") dropdown_items = find(".dropdown-menu").all(".dropdown-item:not([disabled])")
......
...@@ -91,7 +91,7 @@ RSpec.describe 'User sees feature flag list', :js do ...@@ -91,7 +91,7 @@ RSpec.describe 'User sees feature flag list', :js do
it 'shows the empty page' do it 'shows the empty page' do
expect(page).to have_text 'Get started with feature flags' expect(page).to have_text 'Get started with feature flags'
expect(page).to have_selector('.btn-confirm', text: 'New feature flag') expect(page).to have_selector('.btn-confirm', text: 'New feature flag')
expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure') expect(page).to have_selector('[data-qa-selector="configure_feature_flags_button"]', text: 'Configure') # rubocop:disable QA/SelectorUsage
end end
end end
end end
...@@ -18,7 +18,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license ...@@ -18,7 +18,7 @@ RSpec.describe 'Projects > Files > Project owner sees a link to create a license
expect(current_path).to eq("/-/ide/project/#{project.full_path}/edit/master/-/LICENSE") expect(current_path).to eq("/-/ide/project/#{project.full_path}/edit/master/-/LICENSE")
expect(page).to have_selector('.qa-file-templates-bar') expect(page).to have_selector('.qa-file-templates-bar') # rubocop:disable QA/SelectorUsage
select_template('MIT License') select_template('MIT License')
......
...@@ -181,8 +181,8 @@ RSpec.describe 'Project fork' do ...@@ -181,8 +181,8 @@ RSpec.describe 'Project fork' do
it 'allows user to fork only to the group on fork page', :js do it 'allows user to fork only to the group on fork page', :js do
visit new_project_fork_path(project) visit new_project_fork_path(project)
to_personal_namespace = find('[data-qa-selector=fork_namespace_button].disabled') to_personal_namespace = find('[data-qa-selector=fork_namespace_button].disabled') # rubocop:disable QA/SelectorUsage
to_group = find(".fork-groups button[data-qa-name=#{group.name}]") to_group = find(".fork-groups button[data-qa-name=#{group.name}]") # rubocop:disable QA/SelectorUsage
expect(to_personal_namespace).not_to be_nil expect(to_personal_namespace).not_to be_nil
expect(to_group).not_to be_disabled expect(to_group).not_to be_disabled
......
...@@ -62,6 +62,6 @@ RSpec.describe 'Import/Export - project import integration test', :js do ...@@ -62,6 +62,6 @@ RSpec.describe 'Import/Export - project import integration test', :js do
end end
def click_import_project def click_import_project
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -13,7 +13,7 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -13,7 +13,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
where(:invite_members_group_modal_enabled, :expected_invite_group_selector) do where(:invite_members_group_modal_enabled, :expected_invite_group_selector) do
true | 'button[data-qa-selector="invite_a_group_button"]' true | 'button[data-qa-selector="invite_a_group_button"]' # rubocop:disable QA/SelectorUsage
false | '#invite-group-tab' false | '#invite-group-tab'
end end
...@@ -43,7 +43,7 @@ RSpec.describe 'Project > Members > Invite group', :js do ...@@ -43,7 +43,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
end end
describe 'Share with group lock' do describe 'Share with group lock' do
let(:invite_group_selector) { 'button[data-qa-selector="invite_a_group_button"]' } let(:invite_group_selector) { 'button[data-qa-selector="invite_a_group_button"]' } # rubocop:disable QA/SelectorUsage
shared_examples 'the project can be shared with groups' do shared_examples 'the project can be shared with groups' do
it 'the "Invite a group" button exists' do it 'the "Invite a group" button exists' do
......
...@@ -19,7 +19,7 @@ RSpec.describe 'New project', :js do ...@@ -19,7 +19,7 @@ RSpec.describe 'New project', :js do
) )
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
expect(page).to have_content 'Other visibility settings have been disabled by the administrator.' expect(page).to have_content 'Other visibility settings have been disabled by the administrator.'
end end
...@@ -30,7 +30,7 @@ RSpec.describe 'New project', :js do ...@@ -30,7 +30,7 @@ RSpec.describe 'New project', :js do
) )
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
expect(page).to have_content 'Visibility settings have been disabled by the administrator.' expect(page).to have_content 'Visibility settings have been disabled by the administrator.'
end end
...@@ -45,14 +45,14 @@ RSpec.describe 'New project', :js do ...@@ -45,14 +45,14 @@ RSpec.describe 'New project', :js do
it 'shows "New project" page', :js do it 'shows "New project" page', :js do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
expect(page).to have_content('Project name') expect(page).to have_content('Project name')
expect(page).to have_content('Project URL') expect(page).to have_content('Project URL')
expect(page).to have_content('Project slug') expect(page).to have_content('Project slug')
click_link('New project') click_link('New project')
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
expect(page).to have_link('GitHub') expect(page).to have_link('GitHub')
expect(page).to have_link('Bitbucket') expect(page).to have_link('Bitbucket')
...@@ -65,7 +65,7 @@ RSpec.describe 'New project', :js do ...@@ -65,7 +65,7 @@ RSpec.describe 'New project', :js do
before do before do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
end end
it 'has Manifest file' do it 'has Manifest file' do
...@@ -79,7 +79,7 @@ RSpec.describe 'New project', :js do ...@@ -79,7 +79,7 @@ RSpec.describe 'New project', :js do
stub_application_setting(default_project_visibility: level) stub_application_setting(default_project_visibility: level)
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
page.within('#blank-project-pane') do page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{level}")).to be_checked expect(find_field("project_visibility_level_#{level}")).to be_checked
end end
...@@ -87,7 +87,7 @@ RSpec.describe 'New project', :js do ...@@ -87,7 +87,7 @@ RSpec.describe 'New project', :js do
it "saves visibility level #{level} on validation error" do it "saves visibility level #{level} on validation error" do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
choose(key) choose(key)
click_button('Create project') click_button('Create project')
...@@ -107,7 +107,7 @@ RSpec.describe 'New project', :js do ...@@ -107,7 +107,7 @@ RSpec.describe 'New project', :js do
context 'when admin mode is enabled', :enable_admin_mode do context 'when admin mode is enabled', :enable_admin_mode do
it 'has private selected' do it 'has private selected' do
visit new_project_path(namespace_id: group.id) visit new_project_path(namespace_id: group.id)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
page.within('#blank-project-pane') do page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
...@@ -134,7 +134,7 @@ RSpec.describe 'New project', :js do ...@@ -134,7 +134,7 @@ RSpec.describe 'New project', :js do
context 'when admin mode is enabled', :enable_admin_mode do context 'when admin mode is enabled', :enable_admin_mode do
it 'has private selected' do it 'has private selected' do
visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE }) visit new_project_path(namespace_id: group.id, project: { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
page.within('#blank-project-pane') do page.within('#blank-project-pane') do
expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked expect(find_field("project_visibility_level_#{Gitlab::VisibilityLevel::PRIVATE}")).to be_checked
...@@ -155,7 +155,7 @@ RSpec.describe 'New project', :js do ...@@ -155,7 +155,7 @@ RSpec.describe 'New project', :js do
context 'Readme selector' do context 'Readme selector' do
it 'shows the initialize with Readme checkbox on "Blank project" tab' do it 'shows the initialize with Readme checkbox on "Blank project" tab' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
expect(page).to have_css('input#project_initialize_with_readme') expect(page).to have_css('input#project_initialize_with_readme')
expect(page).to have_content('Initialize repository with a README') expect(page).to have_content('Initialize repository with a README')
...@@ -163,7 +163,7 @@ RSpec.describe 'New project', :js do ...@@ -163,7 +163,7 @@ RSpec.describe 'New project', :js do
it 'does not show the initialize with Readme checkbox on "Create from template" tab' do it 'does not show the initialize with Readme checkbox on "Create from template" tab' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
first('.choose-template').click first('.choose-template').click
page.within '.project-fields-form' do page.within '.project-fields-form' do
...@@ -174,7 +174,7 @@ RSpec.describe 'New project', :js do ...@@ -174,7 +174,7 @@ RSpec.describe 'New project', :js do
it 'does not show the initialize with Readme checkbox on "Import project" tab' do it 'does not show the initialize with Readme checkbox on "Import project" tab' do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
first('.js-import-git-toggle-button').click first('.js-import-git-toggle-button').click
page.within '#import-project-pane' do page.within '#import-project-pane' do
...@@ -188,7 +188,7 @@ RSpec.describe 'New project', :js do ...@@ -188,7 +188,7 @@ RSpec.describe 'New project', :js do
context 'with user namespace' do context 'with user namespace' do
before do before do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
end end
it 'selects the user namespace' do it 'selects the user namespace' do
...@@ -204,7 +204,7 @@ RSpec.describe 'New project', :js do ...@@ -204,7 +204,7 @@ RSpec.describe 'New project', :js do
before do before do
group.add_owner(user) group.add_owner(user)
visit new_project_path(namespace_id: group.id) visit new_project_path(namespace_id: group.id)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
end end
it 'selects the group namespace' do it 'selects the group namespace' do
...@@ -221,7 +221,7 @@ RSpec.describe 'New project', :js do ...@@ -221,7 +221,7 @@ RSpec.describe 'New project', :js do
before do before do
group.add_maintainer(user) group.add_maintainer(user)
visit new_project_path(namespace_id: subgroup.id) visit new_project_path(namespace_id: subgroup.id)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
end end
it 'selects the group namespace' do it 'selects the group namespace' do
...@@ -241,7 +241,7 @@ RSpec.describe 'New project', :js do ...@@ -241,7 +241,7 @@ RSpec.describe 'New project', :js do
internal_group.add_owner(user) internal_group.add_owner(user)
private_group.add_owner(user) private_group.add_owner(user)
visit new_project_path(namespace_id: public_group.id) visit new_project_path(namespace_id: public_group.id)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
end end
it 'enables the correct visibility options' do it 'enables the correct visibility options' do
...@@ -271,7 +271,7 @@ RSpec.describe 'New project', :js do ...@@ -271,7 +271,7 @@ RSpec.describe 'New project', :js do
context 'Import project options', :js do context 'Import project options', :js do
before do before do
visit new_project_path visit new_project_path
find('[data-qa-panel-name="import_project"]').click find('[data-qa-panel-name="import_project"]').click # rubocop:disable QA/SelectorUsage
end end
context 'from git repository url, "Repo by URL"' do context 'from git repository url, "Repo by URL"' do
...@@ -343,7 +343,7 @@ RSpec.describe 'New project', :js do ...@@ -343,7 +343,7 @@ RSpec.describe 'New project', :js do
before do before do
group.add_developer(user) group.add_developer(user)
visit new_project_path(namespace_id: group.id) visit new_project_path(namespace_id: group.id)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
end end
it 'selects the group namespace' do it 'selects the group namespace' do
......
...@@ -39,7 +39,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do ...@@ -39,7 +39,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
# The dropdown above the tree # The dropdown above the tree
page.within('.repo-breadcrumb') do page.within('.repo-breadcrumb') do
find('.qa-add-to-tree').click find('.qa-add-to-tree').click # rubocop:disable QA/SelectorUsage
aggregate_failures 'dropdown links above the repo tree' do aggregate_failures 'dropdown links above the repo tree' do
expect(page).to have_link('New file') expect(page).to have_link('New file')
...@@ -71,7 +71,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do ...@@ -71,7 +71,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
find_new_menu_toggle.click find_new_menu_toggle.click
end end
expect(page).not_to have_selector('.qa-add-to-tree') expect(page).not_to have_selector('.qa-add-to-tree') # rubocop:disable QA/SelectorUsage
expect(page).not_to have_link('Web IDE') expect(page).not_to have_link('Web IDE')
end end
......
...@@ -49,8 +49,8 @@ RSpec.describe 'Multi-file editor new directory', :js do ...@@ -49,8 +49,8 @@ RSpec.describe 'Multi-file editor new directory', :js do
# Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT, # Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
# (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is # (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
# taller (as it is by default with chrome headless) then the button will not exist. # taller (as it is by default with chrome headless) then the button will not exist.
if page.has_css?('.qa-begin-commit-button') if page.has_css?('.qa-begin-commit-button') # rubocop:disable QA/SelectorUsage
find('.qa-begin-commit-button').click find('.qa-begin-commit-button').click # rubocop:disable QA/SelectorUsage
end end
fill_in('commit-message', with: 'commit message ide') fill_in('commit-message', with: 'commit message ide')
......
...@@ -39,8 +39,8 @@ RSpec.describe 'Multi-file editor new file', :js do ...@@ -39,8 +39,8 @@ RSpec.describe 'Multi-file editor new file', :js do
# Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT, # Compact mode depends on the size of window. If it is shorter than MAX_WINDOW_HEIGHT_COMPACT,
# (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is # (as it is with WEBDRIVER_HEADLESS=0), this initial commit button will exist. Otherwise, if it is
# taller (as it is by default with chrome headless) then the button will not exist. # taller (as it is by default with chrome headless) then the button will not exist.
if page.has_css?('.qa-begin-commit-button') if page.has_css?('.qa-begin-commit-button') # rubocop:disable QA/SelectorUsage
find('.qa-begin-commit-button').click find('.qa-begin-commit-button').click # rubocop:disable QA/SelectorUsage
end end
fill_in('commit-message', with: 'commit message ide') fill_in('commit-message', with: 'commit message ide')
......
...@@ -26,7 +26,7 @@ RSpec.describe 'Projects tree', :js do ...@@ -26,7 +26,7 @@ RSpec.describe 'Projects tree', :js do
expect(page).to have_selector('.tree-item') expect(page).to have_selector('.tree-item')
expect(page).to have_content('add tests for .gitattributes custom highlighting') expect(page).to have_content('add tests for .gitattributes custom highlighting')
expect(page).not_to have_selector('.flash-alert') expect(page).not_to have_selector('.flash-alert')
expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage
end end
it 'renders tree table for a subtree without errors' do it 'renders tree table for a subtree without errors' do
...@@ -35,7 +35,7 @@ RSpec.describe 'Projects tree', :js do ...@@ -35,7 +35,7 @@ RSpec.describe 'Projects tree', :js do
expect(page).to have_selector('.tree-item') expect(page).to have_selector('.tree-item')
expect(page).to have_content('add spaces in whitespace file') expect(page).to have_content('add spaces in whitespace file')
expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') expect(page).not_to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage
expect(page).not_to have_selector('.flash-alert') expect(page).not_to have_selector('.flash-alert')
end end
...@@ -112,7 +112,7 @@ RSpec.describe 'Projects tree', :js do ...@@ -112,7 +112,7 @@ RSpec.describe 'Projects tree', :js do
it 'renders LFS badge on blob item' do it 'renders LFS badge on blob item' do
visit project_tree_path(project, File.join('master', 'files/lfs')) visit project_tree_path(project, File.join('master', 'files/lfs'))
expect(page).to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') expect(page).to have_selector('[data-qa-selector="label-lfs"]', text: 'LFS') # rubocop:disable QA/SelectorUsage
end end
end end
......
...@@ -13,7 +13,7 @@ RSpec.describe 'User creates a project', :js do ...@@ -13,7 +13,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do it 'creates a new project' do
visit(new_project_path) visit(new_project_path)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
fill_in(:project_name, with: 'Empty') fill_in(:project_name, with: 'Empty')
expect(page).to have_checked_field 'Initialize repository with a README' expect(page).to have_checked_field 'Initialize repository with a README'
...@@ -43,7 +43,7 @@ RSpec.describe 'User creates a project', :js do ...@@ -43,7 +43,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do it 'creates a new project' do
visit(new_project_path) visit(new_project_path)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
fill_in :project_name, with: 'A Subgroup Project' fill_in :project_name, with: 'A Subgroup Project'
fill_in :project_path, with: 'a-subgroup-project' fill_in :project_path, with: 'a-subgroup-project'
...@@ -72,7 +72,7 @@ RSpec.describe 'User creates a project', :js do ...@@ -72,7 +72,7 @@ RSpec.describe 'User creates a project', :js do
it 'creates a new project' do it 'creates a new project' do
visit(new_project_path) visit(new_project_path)
find('[data-qa-panel-name="blank_project"]').click find('[data-qa-panel-name="blank_project"]').click # rubocop:disable QA/SelectorUsage
fill_in :project_name, with: 'a-new-project' fill_in :project_name, with: 'a-new-project'
fill_in :project_path, with: 'a-new-project' fill_in :project_path, with: 'a-new-project'
......
...@@ -16,7 +16,7 @@ RSpec.describe 'Project' do ...@@ -16,7 +16,7 @@ RSpec.describe 'Project' do
shared_examples 'creates from template' do |template, sub_template_tab = nil| shared_examples 'creates from template' do |template, sub_template_tab = nil|
it "is created from template", :js do it "is created from template", :js do
find('[data-qa-panel-name="create_from_template"]').click find('[data-qa-panel-name="create_from_template"]').click # rubocop:disable QA/SelectorUsage
find(".project-template #{sub_template_tab}").click if sub_template_tab find(".project-template #{sub_template_tab}").click if sub_template_tab
find("label[for=#{template.name}]").click find("label[for=#{template.name}]").click
fill_in("project_name", with: template.name) fill_in("project_name", with: template.name)
...@@ -290,7 +290,7 @@ RSpec.describe 'Project' do ...@@ -290,7 +290,7 @@ RSpec.describe 'Project' do
it 'has working links to submodules' do it 'has working links to submodules' do
click_link('645f6c4c') click_link('645f6c4c')
expect(page).to have_selector('.qa-branches-select', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6') expect(page).to have_selector('.qa-branches-select', text: '645f6c4c82fd3f5e06f67134450a570b795e55a6') # rubocop:disable QA/SelectorUsage
end end
context 'for signed commit on default branch', :js do context 'for signed commit on default branch', :js do
......
import { GlToggle } from '@gitlab/ui'; import { GlSprintf, GlToggle } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils'; import { shallowMount, mount } from '@vue/test-utils';
import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue'; import projectFeatureSetting from '~/pages/projects/shared/permissions/components/project_feature_setting.vue';
import settingsPanel from '~/pages/projects/shared/permissions/components/settings_panel.vue'; import settingsPanel from '~/pages/projects/shared/permissions/components/settings_panel.vue';
...@@ -22,7 +22,7 @@ const defaultProps = { ...@@ -22,7 +22,7 @@ const defaultProps = {
operationsAccessLevel: 20, operationsAccessLevel: 20,
pagesAccessLevel: 10, pagesAccessLevel: 10,
analyticsAccessLevel: 20, analyticsAccessLevel: 20,
containerRegistryEnabled: true, containerRegistryAccessLevel: 20,
lfsEnabled: true, lfsEnabled: true,
emailsDisabled: false, emailsDisabled: false,
packagesEnabled: true, packagesEnabled: true,
...@@ -85,8 +85,10 @@ describe('Settings Panel', () => { ...@@ -85,8 +85,10 @@ describe('Settings Panel', () => {
const findBuildsAccessLevelInput = () => const findBuildsAccessLevelInput = () =>
wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]'); wrapper.find('[name="project[project_feature_attributes][builds_access_level]"]');
const findContainerRegistrySettings = () => wrapper.find({ ref: 'container-registry-settings' }); const findContainerRegistrySettings = () => wrapper.find({ ref: 'container-registry-settings' });
const findContainerRegistryEnabledInput = () => const findContainerRegistryPublicNoteGlSprintfComponent = () =>
wrapper.find('[name="project[container_registry_enabled]"]'); findContainerRegistrySettings().findComponent(GlSprintf);
const findContainerRegistryAccessLevelInput = () =>
wrapper.find('[name="project[project_feature_attributes][container_registry_access_level]"]');
const findPackageSettings = () => wrapper.find({ ref: 'package-settings' }); const findPackageSettings = () => wrapper.find({ ref: 'package-settings' });
const findPackagesEnabledInput = () => wrapper.find('[name="project[packages_enabled]"]'); const findPackagesEnabledInput = () => wrapper.find('[name="project[packages_enabled]"]');
const findPagesSettings = () => wrapper.find({ ref: 'pages-settings' }); const findPagesSettings = () => wrapper.find({ ref: 'pages-settings' });
...@@ -275,24 +277,38 @@ describe('Settings Panel', () => { ...@@ -275,24 +277,38 @@ describe('Settings Panel', () => {
it('should show the container registry public note if the visibility level is public and the registry is available', () => { it('should show the container registry public note if the visibility level is public and the registry is available', () => {
wrapper = mountComponent({ wrapper = mountComponent({
currentSettings: { visibilityLevel: visibilityOptions.PUBLIC }, currentSettings: {
visibilityLevel: visibilityOptions.PUBLIC,
containerRegistryAccessLevel: featureAccessLevel.EVERYONE,
},
registryAvailable: true, registryAvailable: true,
}); });
expect(findContainerRegistrySettings().text()).toContain( expect(findContainerRegistryPublicNoteGlSprintfComponent().exists()).toBe(true);
'Note: the container registry is always visible when a project is public', expect(findContainerRegistryPublicNoteGlSprintfComponent().attributes('message')).toContain(
`Note: The container registry is always visible when a project is public and the container registry is set to '%{access_level_description}'`,
); );
}); });
it('should hide the container registry public note if the visibility level is public but the registry is private', () => {
wrapper = mountComponent({
currentSettings: {
visibilityLevel: visibilityOptions.PUBLIC,
containerRegistryAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
},
registryAvailable: true,
});
expect(findContainerRegistryPublicNoteGlSprintfComponent().exists()).toBe(false);
});
it('should hide the container registry public note if the visibility level is private and the registry is available', () => { it('should hide the container registry public note if the visibility level is private and the registry is available', () => {
wrapper = mountComponent({ wrapper = mountComponent({
currentSettings: { visibilityLevel: visibilityOptions.PRIVATE }, currentSettings: { visibilityLevel: visibilityOptions.PRIVATE },
registryAvailable: true, registryAvailable: true,
}); });
expect(findContainerRegistrySettings().text()).not.toContain( expect(findContainerRegistryPublicNoteGlSprintfComponent().exists()).toBe(false);
'Note: the container registry is always visible when a project is public',
);
}); });
it('should enable the container registry input when the repository is enabled', () => { it('should enable the container registry input when the repository is enabled', () => {
...@@ -301,7 +317,7 @@ describe('Settings Panel', () => { ...@@ -301,7 +317,7 @@ describe('Settings Panel', () => {
registryAvailable: true, registryAvailable: true,
}); });
expect(findContainerRegistryEnabledInput().props('disabled')).toBe(false); expect(findContainerRegistryAccessLevelInput().props('disabledInput')).toBe(false);
}); });
it('should disable the container registry input when the repository is disabled', () => { it('should disable the container registry input when the repository is disabled', () => {
...@@ -310,7 +326,7 @@ describe('Settings Panel', () => { ...@@ -310,7 +326,7 @@ describe('Settings Panel', () => {
registryAvailable: true, registryAvailable: true,
}); });
expect(findContainerRegistryEnabledInput().props('disabled')).toBe(true); expect(findContainerRegistryAccessLevelInput().props('disabledInput')).toBe(true);
}); });
it('has label for the toggle', () => { it('has label for the toggle', () => {
...@@ -319,7 +335,7 @@ describe('Settings Panel', () => { ...@@ -319,7 +335,7 @@ describe('Settings Panel', () => {
registryAvailable: true, registryAvailable: true,
}); });
expect(findContainerRegistrySettings().findComponent(GlToggle).props('label')).toBe( expect(findContainerRegistryAccessLevelInput().props('label')).toBe(
settingsPanel.i18n.containerRegistryLabel, settingsPanel.i18n.containerRegistryLabel,
); );
}); });
......
# frozen_string_literal: true
require 'fast_spec_helper'
require_relative '../../../../rubocop/cop/qa/selector_usage'
RSpec.describe RuboCop::Cop::QA::SelectorUsage do
subject(:cop) { described_class.new }
shared_examples 'non-qa file usage' do
it 'reports an offense' do
expect_offense(<<-RUBY)
find('#{selector}').click
#{'^' * (selector.size + 2)} Do not use `#{selector}` as this is reserved for the end-to-end specs. Use a different selector or a data-testid instead.
RUBY
end
end
context 'in a QA file' do
before do
allow(cop).to receive(:in_qa_file?).and_return(true)
end
it 'has no error' do
expect_no_offenses(<<-RUBY)
has_element?('[data-qa-selector="my_selector"]')
RUBY
end
end
context 'outside of QA' do
before do
allow(cop).to receive(:in_qa_file?).and_return(false)
allow(cop).to receive(:in_spec?).and_return(true)
end
context 'data-qa-selector' do
let(:selector) { '[data-qa-selector="my_selector"]' }
it_behaves_like 'non-qa file usage'
end
context 'qa class' do
let(:selector) { '.qa-selector' }
it_behaves_like 'non-qa file usage'
end
end
end
...@@ -308,7 +308,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re ...@@ -308,7 +308,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
let(:reply_id) { find("#{comments_selector} .note:last-of-type", match: :first)['data-note-id'] } let(:reply_id) { find("#{comments_selector} .note:last-of-type", match: :first)['data-note-id'] }
it 'can be replied to after resolving' do it 'can be replied to after resolving' do
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
wait_for_requests wait_for_requests
refresh refresh
...@@ -320,7 +320,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re ...@@ -320,7 +320,7 @@ RSpec.shared_examples 'thread comments for issue, epic and merge request' do |re
it 'shows resolved thread when toggled' do it 'shows resolved thread when toggled' do
submit_reply('a') submit_reply('a')
find('button[data-qa-selector="resolve_discussion_button"]').click find('button[data-qa-selector="resolve_discussion_button"]').click # rubocop:disable QA/SelectorUsage
wait_for_requests wait_for_requests
expect(page).to have_selector(".note-row-#{note_id}", visible: true) expect(page).to have_selector(".note-row-#{note_id}", visible: true)
......
...@@ -14,7 +14,7 @@ RSpec.shared_examples 'packages list' do |check_project_name: false| ...@@ -14,7 +14,7 @@ RSpec.shared_examples 'packages list' do |check_project_name: false|
end end
def package_table_row(index) def package_table_row(index)
page.all("#{packages_table_selector} > [data-qa-selector=\"package_row\"]")[index].text page.all("#{packages_table_selector} > [data-qa-selector=\"package_row\"]")[index].text # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -92,7 +92,7 @@ RSpec.shared_examples 'shared package sorting' do ...@@ -92,7 +92,7 @@ RSpec.shared_examples 'shared package sorting' do
end end
def packages_table_selector def packages_table_selector
'[data-qa-selector="packages-table"]' '[data-qa-selector="packages-table"]' # rubocop:disable QA/SelectorUsage
end end
def click_sort_option(option, ascending) def click_sort_option(option, ascending)
......
...@@ -23,7 +23,7 @@ RSpec.shared_examples 'Deploy keys with protected branches' do ...@@ -23,7 +23,7 @@ RSpec.shared_examples 'Deploy keys with protected branches' do
find(".js-allowed-to-push").click find(".js-allowed-to-push").click
wait_for_requests wait_for_requests
within('.qa-allowed-to-push-dropdown') do within('.qa-allowed-to-push-dropdown') do # rubocop:disable QA/SelectorUsage
dropdown_headers = page.all('.dropdown-header').map(&:text) dropdown_headers = page.all('.dropdown-header').map(&:text)
expect(dropdown_headers).to contain_exactly(*all_dropdown_sections) expect(dropdown_headers).to contain_exactly(*all_dropdown_sections)
...@@ -38,7 +38,7 @@ RSpec.shared_examples 'Deploy keys with protected branches' do ...@@ -38,7 +38,7 @@ RSpec.shared_examples 'Deploy keys with protected branches' do
find(".js-allowed-to-merge").click find(".js-allowed-to-merge").click
wait_for_requests wait_for_requests
within('.qa-allowed-to-merge-dropdown') do within('.qa-allowed-to-merge-dropdown') do # rubocop:disable QA/SelectorUsage
dropdown_headers = page.all('.dropdown-header').map(&:text) dropdown_headers = page.all('.dropdown-header').map(&:text)
expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys) expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys)
...@@ -68,7 +68,7 @@ RSpec.shared_examples 'Deploy keys with protected branches' do ...@@ -68,7 +68,7 @@ RSpec.shared_examples 'Deploy keys with protected branches' do
find(".js-allowed-to-push").click find(".js-allowed-to-push").click
wait_for_requests wait_for_requests
within('.qa-allowed-to-push-dropdown') do within('.qa-allowed-to-push-dropdown') do # rubocop:disable QA/SelectorUsage
dropdown_headers = page.all('.dropdown-header').map(&:text) dropdown_headers = page.all('.dropdown-header').map(&:text)
expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys) expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys)
......
...@@ -9,7 +9,7 @@ end ...@@ -9,7 +9,7 @@ end
RSpec.shared_examples "it has an RSS button with current_user's feed token" do RSpec.shared_examples "it has an RSS button with current_user's feed token" do
it "shows the RSS button with current_user's feed token" do it "shows the RSS button with current_user's feed token" do
expect(page) expect(page)
.to have_css("a:has(.qa-rss-icon)[href*='feed_token=#{user.feed_token}']") .to have_css("a:has(.qa-rss-icon)[href*='feed_token=#{user.feed_token}']") # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -22,6 +22,6 @@ end ...@@ -22,6 +22,6 @@ end
RSpec.shared_examples "it has an RSS button without a feed token" do RSpec.shared_examples "it has an RSS button without a feed token" do
it "shows the RSS button without a feed token" do it "shows the RSS button without a feed token" do
expect(page) expect(page)
.to have_css("a:has(.qa-rss-icon):not([href*='feed_token'])") .to have_css("a:has(.qa-rss-icon):not([href*='feed_token'])") # rubocop:disable QA/SelectorUsage
end end
end end
...@@ -91,7 +91,7 @@ RSpec.shared_examples 'variable list' do ...@@ -91,7 +91,7 @@ RSpec.shared_examples 'variable list' do
end end
page.within('#add-ci-variable') do page.within('#add-ci-variable') do
find('[data-qa-selector="ci_variable_key_field"] input').set('new_key') find('[data-qa-selector="ci_variable_key_field"] input').set('new_key') # rubocop:disable QA/SelectorUsage
click_button('Update variable') click_button('Update variable')
end end
...@@ -173,7 +173,7 @@ RSpec.shared_examples 'variable list' do ...@@ -173,7 +173,7 @@ RSpec.shared_examples 'variable list' do
click_button('Add variable') click_button('Add variable')
page.within('#add-ci-variable') do page.within('#add-ci-variable') do
find('[data-qa-selector="ci_variable_key_field"] input').set('empty_mask_key') find('[data-qa-selector="ci_variable_key_field"] input').set('empty_mask_key') # rubocop:disable QA/SelectorUsage
find('[data-testid="ci-variable-protected-checkbox"]').click find('[data-testid="ci-variable-protected-checkbox"]').click
find('[data-testid="ci-variable-masked-checkbox"]').click find('[data-testid="ci-variable-masked-checkbox"]').click
...@@ -286,8 +286,8 @@ RSpec.shared_examples 'variable list' do ...@@ -286,8 +286,8 @@ RSpec.shared_examples 'variable list' do
wait_for_requests wait_for_requests
page.within('#add-ci-variable') do page.within('#add-ci-variable') do
find('[data-qa-selector="ci_variable_key_field"] input').set(key) find('[data-qa-selector="ci_variable_key_field"] input').set(key) # rubocop:disable QA/SelectorUsage
find('[data-qa-selector="ci_variable_value_field"]').set(value) if value.present? find('[data-qa-selector="ci_variable_value_field"]').set(value) if value.present? # rubocop:disable QA/SelectorUsage
find('[data-testid="ci-variable-protected-checkbox"]').click if protected find('[data-testid="ci-variable-protected-checkbox"]').click if protected
find('[data-testid="ci-variable-masked-checkbox"]').click if masked find('[data-testid="ci-variable-masked-checkbox"]').click if masked
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'User views AsciiDoc page with includes' do RSpec.shared_examples 'User views AsciiDoc page with includes' do
let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' } let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' } # rubocop:disable QA/SelectorUsage
let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')} let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')}
let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") } let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") }
......
...@@ -19,9 +19,9 @@ RSpec.describe 'admin/sessions/new.html.haml' do ...@@ -19,9 +19,9 @@ RSpec.describe 'admin/sessions/new.html.haml' do
it 'shows enter password form' do it 'shows enter password form' do
render render
expect(rendered).to have_selector('[data-qa-selector="sign_in_tab"]') expect(rendered).to have_selector('[data-qa-selector="sign_in_tab"]') # rubocop:disable QA/SelectorUsage
expect(rendered).to have_css('#login-pane.active') expect(rendered).to have_css('#login-pane.active')
expect(rendered).to have_selector('[data-qa-selector="password_field"]') expect(rendered).to have_selector('[data-qa-selector="password_field"]') # rubocop:disable QA/SelectorUsage
end end
it 'warns authentication not possible if password not set' do it 'warns authentication not possible if password not set' do
...@@ -60,7 +60,7 @@ RSpec.describe 'admin/sessions/new.html.haml' do ...@@ -60,7 +60,7 @@ RSpec.describe 'admin/sessions/new.html.haml' do
it 'is shown when enabled' do it 'is shown when enabled' do
render render
expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
expect(rendered).to have_css('.login-box#ldapmain') expect(rendered).to have_css('.login-box#ldapmain')
expect(rendered).to have_field('LDAP Username') expect(rendered).to have_field('LDAP Username')
expect(rendered).not_to have_content('No authentication methods configured') expect(rendered).not_to have_content('No authentication methods configured')
...@@ -71,7 +71,7 @@ RSpec.describe 'admin/sessions/new.html.haml' do ...@@ -71,7 +71,7 @@ RSpec.describe 'admin/sessions/new.html.haml' do
render render
expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_field('LDAP Username') expect(rendered).not_to have_field('LDAP Username')
expect(rendered).to have_content('No authentication methods configured') expect(rendered).to have_content('No authentication methods configured')
end end
......
...@@ -48,7 +48,7 @@ RSpec.describe 'devise/sessions/new' do ...@@ -48,7 +48,7 @@ RSpec.describe 'devise/sessions/new' do
render render
expect(rendered).to have_selector('.new-session-tabs') expect(rendered).to have_selector('.new-session-tabs')
expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') expect(rendered).to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
expect(rendered).to have_field('LDAP Username') expect(rendered).to have_field('LDAP Username')
end end
...@@ -58,7 +58,7 @@ RSpec.describe 'devise/sessions/new' do ...@@ -58,7 +58,7 @@ RSpec.describe 'devise/sessions/new' do
render render
expect(rendered).to have_content('No authentication methods configured') expect(rendered).to have_content('No authentication methods configured')
expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') expect(rendered).not_to have_selector('[data-qa-selector="ldap_tab"]') # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_field('LDAP Username') expect(rendered).not_to have_field('LDAP Username')
end end
end end
......
...@@ -9,8 +9,8 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do ...@@ -9,8 +9,8 @@ RSpec.describe 'groups/settings/_transfer.html.haml' do
render 'groups/settings/transfer', group: group render 'groups/settings/transfer', group: group
expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' expect(rendered).to have_selector '[data-qa-selector="select_group_dropdown"]' # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' expect(rendered).not_to have_selector '[data-qa-selector="select_group_dropdown"][disabled]' # rubocop:disable QA/SelectorUsage
expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]' expect(rendered).not_to have_selector '[data-testid="group-to-transfer-has-linked-subscription-alert"]'
end end
end end
......
...@@ -40,7 +40,7 @@ module Tooling ...@@ -40,7 +40,7 @@ module Tooling
%r{\A(ee/)?config/feature_flags/} => :feature_flag, %r{\A(ee/)?config/feature_flags/} => :feature_flag,
%r{\Adoc/development/usage_ping/dictionary\.md\z} => [:docs, :product_intelligence], %r{\Adoc/development/usage_ping/dictionary\.md\z} => [:docs, :product_intelligence],
%r{\Adoc/.*(\.(md|png|gif|jpg))\z} => :docs, %r{\Adoc/.*(\.(md|png|gif|jpg|yml))\z} => :docs,
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs, %r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
%r{\Adata/whats_new/} => :docs, %r{\Adata/whats_new/} => :docs,
......
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