Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-27 12:09:11 +00:00
parent 1f84ff323d
commit bbd945a9ea
43 changed files with 476 additions and 330 deletions

View File

@ -62,7 +62,7 @@ _Consider adding links to check for Sentry errors, Production logs for 5xx, 302s
- Ensure that the feature MRs have been deployed to non-production environments.
- [ ] `/chatops run auto_deploy status <merge-commit-of-your-feature>`
- [ ] Enable the feature globally on non-production environments.
- [ ] `/chatops run feature set <feature-flag-name> true --dev --staging`
- [ ] `/chatops run feature set <feature-flag-name> true --dev --staging --staging-ref`
- [ ] Verify that the feature works as expected. Posting the QA result in this issue is preferable.
The best environment to validate the feature in is [staging-canary](https://about.gitlab.com/handbook/engineering/infrastructure/environments/#staging-canary)
as this is the first environment deployed to. Note you will need to make sure you are configured to use canary as outlined [here](https://about.gitlab.com/handbook/engineering/infrastructure/environments/canary-stage/)
@ -120,7 +120,7 @@ To do so, follow these steps:
the feature can be officially announced in a release blog post.
- [ ] `/chatops run release check <merge-request-url> <milestone>`
- [ ] Consider cleaning up the feature flag from all environments by running these chatops command in `#production` channel. Otherwise these settings may override the default enabled.
- [ ] `/chatops run feature delete <feature-flag-name> --dev --staging --production`
- [ ] `/chatops run feature delete <feature-flag-name> --dev --staging --staging-ref --production`
- [ ] Close [the feature issue](ISSUE LINK) to indicate the feature will be released in the current milestone.
- [ ] Set the next milestone to this rollout issue for scheduling [the flag removal](#release-the-feature).
- [ ] (Optional) You can [create a separate issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20Flag%20Cleanup) for scheduling the steps below to [Release the feature](#release-the-feature).
@ -156,7 +156,7 @@ You can either [create a follow-up issue for Feature Flag Cleanup](https://gitla
- [ ] `/chatops run release check <merge-request-url> <milestone>`
- [ ] Close [the feature issue](ISSUE LINK) to indicate the feature will be released in the current milestone.
- [ ] If not already done, clean up the feature flag from all environments by running these chatops command in `#production` channel:
- [ ] `/chatops run feature delete <feature-flag-name> --dev --staging --production`
- [ ] `/chatops run feature delete <feature-flag-name> --dev --staging --staging-ref --production`
- [ ] Close this rollout issue.
## Rollback Steps

View File

@ -2825,7 +2825,6 @@ Layout/LineLength:
- 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
- 'ee/spec/services/ee/boards/lists/max_limits_spec.rb'
- 'ee/spec/services/ee/ci/pipeline_processing/atomic_processing_service_spec.rb'
- 'ee/spec/services/ee/commits/create_service_spec.rb'
- 'ee/spec/services/ee/git/wiki_push_service_spec.rb'
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
- 'ee/spec/services/ee/groups/deploy_tokens/create_service_spec.rb'

View File

@ -41,7 +41,7 @@ export default {
'gl-mt-5': !commitsEmpty && contextCommitsEmpty,
},
]"
:variant="commitsEmpty ? 'info' : 'default'"
:variant="commitsEmpty ? 'confirm' : 'default'"
@click="openModal"
>
{{ buttonText }}

View File

@ -206,6 +206,7 @@ export default {
);
},
updateStartLine(line) {
this.commentLineStart = line;
this.lines.start = line;
},
},
@ -216,7 +217,6 @@ export default {
<div class="content discussion-form discussion-form-container discussion-notes">
<div class="gl-mb-3 gl-text-gray-500 gl-pb-3">
<multiline-comment-form
v-model="commentLineStart"
:line="line"
:line-range="lines"
:comment-line-options="commentLineOptions"

View File

@ -7,14 +7,16 @@ import mrPageModule from './modules';
Vue.use(Vuex);
export const createModules = () => ({
page: mrPageModule(),
notes: notesModule(),
diffs: diffsModule(),
batchComments: batchCommentsModule(),
});
export const createStore = () =>
new Vuex.Store({
modules: {
page: mrPageModule(),
notes: notesModule(),
diffs: diffsModule(),
batchComments: batchCommentsModule(),
},
modules: createModules(),
});
export default createStore();

View File

@ -14,12 +14,12 @@ export default {
</script>
<template>
<div>
<div class="color-item">
<span
class="dropdown-label-box gl-flex-shrink-0 gl-top-1 gl-mr-0"
class="dropdown-label-box color-item-color"
data-testid="color-item"
:style="{ backgroundColor: color }"
></span>
<span class="hide-collapsed">{{ title }}</span>
<span class="color-item-text">{{ title }}</span>
</div>
</template>

View File

@ -1,4 +1,5 @@
<script>
import { isString } from 'lodash';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
@ -52,13 +53,23 @@ export default {
required: false,
default: s__('ColorWidget|Assign epic color'),
},
defaultColor: {
type: Object,
required: false,
validator(value) {
return isString(value?.color) && isString(value?.title);
},
default() {
return {
color: '',
title: '',
};
},
},
},
data() {
return {
issuableColor: {
color: '',
title: '',
},
issuableColor: this.defaultColor,
colorUpdateInProgress: false,
oldIid: null,
sidebarExpandedOnClick: false,

View File

@ -1,4 +1,4 @@
import { __, s__ } from '~/locale';
import { s__ } from '~/locale';
export const COLOR_WIDGET_COLOR = s__('ColorWidget|Color');
@ -7,7 +7,7 @@ export const DROPDOWN_VARIANT = {
Embedded: 'embedded',
};
export const DEFAULT_COLOR = { title: __('SuggestedColors|Blue'), color: '#1068bf' };
export const DEFAULT_COLOR = { title: s__('SuggestedColors|Blue'), color: '#1068bf' };
export const ISSUABLE_COLORS = [
DEFAULT_COLOR,

View File

@ -1,11 +1,13 @@
<script>
import { GlDropdown } from '@gitlab/ui';
import ColorItem from './color_item.vue';
import DropdownContentsColorView from './dropdown_contents_color_view.vue';
import DropdownHeader from './dropdown_header.vue';
import { isDropdownVariantSidebar } from './utils';
export default {
components: {
ColorItem,
DropdownContentsColorView,
DropdownHeader,
GlDropdown,
@ -42,12 +44,15 @@ export default {
},
computed: {
buttonText() {
if (!this.localSelectedColor?.title) {
if (!this.hasSelectedColor()) {
return this.dropdownButtonText;
}
return this.localSelectedColor.title;
},
hasSelectedColor() {
return this.localSelectedColor?.title;
},
},
watch: {
localSelectedColor: {
@ -91,7 +96,15 @@ export default {
</script>
<template>
<gl-dropdown ref="dropdown" :text="buttonText" class="gl-w-full" @hide="handleDropdownHide">
<gl-dropdown ref="dropdown" class="gl-w-full" @hide="handleDropdownHide">
<template #button-text>
<color-item
v-if="hasSelectedColor"
:color="localSelectedColor.color"
:title="localSelectedColor.title"
/>
<span v-else>{{ buttonText }}</span>
</template>
<template #header>
<dropdown-header
ref="header"

View File

@ -36,8 +36,8 @@ export default {
</script>
<template>
<gl-dropdown-form>
<div>
<gl-dropdown-form class="js-colors-list">
<div data-testid="dropdown-content">
<gl-dropdown-item
v-for="color in colors"
:key="color.color"

View File

@ -20,6 +20,11 @@ export default {
required: true,
},
},
computed: {
hasColor() {
return this.selectedColor.color !== '';
},
},
};
</script>
@ -31,13 +36,18 @@ export default {
class="sidebar-collapsed-icon"
>
<gl-icon name="appearance" />
<color-item
:color="selectedColor.color"
:title="selectedColor.title"
class="gl-font-base gl-line-height-24"
/>
<color-item :color="selectedColor.color" :title="selectedColor.title" />
</div>
<color-item class="hide-collapsed" :color="selectedColor.color" :title="selectedColor.title" />
<span v-if="!hasColor" class="no-value hide-collapsed">
<slot></slot>
</span>
<template v-else>
<color-item
class="hide-collapsed"
:color="selectedColor.color"
:title="selectedColor.title"
/>
</template>
</div>
</template>

View File

@ -1,5 +1,6 @@
@import './pages/branches';
@import './pages/clusters';
@import './pages/colors';
@import './pages/commits';
@import './pages/deploy_keys';
@import './pages/detail_page';
@ -8,6 +9,7 @@
@import './pages/events';
@import './pages/groups';
@import './pages/help';
@import './pages/hierarchy';
@import './pages/issuable';
@import './pages/issues';
@import './pages/labels';
@ -25,9 +27,8 @@
@import './pages/registry';
@import './pages/search';
@import './pages/service_desk';
@import './pages/settings';
@import './pages/settings_ci_cd';
@import './pages/settings';
@import './pages/storage_quota';
@import './pages/tree';
@import './pages/users';
@import './pages/hierarchy';

View File

@ -188,7 +188,11 @@ $dark-il: #de935f;
.diff-line-num.new,
.line-coverage.new,
.line-codequality.new,
.line_content.new {
.line_content.new,
.diff-line-num.new-nomappinginraw,
.line-coverage.new-nomappinginraw,
.line-codequality.new-nomappinginraw,
.line_content.new-nomappinginraw {
@include diff-background($dark-new-bg, $dark-new-idiff, $dark-border);
&::before,
@ -200,7 +204,11 @@ $dark-il: #de935f;
.diff-line-num.old,
.line-coverage.old,
.line-codequality.old,
.line_content.old {
.line_content.old,
.diff-line-num.old-nomappinginraw,
.line-coverage.old-nomappinginraw,
.line-codequality.old-nomappinginraw,
.line_content.old-nomappinginraw {
@include diff-background($dark-old-bg, $dark-old-idiff, $dark-border);
&::before,

View File

@ -178,7 +178,11 @@ $monokai-gh: #75715e;
.diff-line-num.new,
.line-coverage.new,
.line-codequality.new,
.line_content.new {
.line_content.new,
.diff-line-num.new-nomappinginraw,
.line-coverage.new-nomappinginraw,
.line-codequality.new-nomappinginraw,
.line_content.new-nomappinginraw {
@include diff-background($monokai-new-bg, $monokai-new-idiff, $monokai-diff-border);
&::before,
@ -190,7 +194,11 @@ $monokai-gh: #75715e;
.diff-line-num.old,
.line-coverage.old,
.line-codequality.old,
.line_content.old {
.line_content.old,
.diff-line-num.old-nomappinginraw,
.line-coverage.old-nomappinginraw,
.line-codequality.old-nomappinginraw,
.line_content.old-nomappinginraw {
@include diff-background($monokai-old-bg, $monokai-old-idiff, $monokai-diff-border);
&::before,

View File

@ -75,7 +75,9 @@
.line-coverage,
.line-codequality {
&.old,
&.new {
&.new,
&.new-nomappinginraw,
&.old-nomappinginraw {
background-color: $white-normal;
}
}
@ -131,7 +133,7 @@
}
.line_content {
&.old {
&.old, &.old-nomappinginraw {
background-color: $white-normal;
&::before {
@ -144,7 +146,7 @@
}
}
&.new {
&.new, &.new-nomappinginraw {
background-color: $white-normal;
&::before {

View File

@ -117,7 +117,7 @@ $solarized-dark-il: #2aa198;
@include hljs-override('bullet', $solarized-dark-n);
@include hljs-override('subst', $solarized-dark-p);
@include hljs-override('symbol', $solarized-dark-ni);
// Line numbers
.file-line-num {
@include line-number-link($solarized-dark-line-color);
@ -189,7 +189,11 @@ $solarized-dark-il: #2aa198;
.diff-line-num.new,
.line-coverage.new,
.line-codequality.new,
.line_content.new {
.line_content.new,
.diff-line-num.new-nomappinginraw,
.line-coverage.new-nomappinginraw,
.line-codequality.new-nomappinginraw,
.line_content.new-nomappinginraw {
@include diff-background($solarized-dark-new-bg, $solarized-dark-new-idiff, $solarized-dark-border);
&::before,
@ -201,7 +205,11 @@ $solarized-dark-il: #2aa198;
.diff-line-num.old,
.line-coverage.old,
.line-codequality.old,
.line_content.old {
.line_content.old,
.diff-line-num.old-nomappinginraw,
.line-coverage.old-nomappinginraw,
.line-codequality.old-nomappinginraw,
.line_content.old-nomappinginraw {
@include diff-background($solarized-dark-old-bg, $solarized-dark-old-idiff, $solarized-dark-border);
&::before,

View File

@ -169,7 +169,11 @@ $solarized-light-il: #2aa198;
.diff-line-num.new,
.line-coverage.new,
.line-codequality.new,
.line_content.new {
.line_content.new,
.diff-line-num.new-nomappinginraw,
.line-coverage.new-nomappinginraw,
.line-codequality.new-nomappinginraw,
.line_content.new-nomappinginraw {
@include diff-background($solarized-light-new-bg,
$solarized-light-new-idiff, $solarized-light-border);
@ -190,7 +194,11 @@ $solarized-light-il: #2aa198;
.diff-line-num.old,
.line-coverage.old,
.line-codequality.old,
.line_content.old {
.line_content.old,
.diff-line-num.old-nomappinginraw,
.line-coverage.old-nomappinginraw,
.line-codequality.old-nomappinginraw,
.line_content.old-nomappinginraw {
@include diff-background($solarized-light-old-bg, $solarized-light-old-idiff, $solarized-light-border);
&::before,

View File

@ -158,7 +158,8 @@ pre.code,
}
.diff-line-num {
&.old {
&.old,
&.old-nomappinginraw {
background-color: $line-number-old;
a {
@ -166,7 +167,8 @@ pre.code,
}
}
&.new {
&.new,
&.new-nomappinginraw {
background-color: $line-number-new;
a {
@ -204,7 +206,8 @@ pre.code,
}
.line_content {
&.old {
&.old,
&.old-nomappinginraw {
background-color: $line-removed;
&::before {
@ -216,7 +219,8 @@ pre.code,
}
}
&.new {
&.new,
&.new-nomappinginraw {
background-color: $line-added;
&::before {
@ -243,11 +247,13 @@ pre.code,
.line-coverage,
.line-codequality {
&.old {
&.old,
&.old-nomappinginraw {
background-color: $line-removed;
}
&.new {
&.new,
&.new-nomappinginraw {
background-color: $line-added;
}

View File

@ -0,0 +1,24 @@
.color-item {
@include gl-align-items-center;
@include gl-display-flex;
}
.color-item-color {
@include gl-flex-shrink-0;
@include gl-mr-3;
@include gl-top-0;
}
.right-sidebar-collapsed {
.color-item {
@include gl-pt-3;
}
.color-item-color {
margin: 0;
}
.color-item-text {
display: none;
}
}

View File

@ -1,5 +1,5 @@
= gitlab_ui_form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-performance-bar-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
= form_errors(@application_setting, pajamas_alert: true)
%fieldset
.form-group

View File

@ -5,7 +5,7 @@
%b= s_('ProjectSettings|Squash commits when merging')
%p.text-secondary
= s_('ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests.')
= link_to "What is squashing?", help_page_path('user/project/merge_requests/squash_and_merge.md'), target: '_blank', rel: 'noopener noreferrer'
= link_to s_('ProjectSettings|What is squashing?'), help_page_path('user/project/merge_requests/squash_and_merge.md'), target: '_blank', rel: 'noopener noreferrer'
= settings.gitlab_ui_radio_component :squash_option,
:never,

View File

@ -1060,6 +1060,9 @@ License.current.expires_at
# Is this a trial license?
License.current.trial?
# License ID for lookup on CustomersDot
License.current.license_id
```
### Check if a project feature is available on the instance

View File

@ -1147,6 +1147,9 @@ Payload example:
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": null,
"finished_at": null,
"duration": null,
"queued_duration": null,
"failure_reason": null,
"when": "manual",
"manual": true,
"allow_failure": false,
@ -1175,7 +1178,10 @@ Payload example:
"status": "success",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": "2016-08-12 15:26:12 UTC",
"finished_at": null,
"finished_at": "2016-08-12 15:26:29 UTC",
"duration": 17.0,
"queued_duration": 196.0,
"failure_reason": null,
"when": "on_success",
"manual": false,
"allow_failure": false,
@ -1208,10 +1214,13 @@ Payload example:
"id": 378,
"stage": "test",
"name": "test-build",
"status": "success",
"status": "failed",
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": "2016-08-12 15:26:12 UTC",
"finished_at": "2016-08-12 15:26:29 UTC",
"duration": 17.0,
"queued_duration": 196.0,
"failure_reason": "script_failure",
"when": "on_success",
"manual": false,
"allow_failure": false,
@ -1247,6 +1256,9 @@ Payload example:
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": "2016-08-12 15:24:56 UTC",
"finished_at": "2016-08-12 15:25:26 UTC",
"duration": 17.0,
"queued_duration": 196.0,
"failure_reason": null,
"when": "on_success",
"manual": false,
"allow_failure": false,
@ -1282,6 +1294,9 @@ Payload example:
"created_at": "2016-08-12 15:23:28 UTC",
"started_at": null,
"finished_at": null,
"duration": null,
"queued_duration": null,
"failure_reason": null,
"when": "on_success",
"manual": false,
"allow_failure": false,

View File

@ -118,6 +118,7 @@ module Gitlab
finished_at: build.finished_at,
duration: build.duration,
queued_duration: build.queued_duration,
failure_reason: (build.failure_reason if build.failed?),
when: build.when,
manual: build.action?,
allow_failure: build.allow_failure,

View File

@ -9035,6 +9035,9 @@ msgstr ""
msgid "Collector hostname"
msgstr ""
msgid "Color"
msgstr ""
msgid "ColorWidget|An error occurred while updating color."
msgstr ""
@ -30331,6 +30334,9 @@ msgstr ""
msgid "ProjectSettings|What are merge trains?"
msgstr ""
msgid "ProjectSettings|What is squashing?"
msgstr ""
msgid "ProjectSettings|When merge request pipelines are enabled in the CI/CD configuration file, pipelines validate the combined results of the source and target branches. %{link_start}How to configure merge request pipelines?%{link_end}"
msgstr ""
@ -34766,6 +34772,9 @@ msgstr ""
msgid "Select a branch to compare"
msgstr ""
msgid "Select a color"
msgstr ""
msgid "Select a compliance framework to apply to this project. %{linkStart}How are these added?%{linkEnd}"
msgstr ""

View File

@ -124,7 +124,7 @@
"graphql": "^15.7.2",
"graphql-tag": "^2.11.0",
"hast-util-to-string": "^2.0.0",
"highlight.js": "^11.3.1",
"highlight.js": "^11.5.1",
"immer": "^7.0.7",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
@ -136,7 +136,7 @@
"jszip-utils": "^0.0.2",
"katex": "^0.13.2",
"lodash": "^4.17.20",
"lowlight": "^2.5.0",
"lowlight": "^2.6.1",
"marked": "^0.3.12",
"mathjax": "3",
"mermaid": "^9.1.1",

View File

@ -1,7 +1,7 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import initMRPage from '~/mr_notes';
import diffFileMockData from '../diffs/mock_data/diff_file';
import { getDiffFileMock } from '../diffs/mock_data/diff_file';
import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data';
export default function initVueMRPage() {
@ -39,7 +39,7 @@ export default function initVueMRPage() {
const mock = new MockAdapter(axios);
mock.onGet(diffsAppEndpoint).reply(200, {
branch_name: 'foo',
diff_files: [diffFileMockData],
diff_files: [getDiffFileMock()],
});
initMRPage();

View File

@ -6,7 +6,7 @@ import { EVT_EXPAND_ALL_FILES } from '~/diffs/constants';
import eventHub from '~/diffs/event_hub';
import createStore from '~/diffs/store/modules';
import file from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
const propsData = {
limited: true,
@ -15,7 +15,7 @@ const propsData = {
};
async function files(store, count) {
const copies = Array(count).fill(file);
const copies = Array(count).fill(getDiffFileMock());
store.state.diffs.diffFiles.push(...copies);
await nextTick();

View File

@ -10,7 +10,7 @@ import { diffViewerModes } from '~/ide/constants';
import NoteForm from '~/notes/components/note_form.vue';
import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_preview.vue';
import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
import diffFileMockData from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
Vue.use(Vuex);
@ -28,7 +28,7 @@ describe('DiffContent', () => {
const getCommentFormForDiffFileGetterMock = jest.fn();
const defaultProps = {
diffFile: JSON.parse(JSON.stringify(diffFileMockData)),
diffFile: getDiffFileMock(),
};
const createComponent = ({ props, state, provide } = {}) => {
@ -70,7 +70,7 @@ describe('DiffContent', () => {
isInlineView: isInlineViewGetterMock,
isParallelView: isParallelViewGetterMock,
getCommentFormForDiffFile: getCommentFormForDiffFileGetterMock,
diffLines: () => () => [...diffFileMockData.parallel_diff_lines],
diffLines: () => () => [...getDiffFileMock().parallel_diff_lines],
fileLineCodequality: () => () => [],
},
actions: {

View File

@ -1,10 +1,9 @@
import { mount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
import DiffExpansionCell from '~/diffs/components/diff_expansion_cell.vue';
import { INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
import { getPreviousLineIndex } from '~/diffs/store/utils';
import { createStore } from '~/mr_notes/stores';
import diffFileMockData from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
const EXPAND_UP_CLASS = '.js-unfold';
const EXPAND_DOWN_CLASS = '.js-unfold-down';
@ -26,7 +25,7 @@ function makeLoadMoreLinesPayload({
isExpandDown = false,
}) {
return {
endpoint: diffFileMockData.context_lines_path,
endpoint: getDiffFileMock().context_lines_path,
params: {
since: sinceLine,
to: toLine,
@ -57,7 +56,7 @@ describe('DiffExpansionCell', () => {
let store;
beforeEach(() => {
mockFile = cloneDeep(diffFileMockData);
mockFile = getDiffFileMock();
mockLine = getLine(mockFile, INLINE_DIFF_VIEW_TYPE, 8);
store = createStore();
store.state.diffs.diffFiles = [mockFile];
@ -117,102 +116,102 @@ describe('DiffExpansionCell', () => {
});
describe('any row', () => {
[
{ diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: cloneDeep(diffFileMockData) },
].forEach(({ diffViewType, file, lineIndex }) => {
describe(`with diffViewType (${diffViewType})`, () => {
beforeEach(() => {
mockLine = getLine(mockFile, diffViewType, lineIndex);
store.state.diffs.diffFiles = [{ ...mockFile, ...file }];
store.state.diffs.diffViewType = diffViewType;
});
it('does not initially dispatch anything', () => {
expect(store.dispatch).not.toHaveBeenCalled();
});
it('on expand all clicked, dispatch loadMoreLines', () => {
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
const previousIndex = getPreviousLineIndex(mockFile, {
oldLineNumber,
newLineNumber,
[{ diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: getDiffFileMock() }].forEach(
({ diffViewType, file, lineIndex }) => {
describe(`with diffViewType (${diffViewType})`, () => {
beforeEach(() => {
mockLine = getLine(mockFile, diffViewType, lineIndex);
store.state.diffs.diffFiles = [{ ...mockFile, ...file }];
store.state.diffs.diffViewType = diffViewType;
});
const wrapper = createComponent({ file, lineCountBetween: 10 });
it('does not initially dispatch anything', () => {
expect(store.dispatch).not.toHaveBeenCalled();
});
findExpandAll(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith(
'diffs/loadMoreLines',
makeLoadMoreLinesPayload({
fileHash: mockFile.file_hash,
toLine: newLineNumber - 1,
sinceLine: previousIndex,
it('on expand all clicked, dispatch loadMoreLines', () => {
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
const previousIndex = getPreviousLineIndex(mockFile, {
oldLineNumber,
}),
);
});
newLineNumber,
});
it('on expand up clicked, dispatch loadMoreLines', () => {
mockLine.meta_data.old_pos = 200;
mockLine.meta_data.new_pos = 200;
const wrapper = createComponent({ file, lineCountBetween: 10 });
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
findExpandAll(wrapper).trigger('click');
const wrapper = createComponent({ file });
expect(store.dispatch).toHaveBeenCalledWith(
'diffs/loadMoreLines',
makeLoadMoreLinesPayload({
fileHash: mockFile.file_hash,
toLine: newLineNumber - 1,
sinceLine: previousIndex,
oldLineNumber,
}),
);
});
findExpandUp(wrapper).trigger('click');
it('on expand up clicked, dispatch loadMoreLines', () => {
mockLine.meta_data.old_pos = 200;
mockLine.meta_data.new_pos = 200;
expect(store.dispatch).toHaveBeenCalledWith(
'diffs/loadMoreLines',
makeLoadMoreLinesPayload({
const oldLineNumber = mockLine.meta_data.old_pos;
const newLineNumber = mockLine.meta_data.new_pos;
const wrapper = createComponent({ file });
findExpandUp(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith(
'diffs/loadMoreLines',
makeLoadMoreLinesPayload({
fileHash: mockFile.file_hash,
toLine: newLineNumber - 1,
sinceLine: 179,
oldLineNumber,
diffViewType,
unfold: true,
}),
);
});
it('on expand down clicked, dispatch loadMoreLines', () => {
mockFile[lineSources[diffViewType]][lineIndex + 1] = getDiffFileMock()[
lineSources[diffViewType]
][lineIndex];
const nextLine = getLine(mockFile, diffViewType, lineIndex + 1);
nextLine.meta_data.old_pos = 300;
nextLine.meta_data.new_pos = 300;
mockLine.meta_data.old_pos = 200;
mockLine.meta_data.new_pos = 200;
const wrapper = createComponent({ file });
findExpandDown(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('diffs/loadMoreLines', {
endpoint: mockFile.context_lines_path,
params: {
since: 1,
to: 21, // the load amount, plus 1 line
offset: 0,
unfold: true,
bottom: true,
},
lineNumbers: {
// when expanding down, these are based on the previous line, 0, in this case
oldLineNumber: 0,
newLineNumber: 0,
},
nextLineNumbers: { old_line: 200, new_line: 200 },
fileHash: mockFile.file_hash,
toLine: newLineNumber - 1,
sinceLine: 179,
oldLineNumber,
diffViewType,
unfold: true,
}),
);
});
it('on expand down clicked, dispatch loadMoreLines', () => {
mockFile[lineSources[diffViewType]][lineIndex + 1] = cloneDeep(
mockFile[lineSources[diffViewType]][lineIndex],
);
const nextLine = getLine(mockFile, diffViewType, lineIndex + 1);
nextLine.meta_data.old_pos = 300;
nextLine.meta_data.new_pos = 300;
mockLine.meta_data.old_pos = 200;
mockLine.meta_data.new_pos = 200;
const wrapper = createComponent({ file });
findExpandDown(wrapper).trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('diffs/loadMoreLines', {
endpoint: diffFileMockData.context_lines_path,
params: {
since: 1,
to: 21, // the load amount, plus 1 line
offset: 0,
unfold: true,
bottom: true,
},
lineNumbers: {
// when expanding down, these are based on the previous line, 0, in this case
oldLineNumber: 0,
newLineNumber: 0,
},
nextLineNumbers: { old_line: 200, new_line: 200 },
fileHash: mockFile.file_hash,
isExpandDown: true,
isExpandDown: true,
});
});
});
});
});
},
);
});
});

View File

@ -20,7 +20,7 @@ import axios from '~/lib/utils/axios_utils';
import { scrollToElement } from '~/lib/utils/common_utils';
import httpStatus from '~/lib/utils/http_status';
import createNotesStore from '~/notes/stores/modules';
import diffFileMockDataReadable from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
import diffFileMockDataUnreadable from '../mock_data/diff_file_unreadable';
jest.mock('~/lib/utils/common_utils');
@ -106,7 +106,7 @@ const findLoader = (wrapper) => wrapper.find('[data-testid="loader-icon"]');
const findToggleButton = (wrapper) => wrapper.find('[data-testid="expand-button"]');
const toggleFile = (wrapper) => findDiffHeader(wrapper).vm.$emit('toggleFile');
const getReadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataReadable));
const getReadableFile = () => getDiffFileMock();
const getUnreadableFile = () => JSON.parse(JSON.stringify(diffFileMockDataUnreadable));
const makeFileAutomaticallyCollapsed = (store, index = 0) =>

View File

@ -1,82 +1,166 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Vuex from 'vuex';
import Autosave from '~/autosave';
import DiffLineNoteForm from '~/diffs/components/diff_line_note_form.vue';
import { createStore } from '~/mr_notes/stores';
import { createModules } from '~/mr_notes/stores';
import NoteForm from '~/notes/components/note_form.vue';
import MultilineCommentForm from '~/notes/components/multiline_comment_form.vue';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { noteableDataMock } from 'jest/notes/mock_data';
import diffFileMockData from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal', () => {
return {
confirmAction: jest.fn(),
};
});
jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
jest.mock('~/autosave');
describe('DiffLineNoteForm', () => {
let wrapper;
let diffFile;
let diffLines;
const getDiffFileMock = () => ({ ...diffFileMockData });
let actions;
let store;
const createComponent = (args = {}) => {
diffFile = getDiffFileMock();
diffLines = diffFile.highlighted_diff_lines;
const store = createStore();
const getSelectedLine = () => {
const lineCode = diffLines[1].line_code;
return diffFile.highlighted_diff_lines.find((l) => l.line_code === lineCode);
};
const createStore = (state) => {
const modules = createModules();
modules.diffs.actions = {
...modules.diffs.actions,
saveDiffDiscussion: jest.fn(() => Promise.resolve()),
};
modules.diffs.getters = {
...modules.diffs.getters,
diffCompareDropdownTargetVersions: jest.fn(),
diffCompareDropdownSourceVersions: jest.fn(),
selectedSourceIndex: jest.fn(),
};
modules.notes.getters = {
...modules.notes.getters,
noteableType: jest.fn(),
};
actions = modules.diffs.actions;
store = new Vuex.Store({ modules });
store.state.notes.userData.id = 1;
store.state.notes.noteableData = noteableDataMock;
store.replaceState({ ...store.state, ...state });
};
const createComponent = ({ props, state } = {}) => {
wrapper?.destroy();
diffFile = getDiffFileMock();
diffLines = diffFile.highlighted_diff_lines;
createStore(state);
store.state.diffs.diffFiles = [diffFile];
store.replaceState({ ...store.state, ...args.state });
const propsData = {
diffFileHash: diffFile.file_hash,
diffLines,
line: diffLines[1],
range: { start: diffLines[0], end: diffLines[1] },
noteTargetLine: diffLines[1],
...props,
};
return shallowMount(DiffLineNoteForm, {
wrapper = shallowMount(DiffLineNoteForm, {
store,
propsData: {
...{
diffFileHash: diffFile.file_hash,
diffLines,
line: diffLines[1],
range: { start: diffLines[0], end: diffLines[1] },
noteTargetLine: diffLines[1],
},
...(args.props || {}),
},
propsData,
});
};
const findNoteForm = () => wrapper.findComponent(NoteForm);
const findCommentForm = () => wrapper.findComponent(MultilineCommentForm);
describe('methods', () => {
beforeEach(() => {
wrapper = createComponent();
beforeEach(() => {
Autosave.mockClear();
createComponent();
});
it('shows note form', () => {
expect(wrapper.find(NoteForm).exists()).toBe(true);
});
it('passes the provided range of lines to comment form', () => {
expect(findCommentForm().props('lineRange')).toMatchObject({
start: diffLines[0],
end: diffLines[1],
});
});
it('respects empty range when passing a range of lines', () => {
createComponent({ props: { range: null } });
expect(findCommentForm().props('lineRange')).toMatchObject({
start: diffLines[1],
end: diffLines[1],
});
});
it('should init autosave', () => {
expect(Autosave).toHaveBeenCalledWith({}, [
'Note',
'Issue',
98,
undefined,
'DiffNote',
undefined,
'1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
]);
});
describe('when cancelling form', () => {
afterEach(() => {
confirmAction.mockReset();
});
describe('handleCancelCommentForm', () => {
afterEach(() => {
confirmAction.mockReset();
it('should only ask for confirmation once', () => {
let finalizePromise;
confirmAction.mockImplementation(
() =>
new Promise((resolve) => {
finalizePromise = resolve;
}),
);
findNoteForm().vm.$emit('cancelForm', true, true);
findNoteForm().vm.$emit('cancelForm', true, true);
expect(confirmAction).toHaveBeenCalledTimes(1);
finalizePromise();
});
describe('with confirmation', () => {
beforeEach(() => {
confirmAction.mockResolvedValueOnce(true);
});
it('should ask form confirmation and hide form for a line', async () => {
findNoteForm().vm.$emit('cancelForm', true, true);
await nextTick();
expect(confirmAction).toHaveBeenCalled();
await nextTick();
expect(getSelectedLine().hasForm).toBe(false);
expect(Autosave.mock.instances[0].reset).toHaveBeenCalled();
});
});
describe('without confirmation', () => {
beforeEach(() => {
confirmAction.mockResolvedValueOnce(false);
});
it('should ask for confirmation when shouldConfirm and isDirty passed as truthy', () => {
confirmAction.mockResolvedValueOnce(false);
findNoteForm().vm.$emit('cancelForm', true, true);
expect(confirmAction).toHaveBeenCalled();
});
it('should only ask for confirmation once', () => {
// Never resolve so we can test what happens when triggered while "confirmAction" is loading
confirmAction.mockImplementation(() => new Promise(() => {}));
findNoteForm().vm.$emit('cancelForm', true, true);
findNoteForm().vm.$emit('cancelForm', true, true);
expect(confirmAction).toHaveBeenCalledTimes(1);
});
it('should not ask for confirmation when one of the params false', () => {
confirmAction.mockResolvedValueOnce(false);
findNoteForm().vm.$emit('cancelForm', true, false);
expect(confirmAction).not.toHaveBeenCalled();
@ -85,116 +169,39 @@ describe('DiffLineNoteForm', () => {
expect(confirmAction).not.toHaveBeenCalled();
});
it('should call cancelCommentForm with lineCode', async () => {
confirmAction.mockResolvedValueOnce(true);
jest.spyOn(wrapper.vm, 'cancelCommentForm').mockImplementation(() => {});
jest.spyOn(wrapper.vm, 'resetAutoSave').mockImplementation(() => {});
findNoteForm().vm.$emit('cancelForm', true, true);
await nextTick();
expect(confirmAction).toHaveBeenCalled();
await nextTick();
expect(wrapper.vm.cancelCommentForm).toHaveBeenCalledWith({
lineCode: diffLines[1].line_code,
fileHash: wrapper.vm.diffFileHash,
});
expect(wrapper.vm.resetAutoSave).toHaveBeenCalled();
});
});
describe('saveNoteForm', () => {
it('should call saveNote action with proper params', async () => {
const saveDiffDiscussionSpy = jest
.spyOn(wrapper.vm, 'saveDiffDiscussion')
.mockReturnValue(Promise.resolve());
const lineRange = {
start: {
line_code: wrapper.vm.commentLineStart.line_code,
type: wrapper.vm.commentLineStart.type,
new_line: 2,
old_line: null,
},
end: {
line_code: wrapper.vm.line.line_code,
type: wrapper.vm.line.type,
new_line: 2,
old_line: null,
},
};
const formData = {
...wrapper.vm.formData,
lineRange,
};
await wrapper.vm.handleSaveNote('note body');
expect(saveDiffDiscussionSpy).toHaveBeenCalledWith({
note: 'note body',
formData,
});
});
});
});
describe('created', () => {
it('should use the provided `range` of lines', () => {
wrapper = createComponent();
expect(wrapper.vm.lines.start).toBe(diffLines[0]);
expect(wrapper.vm.lines.end).toBe(diffLines[1]);
});
it("should fill the internal `lines` data with the provided `line` if there's no provided `range", () => {
wrapper = createComponent({ props: { range: null } });
expect(wrapper.vm.lines.start).toBe(diffLines[1]);
expect(wrapper.vm.lines.end).toBe(diffLines[1]);
});
});
describe('mounted', () => {
it('should init autosave', () => {
const key = 'autosave/Note/Issue/98//DiffNote//1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2';
wrapper = createComponent();
expect(wrapper.vm.autosave).toBeDefined();
expect(wrapper.vm.autosave.key).toEqual(key);
});
it('should set selectedCommentPosition', () => {
wrapper = createComponent();
let startLineCode = wrapper.vm.commentLineStart.line_code;
let lineCode = wrapper.vm.line.line_code;
expect(startLineCode).toEqual(lineCode);
wrapper.destroy();
const state = {
notes: {
selectedCommentPosition: {
start: {
line_code: 'test',
},
},
describe('saving note', () => {
it('should save original line', async () => {
const lineRange = {
start: {
line_code: diffLines[1].line_code,
type: diffLines[1].type,
new_line: 2,
old_line: null,
},
end: {
line_code: diffLines[1].line_code,
type: diffLines[1].type,
new_line: 2,
old_line: null,
},
};
wrapper = createComponent({ state });
startLineCode = wrapper.vm.commentLineStart.line_code;
lineCode = state.notes.selectedCommentPosition.start.line_code;
expect(startLineCode).toEqual(lineCode);
await findNoteForm().vm.$emit('handleFormUpdate', 'note body');
expect(actions.saveDiffDiscussion.mock.calls[0][1].formData).toMatchObject({
lineRange,
});
});
});
describe('template', () => {
it('should have note form', () => {
wrapper = createComponent();
expect(wrapper.find(NoteForm).exists()).toBe(true);
it('should save selected line from the store', async () => {
const lineCode = 'test';
store.state.notes.selectedCommentPosition = { start: { line_code: lineCode } };
createComponent({ state: store.state });
await findNoteForm().vm.$emit('handleFormUpdate', 'note body');
expect(actions.saveDiffDiscussion.mock.calls[0][1].formData.lineRange.start.line_code).toBe(
lineCode,
);
});
});
});

View File

@ -6,7 +6,7 @@ import DiffRow from '~/diffs/components/diff_row.vue';
import { mapParallel } from '~/diffs/components/diff_row_utils';
import diffsModule from '~/diffs/store/modules';
import { findInteropAttributes } from '../find_interop_attributes';
import diffFileMockData from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
const showCommentForm = jest.fn();
const enterdragging = jest.fn();
@ -210,6 +210,7 @@ describe('DiffRow', () => {
});
describe('sets coverage title and class', () => {
const diffFileMockData = getDiffFileMock();
const thisLine = diffFileMockData.parallel_diff_lines[2];
const rightLine = diffFileMockData.parallel_diff_lines[2].right;

View File

@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import DiffStats from '~/diffs/components/diff_stats.vue';
import mockDiffFile from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
const TEST_ADDED_LINES = 100;
const TEST_REMOVED_LINES = 200;
@ -48,6 +48,7 @@ describe('diff_stats', () => {
const getBytesContainer = () => wrapper.find('.diff-stats > div:first-child');
beforeEach(() => {
const mockDiffFile = getDiffFileMock();
file = {
...mockDiffFile,
viewer: {

View File

@ -1,4 +1,4 @@
export default {
export const getDiffFileMock = () => ({
submodule: false,
submodule_link: null,
blob: {
@ -305,4 +305,4 @@ export default {
],
discussions: [],
renderingLines: false,
};
});

View File

@ -3,7 +3,7 @@ import Cookies from '~/lib/utils/cookies';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { getDiffFileMock } from 'jest/diffs/mock_data/diff_file';
import {
DIFF_VIEW_COOKIE_NAME,
INLINE_DIFF_VIEW_TYPE,
@ -754,7 +754,7 @@ describe('DiffsStoreActions', () => {
it('dispatches actions', () => {
const commitId = 'something';
const formData = {
diffFile: { ...mockDiffFile },
diffFile: getDiffFileMock(),
noteableData: {},
};
const note = {};

View File

@ -3,7 +3,7 @@ import createState from '~/diffs/store/modules/diff_state';
import * as types from '~/diffs/store/mutation_types';
import mutations from '~/diffs/store/mutations';
import * as utils from '~/diffs/store/utils';
import diffFileMockData from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
describe('DiffsStoreMutations', () => {
describe('SET_BASE_CONFIG', () => {
@ -71,6 +71,7 @@ describe('DiffsStoreMutations', () => {
describe('SET_DIFF_METADATA', () => {
it('should overwrite state with the camelCased data that is passed in', () => {
const diffFileMockData = getDiffFileMock();
const state = {
diffFiles: [],
};
@ -94,7 +95,7 @@ describe('DiffsStoreMutations', () => {
it('should set diff data batch type properly', () => {
const state = { diffFiles: [] };
const diffMock = {
diff_files: [diffFileMockData],
diff_files: [getDiffFileMock()],
};
mutations[types.SET_DIFF_DATA_BATCH](state, diffMock);

View File

@ -1,4 +1,3 @@
import { clone } from 'lodash';
import {
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
@ -14,10 +13,9 @@ import {
import * as utils from '~/diffs/store/utils';
import { MERGE_REQUEST_NOTEABLE_TYPE } from '~/notes/constants';
import { noteableDataMock } from 'jest/notes/mock_data';
import diffFileMockData from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
import { diffMetadata } from '../mock_data/diff_metadata';
const getDiffFileMock = () => JSON.parse(JSON.stringify(diffFileMockData));
const getDiffMetadataMock = () => JSON.parse(JSON.stringify(diffMetadata));
describe('DiffsStoreUtils', () => {
@ -47,7 +45,7 @@ describe('DiffsStoreUtils', () => {
let diffFile;
beforeEach(() => {
diffFile = { ...clone(diffFileMockData) };
diffFile = getDiffFileMock();
});
it('should return the correct previous line number', () => {

View File

@ -6,7 +6,7 @@ import {
match,
} from '~/diffs/utils/diff_file';
import { diffViewerModes } from '~/ide/constants';
import mockDiffFile from '../mock_data/diff_file';
import { getDiffFileMock } from '../mock_data/diff_file';
function getDiffFiles() {
const loadFull = 'namespace/project/-/merge_requests/12345/diff_for_path?file_identifier=abc';
@ -210,7 +210,7 @@ describe('diff_file utilities', () => {
];
const validFile = [
'computes the correct stats from a file',
mockDiffFile,
getDiffFileMock(),
{
changed: 1024,
percent: 100,
@ -223,7 +223,7 @@ describe('diff_file utilities', () => {
const negativeChange = [
'computed the correct states from a file with a negative size change',
{
...mockDiffFile,
...getDiffFileMock(),
new_size: 0,
old_size: 1024,
},

View File

@ -2,7 +2,7 @@ import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import discussionWithTwoUnresolvedNotes from 'test_fixtures/merge_requests/resolved_diff_discussion.json';
import { trimText } from 'helpers/text_helper';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { getDiffFileMock } from 'jest/diffs/mock_data/diff_file';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
@ -45,7 +45,7 @@ describe('noteable_discussion component', () => {
it('should render thread header', async () => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_file = getDiffFileMock();
discussion.diff_discussion = true;
discussion.expanded = false;
@ -57,7 +57,7 @@ describe('noteable_discussion component', () => {
it('should hide actions when diff refs do not exists', async () => {
const discussion = { ...discussionMock };
discussion.diff_file = { ...mockDiffFile, diff_refs: null };
discussion.diff_file = { ...getDiffFileMock(), diff_refs: null };
discussion.diff_discussion = true;
discussion.expanded = false;

View File

@ -33,7 +33,7 @@ describe('DropdownValue', () => {
it.each`
index | cssClass
${0} | ${['gl-font-base', 'gl-line-height-24']}
${0} | ${[]}
${1} | ${['hide-collapsed']}
`(
'passes correct props to the ColorItem with CSS class `$cssClass`',

View File

@ -36,6 +36,7 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
expect(build_data).to be_a(Hash)
expect(build_data[:id]).to eq(build.id)
expect(build_data[:status]).to eq(build.status)
expect(build_data[:failure_reason]).to be_nil
expect(build_data[:allow_failure]).to eq(build.allow_failure)
expect(build_data[:environment]).to be_nil
expect(runner_data).to eq(nil)
@ -197,4 +198,14 @@ RSpec.describe Gitlab::DataBuilder::Pipeline do
end
end
end
describe '.build failed' do
let(:build) { create(:ci_build, :failed, pipeline: pipeline, failure_reason: :script_failure) }
let(:data) { described_class.build(pipeline) }
let(:build_data) { data[:builds].last }
it 'has failure_reason' do
expect(build_data[:failure_reason]).to eq(build.failure_reason)
end
end
end

View File

@ -6673,10 +6673,10 @@ he@^1.1.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
highlight.js@^11.3.1, highlight.js@~11.4.0:
version "11.4.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.4.0.tgz#34ceadd49e1596ee5aba3d99346cdfd4845ee05a"
integrity sha512-nawlpCBCSASs7EdvZOYOYVkJpGmAOKMYZgZtUqSRqodZE0GRVcFKwo1RcpeOemqh9hyttTdd5wDBwHkuSyUfnA==
highlight.js@^11.5.1, highlight.js@~11.5.0:
version "11.5.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.5.1.tgz#027c24e4509e2f4dcd00b4a6dda542ce0a1f7aea"
integrity sha512-LKzHqnxr4CrD2YsNoIf/o5nJ09j4yi/GcH5BnYz9UnVpZdS4ucMgvP61TDty5xJcFGRjnH4DpujkS9bHT3hq0Q==
highlight.js@~10.7.0:
version "10.7.2"
@ -8405,14 +8405,14 @@ lowlight@^1.20.0:
fault "^1.0.0"
highlight.js "~10.7.0"
lowlight@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-2.5.0.tgz#723a39fc0d9b911731a395b320519cbb0790ab14"
integrity sha512-OXGUch9JZu4q5r4Ir6QlUp5pBXMxS7NHaclhRiUlxNRcOSK0gtXZcVrsGP4eM7bv0/KDHg/TXQagx/X35EULsA==
lowlight@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-2.6.1.tgz#d3cbc7ae0530c848e512b8e6528609587520b44f"
integrity sha512-t0ueDL6SIn9FKHipm78CNjWcJQv0xi6WCjYAICyO6GyPzoT7E58yom1mNwvI7AMwVe3pLwwFT0Bt2gml7uaUeQ==
dependencies:
"@types/hast" "^2.0.0"
fault "^2.0.0"
highlight.js "~11.4.0"
highlight.js "~11.5.0"
lru-cache@^4.1.2, lru-cache@^4.1.5:
version "4.1.5"