Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-04-30 18:09:38 +00:00
parent 7f305b576b
commit 028bb5dda7
68 changed files with 385 additions and 238 deletions

View File

@ -30,7 +30,7 @@ workflow:
# merge requests used for this merge a branch release-tools/X into a stable
# branch. For these merge requests we don't want to run any pipelines, as
# they serve no purpose and will run anyway when the changes are merged.
- if: '$CI_COMMIT_BRANCH =~ /^release-tools\/\d+\.\d+\.\d+-rc\d+$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/ && $CI_PROJECT_PATH == "gitlab-org/gitlab"'
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^release-tools\/\d+\.\d+\.\d+-rc\d+$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee)?$/ && $CI_PROJECT_PATH == "gitlab-org/gitlab"'
when: never
# For merge requests, create a pipeline.
- if: '$CI_MERGE_REQUEST_IID'

View File

@ -16,6 +16,7 @@ export const getSettings = (state, getters) => ({
older_than: getters.getOlderThan,
keep_n: getters.getKeepN,
name_regex: state.settings.name_regex,
name_regex_keep: state.settings.name_regex_keep,
});
export const getIsEdited = state => !isEqual(state.original, state.settings);

View File

@ -1,8 +1,23 @@
<script>
import { uniqueId } from 'lodash';
import { GlFormGroup, GlToggle, GlFormSelect, GlFormTextarea, GlSprintf } from '@gitlab/ui';
import { s__, __ } from '~/locale';
import { NAME_REGEX_LENGTH } from '../constants';
import {
NAME_REGEX_LENGTH,
ENABLED_TEXT,
DISABLED_TEXT,
TEXT_AREA_INVALID_FEEDBACK,
EXPIRATION_INTERVAL_LABEL,
EXPIRATION_SCHEDULE_LABEL,
KEEP_N_LABEL,
NAME_REGEX_LABEL,
NAME_REGEX_PLACEHOLDER,
NAME_REGEX_DESCRIPTION,
NAME_REGEX_KEEP_LABEL,
NAME_REGEX_KEEP_PLACEHOLDER,
NAME_REGEX_KEEP_DESCRIPTION,
ENABLE_TOGGLE_LABEL,
ENABLE_TOGGLE_DESCRIPTION,
} from '../constants';
import { mapComputedToEvent } from '../utils';
export default {
@ -40,42 +55,73 @@ export default {
default: 'right',
},
},
nameRegexPlaceholder: '.*',
i18n: {
textAreaInvalidFeedback: TEXT_AREA_INVALID_FEEDBACK,
enableToggleLabel: ENABLE_TOGGLE_LABEL,
enableToggleDescription: ENABLE_TOGGLE_DESCRIPTION,
},
selectList: [
{
name: 'expiration-policy-interval',
label: s__('ContainerRegistry|Expiration interval:'),
label: EXPIRATION_INTERVAL_LABEL,
model: 'older_than',
optionKey: 'olderThan',
},
{
name: 'expiration-policy-schedule',
label: s__('ContainerRegistry|Expiration schedule:'),
label: EXPIRATION_SCHEDULE_LABEL,
model: 'cadence',
optionKey: 'cadence',
},
{
name: 'expiration-policy-latest',
label: s__('ContainerRegistry|Number of tags to retain:'),
label: KEEP_N_LABEL,
model: 'keep_n',
optionKey: 'keepN',
},
],
textAreaList: [
{
name: 'expiration-policy-name-matching',
label: NAME_REGEX_LABEL,
model: 'name_regex',
placeholder: NAME_REGEX_PLACEHOLDER,
stateVariable: 'nameRegexState',
description: NAME_REGEX_DESCRIPTION,
},
{
name: 'expiration-policy-keep-name',
label: NAME_REGEX_KEEP_LABEL,
model: 'name_regex_keep',
placeholder: NAME_REGEX_KEEP_PLACEHOLDER,
stateVariable: 'nameKeepRegexState',
description: NAME_REGEX_KEEP_DESCRIPTION,
},
],
data() {
return {
uniqueId: uniqueId(),
};
},
computed: {
...mapComputedToEvent(['enabled', 'cadence', 'older_than', 'keep_n', 'name_regex'], 'value'),
...mapComputedToEvent(
['enabled', 'cadence', 'older_than', 'keep_n', 'name_regex', 'name_regex_keep'],
'value',
),
policyEnabledText() {
return this.enabled ? __('enabled') : __('disabled');
return this.enabled ? ENABLED_TEXT : DISABLED_TEXT;
},
nameRegexState() {
return this.name_regex ? this.name_regex.length <= NAME_REGEX_LENGTH : null;
textAreaState() {
return {
nameRegexState: this.validateNameRegex(this.name_regex),
nameKeepRegexState: this.validateNameRegex(this.name_regex_keep),
};
},
fieldsValidity() {
return this.nameRegexState !== false;
return (
this.textAreaState.nameRegexState !== false &&
this.textAreaState.nameKeepRegexState !== false
);
},
isFormElementDisabled() {
return !this.enabled || this.isLoading;
@ -94,6 +140,9 @@ export default {
},
},
methods: {
validateNameRegex(value) {
return value ? value.length <= NAME_REGEX_LENGTH : null;
},
idGenerator(id) {
return `${id}_${this.uniqueId}`;
},
@ -111,7 +160,7 @@ export default {
:label-cols="labelCols"
:label-align="labelAlign"
:label-for="idGenerator('expiration-policy-toggle')"
:label="s__('ContainerRegistry|Expiration policy:')"
:label="$options.i18n.enableToggleLabel"
>
<div class="d-flex align-items-start">
<gl-toggle
@ -120,9 +169,7 @@ export default {
:disabled="isLoading"
/>
<span class="mb-2 ml-1 lh-2">
<gl-sprintf
:message="s__('ContainerRegistry|Docker tag expiration policy is %{toggleStatus}')"
>
<gl-sprintf :message="$options.i18n.enableToggleDescription">
<template #toggleStatus>
<strong>{{ policyEnabledText }}</strong>
</template>
@ -157,35 +204,34 @@ export default {
</gl-form-group>
<gl-form-group
:id="idGenerator('expiration-policy-name-matching-group')"
v-for="textarea in $options.textAreaList"
:id="idGenerator(`${textarea.name}-group`)"
:key="textarea.name"
:label-cols="labelCols"
:label-align="labelAlign"
:label-for="idGenerator('expiration-policy-name-matching')"
:label="
s__('ContainerRegistry|Docker tags with names matching this regex pattern will expire:')
"
:state="nameRegexState"
:invalid-feedback="
s__('ContainerRegistry|The value of this input should be less than 255 characters')
"
:label-for="idGenerator(textarea.name)"
:state="textAreaState[textarea.stateVariable]"
:invalid-feedback="$options.i18n.textAreaInvalidFeedback"
>
<template #label>
<gl-sprintf :message="textarea.label">
<template #italic="{content}">
<i>{{ content }}</i>
</template>
</gl-sprintf>
</template>
<gl-form-textarea
:id="idGenerator('expiration-policy-name-matching')"
v-model="name_regex"
:placeholder="$options.nameRegexPlaceholder"
:state="nameRegexState"
:id="idGenerator(textarea.name)"
:value="value[textarea.model]"
:placeholder="textarea.placeholder"
:state="textAreaState[textarea.stateVariable]"
:disabled="isFormElementDisabled"
trim
@input="updateModel($event, textarea.model)"
/>
<template #description>
<span ref="regex-description">
<gl-sprintf
:message="
s__(
'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
)
"
>
<gl-sprintf :message="textarea.description">
<template #code="{content}">
<code>{{ content }}</code>
</template>

View File

@ -1,4 +1,4 @@
import { s__ } from '~/locale';
import { s__, __ } from '~/locale';
export const FETCH_SETTINGS_ERROR_MESSAGE = s__(
'ContainerRegistry|Something went wrong while fetching the expiration policy.',
@ -13,3 +13,33 @@ export const UPDATE_SETTINGS_SUCCESS_MESSAGE = s__(
);
export const NAME_REGEX_LENGTH = 255;
export const ENABLED_TEXT = __('enabled');
export const DISABLED_TEXT = __('disabled');
export const ENABLE_TOGGLE_LABEL = s__('ContainerRegistry|Expiration policy:');
export const ENABLE_TOGGLE_DESCRIPTION = s__(
'ContainerRegistry|Docker tag expiration policy is %{toggleStatus}',
);
export const TEXT_AREA_INVALID_FEEDBACK = s__(
'ContainerRegistry|The value of this input should be less than 255 characters',
);
export const EXPIRATION_INTERVAL_LABEL = s__('ContainerRegistry|Expiration interval:');
export const EXPIRATION_SCHEDULE_LABEL = s__('ContainerRegistry|Expiration schedule:');
export const KEEP_N_LABEL = s__('ContainerRegistry|Number of tags to retain:');
export const NAME_REGEX_LABEL = s__(
'ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}',
);
export const NAME_REGEX_PLACEHOLDER = '.*';
export const NAME_REGEX_DESCRIPTION = s__(
'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
);
export const NAME_REGEX_KEEP_LABEL = s__(
'ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}be preserved:%{italicEnd}',
);
export const NAME_REGEX_KEEP_PLACEHOLDER = '';
export const NAME_REGEX_KEEP_DESCRIPTION = s__(
'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported',
);

View File

@ -28,7 +28,8 @@ export default {
},
returnUrl: {
type: String,
required: true,
required: false,
default: '',
},
},
};
@ -46,7 +47,7 @@ export default {
}}
</p>
<div class="d-flex justify-content-end">
<gl-button ref="returnToSiteButton" :href="returnUrl">{{
<gl-button v-if="returnUrl" ref="returnToSiteButton" :href="returnUrl">{{
s__('StaticSiteEditor|Return to site')
}}</gl-button>
<gl-button ref="mergeRequestButton" class="ml-2" :href="mergeRequest.url" variant="success">
@ -60,7 +61,7 @@ export default {
<ul>
<li>
{{ s__('StaticSiteEditor|You created a new branch:') }}
<span ref="branchLink">{{ branch.label }}</span>
<gl-link ref="branchLink" :href="branch.url">{{ branch.label }}</gl-link>
</li>
<li>
{{ s__('StaticSiteEditor|You created a merge request:') }}

View File

@ -48,6 +48,7 @@ export default {
<!-- Success view -->
<saved-changes-message
v-if="savedContentMeta"
class="w-75"
:branch="savedContentMeta.branch"
:commit="savedContentMeta.commit"
:merge-request="savedContentMeta.mergeRequest"

View File

@ -56,8 +56,8 @@ const submitContentChanges = ({ username, projectId, sourcePath, content }) => {
const meta = {};
return createBranch(projectId, branch)
.then(() => {
Object.assign(meta, { branch: { label: branch } });
.then(({ data: { web_url: url } }) => {
Object.assign(meta, { branch: { label: branch, url } });
return commitContent(projectId, mergeRequestTitle, branch, sourcePath, content);
})
@ -67,7 +67,7 @@ const submitContentChanges = ({ username, projectId, sourcePath, content }) => {
return createMergeRequest(projectId, mergeRequestTitle, branch);
})
.then(({ data: { iid: label, web_url: url } }) => {
Object.assign(meta, { mergeRequest: { label, url } });
Object.assign(meta, { mergeRequest: { label: label.toString(), url } });
return meta;
});

View File

@ -43,7 +43,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def usage_data
respond_to do |format|
format.html do
usage_data_json = JSON.pretty_generate(Gitlab::UsageData.data)
usage_data_json = Gitlab::Json.pretty_generate(Gitlab::UsageData.data)
render html: Gitlab::Highlight.highlight('payload.json', usage_data_json, language: 'json')
end

View File

@ -15,7 +15,7 @@ class Import::GoogleCodeController < Import::BaseController
end
begin
dump = JSON.parse(dump_file.read)
dump = Gitlab::Json.parse(dump_file.read)
rescue
return redirect_back_or_default(options: { alert: _("The uploaded file is not a valid Google Takeout archive.") })
end
@ -42,7 +42,7 @@ class Import::GoogleCodeController < Import::BaseController
user_map_json = "{}" if user_map_json.blank?
begin
user_map = JSON.parse(user_map_json)
user_map = Gitlab::Json.parse(user_map_json)
rescue
flash.now[:alert] = _("The entered user map is not a valid JSON user map.")

View File

@ -158,6 +158,6 @@ module IconsHelper
def known_sprites
return if Rails.env.production?
@known_sprites ||= JSON.parse(File.read(Rails.root.join('node_modules/@gitlab/svgs/dist/icons.json')))['icons']
@known_sprites ||= Gitlab::Json.parse(File.read(Rails.root.join('node_modules/@gitlab/svgs/dist/icons.json')))['icons']
end
end

View File

@ -32,7 +32,7 @@ module BlobViewer
def json_data
@json_data ||= begin
prepare!
JSON.parse(blob.data)
Gitlab::Json.parse(blob.data)
rescue
{}
end

View File

@ -5,7 +5,7 @@ require 'securerandom'
module Clusters
module Applications
class Jupyter < ApplicationRecord
VERSION = '0.9.0-beta.2'
VERSION = '0.9.0'
self.table_name = 'clusters_applications_jupyter'

View File

@ -17,7 +17,7 @@ module DiffPositionableNote
%i(original_position position change_position).each do |meth|
define_method "#{meth}=" do |new_position|
if new_position.is_a?(String)
new_position = JSON.parse(new_position) rescue nil
new_position = Gitlab::Json.parse(new_position) rescue nil
end
if new_position.is_a?(Hash)

View File

@ -43,7 +43,7 @@ module RedisCacheable
strong_memoize(:cached_attributes) do
Gitlab::Redis::Cache.with do |redis|
data = redis.get(cache_attribute_key)
JSON.parse(data, symbolize_names: true) if data
Gitlab::Json.parse(data, symbolize_names: true) if data
end
end
end

View File

@ -14,7 +14,7 @@ class MockMonitoringService < MonitoringService
end
def metrics(environment)
JSON.parse(File.read(Rails.root + 'spec/fixtures/metrics.json'))
Gitlab::Json.parse(File.read(Rails.root + 'spec/fixtures/metrics.json'))
end
def can_test?

View File

@ -76,7 +76,7 @@ class SentNotification < ApplicationRecord
def position=(new_position)
if new_position.is_a?(String)
new_position = JSON.parse(new_position) rescue nil
new_position = Gitlab::Json.parse(new_position) rescue nil
end
if new_position.is_a?(Hash)

View File

@ -113,7 +113,7 @@ module Metrics
end
def parse_json(json)
JSON.parse(json, symbolize_names: true)
Gitlab::Json.parse(json, symbolize_names: true)
rescue JSON::ParserError
raise DashboardProcessingError.new('Grafana response contains invalid json')
end

View File

@ -23,7 +23,7 @@ module Metrics
override :get_raw_dashboard
def get_raw_dashboard
JSON.parse(params[:embed_json])
Gitlab::Json.parse(params[:embed_json])
rescue JSON::ParserError => e
invalid_embed_json!(e.message)
end

View File

@ -69,7 +69,7 @@ module Projects
# application/vnd.git-lfs+json
# (https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#requests),
# HTTParty does not know this is actually JSON.
data = JSON.parse(response.body)
data = Gitlab::Json.parse(response.body)
raise DownloadLinksError, "LFS Batch API did return any objects" unless data.is_a?(Hash) && data.key?('objects')

View File

@ -42,7 +42,7 @@ module Projects
file.open do |stream|
Zlib::GzipReader.wrap(stream) do |gz_stream|
data = JSON.parse(gz_stream.read)
data = Gitlab::Json.parse(gz_stream.read)
end
end

View File

@ -53,7 +53,7 @@ class IrkerWorker # rubocop:disable Scalability/IdempotentWorker
def sendtoirker(privmsg)
to_send = { to: @channels, privmsg: privmsg }
@socket.puts JSON.dump(to_send)
@socket.puts Gitlab::Json.dump(to_send)
end
def close_connection

View File

@ -0,0 +1,5 @@
---
title: Add new keep regex to expiration policy settings ui
merge_request: 29940
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Update managed jupyter chart to 0.9.0 (stable)
merge_request: 30393
author:
type: changed

View File

@ -503,7 +503,7 @@ then goes through a process of excluding tags from it until only the ones to be
1. Evaluates the `name_regex`, excluding non-matching names from the list.
1. Excludes any tags that do not have a manifest (not part of the options).
1. Orders the remaining tags by `created_date`.
1. Excludes from the list the N tags based on the `keep_n` value (Expiration latest).
1. Excludes from the list the N tags based on the `keep_n` value (Number of tags to retain).
1. Excludes from the list the tags older than the `older_than` value (Expiration interval).
1. Finally, the remaining tags in the list are deleted from the Container Registry.
@ -518,7 +518,7 @@ The UI allows you to configure the following:
- **Expiration policy:** enable or disable the expiration policy.
- **Expiration interval:** how long tags are exempt from being deleted.
- **Expiration schedule:** how often the cron job checking the tags should run.
- **Expiration latest:** how many tags to _always_ keep for each image.
- **Number of tags to retain:** how many tags to _always_ keep for each image.
- **Docker tags with names matching this regex pattern will expire:** the regex used to determine what tags should be expired. To qualify all tags for expiration, use the default value of `.*`.
### Managing project expiration policy through the API

View File

@ -42,7 +42,7 @@ The importer will create any new namespaces (groups) if they don't exist or in
the case the namespace is taken, the repository will be imported under the user's
namespace that started the import process.
## Importing your Bitbucket repositories
## Import your Bitbucket repositories
1. Sign in to GitLab and go to your dashboard.
1. Click on **New project**.
@ -60,3 +60,12 @@ namespace that started the import process.
each project will be imported.
![Import projects](img/bitbucket_import_select_project_v12_3.png)
## Troubleshooting
If you have more than one Bitbucket account, be sure to sign in to the correct account.
If you've accidentally started the import process with the wrong account, follow these steps:
1. Revoke GitLab access to your Bitbucket account, essentially reversing the process in the following procedure: [Import your Bitbucket repositories](#import-your-bitbucket-repositories).
1. Sign out of the Bitbucket account. Follow the procedure linked from the previous step.

View File

@ -73,3 +73,7 @@ namespace that started the import process.
imported.
![Import projects](img/bitbucket_server_import_select_project_v12_3.png)
## Troubleshooting
See the [troubleshooting](bitbucket.md#troubleshooting) section for [Bitbucket](bitbucket.md).

View File

@ -65,10 +65,10 @@ also requires the GitLab Runner 11.5 or later. For earlier versions, use the
This example shows how to run Code Quality on your code by using GitLab CI/CD and Docker.
First, you need GitLab Runner with:
First, you need GitLab Runner configured:
- The [docker-in-docker executor](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
- Enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB.
- For the [docker-in-docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor).
- With enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB.
Once you set up the Runner, include the CodeQuality template in your CI config:

View File

@ -41,7 +41,10 @@ groups:
- [Label](../project/labels.md)
- My-reaction
- Confidential
- Epic ([Introduced](https://gitlab.com/gitlab-org/gitlab/issues/195704) in GitLab 12.9)
- Epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9),
including [child epic](../group/epics/index.md#multi-level-child-epics-ultimate)
([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in
[GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0)
- Search for this text
1. Select or type the operator to use for filtering the attribute. The following operators are
available:

View File

@ -78,12 +78,18 @@ module Gitlab
run_block_with_transaction
rescue ActiveRecord::LockWaitTimeout
if retry_with_lock_timeout?
disable_idle_in_transaction_timeout
wait_until_next_retry
reset_db_settings
retry
else
reset_db_settings
run_block_without_lock_timeout
end
ensure
reset_db_settings
end
end
@ -153,6 +159,14 @@ module Gitlab
def current_sleep_time_in_seconds
timing_configuration[current_iteration - 1][1].to_f
end
def disable_idle_in_transaction_timeout
execute("SET LOCAL idle_in_transaction_session_timeout TO '0'")
end
def reset_db_settings
execute('RESET idle_in_transaction_session_timeout; RESET lock_timeout')
end
end
end
end

View File

@ -5606,9 +5606,6 @@ msgstr ""
msgid "ContainerRegistry|Docker tag expiration policy is %{toggleStatus}"
msgstr ""
msgid "ContainerRegistry|Docker tags with names matching this regex pattern will expire:"
msgstr ""
msgid "ContainerRegistry|Edit Settings"
msgstr ""
@ -5654,7 +5651,10 @@ msgstr ""
msgid "ContainerRegistry|Quick Start"
msgstr ""
msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported"
msgstr ""
msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
msgstr ""
msgid "ContainerRegistry|Remove repository"
@ -5707,6 +5707,12 @@ msgstr ""
msgid "ContainerRegistry|Tags deleted successfully"
msgstr ""
msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}be preserved:%{italicEnd}"
msgstr ""
msgid "ContainerRegistry|Tags with names matching this regex pattern will %{italicStart}expire:%{italicEnd}"
msgstr ""
msgid "ContainerRegistry|The Container Registry tag expiration and retention policies for this project have not been enabled."
msgstr ""

View File

@ -9,7 +9,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show
expect(response).to have_gitlab_http_status(:unauthorized)
expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@ -23,7 +23,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: access_token.token }
expect(response).to have_gitlab_http_status(:ok)
expect(JSON.parse(response.body)).to eq(
expect(Gitlab::Json.parse(response.body)).to eq(
'scope' => %w[api],
'scopes' => %w[api],
'created_at' => access_token.created_at.to_i,
@ -40,7 +40,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: 'unknown_token' }
expect(response).to have_gitlab_http_status(:unauthorized)
expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@ -53,7 +53,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: access_token.token }
expect(response).to have_gitlab_http_status(:unauthorized)
expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@ -64,7 +64,7 @@ RSpec.describe Oauth::TokenInfoController do
get :show, params: { access_token: access_token.token }
expect(response).to have_gitlab_http_status(:unauthorized)
expect(JSON.parse(response.body)).to include('error' => 'invalid_request')
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
end

View File

@ -334,7 +334,7 @@ describe Projects::ArtifactsController do
def params
@params ||= begin
base64_params = send_data.sub(/\Aartifacts\-entry:/, '')
JSON.parse(Base64.urlsafe_decode64(base64_params))
Gitlab::Json.parse(Base64.urlsafe_decode64(base64_params))
end
end
end

View File

@ -17,7 +17,7 @@ describe Projects::CycleAnalytics::EventsController do
get_issue
expect(response).to be_successful
expect(JSON.parse(response.body)['events']).to be_empty
expect(Gitlab::Json.parse(response.body)['events']).to be_empty
end
end
@ -38,7 +38,7 @@ describe Projects::CycleAnalytics::EventsController do
it 'contains event detais' do
get_issue
events = JSON.parse(response.body)['events']
events = Gitlab::Json.parse(response.body)['events']
expect(events).not_to be_empty
expect(events.first).to include('title', 'author', 'iid', 'total_time', 'created_at', 'url')
@ -51,7 +51,7 @@ describe Projects::CycleAnalytics::EventsController do
expect(response).to be_successful
expect(JSON.parse(response.body)['events']).to be_empty
expect(Gitlab::Json.parse(response.body)['events']).to be_empty
end
end
end

View File

@ -38,7 +38,7 @@ describe Projects::Environments::PrometheusApiController do
context 'with success result' do
let(:service_result) { { status: :success, body: prometheus_body } }
let(:prometheus_body) { '{"status":"success"}' }
let(:prometheus_json_body) { JSON.parse(prometheus_body) }
let(:prometheus_json_body) { Gitlab::Json.parse(prometheus_body) }
it 'returns prometheus response' do
get :proxy, params: environment_params

View File

@ -50,7 +50,7 @@ describe Projects::LogsController do
container_name: container
}
end
let(:service_result_json) { JSON.parse(service_result.to_json) }
let(:service_result_json) { Gitlab::Json.parse(service_result.to_json) }
let_it_be(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) }

View File

@ -6,7 +6,7 @@ describe 'When a user filters Sentry errors by status', :js, :use_clean_rails_me
include_context 'sentry error tracking context feature'
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:filtered_errors_by_status_response) { JSON.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
let_it_be(:filtered_errors_by_status_response) { Gitlab::Json.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}

View File

@ -6,7 +6,7 @@ describe 'View error index page', :js, :use_clean_rails_memory_store_caching, :s
include_context 'sentry error tracking context feature'
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:issues_response) { JSON.parse(issues_response_body) }
let_it_be(:issues_response) { Gitlab::Json.parse(issues_response_body) }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
before do

View File

@ -52,7 +52,7 @@ describe 'Import/Export - project export integration test', :js do
project_json_path = File.join(tmpdir, 'project.json')
expect(File).to exist(project_json_path)
project_hash = JSON.parse(IO.read(project_json_path))
project_hash = Gitlab::Json.parse(IO.read(project_json_path))
sensitive_words.each do |sensitive_word|
found = find_sensitive_attributes(sensitive_word, project_hash)
@ -78,7 +78,7 @@ describe 'Import/Export - project export integration test', :js do
expect(File).to exist(project_json_path)
relations = []
relations << JSON.parse(IO.read(project_json_path))
relations << Gitlab::Json.parse(IO.read(project_json_path))
Dir.glob(File.join(tmpdir, 'tree/project', '*.ndjson')) do |rb_filename|
File.foreach(rb_filename) do |line|
json = ActiveSupport::JSON.decode(line)

View File

@ -76,7 +76,7 @@ describe 'Projects > Settings > For a forked project', :js do
context 'success path' do
let(:projects_sample_response) do
Gitlab::Utils.deep_indifferent_access(
JSON.parse(fixture_file('sentry/list_projects_sample_response.json'))
Gitlab::Json.parse(fixture_file('sentry/list_projects_sample_response.json'))
)
end

View File

@ -29,7 +29,7 @@ describe 'Project > Settings > CI/CD > Container registry tag expiration policy'
select('7 days until tags are automatically removed', from: 'Expiration interval:')
select('Every day', from: 'Expiration schedule:')
select('50 tags per image name', from: 'Number of tags to retain:')
fill_in('Docker tags with names matching this regex pattern will expire:', with: '*-production')
fill_in('Tags with names matching this regex pattern will expire:', with: '*-production')
end
submit_button = find('.card-footer .btn.btn-success')
expect(submit_button).not_to be_disabled

View File

@ -16,7 +16,7 @@ describe('IntegrationSettingsForm', () => {
beforeEach(() => {
integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
spyOn(integrationSettingsForm, 'init');
jest.spyOn(integrationSettingsForm, 'init').mockImplementation(() => {});
});
it('should initialize form element refs on class object', () => {
@ -130,7 +130,7 @@ describe('IntegrationSettingsForm', () => {
beforeEach(() => {
mock = new MockAdaptor(axios);
spyOn(axios, 'put').and.callThrough();
jest.spyOn(axios, 'put');
integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
// eslint-disable-next-line no-jquery/no-serialize
@ -141,18 +141,13 @@ describe('IntegrationSettingsForm', () => {
mock.restore();
});
it('should make an ajax request with provided `formData`', done => {
integrationSettingsForm
.testSettings(formData)
.then(() => {
expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
done();
})
.catch(done.fail);
it('should make an ajax request with provided `formData`', () => {
return integrationSettingsForm.testSettings(formData).then(() => {
expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
});
});
it('should show error Flash with `Save anyway` action if ajax request responds with error in test', done => {
it('should show error Flash with `Save anyway` action if ajax request responds with error in test', () => {
const errorMessage = 'Test failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
@ -161,32 +156,27 @@ describe('IntegrationSettingsForm', () => {
test_failed: true,
});
integrationSettingsForm
.testSettings(formData)
.then(() => {
const $flashContainer = $('.flash-container');
return integrationSettingsForm.testSettings(formData).then(() => {
const $flashContainer = $('.flash-container');
expect(
$flashContainer
.find('.flash-text')
.text()
.trim(),
).toEqual('Test failed. some error');
expect(
$flashContainer
.find('.flash-text')
.text()
.trim(),
).toEqual('Test failed. some error');
expect($flashContainer.find('.flash-action')).toBeDefined();
expect(
$flashContainer
.find('.flash-action')
.text()
.trim(),
).toEqual('Save anyway');
done();
})
.catch(done.fail);
expect($flashContainer.find('.flash-action')).toBeDefined();
expect(
$flashContainer
.find('.flash-action')
.text()
.trim(),
).toEqual('Save anyway');
});
});
it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', done => {
it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', () => {
const errorMessage = 'Validations failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
@ -195,50 +185,40 @@ describe('IntegrationSettingsForm', () => {
test_failed: false,
});
integrationSettingsForm
.testSettings(formData)
.then(() => {
const $flashContainer = $('.flash-container');
return integrationSettingsForm.testSettings(formData).then(() => {
const $flashContainer = $('.flash-container');
expect(
$flashContainer
.find('.flash-text')
.text()
.trim(),
).toEqual('Validations failed. some error');
expect(
$flashContainer
.find('.flash-text')
.text()
.trim(),
).toEqual('Validations failed. some error');
expect($flashContainer.find('.flash-action')).toBeDefined();
expect(
$flashContainer
.find('.flash-action')
.text()
.trim(),
).toEqual('');
done();
})
.catch(done.fail);
expect($flashContainer.find('.flash-action')).toBeDefined();
expect(
$flashContainer
.find('.flash-action')
.text()
.trim(),
).toEqual('');
});
});
it('should submit form if ajax request responds without any error in test', done => {
spyOn(integrationSettingsForm.$form, 'submit');
it('should submit form if ajax request responds without any error in test', () => {
jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: false,
});
integrationSettingsForm
.testSettings(formData)
.then(() => {
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
done();
})
.catch(done.fail);
return integrationSettingsForm.testSettings(formData).then(() => {
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
});
});
it('should submit form when clicked on `Save anyway` action of error Flash', done => {
spyOn(integrationSettingsForm.$form, 'submit');
it('should submit form when clicked on `Save anyway` action of error Flash', () => {
jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
const errorMessage = 'Test failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
@ -247,7 +227,7 @@ describe('IntegrationSettingsForm', () => {
test_failed: true,
});
integrationSettingsForm
return integrationSettingsForm
.testSettings(formData)
.then(() => {
const $flashAction = $('.flash-container .flash-action');
@ -258,44 +238,31 @@ describe('IntegrationSettingsForm', () => {
})
.then(() => {
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
done();
})
.catch(done.fail);
});
});
it('should show error Flash if ajax request failed', done => {
it('should show error Flash if ajax request failed', () => {
const errorMessage = 'Something went wrong on our end.';
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
integrationSettingsForm
.testSettings(formData)
.then(() => {
expect(
$('.flash-container .flash-text')
.text()
.trim(),
).toEqual(errorMessage);
done();
})
.catch(done.fail);
return integrationSettingsForm.testSettings(formData).then(() => {
expect(
$('.flash-container .flash-text')
.text()
.trim(),
).toEqual(errorMessage);
});
});
it('should always call `toggleSubmitBtnState` with `false` once request is completed', done => {
it('should always call `toggleSubmitBtnState` with `false` once request is completed', () => {
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
spyOn(integrationSettingsForm, 'toggleSubmitBtnState');
jest.spyOn(integrationSettingsForm, 'toggleSubmitBtnState').mockImplementation(() => {});
integrationSettingsForm
.testSettings(formData)
.then(() => {
expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
done();
})
.catch(done.fail);
return integrationSettingsForm.testSettings(formData).then(() => {
expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
});
});
});
});

View File

@ -4,9 +4,12 @@ import { formOptions } from '../../shared/mock_data';
describe('Getters registry settings store', () => {
const settings = {
enabled: true,
cadence: 'foo',
keep_n: 'bar',
older_than: 'baz',
name_regex: 'name-foo',
name_regex_keep: 'name-keep-bar',
};
describe.each`
@ -29,6 +32,17 @@ describe('Getters registry settings store', () => {
});
});
describe('getSettings', () => {
it('returns the content of settings', () => {
const computedGetters = {
getCadence: settings.cadence,
getOlderThan: settings.older_than,
getKeepN: settings.keep_n,
};
expect(getters.getSettings({ settings }, computedGetters)).toEqual(settings);
});
});
describe('getIsEdited', () => {
it('returns false when original is equal to settings', () => {
const same = { foo: 'bar' };

View File

@ -117,11 +117,11 @@ exports[`Expiration Policy Form renders 1`] = `
<gl-form-group-stub
id="expiration-policy-name-matching-group"
invalid-feedback="The value of this input should be less than 255 characters"
label="Docker tags with names matching this regex pattern will expire:"
label-align="right"
label-cols="3"
label-for="expiration-policy-name-matching"
>
<gl-form-textarea-stub
disabled="true"
id="expiration-policy-name-matching"
@ -130,5 +130,21 @@ exports[`Expiration Policy Form renders 1`] = `
value=""
/>
</gl-form-group-stub>
<gl-form-group-stub
id="expiration-policy-keep-name-group"
invalid-feedback="The value of this input should be less than 255 characters"
label-align="right"
label-cols="3"
label-for="expiration-policy-keep-name"
>
<gl-form-textarea-stub
disabled="true"
id="expiration-policy-keep-name"
placeholder=""
trim=""
value=""
/>
</gl-form-group-stub>
</div>
`;

View File

@ -40,12 +40,13 @@ describe('Expiration Policy Form', () => {
});
describe.each`
elementName | modelName | value | disabledByToggle
${'toggle'} | ${'enabled'} | ${true} | ${'not disabled'}
${'interval'} | ${'older_than'} | ${'foo'} | ${'disabled'}
${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'}
${'latest'} | ${'keep_n'} | ${'foo'} | ${'disabled'}
${'name-matching'} | ${'name_regex'} | ${'foo'} | ${'disabled'}
elementName | modelName | value | disabledByToggle
${'toggle'} | ${'enabled'} | ${true} | ${'not disabled'}
${'interval'} | ${'older_than'} | ${'foo'} | ${'disabled'}
${'schedule'} | ${'cadence'} | ${'foo'} | ${'disabled'}
${'latest'} | ${'keep_n'} | ${'foo'} | ${'disabled'}
${'name-matching'} | ${'name_regex'} | ${'foo'} | ${'disabled'}
${'keep-name'} | ${'name_regex_keep'} | ${'bar'} | ${'disabled'}
`(
`${FORM_ELEMENTS_ID_PREFIX}-$elementName form element`,
({ elementName, modelName, value, disabledByToggle }) => {
@ -118,21 +119,26 @@ describe('Expiration Policy Form', () => {
${'schedule'}
${'latest'}
${'name-matching'}
${'keep-name'}
`(`${FORM_ELEMENTS_ID_PREFIX}-$elementName is disabled`, ({ elementName }) => {
expect(findFormElements(elementName).attributes('disabled')).toBe('true');
});
});
describe('form validation', () => {
describe.each`
modelName | elementName | stateVariable
${'name_regex'} | ${'name-matching'} | ${'nameRegexState'}
${'name_regex_keep'} | ${'keep-name'} | ${'nameKeepRegexState'}
`('regex textarea validation', ({ modelName, elementName, stateVariable }) => {
describe(`when name regex is longer than ${NAME_REGEX_LENGTH}`, () => {
const invalidString = new Array(NAME_REGEX_LENGTH + 2).join(',');
beforeEach(() => {
mountComponent({ value: { name_regex: invalidString } });
mountComponent({ value: { [modelName]: invalidString } });
});
it('nameRegexState is false', () => {
expect(wrapper.vm.nameRegexState).toBe(false);
it(`${stateVariable} is false`, () => {
expect(wrapper.vm.textAreaState[stateVariable]).toBe(false);
});
it('emit the @invalidated event', () => {
@ -141,17 +147,20 @@ describe('Expiration Policy Form', () => {
});
it('if the user did not type validation is null', () => {
mountComponent({ value: { name_regex: '' } });
mountComponent({ value: { [modelName]: '' } });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.nameRegexState).toBe(null);
expect(wrapper.vm.textAreaState[stateVariable]).toBe(null);
expect(wrapper.emitted('validated')).toBeTruthy();
});
});
it(`if the user typed and is less than ${NAME_REGEX_LENGTH} state is true`, () => {
mountComponent({ value: { name_regex: 'foo' } });
mountComponent({ value: { [modelName]: 'foo' } });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.nameRegexState).toBe(true);
const formGroup = findFormGroup(elementName);
const formElement = findFormElements(elementName, formGroup);
expect(formGroup.attributes('state')).toBeTruthy();
expect(formElement.attributes('state')).toBeTruthy();
});
});
});

View File

@ -46,14 +46,11 @@ describe('~/static_site_editor/components/saved_changes_message.vue', () => {
${'branch'} | ${findBranchLink} | ${props.branch}
${'commit'} | ${findCommitLink} | ${props.commit}
${'merge request'} | ${findMergeRequestLink} | ${props.mergeRequest}
`('renders $desc link', ({ desc, findEl, prop }) => {
`('renders $desc link', ({ findEl, prop }) => {
const el = findEl();
expect(el.exists()).toBe(true);
expect(el.text()).toBe(prop.label);
if (desc !== 'branch') {
expect(el.attributes('href')).toBe(prop.url);
}
expect(el.attributes('href')).toBe(prop.url);
});
});

View File

@ -34,6 +34,9 @@ export const savedContentMeta = {
};
export const submitChangesError = 'Could not save changes';
export const commitBranchResponse = {
web_url: '/tree/root-master-patch-88195',
};
export const commitMultipleResponse = {
short_id: 'ed899a2f4b5',
web_url: '/commit/ed899a2f4b5',

View File

@ -13,6 +13,7 @@ import submitContentChanges from '~/static_site_editor/services/submit_content_c
import {
username,
projectId,
commitBranchResponse,
commitMultipleResponse,
createMergeRequestResponse,
sourcePath,
@ -26,7 +27,7 @@ describe('submitContentChanges', () => {
const branch = 'branch-name';
beforeEach(() => {
jest.spyOn(Api, 'createBranch').mockResolvedValue();
jest.spyOn(Api, 'createBranch').mockResolvedValue({ data: commitBranchResponse });
jest.spyOn(Api, 'commitMultiple').mockResolvedValue({ data: commitMultipleResponse });
jest
.spyOn(Api, 'createProjectMergeRequest')

View File

@ -32,7 +32,7 @@ describe TodosHelper do
{ 'id' => projects.first.id, 'text' => projects.first.full_name }
]
expect(JSON.parse(helper.todo_projects_options)).to match_array(expected_results)
expect(Gitlab::Json.parse(helper.todo_projects_options)).to match_array(expected_results)
end
end
end

View File

@ -123,7 +123,7 @@ describe 'lograge', type: :request do
let(:logger) do
Logger.new(log_output).tap { |logger| logger.formatter = ->(_, _, _, msg) { msg } }
end
let(:log_data) { JSON.parse(log_output.string) }
let(:log_data) { Gitlab::Json.parse(log_output.string) }
before do
Lograge.logger = logger

View File

@ -84,7 +84,7 @@ describe Gitlab::Database::WithLockRetries do
subject.run do
lock_attempts += 1
if lock_attempts == retry_count # we reached the last retry iteration, if we kill the thread, the last try (no lock_timeout) will succeed)
if lock_attempts == retry_count # we reached the last retry iteration, if we kill the thread, the last try (no lock_timeout) will succeed
lock_fiber.resume
end
@ -106,9 +106,13 @@ describe Gitlab::Database::WithLockRetries do
end
context 'after the retries, without setting lock_timeout' do
let(:retry_count) { timing_configuration.size }
let(:retry_count) { timing_configuration.size + 1 }
it_behaves_like 'retriable exclusive lock on `projects`'
it_behaves_like 'retriable exclusive lock on `projects`' do
before do
expect(subject).to receive(:run_block_without_lock_timeout).and_call_original
end
end
end
context 'when statement timeout is reached' do
@ -129,11 +133,22 @@ describe Gitlab::Database::WithLockRetries do
end
end
context 'restore local database variables' do
it do
expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW lock_timeout").to_a }
end
it do
expect { subject.run {} }.not_to change { ActiveRecord::Base.connection.execute("SHOW idle_in_transaction_session_timeout").to_a }
end
end
context 'casting durations correctly' do
let(:timing_configuration) { [[0.015.seconds, 0.025.seconds], [0.015.seconds, 0.025.seconds]] } # 15ms, 25ms
it 'executes `SET LOCAL lock_timeout` using the configured timeout value in milliseconds' do
expect(ActiveRecord::Base.connection).to receive(:execute).with("SAVEPOINT active_record_1").and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with('RESET idle_in_transaction_session_timeout; RESET lock_timeout').and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with("SET LOCAL lock_timeout TO '15ms'").and_call_original
expect(ActiveRecord::Base.connection).to receive(:execute).with("RELEASE SAVEPOINT active_record_1").and_call_original

View File

@ -2351,7 +2351,7 @@ describe Ci::Pipeline, :mailer do
def have_requested_pipeline_hook(status)
have_requested(:post, stubbed_hostname(hook.url)).with do |req|
json_body = JSON.parse(req.body)
json_body = Gitlab::Json.parse(req.body)
json_body['object_attributes']['status'] == status &&
json_body['builds'].length == 2
end

View File

@ -57,7 +57,7 @@ describe Clusters::Applications::Jupyter do
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('jupyter')
expect(subject.chart).to eq('jupyter/jupyterhub')
expect(subject.version).to eq('0.9.0-beta.2')
expect(subject.version).to eq('0.9.0')
expect(subject).to be_rbac
expect(subject.repository).to eq('https://jupyterhub.github.io/helm-chart/')
@ -76,7 +76,7 @@ describe Clusters::Applications::Jupyter do
let(:jupyter) { create(:clusters_applications_jupyter, :errored, version: '0.0.1') }
it 'is initialized with the locked version' do
expect(subject.version).to eq('0.9.0-beta.2')
expect(subject.version).to eq('0.9.0')
end
end
end

View File

@ -19,7 +19,7 @@ describe ContainerRepository do
.with(headers: { 'Accept' => ContainerRegistry::Client::ACCEPTED_TYPES.join(', ') })
.to_return(
status: 200,
body: JSON.dump(tags: ['test_tag']),
body: Gitlab::Json.dump(tags: ['test_tag']),
headers: { 'Content-Type' => 'application/json' })
end

View File

@ -65,7 +65,7 @@ describe IrkerService do
conn = @irker_server.accept
conn.each_line do |line|
msg = JSON.parse(line.chomp("\n"))
msg = Gitlab::Json.parse(line.chomp("\n"))
expect(msg.keys).to match_array(%w(to privmsg))
expect(msg['to']).to match_array(["irc://chat.freenode.net/#commits",
"irc://test.net/#test"])

View File

@ -529,11 +529,11 @@ describe Snippet do
let(:snippet) { build(:snippet) }
it 'excludes secret_token from generated json' do
expect(JSON.parse(to_json).keys).not_to include("secret_token")
expect(Gitlab::Json.parse(to_json).keys).not_to include("secret_token")
end
it 'does not override existing exclude option value' do
expect(JSON.parse(to_json(except: [:id])).keys).not_to include("secret_token", "id")
expect(Gitlab::Json.parse(to_json(except: [:id])).keys).not_to include("secret_token", "id")
end
def to_json(params = {})

View File

@ -132,6 +132,6 @@ describe 'get board lists' do
end
def grab_list_data(response_body)
JSON.parse(response_body)['data'][board_parent_type]['boards']['edges'][0]['node']['lists']['edges']
Gitlab::Json.parse(response_body)['data'][board_parent_type]['boards']['edges'][0]['node']['lists']['edges']
end
end

View File

@ -171,7 +171,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: DUE_DATE_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([due_issue1.iid, due_issue4.iid, due_issue2.iid])
end
@ -193,7 +193,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: DUE_DATE_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([due_issue3.iid, due_issue4.iid, due_issue2.iid])
end
@ -239,7 +239,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: RELATIVE_POSITION_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([relative_issue1.iid, relative_issue4.iid, relative_issue2.iid])
end
@ -288,7 +288,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: PRIORITY_ASC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end
@ -310,7 +310,7 @@ describe 'getting an issue list for a project' do
cursored_query = query("sort: PRIORITY_DESC, after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data']['project']['issues']['edges']
response_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
expect(grab_iids(response_data)).to eq([priority_issue2.iid, priority_issue4.iid])
end

View File

@ -24,7 +24,7 @@ shared_examples 'languages and percentages JSON response' do
get api("/projects/#{project.id}/languages", user)
expect(response).to have_gitlab_http_status(:ok)
expect(JSON.parse(response.body)).to eq(expected_languages)
expect(Gitlab::Json.parse(response.body)).to eq(expected_languages)
end
end
@ -672,7 +672,7 @@ describe API::Projects do
match[1]
end
ids += JSON.parse(response.body).map { |p| p['id'] }
ids += Gitlab::Json.parse(response.body).map { |p| p['id'] }
end
expect(ids).to contain_exactly(*projects.map(&:id))

View File

@ -217,7 +217,7 @@ describe Metrics::Dashboard::DatasourceNameParser do
include GrafanaApiHelpers
let(:grafana_url) { valid_grafana_dashboard_link('https://gitlab.grafana.net') }
let(:grafana_dashboard) { JSON.parse(fixture_file('grafana/dashboard_response.json'), symbolize_names: true) }
let(:grafana_dashboard) { Gitlab::Json.parse(fixture_file('grafana/dashboard_response.json'), symbolize_names: true) }
subject { described_class.new(grafana_url, grafana_dashboard).parse }

View File

@ -86,7 +86,7 @@ module StubGitlabCalls
def stub_container_registry_tag_manifest_content
fixture_path = 'spec/fixtures/container_registry/tag_manifest.json'
JSON.parse(File.read(Rails.root + fixture_path))
Gitlab::Json.parse(File.read(Rails.root + fixture_path))
end
def stub_container_registry_blob_content
@ -113,12 +113,12 @@ module StubGitlabCalls
def stub_project_8
data = File.read(Rails.root.join('spec/support/gitlab_stubs/project_8.json'))
allow_any_instance_of(Network).to receive(:project).and_return(JSON.parse(data))
allow_any_instance_of(Network).to receive(:project).and_return(Gitlab::Json.parse(data))
end
def stub_project_8_hooks
data = File.read(Rails.root.join('spec/support/gitlab_stubs/project_8_hooks.json'))
allow_any_instance_of(Network).to receive(:project_hooks).and_return(JSON.parse(data))
allow_any_instance_of(Network).to receive(:project_hooks).and_return(Gitlab::Json.parse(data))
end
def stub_projects
@ -143,7 +143,7 @@ module StubGitlabCalls
def project_hash_array
f = File.read(Rails.root.join('spec/support/gitlab_stubs/projects.json'))
JSON.parse f
Gitlab::Json.parse(f)
end
end

View File

@ -11,7 +11,7 @@ module WorkhorseHelpers
header = split_header.join(':')
[
type,
JSON.parse(Base64.urlsafe_decode64(header))
Gitlab::Json.parse(Base64.urlsafe_decode64(header))
]
end
end

View File

@ -44,8 +44,8 @@ module ConfigurationHelper
import_export_config = config_hash(config)
excluded_attributes = import_export_config[:excluded_attributes][relation_name.to_sym]
included_attributes = import_export_config[:included_attributes][relation_name.to_sym]
attributes = attributes - JSON.parse(excluded_attributes.to_json) if excluded_attributes
attributes = attributes & JSON.parse(included_attributes.to_json) if included_attributes
attributes = attributes - Gitlab::Json.parse(excluded_attributes.to_json) if excluded_attributes
attributes = attributes & Gitlab::Json.parse(included_attributes.to_json) if included_attributes
attributes
end

View File

@ -11,7 +11,7 @@ end
RSpec::Matchers.define :disallow_request_in_json do
match do |response|
json_response = JSON.parse(response.body)
json_response = Gitlab::Json.parse(response.body)
response.body.include?('You cannot perform write operations') && json_response.key?('message')
end
end

View File

@ -6,9 +6,9 @@ shared_context 'sentry error tracking context feature' do
let_it_be(:project) { create(:project) }
let_it_be(:project_error_tracking_settings) { create(:project_error_tracking_setting, project: project) }
let_it_be(:issue_response_body) { fixture_file('sentry/issue_sample_response.json') }
let_it_be(:issue_response) { JSON.parse(issue_response_body) }
let_it_be(:issue_response) { Gitlab::Json.parse(issue_response_body) }
let_it_be(:event_response_body) { fixture_file('sentry/issue_latest_event_sample_response.json') }
let_it_be(:event_response) { JSON.parse(event_response_body) }
let_it_be(:event_response) { Gitlab::Json.parse(event_response_body) }
let(:sentry_api_urls) { Sentry::ApiUrls.new(project_error_tracking_settings.api_url) }
let(:issue_id) { issue_response['id'] }
let(:issue_seen) { 1.year.ago.utc }

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
RSpec.shared_context 'JSON response' do
let(:json_response) { JSON.parse(response.body) }
let(:json_response) { Gitlab::Json.parse(response.body) }
end

View File

@ -82,7 +82,7 @@ RSpec.shared_examples 'sorted paginated query' do
cursored_query = pagination_query("sort: #{sort_param}, after: \"#{end_cursor}\"", page_info)
post_graphql(cursored_query, current_user: current_user)
response_data = graphql_dig_at(JSON.parse(response.body), :data, *data_path, :edges)
response_data = graphql_dig_at(Gitlab::Json.parse(response.body), :data, *data_path, :edges)
expect(pagination_results_data(response_data)).to eq expected_results.drop(first_param)
end

View File

@ -80,7 +80,7 @@ RSpec.shared_examples 'group and project boards query' do
cursored_query = query("after: \"#{end_cursor}\"")
post_graphql(cursored_query, current_user: current_user)
response_data = JSON.parse(response.body)['data'][board_parent_type]['boards']['edges']
response_data = Gitlab::Json.parse(response.body)['data'][board_parent_type]['boards']['edges']
expect(grab_names(response_data)).to eq expected_boards.drop(2).first(2).map(&:name)
end

View File

@ -23,7 +23,7 @@ RSpec.shared_examples 'valid dashboard service response for schema' do
end
RSpec.shared_examples 'valid dashboard service response' do
let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) }
let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/dashboard.json')) }
it_behaves_like 'valid dashboard service response for schema'
end
@ -38,7 +38,7 @@ RSpec.shared_examples 'caches the unprocessed dashboard for subsequent calls' do
end
RSpec.shared_examples 'valid embedded dashboard service response' do
let(:dashboard_schema) { JSON.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) }
let(:dashboard_schema) { Gitlab::Json.parse(fixture_file('lib/gitlab/metrics/dashboard/schemas/embedded_dashboard.json')) }
it_behaves_like 'valid dashboard service response for schema'
end