Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a27d3c27d8
commit
97576e3dfd
|
|
@ -25,7 +25,7 @@ review-build-cng:
|
|||
extends:
|
||||
- .default-retry
|
||||
- .review:rules:review-build-cng
|
||||
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
|
||||
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7
|
||||
stage: review-prepare
|
||||
before_script:
|
||||
- source ./scripts/utils.sh
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ no_ee_check:
|
|||
verify-tests-yml:
|
||||
extends:
|
||||
- .setup:rules:verify-tests-yml
|
||||
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7-alpine
|
||||
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7
|
||||
stage: test
|
||||
needs: []
|
||||
script:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<script>
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import { NodeViewWrapper } from '@tiptap/vue-2';
|
||||
|
||||
export default {
|
||||
name: 'ImageWrapper',
|
||||
components: {
|
||||
NodeViewWrapper,
|
||||
GlLoadingIcon,
|
||||
},
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<node-view-wrapper class="gl-display-inline-block">
|
||||
<span class="gl-relative">
|
||||
<img
|
||||
data-testid="image"
|
||||
class="gl-max-w-full gl-h-auto"
|
||||
:class="{ 'gl-opacity-5': node.attrs.uploading }"
|
||||
:src="node.attrs.src"
|
||||
/>
|
||||
<gl-loading-icon v-if="node.attrs.uploading" class="gl-absolute gl-left-50p gl-top-half" />
|
||||
</span>
|
||||
</node-view-wrapper>
|
||||
</template>
|
||||
|
|
@ -4,7 +4,7 @@ import Vue from 'vue';
|
|||
import createFlash from '~/flash';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
|
||||
import { confidentialityQueries } from '~/sidebar/constants';
|
||||
import { confidentialityQueries, Tracking } from '~/sidebar/constants';
|
||||
import SidebarConfidentialityContent from './sidebar_confidentiality_content.vue';
|
||||
import SidebarConfidentialityForm from './sidebar_confidentiality_form.vue';
|
||||
|
||||
|
|
@ -18,8 +18,8 @@ const hideDropdownEvent = new CustomEvent('hiddenGlDropdown', {
|
|||
|
||||
export default {
|
||||
tracking: {
|
||||
event: 'click_edit_button',
|
||||
label: 'right_sidebar',
|
||||
event: Tracking.editEvent,
|
||||
label: Tracking.rightSidebarLabel,
|
||||
property: 'confidentiality',
|
||||
},
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,13 @@ import { IssuableType } from '~/issue_show/constants';
|
|||
import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
|
||||
import { dateFields, dateTypes, dueDateQueries, startDateQueries } from '~/sidebar/constants';
|
||||
import {
|
||||
dateFields,
|
||||
dateTypes,
|
||||
dueDateQueries,
|
||||
startDateQueries,
|
||||
Tracking,
|
||||
} from '~/sidebar/constants';
|
||||
import SidebarFormattedDate from './sidebar_formatted_date.vue';
|
||||
import SidebarInheritDate from './sidebar_inherit_date.vue';
|
||||
|
||||
|
|
@ -15,8 +21,8 @@ const hideDropdownEvent = new CustomEvent('hiddenGlDropdown', {
|
|||
|
||||
export default {
|
||||
tracking: {
|
||||
event: 'click_edit_button',
|
||||
label: 'right_sidebar',
|
||||
event: Tracking.editEvent,
|
||||
label: Tracking.rightSidebarLabel,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@ import { IssuableType } from '~/issue_show/constants';
|
|||
import { __, s__, sprintf } from '~/locale';
|
||||
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
|
||||
import {
|
||||
Tracking,
|
||||
IssuableAttributeState,
|
||||
IssuableAttributeType,
|
||||
issuableAttributesQueries,
|
||||
noAttributeId,
|
||||
defaultEpicSort,
|
||||
} from '../constants';
|
||||
} from '~/sidebar/constants';
|
||||
|
||||
export default {
|
||||
noAttributeId,
|
||||
|
|
@ -148,8 +149,8 @@ export default {
|
|||
currentAttribute: null,
|
||||
attributesList: [],
|
||||
tracking: {
|
||||
label: 'right_sidebar',
|
||||
event: 'click_edit_button',
|
||||
event: Tracking.editEvent,
|
||||
label: Tracking.rightSidebarLabel,
|
||||
property: this.issuableAttribute,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@ import { IssuableType } from '~/issue_show/constants';
|
|||
import { isLoggedIn } from '~/lib/utils/common_utils';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
|
||||
import { subscribedQueries } from '~/sidebar/constants';
|
||||
import { subscribedQueries, Tracking } from '~/sidebar/constants';
|
||||
|
||||
const ICON_ON = 'notifications';
|
||||
const ICON_OFF = 'notifications-off';
|
||||
|
||||
export default {
|
||||
tracking: {
|
||||
event: 'click_edit_button',
|
||||
label: 'right_sidebar',
|
||||
event: Tracking.editEvent,
|
||||
label: Tracking.rightSidebarLabel,
|
||||
property: 'subscriptions',
|
||||
},
|
||||
directives: {
|
||||
|
|
|
|||
|
|
@ -130,6 +130,11 @@ export const subscribedQueries = {
|
|||
},
|
||||
};
|
||||
|
||||
export const Tracking = {
|
||||
editEvent: 'click_edit_button',
|
||||
rightSidebarLabel: 'right_sidebar',
|
||||
};
|
||||
|
||||
export const timeTrackingQueries = {
|
||||
[IssuableType.Issue]: {
|
||||
query: issueTimeTrackingQuery,
|
||||
|
|
|
|||
|
|
@ -153,7 +153,8 @@ class ContainerRepository < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.create_from_path!(path)
|
||||
build_from_path(path).tap(&:save!)
|
||||
safe_find_or_create_by!(project: path.repository_project,
|
||||
name: path.repository_name)
|
||||
end
|
||||
|
||||
def self.build_root_repository(project)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ Crawling continues by taking more snapshots and finding subsequent actions.
|
|||
|
||||
The benefit of crawling by following user actions in a browser is that the crawler can interact with the target application much like a real user would, identifying complex flows that traditional web crawlers don’t understand. This results in better coverage of the website.
|
||||
|
||||
Scanning a web application with both the browser-based crawler and GitLab DAST should provide greater coverage, compared with only GitLab DAST. The new crawler does not support API scanning or the DAST AJAX crawler.
|
||||
Using the browser-based crawler should provide greater coverage for most web applications, compared with the current DAST AJAX crawler. The new crawler replaces the AJAX crawler and is specifically designed to maximize crawl coverage in modern web applications. While both crawlers are currently used in conjunction with the existing DAST scanner, the combination of the browser-based crawler with the current DAST scanner is much more effective at finding and testing every page in an application.
|
||||
|
||||
## Enable browser-based crawler
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import { NodeViewWrapper } from '@tiptap/vue-2';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import ImageWrapper from '~/content_editor/components/wrappers/image.vue';
|
||||
|
||||
describe('content/components/wrappers/image', () => {
|
||||
let wrapper;
|
||||
|
||||
const createWrapper = async (nodeAttrs = {}) => {
|
||||
wrapper = shallowMountExtended(ImageWrapper, {
|
||||
propsData: {
|
||||
node: {
|
||||
attrs: nodeAttrs,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
const findImage = () => wrapper.findByTestId('image');
|
||||
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('renders a node-view-wrapper with display-inline-block class', () => {
|
||||
createWrapper();
|
||||
|
||||
expect(wrapper.findComponent(NodeViewWrapper).classes()).toContain('gl-display-inline-block');
|
||||
});
|
||||
|
||||
it('renders an image that displays the node src', () => {
|
||||
const src = 'foobar.png';
|
||||
|
||||
createWrapper({ src });
|
||||
|
||||
expect(findImage().attributes().src).toBe(src);
|
||||
});
|
||||
|
||||
describe('when uploading', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ uploading: true });
|
||||
});
|
||||
|
||||
it('renders a gl-loading-icon component', () => {
|
||||
expect(findLoadingIcon().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('adds gl-opacity-5 class selector to image', () => {
|
||||
expect(findImage().classes()).toContain('gl-opacity-5');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when not uploading', () => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ uploading: false });
|
||||
});
|
||||
|
||||
it('does not render a gl-loading-icon component', () => {
|
||||
expect(findLoadingIcon().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('does not add gl-opacity-5 class selector to image', () => {
|
||||
expect(findImage().classes()).not.toContain('gl-opacity-5');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -281,6 +281,16 @@ RSpec.describe ContainerRepository do
|
|||
expect(repository.name).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when repository already exists' do
|
||||
let(:path) { project.full_path + '/some/image' }
|
||||
|
||||
it 'returns the existing repository' do
|
||||
container_repository = create(:container_repository, project: project, name: 'some/image')
|
||||
|
||||
expect(repository.id).to eq(container_repository.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.build_root_repository' do
|
||||
|
|
|
|||
Loading…
Reference in New Issue