Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
26e44c6225
commit
006000e366
|
@ -43,6 +43,17 @@ rules:
|
|||
promise/always-return: off
|
||||
promise/no-callback-in-promise: off
|
||||
'@gitlab/no-global-event-off': error
|
||||
no-param-reassign:
|
||||
- error
|
||||
- props: true
|
||||
ignorePropertyModificationsFor:
|
||||
- acc
|
||||
- accumulator
|
||||
- el
|
||||
- element
|
||||
- state
|
||||
ignorePropertyModificationsForRegex:
|
||||
- '^draft'
|
||||
import/order:
|
||||
- error
|
||||
- groups:
|
||||
|
|
|
@ -104,10 +104,8 @@ export default {
|
|||
const { projects: previousProjects } = previousResult;
|
||||
|
||||
return produce(previousResult, (draftData) => {
|
||||
/* eslint-disable no-param-reassign */
|
||||
draftData.projects.nodes = [...previousProjects.nodes, ...newProjects.nodes];
|
||||
draftData.projects.pageInfo = newProjects.pageInfo;
|
||||
/* eslint-enable no-param-reassign */
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -27,10 +27,8 @@ const resolvers = {
|
|||
const sourceData = cache.readQuery({ query: getCurrentIntegrationQuery });
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
if (id === null) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.currentIntegration = null;
|
||||
} else {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.currentIntegration = {
|
||||
id,
|
||||
name,
|
||||
|
|
|
@ -15,7 +15,6 @@ const deleteIntegrationFromStore = (store, query, { httpIntegrationDestroy }, va
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.alertManagementIntegrations.nodes = draftData.project.alertManagementIntegrations.nodes.filter(
|
||||
({ id }) => id !== integration.id,
|
||||
);
|
||||
|
@ -46,7 +45,6 @@ const addIntegrationToStore = (
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.alertManagementIntegrations.nodes = [
|
||||
integration,
|
||||
...draftData.project.alertManagementIntegrations.nodes,
|
||||
|
@ -72,7 +70,6 @@ const addHttpIntegrationToStore = (store, query, { httpIntegrationCreate }, vari
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.alertManagementHttpIntegrations.nodes = [
|
||||
integration,
|
||||
...draftData.project.alertManagementHttpIntegrations.nodes,
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
GlIntersectionObserver,
|
||||
GlLoadingIcon,
|
||||
} from '@gitlab/ui';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import { mapActions, mapState, mapGetters } from 'vuex';
|
||||
import { s__ } from '~/locale';
|
||||
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
|
||||
import { ListType } from '../constants';
|
||||
|
@ -49,7 +49,8 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState(['groupProjects', 'groupProjectsFlags']),
|
||||
...mapState(['groupProjectsFlags']),
|
||||
...mapGetters(['activeGroupProjects']),
|
||||
selectedProjectName() {
|
||||
return this.selectedProject.name || this.$options.i18n.dropdownText;
|
||||
},
|
||||
|
@ -65,7 +66,7 @@ export default {
|
|||
};
|
||||
},
|
||||
isFetchResultEmpty() {
|
||||
return this.groupProjects.length === 0;
|
||||
return this.activeGroupProjects.length === 0;
|
||||
},
|
||||
hasNextPage() {
|
||||
return this.groupProjectsFlags.pageInfo?.hasNextPage;
|
||||
|
@ -84,7 +85,7 @@ export default {
|
|||
methods: {
|
||||
...mapActions(['fetchGroupProjects', 'setSelectedProject']),
|
||||
selectProject(projectId) {
|
||||
this.selectedProject = this.groupProjects.find((project) => project.id === projectId);
|
||||
this.selectedProject = this.activeGroupProjects.find((project) => project.id === projectId);
|
||||
this.setSelectedProject(this.selectedProject);
|
||||
},
|
||||
loadMoreProjects() {
|
||||
|
@ -113,7 +114,7 @@ export default {
|
|||
:placeholder="$options.i18n.searchPlaceholder"
|
||||
/>
|
||||
<gl-dropdown-item
|
||||
v-for="project in groupProjects"
|
||||
v-for="project in activeGroupProjects"
|
||||
v-show="!groupProjectsFlags.isLoading"
|
||||
:key="project.id"
|
||||
:name="project.name"
|
||||
|
|
|
@ -25,6 +25,7 @@ export default {
|
|||
with_shared: false,
|
||||
include_subgroups: true,
|
||||
order_by: 'similarity',
|
||||
archived: false,
|
||||
},
|
||||
components: {
|
||||
GlLoadingIcon,
|
||||
|
|
|
@ -8,6 +8,7 @@ query getGroupProjects($fullPath: ID!, $search: String, $after: String) {
|
|||
name
|
||||
fullPath
|
||||
nameWithNamespace
|
||||
archived
|
||||
}
|
||||
pageInfo {
|
||||
...PageInfo
|
||||
|
|
|
@ -29,6 +29,10 @@ export default {
|
|||
return referencePath.slice(0, referencePath.indexOf('#'));
|
||||
},
|
||||
|
||||
activeGroupProjects: (state) => {
|
||||
return state.groupProjects.filter((p) => !p.archived);
|
||||
},
|
||||
|
||||
getListByLabelId: (state) => (labelId) => {
|
||||
if (!labelId) {
|
||||
return null;
|
||||
|
|
|
@ -20,7 +20,6 @@ const resolvers = {
|
|||
const sourceData = cache.readQuery({ query: activeDiscussionQuery });
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.activeDiscussion = {
|
||||
__typename: 'ActiveDiscussion',
|
||||
id,
|
||||
|
|
|
@ -41,7 +41,6 @@ const addNewVersionToStore = (store, query, version) => {
|
|||
const sourceData = store.readQuery(query);
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.issue.designCollection.versions.nodes = [
|
||||
version,
|
||||
...draftData.project.issue.designCollection.versions.nodes,
|
||||
|
@ -168,7 +167,6 @@ const addNewDesignToStore = (store, designManagementUpload, query) => {
|
|||
nodes: newVersions,
|
||||
},
|
||||
};
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.issue.designCollection = updatedDesigns;
|
||||
});
|
||||
|
||||
|
@ -182,7 +180,6 @@ const moveDesignInStore = (store, designManagementMove, query) => {
|
|||
const sourceData = store.readQuery(query);
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.issue.designCollection.designs =
|
||||
designManagementMove.designCollection.designs;
|
||||
});
|
||||
|
|
|
@ -21,8 +21,7 @@ export const addInProgressImportToStore = (store, jiraImportStart, fullPath) =>
|
|||
store.writeQuery({
|
||||
...queryDetails,
|
||||
data: produce(sourceData, (draftData) => {
|
||||
draftData.project.jiraImportStatus = IMPORT_STATE.SCHEDULED; // eslint-disable-line no-param-reassign
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.jiraImportStatus = IMPORT_STATE.SCHEDULED;
|
||||
draftData.project.jiraImports.nodes = [
|
||||
...sourceData.project.jiraImports.nodes,
|
||||
jiraImportStart.jiraImport,
|
||||
|
|
|
@ -86,7 +86,6 @@ export default {
|
|||
const originalMetricQuery = this.graphData.metrics[0];
|
||||
|
||||
const metricQuery = produce(originalMetricQuery, (draftQuery) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftQuery.result[0].values = draftQuery.result[0].values.map(([x, y]) => [
|
||||
x,
|
||||
y + this.yOffset,
|
||||
|
|
|
@ -9,7 +9,6 @@ export const updateGroupPackageSettings = (fullPath) => (client, { data: updated
|
|||
const sourceData = client.readQuery(queryAndParams);
|
||||
|
||||
const data = produce(sourceData, (draftState) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftState.group.packageSettings = {
|
||||
...updatedData.updateNamespacePackageSettings.packageSettings,
|
||||
};
|
||||
|
|
|
@ -29,7 +29,6 @@ export default {
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftState) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftState.containerRepository.status =
|
||||
destroyContainerRepository.containerRepository.status;
|
||||
});
|
||||
|
|
|
@ -9,7 +9,6 @@ export const updateContainerExpirationPolicy = (projectPath) => (client, { data:
|
|||
const sourceData = client.readQuery(queryAndParams);
|
||||
|
||||
const data = produce(sourceData, (draftState) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftState.project.containerExpirationPolicy = {
|
||||
...updatedData.updateContainerExpirationPolicy.containerExpirationPolicy,
|
||||
};
|
||||
|
|
|
@ -95,7 +95,6 @@ export default {
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.workspace.issuable.confidential = !this.confidential;
|
||||
});
|
||||
|
||||
|
|
|
@ -87,11 +87,8 @@ export default {
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftState) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftState.project.mergeRequest.mergeableDiscussionsState = mergeableDiscussionsState;
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftState.project.mergeRequest.workInProgress = workInProgress;
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftState.project.mergeRequest.title = title;
|
||||
});
|
||||
|
||||
|
|
|
@ -116,7 +116,6 @@ export default {
|
|||
});
|
||||
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.project.alertManagementAlerts.nodes[0].todos.nodes = [];
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ export default (selector) => {
|
|||
toggleSidebarStatus: (_, __, { cache }) => {
|
||||
const sourceData = cache.readQuery({ query: sidebarStatusQuery });
|
||||
const data = produce(sourceData, (draftData) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
draftData.sidebarStatus = !draftData.sidebarStatus;
|
||||
});
|
||||
cache.writeQuery({ query: sidebarStatusQuery, data });
|
||||
|
|
|
@ -343,7 +343,7 @@ module InProductMarketingHelper
|
|||
end
|
||||
end
|
||||
|
||||
def inline_image_link(folder, image, **options)
|
||||
def inline_image_link(folder, image, options)
|
||||
attachments.inline[image] = File.read(Rails.root.join("app/assets/images", folder, image))
|
||||
image_tag attachments[image].url, **options
|
||||
end
|
||||
|
|
|
@ -159,8 +159,17 @@ class Wiki
|
|||
find_page(SIDEBAR, version)
|
||||
end
|
||||
|
||||
def find_file(name, version = 'HEAD')
|
||||
wiki.file(name, version)
|
||||
def find_file(name, version = 'HEAD', load_content: true)
|
||||
if Feature.enabled?(:gitaly_find_file, user, default_enabled: :yaml)
|
||||
data_limit = load_content ? -1 : 0
|
||||
blobs = repository.blobs_at([[version, name]], blob_size_limit: data_limit)
|
||||
|
||||
return if blobs.empty?
|
||||
|
||||
Gitlab::Git::WikiFile.from_blob(blobs.first)
|
||||
else
|
||||
wiki.file(name, version)
|
||||
end
|
||||
end
|
||||
|
||||
def create_page(title, content, format = :markdown, message = nil)
|
||||
|
|
|
@ -177,8 +177,9 @@
|
|||
%td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
|
||||
%p{ style: "margin: 0 0 20px 0;" }
|
||||
= in_product_marketing_body_line1(@track, @series, format: :html).html_safe
|
||||
%p{ style: "margin: 0 0 20px 0;" }
|
||||
= in_product_marketing_body_line2(@track, @series, format: :html).html_safe
|
||||
- in_product_marketing_body_line2(@track, @series, format: :html)&.tap do |line|
|
||||
%p{ style: "margin: 0 0 20px 0;" }
|
||||
= line.html_safe
|
||||
%tr
|
||||
%td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
|
||||
.cta_link= cta_link(@track, @series, @group, format: :html)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Hide archived projects from group boards project select dropdown
|
||||
merge_request: 56452
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: gitaly_find_file
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56321
|
||||
rollout_issue_url:
|
||||
milestone: '13.10'
|
||||
type: development
|
||||
group: group::editor
|
||||
default_enabled: false
|
|
@ -1,16 +1,19 @@
|
|||
---
|
||||
key_path: signup_enabled
|
||||
description: Whether public signup is enabled
|
||||
product_section: growth
|
||||
product_stage: growth
|
||||
product_group: group::product intelligence
|
||||
product_category: collection
|
||||
product_section: dev
|
||||
product_stage: manage
|
||||
product_group: group::access
|
||||
product_category: authentication_and_authorization
|
||||
value_type: boolean
|
||||
status: data_available
|
||||
time_frame: none
|
||||
data_source:
|
||||
data_source: database
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
skip_validation: true
|
||||
|
|
|
@ -39,3 +39,30 @@ See [this video](https://youtu.be/-BkEhghP-kM) for an in-depth overview and inve
|
|||
```
|
||||
|
||||
Please note that `toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation.
|
||||
|
||||
### Script issues
|
||||
|
||||
## `core-js` errors when running scripts within the GitLab repository
|
||||
|
||||
The following command assumes you've set up the GitLab repository in the
|
||||
`~/workspace/gdk` directory. When running scripts within the GitLab repository,
|
||||
such as code transformations, you might run into issues with `core-js` like this:
|
||||
|
||||
```shell
|
||||
~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:7
|
||||
$({
|
||||
^
|
||||
TypeError: $ is not a function
|
||||
at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:6:1)
|
||||
at Module._compile (internal/modules/cjs/loader.js:1063:30)
|
||||
at Module._compile (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:99:24)
|
||||
at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
|
||||
at Object.newLoader [as .js] (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:104:7)
|
||||
at Module.load (internal/modules/cjs/loader.js:928:32)
|
||||
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
|
||||
at Module.require (internal/modules/cjs/loader.js:952:19)
|
||||
at require (internal/modules/cjs/helpers.js:88:18)
|
||||
at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/esnext.global-this.js:2:1)
|
||||
```
|
||||
|
||||
**Remedy - Try moving the script into a separate repository and point to it to files in the GitLab repository**
|
||||
|
|
|
@ -289,7 +289,7 @@ For example, to add support for files referenced by a `Widget` model with a
|
|||
t.binary :verification_checksum
|
||||
t.binary :verification_checksum_mismatched
|
||||
t.string :verification_failure, limit: 255
|
||||
t.text :last_sync_failure
|
||||
t.string :last_sync_failure, limit: 255
|
||||
|
||||
t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true
|
||||
t.index :retry_at
|
||||
|
@ -303,8 +303,6 @@ For example, to add support for files referenced by a `Widget` model with a
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
add_text_limit :widget_registry, :last_sync_failure, 255
|
||||
end
|
||||
|
||||
def down
|
||||
|
@ -940,7 +938,7 @@ For example, to add support for files referenced by a `Gizmos` model with a
|
|||
t.bigint :gizmo_id, null: false
|
||||
t.integer :state, default: 0, null: false, limit: 2
|
||||
t.integer :retry_count, default: 0, limit: 2
|
||||
t.text :last_sync_failure
|
||||
t.string :last_sync_failure, limit: 255
|
||||
t.boolean :force_to_redownload
|
||||
t.boolean :missing_on_primary
|
||||
|
||||
|
@ -948,8 +946,6 @@ For example, to add support for files referenced by a `Gizmos` model with a
|
|||
t.index :retry_at
|
||||
t.index :state
|
||||
end
|
||||
|
||||
add_text_limit :gizmo_registry, :last_sync_failure, 255
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -13610,11 +13610,11 @@ Whether public signup is enabled
|
|||
|
||||
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124918_signup_enabled.yml)
|
||||
|
||||
Group: `group::product intelligence`
|
||||
Group: `group::access`
|
||||
|
||||
Status: `data_available`
|
||||
|
||||
Tiers: `free`
|
||||
Tiers: `free`, `premium`, `ultimate`
|
||||
|
||||
### `topology.duration_s`
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ module Banzai
|
|||
|
||||
if url?(content)
|
||||
path = content
|
||||
elsif file = wiki.find_file(content)
|
||||
elsif file = wiki.find_file(content, load_content: false)
|
||||
path = ::File.join(wiki_base_path, file.path)
|
||||
end
|
||||
|
||||
|
|
|
@ -12,6 +12,19 @@ module Gitlab
|
|||
@name = gitaly_file.name
|
||||
@path = gitaly_file.path
|
||||
end
|
||||
|
||||
def self.from_blob(blob)
|
||||
hash = {
|
||||
name: File.basename(blob.name),
|
||||
mime_type: blob.mime_type,
|
||||
path: blob.path,
|
||||
raw_data: blob.data
|
||||
}
|
||||
|
||||
gitaly_file = Gitlab::GitalyClient::WikiFile.new(hash)
|
||||
|
||||
Gitlab::Git::WikiFile.new(gitaly_file)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,10 +25,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil) # rubocop:disable Metrics/ParameterLists
|
||||
context += [Tracking::StandardContext.new(project: project, user: user, namespace: namespace).to_context]
|
||||
contexts = [Tracking::StandardContext.new(project: project, user: user, namespace: namespace).to_context, *context]
|
||||
|
||||
snowplow.event(category, action, label: label, property: property, value: value, context: context)
|
||||
product_analytics.event(category, action, label: label, property: property, value: value, context: context)
|
||||
snowplow.event(category, action, label: label, property: property, value: value, context: contexts)
|
||||
product_analytics.event(category, action, label: label, property: property, value: value, context: contexts)
|
||||
end
|
||||
|
||||
def self_describing_event(schema_url, data:, context: nil)
|
||||
|
|
|
@ -56,9 +56,9 @@
|
|||
"@babel/preset-env": "^7.10.1",
|
||||
"@gitlab/at.js": "1.5.7",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "1.184.0",
|
||||
"@gitlab/svgs": "1.185.0",
|
||||
"@gitlab/tributejs": "1.0.0",
|
||||
"@gitlab/ui": "28.6.0",
|
||||
"@gitlab/ui": "28.9.1",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "^6.0.3-4",
|
||||
"@rails/ujs": "^6.0.3-4",
|
||||
|
|
|
@ -56,7 +56,7 @@ RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures do
|
|||
it 'benchmarks several pipelines' do
|
||||
path = 'images/example.jpg'
|
||||
gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
|
||||
allow(wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
|
||||
allow(wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
|
||||
allow(wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
|
||||
|
||||
puts "\n--> Benchmarking Full, Wiki, and Plain pipelines\n"
|
||||
|
|
|
@ -290,7 +290,7 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
|
|||
|
||||
path = 'images/example.jpg'
|
||||
gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
|
||||
expect(@wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
|
||||
expect(@wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
|
||||
allow(@wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
|
||||
|
||||
@html = markdown(@feat.raw_markdown, { pipeline: :wiki, wiki: @wiki, page_slug: @wiki_page.slug })
|
||||
|
|
|
@ -351,6 +351,7 @@ export const issues = {
|
|||
[mockIssue4.id]: mockIssue4,
|
||||
};
|
||||
|
||||
// The response from group project REST API
|
||||
export const mockRawGroupProjects = [
|
||||
{
|
||||
id: 0,
|
||||
|
@ -366,17 +367,34 @@ export const mockRawGroupProjects = [
|
|||
},
|
||||
];
|
||||
|
||||
export const mockGroupProjects = [
|
||||
{
|
||||
id: 0,
|
||||
name: 'Example Project',
|
||||
nameWithNamespace: 'Awesome Group / Example Project',
|
||||
fullPath: 'awesome-group/example-project',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'Foobar Project',
|
||||
nameWithNamespace: 'Awesome Group / Foobar Project',
|
||||
fullPath: 'awesome-group/foobar-project',
|
||||
},
|
||||
// The response from GraphQL endpoint
|
||||
export const mockGroupProject1 = {
|
||||
id: 0,
|
||||
name: 'Example Project',
|
||||
nameWithNamespace: 'Awesome Group / Example Project',
|
||||
fullPath: 'awesome-group/example-project',
|
||||
archived: false,
|
||||
};
|
||||
|
||||
export const mockGroupProject2 = {
|
||||
id: 1,
|
||||
name: 'Foobar Project',
|
||||
nameWithNamespace: 'Awesome Group / Foobar Project',
|
||||
fullPath: 'awesome-group/foobar-project',
|
||||
archived: false,
|
||||
};
|
||||
|
||||
export const mockArchivedGroupProject = {
|
||||
id: 2,
|
||||
name: 'Archived Project',
|
||||
nameWithNamespace: 'Awesome Group / Archived Project',
|
||||
fullPath: 'awesome-group/archived-project',
|
||||
archived: true,
|
||||
};
|
||||
|
||||
export const mockGroupProjects = [mockGroupProject1, mockGroupProject2];
|
||||
|
||||
export const mockActiveGroupProjects = [
|
||||
{ ...mockGroupProject1, archived: false },
|
||||
{ ...mockGroupProject2, archived: false },
|
||||
];
|
||||
|
|
|
@ -27,6 +27,7 @@ const mockDefaultFetchOptions = {
|
|||
with_shared: false,
|
||||
include_subgroups: true,
|
||||
order_by: 'similarity',
|
||||
archived: false,
|
||||
};
|
||||
|
||||
const itemsPerPage = 20;
|
||||
|
|
|
@ -1,30 +1,17 @@
|
|||
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { createLocalVue, mount } from '@vue/test-utils';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import ProjectSelect from '~/boards/components/project_select.vue';
|
||||
import defaultState from '~/boards/stores/state';
|
||||
|
||||
import { mockList, mockGroupProjects } from './mock_data';
|
||||
import { mockList, mockActiveGroupProjects } from './mock_data';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const actions = {
|
||||
fetchGroupProjects: jest.fn(),
|
||||
setSelectedProject: jest.fn(),
|
||||
};
|
||||
|
||||
const createStore = (state = defaultState) => {
|
||||
return new Vuex.Store({
|
||||
state,
|
||||
actions,
|
||||
});
|
||||
};
|
||||
|
||||
const mockProjectsList1 = mockGroupProjects.slice(0, 1);
|
||||
const mockProjectsList1 = mockActiveGroupProjects.slice(0, 1);
|
||||
|
||||
describe('ProjectSelect component', () => {
|
||||
let wrapper;
|
||||
let store;
|
||||
|
||||
const findLabel = () => wrapper.find("[data-testid='header-label']");
|
||||
const findGlDropdown = () => wrapper.find(GlDropdown);
|
||||
|
@ -36,20 +23,37 @@ describe('ProjectSelect component', () => {
|
|||
const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']");
|
||||
const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']");
|
||||
|
||||
const createWrapper = (state = {}) => {
|
||||
const store = createStore({
|
||||
groupProjects: [],
|
||||
groupProjectsFlags: {
|
||||
isLoading: false,
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
const createStore = ({ state, activeGroupProjects }) => {
|
||||
Vue.use(Vuex);
|
||||
|
||||
store = new Vuex.Store({
|
||||
state: {
|
||||
defaultState,
|
||||
groupProjectsFlags: {
|
||||
isLoading: false,
|
||||
pageInfo: {
|
||||
hasNextPage: false,
|
||||
},
|
||||
},
|
||||
...state,
|
||||
},
|
||||
...state,
|
||||
actions: {
|
||||
fetchGroupProjects: jest.fn(),
|
||||
setSelectedProject: jest.fn(),
|
||||
},
|
||||
getters: {
|
||||
activeGroupProjects: () => activeGroupProjects,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const createWrapper = ({ state = {}, activeGroupProjects = [] } = {}) => {
|
||||
createStore({
|
||||
state,
|
||||
activeGroupProjects,
|
||||
});
|
||||
|
||||
wrapper = mount(ProjectSelect, {
|
||||
localVue,
|
||||
propsData: {
|
||||
list: mockList,
|
||||
},
|
||||
|
@ -93,7 +97,7 @@ describe('ProjectSelect component', () => {
|
|||
describe('when dropdown menu is open', () => {
|
||||
describe('by default', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ groupProjects: mockGroupProjects });
|
||||
createWrapper({ activeGroupProjects: mockActiveGroupProjects });
|
||||
});
|
||||
|
||||
it('shows GlSearchBoxByType with default attributes', () => {
|
||||
|
@ -128,7 +132,7 @@ describe('ProjectSelect component', () => {
|
|||
|
||||
describe('when a project is selected', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ groupProjects: mockProjectsList1 });
|
||||
createWrapper({ activeGroupProjects: mockProjectsList1 });
|
||||
|
||||
findFirstGlDropdownItem().find('button').trigger('click');
|
||||
});
|
||||
|
@ -142,7 +146,7 @@ describe('ProjectSelect component', () => {
|
|||
|
||||
describe('when projects are loading', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ groupProjectsFlags: { isLoading: true } });
|
||||
createWrapper({ state: { groupProjectsFlags: { isLoading: true } } });
|
||||
});
|
||||
|
||||
it('displays and hides gl-loading-icon while and after fetching data', () => {
|
||||
|
|
|
@ -7,6 +7,8 @@ import {
|
|||
mockIssuesByListId,
|
||||
issues,
|
||||
mockLists,
|
||||
mockGroupProject1,
|
||||
mockArchivedGroupProject,
|
||||
} from '../mock_data';
|
||||
|
||||
describe('Boards - Getters', () => {
|
||||
|
@ -165,4 +167,14 @@ describe('Boards - Getters', () => {
|
|||
expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockLists[1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activeGroupProjects', () => {
|
||||
const state = {
|
||||
groupProjects: [mockGroupProject1, mockArchivedGroupProject],
|
||||
};
|
||||
|
||||
it('returns only returns non-archived group projects', () => {
|
||||
expect(getters.activeGroupProjects(state)).toEqual([mockGroupProject1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,7 +22,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do
|
|||
path: 'images/image.jpg',
|
||||
raw_data: '')
|
||||
wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double)
|
||||
expect(wiki).to receive(:find_file).with('images/image.jpg').and_return(wiki_file)
|
||||
expect(wiki).to receive(:find_file).with('images/image.jpg', load_content: false).and_return(wiki_file)
|
||||
|
||||
tag = '[[images/image.jpg]]'
|
||||
doc = filter("See #{tag}", wiki: wiki)
|
||||
|
@ -31,7 +31,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do
|
|||
end
|
||||
|
||||
it 'does not creates img tag if image does not exist' do
|
||||
expect(wiki).to receive(:find_file).with('images/image.jpg').and_return(nil)
|
||||
expect(wiki).to receive(:find_file).with('images/image.jpg', load_content: false).and_return(nil)
|
||||
|
||||
tag = '[[images/image.jpg]]'
|
||||
doc = filter("See #{tag}", wiki: wiki)
|
||||
|
|
|
@ -61,8 +61,8 @@ RSpec.describe Gitlab::Tracking do
|
|||
expect(args[:property]).to eq('property')
|
||||
expect(args[:value]).to eq(1.5)
|
||||
expect(args[:context].length).to eq(2)
|
||||
expect(args[:context].first).to eq(other_context)
|
||||
expect(args[:context].last.to_json[:schema]).to eq(Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL)
|
||||
expect(args[:context].first.to_json[:schema]).to eq(Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL)
|
||||
expect(args[:context].last).to eq(other_context)
|
||||
end
|
||||
|
||||
described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5,
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require 'email_spec'
|
||||
|
||||
RSpec.describe Emails::InProductMarketing do
|
||||
include EmailSpec::Matchers
|
||||
include InProductMarketingHelper
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
||||
describe '#in_product_marketing_email' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:track, :series) do
|
||||
:create | 0
|
||||
:create | 1
|
||||
:create | 2
|
||||
:verify | 0
|
||||
:verify | 1
|
||||
:verify | 2
|
||||
:trial | 0
|
||||
:trial | 1
|
||||
:trial | 2
|
||||
:team | 0
|
||||
:team | 1
|
||||
:team | 2
|
||||
end
|
||||
|
||||
with_them do
|
||||
subject { Notify.in_product_marketing_email(user.id, group.id, track, series) }
|
||||
|
||||
it 'has the correct subject and content' do
|
||||
aggregate_failures do
|
||||
is_expected.to have_subject(subject_line(track, series))
|
||||
is_expected.to have_body_text(in_product_marketing_title(track, series))
|
||||
is_expected.to have_body_text(in_product_marketing_subtitle(track, series))
|
||||
is_expected.to have_body_text(in_product_marketing_cta_text(track, series))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -354,27 +354,47 @@ RSpec.shared_examples 'wiki model' do
|
|||
subject.repository.create_file(user, 'image.png', image, branch_name: subject.default_branch, message: 'add image')
|
||||
end
|
||||
|
||||
it 'returns the latest version of the file if it exists' do
|
||||
file = subject.find_file('image.png')
|
||||
shared_examples 'find_file results' do
|
||||
it 'returns the latest version of the file if it exists' do
|
||||
file = subject.find_file('image.png')
|
||||
|
||||
expect(file.mime_type).to eq('image/png')
|
||||
expect(file.mime_type).to eq('image/png')
|
||||
end
|
||||
|
||||
it 'returns nil if the page does not exist' do
|
||||
expect(subject.find_file('non-existent')).to eq(nil)
|
||||
end
|
||||
|
||||
it 'returns a Gitlab::Git::WikiFile instance' do
|
||||
file = subject.find_file('image.png')
|
||||
|
||||
expect(file).to be_a Gitlab::Git::WikiFile
|
||||
end
|
||||
|
||||
it 'returns the whole file' do
|
||||
file = subject.find_file('image.png')
|
||||
image.rewind
|
||||
|
||||
expect(file.raw_data.b).to eq(image.read.b)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns nil if the page does not exist' do
|
||||
expect(subject.find_file('non-existent')).to eq(nil)
|
||||
it_behaves_like 'find_file results'
|
||||
|
||||
context 'when load_content is disabled' do
|
||||
it 'includes the file data in the Gitlab::Git::WikiFile' do
|
||||
file = subject.find_file('image.png', load_content: false)
|
||||
|
||||
expect(file.raw_data).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns a Gitlab::Git::WikiFile instance' do
|
||||
file = subject.find_file('image.png')
|
||||
context 'when feature flag :gitaly_find_file is disabled' do
|
||||
before do
|
||||
stub_feature_flags(gitaly_find_file: false)
|
||||
end
|
||||
|
||||
expect(file).to be_a Gitlab::Git::WikiFile
|
||||
end
|
||||
|
||||
it 'returns the whole file' do
|
||||
file = subject.find_file('image.png')
|
||||
image.rewind
|
||||
|
||||
expect(file.raw_data.b).to eq(image.read.b)
|
||||
it_behaves_like 'find_file results'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
|
|||
subject { project_helper.all_ee_changes }
|
||||
|
||||
it 'returns all changed files starting with ee/' do
|
||||
expect(project_helper).to receive(:all_changed_files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k])
|
||||
expect(fake_helper).to receive(:all_changed_files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k])
|
||||
|
||||
is_expected.to match_array(%w[ee/wine.rb ee/lib/ido.rb])
|
||||
end
|
||||
|
|
|
@ -149,7 +149,7 @@ module Tooling
|
|||
end
|
||||
|
||||
def all_ee_changes
|
||||
all_changed_files.grep(%r{\Aee/})
|
||||
helper.all_changed_files.grep(%r{\Aee/})
|
||||
end
|
||||
|
||||
def project_name
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -897,20 +897,20 @@
|
|||
stylelint-declaration-strict-value "1.7.7"
|
||||
stylelint-scss "3.18.0"
|
||||
|
||||
"@gitlab/svgs@1.184.0":
|
||||
version "1.184.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.184.0.tgz#7fe90309999b987362eb1649aa91df24748d3df1"
|
||||
integrity sha512-K8r5jhnjWR4347j2ADFek7yLgs+MDGqm9cjvwT04aa1vSfhvheLqyKGUy1yz8v7RzXC0Mev6+RT1AbK7m6Ay+w==
|
||||
"@gitlab/svgs@1.185.0":
|
||||
version "1.185.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.185.0.tgz#15b5c6d680b5fcfc2deb2a5decef427939e34ed7"
|
||||
integrity sha512-1XIyOm8MyTZi8H0v9WVnqVDziTLH8Q5H/fKfBj+nzprHNYvJj2fvz+EV9N5luF90KTzlQf1QYCbHWe2zKLZuUw==
|
||||
|
||||
"@gitlab/tributejs@1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
||||
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
||||
|
||||
"@gitlab/ui@28.6.0":
|
||||
version "28.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.6.0.tgz#dae21f072cbf898bfa87dcefbef951c2811ecba0"
|
||||
integrity sha512-6LvPoQbSzbY9kmP3y84eQj48w6XzgLktSBX0NM2IB3/sZzEtFlpLpnqmv6cWhS2V1HAM7xW6nLZ4SGyM3JRhvA==
|
||||
"@gitlab/ui@28.9.1":
|
||||
version "28.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.9.1.tgz#7d4d4502ff09fca19ab815504f80afbf03dd2fc1"
|
||||
integrity sha512-+JqkpwzkKBnxo4KkC8XSPEJ5Au9y+TIOE7w9I5o+04krgWCbZKNqaiKZkg2IqSlo/sZSfvihXZMhEVc/JXf7HQ==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
"@gitlab/vue-toasted" "^1.3.0"
|
||||
|
|
Loading…
Reference in New Issue