Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-19 03:10:24 +00:00
parent a94adeb6b2
commit 7b50347823
40 changed files with 523 additions and 385 deletions

View File

@ -1 +1 @@
837b920e969e4b707c871be91ab587adcc9a9283
43d2f4f949f8a986ecad759c5e02bd01a243ed4f

View File

@ -279,8 +279,6 @@ export function emojiImageTag(name, src) {
title: `:${name}:`,
alt: `:${name}:`,
src,
width: '16',
height: '16',
align: 'absmiddle',
});

View File

@ -3,8 +3,11 @@ gl-emoji {
display: inline-flex;
vertical-align: baseline;
font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-size: 1.2em;
line-height: 1;
img {
width: 1.2em;
height: 1.2em;
}
}
.user-status-emoji {

View File

@ -7,5 +7,17 @@ module Projects
(Gitlab.config.pages.external_http || Gitlab.config.pages.external_https) &&
project.can_create_custom_domains?
end
def pages_subdomain(project)
Gitlab::Pages::UrlBuilder
.new(project)
.project_namespace
end
def build_pages_url(project, with_unique_domain:)
Gitlab::Pages::UrlBuilder
.new(project)
.pages_url(with_unique_domain: with_unique_domain)
end
end
end

View File

@ -4,8 +4,6 @@ module Ci
class ArtifactBlob
include BlobLike
EXTENSIONS_SERVED_BY_PAGES = %w[.html .htm .txt .json .xml .log].freeze
attr_reader :entry
def initialize(entry)
@ -35,31 +33,18 @@ module Ci
:build_artifact
end
def external_url(project, job)
return unless external_link?(job)
url_project_path = project.full_path.partition('/').last
artifact_path = [
'-', url_project_path, '-',
'jobs', job.id,
'artifacts', path
].join('/')
"#{project.pages_namespace_url}/#{artifact_path}"
def external_url(job)
pages_url_builder(job.project).artifact_url(entry, job)
end
def external_link?(job)
pages_config.enabled &&
pages_config.artifacts_server &&
EXTENSIONS_SERVED_BY_PAGES.include?(File.extname(name)) &&
(pages_config.access_control || job.project.public?)
pages_url_builder(job.project).artifact_url_available?(entry, job)
end
private
def pages_config
Gitlab.config.pages
def pages_url_builder(project)
@pages_url_builder ||= Gitlab::Pages::UrlBuilder.new(project)
end
end
end

View File

@ -46,7 +46,7 @@ module Pages
strong_memoize_attr :source
def prefix
if project.pages_namespace_url == project.pages_url
if url_builder.namespace_pages?
'/'
else
"#{project.full_path.delete_prefix(trim_prefix)}/"
@ -55,9 +55,7 @@ module Pages
strong_memoize_attr :prefix
def unique_host
return unless project.project_setting.pages_unique_domain_enabled?
project.pages_unique_host
url_builder.unique_host
end
strong_memoize_attr :unique_host
@ -76,5 +74,10 @@ module Pages
project.pages_metadatum.pages_deployment
end
strong_memoize_attr :deployment
def url_builder
Gitlab::Pages::UrlBuilder.new(project)
end
strong_memoize_attr :url_builder
end
end

View File

@ -2218,42 +2218,6 @@ class Project < ApplicationRecord
pages_metadatum&.deployed?
end
def pages_url(with_unique_domain: false)
return pages_unique_url if with_unique_domain && pages_unique_domain_enabled?
url = pages_namespace_url
url_path = full_path.partition('/').last
namespace_url = "#{Settings.pages.protocol}://#{url_path}".downcase
if Rails.env.development?
url_without_port = URI.parse(url)
url_without_port.port = nil
return url if url_without_port.to_s == namespace_url
end
# If the project path is the same as host, we serve it as group page
return url if url == namespace_url
"#{url}/#{url_path}"
end
def pages_unique_url
pages_url_for(project_setting.pages_unique_domain)
end
def pages_unique_host
URI(pages_unique_url).host
end
def pages_namespace_url
pages_url_for(pages_subdomain)
end
def pages_subdomain
full_path.partition('/').first
end
def pages_path
# TODO: when we migrate Pages to work with new storage types, change here to use disk_path
File.join(Settings.pages.path, full_path)
@ -2500,7 +2464,7 @@ class Project < ApplicationRecord
break unless pages_enabled?
variables.append(key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host)
variables.append(key: 'CI_PAGES_URL', value: pages_url)
variables.append(key: 'CI_PAGES_URL', value: Gitlab::Pages::UrlBuilder.new(self).pages_url)
end
end
@ -3259,18 +3223,6 @@ class Project < ApplicationRecord
private
def pages_unique_domain_enabled?
Feature.enabled?(:pages_unique_domain, self) &&
project_setting.pages_unique_domain_enabled?
end
def pages_url_for(domain)
# The host in URL always needs to be downcased
Gitlab.config.pages.url.sub(%r{^https?://}) do |prefix|
"#{prefix}#{domain}."
end.downcase
end
# overridden in EE
def project_group_links_with_preload
project_group_links

View File

@ -1,3 +1,4 @@
- external_url = @blob.external_url(@build)
- page_title @path, _('Artifacts'), "#{@build.name} (##{@build.id})", _('Jobs')
= render "projects/jobs/header"
@ -8,8 +9,8 @@
%h2= _("You are being redirected away from GitLab")
%p= _("This page is hosted on GitLab pages but contains user-generated content and may contain malicious code. Do not accept unless you trust the author and source.")
= link_to @blob.external_url(@project, @build),
@blob.external_url(@project, @build),
= link_to external_url,
external_url,
target: '_blank',
title: _('Opens in a new window'),
rel: 'noopener noreferrer'

View File

@ -1,5 +1,5 @@
- if @project.pages_deployed?
- pages_url = @project.pages_url(with_unique_domain: true)
- pages_url = build_pages_url(@project, with_unique_domain: true)
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5', data: { qa_selector: 'access_page_container' } }, footer_options: { class: 'gl-alert-warning' }) do |c|
- c.with_header do

View File

@ -11,7 +11,7 @@
= render 'pages_settings'
%hr.clearfix
= render 'ssl_limitations_warning' if @project.pages_subdomain.include?(".")
= render 'ssl_limitations_warning' if pages_subdomain(@project).include?(".")
= render 'access'
- if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
= render 'list'

View File

@ -1,5 +1,5 @@
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
- dns_record = "#{domain_presenter.domain} ALIAS #{domain_presenter.project.pages_subdomain}.#{Settings.pages.host}."
- dns_record = "#{domain_presenter.domain} ALIAS #{pages_subdomain(domain_presenter.project)}.#{Settings.pages.host}."
.form-group.border-section
.row

View File

@ -208,7 +208,7 @@ Adding a semicolon(`;`) and a follow-up statement at the end of a statement prev
```ruby
puts ActiveRecord::Base.descendants; :ok
Project.select(&:pages_deployed?).each {|p| puts p.pages_url }; true
Project.select(&:pages_deployed?).each {|p| puts p.path }; true
```
## Get or store the result of last operation

View File

@ -8516,6 +8516,29 @@ The edge type for [`ComplianceFramework`](#complianceframework).
| <a id="complianceframeworkedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="complianceframeworkedgenode"></a>`node` | [`ComplianceFramework`](#complianceframework) | The item at the end of the edge. |
#### `ComplianceStandardsAdherenceConnection`
The connection type for [`ComplianceStandardsAdherence`](#compliancestandardsadherence).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="compliancestandardsadherenceconnectionedges"></a>`edges` | [`[ComplianceStandardsAdherenceEdge]`](#compliancestandardsadherenceedge) | A list of edges. |
| <a id="compliancestandardsadherenceconnectionnodes"></a>`nodes` | [`[ComplianceStandardsAdherence]`](#compliancestandardsadherence) | A list of nodes. |
| <a id="compliancestandardsadherenceconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
#### `ComplianceStandardsAdherenceEdge`
The edge type for [`ComplianceStandardsAdherence`](#compliancestandardsadherence).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="compliancestandardsadherenceedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="compliancestandardsadherenceedgenode"></a>`node` | [`ComplianceStandardsAdherence`](#compliancestandardsadherence) | The item at the end of the edge. |
#### `ComplianceViolationConnection`
The connection type for [`ComplianceViolation`](#complianceviolation).
@ -13673,6 +13696,21 @@ Represents a ComplianceFramework associated with a Project.
| <a id="complianceframeworkname"></a>`name` | [`String!`](#string) | Name of the compliance framework. |
| <a id="complianceframeworkpipelineconfigurationfullpath"></a>`pipelineConfigurationFullPath` | [`String`](#string) | Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hipaa` **(ULTIMATE)**. |
### `ComplianceStandardsAdherence`
Compliance standards adherence for a project.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="compliancestandardsadherencecheckname"></a>`checkName` | [`ComplianceStandardsAdherenceCheckName!`](#compliancestandardsadherencecheckname) | Name of the check for the compliance standard. |
| <a id="compliancestandardsadherenceid"></a>`id` | [`ID!`](#id) | Compliance standards adherence ID. |
| <a id="compliancestandardsadherenceproject"></a>`project` | [`Project!`](#project) | Project adhering to the compliance standard. |
| <a id="compliancestandardsadherencestandard"></a>`standard` | [`ComplianceStandardsAdherenceStandard!`](#compliancestandardsadherencestandard) | Name of the compliance standard. |
| <a id="compliancestandardsadherencestatus"></a>`status` | [`ComplianceStandardsAdherenceStatus!`](#compliancestandardsadherencestatus) | Status of the compliance standards adherence. |
| <a id="compliancestandardsadherenceupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp when the adherence was updated. |
### `ComplianceViolation`
Compliance violation associated with a merged merge request.
@ -16609,6 +16647,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="grouppackagessort"></a>`sort` | [`PackageGroupSort`](#packagegroupsort) | Sort packages by this criteria. |
| <a id="grouppackagesstatus"></a>`status` | [`PackageStatus`](#packagestatus) | Filter a package by status. |
##### `Group.projectComplianceStandardsAdherence`
Compliance standards adherence for the projects in a group and its subgroups.
Returns [`ComplianceStandardsAdherenceConnection`](#compliancestandardsadherenceconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="groupprojectcompliancestandardsadherencefilters"></a>`filters` | [`ComplianceStandardsAdherenceInput`](#compliancestandardsadherenceinput) | Filters applied when retrieving compliance standards adherence. |
##### `Group.projects`
Projects within this namespace.
@ -25199,6 +25253,31 @@ ComplianceFramework of a project for filtering.
| <a id="complianceframeworkpresencefilterany"></a>`ANY` | Any compliance framework is assigned. |
| <a id="complianceframeworkpresencefilternone"></a>`NONE` | No compliance framework is assigned. |
### `ComplianceStandardsAdherenceCheckName`
Name of the check for the compliance standard.
| Value | Description |
| ----- | ----------- |
| <a id="compliancestandardsadherencechecknameprevent_approval_by_merge_request_author"></a>`PREVENT_APPROVAL_BY_MERGE_REQUEST_AUTHOR` | Prevent approval by merge request author. |
### `ComplianceStandardsAdherenceStandard`
Name of the compliance standard.
| Value | Description |
| ----- | ----------- |
| <a id="compliancestandardsadherencestandardgitlab"></a>`GITLAB` | Gitlab. |
### `ComplianceStandardsAdherenceStatus`
Status of the compliance standards adherence.
| Value | Description |
| ----- | ----------- |
| <a id="compliancestandardsadherencestatusfail"></a>`FAIL` | Fail. |
| <a id="compliancestandardsadherencestatussuccess"></a>`SUCCESS` | Success. |
### `ComplianceViolationReason`
Reason for the compliance violation.
@ -28951,6 +29030,16 @@ Attributes for defining a CI/CD variable.
| <a id="complianceframeworkinputname"></a>`name` | [`String`](#string) | New name for the compliance framework. |
| <a id="complianceframeworkinputpipelineconfigurationfullpath"></a>`pipelineConfigurationFullPath` | [`String`](#string) | Full path of the compliance pipeline configuration stored in a project repository, such as `.gitlab/.compliance-gitlab-ci.yml@compliance/hipaa` **(ULTIMATE)**. |
### `ComplianceStandardsAdherenceInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="compliancestandardsadherenceinputcheckname"></a>`checkName` | [`ComplianceStandardsAdherenceCheckName`](#compliancestandardsadherencecheckname) | Name of the check for the compliance standard. |
| <a id="compliancestandardsadherenceinputprojectids"></a>`projectIds` | [`[ProjectID!]`](#projectid) | Filter compliance standards adherence by project. |
| <a id="compliancestandardsadherenceinputstandard"></a>`standard` | [`ComplianceStandardsAdherenceStandard`](#compliancestandardsadherencestandard) | Name of the compliance standard. |
### `ComplianceViolationInput`
#### Arguments

View File

@ -169,7 +169,7 @@ containing:
For example, for a component repository located at `gitlab-org/dast` on `gitlab.com`:
- The path `gitlab.com/gitlab-org/dast` tries to load the `template.yml` from the root directory.
- The path `gitalb.com/gitlab-org/dast/api-scan` tries to load the `template.yml` from the `/api-scan` directory.
- The path `gitlab.com/gitlab-org/dast/api-scan` tries to load the `template.yml` from the `/api-scan` directory.
**Additional notes:**

View File

@ -185,7 +185,7 @@ After the long-term quarantining MR has reached production, you should revert th
For Jest specs, you can use the `.skip` method along with the `eslint-disable-next-line` comment to disable the `jest/no-disabled-tests` ESLint rule and include the issue URL. Here's an example:
```javascript
// https://gitlab.com/gitlab-org/gitlab/-/issues/56789
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/56789
// eslint-disable-next-line jest/no-disabled-tests
it.skip('should throw an error', () => {
expect(response).toThrowError(expected_error)
@ -198,6 +198,12 @@ This means it is skipped unless the test suit is run with `--runInBand` Jest com
jest --runInBand
```
A list of files with quarantined specs in them can be found with the command:
```shell
yarn jest:quarantine
```
For both test frameworks, make sure to add the `~"quarantined test"` label to the issue.
Once a test is in quarantine, there are 3 choices:

View File

@ -9,6 +9,7 @@ module Banzai
Filter::SanitizationFilter,
Filter::AssetProxyFilter,
Filter::EmojiFilter,
Filter::CustomEmojiFilter,
Filter::AutolinkFilter,
Filter::ExternalLinkFilter,
*reference_filters

View File

@ -1,5 +1,5 @@
variables:
AUTO_BUILD_IMAGE_VERSION: 'v1.36.0'
AUTO_BUILD_IMAGE_VERSION: 'v1.37.0'
build:
stage: build

View File

@ -1,5 +1,5 @@
variables:
AUTO_BUILD_IMAGE_VERSION: 'v1.36.0'
AUTO_BUILD_IMAGE_VERSION: 'v1.37.0'
build:
stage: build

View File

@ -0,0 +1,94 @@
# frozen_string_literal: true
module Gitlab
module Pages
class UrlBuilder
attr_reader :project_namespace
ALLOWED_ARTIFACT_EXTENSIONS = %w[.html .htm .txt .json .xml .log].freeze
ARTIFACT_URL = "%{host}/-/%{project_path}/-/jobs/%{job_id}/artifacts/%{artifact_path}"
def initialize(project)
@project = project
@project_namespace, _, @project_path = project.full_path.partition('/')
end
def pages_url(with_unique_domain: false)
return unique_url if with_unique_domain && unique_domain_enabled?
project_path_url = "#{config.protocol}://#{project_path}".downcase
# If the project path is the same as host, we serve it as group page
# On development we ignore the URL port to make it work on GDK
return namespace_url if Rails.env.development? && portless(namespace_url) == project_path_url
# If the project path is the same as host, we serve it as group page
return namespace_url if namespace_url == project_path_url
"#{namespace_url}/#{project_path}"
end
def unique_host
return unless unique_domain_enabled?
URI(unique_url).host
end
def namespace_pages?
namespace_url == pages_url
end
def artifact_url(artifact, job)
return unless artifact_url_available?(artifact, job)
format(
ARTIFACT_URL,
host: namespace_url,
project_path: project_path,
job_id: job.id,
artifact_path: artifact.path)
end
def artifact_url_available?(artifact, job)
config.enabled &&
config.artifacts_server &&
ALLOWED_ARTIFACT_EXTENSIONS.include?(File.extname(artifact.name)) &&
(config.access_control || job.project.public?)
end
private
attr_reader :project, :project_path
def namespace_url
@namespace_url ||= url_for(project_namespace)
end
def unique_url
@unique_url ||= url_for(project.project_setting.pages_unique_domain)
end
def url_for(subdomain)
URI(config.url)
.tap { |url| url.port = config.port }
.tap { |url| url.host.prepend("#{subdomain}.") }
.to_s
.downcase
end
def portless(url)
URI(url)
.tap { |u| u.port = nil }
.to_s
end
def unique_domain_enabled?
Feature.enabled?(:pages_unique_domain, project) &&
project.project_setting.pages_unique_domain_enabled?
end
def config
Gitlab.config.pages
end
end
end
end

View File

@ -115,7 +115,7 @@ module Gitlab
if Feature.enabled?(:use_metric_definitions_for_events_list)
events = Gitlab::Usage::MetricDefinition.not_removed.values.map do |d|
d.attributes[:options] && d.attributes[:options][:events]
end.flatten.compact
end.flatten.compact.uniq
events.map do |e|
{ name: e }.with_indifferent_access
@ -132,7 +132,7 @@ module Gitlab
end
def known_events_names
known_events.map { |event| event[:name] }
@known_events_names ||= known_events.map { |event| event[:name] }
end
def event_for(event_name)

View File

@ -17,6 +17,7 @@
"jest:ci:predictive": "jest --config jest.config.js --ci --coverage --findRelatedTests $(cat $RSPEC_CHANGED_FILES_PATH) $(cat $RSPEC_MATCHING_JS_FILES_PATH) --passWithNoTests --testSequencer ./scripts/frontend/parallel_ci_sequencer.js",
"jest:contract": "PACT_DO_NOT_TRACK=true jest --config jest.config.contract.js --runInBand",
"jest:integration": "jest --config jest.config.integration.js",
"jest:quarantine": "grep -r 'quarantine:' spec/frontend ee/spec/frontend",
"lint:eslint": "node scripts/frontend/eslint.js",
"lint:eslint:fix": "node scripts/frontend/eslint.js --fix",
"lint:eslint:all": "node scripts/frontend/eslint.js .",

View File

View File

@ -178,7 +178,7 @@ RSpec.describe 'User adds pages domain', :js, feature_category: :pages do
visit project_pages_path(project)
within('#content-body') { click_link 'Edit' }
expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS #{domain.project.pages_subdomain}.#{Settings.pages.host}."
expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS namespace1.example.com."
end
end
end

View File

@ -59,13 +59,13 @@ describe('gl_emoji', () => {
'bomb emoji just with name attribute',
'<gl-emoji data-name="bomb"></gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
`<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="16" height="16" align="absmiddle"></gl-emoji>`,
`<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" align="absmiddle"></gl-emoji>`,
],
[
'bomb emoji with name attribute and unicode version',
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
`<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="16" height="16" align="absmiddle"></gl-emoji>`,
`<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" align="absmiddle"></gl-emoji>`,
],
[
'bomb emoji with sprite fallback',
@ -77,19 +77,19 @@ describe('gl_emoji', () => {
'bomb emoji with image fallback',
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb"></gl-emoji>',
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/bomb.png" width="16" height="16" align="absmiddle"></gl-emoji>',
'<gl-emoji data-fallback-src="/bomb.png" data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/bomb.png" align="absmiddle"></gl-emoji>',
],
[
'invalid emoji',
'<gl-emoji data-name="invalid_emoji"></gl-emoji>',
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament">❔</gl-emoji>',
`<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" width="16" height="16" align="absmiddle"></gl-emoji>`,
`<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" align="absmiddle"></gl-emoji>`,
],
[
'custom emoji with image fallback',
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"></gl-emoji>',
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" width="16" height="16" align="absmiddle"></gl-emoji>',
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" width="16" height="16" align="absmiddle"></gl-emoji>',
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" align="absmiddle"></gl-emoji>',
'<gl-emoji data-fallback-src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" data-name="party-parrot" data-unicode-version="custom"><img class="emoji" title=":party-parrot:" alt=":party-parrot:" src="https://cultofthepartyparrot.com/parrots/hd/parrot.gif" align="absmiddle"></gl-emoji>',
],
])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => {
it(`renders correctly with emoji support`, async () => {
@ -119,7 +119,7 @@ describe('gl_emoji', () => {
await waitForPromises();
expect(glEmojiElement.outerHTML).toBe(
'<gl-emoji data-name="&quot;x=&quot;y&quot; onload=&quot;alert(document.location.href)&quot;" data-unicode-version="x"><img class="emoji" title=":&quot;x=&quot;y&quot; onload=&quot;alert(document.location.href)&quot;:" alt=":&quot;x=&quot;y&quot; onload=&quot;alert(document.location.href)&quot;:" src="/-/emojis/2/grey_question.png" width="16" height="16" align="absmiddle"></gl-emoji>',
'<gl-emoji data-name="&quot;x=&quot;y&quot; onload=&quot;alert(document.location.href)&quot;" data-unicode-version="x"><img class="emoji" title=":&quot;x=&quot;y&quot; onload=&quot;alert(document.location.href)&quot;:" alt=":&quot;x=&quot;y&quot; onload=&quot;alert(document.location.href)&quot;:" src="/-/emojis/2/grey_question.png" align="absmiddle"></gl-emoji>',
);
});

View File

@ -156,7 +156,7 @@ describe('AdminRunnersApp', () => {
await createComponent({ mountFn: mountExtended });
});
// https://gitlab.com/gitlab-org/gitlab/-/issues/414975
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/414975
// eslint-disable-next-line jest/no-disabled-tests
it.skip('fetches counts', () => {
expect(mockRunnersCountHandler).toHaveBeenCalledTimes(COUNT_QUERIES);

View File

@ -60,7 +60,7 @@ describe('RelatedIssuesRoot', () => {
await createComponent();
});
// Quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/417177
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/417177
// eslint-disable-next-line jest/no-disabled-tests
it.skip('removes related issue on API success', async () => {
mock.onDelete(issuable1.referencePath).reply(HTTP_STATUS_OK, { issues: [] });

View File

@ -121,7 +121,7 @@ describe('IssuesDashboardApp component', () => {
await waitForPromises();
});
// https://gitlab.com/gitlab-org/gitlab/-/issues/391722
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/391722
// eslint-disable-next-line jest/no-disabled-tests
it.skip('renders IssuableList component', () => {
expect(findIssuableList().props()).toMatchObject({

View File

@ -19,7 +19,7 @@ const setupHTML = (initialData) => {
describe('Issue show index', () => {
describe('initIssueApp', () => {
// https://gitlab.com/gitlab-org/gitlab/-/issues/390368
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/390368
// eslint-disable-next-line jest/no-disabled-tests
it.skip('should initialize app with no potential XSS attack', async () => {
const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {});

View File

@ -122,7 +122,7 @@ describe('note_app', () => {
);
});
// https://gitlab.com/gitlab-org/gitlab/-/issues/410409
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/410409
// eslint-disable-next-line jest/no-disabled-tests
it.skip('should render form comment button as disabled', () => {
expect(findCommentButton().props('disabled')).toEqual(true);

View File

@ -32,8 +32,7 @@ function wrappedDiscussionNote(note) {
return `<table><tbody>${note}</tbody></table>`;
}
// the following test is unreliable and failing in main 2-3 times a day
// see https://gitlab.com/gitlab-org/gitlab/issues/206906#note_290602581
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/208441
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('Old Notes (~/deprecated_notes.js)', () => {
beforeEach(() => {

View File

@ -175,7 +175,7 @@ describe('MrWidgetOptions', () => {
return createComponent();
});
// https://gitlab.com/gitlab-org/gitlab/-/issues/385238
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/385238
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('data', () => {
it('should instantiate Store and Service', () => {
@ -186,6 +186,7 @@ describe('MrWidgetOptions', () => {
describe('computed', () => {
describe('componentName', () => {
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/409365
// eslint-disable-next-line jest/no-disabled-tests
it.skip.each`
${'merged'} | ${'mr-widget-merged'}

View File

@ -128,7 +128,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
});
});
// quarantine flaky spec:https://gitlab.com/gitlab-org/gitlab/-/issues/412618
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/412618
// eslint-disable-next-line jest/no-disabled-tests
it.skip('passes render_quick_actions param to renderMarkdownPath if quick actions are enabled', async () => {
buildWrapper({ propsData: { supportsQuickActions: true } });
@ -139,7 +139,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
expect(mock.history.post[0].url).toContain(`render_quick_actions=true`);
});
// quarantine flaky spec: https://gitlab.com/gitlab-org/gitlab/-/issues/411565
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/411565
// eslint-disable-next-line jest/no-disabled-tests
it.skip('does not pass render_quick_actions param to renderMarkdownPath if quick actions are disabled', async () => {
buildWrapper({ propsData: { supportsQuickActions: false } });
@ -213,7 +213,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => {
expect(findMarkdownField().find('textarea').attributes('disabled')).toBe(undefined);
});
// quarantine flaky spec: https://gitlab.com/gitlab-org/gitlab/-/issues/404734
// quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/404734
// eslint-disable-next-line jest/no-disabled-tests
it.skip('disables content editor when disabled prop is true', async () => {
buildWrapper({ propsData: { disabled: true } });

View File

@ -98,7 +98,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache, featur
{ key: 'CI_PAGES_DOMAIN',
value: Gitlab.config.pages.host },
{ key: 'CI_PAGES_URL',
value: project.pages_url },
value: Gitlab::Pages::UrlBuilder.new(project).pages_url },
{ key: 'CI_API_V4_URL',
value: API::Helpers::Version.new('v4').root_url },
{ key: 'CI_API_GRAPHQL_URL',

View File

@ -0,0 +1,227 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Pages::UrlBuilder, feature_category: :pages do
let(:pages_enabled) { true }
let(:artifacts_server) { true }
let(:access_control) { true }
let(:port) { nil }
let(:host) { 'example.com' }
let(:full_path) { 'group/project' }
let(:project_public) { true }
let(:unique_domain) { 'unique-domain' }
let(:unique_domain_enabled) { false }
let(:project_setting) do
instance_double(
ProjectSetting,
pages_unique_domain: unique_domain,
pages_unique_domain_enabled?: unique_domain_enabled
)
end
let(:project) do
instance_double(
Project,
flipper_id: 'project:1', # required for the feature flag check
public?: project_public,
project_setting: project_setting,
full_path: full_path
)
end
subject(:builder) { described_class.new(project) }
before do
stub_pages_setting(
enabled: pages_enabled,
host: host,
url: 'http://example.com',
protocol: 'http',
artifacts_server: artifacts_server,
access_control: access_control,
port: port
)
end
describe '#pages_url' do
subject(:pages_url) { builder.pages_url }
it { is_expected.to eq('http://group.example.com/project') }
context 'when namespace is upper cased' do
let(:full_path) { 'Group/project' }
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when project is in a nested group page' do
let(:full_path) { 'group/subgroup/project' }
it { is_expected.to eq('http://group.example.com/subgroup/project') }
end
context 'when using domain pages' do
let(:full_path) { 'group/group.example.com' }
it { is_expected.to eq('http://group.example.com') }
context 'in development mode' do
let(:port) { 3010 }
before do
stub_rails_env('development')
end
it { is_expected.to eq('http://group.example.com:3010') }
end
end
context 'when not using pages_unique_domain' do
subject(:pages_url) { builder.pages_url(with_unique_domain: false) }
context 'when pages_unique_domain feature flag is disabled' do
before do
stub_feature_flags(pages_unique_domain: false)
end
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain feature flag is enabled' do
before do
stub_feature_flags(pages_unique_domain: true)
end
context 'when pages_unique_domain_enabled is false' do
let(:unique_domain_enabled) { false }
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain_enabled is true' do
let(:unique_domain_enabled) { true }
it { is_expected.to eq('http://group.example.com/project') }
end
end
end
context 'when using pages_unique_domain' do
subject(:pages_url) { builder.pages_url(with_unique_domain: true) }
context 'when pages_unique_domain feature flag is disabled' do
before do
stub_feature_flags(pages_unique_domain: false)
end
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain feature flag is enabled' do
before do
stub_feature_flags(pages_unique_domain: true)
end
context 'when pages_unique_domain_enabled is false' do
let(:unique_domain_enabled) { false }
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain_enabled is true' do
let(:unique_domain_enabled) { true }
it { is_expected.to eq('http://unique-domain.example.com') }
end
end
end
end
describe '#unique_host' do
subject(:unique_host) { builder.unique_host }
context 'when pages_unique_domain feature flag is disabled' do
before do
stub_feature_flags(pages_unique_domain: false)
end
it { is_expected.to be_nil }
end
context 'when pages_unique_domain feature flag is enabled' do
before do
stub_feature_flags(pages_unique_domain: true)
end
context 'when pages_unique_domain_enabled is false' do
let(:unique_domain_enabled) { false }
it { is_expected.to be_nil }
end
context 'when pages_unique_domain_enabled is true' do
let(:unique_domain_enabled) { true }
it { is_expected.to eq('unique-domain.example.com') }
end
end
end
describe '#artifact_url' do
let(:job) { instance_double(Ci::Build, id: 1) }
let(:artifact) do
instance_double(
Gitlab::Ci::Build::Artifacts::Metadata::Entry,
name: artifact_name,
path: "path/#{artifact_name}")
end
subject(:artifact_url) { builder.artifact_url(artifact, job) }
context 'with not allowed extension' do
let(:artifact_name) { 'file.gif' }
it { is_expected.to be_nil }
end
context 'with allowed extension' do
let(:artifact_name) { 'file.txt' }
it { is_expected.to eq("http://group.example.com/-/project/-/jobs/1/artifacts/path/file.txt") }
context 'when port is configured' do
let(:port) { 1234 }
it { is_expected.to eq("http://group.example.com:1234/-/project/-/jobs/1/artifacts/path/file.txt") }
end
end
end
describe '#artifact_url_available?' do
let(:job) { instance_double(Ci::Build, id: 1) }
let(:artifact) do
instance_double(
Gitlab::Ci::Build::Artifacts::Metadata::Entry,
name: artifact_name,
path: "path/#{artifact_name}")
end
subject(:artifact_url_available) { builder.artifact_url_available?(artifact, job) }
context 'with not allowed extensions' do
let(:artifact_name) { 'file.gif' }
it { is_expected.to be false }
end
context 'with allowed extensions' do
let(:artifact_name) { 'file.txt' }
it { is_expected.to be true }
end
end
end

View File

@ -18,9 +18,11 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
# depending on which day of the week test is run.
# Monday 6th of June
described_class.clear_memoization(:known_events)
described_class.clear_memoization(:known_events_names)
reference_time = Time.utc(2020, 6, 1)
travel_to(reference_time) { example.run }
described_class.clear_memoization(:known_events)
described_class.clear_memoization(:known_events_names)
end
describe '.known_events' do

View File

@ -4,8 +4,6 @@ require 'spec_helper'
RSpec.describe Gitlab::UsageDataMetrics, :with_license, feature_category: :service_ping do
describe '.uncached_data' do
let(:aggregate) { instance_double('Gitlab::Usage::Metrics::Aggregates::Aggregate') }
subject { described_class.uncached_data }
around do |example|
@ -15,11 +13,6 @@ RSpec.describe Gitlab::UsageDataMetrics, :with_license, feature_category: :servi
end
before do
# stub time-consuming and unnecessary computation
allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).and_return(1)
allow(Gitlab::Usage::Metrics::Aggregates::Aggregate).to receive(:new).and_return(aggregate)
allow(aggregate).to receive(:calculate_count_for_aggregation).and_return(1)
allow_next_instance_of(Gitlab::Database::BatchCounter) do |batch_counter|
allow(batch_counter).to receive(:transaction_open?).and_return(false)
end

View File

@ -3,104 +3,92 @@
require 'spec_helper'
RSpec.describe Ci::ArtifactBlob, feature_category: :continuous_integration do
let_it_be(:project) { create(:project, :public) }
let_it_be(:project) { create(:project, :public, path: 'project1') }
let_it_be(:build) { create(:ci_build, :artifacts, project: project) }
let(:pages_port) { nil }
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/another-subdirectory/banana_sample.gif') }
subject { described_class.new(entry) }
subject(:blob) { described_class.new(entry) }
before do
stub_pages_setting(
enabled: true,
artifacts_server: true,
access_control: true,
port: pages_port
)
end
describe '#id' do
it 'returns a hash of the path' do
expect(subject.id).to eq(Digest::SHA1.hexdigest(entry.path))
expect(blob.id).to eq(Digest::SHA1.hexdigest(entry.path))
end
end
describe '#name' do
it 'returns the entry name' do
expect(subject.name).to eq(entry.name)
expect(blob.name).to eq(entry.name)
end
end
describe '#path' do
it 'returns the entry path' do
expect(subject.path).to eq(entry.path)
expect(blob.path).to eq(entry.path)
end
end
describe '#size' do
it 'returns the entry size' do
expect(subject.size).to eq(entry.metadata[:size])
expect(blob.size).to eq(entry.metadata[:size])
end
end
describe '#mode' do
it 'returns the entry mode' do
expect(subject.mode).to eq(entry.metadata[:mode])
expect(blob.mode).to eq(entry.metadata[:mode])
end
end
describe '#external_storage' do
it 'returns :build_artifact' do
expect(subject.external_storage).to eq(:build_artifact)
expect(blob.external_storage).to eq(:build_artifact)
end
end
describe '#external_url' do
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true)
subject(:url) { blob.external_url(build) }
context 'with not allowed extension' do
it { is_expected.to be_nil }
end
describe '.gif extension' do
it 'returns nil' do
expect(subject.external_url(build.project, build)).to be_nil
end
end
context 'txt extensions' do
context 'with allowed extension' do
let(:path) { 'other_artifacts_0.1.2/doc_sample.txt' }
let(:entry) { build.artifacts_metadata_entry(path) }
it 'returns a URL' do
url = subject.external_url(build.project, build)
expect(url).not_to be_nil
expect(url).to eq("http://#{project.namespace.path}.#{Gitlab.config.pages.host}/-/#{project.path}/-/jobs/#{build.id}/artifacts/#{path}")
end
it { is_expected.to eq("http://#{project.namespace.path}.example.com/-/project1/-/jobs/#{build.id}/artifacts/other_artifacts_0.1.2/doc_sample.txt") }
context 'when port is configured' do
let(:port) { 1234 }
let(:pages_port) { 1234 }
it 'returns an URL with port number' do
allow(Gitlab.config.pages).to receive(:url).and_return("#{Gitlab.config.pages.url}:#{port}")
url = subject.external_url(build.project, build)
expect(url).not_to be_nil
expect(url).to eq("http://#{project.namespace.path}.#{Gitlab.config.pages.host}:#{port}/-/#{project.path}/-/jobs/#{build.id}/artifacts/#{path}")
end
it { is_expected.to eq("http://#{project.namespace.path}.example.com:1234/-/project1/-/jobs/#{build.id}/artifacts/other_artifacts_0.1.2/doc_sample.txt") }
end
end
end
describe '#external_link?' do
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true)
end
context 'gif extensions' do
context 'with not allowed extensions' do
it 'returns false' do
expect(subject.external_link?(build)).to be false
expect(blob.external_link?(build)).to be false
end
end
context 'txt extensions' do
context 'with allowed extensions' do
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/doc_sample.txt') }
it 'returns true' do
expect(subject.external_link?(build)).to be true
expect(blob.external_link?(build)).to be true
end
end
end

View File

@ -2899,7 +2899,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
{ key: 'CI_DEFAULT_BRANCH', value: project.default_branch, public: true, masked: false },
{ key: 'CI_CONFIG_PATH', value: project.ci_config_path_or_default, public: true, masked: false },
{ key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true, masked: false },
{ key: 'CI_PAGES_URL', value: project.pages_url, public: true, masked: false },
{ key: 'CI_PAGES_URL', value: Gitlab::Pages::UrlBuilder.new(project).pages_url, public: true, masked: false },
{ key: 'CI_DEPENDENCY_PROXY_SERVER', value: Gitlab.host_with_port, public: true, masked: false },
{ key: 'CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX',
value: "#{Gitlab.host_with_port}/#{project.namespace.root_ancestor.path.downcase}#{DependencyProxy::URL_SUFFIX}",

View File

@ -8,7 +8,12 @@ RSpec.describe Pages::LookupPath, feature_category: :pages do
subject(:lookup_path) { described_class.new(project) }
before do
stub_pages_setting(access_control: true, external_https: ["1.1.1.1:443"])
stub_pages_setting(
access_control: true,
external_https: ["1.1.1.1:443"],
url: 'http://example.com',
protocol: 'http'
)
stub_pages_object_storage(::Pages::DeploymentUploader)
end
@ -120,18 +125,14 @@ RSpec.describe Pages::LookupPath, feature_category: :pages do
describe '#prefix' do
it 'returns "/" for pages group root projects' do
project = instance_double(Project, pages_namespace_url: "namespace.test", pages_url: "namespace.test")
project = instance_double(Project, full_path: "namespace/namespace.example.com")
lookup_path = described_class.new(project, trim_prefix: 'mygroup')
expect(lookup_path.prefix).to eq('/')
end
it 'returns the project full path with the provided prefix removed' do
project = instance_double(
Project,
pages_namespace_url: "namespace.test",
pages_url: "namespace.other",
full_path: 'mygroup/myproject')
project = instance_double(Project, full_path: 'mygroup/myproject')
lookup_path = described_class.new(project, trim_prefix: 'mygroup')
expect(lookup_path.prefix).to eq('/myproject/')

View File

@ -2806,224 +2806,6 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
end
end
describe '#pages_url', feature_category: :pages do
let(:group_name) { 'group' }
let(:project_name) { 'project' }
let(:group) { create(:group, name: group_name) }
let(:nested_group) { create(:group, parent: group) }
let(:project_path) { project_name.downcase }
let(:project) do
create(
:project,
namespace: group,
name: project_name,
path: project_path)
end
let(:domain) { 'Example.com' }
let(:port) { nil }
subject { project.pages_url }
before do
allow(Settings.pages).to receive(:host).and_return(domain)
allow(Gitlab.config.pages)
.to receive(:url)
.and_return(['http://example.com', port].compact.join(':'))
end
context 'when not using pages_unique_domain' do
subject { project.pages_url(with_unique_domain: false) }
context 'when pages_unique_domain feature flag is disabled' do
before do
stub_feature_flags(pages_unique_domain: false)
end
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain feature flag is enabled' do
before do
stub_feature_flags(pages_unique_domain: true)
project.project_setting.update!(
pages_unique_domain_enabled: pages_unique_domain_enabled,
pages_unique_domain: 'unique-domain'
)
end
context 'when pages_unique_domain_enabled is false' do
let(:pages_unique_domain_enabled) { false }
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain_enabled is true' do
let(:pages_unique_domain_enabled) { true }
it { is_expected.to eq('http://group.example.com/project') }
end
end
end
context 'when using pages_unique_domain' do
subject { project.pages_url(with_unique_domain: true) }
context 'when pages_unique_domain feature flag is disabled' do
before do
stub_feature_flags(pages_unique_domain: false)
end
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain feature flag is enabled' do
before do
stub_feature_flags(pages_unique_domain: true)
project.project_setting.update!(
pages_unique_domain_enabled: pages_unique_domain_enabled,
pages_unique_domain: 'unique-domain'
)
end
context 'when pages_unique_domain_enabled is false' do
let(:pages_unique_domain_enabled) { false }
it { is_expected.to eq('http://group.example.com/project') }
end
context 'when pages_unique_domain_enabled is true' do
let(:pages_unique_domain_enabled) { true }
it { is_expected.to eq('http://unique-domain.example.com') }
end
end
end
context 'with nested group' do
let(:project) { create(:project, namespace: nested_group, name: project_name) }
let(:expected_url) { "http://group.example.com/#{nested_group.path}/#{project.path}" }
context 'group page' do
let(:project_name) { 'group.example.com' }
it { is_expected.to eq(expected_url) }
end
context 'project page' do
let(:project_name) { 'Project' }
it { is_expected.to eq(expected_url) }
end
end
context 'when the project matches its namespace url' do
let(:project_name) { 'group.example.com' }
it { is_expected.to eq('http://group.example.com') }
context 'with different group name capitalization' do
let(:group_name) { 'Group' }
it { is_expected.to eq("http://group.example.com") }
end
context 'with different project path capitalization' do
let(:project_path) { 'Group.example.com' }
it { is_expected.to eq("http://group.example.com") }
end
context 'with different project name capitalization' do
let(:project_name) { 'Project' }
it { is_expected.to eq("http://group.example.com/project") }
end
context 'when there is an explicit port' do
let(:port) { 3000 }
context 'when not in dev mode' do
before do
stub_rails_env('production')
end
it { is_expected.to eq('http://group.example.com:3000/group.example.com') }
end
context 'when in dev mode' do
before do
stub_rails_env('development')
end
it { is_expected.to eq('http://group.example.com:3000') }
end
end
end
end
describe '#pages_unique_url', feature_category: :pages do
let(:project_settings) { create(:project_setting, pages_unique_domain: 'unique-domain') }
let(:project) { build(:project, project_setting: project_settings) }
let(:domain) { 'example.com' }
before do
allow(Settings.pages).to receive(:host).and_return(domain)
allow(Gitlab.config.pages).to receive(:url).and_return("http://#{domain}")
end
it 'returns the pages unique url' do
expect(project.pages_unique_url).to eq('http://unique-domain.example.com')
end
end
describe '#pages_unique_host', feature_category: :pages do
let(:project_settings) { create(:project_setting, pages_unique_domain: 'unique-domain') }
let(:project) { build(:project, project_setting: project_settings) }
let(:domain) { 'example.com' }
before do
allow(Settings.pages).to receive(:host).and_return(domain)
allow(Gitlab.config.pages).to receive(:url).and_return("http://#{domain}")
end
it 'returns the pages unique url' do
expect(project.pages_unique_host).to eq('unique-domain.example.com')
end
end
describe '#pages_namespace_url', feature_category: :pages do
let(:group) { create(:group, name: group_name) }
let(:project) { create(:project, namespace: group, name: project_name) }
let(:domain) { 'Example.com' }
let(:port) { 1234 }
subject { project.pages_namespace_url }
before do
allow(Settings.pages).to receive(:host).and_return(domain)
allow(Gitlab.config.pages).to receive(:url).and_return("http://example.com:#{port}")
end
context 'group page' do
let(:group_name) { 'Group' }
let(:project_name) { 'group.example.com' }
it { is_expected.to eq("http://group.example.com:#{port}") }
end
context 'project page' do
let(:group_name) { 'Group' }
let(:project_name) { 'Project' }
it { is_expected.to eq("http://group.example.com:#{port}") }
end
end
describe '.search' do
let_it_be(:project) { create(:project, description: 'kitten mittens') }