Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-21 21:10:20 +00:00
parent c742109766
commit 798e0b5920
35 changed files with 241 additions and 63 deletions

View File

@ -129,7 +129,7 @@ gem 'apollo_upload_server', '~> 2.1.0'
gem 'graphql-docs', '~> 2.1.0', group: [:development, :test] gem 'graphql-docs', '~> 2.1.0', group: [:development, :test]
gem 'graphlient', '~> 0.5.0' # Used by BulkImport feature (group::import) gem 'graphlient', '~> 0.5.0' # Used by BulkImport feature (group::import)
gem 'hashie' gem 'hashie', '~> 5.0.0'
# Disable strong_params so that Mash does not respond to :permitted? # Disable strong_params so that Mash does not respond to :permitted?
gem 'hashie-forbidden_attributes' gem 'hashie-forbidden_attributes'

View File

@ -259,7 +259,7 @@
{"name":"hana","version":"1.3.7","platform":"ruby","checksum":"5425db42d651fea08859811c29d20446f16af196308162894db208cac5ce9b0d"}, {"name":"hana","version":"1.3.7","platform":"ruby","checksum":"5425db42d651fea08859811c29d20446f16af196308162894db208cac5ce9b0d"},
{"name":"hangouts-chat","version":"0.0.5","platform":"ruby","checksum":"bdbeb6c6e4abc98f395cb273f53b39911b3aa9e248fbbf063242b021ced8b6b6"}, {"name":"hangouts-chat","version":"0.0.5","platform":"ruby","checksum":"bdbeb6c6e4abc98f395cb273f53b39911b3aa9e248fbbf063242b021ced8b6b6"},
{"name":"hashdiff","version":"1.0.1","platform":"ruby","checksum":"2cd4d04f5080314ecc8403c4e2e00dbaa282dff395e2d031bc16c8d501bdd6db"}, {"name":"hashdiff","version":"1.0.1","platform":"ruby","checksum":"2cd4d04f5080314ecc8403c4e2e00dbaa282dff395e2d031bc16c8d501bdd6db"},
{"name":"hashie","version":"4.1.0","platform":"ruby","checksum":"7890dcb9ec18a4b66acec797018c73824b89cef5eb8cda36e8e8501845e87a09"}, {"name":"hashie","version":"5.0.0","platform":"ruby","checksum":"9d6c4e51f2a36d4616cbc8a322d619a162d8f42815a792596039fc95595603da"},
{"name":"hashie-forbidden_attributes","version":"0.1.1","platform":"ruby","checksum":"3a6ed37f3a314e4fb1dd1e2df6eb7721bcadd023a30bc0b951b2b5285a790fb2"}, {"name":"hashie-forbidden_attributes","version":"0.1.1","platform":"ruby","checksum":"3a6ed37f3a314e4fb1dd1e2df6eb7721bcadd023a30bc0b951b2b5285a790fb2"},
{"name":"health_check","version":"3.1.0","platform":"ruby","checksum":"10146508237dc54ed7e24c292d8ba7fb8f9590cf26c66e325b947438c4103b57"}, {"name":"health_check","version":"3.1.0","platform":"ruby","checksum":"10146508237dc54ed7e24c292d8ba7fb8f9590cf26c66e325b947438c4103b57"},
{"name":"heapy","version":"0.2.0","platform":"ruby","checksum":"74141e845d61ffc7c1e8bf8b127c8cf94544ec7a1181aec613288682543585ea"}, {"name":"heapy","version":"0.2.0","platform":"ruby","checksum":"74141e845d61ffc7c1e8bf8b127c8cf94544ec7a1181aec613288682543585ea"},

View File

@ -709,7 +709,7 @@ GEM
hana (1.3.7) hana (1.3.7)
hangouts-chat (0.0.5) hangouts-chat (0.0.5)
hashdiff (1.0.1) hashdiff (1.0.1)
hashie (4.1.0) hashie (5.0.0)
hashie-forbidden_attributes (0.1.1) hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0) hashie (>= 3.0)
health_check (3.1.0) health_check (3.1.0)
@ -1661,7 +1661,7 @@ DEPENDENCIES
haml_lint (~> 0.40.0) haml_lint (~> 0.40.0)
hamlit (~> 2.15.0) hamlit (~> 2.15.0)
hangouts-chat (~> 0.0.5) hangouts-chat (~> 0.0.5)
hashie hashie (~> 5.0.0)
hashie-forbidden_attributes hashie-forbidden_attributes
health_check (~> 3.0) health_check (~> 3.0)
html-pipeline (~> 2.13.2) html-pipeline (~> 2.13.2)

View File

@ -109,10 +109,11 @@ export default {
writePackageRegistryHelp: s__( writePackageRegistryHelp: s__(
'DeployTokens|Allows read and write access to the package registry.', 'DeployTokens|Allows read and write access to the package registry.',
), ),
createTokenFailedAlert: s__('DeployTokens|Failed to create a new deployment token'),
}, },
computed: { computed: {
formattedExpiryDate() { formattedExpiryDate() {
return formatDate(this.expiresAt, 'yyyy-mm-dd'); return this.expiresAt ? formatDate(this.expiresAt, 'yyyy-mm-dd') : '';
}, },
newTokenCreatedMessage() { newTokenCreatedMessage() {
return this.tokenType === 'group' return this.tokenType === 'group'
@ -129,6 +130,9 @@ export default {
name: this.name, name: this.name,
read_repository: this.readRepository, read_repository: this.readRepository,
read_registry: this.readRegistry, read_registry: this.readRegistry,
write_registry: this.writeRegistry,
read_package_registry: this.readPackageRegistry,
write_package_registry: this.writePackageRegistry,
username: this.username, username: this.username,
}, },
}) })
@ -142,7 +146,8 @@ export default {
}) })
.catch((error) => { .catch((error) => {
createAlert({ createAlert({
message: error.response.data.message, message:
error?.response?.data?.message || this.$options.translations.createTokenFailedAlert,
}); });
}); });
}, },

View File

@ -1,7 +1,6 @@
<script> <script>
import { GlLink, GlTooltipDirective } from '@gitlab/ui'; import { GlLink, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago'; import timeagoMixin from '~/vue_shared/mixins/timeago';
import { import {
MANUAL_DEPLOY, MANUAL_DEPLOY,
@ -18,7 +17,7 @@ export default {
components: { components: {
GlLink, GlLink,
MemoryUsage: () => import('./memory_usage.vue'), MemoryUsage: () => import('./memory_usage.vue'),
TooltipOnTruncate, GlTruncate,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
@ -74,16 +73,19 @@ export default {
<div class="js-deployment-info deployment-info"> <div class="js-deployment-info deployment-info">
<template v-if="hasDeploymentMeta"> <template v-if="hasDeploymentMeta">
<span>{{ deployedText }}</span> <span>{{ deployedText }}</span>
<tooltip-on-truncate :title="deployment.name" truncate-target="child" class="label-truncate"> <gl-link
<gl-link :href="deployment.url"
:href="deployment.url" target="_blank"
target="_blank" rel="noopener noreferrer nofollow"
rel="noopener noreferrer nofollow" class="js-deploy-meta gl-font-sm gl-pb-1"
class="js-deploy-meta gl-font-sm gl-pb-1" >
> <gl-truncate
{{ deployment.name }} class="js-deploy-env-name"
</gl-link> :text="deployment.name"
</tooltip-on-truncate> position="middle"
with-tooltip
/>
</gl-link>
</template> </template>
<span <span
v-if="hasDeploymentTime" v-if="hasDeploymentTime"

View File

@ -72,7 +72,7 @@ export default {
:display="appButtonText" :display="appButtonText"
:link="deploymentExternalUrl" :link="deploymentExternalUrl"
size="small" size="small"
css-class="deploy-link js-deploy-url inline gl-ml-3" css-class="deploy-link js-deploy-url inline"
/> />
<modal-copy-button <modal-copy-button
v-else v-else
@ -116,7 +116,7 @@ export default {
:display="appButtonText" :display="appButtonText"
:link="deploymentExternalUrl" :link="deploymentExternalUrl"
size="small" size="small"
css-class="deploy-link js-deploy-url inline gl-ml-3" css-class="deploy-link js-deploy-url inline"
/> />
<modal-copy-button <modal-copy-button
v-else v-else

View File

@ -391,6 +391,10 @@ $tabs-holder-z-index: 250;
text-overflow: ellipsis; text-overflow: ellipsis;
min-width: 100px; min-width: 100px;
display: grid;
grid-template-columns: max-content minmax(0, max-content) max-content;
grid-gap: $gl-spacing-scale-2;
@include media-breakpoint-up(xs) { @include media-breakpoint-up(xs) {
min-width: 0; min-width: 0;
max-width: 100%; max-width: 100%;
@ -404,6 +408,7 @@ $tabs-holder-z-index: 250;
.deploy-heading, .deploy-heading,
.merge-train-position-indicator { .merge-train-position-indicator {
padding: $gl-padding-8;
@include media-breakpoint-up(md) { @include media-breakpoint-up(md) {
padding: $gl-padding-8 $gl-padding; padding: $gl-padding-8 $gl-padding;
} }
@ -637,7 +642,6 @@ $tabs-holder-z-index: 250;
word-break: break-all; word-break: break-all;
} }
.deploy-link,
.label-branch { .label-branch {
&.label-truncate { &.label-truncate {
// NOTE: This selector targets its children because some of the HTML comes from // NOTE: This selector targets its children because some of the HTML comes from

View File

@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Troubleshooting topic type # Troubleshooting topic type
Troubleshooting topics should be the last topics on a page. Troubleshooting topics should be the final topics on a page.
If a page has more than five troubleshooting topics, put the content on a separate page that has troubleshooting information exclusively. Name the page `Troubleshooting <feature>` If a page has more than five troubleshooting topics, put the content on a separate page that has troubleshooting information exclusively. Name the page `Troubleshooting <feature>`
and in the left nav, use the word `Troubleshooting` only. and in the left nav, use the word `Troubleshooting` only.
@ -54,3 +54,13 @@ For the heading of a **Troubleshooting reference** topic:
- Use fewer than 70 characters. - Use fewer than 70 characters.
If you do not put the full error in the title, include it in the body text. If you do not put the full error in the title, include it in the body text.
## Rails console write functions
If the troubleshooting suggestion includes a function that changes data on the GitLab instance,
add the following warning:
```markdown
WARNING:
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
```

View File

@ -32,7 +32,7 @@ For error tracking to work, you need two pieces:
### Deploying Sentry ### Deploying Sentry
You can sign up to the cloud hosted [Sentry](https://sentry.io), deploy your own [on-premise instance](https://github.com/getsentry/onpremise/), or use GitLab to [install Sentry to a Kubernetes cluster](../user/infrastructure/clusters/manage/management_project_applications/sentry.md). You can sign up to the cloud hosted [Sentry](https://sentry.io) or deploy your own [on-premise instance](https://github.com/getsentry/onpremise/).
### Enabling Sentry ### Enabling Sentry
@ -156,11 +156,11 @@ You can find the feature configuration at **Settings > Monitor > Error Tracking*
1. Select **GitLab** as the error tracking backend for your project: 1. Select **GitLab** as the error tracking backend for your project:
![Error Tracking Settings](img/error_tracking_setting_v14_3.png) ![Error Tracking Settings](img/error_tracking_setting_v14_3.png)
1. Select **Save changes**. After page reload you should see a text field with the DSN string. Copy it. 1. Select **Save changes**. After page reload you should see a text field with the DSN string. Copy it.
![Error Tracking Settings DSN](img/error_tracking_setting_dsn_v14_4.png) ![Error Tracking Settings DSN](img/error_tracking_setting_dsn_v14_4.png)
1. Take the DSN from the previous step and configure your Sentry SDK with it. Errors are now 1. Take the DSN from the previous step and configure your Sentry SDK with it. Errors are now
reported to the GitLab collector and are visible in the [GitLab UI](#error-tracking-list). reported to the GitLab collector and are visible in the [GitLab UI](#error-tracking-list).

View File

@ -103,7 +103,6 @@ The [built-in supported applications](https://gitlab.com/gitlab-org/project-temp
- [GitLab Runner](../infrastructure/clusters/manage/management_project_applications/runner.md) - [GitLab Runner](../infrastructure/clusters/manage/management_project_applications/runner.md)
- [Ingress](../infrastructure/clusters/manage/management_project_applications/ingress.md) - [Ingress](../infrastructure/clusters/manage/management_project_applications/ingress.md)
- [Prometheus](../infrastructure/clusters/manage/management_project_applications/prometheus.md) - [Prometheus](../infrastructure/clusters/manage/management_project_applications/prometheus.md)
- [Sentry](../infrastructure/clusters/manage/management_project_applications/sentry.md)
- [Vault](../infrastructure/clusters/manage/management_project_applications/vault.md) - [Vault](../infrastructure/clusters/manage/management_project_applications/vault.md)
Each application has an `applications/{app}/values.yaml` file. Each application has an `applications/{app}/values.yaml` file.

View File

@ -13309,6 +13309,9 @@ msgstr ""
msgid "DeployTokens|Expires" msgid "DeployTokens|Expires"
msgstr "" msgstr ""
msgid "DeployTokens|Failed to create a new deployment token"
msgstr ""
msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group." msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
msgstr "" msgstr ""

View File

@ -6,7 +6,7 @@ module QA
RSpec.describe 'Plan' do RSpec.describe 'Plan' do
include Support::API include Support::API
describe 'Issue' do describe 'Issue', product_group: :project_management do
let(:issue) do let(:issue) do
Resource::Issue.fabricate_via_api! Resource::Issue.fabricate_via_api!
end end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :orchestrated, :smtp, :reliable do RSpec.describe 'Plan', :orchestrated, :smtp, :reliable, product_group: :project_management do
describe 'Email Notification' do describe 'Email Notification' do
include Support::API include Support::API

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
let!(:user) do let!(:user) do
Resource::User.fabricate_via_api! do |user| Resource::User.fabricate_via_api! do |user|
user.name = "QA User <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;" user.name = "QA User <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;"

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'collapse comments in issue discussions' do describe 'collapse comments in issue discussions' do
let(:my_first_reply) { 'My first reply' } let(:my_first_reply) { 'My first reply' }
let(:one_reply) { '1 reply' } let(:one_reply) { '1 reply' }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Issue comments' do describe 'Issue comments' do
before do before do
Flow::Login.sign_in Flow::Login.sign_in

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :smoke do RSpec.describe 'Plan', :smoke, product_group: :project_management do
describe 'Issue creation' do describe 'Issue creation' do
let(:project) { Resource::Project.fabricate_via_api! } let(:project) { Resource::Project.fabricate_via_api! }
let(:closed_issue) { Resource::Issue.fabricate_via_api! { |issue| issue.project = project } } let(:closed_issue) { Resource::Issue.fabricate_via_api! { |issue| issue.project = project } }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Custom issue templates' do describe 'Custom issue templates' do
let(:template_name) { 'custom_issue_template' } let(:template_name) { 'custom_issue_template' }
let(:template_content) { 'This is a custom issue template test' } let(:template_content) { 'This is a custom issue template test' }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Issues list' do describe 'Issues list' do
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'filter issue comments activities' do describe 'filter issue comments activities' do
before do before do
Flow::Login.sign_in Flow::Login.sign_in

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'issue suggestions' do describe 'issue suggestions' do
let(:issue_title) { 'Issue Lists are awesome' } let(:issue_title) { 'Issue Lists are awesome' }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :smoke do RSpec.describe 'Plan', :smoke, product_group: :project_management do
describe 'mention' do describe 'mention' do
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) } let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:project) do let(:project) do

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan' do RSpec.describe 'Plan', product_group: :project_management do
describe 'Assignees' do describe 'Assignees' do
let(:user1) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) } let(:user1) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:user2) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) } let(:user2) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_2, Runtime::Env.gitlab_qa_password_2) }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Issue board focus mode' do describe 'Issue board focus mode' do
let(:project) do let(:project) do
QA::Resource::Project.fabricate_via_api! do |project| QA::Resource::Project.fabricate_via_api! do |project|

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Milestones' do describe 'Milestones' do
include Support::Dates include Support::Dates

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Group milestone' do describe 'Group milestone' do
include Support::Dates include Support::Dates

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Project milestone' do describe 'Project milestone' do
include Support::Dates include Support::Dates

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :reliable do RSpec.describe 'Plan', :reliable, product_group: :project_management do
describe 'Related issues' do describe 'Related issues' do
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
module QA module QA
RSpec.describe 'Plan', :transient do RSpec.describe 'Plan', :transient, product_group: :project_management do
describe 'Discussion comments transient bugs' do describe 'Discussion comments transient bugs' do
let(:user1) do let(:user1) do
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)

View File

@ -1,4 +1,5 @@
#!/bin/sh #!/usr/bin/env bash
set -euo pipefail
# #
# This script runs the LicenseFinder gem to verify that all licenses are # This script runs the LicenseFinder gem to verify that all licenses are
# compliant. However, bundler v2.2+ and LicenseFinder do not play well # compliant. However, bundler v2.2+ and LicenseFinder do not play well

View File

@ -18,6 +18,11 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
let(:build) { create(:ci_build, :with_deployment, environment: environment.name, pipeline: pipeline) } let(:build) { create(:ci_build, :with_deployment, environment: environment.name, pipeline: pipeline) }
let!(:deployment) { build.deployment } let!(:deployment) { build.deployment }
def assert_env_widget(text, env_name)
expect(find('.js-deploy-env-name')[:title]).to have_text(env_name)
expect(page).to have_content(text)
end
before do before do
merge_request.update!(merge_commit_sha: sha) merge_request.update!(merge_commit_sha: sha)
project.add_member(user, role) project.add_member(user, role)
@ -33,7 +38,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
visit project_merge_request_path(project, merge_request) visit project_merge_request_path(project, merge_request)
wait_for_requests wait_for_requests
expect(page).to have_content("Deployed to #{environment.name}") assert_env_widget("Deployed to", environment.name)
expect(find('.js-deploy-time')['title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium)) expect(find('.js-deploy-time')['title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
end end
@ -47,8 +52,8 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
wait_for_requests wait_for_requests
expect(page).to have_selector('.js-deployment-info', count: 1) expect(page).to have_selector('.js-deployment-info', count: 1)
expect(page).to have_content("#{environment.name}") expect(find('.js-deploy-env-name')[:title]).to have_text(environment.name)
expect(page).not_to have_content("#{environment2.name}") expect(find('.js-deploy-env-name')[:title]).not_to have_text(environment2.name)
end end
end end
end end
@ -62,7 +67,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
visit project_merge_request_path(project, merge_request) visit project_merge_request_path(project, merge_request)
wait_for_requests wait_for_requests
expect(page).to have_content("Failed to deploy to #{environment.name}") assert_env_widget("Failed to deploy to", environment.name)
expect(page).not_to have_css('.js-deploy-time') expect(page).not_to have_css('.js-deploy-time')
end end
end end
@ -76,7 +81,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
visit project_merge_request_path(project, merge_request) visit project_merge_request_path(project, merge_request)
wait_for_requests wait_for_requests
expect(page).to have_content("Deploying to #{environment.name}") assert_env_widget("Deploying to", environment.name)
expect(page).not_to have_css('.js-deploy-time') expect(page).not_to have_css('.js-deploy-time')
end end
end end
@ -89,7 +94,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
visit project_merge_request_path(project, merge_request) visit project_merge_request_path(project, merge_request)
wait_for_requests wait_for_requests
expect(page).to have_content("Will deploy to #{environment.name}") assert_env_widget("Will deploy to", environment.name)
expect(page).not_to have_css('.js-deploy-time') expect(page).not_to have_css('.js-deploy-time')
end end
end end
@ -103,7 +108,7 @@ RSpec.describe 'Merge request > User sees deployment widget', :js do
visit project_merge_request_path(project, merge_request) visit project_merge_request_path(project, merge_request)
wait_for_requests wait_for_requests
expect(page).to have_content("Canceled deployment to #{environment.name}") assert_env_widget("Canceled deployment to", environment.name)
expect(page).not_to have_css('.js-deploy-time') expect(page).not_to have_css('.js-deploy-time')
end end
end end

View File

@ -64,7 +64,8 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
wait_for_requests wait_for_requests
page.within('.js-pre-deployment') do page.within('.js-pre-deployment') do
expect(page).to have_content("Deployed to #{environment.name}") expect(find('.js-deploy-env-name')[:title]).to have_text(environment.name)
expect(page).to have_content("Deployed to")
expect(find('.js-deploy-url')[:href]).to include(environment.formatted_external_url) expect(find('.js-deploy-url')[:href]).to include(environment.formatted_external_url)
end end
end end

View File

@ -59,6 +59,19 @@ describe('New Deploy Token', () => {
expect(checkbox.text()).toBe('read_registry'); expect(checkbox.text()).toBe('read_registry');
}); });
function submitTokenThenCheck() {
wrapper.findAllComponents(GlButton).at(0).vm.$emit('click');
return waitForPromises()
.then(() => nextTick())
.then(() => {
const [tokenUsername, tokenValue] = wrapper.findAllComponents(GlFormInputGroup).wrappers;
expect(tokenUsername.props('value')).toBe('test token username');
expect(tokenValue.props('value')).toBe('test token');
});
}
it('should make a request to create a token on submit', () => { it('should make a request to create a token on submit', () => {
const mockAxios = new MockAdapter(axios); const mockAxios = new MockAdapter(axios);
@ -72,9 +85,18 @@ describe('New Deploy Token', () => {
const datepicker = wrapper.findAllComponents(GlDatepicker).at(0); const datepicker = wrapper.findAllComponents(GlDatepicker).at(0);
datepicker.vm.$emit('input', date); datepicker.vm.$emit('input', date);
const [readRepo, readRegistry] = wrapper.findAllComponents(GlFormCheckbox).wrappers; const [
readRepo,
readRegistry,
writeRegistry,
readPackageRegistry,
writePackageRegistry,
] = wrapper.findAllComponents(GlFormCheckbox).wrappers;
readRepo.vm.$emit('input', true); readRepo.vm.$emit('input', true);
readRegistry.vm.$emit('input', true); readRegistry.vm.$emit('input', true);
writeRegistry.vm.$emit('input', true);
readPackageRegistry.vm.$emit('input', true);
writePackageRegistry.vm.$emit('input', true);
mockAxios mockAxios
.onPost(createNewTokenPath, { .onPost(createNewTokenPath, {
@ -84,20 +106,47 @@ describe('New Deploy Token', () => {
username: 'test username', username: 'test username',
read_repository: true, read_repository: true,
read_registry: true, read_registry: true,
write_registry: true,
read_package_registry: true,
write_package_registry: true,
}, },
}) })
.replyOnce(200, { username: 'test token username', token: 'test token' }); .replyOnce(200, { username: 'test token username', token: 'test token' });
wrapper.findAllComponents(GlButton).at(0).vm.$emit('click'); return submitTokenThenCheck();
});
return waitForPromises() it('should request a token without an expiration date', () => {
.then(() => nextTick()) const mockAxios = new MockAdapter(axios);
.then(() => {
const [tokenUsername, tokenValue] = wrapper.findAllComponents(GlFormInputGroup).wrappers;
expect(tokenUsername.props('value')).toBe('test token username'); const formInputs = wrapper.findAllComponents(GlFormInput);
expect(tokenValue.props('value')).toBe('test token'); const name = formInputs.at(0);
}); const username = formInputs.at(2);
name.vm.$emit('input', 'test never expire name');
username.vm.$emit('input', 'test never expire username');
const [, , , readPackageRegistry, writePackageRegistry] = wrapper.findAllComponents(
GlFormCheckbox,
).wrappers;
readPackageRegistry.vm.$emit('input', true);
writePackageRegistry.vm.$emit('input', true);
mockAxios
.onPost(createNewTokenPath, {
deploy_token: {
name: 'test never expire name',
expires_at: null,
username: 'test never expire username',
read_repository: false,
read_registry: false,
write_registry: false,
read_package_registry: true,
write_package_registry: true,
},
})
.replyOnce(200, { username: 'test token username', token: 'test token' });
return submitTokenThenCheck();
}); });
}); });
}); });

View File

@ -0,0 +1,42 @@
import { mount } from '@vue/test-utils';
import { GlTruncate, GlLink } from '@gitlab/ui';
import DeploymentInfo from '~/vue_merge_request_widget/components/deployment/deployment_info.vue';
import { deploymentMockData } from './deployment_mock_data';
// This component is well covered in ./deployment_spec.js
// more component-specific tests are added below
describe('Deployment Info component', () => {
let wrapper;
const defaultDeploymentInfoOptions = {
computedDeploymentStatus: 'computed deployment status',
deployment: deploymentMockData,
showMetrics: false,
};
const factory = (options = {}) => {
const componentProps = { ...defaultDeploymentInfoOptions, ...options };
const componentOptions = { propsData: componentProps };
wrapper = mount(DeploymentInfo, componentOptions);
};
beforeEach(() => {
factory();
});
it('should render gl-truncate for environment name', () => {
const envNameComponent = wrapper.findComponent(GlTruncate);
expect(envNameComponent.exists()).toBe(true, 'We should use gl-truncate for environment name');
expect(envNameComponent.props()).toEqual({
text: deploymentMockData.name,
withTooltip: true,
position: 'middle',
});
});
it('should have a link with a correct href to deployed environment', () => {
const envLink = wrapper.findComponent(GlLink);
expect(envLink.exists()).toBe(true, 'We should have gl-link pointing to deployed environment');
expect(envLink.attributes().href).toBe(deploymentMockData.url);
});
});

View File

@ -125,6 +125,63 @@ RSpec.shared_context 'ProjectPolicyTable context' do
:private | :disabled | :anonymous | nil | 0 :private | :disabled | :anonymous | nil | 0
end end
# This table is based on permission_table_for_guest_feature_access,
# but takes into account note confidentiality. It is required on the context
# to have one regular note and one confidential note.
#
# project_level, :feature_access_level, :membership, :admin_mode, :expected_count
def permission_table_for_notes_feature_access
:public | :enabled | :admin | true | 2
:public | :enabled | :admin | false | 1
:public | :enabled | :reporter | nil | 2
:public | :enabled | :guest | nil | 1
:public | :enabled | :non_member | nil | 1
:public | :enabled | :anonymous | nil | 1
:public | :private | :admin | true | 2
:public | :private | :admin | false | 0
:public | :private | :reporter | nil | 2
:public | :private | :guest | nil | 1
:public | :private | :non_member | nil | 0
:public | :private | :anonymous | nil | 0
:public | :disabled | :reporter | nil | 0
:public | :disabled | :guest | nil | 0
:public | :disabled | :non_member | nil | 0
:public | :disabled | :anonymous | nil | 0
:internal | :enabled | :admin | true | 2
:internal | :enabled | :admin | false | 1
:internal | :enabled | :reporter | nil | 2
:internal | :enabled | :guest | nil | 1
:internal | :enabled | :non_member | nil | 1
:internal | :enabled | :anonymous | nil | 0
:internal | :private | :admin | true | 2
:internal | :private | :admin | false | 0
:internal | :private | :reporter | nil | 2
:internal | :private | :guest | nil | 1
:internal | :private | :non_member | nil | 0
:internal | :private | :anonymous | nil | 0
:internal | :disabled | :reporter | nil | 0
:internal | :disabled | :guest | nil | 0
:internal | :disabled | :non_member | nil | 0
:internal | :disabled | :anonymous | nil | 0
:private | :private | :admin | true | 2
:private | :private | :admin | false | 0
:private | :private | :reporter | nil | 2
:private | :private | :guest | nil | 1
:private | :private | :non_member | nil | 0
:private | :private | :anonymous | nil | 0
:private | :disabled | :reporter | nil | 0
:private | :disabled | :guest | nil | 0
:private | :disabled | :non_member | nil | 0
:private | :disabled | :anonymous | nil | 0
end
# This table is based on permission_table_for_guest_feature_access, # This table is based on permission_table_for_guest_feature_access,
# but with a slight twist. # but with a slight twist.
# Some features can be hidden away to GUEST, when project is private. # Some features can be hidden away to GUEST, when project is private.