Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-02-17 15:09:01 +00:00
parent b84eeb256c
commit b304a72312
79 changed files with 782 additions and 332 deletions

View File

@ -126,7 +126,6 @@ review-build-cng:
- .default-tags
- .default-retry
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
dependencies: []
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
@ -142,6 +141,9 @@ review-deploy:
- .review-workflow-base
- .review:rules:mr-and-schedule
stage: review
needs:
- job: review-build-cng
artifacts: false
allow_failure: true
before_script:
- '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"'
@ -169,6 +171,7 @@ review-deploy:
extends: .review-workflow-base
environment:
action: stop
dependencies: []
variables:
# We're cloning the repo instead of downloading the script for now
# because some repos are private and CI_JOB_TOKEN cannot access files.

View File

@ -4,14 +4,34 @@
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from './file_row_stats.vue';
export default {
name: 'DiffFileRow',
components: {
FileRow,
FileRowStats,
},
props: {
file: {
type: Object,
required: true,
},
hideFileStats: {
type: Boolean,
required: true,
},
},
computed: {
showFileRowStats() {
return !this.hideFileStats && this.file.type === 'blob';
},
},
};
</script>
<template>
<file-row v-bind="$attrs" v-on="$listeners" />
<file-row :file="file" :hide-file-stats="hideFileStats" v-bind="$attrs" v-on="$listeners">
<file-row-stats v-if="showFileRowStats" :file="file" />
</file-row>
</template>

View File

@ -5,7 +5,6 @@ import { s__, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import FileTree from '~/vue_shared/components/file_tree.vue';
import DiffFileRow from './diff_file_row.vue';
import FileRowStats from './file_row_stats.vue';
export default {
directives: {
@ -49,9 +48,6 @@ export default {
return acc;
}, []);
},
fileRowExtraComponent() {
return this.hideFileStats ? null : FileRowStats;
},
},
methods: {
...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']),
@ -98,8 +94,8 @@ export default {
:key="file.key"
:file="file"
:level="0"
:hide-file-stats="hideFileStats"
:hide-extra-on-tree="true"
:extra-component="fileRowExtraComponent"
:show-changed-icon="true"
:file-row-component="$options.DiffFileRow"
@toggleTreeOpen="toggleTreeOpen"

View File

@ -719,7 +719,7 @@ GfmAutoComplete.Milestones = {
};
GfmAutoComplete.Loading = {
template:
'<li style="pointer-events: none;"><i class="fa fa-spinner fa-spin"></i> Loading...</li>',
'<li style="pointer-events: none;"><span class="spinner align-text-bottom mr-1"></span>Loading...</li>',
};
export default GfmAutoComplete;

View File

@ -4,14 +4,35 @@
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from './file_row_extra.vue';
export default {
name: 'IdeFileRow',
components: {
FileRow,
FileRowExtra,
},
props: {
file: {
type: Object,
required: true,
},
},
data() {
return {
dropdownOpen: false,
};
},
methods: {
toggleDropdown(val) {
this.dropdownOpen = val;
},
},
};
</script>
<template>
<file-row v-bind="$attrs" v-on="$listeners" />
<file-row :file="file" v-bind="$attrs" @mouseleave="toggleDropdown(false)" v-on="$listeners">
<file-row-extra :file="file" :dropdown-open="dropdownOpen" @toggle="toggleDropdown($event)" />
</file-row>
</template>

View File

@ -4,7 +4,6 @@ import { GlSkeletonLoading } from '@gitlab/ui';
import FileTree from '~/vue_shared/components/file_tree.vue';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
import FileRowExtra from './file_row_extra.vue';
export default {
components: {
@ -36,7 +35,6 @@ export default {
methods: {
...mapActions(['updateViewer', 'toggleTreeOpen']),
},
FileRowExtra,
IdeFileRow,
};
</script>
@ -60,7 +58,6 @@ export default {
:key="file.key"
:file="file"
:level="0"
:extra-component="$options.FileRowExtra"
:file-row-component="$options.IdeFileRow"
@toggleTreeOpen="toggleTreeOpen"
/>

View File

@ -201,9 +201,15 @@ document.addEventListener('DOMContentLoaded', () => {
});
if (bootstrapBreakpoint === 'sm' || bootstrapBreakpoint === 'xs') {
const $rightSidebar = $('aside.right-sidebar, .layout-page');
const $rightSidebar = $('aside.right-sidebar');
const $layoutPage = $('.layout-page');
$rightSidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
if ($rightSidebar.length > 0) {
$rightSidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
$layoutPage.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
} else {
$layoutPage.removeClass('right-sidebar-expanded right-sidebar-collapsed');
}
}
// prevent default action for disabled buttons

View File

@ -77,7 +77,7 @@ export default {
};
</script>
<template>
<div class="mr-source-target append-bottom-default">
<div class="d-flex mr-source-target append-bottom-default">
<mr-widget-icon name="git-merge" />
<div class="git-merge-container d-flex">
<div class="normal">

View File

@ -0,0 +1,45 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import MrWidgetIcon from './mr_widget_icon.vue';
export default {
name: 'MRWidgetSuggestPipeline',
iconName: 'status_notfound',
components: {
GlLink,
GlSprintf,
MrWidgetIcon,
},
props: {
pipelinePath: {
type: String,
required: true,
},
},
};
</script>
<template>
<div class="d-flex mr-pipeline-suggest append-bottom-default">
<mr-widget-icon :name="$options.iconName" />
<gl-sprintf
class="js-no-pipeline-message"
:message="
s__(`mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd}
%{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd}
to create one.`)
"
>
<template #prefixToLink="{content}">
<strong>
{{ content }}
</strong>
</template>
<template #addPipelineLink="{content}">
<gl-link :href="pipelinePath" class="ml-2">
{{ content }}
</gl-link>
&nbsp;
</template>
</gl-sprintf>
</div>
</template>

View File

@ -9,6 +9,7 @@ import SmartInterval from '~/smart_interval';
import createFlash from '../flash';
import Loading from './components/loading.vue';
import WidgetHeader from './components/mr_widget_header.vue';
import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue';
import WidgetMergeHelp from './components/mr_widget_merge_help.vue';
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
import Deployment from './components/deployment/deployment.vue';
@ -46,6 +47,7 @@ export default {
components: {
Loading,
'mr-widget-header': WidgetHeader,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
'mr-widget-merge-help': WidgetMergeHelp,
MrWidgetPipelineContainer,
Deployment,
@ -99,6 +101,9 @@ export default {
shouldRenderPipelines() {
return this.mr.hasCI;
},
shouldSuggestPipelines() {
return gon.features?.suggestPipeline && !this.mr.hasCI && this.mr.mergeRequestAddCiConfigPath;
},
shouldRenderRelatedLinks() {
return Boolean(this.mr.relatedLinks) && !this.mr.isNothingToMergeState;
},
@ -353,6 +358,11 @@ export default {
<template>
<div v-if="mr" class="mr-state-widget prepend-top-default">
<mr-widget-header :mr="mr" />
<mr-widget-suggest-pipeline
v-if="shouldSuggestPipelines"
class="mr-widget-workflow"
:pipeline-path="mr.mergeRequestAddCiConfigPath"
/>
<mr-widget-pipeline-container
v-if="shouldRenderPipelines"
class="mr-widget-workflow"

View File

@ -175,6 +175,8 @@ export default class MergeRequestStore {
this.securityApprovalsHelpPagePath = data.security_approvals_help_page_path;
this.eligibleApproversDocsPath = data.eligible_approvers_docs_path;
this.mergeImmediatelyDocsPath = data.merge_immediately_docs_path;
this.mergeRequestAddCiConfigPath = data.merge_request_add_ci_config_path;
this.humanAccess = data.human_access;
}
get isNothingToMergeState() {

View File

@ -1,5 +1,4 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
import FileHeader from '~/vue_shared/components/file_row_header.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
@ -9,7 +8,6 @@ export default {
components: {
FileHeader,
FileIcon,
Icon,
ChangedFileIcon,
},
props: {
@ -21,27 +19,12 @@ export default {
type: Number,
required: true,
},
extraComponent: {
type: Object,
required: false,
default: null,
},
hideExtraOnTree: {
type: Boolean,
required: false,
default: false,
},
showChangedIcon: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
dropdownOpen: false,
};
},
computed: {
isTree() {
return this.file.type === 'tree';
@ -120,9 +103,6 @@ export default {
return this.$router.currentRoute.path === `/project${this.file.url}`;
},
toggleDropdown(val) {
this.dropdownOpen = val;
},
},
};
</script>
@ -136,7 +116,7 @@ export default {
class="file-row"
role="button"
@click="clickFile"
@mouseleave="toggleDropdown(false)"
@mouseleave="$emit('mouseleave', $event)"
>
<div class="file-row-name-container">
<span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated">
@ -152,13 +132,7 @@ export default {
<changed-file-icon v-else :file="file" :size="16" class="append-right-5" />
{{ file.name }}
</span>
<component
:is="extraComponent"
v-if="extraComponent && !(hideExtraOnTree && file.type === 'tree')"
:file="file"
:dropdown-open="dropdownOpen"
@toggle="toggleDropdown($event)"
/>
<slot></slot>
</div>
</div>
</template>

View File

@ -3,6 +3,8 @@
*
*/
$mr-widget-min-height: 69px;
.space-children {
@include clearfix;
@ -555,12 +557,11 @@
}
.mr-source-target {
display: flex;
flex-wrap: wrap;
border-radius: $border-radius-default;
padding: $gl-padding;
border: 1px solid $border-color;
min-height: 69px;
min-height: $mr-widget-min-height;
@include media-breakpoint-up(md) {
align-items: center;
@ -599,6 +600,22 @@
}
}
.mr-pipeline-suggest {
flex-wrap: wrap;
border-radius: $border-radius-default;
padding: $gl-padding;
border: 1px solid $border-color;
min-height: $mr-widget-min-height;
@include media-breakpoint-up(md) {
align-items: center;
}
.circle-icon-container {
color: $gl-text-color-quaternary;
}
}
.card-new-merge-request {
.card-header {
padding: 5px 10px;

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
##
# Concern for setting Sidekiq settings for the various Secure product queues
#
module SecurityScansQueue
extend ActiveSupport::Concern
included do
queue_namespace :security_scans
feature_category :static_application_security_testing
end
end

View File

@ -0,0 +1,5 @@
---
title: Destroy the OAuth application when Geo secondary becomes a primary
merge_request: 25154
author: briankabiro
type: other

View File

@ -0,0 +1,6 @@
---
title: update main javascript file to only apply right sidebar class when an aside
is present
merge_request:
author: Oregand
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Remove name & path from list of excluded attributes during Group Import
merge_request: 25342
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Internationalize messages for group audit events
merge_request: 25233
author: Takuya Noguchi
type: other

View File

@ -0,0 +1,5 @@
---
title: Migrate from class .fa-spinner to .spinner in app/assets/javascripts/gfm_auto_complete.js
merge_request: 25039
author: rk4bir
type: changed

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class MigrateStoreSecurityReportsSidekiqQueue < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
sidekiq_queue_migrate 'pipeline_default:store_security_reports', to: 'security_scans:store_security_reports'
end
def down
sidekiq_queue_migrate 'security_scans:store_security_reports', to: 'pipeline_default:store_security_reports'
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class MigrateSyncSecurityReportsToReportApprovalRulesSidekiqQueue < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
sidekiq_queue_migrate 'pipeline_default:sync_security_reports_to_report_approval_rules',
to: 'security_scans:sync_security_reports_to_report_approval_rules'
end
def down
sidekiq_queue_migrate 'security_scans:sync_security_reports_to_report_approval_rules',
to: 'pipeline_default:sync_security_reports_to_report_approval_rules'
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_02_13_204737) do
ActiveRecord::Schema.define(version: 2020_02_13_220211) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"

View File

@ -261,7 +261,10 @@ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your 'front door' GitLab URL or an internal load
# balancer.
gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
# Possible values could be: 'http://10.23.101.53', 'https://gitlab.example.com',
# etc. Please replace GITLAB_SERVER_ADDRESS with proper value and change schema
# to 'https' in case you use encrypted connection.
gitlab_rails['internal_api_url'] = 'http://GITLAB_SERVER_ADDRESS'
# Replace PRAEFECT_INTERNAL_TOKEN below with a real secret.
gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN'
@ -324,6 +327,12 @@ git_data_dirs({
# Replace GITLAB_SHELL_SECRET_TOKEN below with real secret
gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
# Possible values could be: 'http://10.23.101.53', 'https://gitlab.example.com',
# etc. Please replace GITLAB_SERVER_ADDRESS with proper value and change schema
# to 'https' in case you use encrypted connection. For more info please refer
# to https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab
external_url "http://<GITLAB_SERVER_ADDRESS>"
```
Replace `GITLAB_SHELL_SECRET_TOKEN` and `PRAEFECT_EXTERNAL_TOKEN`

View File

@ -42,25 +42,25 @@ sprite_icon(icon_name, size: nil, css_class: '')
### Usage in Vue
We have a special Vue component for our sprite icons in `\vue_shared\components\icon.vue`.
[GitLab UI][gitlab-ui], our components library, provides a component to display sprite icons.
Sample usage :
```javascript
```html
<script>
import Icon from "~/vue_shared/components/icon.vue"
import { GlIcon } from "@gitlab/ui";
export default {
components: {
Icon,
GlIcon,
},
};
<script>
<template>
<icon
<gl-icon
name="issues"
:size="24"
class="icon-danger"
/>
</template>
```
@ -95,7 +95,7 @@ To use an SVG illustrations in a template provide the path as a property and dis
Component:
```js
```html
<script>
export default {
props: {
@ -106,6 +106,7 @@ export default {
},
};
<script>
<template>
<img :src="svgIllustrationPath" />
</template>
@ -114,3 +115,4 @@ export default {
[npm]: https://www.npmjs.com/package/@gitlab/svgs
[gitlab-svgs]: https://gitlab.com/gitlab-org/gitlab-svgs
[svg-preview]: https://gitlab-org.gitlab.io/gitlab-svgs
[gitlab-ui]: https://gitlab-org.gitlab.io/gitlab-ui/

View File

@ -253,7 +253,6 @@ graph RL;
E[review-build-cng];
F[build-qa-image];
G[review-deploy];
G2["schedule:review-deploy<br/>(master only)"];
I["karma, jest, webpack-dev-server, static-analysis"];
I2["karma-foss, jest-foss<br/>(EE default refs only)"];
J["compile-assets pull-push-cache<br/>(master only)"];
@ -297,19 +296,16 @@ subgraph "`post-test` stage"
subgraph "`review-prepare` stage"
E -.-> |needs| C;
E2["schedule:review-build-cng<br/>(master schedule only)"] -.-> |needs| C;
end
subgraph "`review` stage"
G --> |happens after| E
G2 --> |happens after| E2
G -.-> |needs| E
end
subgraph "`qa` stage"
Q -.-> |needs| C;
Q -.-> |needs| F;
QA1["review-qa-smoke, review-qa-all, review-performance, dast"] -.-> |needs and depends on| G;
QA2["schedule:review-performance<br/>(master only)"] -.-> |needs and depends on| G2;
QA1["review-qa-smoke, review-qa-all, review-performance, dast"] -.-> |needs| G;
end
subgraph "`post-qa` stage"

View File

@ -28,8 +28,6 @@ included_attributes:
excluded_attributes:
group:
- :id
- :name
- :path
- :owner_id
- :parent_id
- :created_at

View File

@ -7806,6 +7806,9 @@ msgstr ""
msgid "Events"
msgstr ""
msgid "Events in %{group_name}"
msgstr ""
msgid "Events in %{project_path}"
msgstr ""
@ -9525,6 +9528,9 @@ msgstr ""
msgid "Group %{group_name} was successfully created."
msgstr ""
msgid "Group Audit Events"
msgstr ""
msgid "Group CI/CD settings"
msgstr ""
@ -23123,6 +23129,9 @@ msgstr ""
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
msgid "mrWidget|Added to the merge train by"
msgstr ""

View File

@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import DiffFileRow from '~/diffs/components/diff_file_row.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowStats from '~/diffs/components/file_row_stats.vue';
describe('Diff File Row component', () => {
let wrapper;
@ -16,10 +17,42 @@ describe('Diff File Row component', () => {
});
it('renders file row component', () => {
createComponent({
const sharedProps = {
level: 4,
file: {},
};
const diffFileRowProps = {
hideFileStats: false,
};
createComponent({
...sharedProps,
...diffFileRowProps,
});
expect(wrapper.find(FileRow).props()).toEqual(
expect.objectContaining({
...sharedProps,
}),
);
});
describe('FileRowStats components', () => {
it.each`
type | hideFileStats | value | desc
${'blob'} | ${false} | ${true} | ${'is shown if file type is blob'}
${'tree'} | ${false} | ${false} | ${'is hidden if file is not blob'}
${'blob'} | ${true} | ${false} | ${'is hidden if hideFileStats is true'}
`('$desc', ({ type, value, hideFileStats }) => {
createComponent({
level: 4,
file: {
type,
},
hideFileStats,
});
expect(wrapper.find(FileRowStats).exists()).toEqual(value);
});
expect(wrapper.find(FileRow).exists()).toEqual(true);
});
});

View File

@ -0,0 +1 @@
Element.prototype.scrollIntoView = jest.fn();

View File

@ -1,3 +1,4 @@
import './element_scroll_into_view';
import './get_client_rects';
import './inner_text';
import './window_scroll_to';

View File

@ -1,25 +1,117 @@
import { shallowMount } from '@vue/test-utils';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex from 'vuex';
import IdeFileRow from '~/ide/components/ide_file_row.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import { createStore } from '~/ide/stores';
const localVue = createLocalVue();
localVue.use(Vuex);
const TEST_EXTRA_PROPS = {
testattribute: 'abc',
};
const defaultComponentProps = (type = 'tree') => ({
level: 4,
file: {
type,
name: 'js',
},
});
describe('Ide File Row component', () => {
let wrapper;
const createComponent = (props = {}) => {
wrapper = shallowMount(IdeFileRow, {
propsData: { ...props },
const createComponent = (props = {}, options = {}) => {
wrapper = mount(IdeFileRow, {
propsData: {
...defaultComponentProps(),
...props,
},
store: createStore(),
localVue,
...options,
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('renders file row component', () => {
createComponent({
level: 4,
file: {},
const findFileRowExtra = () => wrapper.find(FileRowExtra);
const findFileRow = () => wrapper.find(FileRow);
const hasDropdownOpen = () => findFileRowExtra().props('dropdownOpen');
it('fileRow component has listeners', () => {
const toggleTreeOpen = jest.fn();
createComponent(
{},
{
listeners: {
toggleTreeOpen,
},
},
);
findFileRow().vm.$emit('toggleTreeOpen');
return wrapper.vm.$nextTick().then(() => {
expect(toggleTreeOpen).toHaveBeenCalled();
});
});
describe('default', () => {
beforeEach(() => {
createComponent(TEST_EXTRA_PROPS);
});
it('renders file row component', () => {
const fileRow = findFileRow();
expect(fileRow.props()).toEqual(expect.objectContaining(defaultComponentProps()));
expect(fileRow.attributes()).toEqual(expect.objectContaining(TEST_EXTRA_PROPS));
});
it('renders file row extra', () => {
const extra = findFileRowExtra();
expect(extra.exists()).toBe(true);
expect(extra.props()).toEqual({
file: defaultComponentProps().file,
dropdownOpen: false,
});
});
});
describe('with open dropdown', () => {
beforeEach(() => {
createComponent();
findFileRowExtra().vm.$emit('toggle', true);
return wrapper.vm.$nextTick();
});
it('shows open dropdown', () => {
expect(hasDropdownOpen()).toBe(true);
});
it('hides dropdown when mouseleave', () => {
findFileRow().vm.$emit('mouseleave');
return wrapper.vm.$nextTick().then(() => {
expect(hasDropdownOpen()).toEqual(false);
});
});
it('hides dropdown on toggle', () => {
findFileRowExtra().vm.$emit('toggle', false);
return wrapper.vm.$nextTick().then(() => {
expect(hasDropdownOpen()).toEqual(false);
});
});
expect(wrapper.find(FileRow).exists()).toEqual(true);
});
});

View File

@ -0,0 +1,52 @@
import { mount } from '@vue/test-utils';
import { GlLink } from '@gitlab/ui';
import suggestPipelineComponent from '~/vue_merge_request_widget/components/mr_widget_suggest_pipeline.vue';
import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
describe('MRWidgetHeader', () => {
let wrapper;
const pipelinePath = '/foo/bar/add/pipeline/path';
const iconName = 'status_notfound';
beforeEach(() => {
wrapper = mount(suggestPipelineComponent, {
propsData: { pipelinePath },
});
});
afterEach(() => {
wrapper.destroy();
});
describe('template', () => {
it('renders add pipeline file link', () => {
const link = wrapper.find(GlLink);
return wrapper.vm.$nextTick().then(() => {
expect(link.exists()).toBe(true);
expect(link.attributes().href).toBe(pipelinePath);
});
});
it('renders the expected text', () => {
const messageText = /\s*No pipeline\s*Add the .gitlab-ci.yml file\s*to create one./;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.text()).toMatch(messageText);
});
});
it('renders widget icon', () => {
const icon = wrapper.find(MrWidgetIcon);
return wrapper.vm.$nextTick().then(() => {
expect(icon.exists()).toBe(true);
expect(icon.props()).toEqual(
expect.objectContaining({
name: iconName,
}),
);
});
});
});
});

View File

@ -16,6 +16,7 @@ export default {
updated_at: '2017-04-07T15:39:25.852Z',
time_estimate: 0,
total_time_spent: 0,
human_access: 'Maintainer',
human_time_estimate: null,
human_total_time_spent: null,
in_progress_merge_commit_sha: null,
@ -34,6 +35,7 @@ export default {
target_branch: 'master',
target_project_id: 19,
target_project_full_path: '/group2/project2',
merge_request_add_ci_config_path: '/group2/project2/new/pipeline',
metrics: {
merged_by: {
name: 'Administrator',

View File

@ -94,6 +94,61 @@ describe('mrWidgetOptions', () => {
});
});
describe('shouldSuggestPipelines', () => {
describe('given suggestPipeline feature flag is enabled', () => {
beforeEach(() => {
gon.features = { suggestPipeline: true };
vm = mountComponent(MrWidgetOptions, {
mrData: { ...mockData },
});
});
afterEach(() => {
gon.features = {};
});
it('should suggest pipelines when none exist', () => {
vm.mr.mergeRequestAddCiConfigPath = 'some/path';
vm.mr.hasCI = false;
expect(vm.shouldSuggestPipelines).toBeTruthy();
});
it('should not suggest pipelines when they exist', () => {
vm.mr.mergeRequestAddCiConfigPath = null;
vm.mr.hasCI = false;
expect(vm.shouldSuggestPipelines).toBeFalsy();
});
it('should not suggest pipelines hasCI is true', () => {
vm.mr.mergeRequestAddCiConfigPath = 'some/path';
vm.mr.hasCI = true;
expect(vm.shouldSuggestPipelines).toBeFalsy();
});
});
describe('given suggestPipeline feature flag is not enabled', () => {
beforeEach(() => {
gon.features = { suggestPipeline: false };
vm = mountComponent(MrWidgetOptions, {
mrData: { ...mockData },
});
});
afterEach(() => {
gon.features = {};
});
it('should not suggest pipelines', () => {
vm.mr.mergeRequestAddCiConfigPath = null;
expect(vm.shouldSuggestPipelines).toBeFalsy();
});
});
});
describe('shouldRenderRelatedLinks', () => {
it('should return false for the initial data', () => {
expect(vm.shouldRenderRelatedLinks).toBeFalsy();

View File

@ -83,4 +83,18 @@ describe('MergeRequestStore', () => {
});
});
});
describe('setPaths', () => {
it('should set the add ci config path', () => {
store.setData({ ...mockData });
expect(store.mergeRequestAddCiConfigPath).toEqual('/group2/project2/new/pipeline');
});
it('should set humanAccess=Maintainer when user has that role', () => {
store.setData({ ...mockData });
expect(store.humanAccess).toEqual('Maintainer');
});
});
});

View File

@ -1,7 +1,6 @@
import Vue from 'vue';
import { file } from 'spec/ide/helpers';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('File row component', () => {
@ -17,9 +16,6 @@ describe('File row component', () => {
vm.$destroy();
});
const findNewDropdown = () => vm.$el.querySelector('.ide-new-btn .dropdown');
const findNewDropdownButton = () => vm.$el.querySelector('.ide-new-btn .dropdown button');
it('renders name', () => {
createComponent({
file: file('t4'),
@ -88,59 +84,4 @@ describe('File row component', () => {
expect(vm.$el.classList).toContain('js-file-row-header');
});
describe('new dropdown', () => {
beforeEach(() => {
createComponent({
file: file('t5'),
level: 1,
extraComponent: FileRowExtra,
});
});
it('renders in extra component', () => {
expect(findNewDropdown()).not.toBe(null);
});
it('is hidden at start', () => {
expect(findNewDropdown()).not.toHaveClass('show');
});
it('is opened when button is clicked', done => {
expect(vm.dropdownOpen).toBe(false);
findNewDropdownButton().dispatchEvent(new Event('click'));
vm.$nextTick()
.then(() => {
expect(vm.dropdownOpen).toBe(true);
expect(findNewDropdown()).toHaveClass('show');
})
.then(done)
.catch(done.fail);
});
describe('when opened', () => {
beforeEach(() => {
vm.dropdownOpen = true;
});
it('stays open when button triggers mouseout', () => {
findNewDropdownButton().dispatchEvent(new Event('mouseout'));
expect(vm.dropdownOpen).toBe(true);
});
it('stays open when button triggers mouseleave', () => {
findNewDropdownButton().dispatchEvent(new Event('mouseleave'));
expect(vm.dropdownOpen).toBe(true);
});
it('closes when row triggers mouseleave', () => {
vm.$el.dispatchEvent(new Event('mouseleave'));
expect(vm.dropdownOpen).toBe(false);
});
});
});
});

View File

@ -82,8 +82,6 @@ describe Gitlab::ImportExport::GroupTreeRestorer do
shared_examples 'excluded attributes' do
excluded_attributes = %w[
id
name
path
owner_id
parent_id
created_at

View File

@ -160,8 +160,6 @@ describe Gitlab::ImportExport::GroupTreeSaver do
shared_examples 'excluded attributes' do
excluded_attributes = %w[
id
name
path
owner_id
parent_id
created_at

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200213220159_migrate_store_security_reports_sidekiq_queue.rb')
describe MigrateStoreSecurityReportsSidekiqQueue, :redis do
include Gitlab::Database::MigrationHelpers
include StubWorker
context 'when there are jobs in the queue' do
it 'migrates queue when migrating up' do
Sidekiq::Testing.disable! do
stub_worker(queue: 'pipeline_default:store_security_reports').perform_async(1, 5)
described_class.new.up
expect(sidekiq_queue_length('pipeline_default:store_security_reports')).to eq 0
expect(sidekiq_queue_length('security_scans:store_security_reports')).to eq 1
end
end
it 'migrates queue when migrating down' do
Sidekiq::Testing.disable! do
stub_worker(queue: 'security_scans:store_security_reports').perform_async(1, 5)
described_class.new.down
expect(sidekiq_queue_length('pipeline_default:store_security_reports')).to eq 1
expect(sidekiq_queue_length('security_scans:store_security_reports')).to eq 0
end
end
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200213220211_migrate_sync_security_reports_to_report_approval_rules_sidekiq_queue.rb')
describe MigrateSyncSecurityReportsToReportApprovalRulesSidekiqQueue, :redis do
include Gitlab::Database::MigrationHelpers
include StubWorker
context 'when there are jobs in the queue' do
it 'migrates queue when migrating up' do
Sidekiq::Testing.disable! do
stub_worker(queue: 'pipeline_default:sync_security_reports_to_report_approval_rules').perform_async(1, 5)
described_class.new.up
expect(sidekiq_queue_length('pipeline_default:sync_security_reports_to_report_approval_rules')).to eq 0
expect(sidekiq_queue_length('security_scans:sync_security_reports_to_report_approval_rules')).to eq 1
end
end
it 'migrates queue when migrating down' do
Sidekiq::Testing.disable! do
stub_worker(queue: 'security_scans:sync_security_reports_to_report_approval_rules').perform_async(1, 5)
described_class.new.down
expect(sidekiq_queue_length('pipeline_default:sync_security_reports_to_report_approval_rules')).to eq 1
expect(sidekiq_queue_length('security_scans:sync_security_reports_to_report_approval_rules')).to eq 0
end
end
end
end

View File

@ -303,6 +303,20 @@ describe User, :do_not_mock_admin_mode do
end
end
context 'bad regex' do
before do
allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['([a-zA-Z0-9]+)+\.com'])
end
it 'does not hang on evil input' do
user = build(:user, email: 'user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!.com')
expect do
Timeout.timeout(2.seconds) { user.valid? }
end.not_to raise_error
end
end
context 'when a signup domain is whitelisted and subdomains are allowed' do
before do
allow_any_instance_of(ApplicationSetting).to receive(:domain_whitelist).and_return(['example.com', '*.example.com'])
@ -356,6 +370,20 @@ describe User, :do_not_mock_admin_mode do
allow_any_instance_of(ApplicationSetting).to receive(:domain_blacklist).and_return(['example.com'])
end
context 'bad regex' do
before do
allow_any_instance_of(ApplicationSetting).to receive(:domain_blacklist).and_return(['([a-zA-Z0-9]+)+\.com'])
end
it 'does not hang on evil input' do
user = build(:user, email: 'user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!.com')
expect do
Timeout.timeout(2.seconds) { user.valid? }
end.not_to raise_error
end
end
context 'when a signup domain is blacklisted' do
it 'accepts info@test.com' do
user = build(:user, email: 'info@test.com')

View File

@ -3,12 +3,12 @@
require 'spec_helper'
describe API::AccessRequests do
set(:maintainer) { create(:user) }
set(:developer) { create(:user) }
set(:access_requester) { create(:user) }
set(:stranger) { create(:user) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:access_requester) { create(:user) }
let_it_be(:stranger) { create(:user) }
set(:project) do
let_it_be(:project) do
create(:project, :public, creator_id: maintainer.id, namespace: maintainer.namespace) do |project|
project.add_developer(developer)
project.add_maintainer(maintainer)
@ -16,7 +16,7 @@ describe API::AccessRequests do
end
end
set(:group) do
let_it_be(:group) do
create(:group, :public) do |group|
group.add_developer(developer)
group.add_owner(maintainer)

View File

@ -3,14 +3,13 @@
require 'spec_helper'
describe API::AwardEmoji do
set(:user) { create(:user) }
set(:project) { create(:project) }
set(:issue) { create(:issue, project: project) }
set(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
set(:note) { create(:note, project: project, noteable: issue) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:award_emoji) { create(:award_emoji, awardable: issue, user: user) }
let_it_be(:note) { create(:note, project: project, noteable: issue) }
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
let!(:downvote) { create(:award_emoji, :downvote, awardable: merge_request, user: user) }
before do
project.add_maintainer(user)

View File

@ -3,35 +3,35 @@
require 'spec_helper'
describe API::Boards do
set(:user) { create(:user) }
set(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:admin) { create(:user, :admin) }
set(:board_parent) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) }
let_it_be(:user) { create(:user) }
let_it_be(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:board_parent, reload: true) { create(:project, :public, creator_id: user.id, namespace: user.namespace ) }
set(:dev_label) do
let_it_be(:dev_label) do
create(:label, title: 'Development', color: '#FFAABB', project: board_parent)
end
set(:test_label) do
let_it_be(:test_label) do
create(:label, title: 'Testing', color: '#FFAACC', project: board_parent)
end
set(:ux_label) do
let_it_be(:ux_label) do
create(:label, title: 'UX', color: '#FF0000', project: board_parent)
end
set(:dev_list) do
let_it_be(:dev_list) do
create(:list, label: dev_label, position: 1)
end
set(:test_list) do
let_it_be(:test_list) do
create(:list, label: test_label, position: 2)
end
set(:milestone) { create(:milestone, project: board_parent) }
set(:board_label) { create(:label, project: board_parent) }
set(:board) { create(:board, project: board_parent, lists: [dev_list, test_list]) }
let_it_be(:milestone) { create(:milestone, project: board_parent) }
let_it_be(:board_label) { create(:label, project: board_parent) }
let_it_be(:board) { create(:board, project: board_parent, lists: [dev_list, test_list]) }
it_behaves_like 'group and project boards', "/projects/:id/boards"
@ -66,11 +66,11 @@ describe API::Boards do
end
describe "POST /groups/:id/boards/lists" do
set(:group) { create(:group) }
set(:board_parent) { create(:group, parent: group ) }
let_it_be(:group) { create(:group) }
let_it_be(:board_parent) { create(:group, parent: group ) }
let(:url) { "/groups/#{board_parent.id}/boards/#{board.id}/lists" }
set(:board) { create(:board, group: board_parent) }
let_it_be(:board) { create(:board, group: board_parent) }
it 'creates a new board list for ancestor group labels' do
group.add_developer(user)

View File

@ -3,7 +3,7 @@
require 'spec_helper'
describe API::Branches do
set(:user) { create(:user) }
let_it_be(:user) { create(:user) }
let(:project) { create(:project, :repository, creator: user, path: 'my.project') }
let(:guest) { create(:user).tap { |u| project.add_guest(u) } }
let(:branch_name) { 'feature' }

View File

@ -3,9 +3,9 @@
require 'spec_helper'
describe API::BroadcastMessages do
set(:user) { create(:user) }
set(:admin) { create(:admin) }
set(:message) { create(:broadcast_message) }
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
let_it_be(:message) { create(:broadcast_message) }
describe 'GET /broadcast_messages' do
it 'returns an Array of BroadcastMessages' do

View File

@ -3,8 +3,8 @@
require 'spec_helper'
describe API::Features do
set(:user) { create(:user) }
set(:admin) { create(:admin) }
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
before do
Flipper.unregister_groups

View File

@ -16,7 +16,7 @@ describe 'getting project information' do
end
context 'when there is a current_user' do
set(:current_user) { create(:user) }
let_it_be(:current_user) { create(:user) }
it_behaves_like 'a working graphql query'

View File

@ -5,7 +5,7 @@ require 'spec_helper'
describe 'GitlabSchema configurations' do
include GraphqlHelpers
set(:project) { create(:project) }
let_it_be(:project) { create(:project) }
shared_examples 'imposing query limits' do
describe 'timeouts' do

View File

@ -5,9 +5,9 @@ require 'spec_helper'
describe 'Adding an AwardEmoji' do
include GraphqlHelpers
set(:current_user) { create(:user) }
set(:project) { create(:project) }
set(:awardable) { create(:note, project: project) }
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:awardable) { create(:note, project: project) }
let(:emoji_name) { 'thumbsup' }
let(:mutation) do
variables = {

View File

@ -5,9 +5,9 @@ require 'spec_helper'
describe 'Toggling an AwardEmoji' do
include GraphqlHelpers
set(:current_user) { create(:user) }
set(:project) { create(:project) }
set(:awardable) { create(:note, project: project) }
let_it_be(:current_user) { create(:user) }
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:awardable) { create(:note, project: project) }
let(:emoji_name) { 'thumbsup' }
let(:mutation) do
variables = {

View File

@ -5,7 +5,7 @@ require 'spec_helper'
describe 'Adding a DiffNote' do
include GraphqlHelpers
set(:current_user) { create(:user) }
let_it_be(:current_user) { create(:user) }
let(:noteable) { create(:merge_request, source_project: project, target_project: project) }
let(:project) { create(:project, :repository) }
let(:diff_refs) { noteable.diff_refs }

View File

@ -5,7 +5,7 @@ require 'spec_helper'
describe 'Adding an image DiffNote' do
include GraphqlHelpers
set(:current_user) { create(:user) }
let_it_be(:current_user) { create(:user) }
let(:noteable) { create(:merge_request, source_project: project, target_project: project) }
let(:project) { create(:project, :repository) }
let(:diff_refs) { noteable.diff_refs }

View File

@ -5,7 +5,7 @@ require 'spec_helper'
describe 'Adding a Note' do
include GraphqlHelpers
set(:current_user) { create(:user) }
let_it_be(:current_user) { create(:user) }
let(:noteable) { create(:merge_request, source_project: project, target_project: project) }
let(:project) { create(:project) }
let(:discussion) { nil }

View File

@ -9,8 +9,8 @@ describe 'getting task completion status information' do
DESCRIPTION_1_DONE = '- [x] task 1\n- [ ] task 2'
DESCRIPTION_2_DONE = '- [x] task 1\n- [x] task 2'
set(:user1) { create(:user) }
set(:project) { create(:project, :repository, :public) }
let_it_be(:user1) { create(:user) }
let_it_be(:project) { create(:project, :repository, :public) }
let(:fields) do
<<~QUERY

View File

@ -3,42 +3,42 @@
require 'spec_helper'
describe API::GroupBoards do
set(:user) { create(:user) }
set(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:admin) { create(:user, :admin) }
set(:board_parent) { create(:group, :public) }
let_it_be(:user) { create(:user) }
let_it_be(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:board_parent) { create(:group, :public) }
before do
board_parent.add_owner(user)
end
set(:project) { create(:project, :public, namespace: board_parent ) }
let_it_be(:project) { create(:project, :public, namespace: board_parent ) }
set(:dev_label) do
let_it_be(:dev_label) do
create(:group_label, title: 'Development', color: '#FFAABB', group: board_parent)
end
set(:test_label) do
let_it_be(:test_label) do
create(:group_label, title: 'Testing', color: '#FFAACC', group: board_parent)
end
set(:ux_label) do
let_it_be(:ux_label) do
create(:group_label, title: 'UX', color: '#FF0000', group: board_parent)
end
set(:dev_list) do
let_it_be(:dev_list) do
create(:list, label: dev_label, position: 1)
end
set(:test_list) do
let_it_be(:test_list) do
create(:list, label: test_label, position: 2)
end
set(:milestone) { create(:milestone, group: board_parent) }
set(:board_label) { create(:group_label, group: board_parent) }
let_it_be(:milestone) { create(:milestone, group: board_parent) }
let_it_be(:board_label) { create(:group_label, group: board_parent) }
set(:board) { create(:board, group: board_parent, lists: [dev_list, test_list]) }
let_it_be(:board) { create(:board, group: board_parent, lists: [dev_list, test_list]) }
it_behaves_like 'group and project boards', "/groups/:id/boards", false

View File

@ -3,18 +3,16 @@
require 'spec_helper'
describe API::Issues do
set(:user) { create(:user) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:author) { create(:author) }
set(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:issue_title) { 'foo' }
let(:issue_description) { 'closed' }
let(:no_milestone_title) { 'None' }
let_it_be(:user) { create(:user) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:author) { create(:author) }
let_it_be(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:issue_title) { 'foo' }
let(:issue_description) { 'closed' }
let(:no_milestone_title) { 'None' }
let(:any_milestone_title) { 'Any' }
before do

View File

@ -3,18 +3,18 @@
require 'spec_helper'
describe API::Issues do
set(:user) { create(:user) }
set(:project) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace) }
set(:private_mrs_project) do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace) }
let_it_be(:private_mrs_project) do
create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, merge_requests_access_level: ProjectFeature::PRIVATE)
end
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:author) { create(:author) }
set(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:author) { create(:author) }
let_it_be(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:issue_title) { 'foo' }
let(:issue_description) { 'closed' }
let!(:closed_issue) do
@ -48,12 +48,12 @@ describe API::Issues do
title: issue_title,
description: issue_description
end
set(:label) do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
set(:empty_milestone) do
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }

View File

@ -3,18 +3,18 @@
require 'spec_helper'
describe API::Issues do
set(:user) { create(:user) }
set(:project) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace) }
set(:private_mrs_project) do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace) }
let_it_be(:private_mrs_project) do
create(:project, :public, :repository, creator_id: user.id, namespace: user.namespace, merge_requests_access_level: ProjectFeature::PRIVATE)
end
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:author) { create(:author) }
set(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:author) { create(:author) }
let_it_be(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:issue_title) { 'foo' }
let(:issue_description) { 'closed' }
let!(:closed_issue) do
@ -48,12 +48,12 @@ describe API::Issues do
title: issue_title,
description: issue_description
end
set(:label) do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
set(:empty_milestone) do
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }

View File

@ -3,17 +3,17 @@
require 'spec_helper'
describe API::Issues do
set(:user) { create(:user) }
set(:project) do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) do
create(:project, :public, creator_id: user.id, namespace: user.namespace)
end
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:author) { create(:author) }
set(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:author) { create(:author) }
let_it_be(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:issue_title) { 'foo' }
let(:issue_description) { 'closed' }
let!(:closed_issue) do
@ -47,12 +47,12 @@ describe API::Issues do
title: issue_title,
description: issue_description
end
set(:label) do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
set(:empty_milestone) do
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }

View File

@ -3,17 +3,17 @@
require 'spec_helper'
describe API::Issues do
set(:user) { create(:user) }
set(:project) do
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) do
create(:project, :public, creator_id: user.id, namespace: user.namespace)
end
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
set(:guest) { create(:user) }
set(:author) { create(:author) }
set(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:user2) { create(:user) }
let(:non_member) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:author) { create(:author) }
let_it_be(:assignee) { create(:assignee) }
let(:admin) { create(:user, :admin) }
let(:issue_title) { 'foo' }
let(:issue_description) { 'closed' }
let!(:closed_issue) do
@ -47,12 +47,12 @@ describe API::Issues do
title: issue_title,
description: issue_description
end
set(:label) do
let_it_be(:label) do
create(:label, title: 'label', color: '#FFAABB', project: project)
end
let!(:label_link) { create(:label_link, label: label, target: issue) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
set(:empty_milestone) do
let_it_be(:empty_milestone) do
create(:milestone, title: '2.0.0', project: project)
end
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }

View File

@ -31,11 +31,11 @@ describe API::Jobs do
end
end
set(:project) do
let_it_be(:project, reload: true) do
create(:project, :repository, public_builds: false)
end
set(:pipeline) do
let_it_be(:pipeline, reload: true) do
create(:ci_empty_pipeline, project: project,
sha: project.commit.id,
ref: project.default_branch)

View File

@ -52,8 +52,8 @@ describe API::Markdown do
end
context "when arguments are valid" do
set(:project) { create(:project) }
set(:issue) { create(:issue, project: project) }
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let(:text) { ":tada: Hello world! :100: #{issue.to_reference}" }
context "when not using gfm" do

View File

@ -6,9 +6,9 @@ describe API::MergeRequests do
include ProjectForksHelper
let(:base_time) { Time.now }
set(:user) { create(:user) }
set(:user2) { create(:user) }
set(:admin) { create(:user, :admin) }
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
let(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let(:milestone1) { create(:milestone, title: '0.9', project: project) }

View File

@ -6,16 +6,15 @@ describe "Internal Project Pages Access" do
using RSpec::Parameterized::TableSyntax
include AccessMatchers
set(:group) { create(:group) }
set(:project) { create(:project, :internal, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
set(:admin) { create(:admin) }
set(:owner) { create(:user) }
set(:master) { create(:user) }
set(:developer) { create(:user) }
set(:reporter) { create(:user) }
set(:guest) { create(:user) }
set(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :internal, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
let_it_be(:admin) { create(:admin) }
let_it_be(:owner) { create(:user) }
let_it_be(:master) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:user) { create(:user) }
before do
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)

View File

@ -6,16 +6,15 @@ describe "Private Project Pages Access" do
using RSpec::Parameterized::TableSyntax
include AccessMatchers
set(:group) { create(:group) }
set(:project) { create(:project, :private, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
set(:admin) { create(:admin) }
set(:owner) { create(:user) }
set(:master) { create(:user) }
set(:developer) { create(:user) }
set(:reporter) { create(:user) }
set(:guest) { create(:user) }
set(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :private, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
let_it_be(:admin) { create(:admin) }
let_it_be(:owner) { create(:user) }
let_it_be(:master) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:user) { create(:user) }
before do
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)

View File

@ -6,16 +6,15 @@ describe "Public Project Pages Access" do
using RSpec::Parameterized::TableSyntax
include AccessMatchers
set(:group) { create(:group) }
set(:project) { create(:project, :public, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
set(:admin) { create(:admin) }
set(:owner) { create(:user) }
set(:master) { create(:user) }
set(:developer) { create(:user) }
set(:reporter) { create(:user) }
set(:guest) { create(:user) }
set(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :public, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
let_it_be(:admin) { create(:admin) }
let_it_be(:owner) { create(:user) }
let_it_be(:master) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:user) { create(:user) }
before do
allow(Gitlab.config.pages).to receive(:access_control).and_return(true)

View File

@ -3,9 +3,9 @@
require 'spec_helper'
describe API::PipelineSchedules do
set(:developer) { create(:user) }
set(:user) { create(:user) }
set(:project) { create(:project, :repository, public_builds: false) }
let_it_be(:developer) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, public_builds: false) }
before do
project.add_developer(developer)
@ -375,7 +375,7 @@ describe API::PipelineSchedules do
describe 'POST /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables' do
let(:params) { attributes_for(:ci_pipeline_schedule_variable) }
set(:pipeline_schedule) do
let_it_be(:pipeline_schedule) do
create(:ci_pipeline_schedule, project: project, owner: developer)
end
@ -432,7 +432,7 @@ describe API::PipelineSchedules do
end
describe 'PUT /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key' do
set(:pipeline_schedule) do
let_it_be(:pipeline_schedule) do
create(:ci_pipeline_schedule, project: project, owner: developer)
end
@ -472,7 +472,7 @@ describe API::PipelineSchedules do
describe 'DELETE /projects/:id/pipeline_schedules/:pipeline_schedule_id/variables/:key' do
let(:maintainer) { create(:user) }
set(:pipeline_schedule) do
let_it_be(:pipeline_schedule) do
create(:ci_pipeline_schedule, project: project, owner: developer)
end

View File

@ -5,12 +5,11 @@ require 'spec_helper'
describe API::ProjectContainerRepositories do
include ExclusiveLeaseHelpers
set(:project) { create(:project, :private) }
set(:maintainer) { create(:user) }
set(:developer) { create(:user) }
set(:reporter) { create(:user) }
set(:guest) { create(:user) }
let_it_be(:project) { create(:project, :private) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:guest) { create(:user) }
let(:root_repository) { create(:container_repository, :root, project: project) }
let(:test_repository) { create(:container_repository, project: project) }

View File

@ -3,13 +3,13 @@
require 'spec_helper'
describe API::ProjectExport, :clean_gitlab_redis_cache do
set(:project) { create(:project) }
set(:project_none) { create(:project) }
set(:project_started) { create(:project) }
let_it_be(:project) { create(:project) }
let_it_be(:project_none) { create(:project) }
let_it_be(:project_started) { create(:project) }
let(:project_finished) { create(:project, :with_export) }
let(:project_after_export) { create(:project, :with_export) }
set(:user) { create(:user) }
set(:admin) { create(:admin) }
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
let(:path) { "/projects/#{project.id}/export" }
let(:path_none) { "/projects/#{project_none.id}/export" }

View File

@ -3,9 +3,9 @@
require 'spec_helper'
describe API::ProjectSnippets do
set(:project) { create(:project, :public) }
set(:user) { create(:user) }
set(:admin) { create(:admin) }
let_it_be(:project) { create(:project, :public) }
let_it_be(:user) { create(:user) }
let_it_be(:admin) { create(:admin) }
describe "GET /projects/:project_id/snippets/:id/user_agent_detail" do
let(:snippet) { create(:project_snippet, :public, project: project) }

View File

@ -3,9 +3,9 @@
require 'spec_helper'
describe API::ResourceLabelEvents do
set(:user) { create(:user) }
set(:project) { create(:project, :public, namespace: user.namespace) }
set(:label) { create(:label, project: project) }
let_it_be(:user) { create(:user) }
let_it_be(:project, reload: true) { create(:project, :public, namespace: user.namespace) }
let_it_be(:label) { create(:label, project: project) }
before do
project.add_developer(user)

View File

@ -557,7 +557,7 @@ describe API::Runners do
end
describe 'GET /runners/:id/jobs' do
set(:job_1) { create(:ci_build) }
let_it_be(:job_1) { create(:ci_build) }
let!(:job_2) { create(:ci_build, :running, runner: shared_runner, project: project) }
let!(:job_3) { create(:ci_build, :failed, runner: shared_runner, project: project) }
let!(:job_4) { create(:ci_build, :running, runner: project_runner, project: project) }

View File

@ -3,10 +3,10 @@
require 'spec_helper'
describe API::Search do
set(:user) { create(:user) }
set(:group) { create(:group) }
set(:project) { create(:project, :wiki_repo, :public, name: 'awesome project', group: group) }
set(:repo_project) { create(:project, :public, :repository, group: group) }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project, reload: true) { create(:project, :wiki_repo, :public, name: 'awesome project', group: group) }
let_it_be(:repo_project) { create(:project, :public, :repository, group: group) }
shared_examples 'response is correct' do |schema:, size: 1|
it { expect(response).to have_gitlab_http_status(200) }

View File

@ -3,10 +3,10 @@
require "spec_helper"
describe API::Services do
set(:user) { create(:user) }
set(:user2) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
set(:project) do
let_it_be(:project, reload: true) do
create(:project, creator_id: user.id, namespace: user.namespace)
end

View File

@ -5,7 +5,7 @@ require 'spec_helper'
describe API::Settings, 'Settings' do
let(:user) { create(:user) }
set(:admin) { create(:admin) }
let_it_be(:admin) { create(:admin) }
describe "GET /application/settings" do
it "returns application settings" do

View File

@ -89,8 +89,8 @@ describe API::Snippets do
end
describe 'GET /snippets/:id/raw' do
set(:author) { create(:user) }
set(:snippet) { create(:personal_snippet, :private, author: author) }
let_it_be(:author) { create(:user) }
let_it_be(:snippet) { create(:personal_snippet, :private, author: author) }
it 'requires authentication' do
get api("/snippets/#{snippet.id}", nil)
@ -137,10 +137,10 @@ describe API::Snippets do
end
describe 'GET /snippets/:id' do
set(:admin) { create(:user, :admin) }
set(:author) { create(:user) }
set(:private_snippet) { create(:personal_snippet, :private, author: author) }
set(:internal_snippet) { create(:personal_snippet, :internal, author: author) }
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:author) { create(:user) }
let_it_be(:private_snippet) { create(:personal_snippet, :private, author: author) }
let_it_be(:internal_snippet) { create(:personal_snippet, :internal, author: author) }
it 'requires authentication' do
get api("/snippets/#{private_snippet.id}", nil)

View File

@ -3,8 +3,8 @@
require 'spec_helper'
describe 'task completion status response' do
set(:user) { create(:user) }
set(:project) do
let_it_be(:user) { create(:user) }
let_it_be(:project) do
create(:project, :public, creator_id: user.id, namespace: user.namespace)
end

View File

@ -3,8 +3,8 @@
require 'spec_helper'
describe API::Triggers do
set(:user) { create(:user) }
set(:user2) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let!(:trigger_token) { 'secure_token' }
let!(:trigger_token_2) { 'secure_token_2' }