Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8c2d06cba7
commit
a16398e10f
|
@ -1 +1 @@
|
|||
0fa08d953e0d5497fe5366836d0ed54b9ff557d8
|
||||
31ea786fbf0a7874b44efcb1f8b43bc4536d9b7e
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
import { Mark } from 'prosemirror-model';
|
||||
import { visitParents, SKIP } from 'unist-util-visit-parents';
|
||||
import { isFunction, isString, noop } from 'lodash';
|
||||
import { isFunction, isString, noop, mapValues } from 'lodash';
|
||||
|
||||
const NO_ATTRIBUTES = {};
|
||||
|
||||
|
@ -73,28 +73,47 @@ function createSourceMapAttributes(hastNode, markdown) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Compute ProseMirror node’s attributes from a Hast node.
|
||||
* By default, this function includes sourcemap position
|
||||
* information in the object returned.
|
||||
* Creates a function that resolves the attributes
|
||||
* of a ProseMirror node based on a hast node.
|
||||
*
|
||||
* Other attributes are retrieved by invoking a getAttrs
|
||||
* function provided by the ProseMirror node factory spec.
|
||||
*
|
||||
* @param {*} proseMirrorNodeSpec ProseMirror node spec object
|
||||
* @param {HastNode} hastNode A hast node
|
||||
* @param {Array<HastNode>} hastParents All the ancestors of the hastNode
|
||||
* @param {String} markdown Markdown source file’s content
|
||||
*
|
||||
* @returns An object that contains a ProseMirror node’s attributes
|
||||
* @param {Object} params Parameters
|
||||
* @param {String} params.markdown Markdown source from which the AST was generated
|
||||
* @param {Object} params.attributeTransformer An object that allows applying a transformation
|
||||
* function to all the attributes listed in the attributes property.
|
||||
* @param {Array} params.attributeTransformer.attributes A list of attributes names
|
||||
* that the getAttrs function should apply the transformation
|
||||
* @param {Function} params.attributeTransformer.transform A function that applies
|
||||
* a transform operation on an attribute value.
|
||||
* @returns A `getAttrs` function
|
||||
*/
|
||||
function getAttrs(proseMirrorNodeSpec, hastNode, hastParents, markdown) {
|
||||
const { getAttrs: specGetAttrs } = proseMirrorNodeSpec;
|
||||
const getAttrsFactory = ({ attributeTransformer, markdown }) =>
|
||||
/**
|
||||
* Compute ProseMirror node’s attributes from a Hast node.
|
||||
* By default, this function includes sourcemap position
|
||||
* information in the object returned.
|
||||
*
|
||||
* Other attributes are retrieved by invoking a getAttrs
|
||||
* function provided by the ProseMirror node factory spec.
|
||||
*
|
||||
* @param {Object} proseMirrorNodeSpec ProseMirror node spec object
|
||||
* @param {Object} hastNode A hast node
|
||||
* @param {Array} hastParents All the ancestors of the hastNode
|
||||
* @param {String} markdown Markdown source file’s content
|
||||
* @returns An object that contains a ProseMirror node’s attributes
|
||||
*/
|
||||
function getAttrs(proseMirrorNodeSpec, hastNode, hastParents) {
|
||||
const { getAttrs: specGetAttrs } = proseMirrorNodeSpec;
|
||||
const attributes = {
|
||||
...createSourceMapAttributes(hastNode, markdown),
|
||||
...(isFunction(specGetAttrs) ? specGetAttrs(hastNode, hastParents, markdown) : {}),
|
||||
};
|
||||
|
||||
return {
|
||||
...createSourceMapAttributes(hastNode, markdown),
|
||||
...(isFunction(specGetAttrs) ? specGetAttrs(hastNode, hastParents, markdown) : {}),
|
||||
return mapValues(attributes, (value, key) =>
|
||||
attributeTransformer.attributes.includes(key)
|
||||
? attributeTransformer.transform(value, key)
|
||||
: value,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track of the Hast -> ProseMirror conversion process.
|
||||
|
@ -322,7 +341,13 @@ class HastToProseMirrorConverterState {
|
|||
*
|
||||
* @returns An object that contains ProseMirror node factories
|
||||
*/
|
||||
const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, markdown) => {
|
||||
const createProseMirrorNodeFactories = (
|
||||
schema,
|
||||
proseMirrorFactorySpecs,
|
||||
attributeTransformer,
|
||||
markdown,
|
||||
) => {
|
||||
const getAttrs = getAttrsFactory({ attributeTransformer, markdown });
|
||||
const factories = {
|
||||
root: {
|
||||
selector: 'root',
|
||||
|
@ -355,20 +380,20 @@ const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, markdow
|
|||
const nodeType = schema.nodeType(proseMirrorName);
|
||||
|
||||
state.closeUntil(parent);
|
||||
state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
|
||||
state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent), factory);
|
||||
};
|
||||
} else if (factory.type === 'inline') {
|
||||
const nodeType = schema.nodeType(proseMirrorName);
|
||||
factory.handle = (state, hastNode, parent) => {
|
||||
state.closeUntil(parent);
|
||||
state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
|
||||
state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent), factory);
|
||||
// Inline nodes do not have children therefore they are immediately closed
|
||||
state.closeNode();
|
||||
};
|
||||
} else if (factory.type === 'mark') {
|
||||
const markType = schema.marks[proseMirrorName];
|
||||
factory.handle = (state, hastNode, parent) => {
|
||||
state.openMark(markType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
|
||||
state.openMark(markType, hastNode, getAttrs(factory, hastNode, parent), factory);
|
||||
};
|
||||
} else if (factory.type === 'ignore') {
|
||||
factory.handle = noop;
|
||||
|
@ -581,9 +606,15 @@ export const createProseMirrorDocFromMdastTree = ({
|
|||
factorySpecs,
|
||||
wrappableTags,
|
||||
tree,
|
||||
attributeTransformer,
|
||||
markdown,
|
||||
}) => {
|
||||
const proseMirrorNodeFactories = createProseMirrorNodeFactories(schema, factorySpecs, markdown);
|
||||
const proseMirrorNodeFactories = createProseMirrorNodeFactories(
|
||||
schema,
|
||||
factorySpecs,
|
||||
attributeTransformer,
|
||||
markdown,
|
||||
);
|
||||
const state = new HastToProseMirrorConverterState();
|
||||
|
||||
visitParents(tree, (hastNode, ancestors) => {
|
||||
|
|
|
@ -125,6 +125,7 @@ const factorySpecs = {
|
|||
selector: 'img',
|
||||
getAttrs: (hastNode) => ({
|
||||
src: hastNode.properties.src,
|
||||
canonicalSrc: hastNode.properties.src,
|
||||
title: hastNode.properties.title,
|
||||
alt: hastNode.properties.alt,
|
||||
}),
|
||||
|
@ -154,6 +155,7 @@ const factorySpecs = {
|
|||
type: 'mark',
|
||||
selector: 'a',
|
||||
getAttrs: (hastNode) => ({
|
||||
canonicalSrc: hastNode.properties.href,
|
||||
href: hastNode.properties.href,
|
||||
title: hastNode.properties.title,
|
||||
}),
|
||||
|
@ -182,6 +184,31 @@ const factorySpecs = {
|
|||
},
|
||||
};
|
||||
|
||||
const resolveUrl = (url) => {
|
||||
try {
|
||||
return new URL(url, window.location.origin).toString();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const attributeTransformer = {
|
||||
attributes: ['href', 'src'],
|
||||
transform: (url) => {
|
||||
if (!url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a URL if provided. The URL is not resolved against
|
||||
* the client origin initially to protect the URL protocol
|
||||
* when it is available, for example, we want to preserve
|
||||
* mailto and application-specific protocols
|
||||
*/
|
||||
return resolveUrl(url);
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return {
|
||||
deserialize: async ({ schema, markdown }) => {
|
||||
|
@ -193,6 +220,7 @@ export default () => {
|
|||
factorySpecs,
|
||||
tree,
|
||||
wrappableTags,
|
||||
attributeTransformer,
|
||||
markdown,
|
||||
}),
|
||||
skipRendering: ['footnoteReference', 'footnoteDefinition', 'code', 'definition'],
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { uniq, isString, omit, isFunction } from 'lodash';
|
||||
import { removeLastSlashInUrlPath, removeUrlProtocol } from '../../lib/utils/url_utility';
|
||||
|
||||
const defaultAttrs = {
|
||||
td: { colspan: 1, rowspan: 1, colwidth: null },
|
||||
|
@ -497,9 +498,7 @@ const linkType = (sourceMarkdown) => {
|
|||
return LINK_HTML;
|
||||
};
|
||||
|
||||
const removeUrlProtocol = (url) => url.replace(/^\w+:\/?\/?/, '');
|
||||
|
||||
const normalizeUrl = (url) => decodeURIComponent(removeUrlProtocol(url));
|
||||
const normalizeUrl = (url) => decodeURIComponent(removeLastSlashInUrlPath(removeUrlProtocol(url)));
|
||||
|
||||
/**
|
||||
* Validates that the provided URL is well-formed
|
||||
|
|
|
@ -669,3 +669,27 @@ export function constructWebIDEPath({
|
|||
webIDEUrl(`/${sourceProjectFullPath}/merge_requests/${iid}`),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Examples
|
||||
*
|
||||
* http://gitlab.com => gitlab.com
|
||||
* https://gitlab.com => gitlab.com
|
||||
*
|
||||
* @param {String} url
|
||||
* @returns A url without a protocol / scheme
|
||||
*/
|
||||
export const removeUrlProtocol = (url) => url.replace(/^\w+:\/?\/?/, '');
|
||||
|
||||
/**
|
||||
* Examples
|
||||
*
|
||||
* https://www.gitlab.com/path/ => https://www.gitlab.com/path
|
||||
* https://www.gitlab.com/?query=search => https://www.gitlab.com?query=search
|
||||
* https://www.gitlab.com/#fragment => https://www.gitlab.com#fragment
|
||||
*
|
||||
* @param {String} url
|
||||
* @returns A URL that does not have a path that ends with slash
|
||||
*/
|
||||
export const removeLastSlashInUrlPath = (url) =>
|
||||
url.replace(/\/$/, '').replace(/\/(\?|#){1}([^/]*)$/, '$1$2');
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/**
|
||||
* Overrides styles from ToastUI editor
|
||||
*/
|
||||
|
||||
.tui-editor-defaultUI {
|
||||
|
||||
// Toolbar buttons
|
||||
.tui-editor-defaultUI-toolbar .toolbar-button {
|
||||
color: $gray-500;
|
||||
border: 0;
|
||||
|
||||
&:hover,
|
||||
&:active {
|
||||
color: $blue-500;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Contextual menu's & popups
|
||||
.tui-popup-wrapper {
|
||||
@include gl-overflow-hidden;
|
||||
@include gl-rounded-base;
|
||||
@include gl-border-gray-200;
|
||||
|
||||
hr {
|
||||
@include gl-m-0;
|
||||
@include gl-bg-gray-200;
|
||||
}
|
||||
|
||||
button {
|
||||
@include gl-text-gray-700;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides styles from ToastUI's Code Mirror (markdown mode) editor.
|
||||
* Toast UI internally overrides some of these using the `.tui-md-` prefix.
|
||||
* https://codemirror.net/doc/manual.html#styling
|
||||
*/
|
||||
|
||||
.te-md-container .CodeMirror * {
|
||||
@include gl-font-monospace;
|
||||
@include gl-font-size-monospace;
|
||||
@include gl-line-height-20;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Styling below ensures that YouTube videos are displayed in the editor the same as they would in about.gitlab.com
|
||||
* https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/main/source/stylesheets/_base.scss#L977
|
||||
*/
|
||||
.video_container {
|
||||
padding-bottom: 56.25%;
|
||||
}
|
|
@ -66,4 +66,9 @@ class DeployKey < Key
|
|||
|
||||
query
|
||||
end
|
||||
|
||||
# This is used for the internal logic of AuditEvents::BuildService.
|
||||
def impersonated?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,6 +40,7 @@ class Key < ApplicationRecord
|
|||
after_destroy :refresh_user_cache
|
||||
|
||||
alias_attribute :fingerprint_md5, :fingerprint
|
||||
alias_attribute :name, :title
|
||||
|
||||
scope :preload_users, -> { preload(:user) }
|
||||
scope :for_user, -> (user) { where(user: user) }
|
||||
|
|
|
@ -1809,12 +1809,8 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
def attention_requested_open_merge_requests_count(force: false)
|
||||
if Feature.enabled?(:uncached_mr_attention_requests_count, self)
|
||||
Rails.cache.fetch(attention_request_cache_key, force: force, expires_in: COUNT_CACHE_VALIDITY_PERIOD) do
|
||||
MergeRequestsFinder.new(self, attention: self.username, state: 'opened', non_archived: true).execute.count
|
||||
else
|
||||
Rails.cache.fetch(attention_request_cache_key, force: force, expires_in: COUNT_CACHE_VALIDITY_PERIOD) do
|
||||
MergeRequestsFinder.new(self, attention: self.username, state: 'opened', non_archived: true).execute.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
name: uncached_mr_attention_requests_count
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84145
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357480
|
||||
milestone: '14.10'
|
||||
name: audit_event_streaming_git_operations_deploy_key_event
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93160
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/368765
|
||||
milestone: '15.3'
|
||||
type: development
|
||||
group: group::code review
|
||||
group: group::release
|
||||
default_enabled: false
|
|
@ -336,6 +336,7 @@ Users with at least the Owner role for a group can list event streaming destinat
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.9 [with a flag](../administration/feature_flags.md) named `audit_event_streaming_git_operations`. Disabled by default.
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/357211) in GitLab 15.0.
|
||||
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/357211) in GitLab 15.1 by default.
|
||||
> - [Added `details.author_class` field](https://gitlab.com/gitlab-org/gitlab/-/issues/363876) in GitLab 15.3.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is available. To hide the
|
||||
|
@ -377,6 +378,7 @@ Fetch:
|
|||
"entity_type": "Project",
|
||||
"details": {
|
||||
"author_name": "Administrator",
|
||||
"author_class": "User",
|
||||
"target_id": 29,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-project",
|
||||
|
@ -408,6 +410,7 @@ Push:
|
|||
"entity_type": "Project",
|
||||
"details": {
|
||||
"author_name": "Administrator",
|
||||
"author_class": "User",
|
||||
"target_id": 29,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-project",
|
||||
|
@ -429,6 +432,42 @@ Push:
|
|||
}
|
||||
```
|
||||
|
||||
#### Example payloads for SSH events with Deploy Key
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/363876) in GitLab 15.3 [with a flag](../administration/feature_flags.md) named `audit_event_streaming_git_operations_deploy_key_event`. Disabled by default.
|
||||
|
||||
Fetch:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"author_id": -3,
|
||||
"entity_id": 29,
|
||||
"entity_type": "Project",
|
||||
"details": {
|
||||
"author_name": "deploy-key-name",
|
||||
"author_class": "DeployKey",
|
||||
"target_id": 29,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-project",
|
||||
"custom_message": {
|
||||
"protocol": "ssh",
|
||||
"action": "git-upload-pack"
|
||||
},
|
||||
"ip_address": "127.0.0.1",
|
||||
"entity_path": "example-group/example-project"
|
||||
},
|
||||
"ip_address": "127.0.0.1",
|
||||
"author_name": "deploy-key-name",
|
||||
"entity_path": "example-group/example-project",
|
||||
"target_details": "example-project",
|
||||
"created_at": "2022-07-26T05:43:53.662Z",
|
||||
"target_type": "Project",
|
||||
"target_id": 29,
|
||||
"event_type": "repository_git_operation"
|
||||
}
|
||||
```
|
||||
|
||||
### Example payloads for HTTP and HTTPS events
|
||||
|
||||
Fetch:
|
||||
|
@ -441,6 +480,7 @@ Fetch:
|
|||
"entity_type": "Project",
|
||||
"details": {
|
||||
"author_name": "Administrator",
|
||||
"author_class": "User",
|
||||
"target_id": 29,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-project",
|
||||
|
@ -472,6 +512,7 @@ Push:
|
|||
"entity_type": "Project",
|
||||
"details": {
|
||||
"author_name": "Administrator",
|
||||
"author_class": "User",
|
||||
"target_id": 29,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-project",
|
||||
|
@ -493,6 +534,40 @@ Push:
|
|||
}
|
||||
```
|
||||
|
||||
#### Example payloads for HTTP and HTTPS events with Deploy Token
|
||||
|
||||
Fetch:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"author_id": -2,
|
||||
"entity_id": 22,
|
||||
"entity_type": "Project",
|
||||
"details": {
|
||||
"author_name": "deploy-token-name",
|
||||
"author_class": "DeployToken",
|
||||
"target_id": 22,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-project",
|
||||
"custom_message": {
|
||||
"protocol": "http",
|
||||
"action": "git-upload-pack"
|
||||
},
|
||||
"ip_address": "127.0.0.1",
|
||||
"entity_path": "example-group/example-project"
|
||||
},
|
||||
"ip_address": "127.0.0.1",
|
||||
"author_name": "deploy-token-name",
|
||||
"entity_path": "example-group/example-project",
|
||||
"target_details": "example-project",
|
||||
"created_at": "2022-07-26T05:46:25.850Z",
|
||||
"target_type": "Project",
|
||||
"target_id": 22,
|
||||
"event_type": "repository_git_operation"
|
||||
}
|
||||
```
|
||||
|
||||
### Example payloads for events from GitLab UI download button
|
||||
|
||||
Fetch:
|
||||
|
@ -506,6 +581,7 @@ Fetch:
|
|||
"details": {
|
||||
"custom_message": "Repository Download Started",
|
||||
"author_name": "example_username",
|
||||
"author_class": "User",
|
||||
"target_id": 29,
|
||||
"target_type": "Project",
|
||||
"target_details": "example-group/example-project",
|
||||
|
|
|
@ -49,6 +49,18 @@ to all the members of that project's group. This might be interpreted as spam.
|
|||
Notifications and mentions can be disabled in
|
||||
[a group's settings](../group/manage.md#disable-email-notifications).
|
||||
|
||||
### Mention a group in an issue or merge request
|
||||
|
||||
When you mention a group in a comment, every member of the group gets a to-do item
|
||||
added to their To-do list.
|
||||
|
||||
1. Open the MR or issue.
|
||||
1. In a comment, type `@` followed by the user, group, or subgroup namespace.
|
||||
For example, `@alex`, `@alex-team`, or `@alex-team/marketing`.
|
||||
1. Select **Comment**.
|
||||
|
||||
A to-do item is created for all the group and subgroup members.
|
||||
|
||||
## Add a comment to a merge request diff
|
||||
|
||||
You can add comments to a merge request diff. These comments
|
||||
|
|
|
@ -48,29 +48,6 @@ For example, consider a user named Alex:
|
|||
| Alex creates a group for their team with the group name `alex-team`. The group and its projects are available at: `https://gitlab.example.com/alex-team`. | The namespace in this case is `alex-team`. |
|
||||
| Alex creates a subgroup of `alex-team` with the subgroup name `marketing`. The subgroup and its projects are available at: `https://gitlab.example.com/alex-team/marketing`. | The namespace in this case is `alex-team/marketing`. |
|
||||
|
||||
## Mention a group in an issue or merge request
|
||||
|
||||
When you mention a group in a comment, every member of the group gets a to-do item
|
||||
added to their To-do list.
|
||||
|
||||
1. Open the MR or issue.
|
||||
1. In a comment, type `@` followed by the user, group, or subgroup namespace.
|
||||
For example, `@alex`, `@alex-team`, or `@alex-team/marketing`.
|
||||
1. Select **Comment**.
|
||||
|
||||
A to-do item is created for all the group and subgroup members.
|
||||
|
||||
## Export members as CSV **(PREMIUM)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/336520) in GitLab 14.5.
|
||||
|
||||
You can export a list of members in a group or subgroup as a CSV.
|
||||
|
||||
1. Go to your group or subgroup and select either **Group information > Members** or **Subgroup information > Members**.
|
||||
1. Select **Export as CSV**.
|
||||
1. After the CSV file has been generated, it is emailed as an attachment to the user that requested it.
|
||||
|
||||
## Related topics
|
||||
|
||||
- [Group wikis](../project/wiki/index.md)
|
||||
|
|
|
@ -380,6 +380,17 @@ To disable group mentions:
|
|||
1. Select **Disable group mentions**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Export members as CSV **(PREMIUM)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287940) in GitLab 14.2.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/336520) in GitLab 14.5.
|
||||
|
||||
You can export a list of members in a group or subgroup as a CSV.
|
||||
|
||||
1. Go to your group or subgroup and select either **Group information > Members** or **Subgroup information > Members**.
|
||||
1. Select **Export as CSV**.
|
||||
1. After the CSV file has been generated, it is emailed as an attachment to the user that requested it.
|
||||
|
||||
## User cap for groups
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/330027) in GitLab 14.7.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -32,6 +32,10 @@ module API
|
|||
key || user
|
||||
end
|
||||
|
||||
def deploy_key_or_user
|
||||
key.instance_of?(DeployKey) ? key : user
|
||||
end
|
||||
|
||||
def username
|
||||
user&.username
|
||||
end
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Audit
|
||||
class DeployKeyAuthor < Gitlab::Audit::NullAuthor
|
||||
def initialize(name: nil)
|
||||
super(id: -3, name: name)
|
||||
end
|
||||
|
||||
def name
|
||||
@name || _('Deploy Key')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -24,6 +24,8 @@ module Gitlab
|
|||
Gitlab::Audit::UnauthenticatedAuthor.new(name: name)
|
||||
elsif id == -2
|
||||
Gitlab::Audit::DeployTokenAuthor.new(name: name)
|
||||
elsif id == -3
|
||||
Gitlab::Audit::DeployKeyAuthor.new(name: name)
|
||||
else
|
||||
Gitlab::Audit::DeletedAuthor.new(id: id, name: name)
|
||||
end
|
||||
|
|
|
@ -20,13 +20,24 @@ namespace :contracts do
|
|||
Pact::VerificationTask.new(:get_pipeline_header_data) do |pact|
|
||||
pact.uri(
|
||||
"#{contracts}/contracts/project/pipeline/show/pipelines#show-get_pipeline_header_data.json",
|
||||
pact_helper: "#{provider}/pact_helpers/project/pipeline/get_pipeline_header_data_helper.rb"
|
||||
pact_helper: "#{provider}/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb"
|
||||
)
|
||||
end
|
||||
|
||||
Pact::VerificationTask.new(:delete_pipeline) do |pact|
|
||||
pact.uri(
|
||||
"#{contracts}/contracts/project/pipeline/show/pipelines#show-delete_pipeline.json",
|
||||
pact_helper: "#{provider}/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb"
|
||||
)
|
||||
end
|
||||
|
||||
desc 'Run all pipeline contract tests'
|
||||
task 'test:pipelines', :contract_mr do |_t, arg|
|
||||
errors = %w[get_list_project_pipelines get_pipeline_header_data].each_with_object([]) do |task, err|
|
||||
errors = %w[
|
||||
get_list_project_pipelines
|
||||
get_pipeline_header_data
|
||||
delete_pipeline
|
||||
].each_with_object([]) do |task, err|
|
||||
Rake::Task["contracts:pipelines:pact:verify:#{task}"].execute
|
||||
rescue StandardError, SystemExit
|
||||
err << "contracts:pipelines:pact:verify:#{task}"
|
||||
|
|
|
@ -34,7 +34,7 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
|
|||
env["BUNDLE_DEPLOYMENT"] = 'false'
|
||||
end
|
||||
|
||||
output, status = Gitlab::Popen.popen([make_cmd, 'all', 'git'], nil, env)
|
||||
output, status = Gitlab::Popen.popen([make_cmd, 'clean-build', 'all', 'git'], nil, env)
|
||||
raise "Gitaly failed to compile: #{output}" unless status&.zero?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12731,6 +12731,9 @@ msgid_plural "Deploys"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "Deploy Key"
|
||||
msgstr ""
|
||||
|
||||
msgid "Deploy Keys"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@
|
|||
"cache-loader": "^4.1.0",
|
||||
"canvas-confetti": "^1.4.0",
|
||||
"clipboard": "^2.0.8",
|
||||
"codemirror": "^5.48.4",
|
||||
"codesandbox-api": "0.0.23",
|
||||
"compression-webpack-plugin": "^5.0.2",
|
||||
"copy-webpack-plugin": "^6.4.1",
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
const DeletePipeline = {
|
||||
success: {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
method: 'POST',
|
||||
path: '/api/graphql',
|
||||
},
|
||||
|
||||
variables: {
|
||||
id: 'gid://gitlab/Ci::Pipeline/316112',
|
||||
},
|
||||
};
|
||||
|
||||
export { DeletePipeline };
|
|
@ -23,3 +23,24 @@ export async function getPipelineHeaderDataRequest(endpoint) {
|
|||
data: graphqlQuery,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deletePipeline(endpoint) {
|
||||
const { url } = endpoint;
|
||||
const query = await extractGraphQLQuery(
|
||||
'app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql',
|
||||
);
|
||||
const graphqlQuery = {
|
||||
query,
|
||||
variables: {
|
||||
id: 'gid://gitlab/Ci::Pipeline/316112',
|
||||
},
|
||||
};
|
||||
|
||||
return axios({
|
||||
baseURL: url,
|
||||
url: '/api/graphql',
|
||||
method: 'POST',
|
||||
headers: { Accept: '*/*' },
|
||||
data: graphqlQuery,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,24 +6,27 @@ import { GraphQLInteraction } from '@pact-foundation/pact';
|
|||
import { extractGraphQLQuery } from '../../../helpers/graphql_query_extractor';
|
||||
|
||||
import { PipelineHeaderData } from '../../../fixtures/project/pipeline/get_pipeline_header_data.fixture';
|
||||
import { getPipelineHeaderDataRequest } from '../../../resources/graphql/pipelines';
|
||||
import { DeletePipeline } from '../../../fixtures/project/pipeline/delete_pipeline.fixture';
|
||||
|
||||
import { getPipelineHeaderDataRequest, deletePipeline } from '../../../resources/graphql/pipelines';
|
||||
|
||||
const CONSUMER_NAME = 'Pipelines#show';
|
||||
const CONSUMER_LOG = '../logs/consumer.log';
|
||||
const CONTRACT_DIR = '../contracts/project/pipeline/show';
|
||||
const PROVIDER_NAME = 'GET pipeline header data';
|
||||
const GET_PIPELINE_HEADER_DATA_PROVIDER_NAME = 'GET pipeline header data';
|
||||
const DELETE_PIPELINE_PROVIDER_NAME = 'DELETE pipeline';
|
||||
|
||||
// GraphQL query: getPipelineHeaderData
|
||||
pactWith(
|
||||
{
|
||||
consumer: CONSUMER_NAME,
|
||||
provider: PROVIDER_NAME,
|
||||
provider: GET_PIPELINE_HEADER_DATA_PROVIDER_NAME,
|
||||
log: CONSUMER_LOG,
|
||||
dir: CONTRACT_DIR,
|
||||
},
|
||||
|
||||
(provider) => {
|
||||
describe(PROVIDER_NAME, () => {
|
||||
describe(GET_PIPELINE_HEADER_DATA_PROVIDER_NAME, () => {
|
||||
beforeEach(async () => {
|
||||
const query = await extractGraphQLQuery(
|
||||
'app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql',
|
||||
|
@ -50,4 +53,41 @@ pactWith(
|
|||
},
|
||||
);
|
||||
|
||||
// GraphQL query: deletePipeline
|
||||
pactWith(
|
||||
{
|
||||
consumer: CONSUMER_NAME,
|
||||
provider: DELETE_PIPELINE_PROVIDER_NAME,
|
||||
log: CONSUMER_LOG,
|
||||
dir: CONTRACT_DIR,
|
||||
},
|
||||
|
||||
(provider) => {
|
||||
describe(DELETE_PIPELINE_PROVIDER_NAME, () => {
|
||||
beforeEach(async () => {
|
||||
const query = await extractGraphQLQuery(
|
||||
'app/assets/javascripts/pipelines/graphql/mutations/delete_pipeline.mutation.graphql',
|
||||
);
|
||||
const graphqlQuery = new GraphQLInteraction()
|
||||
.given('a pipeline for a project exists')
|
||||
.uponReceiving('a request to delete the pipeline')
|
||||
.withQuery(query)
|
||||
.withRequest(DeletePipeline.request)
|
||||
.withVariables(DeletePipeline.variables)
|
||||
.willRespondWith(DeletePipeline.success);
|
||||
|
||||
provider.addInteraction(graphqlQuery);
|
||||
});
|
||||
|
||||
it('returns a successful body', async () => {
|
||||
const deletePipelineResponse = await deletePipeline({
|
||||
url: provider.mockService.baseUrl,
|
||||
});
|
||||
|
||||
expect(deletePipelineResponse.status).toEqual(DeletePipeline.success.status);
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
/* eslint-enable @gitlab/require-i18n-strings */
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"consumer": {
|
||||
"name": "Pipelines#show"
|
||||
},
|
||||
"provider": {
|
||||
"name": "DELETE pipeline"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"description": "a request to delete the pipeline",
|
||||
"providerState": "a pipeline for a project exists",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"path": "/api/graphql",
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
},
|
||||
"body": {
|
||||
"query": "mutation deletePipeline($id: CiPipelineID!) {\n pipelineDestroy(input: { id: $id }) {\n errors\n }\n}\n",
|
||||
"variables": {
|
||||
"id": "gid://gitlab/Ci::Pipeline/316112"
|
||||
}
|
||||
},
|
||||
"matchingRules": {
|
||||
"$.body.query": {
|
||||
"match": "regex",
|
||||
"regex": "mutation\\s*deletePipeline\\(\\$id:\\s*CiPipelineID!\\)\\s*\\{\\s*pipelineDestroy\\(input:\\s*\\{\\s*id:\\s*\\$id\\s*\\}\\)\\s*\\{\\s*errors\\s*\\}\\s*\\}\\s*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../../../spec_helper'
|
||||
require_relative '../../../../states/project/pipeline/show_state'
|
||||
|
||||
module Provider
|
||||
module DeletePipelineHelper
|
||||
Pact.service_provider "DELETE pipeline" do
|
||||
app { Environments::Test.app }
|
||||
|
||||
honours_pact_with 'Pipelines#show' do
|
||||
pact_uri '../contracts/project/pipeline/show/pipelines#show-delete_pipeline.json'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../../spec_helper'
|
||||
require_relative '../../../states/project/pipeline/pipeline_state'
|
||||
require_relative '../../../../spec_helper'
|
||||
require_relative '../../../../states/project/pipeline/pipeline_state'
|
||||
|
||||
module Provider
|
||||
module GetPipelinesHeaderDataHelper
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Pact.provider_states_for "Pipelines#show" do
|
||||
provider_state "a pipeline for a project exists" do
|
||||
set_up do
|
||||
user = User.find_by(name: Provider::UsersHelper::CONTRACT_USER_NAME)
|
||||
namespace = create(:namespace, name: 'gitlab-org')
|
||||
project = create(:project, :repository, name: 'gitlab-qa', namespace: namespace, creator: user)
|
||||
scheduled_job = create(:ci_build, :scheduled)
|
||||
manual_job = create(:ci_build, :manual)
|
||||
|
||||
project.add_maintainer(user)
|
||||
|
||||
create(
|
||||
:ci_pipeline,
|
||||
:with_job,
|
||||
:success,
|
||||
id: 316112,
|
||||
iid: 1,
|
||||
project: project,
|
||||
user: user,
|
||||
duration: 10,
|
||||
finished_at: '2022-06-01T02:47:31.432Z',
|
||||
builds: [scheduled_job, manual_job]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -257,7 +257,12 @@ describe('Client side Markdown processing', () => {
|
|||
expectedDoc: doc(
|
||||
paragraph(
|
||||
source('<img src="bar" alt="foo" />'),
|
||||
image({ ...source('<img src="bar" alt="foo" />'), alt: 'foo', src: 'bar' }),
|
||||
image({
|
||||
...source('<img src="bar" alt="foo" />'),
|
||||
alt: 'foo',
|
||||
canonicalSrc: 'bar',
|
||||
src: 'http://test.host/bar',
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
|
@ -275,7 +280,12 @@ describe('Client side Markdown processing', () => {
|
|||
),
|
||||
paragraph(
|
||||
source('<img src="bar" alt="foo" />'),
|
||||
image({ ...source('<img src="bar" alt="foo" />'), alt: 'foo', src: 'bar' }),
|
||||
image({
|
||||
...source('<img src="bar" alt="foo" />'),
|
||||
alt: 'foo',
|
||||
src: 'http://test.host/bar',
|
||||
canonicalSrc: 'bar',
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
|
@ -287,7 +297,8 @@ describe('Client side Markdown processing', () => {
|
|||
link(
|
||||
{
|
||||
...source('[GitLab](https://gitlab.com "Go to GitLab")'),
|
||||
href: 'https://gitlab.com',
|
||||
href: 'https://gitlab.com/',
|
||||
canonicalSrc: 'https://gitlab.com',
|
||||
title: 'Go to GitLab',
|
||||
},
|
||||
'GitLab',
|
||||
|
@ -305,7 +316,8 @@ describe('Client side Markdown processing', () => {
|
|||
link(
|
||||
{
|
||||
...source('[GitLab](https://gitlab.com "Go to GitLab")'),
|
||||
href: 'https://gitlab.com',
|
||||
href: 'https://gitlab.com/',
|
||||
canonicalSrc: 'https://gitlab.com',
|
||||
title: 'Go to GitLab',
|
||||
},
|
||||
'GitLab',
|
||||
|
@ -322,7 +334,8 @@ describe('Client side Markdown processing', () => {
|
|||
link(
|
||||
{
|
||||
...source('www.commonmark.org'),
|
||||
href: 'http://www.commonmark.org',
|
||||
canonicalSrc: 'http://www.commonmark.org',
|
||||
href: 'http://www.commonmark.org/',
|
||||
},
|
||||
'www.commonmark.org',
|
||||
),
|
||||
|
@ -338,6 +351,7 @@ describe('Client side Markdown processing', () => {
|
|||
link(
|
||||
{
|
||||
...source('www.commonmark.org/help'),
|
||||
canonicalSrc: 'http://www.commonmark.org/help',
|
||||
href: 'http://www.commonmark.org/help',
|
||||
},
|
||||
'www.commonmark.org/help',
|
||||
|
@ -355,6 +369,7 @@ describe('Client side Markdown processing', () => {
|
|||
link(
|
||||
{
|
||||
...source('hello+xyz@mail.example'),
|
||||
canonicalSrc: 'mailto:hello+xyz@mail.example',
|
||||
href: 'mailto:hello+xyz@mail.example',
|
||||
},
|
||||
'hello+xyz@mail.example',
|
||||
|
@ -373,7 +388,8 @@ describe('Client side Markdown processing', () => {
|
|||
{
|
||||
sourceMapKey: null,
|
||||
sourceMarkdown: null,
|
||||
href: 'https://gitlab.com',
|
||||
canonicalSrc: 'https://gitlab.com',
|
||||
href: 'https://gitlab.com/',
|
||||
},
|
||||
'https://gitlab.com',
|
||||
),
|
||||
|
@ -402,6 +418,7 @@ hard line break`,
|
|||
image({
|
||||
...source('![GitLab Logo](https://gitlab.com/logo.png "GitLab Logo")'),
|
||||
alt: 'GitLab Logo',
|
||||
canonicalSrc: 'https://gitlab.com/logo.png',
|
||||
src: 'https://gitlab.com/logo.png',
|
||||
title: 'GitLab Logo',
|
||||
}),
|
||||
|
@ -595,7 +612,12 @@ two
|
|||
paragraph(
|
||||
source('List item with an image ![bar](foo.png)'),
|
||||
'List item with an image',
|
||||
image({ ...source('![bar](foo.png)'), alt: 'bar', src: 'foo.png' }),
|
||||
image({
|
||||
...source('![bar](foo.png)'),
|
||||
alt: 'bar',
|
||||
canonicalSrc: 'foo.png',
|
||||
src: 'http://test.host/foo.png',
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -944,8 +966,17 @@ Paragraph
|
|||
paragraph(
|
||||
source('[![moon](moon.jpg)](/uri)'),
|
||||
link(
|
||||
{ ...source('[![moon](moon.jpg)](/uri)'), href: '/uri' },
|
||||
image({ ...source('![moon](moon.jpg)'), src: 'moon.jpg', alt: 'moon' }),
|
||||
{
|
||||
...source('[![moon](moon.jpg)](/uri)'),
|
||||
canonicalSrc: '/uri',
|
||||
href: 'http://test.host/uri',
|
||||
},
|
||||
image({
|
||||
...source('![moon](moon.jpg)'),
|
||||
canonicalSrc: 'moon.jpg',
|
||||
src: 'http://test.host/moon.jpg',
|
||||
alt: 'moon',
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -975,12 +1006,26 @@ Paragraph
|
|||
source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
|
||||
strike(
|
||||
source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
|
||||
link({ ...source('[moon](moon.jpg)'), href: 'moon.jpg' }, 'moon'),
|
||||
link(
|
||||
{
|
||||
...source('[moon](moon.jpg)'),
|
||||
canonicalSrc: 'moon.jpg',
|
||||
href: 'http://test.host/moon.jpg',
|
||||
},
|
||||
'moon',
|
||||
),
|
||||
),
|
||||
strike(source('~[moon](moon.jpg) and [sun](sun.jpg)~'), ' and '),
|
||||
strike(
|
||||
source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
|
||||
link({ ...source('[sun](sun.jpg)'), href: 'sun.jpg' }, 'sun'),
|
||||
link(
|
||||
{
|
||||
...source('[sun](sun.jpg)'),
|
||||
href: 'http://test.host/sun.jpg',
|
||||
canonicalSrc: 'sun.jpg',
|
||||
},
|
||||
'sun',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1094,7 +1139,12 @@ _world_.
|
|||
paragraph(
|
||||
source('[GitLab][gitlab-url]'),
|
||||
link(
|
||||
{ ...source('[GitLab][gitlab-url]'), href: 'https://gitlab.com', title: 'GitLab' },
|
||||
{
|
||||
...source('[GitLab][gitlab-url]'),
|
||||
href: 'https://gitlab.com/',
|
||||
canonicalSrc: 'https://gitlab.com',
|
||||
title: 'GitLab',
|
||||
},
|
||||
'GitLab',
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1213,42 +1213,47 @@ paragraph
|
|||
};
|
||||
|
||||
it.each`
|
||||
mark | markdown | modifiedMarkdown | editAction
|
||||
${'bold'} | ${'**bold**'} | ${'**bold modified**'} | ${defaultEditAction}
|
||||
${'bold'} | ${'__bold__'} | ${'__bold modified__'} | ${defaultEditAction}
|
||||
${'bold'} | ${'<strong>bold</strong>'} | ${'<strong>bold modified</strong>'} | ${defaultEditAction}
|
||||
${'bold'} | ${'<b>bold</b>'} | ${'<b>bold modified</b>'} | ${defaultEditAction}
|
||||
${'italic'} | ${'_italic_'} | ${'_italic modified_'} | ${defaultEditAction}
|
||||
${'italic'} | ${'*italic*'} | ${'*italic modified*'} | ${defaultEditAction}
|
||||
${'italic'} | ${'<em>italic</em>'} | ${'<em>italic modified</em>'} | ${defaultEditAction}
|
||||
${'italic'} | ${'<i>italic</i>'} | ${'<i>italic modified</i>'} | ${defaultEditAction}
|
||||
${'link'} | ${'[gitlab](https://gitlab.com)'} | ${'[gitlab modified](https://gitlab.com)'} | ${defaultEditAction}
|
||||
${'link'} | ${'<a href="https://gitlab.com">link</a>'} | ${'<a href="https://gitlab.com">link modified</a>'} | ${defaultEditAction}
|
||||
${'link'} | ${'link www.gitlab.com'} | ${'modified link www.gitlab.com'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com'} | ${'modified link https://www.gitlab.com'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link(https://www.gitlab.com)'} | ${'modified link(https://www.gitlab.com)'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link(engineering@gitlab.com)'} | ${'modified link(engineering@gitlab.com)'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link <https://www.gitlab.com>'} | ${'modified link <https://www.gitlab.com>'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link [https://www.gitlab.com>'} | ${'modified link \\[https://www.gitlab.com>'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link <https://www.gitlab.com'} | ${'modified link <https://www.gitlab.com'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com>'} | ${'modified link [https://www.gitlab.com>](https://www.gitlab.com%3E)'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link **https://www.gitlab.com]**'} | ${'modified link [**https://www.gitlab.com\\]**](https://www.gitlab.com%5D)'} | ${prependContentEditAction}
|
||||
${'code'} | ${'`code`'} | ${'`code modified`'} | ${defaultEditAction}
|
||||
${'code'} | ${'<code>code</code>'} | ${'<code>code modified</code>'} | ${defaultEditAction}
|
||||
${'strike'} | ${'~~striked~~'} | ${'~~striked modified~~'} | ${defaultEditAction}
|
||||
${'strike'} | ${'<del>striked</del>'} | ${'<del>striked modified</del>'} | ${defaultEditAction}
|
||||
${'strike'} | ${'<strike>striked</strike>'} | ${'<strike>striked modified</strike>'} | ${defaultEditAction}
|
||||
${'strike'} | ${'<s>striked</s>'} | ${'<s>striked modified</s>'} | ${defaultEditAction}
|
||||
${'list'} | ${'- list item'} | ${'- list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'* list item'} | ${'* list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'+ list item'} | ${'+ list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'- list item 1\n- list item 2'} | ${'- list item 1\n- list item 2 modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'2) list item'} | ${'2) list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'1. list item'} | ${'1. list item modified'} | ${defaultEditAction}
|
||||
${'taskList'} | ${'2) [ ] task list item'} | ${'2) [ ] task list item modified'} | ${defaultEditAction}
|
||||
${'taskList'} | ${'2) [x] task list item'} | ${'2) [x] task list item modified'} | ${defaultEditAction}
|
||||
mark | markdown | modifiedMarkdown | editAction
|
||||
${'bold'} | ${'**bold**'} | ${'**bold modified**'} | ${defaultEditAction}
|
||||
${'bold'} | ${'__bold__'} | ${'__bold modified__'} | ${defaultEditAction}
|
||||
${'bold'} | ${'<strong>bold</strong>'} | ${'<strong>bold modified</strong>'} | ${defaultEditAction}
|
||||
${'bold'} | ${'<b>bold</b>'} | ${'<b>bold modified</b>'} | ${defaultEditAction}
|
||||
${'italic'} | ${'_italic_'} | ${'_italic modified_'} | ${defaultEditAction}
|
||||
${'italic'} | ${'*italic*'} | ${'*italic modified*'} | ${defaultEditAction}
|
||||
${'italic'} | ${'<em>italic</em>'} | ${'<em>italic modified</em>'} | ${defaultEditAction}
|
||||
${'italic'} | ${'<i>italic</i>'} | ${'<i>italic modified</i>'} | ${defaultEditAction}
|
||||
${'link'} | ${'[gitlab](https://gitlab.com)'} | ${'[gitlab modified](https://gitlab.com)'} | ${defaultEditAction}
|
||||
${'link'} | ${'<a href="https://gitlab.com">link</a>'} | ${'<a href="https://gitlab.com/">link modified</a>'} | ${defaultEditAction}
|
||||
${'link'} | ${'link www.gitlab.com'} | ${'modified link www.gitlab.com'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com'} | ${'modified link https://www.gitlab.com'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link(https://www.gitlab.com)'} | ${'modified link(https://www.gitlab.com)'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link(engineering@gitlab.com)'} | ${'modified link(engineering@gitlab.com)'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link <https://www.gitlab.com>'} | ${'modified link <https://www.gitlab.com>'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link [https://www.gitlab.com>'} | ${'modified link \\[https://www.gitlab.com>'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link <https://www.gitlab.com'} | ${'modified link <https://www.gitlab.com'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com>'} | ${'modified link [https://www.gitlab.com>](https://www.gitlab.com%3E)'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com/path'} | ${'modified link https://www.gitlab.com/path'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com?query=search'} | ${'modified link https://www.gitlab.com?query=search'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com/#fragment'} | ${'modified link https://www.gitlab.com/#fragment'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com/?query=search'} | ${'modified link https://www.gitlab.com/?query=search'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link https://www.gitlab.com#fragment'} | ${'modified link https://www.gitlab.com#fragment'} | ${prependContentEditAction}
|
||||
${'link'} | ${'link **https://www.gitlab.com]**'} | ${'modified link [**https://www.gitlab.com\\]**](https://www.gitlab.com%5D)'} | ${prependContentEditAction}
|
||||
${'code'} | ${'`code`'} | ${'`code modified`'} | ${defaultEditAction}
|
||||
${'code'} | ${'<code>code</code>'} | ${'<code>code modified</code>'} | ${defaultEditAction}
|
||||
${'strike'} | ${'~~striked~~'} | ${'~~striked modified~~'} | ${defaultEditAction}
|
||||
${'strike'} | ${'<del>striked</del>'} | ${'<del>striked modified</del>'} | ${defaultEditAction}
|
||||
${'strike'} | ${'<strike>striked</strike>'} | ${'<strike>striked modified</strike>'} | ${defaultEditAction}
|
||||
${'strike'} | ${'<s>striked</s>'} | ${'<s>striked modified</s>'} | ${defaultEditAction}
|
||||
${'list'} | ${'- list item'} | ${'- list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'* list item'} | ${'* list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'+ list item'} | ${'+ list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'- list item 1\n- list item 2'} | ${'- list item 1\n- list item 2 modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'2) list item'} | ${'2) list item modified'} | ${defaultEditAction}
|
||||
${'list'} | ${'1. list item'} | ${'1. list item modified'} | ${defaultEditAction}
|
||||
${'taskList'} | ${'2) [ ] task list item'} | ${'2) [ ] task list item modified'} | ${defaultEditAction}
|
||||
${'taskList'} | ${'2) [x] task list item'} | ${'2) [x] task list item modified'} | ${defaultEditAction}
|
||||
`(
|
||||
'preserves original $mark syntax when sourceMarkdown is available for $content',
|
||||
'preserves original $mark syntax when sourceMarkdown is available for $markdown',
|
||||
async ({ markdown, modifiedMarkdown, editAction }) => {
|
||||
const { document } = await remarkMarkdownDeserializer().deserialize({
|
||||
schema: tiptapEditor.schema,
|
||||
|
|
|
@ -1062,4 +1062,28 @@ describe('URL utility', () => {
|
|||
expect(urlUtils.PROMO_URL).toBe(url);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeUrlProtocol', () => {
|
||||
it.each`
|
||||
input | output
|
||||
${'http://gitlab.com'} | ${'gitlab.com'}
|
||||
${'https://gitlab.com'} | ${'gitlab.com'}
|
||||
${'foo:bar.com'} | ${'bar.com'}
|
||||
${'gitlab.com'} | ${'gitlab.com'}
|
||||
`('transforms $input to $output', ({ input, output }) => {
|
||||
expect(urlUtils.removeUrlProtocol(input)).toBe(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeLastSlashInUrlPath', () => {
|
||||
it.each`
|
||||
input | output
|
||||
${'https://www.gitlab.com/path/'} | ${'https://www.gitlab.com/path'}
|
||||
${'https://www.gitlab.com/?query=search'} | ${'https://www.gitlab.com?query=search'}
|
||||
${'https://www.gitlab.com/#fragment'} | ${'https://www.gitlab.com#fragment'}
|
||||
${'https://www.gitlab.com/hello'} | ${'https://www.gitlab.com/hello'}
|
||||
`('transforms $input to $output', ({ input, output }) => {
|
||||
expect(urlUtils.removeLastSlashInUrlPath(input)).toBe(output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -64,7 +64,7 @@ RSpec.describe Mutations::MergeRequests::SetLabels do
|
|||
end
|
||||
|
||||
context 'when passing operation_mode as REMOVE' do
|
||||
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids, operation_mode: Types::MutationOperationModeEnum.enum[:remove])}
|
||||
subject { mutation.resolve(project_path: merge_request.project.full_path, iid: merge_request.iid, label_ids: label_ids, operation_mode: Types::MutationOperationModeEnum.enum[:remove]) }
|
||||
|
||||
it 'removes the labels, without removing others' do
|
||||
merge_request.update!(labels: [label, label2])
|
||||
|
|
|
@ -11,9 +11,9 @@ RSpec.describe Mutations::Releases::Create do
|
|||
|
||||
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
|
||||
|
||||
let(:tag) { 'v1.1.0'}
|
||||
let(:ref) { 'master'}
|
||||
let(:name) { 'Version 1.0'}
|
||||
let(:tag) { 'v1.1.0' }
|
||||
let(:ref) { 'master' }
|
||||
let(:name) { 'Version 1.0' }
|
||||
let(:description) { 'The first release :rocket:' }
|
||||
let(:released_at) { Time.parse('2018-12-10') }
|
||||
let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe Mutations::Releases::Delete do
|
|||
let_it_be(:reporter) { create(:user) }
|
||||
let_it_be(:developer) { create(:user) }
|
||||
let_it_be(:maintainer) { create(:user) }
|
||||
let_it_be(:tag) { 'v1.1.0'}
|
||||
let_it_be(:tag) { 'v1.1.0' }
|
||||
let_it_be(:release) { create(:release, project: project, tag: tag) }
|
||||
|
||||
let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
|
||||
|
|
|
@ -9,8 +9,8 @@ RSpec.describe Mutations::Releases::Update do
|
|||
let_it_be(:reporter) { create(:user) }
|
||||
let_it_be(:developer) { create(:user) }
|
||||
|
||||
let_it_be(:tag) { 'v1.1.0'}
|
||||
let_it_be(:name) { 'Version 1.0'}
|
||||
let_it_be(:tag) { 'v1.1.0' }
|
||||
let_it_be(:name) { 'Version 1.0' }
|
||||
let_it_be(:description) { 'The first release :rocket:' }
|
||||
let_it_be(:released_at) { Time.parse('2018-12-10').utc }
|
||||
let_it_be(:created_at) { Time.parse('2018-11-05').utc }
|
||||
|
|
|
@ -12,7 +12,7 @@ RSpec.describe Resolvers::Ci::RunnerJobsResolver do
|
|||
let!(:build_one) { create(:ci_build, :success, name: 'Build One', runner: runner, pipeline: pipeline) }
|
||||
let!(:build_two) { create(:ci_build, :success, name: 'Build Two', runner: runner, pipeline: pipeline) }
|
||||
let!(:build_three) { create(:ci_build, :failed, name: 'Build Three', runner: runner, pipeline: pipeline) }
|
||||
let!(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)}
|
||||
let!(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline) }
|
||||
|
||||
let(:args) { {} }
|
||||
let(:runner) { create(:ci_runner, :project, projects: [project]) }
|
||||
|
|
|
@ -17,7 +17,7 @@ RSpec.describe Resolvers::GroupMembers::NotificationEmailResolver do
|
|||
expect(described_class).to have_nullable_graphql_type(GraphQL::Types::String)
|
||||
end
|
||||
|
||||
subject { batch_sync { resolve_notification_email(developer.group_members.first, current_user) }}
|
||||
subject { batch_sync { resolve_notification_email(developer.group_members.first, current_user) } }
|
||||
|
||||
context 'when current_user is admin' do
|
||||
let(:current_user) { create(:user, :admin) }
|
||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe Resolvers::ProjectJobsResolver do
|
|||
let_it_be(:failed_build) { create(:ci_build, :failed, name: 'Build Three', pipeline: pipeline) }
|
||||
let_it_be(:pending_build) { create(:ci_build, :pending, name: 'Build Three', pipeline: pipeline) }
|
||||
|
||||
let(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline)}
|
||||
let(:irrelevant_build) { create(:ci_build, name: 'Irrelevant Build', pipeline: irrelevant_pipeline) }
|
||||
let(:args) { {} }
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe Resolvers::Projects::GrafanaIntegrationResolver do
|
|||
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:grafana_integration) { create(:grafana_integration, project: project)}
|
||||
let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
|
||||
|
||||
describe '#resolve' do
|
||||
context 'when object is not a project' do
|
||||
|
@ -19,7 +19,7 @@ RSpec.describe Resolvers::Projects::GrafanaIntegrationResolver do
|
|||
end
|
||||
|
||||
context 'when object is nil' do
|
||||
it { expect(resolve_integration(obj: nil)).to eq nil}
|
||||
it { expect(resolve_integration(obj: nil)).to eq nil }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ RSpec.describe Resolvers::ProjectsResolver do
|
|||
|
||||
context 'when no sort is provided' do
|
||||
it 'returns projects in descending order by id' do
|
||||
is_expected.to match_array((visible_projecs + named_projects).sort_by { |p| p[:id]}.reverse )
|
||||
is_expected.to match_array((visible_projecs + named_projects).sort_by { |p| p[:id] }.reverse )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,7 +34,7 @@ RSpec.describe GitlabSchema.types['CiJobTokenScopeType'] do
|
|||
subject { GitlabSchema.execute(query, context: { current_user: current_user }).as_json }
|
||||
|
||||
let(:projects_field) { subject.dig('data', 'project', 'ciJobTokenScope', 'projects', 'nodes') }
|
||||
let(:returned_project_paths) { projects_field.map { |project| project['path']} }
|
||||
let(:returned_project_paths) { projects_field.map { |project| project['path'] } }
|
||||
|
||||
context 'with access to scope' do
|
||||
before do
|
||||
|
|
|
@ -167,7 +167,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
|
|||
shared_examples_for 'does not include private notes' do
|
||||
it "does not return private notes" do
|
||||
notes = subject.dig("data", "project", "issue", "notes", 'edges')
|
||||
notes_body = notes.map {|n| n.dig('node', 'body')}
|
||||
notes_body = notes.map { |n| n.dig('node', 'body') }
|
||||
|
||||
expect(notes.size).to eq 1
|
||||
expect(notes_body).not_to include(private_note_body)
|
||||
|
@ -178,7 +178,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
|
|||
shared_examples_for 'includes private notes' do
|
||||
it "returns all notes" do
|
||||
notes = subject.dig("data", "project", "issue", "notes", 'edges')
|
||||
notes_body = notes.map {|n| n.dig('node', 'body')}
|
||||
notes_body = notes.map { |n| n.dig('node', 'body') }
|
||||
|
||||
expect(notes.size).to eq 2
|
||||
expect(notes_body).to include(private_note_body)
|
||||
|
@ -209,7 +209,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
|
|||
end
|
||||
|
||||
describe 'hidden', :enable_admin_mode do
|
||||
let_it_be(:admin) { create(:user, :admin)}
|
||||
let_it_be(:admin) { create(:user, :admin) }
|
||||
let_it_be(:banned_user) { create(:user, :banned) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
|
|
|
@ -49,7 +49,7 @@ RSpec.describe GitlabSchema.types['User'] do
|
|||
end
|
||||
|
||||
describe 'name field' do
|
||||
let_it_be(:admin) { create(:user, :admin)}
|
||||
let_it_be(:admin) { create(:user, :admin) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:requested_user) { create(:user, name: 'John Smith') }
|
||||
let_it_be(:requested_project_bot) { create(:user, :project_bot, name: 'Project bot') }
|
||||
|
|
|
@ -83,6 +83,36 @@ RSpec.describe API::Support::GitAccessActor do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#deploy_key_or_user' do
|
||||
it 'returns a deploy key when the params contains deploy key' do
|
||||
key = create(:deploy_key)
|
||||
params = { key_id: key.id }
|
||||
|
||||
expect(described_class.from_params(params).deploy_key_or_user).to eq(key)
|
||||
end
|
||||
|
||||
it 'returns a user when the params contains personal key' do
|
||||
key = create(:key)
|
||||
params = { key_id: key.id }
|
||||
|
||||
expect(described_class.from_params(params).deploy_key_or_user).to eq(key.user)
|
||||
end
|
||||
|
||||
it 'returns a user when the params contains user id' do
|
||||
user = create(:user)
|
||||
params = { user_id: user.id }
|
||||
|
||||
expect(described_class.from_params(params).deploy_key_or_user).to eq(user)
|
||||
end
|
||||
|
||||
it 'returns a user when the params contains user name' do
|
||||
user = create(:user)
|
||||
params = { username: user.username }
|
||||
|
||||
expect(described_class.from_params(params).deploy_key_or_user).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#username' do
|
||||
context 'when initialized with a User' do
|
||||
let(:user) { build(:user) }
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Audit::DeployKeyAuthor do
|
||||
describe '#initialize' do
|
||||
it 'sets correct attributes' do
|
||||
expect(described_class.new(name: 'Lorem deploy key'))
|
||||
.to have_attributes(id: -3, name: 'Lorem deploy key')
|
||||
end
|
||||
|
||||
it 'sets default name when it is not provided' do
|
||||
expect(described_class.new)
|
||||
.to have_attributes(id: -3, name: 'Deploy Key')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -57,6 +57,15 @@ RSpec.describe Gitlab::Audit::NullAuthor do
|
|||
expect(subject.for(-2, audit_event)).to be_a(Gitlab::Audit::DeployTokenAuthor)
|
||||
expect(subject.for(-2, audit_event)).to have_attributes(id: -2, name: 'Test deploy token')
|
||||
end
|
||||
|
||||
it 'returns DeployKeyAuthor when id equals -3', :aggregate_failures do
|
||||
allow(audit_event).to receive(:[]).with(:author_name).and_return('Test deploy key')
|
||||
allow(audit_event).to receive(:details).and_return({})
|
||||
allow(audit_event).to receive(:target_type)
|
||||
|
||||
expect(subject.for(-3, audit_event)).to be_a(Gitlab::Audit::DeployKeyAuthor)
|
||||
expect(subject.for(-3, audit_event)).to have_attributes(id: -3, name: 'Test deploy key')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#current_sign_in_ip' do
|
||||
|
|
|
@ -5245,25 +5245,8 @@ RSpec.describe User do
|
|||
end
|
||||
|
||||
it 'returns number of open merge requests from non-archived projects' do
|
||||
expect(Rails.cache).not_to receive(:fetch)
|
||||
expect(user.attention_requested_open_merge_requests_count(force: true)).to eq 1
|
||||
end
|
||||
|
||||
context 'when uncached_mr_attention_requests_count is disabled' do
|
||||
before do
|
||||
stub_feature_flags(uncached_mr_attention_requests_count: false)
|
||||
end
|
||||
|
||||
it 'fetches from cache' do
|
||||
expect(Rails.cache).to receive(:fetch).with(
|
||||
user.attention_request_cache_key,
|
||||
force: false,
|
||||
expires_in: described_class::COUNT_CACHE_VALIDITY_PERIOD
|
||||
).and_call_original
|
||||
|
||||
expect(user.attention_requested_open_merge_requests_count).to eq 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#assigned_open_issues_count' do
|
||||
|
|
|
@ -61,7 +61,7 @@ RSpec.describe API::Boards do
|
|||
delete api(url, user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end.to change {board_parent.boards.count}.by(-1)
|
||||
end.to change { board_parent.boards.count }.by(-1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ RSpec.describe API::Branches do
|
|||
|
||||
context 'when sort value is not supported' do
|
||||
it_behaves_like '400 response' do
|
||||
let(:request) { get api(route, user), params: { sort: 'unknown' }}
|
||||
let(:request) { get api(route, user), params: { sort: 'unknown' } }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -158,7 +158,7 @@ RSpec.describe API::Ci::Jobs do
|
|||
|
||||
context 'with basic auth header' do
|
||||
let(:personal_access_token) { create(:personal_access_token, user: user) }
|
||||
let(:token) { personal_access_token.token}
|
||||
let(:token) { personal_access_token.token }
|
||||
|
||||
include_context 'with auth headers' do
|
||||
let(:header) { { Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => token } }
|
||||
|
|
|
@ -29,7 +29,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
|
|||
|
||||
describe 'POST /api/v4/jobs/request' do
|
||||
let!(:last_update) {}
|
||||
let!(:new_update) { }
|
||||
let!(:new_update) {}
|
||||
let(:user_agent) { 'gitlab-runner 9.0.0 (9-0-stable; go1.7.4; linux/amd64)' }
|
||||
|
||||
before do
|
||||
|
|
|
@ -61,7 +61,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_trace_chunks do
|
|||
end
|
||||
|
||||
context 'when job has been updated recently' do
|
||||
it { expect { patch_the_trace }.not_to change { job.updated_at }}
|
||||
it { expect { patch_the_trace }.not_to change { job.updated_at } }
|
||||
|
||||
it "changes the job's trace" do
|
||||
patch_the_trace
|
||||
|
@ -70,7 +70,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_trace_chunks do
|
|||
end
|
||||
|
||||
context 'when Runner makes a force-patch' do
|
||||
it { expect { force_patch_the_trace }.not_to change { job.updated_at }}
|
||||
it { expect { force_patch_the_trace }.not_to change { job.updated_at } }
|
||||
|
||||
it "doesn't change the build.trace" do
|
||||
force_patch_the_trace
|
||||
|
|
|
@ -59,7 +59,7 @@ RSpec.describe API::Ci::SecureFiles do
|
|||
|
||||
expect do
|
||||
post api("/projects/#{project.id}/secure_files", maintainer), params: file_params
|
||||
end.not_to change {project.secure_files.count}
|
||||
end.not_to change { project.secure_files.count }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:service_unavailable)
|
||||
end
|
||||
|
@ -78,7 +78,7 @@ RSpec.describe API::Ci::SecureFiles do
|
|||
it 'returns a 201 when uploading a file when the ci_secure_files_read_only feature flag is disabled' do
|
||||
expect do
|
||||
post api("/projects/#{project.id}/secure_files", maintainer), params: file_params
|
||||
end.to change {project.secure_files.count}.by(1)
|
||||
end.to change { project.secure_files.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
end
|
||||
|
@ -249,7 +249,7 @@ RSpec.describe API::Ci::SecureFiles do
|
|||
it 'creates a secure file' do
|
||||
expect do
|
||||
post api("/projects/#{project.id}/secure_files", maintainer), params: file_params
|
||||
end.to change {project.secure_files.count}.by(1)
|
||||
end.to change { project.secure_files.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response['name']).to eq('upload-keystore.jks')
|
||||
|
|
|
@ -136,8 +136,8 @@ RSpec.describe API::Ci::Triggers do
|
|||
end
|
||||
|
||||
context 'when triggered from another running job' do
|
||||
let!(:trigger) { }
|
||||
let!(:trigger_request) { }
|
||||
let!(:trigger) {}
|
||||
let!(:trigger_request) {}
|
||||
|
||||
context 'when other job is triggered by a user' do
|
||||
let(:trigger_token) { create(:ci_build, :running, project: project, user: user).token }
|
||||
|
@ -242,7 +242,7 @@ RSpec.describe API::Ci::Triggers do
|
|||
expect do
|
||||
post api("/projects/#{project.id}/triggers", user),
|
||||
params: { description: 'trigger' }
|
||||
end.to change {project.triggers.count}.by(1)
|
||||
end.to change { project.triggers.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response).to include('description' => 'trigger')
|
||||
|
@ -335,7 +335,7 @@ RSpec.describe API::Ci::Triggers do
|
|||
delete api("/projects/#{project.id}/triggers/#{trigger.id}", user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end.to change {project.triggers.count}.by(-1)
|
||||
end.to change { project.triggers.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'responds with 404 Not Found if requesting non-existing trigger' do
|
||||
|
|
|
@ -116,7 +116,7 @@ RSpec.describe API::Ci::Variables do
|
|||
it 'creates variable' do
|
||||
expect do
|
||||
post api("/projects/#{project.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
|
||||
end.to change {project.variables.count}.by(1)
|
||||
end.to change { project.variables.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response['key']).to eq('TEST_VARIABLE_2')
|
||||
|
@ -129,7 +129,7 @@ RSpec.describe API::Ci::Variables do
|
|||
it 'creates variable with optional attributes' do
|
||||
expect do
|
||||
post api("/projects/#{project.id}/variables", user), params: { variable_type: 'file', key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
|
||||
end.to change {project.variables.count}.by(1)
|
||||
end.to change { project.variables.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response['key']).to eq('TEST_VARIABLE_2')
|
||||
|
@ -142,7 +142,7 @@ RSpec.describe API::Ci::Variables do
|
|||
it 'does not allow to duplicate variable key' do
|
||||
expect do
|
||||
post api("/projects/#{project.id}/variables", user), params: { key: variable.key, value: 'VALUE_2' }
|
||||
end.to change {project.variables.count}.by(0)
|
||||
end.to change { project.variables.count }.by(0)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
|
@ -268,7 +268,7 @@ RSpec.describe API::Ci::Variables do
|
|||
delete api("/projects/#{project.id}/variables/#{variable.key}", user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end.to change {project.variables.count}.by(-1)
|
||||
end.to change { project.variables.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'responds with 404 Not Found if requesting non-existing variable' do
|
||||
|
@ -295,7 +295,7 @@ RSpec.describe API::Ci::Variables do
|
|||
delete api("/projects/#{project.id}/variables/key1", user), params: { 'filter[environment_scope]': 'production' }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end.to change {project.variables.count}.by(-1)
|
||||
end.to change { project.variables.count }.by(-1)
|
||||
|
||||
expect(var1.reload).to be_present
|
||||
expect { var2.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
|
|
|
@ -101,7 +101,7 @@ RSpec.describe API::Clusters::Agents do
|
|||
expect do
|
||||
post(api("/projects/#{project.id}/cluster_agents", user),
|
||||
params: { name: 'some-agent' })
|
||||
end.to change {project.cluster_agents.count}.by(1)
|
||||
end.to change { project.cluster_agents.count }.by(1)
|
||||
|
||||
aggregate_failures "testing response" do
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
|
@ -139,7 +139,7 @@ RSpec.describe API::Clusters::Agents do
|
|||
delete api("/projects/#{project.id}/cluster_agents/#{agent.id}", user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end.to change {project.cluster_agents.count}.by(-1)
|
||||
end.to change { project.cluster_agents.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'returns a 404 error when deleting non existent agent' do
|
||||
|
|
|
@ -988,8 +988,8 @@ RSpec.describe API::Commits do
|
|||
it 'returns all refs with no scope' do
|
||||
get api(route, current_user), params: { per_page: 100 }
|
||||
|
||||
refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
|
||||
refs.concat(project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]})
|
||||
refs = project.repository.branch_names_contains(commit_id).map { |name| ['branch', name] }
|
||||
refs.concat(project.repository.tag_names_contains(commit_id).map { |name| ['tag', name] })
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_limited_pagination_headers
|
||||
|
@ -1000,8 +1000,8 @@ RSpec.describe API::Commits do
|
|||
it 'returns all refs' do
|
||||
get api(route, current_user), params: { type: 'all', per_page: 100 }
|
||||
|
||||
refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
|
||||
refs.concat(project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]})
|
||||
refs = project.repository.branch_names_contains(commit_id).map { |name| ['branch', name] }
|
||||
refs.concat(project.repository.tag_names_contains(commit_id).map { |name| ['tag', name] })
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
|
||||
|
@ -1010,7 +1010,7 @@ RSpec.describe API::Commits do
|
|||
it 'returns the branch refs' do
|
||||
get api(route, current_user), params: { type: 'branch', per_page: 100 }
|
||||
|
||||
refs = project.repository.branch_names_contains(commit_id).map {|name| ['branch', name]}
|
||||
refs = project.repository.branch_names_contains(commit_id).map { |name| ['branch', name] }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
|
||||
|
@ -1019,7 +1019,7 @@ RSpec.describe API::Commits do
|
|||
it 'returns the tag refs' do
|
||||
get api(route, current_user), params: { type: 'tag', per_page: 100 }
|
||||
|
||||
refs = project.repository.tag_names_contains(commit_id).map {|name| ['tag', name]}
|
||||
refs = project.repository.tag_names_contains(commit_id).map { |name| ['tag', name] }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response.map { |r| [r['type'], r['name']] }.compact).to eq(refs)
|
||||
|
@ -2036,7 +2036,7 @@ RSpec.describe API::Commits do
|
|||
context 'unsigned commit' do
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) { get api(route, current_user) }
|
||||
let(:message) { '404 Signature Not Found'}
|
||||
let(:message) { '404 Signature Not Found' }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ RSpec.describe API::ConanInstancePackages do
|
|||
end
|
||||
|
||||
describe 'DELETE /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
|
||||
subject { delete api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
|
||||
subject { delete api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers }
|
||||
|
||||
it_behaves_like 'delete package endpoint'
|
||||
end
|
||||
|
|
|
@ -93,7 +93,7 @@ RSpec.describe API::ConanProjectPackages do
|
|||
end
|
||||
|
||||
describe 'DELETE /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
|
||||
subject { delete api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
|
||||
subject { delete api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}"), headers: headers }
|
||||
|
||||
it_behaves_like 'delete package endpoint'
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe API::DependencyProxy, api: true do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:blob) { create(:dependency_proxy_blob )}
|
||||
let_it_be(:blob) { create(:dependency_proxy_blob ) }
|
||||
let_it_be(:group, reload: true) { blob.group }
|
||||
|
||||
before do
|
||||
|
|
|
@ -451,7 +451,7 @@ RSpec.describe API::Deployments do
|
|||
describe 'DELETE /projects/:id/deployments/:deployment_id' do
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:environment) { create(:environment, project: project) }
|
||||
let(:commits) { project.repository.commits(nil, { limit: 2 })}
|
||||
let(:commits) { project.repository.commits(nil, { limit: 2 }) }
|
||||
let!(:deploy) do
|
||||
create(
|
||||
:deployment,
|
||||
|
|
|
@ -318,7 +318,7 @@ RSpec.describe API::GoProxy do
|
|||
context 'with a case sensitive project and versions' do
|
||||
let_it_be(:project) { create :project_empty_repo, :public, creator: user, path: 'MyGoLib' }
|
||||
let_it_be(:base) { "#{Settings.build_gitlab_go_url}/#{project.full_path}" }
|
||||
let_it_be(:base_encoded) { base.gsub(/[A-Z]/) { |s| "!#{s.downcase}"} }
|
||||
let_it_be(:base_encoded) { base.gsub(/[A-Z]/) { |s| "!#{s.downcase}" } }
|
||||
|
||||
let_it_be(:modules) do
|
||||
create(:go_module_commit, :files, project: project, files: { 'README.md' => "Hi" })
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'get board lists' do
|
|||
let_it_be(:group_label2) { create(:group_label, group: group, name: 'Testing') }
|
||||
|
||||
let(:params) { '' }
|
||||
let(:board) { }
|
||||
let(:board) {}
|
||||
let(:confidential) { false }
|
||||
let(:board_parent_type) { board_parent.class.to_s.downcase }
|
||||
let(:board_data) { graphql_data[board_parent_type]['boards']['nodes'][0] }
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'get board lists' do
|
|||
let_it_be(:group_label2) { create(:group_label, group: group, name: 'Testing') }
|
||||
|
||||
let(:params) { '' }
|
||||
let(:board) { }
|
||||
let(:board) {}
|
||||
let(:board_parent_type) { board_parent.class.to_s.downcase }
|
||||
let(:board_data) { graphql_data[board_parent_type]['boards']['edges'].first['node'] }
|
||||
let(:lists_data) { board_data['lists']['edges'] }
|
||||
|
|
|
@ -74,7 +74,7 @@ RSpec.describe 'Adding an AwardEmoji' do
|
|||
end
|
||||
|
||||
describe 'marking Todos as done' do
|
||||
let(:user) { current_user}
|
||||
let(:user) { current_user }
|
||||
|
||||
subject { post_graphql_mutation(mutation, current_user: user) }
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ RSpec.describe 'Toggling an AwardEmoji' do
|
|||
end
|
||||
|
||||
describe 'marking Todos as done' do
|
||||
let(:user) { current_user}
|
||||
let(:user) { current_user }
|
||||
|
||||
subject { post_graphql_mutation(mutation, current_user: user) }
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@ RSpec.describe 'Creation of a new release' do
|
|||
|
||||
let(:mutation_name) { :release_create }
|
||||
|
||||
let(:tag_name) { 'v7.12.5'}
|
||||
let(:tag_name) { 'v7.12.5' }
|
||||
let(:tag_message) { nil }
|
||||
let(:ref) { 'master'}
|
||||
let(:name) { 'Version 7.12.5'}
|
||||
let(:ref) { 'master' }
|
||||
let(:name) { 'Version 7.12.5' }
|
||||
let(:description) { 'Release 7.12.5 :rocket:' }
|
||||
let(:released_at) { '2018-12-10' }
|
||||
let(:milestones) { [milestone_12_3.title, milestone_12_4.title] }
|
||||
|
|
|
@ -15,7 +15,7 @@ RSpec.describe 'Updating an existing release' do
|
|||
let_it_be(:milestone_12_4) { create(:milestone, project: project, title: '12.4') }
|
||||
|
||||
let_it_be(:tag_name) { 'v1.1.0' }
|
||||
let_it_be(:name) { 'Version 7.12.5'}
|
||||
let_it_be(:name) { 'Version 7.12.5' }
|
||||
let_it_be(:description) { 'Release 7.12.5 :rocket:' }
|
||||
let_it_be(:released_at) { '2018-12-10' }
|
||||
let_it_be(:created_at) { '2018-11-05' }
|
||||
|
|
|
@ -12,8 +12,8 @@ RSpec.describe 'Creating a Snippet' do
|
|||
let(:title) { 'Initial title' }
|
||||
let(:visibility_level) { 'public' }
|
||||
let(:action) { :create }
|
||||
let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' }}
|
||||
let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' }}
|
||||
let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' } }
|
||||
let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' } }
|
||||
let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] }
|
||||
let(:project_path) { nil }
|
||||
let(:uploaded_files) { nil }
|
||||
|
@ -149,7 +149,7 @@ RSpec.describe 'Creating a Snippet' do
|
|||
end
|
||||
|
||||
context 'when there non ActiveRecord errors' do
|
||||
let(:file_1) { { filePath: 'invalid://file/path', content: 'foobar' }}
|
||||
let(:file_1) { { filePath: 'invalid://file/path', content: 'foobar' } }
|
||||
|
||||
it_behaves_like 'a mutation that returns errors in the response', errors: ['Repository Error creating the snippet - Invalid file name']
|
||||
it_behaves_like 'does not create snippet'
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe 'Delete a timelog' do
|
|||
let_it_be(:author) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :public) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800)}
|
||||
let_it_be(:timelog) { create(:timelog, user: author, issue: issue, time_spent: 1800) }
|
||||
|
||||
let(:current_user) { nil }
|
||||
let(:mutation) { graphql_mutation(:timelogDelete, { 'id' => timelog.to_global_id.to_s }) }
|
||||
|
|
|
@ -129,7 +129,7 @@ RSpec.describe 'Create a work item' do
|
|||
end
|
||||
|
||||
context 'when parent work item is not found' do
|
||||
let_it_be(:parent) { build_stubbed(:work_item, id: non_existing_record_id)}
|
||||
let_it_be(:parent) { build_stubbed(:work_item, id: non_existing_record_id) }
|
||||
|
||||
it 'returns a top level error' do
|
||||
post_graphql_mutation(mutation, current_user: current_user)
|
||||
|
|
|
@ -103,7 +103,7 @@ RSpec.describe 'Update a work item' do
|
|||
let(:input) { { 'confidential' => true } }
|
||||
|
||||
it_behaves_like 'toggling confidentiality' do
|
||||
let(:values) { { old: false, new: true }}
|
||||
let(:values) { { old: false, new: true } }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -115,7 +115,7 @@ RSpec.describe 'Update a work item' do
|
|||
end
|
||||
|
||||
it_behaves_like 'toggling confidentiality' do
|
||||
let(:values) { { old: true, new: false }}
|
||||
let(:values) { { old: true, new: false } }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,7 +49,7 @@ RSpec.describe 'rendering namespace statistics' do
|
|||
it_behaves_like 'a working namespace with storage statistics query'
|
||||
|
||||
context 'when the namespace is public' do
|
||||
let(:group) { create(:group, :public)}
|
||||
let(:group) { create(:group, :public) }
|
||||
|
||||
it 'hides statistics for unauthenticated requests' do
|
||||
post_graphql(query, current_user: nil)
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe 'conan package details' do
|
|||
let_it_be(:package) { create(:conan_package, project: project) }
|
||||
|
||||
let(:metadata) { query_graphql_fragment('ConanMetadata') }
|
||||
let(:package_files_metadata) {query_graphql_fragment('ConanFileMetadata')}
|
||||
let(:package_files_metadata) { query_graphql_fragment('ConanFileMetadata') }
|
||||
|
||||
let(:query) do
|
||||
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe 'helm package details' do
|
|||
|
||||
let_it_be(:package) { create(:helm_package, project: project) }
|
||||
|
||||
let(:package_files_metadata) {query_graphql_fragment('HelmFileMetadata')}
|
||||
let(:package_files_metadata) { query_graphql_fragment('HelmFileMetadata') }
|
||||
|
||||
let(:query) do
|
||||
graphql_query_for(:package, { id: package_global_id }, <<~FIELDS)
|
||||
|
|
|
@ -18,7 +18,7 @@ RSpec.describe 'package details' do
|
|||
let(:depth) { 3 }
|
||||
let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
|
||||
let(:metadata) { query_graphql_fragment('ComposerMetadata') }
|
||||
let(:package_files) {all_graphql_fields_for('PackageFile')}
|
||||
let(:package_files) { all_graphql_fields_for('PackageFile') }
|
||||
let(:package_global_id) { global_id_of(composer_package) }
|
||||
let(:package_details) { graphql_data_at(:package) }
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ RSpec.describe 'query Jira service' do
|
|||
)
|
||||
end
|
||||
|
||||
let(:services) { graphql_data.dig('project', 'services', 'nodes')}
|
||||
let(:services) { graphql_data.dig('project', 'services', 'nodes') }
|
||||
|
||||
it_behaves_like 'unauthorized users cannot read services'
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ RSpec.describe 'query Jira import data' do
|
|||
)
|
||||
end
|
||||
|
||||
let(:jira_imports) { graphql_data.dig('project', 'jiraImports', 'nodes')}
|
||||
let(:jira_import_status) { graphql_data.dig('project', 'jiraImportStatus')}
|
||||
let(:jira_imports) { graphql_data.dig('project', 'jiraImports', 'nodes') }
|
||||
let(:jira_import_status) { graphql_data.dig('project', 'jiraImportStatus') }
|
||||
|
||||
context 'when user cannot read Jira import data' do
|
||||
before do
|
||||
|
@ -89,11 +89,11 @@ RSpec.describe 'query Jira import data' do
|
|||
|
||||
context 'list of jira imports sorted ascending by scheduledAt time' do
|
||||
it 'retuns list of jira imports' do
|
||||
jira_proket_keys = jira_imports.map {|ji| ji['jiraProjectKey']}
|
||||
usernames = jira_imports.map {|ji| ji.dig('scheduledBy', 'username')}
|
||||
imported_issues_count = jira_imports.map {|ji| ji.dig('importedIssuesCount')}
|
||||
failed_issues_count = jira_imports.map {|ji| ji.dig('failedToImportCount')}
|
||||
total_issue_count = jira_imports.map {|ji| ji.dig('totalIssueCount')}
|
||||
jira_proket_keys = jira_imports.map { |ji| ji['jiraProjectKey'] }
|
||||
usernames = jira_imports.map { |ji| ji.dig('scheduledBy', 'username') }
|
||||
imported_issues_count = jira_imports.map { |ji| ji.dig('importedIssuesCount') }
|
||||
failed_issues_count = jira_imports.map { |ji| ji.dig('failedToImportCount') }
|
||||
total_issue_count = jira_imports.map { |ji| ji.dig('totalIssueCount') }
|
||||
|
||||
expect(jira_imports.size).to eq 2
|
||||
expect(jira_proket_keys).to eq %w(BB AA)
|
||||
|
|
|
@ -91,7 +91,7 @@ RSpec.describe API::GroupVariables do
|
|||
it 'creates variable' do
|
||||
expect do
|
||||
post api("/groups/#{group.id}/variables", user), params: { key: 'TEST_VARIABLE_2', value: 'PROTECTED_VALUE_2', protected: true, masked: true }
|
||||
end.to change {group.variables.count}.by(1)
|
||||
end.to change { group.variables.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response['key']).to eq('TEST_VARIABLE_2')
|
||||
|
@ -105,7 +105,7 @@ RSpec.describe API::GroupVariables do
|
|||
it 'creates variable with optional attributes' do
|
||||
expect do
|
||||
post api("/groups/#{group.id}/variables", user), params: { variable_type: 'file', key: 'TEST_VARIABLE_2', value: 'VALUE_2' }
|
||||
end.to change {group.variables.count}.by(1)
|
||||
end.to change { group.variables.count }.by(1)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:created)
|
||||
expect(json_response['key']).to eq('TEST_VARIABLE_2')
|
||||
|
@ -119,7 +119,7 @@ RSpec.describe API::GroupVariables do
|
|||
it 'does not allow to duplicate variable key' do
|
||||
expect do
|
||||
post api("/groups/#{group.id}/variables", user), params: { key: variable.key, value: 'VALUE_2' }
|
||||
end.to change {group.variables.count}.by(0)
|
||||
end.to change { group.variables.count }.by(0)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:bad_request)
|
||||
end
|
||||
|
@ -207,7 +207,7 @@ RSpec.describe API::GroupVariables do
|
|||
delete api("/groups/#{group.id}/variables/#{variable.key}", user)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end.to change {group.variables.count}.by(-1)
|
||||
end.to change { group.variables.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'responds with 404 Not Found if requesting non-existing variable' do
|
||||
|
|
|
@ -864,7 +864,7 @@ RSpec.describe API::Groups do
|
|||
end
|
||||
|
||||
describe 'PUT /groups/:id' do
|
||||
let(:new_group_name) { 'New Group'}
|
||||
let(:new_group_name) { 'New Group' }
|
||||
let(:file_path) { 'spec/fixtures/dk.png' }
|
||||
|
||||
it_behaves_like 'group avatar upload' do
|
||||
|
|
|
@ -26,8 +26,8 @@ RSpec.describe API::Helpers do
|
|||
}
|
||||
end
|
||||
|
||||
let(:header) { }
|
||||
let(:request) { Grape::Request.new(env)}
|
||||
let(:header) {}
|
||||
let(:request) { Grape::Request.new(env) }
|
||||
let(:params) { request.params }
|
||||
|
||||
before do
|
||||
|
|
|
@ -1451,7 +1451,7 @@ RSpec.describe API::Internal::Base do
|
|||
|
||||
describe 'POST /internal/two_factor_otp_check' do
|
||||
let(:key_id) { key.id }
|
||||
let(:otp) { '123456'}
|
||||
let(:otp) { '123456' }
|
||||
|
||||
subject do
|
||||
post api('/internal/two_factor_otp_check'),
|
||||
|
@ -1472,7 +1472,7 @@ RSpec.describe API::Internal::Base do
|
|||
|
||||
describe 'POST /internal/two_factor_manual_otp_check' do
|
||||
let(:key_id) { key.id }
|
||||
let(:otp) { '123456'}
|
||||
let(:otp) { '123456' }
|
||||
|
||||
subject do
|
||||
post api('/internal/two_factor_manual_otp_check'),
|
||||
|
@ -1493,7 +1493,7 @@ RSpec.describe API::Internal::Base do
|
|||
|
||||
describe 'POST /internal/two_factor_push_otp_check' do
|
||||
let(:key_id) { key.id }
|
||||
let(:otp) { '123456'}
|
||||
let(:otp) { '123456' }
|
||||
|
||||
subject do
|
||||
post api('/internal/two_factor_push_otp_check'),
|
||||
|
@ -1514,7 +1514,7 @@ RSpec.describe API::Internal::Base do
|
|||
|
||||
describe 'POST /internal/two_factor_manual_otp_check' do
|
||||
let(:key_id) { key.id }
|
||||
let(:otp) { '123456'}
|
||||
let(:otp) { '123456' }
|
||||
|
||||
subject do
|
||||
post api('/internal/two_factor_manual_otp_check'),
|
||||
|
@ -1534,7 +1534,7 @@ RSpec.describe API::Internal::Base do
|
|||
|
||||
describe 'POST /internal/two_factor_push_otp_check' do
|
||||
let(:key_id) { key.id }
|
||||
let(:otp) { '123456'}
|
||||
let(:otp) { '123456' }
|
||||
|
||||
subject do
|
||||
post api('/internal/two_factor_push_otp_check'),
|
||||
|
|
|
@ -131,7 +131,7 @@ RSpec.describe API::Markdown do
|
|||
end
|
||||
|
||||
context 'when not logged in' do
|
||||
let(:user) { }
|
||||
let(:user) {}
|
||||
|
||||
it_behaves_like 'user without proper access'
|
||||
end
|
||||
|
@ -176,7 +176,7 @@ RSpec.describe API::Markdown do
|
|||
end
|
||||
|
||||
context 'when not logged in' do
|
||||
let(:user) { }
|
||||
let(:user) {}
|
||||
|
||||
it_behaves_like 'user without proper access'
|
||||
end
|
||||
|
|
|
@ -34,7 +34,7 @@ RSpec.describe API::MavenPackages do
|
|||
end
|
||||
|
||||
let(:version) { '1.0-SNAPSHOT' }
|
||||
let(:param_path) { "#{package_name}/#{version}"}
|
||||
let(:param_path) { "#{package_name}/#{version}" }
|
||||
|
||||
before do
|
||||
project.add_developer(user)
|
||||
|
|
|
@ -187,8 +187,8 @@ RSpec.describe API::Members do
|
|||
end
|
||||
|
||||
context 'with a subgroup' do
|
||||
let(:group) { create(:group, :private)}
|
||||
let(:subgroup) { create(:group, :private, parent: group)}
|
||||
let(:group) { create(:group, :private) }
|
||||
let(:subgroup) { create(:group, :private, parent: group) }
|
||||
let(:project) { create(:project, group: subgroup) }
|
||||
|
||||
before do
|
||||
|
|
|
@ -10,7 +10,7 @@ RSpec.describe API::Metrics::Dashboard::Annotations do
|
|||
let(:dashboard) { 'config/prometheus/common_metrics.yml' }
|
||||
let(:starting_at) { Time.now.iso8601 }
|
||||
let(:ending_at) { 1.hour.from_now.iso8601 }
|
||||
let(:params) { attributes_for(:metrics_dashboard_annotation, environment: environment, starting_at: starting_at, ending_at: ending_at, dashboard_path: dashboard)}
|
||||
let(:params) { attributes_for(:metrics_dashboard_annotation, environment: environment, starting_at: starting_at, ending_at: ending_at, dashboard_path: dashboard) }
|
||||
|
||||
shared_examples 'POST /:source_type/:id/metrics_dashboard/annotations' do |source_type|
|
||||
let(:url) { "/#{source_type.pluralize}/#{source.id}/metrics_dashboard/annotations" }
|
||||
|
|
|
@ -111,7 +111,7 @@ RSpec.describe API::Notes do
|
|||
system: false
|
||||
end
|
||||
|
||||
let(:test_url) {"/projects/#{ext_proj.id}/issues/#{ext_issue.iid}/notes"}
|
||||
let(:test_url) { "/projects/#{ext_proj.id}/issues/#{ext_issue.iid}/notes" }
|
||||
|
||||
shared_examples 'a notes request' do
|
||||
it 'is a note array response' do
|
||||
|
|
|
@ -307,8 +307,8 @@ RSpec.describe API::NpmProjectPackages do
|
|||
expect { upload_package_with_token }
|
||||
.to change { project.packages.count }.by(1)
|
||||
.and change { Packages::PackageFile.count }.by(1)
|
||||
.and change { Packages::Dependency.count}.by(4)
|
||||
.and change { Packages::DependencyLink.count}.by(6)
|
||||
.and change { Packages::Dependency.count }.by(4)
|
||||
.and change { Packages::DependencyLink.count }.by(6)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
@ -323,8 +323,8 @@ RSpec.describe API::NpmProjectPackages do
|
|||
expect { upload_package_with_token }
|
||||
.to change { project.packages.count }.by(1)
|
||||
.and change { Packages::PackageFile.count }.by(1)
|
||||
.and not_change { Packages::Dependency.count}
|
||||
.and change { Packages::DependencyLink.count}.by(6)
|
||||
.and not_change { Packages::Dependency.count }
|
||||
.and change { Packages::DependencyLink.count }.by(6)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -73,7 +73,7 @@ RSpec.describe API::NugetGroupPackages do
|
|||
let(:include_prereleases) { true }
|
||||
let(:query_parameters) { { q: search_term, take: take, skip: skip, prerelease: include_prereleases }.compact }
|
||||
|
||||
subject { get api(url), headers: {}}
|
||||
subject { get api(url), headers: {} }
|
||||
|
||||
shared_examples 'handling mixed visibilities' do
|
||||
where(:group_visibility, :subgroup_visibility, :expected_status) do
|
||||
|
|
|
@ -19,7 +19,7 @@ RSpec.describe API::Pages do
|
|||
end
|
||||
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) { delete api("/projects/#{project.id}/pages", admin)}
|
||||
let(:request) { delete api("/projects/#{project.id}/pages", admin) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ RSpec.describe API::PagesDomains do
|
|||
end
|
||||
|
||||
let(:pages_domain_secure_params) { build(:pages_domain, domain: 'ssl.other-domain.test', project: project).slice(:domain, :certificate, :key) }
|
||||
let(:pages_domain_secure_key_missmatch_params) {build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
|
||||
let(:pages_domain_secure_missing_chain_params) {build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
|
||||
let(:pages_domain_secure_key_missmatch_params) { build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
|
||||
let(:pages_domain_secure_missing_chain_params) { build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
|
||||
|
||||
let(:route) { "/projects/#{project.id}/pages/domains" }
|
||||
let(:route_domain) { "/projects/#{project.id}/pages/domains/#{pages_domain.domain}" }
|
||||
|
|
|
@ -34,7 +34,7 @@ RSpec.describe API::PersonalAccessTokens do
|
|||
context 'logged in as a non-Administrator' do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:token) { create(:personal_access_token, user: current_user)}
|
||||
let_it_be(:token) { create(:personal_access_token, user: current_user) }
|
||||
let_it_be(:other_token) { create(:personal_access_token, user: user) }
|
||||
let_it_be(:token_impersonated) { create(:personal_access_token, impersonation: true, user: current_user) }
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ RSpec.describe API::ProjectTemplates do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(response).to match_response_schema('public_api/v4/template_list')
|
||||
expect(json_response.map {|t| t['key']}).to match_array(%w(bug feature_proposal template_test))
|
||||
expect(json_response.map { |t| t['key'] }).to match_array(%w(bug feature_proposal template_test))
|
||||
end
|
||||
|
||||
it 'returns merge request templates' do
|
||||
|
@ -86,7 +86,7 @@ RSpec.describe API::ProjectTemplates do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(response).to match_response_schema('public_api/v4/template_list')
|
||||
expect(json_response.map {|t| t['key']}).to match_array(%w(bug feature_proposal template_test))
|
||||
expect(json_response.map { |t| t['key'] }).to match_array(%w(bug feature_proposal template_test))
|
||||
end
|
||||
|
||||
it 'returns 400 for an unknown template type' do
|
||||
|
|
|
@ -1093,7 +1093,7 @@ RSpec.describe API::Projects do
|
|||
it 'does not create new project and respond with 403' do
|
||||
allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0)
|
||||
expect { post api('/projects', user2), params: { name: 'foo' } }
|
||||
.to change {Project.count}.by(0)
|
||||
.to change { Project.count }.by(0)
|
||||
expect(response).to have_gitlab_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,7 +41,7 @@ RSpec.describe API::PypiPackages do
|
|||
it_behaves_like 'deploy token for package GET requests'
|
||||
|
||||
context 'with group path as id' do
|
||||
let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple"}
|
||||
let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple" }
|
||||
|
||||
it_behaves_like 'deploy token for package GET requests'
|
||||
end
|
||||
|
@ -102,7 +102,7 @@ RSpec.describe API::PypiPackages do
|
|||
it_behaves_like 'deploy token for package GET requests'
|
||||
|
||||
context 'with group path as id' do
|
||||
let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple/#{package_name}"}
|
||||
let(:url) { "/groups/#{CGI.escape(group.full_path)}/-/packages/pypi/simple/#{package_name}" }
|
||||
|
||||
it_behaves_like 'deploy token for package GET requests'
|
||||
end
|
||||
|
|
|
@ -66,7 +66,7 @@ RSpec.describe API::Release::Links do
|
|||
end
|
||||
|
||||
context 'when release does not exist' do
|
||||
let!(:release) { }
|
||||
let!(:release) {}
|
||||
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", maintainer) }
|
||||
|
@ -98,7 +98,7 @@ RSpec.describe API::Release::Links do
|
|||
end
|
||||
|
||||
context 'when the release does not exists' do
|
||||
let!(:release) { }
|
||||
let!(:release) {}
|
||||
|
||||
it_behaves_like '403 response' do
|
||||
let(:request) { get api("/projects/#{project.id}/releases/v0.1/assets/links", non_project_member) }
|
||||
|
@ -409,7 +409,7 @@ RSpec.describe API::Release::Links do
|
|||
end
|
||||
|
||||
context 'when there are no corresponding release link' do
|
||||
let!(:release_link) { }
|
||||
let!(:release_link) {}
|
||||
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) do
|
||||
|
@ -510,7 +510,7 @@ RSpec.describe API::Release::Links do
|
|||
end
|
||||
|
||||
context 'when there are no corresponding release link' do
|
||||
let!(:release_link) { }
|
||||
let!(:release_link) {}
|
||||
|
||||
it_behaves_like '404 response' do
|
||||
let(:request) do
|
||||
|
|
|
@ -962,7 +962,7 @@ RSpec.describe API::Releases do
|
|||
context 'with milestones' do
|
||||
let(:subject) { post api("/projects/#{project.id}/releases", maintainer), params: params }
|
||||
let(:milestone) { create(:milestone, project: project, title: 'v1.0') }
|
||||
let(:returned_milestones) { json_response['milestones'].map {|m| m['title']} }
|
||||
let(:returned_milestones) { json_response['milestones'].map { |m| m['title'] } }
|
||||
|
||||
before do
|
||||
params.merge!(milestone_params)
|
||||
|
@ -1120,7 +1120,7 @@ RSpec.describe API::Releases do
|
|||
end
|
||||
|
||||
context 'when there are no corresponding releases' do
|
||||
let!(:release) { }
|
||||
let!(:release) {}
|
||||
|
||||
it 'forbids the request' do
|
||||
put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params
|
||||
|
@ -1158,7 +1158,7 @@ RSpec.describe API::Releases do
|
|||
end
|
||||
|
||||
context 'with milestones' do
|
||||
let(:returned_milestones) { json_response['milestones'].map {|m| m['title']} }
|
||||
let(:returned_milestones) { json_response['milestones'].map { |m| m['title'] } }
|
||||
|
||||
subject { put api("/projects/#{project.id}/releases/v0.1", maintainer), params: params }
|
||||
|
||||
|
@ -1310,7 +1310,7 @@ RSpec.describe API::Releases do
|
|||
end
|
||||
|
||||
context 'when there are no corresponding releases' do
|
||||
let!(:release) { }
|
||||
let!(:release) {}
|
||||
|
||||
it 'forbids the request' do
|
||||
delete api("/projects/#{project.id}/releases/v0.1", maintainer)
|
||||
|
|
|
@ -28,7 +28,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
|
||||
public_snippet.id,
|
||||
internal_snippet.id,
|
||||
private_snippet.id)
|
||||
|
@ -75,7 +75,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
it 'returns snippets available for user in given time range' do
|
||||
get api(path, personal_access_token: user_token)
|
||||
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
|
||||
private_snippet_in_time_range1.id,
|
||||
private_snippet_in_time_range2.id)
|
||||
end
|
||||
|
@ -99,10 +99,10 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
|
||||
public_snippet.id,
|
||||
public_snippet_other.id)
|
||||
expect(json_response.map { |snippet| snippet['web_url']} ).to contain_exactly(
|
||||
expect(json_response.map { |snippet| snippet['web_url'] } ).to contain_exactly(
|
||||
"http://localhost/-/snippets/#{public_snippet.id}",
|
||||
"http://localhost/-/snippets/#{public_snippet_other.id}")
|
||||
expect(json_response[0]['files'].first).to eq snippet_blob_file(public_snippet_other.blobs.first)
|
||||
|
@ -126,7 +126,7 @@ RSpec.describe API::Snippets, factory_default: :keep do
|
|||
it 'returns public snippets available to user in given time range' do
|
||||
get api(path, personal_access_token: user_token)
|
||||
|
||||
expect(json_response.map { |snippet| snippet['id']} ).to contain_exactly(
|
||||
expect(json_response.map { |snippet| snippet['id'] } ).to contain_exactly(
|
||||
public_snippet_in_time_range.id)
|
||||
end
|
||||
end
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue