Commit 167894d0 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 411cc779
...@@ -299,17 +299,17 @@ export default { ...@@ -299,17 +299,17 @@ export default {
stacked="sm" stacked="sm"
tbody-tr-class="table-row mb-4" tbody-tr-class="table-row mb-4"
> >
<template v-slot:head(error)> <template #head(error)>
<div class="d-none d-sm-block">{{ __('Open errors') }}</div> <div class="d-none d-sm-block">{{ __('Open errors') }}</div>
</template> </template>
<template v-slot:head(events)="data"> <template #head(events)="data">
<div class="text-sm-right">{{ data.label }}</div> <div class="text-sm-right">{{ data.label }}</div>
</template> </template>
<template v-slot:head(users)="data"> <template #head(users)="data">
<div class="text-sm-right">{{ data.label }}</div> <div class="text-sm-right">{{ data.label }}</div>
</template> </template>
<template v-slot:error="errors"> <template #cell(error)="errors">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<gl-link class="d-flex mw-100 text-dark" :href="getDetailsLink(errors.item.id)"> <gl-link class="d-flex mw-100 text-dark" :href="getDetailsLink(errors.item.id)">
<strong class="text-truncate">{{ errors.item.title.trim() }}</strong> <strong class="text-truncate">{{ errors.item.title.trim() }}</strong>
...@@ -319,20 +319,20 @@ export default { ...@@ -319,20 +319,20 @@ export default {
</span> </span>
</div> </div>
</template> </template>
<template v-slot:events="errors"> <template #cell(events)="errors">
<div class="text-right">{{ errors.item.count }}</div> <div class="text-right">{{ errors.item.count }}</div>
</template> </template>
<template v-slot:users="errors"> <template #cell(users)="errors">
<div class="text-right">{{ errors.item.userCount }}</div> <div class="text-right">{{ errors.item.userCount }}</div>
</template> </template>
<template v-slot:lastSeen="errors"> <template #cell(lastSeen)="errors">
<div class="text-md-left text-right"> <div class="text-md-left text-right">
<time-ago :time="errors.item.lastSeen" class="text-secondary" /> <time-ago :time="errors.item.lastSeen" class="text-secondary" />
</div> </div>
</template> </template>
<template v-slot:ignore="errors"> <template #cell(ignore)="errors">
<gl-button <gl-button
ref="ignoreError" ref="ignoreError"
v-gl-tooltip.hover v-gl-tooltip.hover
...@@ -342,7 +342,7 @@ export default { ...@@ -342,7 +342,7 @@ export default {
<gl-icon name="eye-slash" :size="12" /> <gl-icon name="eye-slash" :size="12" />
</gl-button> </gl-button>
</template> </template>
<template v-slot:resolved="errors"> <template #cell(resolved)="errors">
<gl-button <gl-button
ref="resolveError" ref="resolveError"
v-gl-tooltip v-gl-tooltip
...@@ -352,7 +352,7 @@ export default { ...@@ -352,7 +352,7 @@ export default {
<gl-icon name="check-circle" :size="12" /> <gl-icon name="check-circle" :size="12" />
</gl-button> </gl-button>
</template> </template>
<template v-slot:details="errors"> <template #cell(details)="errors">
<gl-button <gl-button
:href="getDetailsLink(errors.item.id)" :href="getDetailsLink(errors.item.id)"
variant="outline-info" variant="outline-info"
...@@ -361,7 +361,7 @@ export default { ...@@ -361,7 +361,7 @@ export default {
{{ __('More details') }} {{ __('More details') }}
</gl-button> </gl-button>
</template> </template>
<template v-slot:empty> <template #empty>
{{ __('No errors to display.') }} {{ __('No errors to display.') }}
<gl-link class="js-try-again" @click="restartPolling"> <gl-link class="js-try-again" @click="restartPolling">
{{ __('Check again') }} {{ __('Check again') }}
......
...@@ -128,8 +128,8 @@ export default { ...@@ -128,8 +128,8 @@ export default {
@click="handleSuggestDismissed" @click="handleSuggestDismissed"
/> />
<gl-popover <gl-popover
v-if="showSuggestPopover" v-if="showSuggestPopover && $refs.suggestButton"
:target="() => $refs.suggestButton" :target="$refs.suggestButton"
:css-classes="['diff-suggest-popover']" :css-classes="['diff-suggest-popover']"
placement="bottom" placement="bottom"
:show="showSuggestPopover" :show="showSuggestPopover"
......
...@@ -26,7 +26,7 @@ module API ...@@ -26,7 +26,7 @@ module API
end end
get ":id/#{noteables_path}/:noteable_id/discussions" do get ":id/#{noteables_path}/:noteable_id/discussions" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable) notes = readable_discussion_notes(noteable)
discussions = Kaminari.paginate_array(Discussion.build_collection(notes, noteable)) discussions = Kaminari.paginate_array(Discussion.build_collection(notes, noteable))
...@@ -42,7 +42,7 @@ module API ...@@ -42,7 +42,7 @@ module API
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable' requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end end
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
if notes.empty? if notes.empty?
...@@ -77,7 +77,7 @@ module API ...@@ -77,7 +77,7 @@ module API
end end
end end
post ":id/#{noteables_path}/:noteable_id/discussions" do post ":id/#{noteables_path}/:noteable_id/discussions" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
type = params[:position] ? 'DiffNote' : 'DiscussionNote' type = params[:position] ? 'DiffNote' : 'DiscussionNote'
id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id id_key = noteable.is_a?(Commit) ? :commit_id : :noteable_id
...@@ -107,7 +107,7 @@ module API ...@@ -107,7 +107,7 @@ module API
requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable' requires :noteable_id, types: [Integer, String], desc: 'The ID of the noteable'
end end
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
if notes.empty? if notes.empty?
...@@ -127,7 +127,7 @@ module API ...@@ -127,7 +127,7 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note' optional :created_at, type: String, desc: 'The creation date of the note'
end end
post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do post ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
notes = readable_discussion_notes(noteable, params[:discussion_id]) notes = readable_discussion_notes(noteable, params[:discussion_id])
first_note = notes.first first_note = notes.first
...@@ -161,7 +161,7 @@ module API ...@@ -161,7 +161,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note' requires :note_id, type: Integer, desc: 'The ID of a note'
end end
get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do get ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id]) get_note(noteable, params[:note_id])
end end
...@@ -178,7 +178,7 @@ module API ...@@ -178,7 +178,7 @@ module API
exactly_one_of :body, :resolved exactly_one_of :body, :resolved
end end
put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
if params[:resolved].nil? if params[:resolved].nil?
update_note(noteable, params[:note_id]) update_note(noteable, params[:note_id])
...@@ -196,7 +196,7 @@ module API ...@@ -196,7 +196,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note' requires :note_id, type: Integer, desc: 'The ID of a note'
end end
delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do delete ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id]) delete_note(noteable, params[:note_id])
end end
...@@ -211,7 +211,7 @@ module API ...@@ -211,7 +211,7 @@ module API
requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved' requires :resolved, type: Boolean, desc: 'Mark discussion resolved/unresolved'
end end
put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do put ":id/#{noteables_path}/:noteable_id/discussions/:discussion_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
resolve_discussion(noteable, params[:discussion_id], params[:resolved]) resolve_discussion(noteable, params[:discussion_id], params[:resolved])
end end
......
...@@ -83,15 +83,15 @@ module API ...@@ -83,15 +83,15 @@ module API
end end
end end
def find_noteable(parent_type, parent_id, noteable_type, noteable_id) def find_noteable(noteable_type, noteable_id)
params = finder_params_by_noteable_type_and_id(noteable_type, noteable_id, parent_id) params = finder_params_by_noteable_type_and_id(noteable_type, noteable_id)
noteable = NotesFinder.new(current_user, params).target noteable = NotesFinder.new(current_user, params).target
noteable = nil unless can?(current_user, noteable_read_ability_name(noteable), noteable) noteable = nil unless can?(current_user, noteable_read_ability_name(noteable), noteable)
noteable || not_found!(noteable_type) noteable || not_found!(noteable_type)
end end
def finder_params_by_noteable_type_and_id(type, id, parent_id) def finder_params_by_noteable_type_and_id(type, id)
target_type = type.name.underscore target_type = type.name.underscore
{ target_type: target_type }.tap do |h| { target_type: target_type }.tap do |h|
if %w(issue merge_request).include?(target_type) if %w(issue merge_request).include?(target_type)
...@@ -100,11 +100,11 @@ module API ...@@ -100,11 +100,11 @@ module API
h[:target_id] = id h[:target_id] = id
end end
add_parent_to_finder_params(h, type, parent_id) add_parent_to_finder_params(h, type)
end end
end end
def add_parent_to_finder_params(finder_params, noteable_type, parent_id) def add_parent_to_finder_params(finder_params, noteable_type)
finder_params[:project] = user_project finder_params[:project] = user_project
end end
......
...@@ -30,7 +30,7 @@ module API ...@@ -30,7 +30,7 @@ module API
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
get ":id/#{noteables_str}/:noteable_id/notes" do get ":id/#{noteables_str}/:noteable_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
# We exclude notes that are cross-references and that cannot be viewed # We exclude notes that are cross-references and that cannot be viewed
# by the current user. By doing this exclusion at this level and not # by the current user. By doing this exclusion at this level and not
...@@ -58,7 +58,7 @@ module API ...@@ -58,7 +58,7 @@ module API
requires :noteable_id, type: Integer, desc: 'The ID of the noteable' requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end end
get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
get_note(noteable, params[:note_id]) get_note(noteable, params[:note_id])
end end
...@@ -71,7 +71,7 @@ module API ...@@ -71,7 +71,7 @@ module API
optional :created_at, type: String, desc: 'The creation date of the note' optional :created_at, type: String, desc: 'The creation date of the note'
end end
post ":id/#{noteables_str}/:noteable_id/notes" do post ":id/#{noteables_str}/:noteable_id/notes" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
opts = { opts = {
note: params[:body], note: params[:body],
...@@ -98,7 +98,7 @@ module API ...@@ -98,7 +98,7 @@ module API
requires :body, type: String, desc: 'The content of a note' requires :body, type: String, desc: 'The content of a note'
end end
put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do put ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
update_note(noteable, params[:note_id]) update_note(noteable, params[:note_id])
end end
...@@ -111,7 +111,7 @@ module API ...@@ -111,7 +111,7 @@ module API
requires :note_id, type: Integer, desc: 'The ID of a note' requires :note_id, type: Integer, desc: 'The ID of a note'
end end
delete ":id/#{noteables_str}/:noteable_id/notes/:note_id" do delete ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
noteable = find_noteable(parent_type, params[:id], noteable_type, params[:noteable_id]) noteable = find_noteable(noteable_type, params[:noteable_id])
delete_note(noteable, params[:note_id]) delete_note(noteable, params[:note_id])
end end
......
...@@ -25,7 +25,7 @@ module API ...@@ -25,7 +25,7 @@ module API
end end
get ":id/#{eventables_str}/:eventable_id/resource_label_events" do get ":id/#{eventables_str}/:eventable_id/resource_label_events" do
eventable = find_noteable(parent_type, params[:id], eventable_type, params[:eventable_id]) eventable = find_noteable(eventable_type, params[:eventable_id])
opts = { page: params[:page], per_page: params[:per_page] } opts = { page: params[:page], per_page: params[:per_page] }
events = ResourceLabelEventFinder.new(current_user, eventable, opts).execute events = ResourceLabelEventFinder.new(current_user, eventable, opts).execute
...@@ -42,7 +42,8 @@ module API ...@@ -42,7 +42,8 @@ module API
requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable' requires :eventable_id, types: [Integer, String], desc: 'The ID of the eventable'
end end
get ":id/#{eventables_str}/:eventable_id/resource_label_events/:event_id" do get ":id/#{eventables_str}/:eventable_id/resource_label_events/:event_id" do
eventable = find_noteable(parent_type, params[:id], eventable_type, params[:eventable_id]) eventable = find_noteable(eventable_type, params[:eventable_id])
event = eventable.resource_label_events.find(params[:event_id]) event = eventable.resource_label_events.find(params[:event_id])
not_found!('ResourceLabelEvent') unless can?(current_user, :read_resource_label_event, event) not_found!('ResourceLabelEvent') unless can?(current_user, :read_resource_label_event, event)
......
...@@ -12,6 +12,12 @@ module QA ...@@ -12,6 +12,12 @@ module QA
yield yield
# Workaround for a bug preventing sign out from secondary nodes
# See https://gitlab.com/gitlab-org/gitlab/issues/198289
if address == :geo_secondary
Runtime::Browser.visit(:geo_primary, Page::Dashboard::Projects)
end
Page::Main::Menu.perform(&:sign_out) Page::Main::Menu.perform(&:sign_out)
end end
......
...@@ -26,13 +26,13 @@ module QA ...@@ -26,13 +26,13 @@ module QA
wait_for_requests wait_for_requests
end end
def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: false) def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: true)
Support::Waiter.wait_until(max_duration: max_duration, sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do Support::Waiter.wait_until(max_duration: max_duration, sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do
yield || (reload && refresh && false) yield || (reload && refresh && false)
end end
end end
def retry_until(max_attempts: 3, reload: false, sleep_interval: 0, raise_on_failure: false) def retry_until(max_attempts: 3, reload: false, sleep_interval: 0, raise_on_failure: true)
Support::Retrier.retry_until(max_attempts: max_attempts, reload_page: (reload && self), sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do Support::Retrier.retry_until(max_attempts: max_attempts, reload_page: (reload && self), sleep_interval: sleep_interval, raise_on_failure: raise_on_failure) do
yield yield
end end
......
...@@ -16,13 +16,6 @@ module QA ...@@ -16,13 +16,6 @@ module QA
super super
end end
def wait_until(max_duration: 60, sleep_interval: 0.1, reload: true, raise_on_failure: false)
log("next wait uses reload: #{reload}")
# Logging of wait start/end/duration is handled by QA::Support::Waiter
super
end
def scroll_to(selector, text: nil) def scroll_to(selector, text: nil)
msg = "scrolling to :#{selector}" msg = "scrolling to :#{selector}"
msg += " with text: #{text}" if text msg += " with text: #{text}" if text
......
...@@ -34,7 +34,7 @@ module QA ...@@ -34,7 +34,7 @@ module QA
result result
end end
def retry_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: false, retry_on_exception: false) def retry_until(max_attempts: nil, max_duration: nil, reload_page: nil, sleep_interval: 0, raise_on_failure: true, retry_on_exception: false)
# For backwards-compatibility # For backwards-compatibility
max_attempts = 3 if max_attempts.nil? && max_duration.nil? max_attempts = 3 if max_attempts.nil? && max_duration.nil?
......
...@@ -7,7 +7,7 @@ module QA ...@@ -7,7 +7,7 @@ module QA
module_function module_function
def wait_until(max_duration: singleton_class::DEFAULT_MAX_WAIT_TIME, reload_page: nil, sleep_interval: 0.1, raise_on_failure: false, retry_on_exception: false) def wait_until(max_duration: singleton_class::DEFAULT_MAX_WAIT_TIME, reload_page: nil, sleep_interval: 0.1, raise_on_failure: true, retry_on_exception: false)
QA::Runtime::Logger.debug( QA::Runtime::Logger.debug(
<<~MSG.tr("\n", ' ') <<~MSG.tr("\n", ' ')
with wait_until: max_duration: #{max_duration}; with wait_until: max_duration: #{max_duration};
......
...@@ -27,24 +27,6 @@ describe QA::Support::Page::Logging do ...@@ -27,24 +27,6 @@ describe QA::Support::Page::Logging do
.to output(%r{refreshing http://current-url}).to_stdout_from_any_process .to output(%r{refreshing http://current-url}).to_stdout_from_any_process
end end
it 'logs wait' do
expect { subject.wait_until(max_duration: 0) {} }
.to output(/next wait uses reload: true/).to_stdout_from_any_process
expect { subject.wait_until(max_duration: 0) {} }
.to output(/with wait_until/).to_stdout_from_any_process
expect { subject.wait_until(max_duration: 0) {} }
.to output(/ended wait_until$/).to_stdout_from_any_process
end
it 'logs wait with reload false' do
expect { subject.wait_until(max_duration: 0, reload: false) {} }
.to output(/next wait uses reload: false/).to_stdout_from_any_process
expect { subject.wait_until(max_duration: 0, reload: false) {} }
.to output(/with wait_until/).to_stdout_from_any_process
expect { subject.wait_until(max_duration: 0, reload: false) {} }
.to output(/ended wait_until$/).to_stdout_from_any_process
end
it 'logs scroll_to' do it 'logs scroll_to' do
expect { subject.scroll_to(:element) } expect { subject.scroll_to(:element) }
.to output(/scrolling to :element/).to_stdout_from_any_process .to output(/scrolling to :element/).to_stdout_from_any_process
......
...@@ -14,12 +14,12 @@ describe QA::Support::Retrier do ...@@ -14,12 +14,12 @@ describe QA::Support::Retrier do
context 'when the condition is true' do context 'when the condition is true' do
it 'logs max attempts (3 by default)' do it 'logs max attempts (3 by default)' do
expect { subject.retry_until { true } } expect { subject.retry_until { true } }
.to output(/with retry_until: max_attempts: 3; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process .to output(/with retry_until: max_attempts: 3; reload_page: ; sleep_interval: 0; raise_on_failure: true; retry_on_exception: false/).to_stdout_from_any_process
end end
it 'logs max duration' do it 'logs max duration' do
expect { subject.retry_until(max_duration: 1) { true } } expect { subject.retry_until(max_duration: 1) { true } }
.to output(/with retry_until: max_duration: 1; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process .to output(/with retry_until: max_duration: 1; reload_page: ; sleep_interval: 0; raise_on_failure: true; retry_on_exception: false/).to_stdout_from_any_process
end end
it 'logs the end' do it 'logs the end' do
...@@ -30,12 +30,12 @@ describe QA::Support::Retrier do ...@@ -30,12 +30,12 @@ describe QA::Support::Retrier do
context 'when the condition is false' do context 'when the condition is false' do
it 'logs the start' do it 'logs the start' do
expect { subject.retry_until(max_duration: 0) { false } } expect { subject.retry_until(max_duration: 0, raise_on_failure: false) { false } }
.to output(/with retry_until: max_duration: 0; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process .to output(/with retry_until: max_duration: 0; reload_page: ; sleep_interval: 0; raise_on_failure: false; retry_on_exception: false/).to_stdout_from_any_process
end end
it 'logs the end' do it 'logs the end' do
expect { subject.retry_until(max_duration: 0) { false } } expect { subject.retry_until(max_duration: 0, raise_on_failure: false) { false } }
.to output(/ended retry_until$/).to_stdout_from_any_process .to output(/ended retry_until$/).to_stdout_from_any_process
end end
end end
...@@ -54,8 +54,8 @@ describe QA::Support::Retrier do ...@@ -54,8 +54,8 @@ describe QA::Support::Retrier do
subject.retry_until subject.retry_until
end end
it 'sets raise_on_failure to false by default' do it 'sets raise_on_failure to true by default' do
expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: false)) expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: true))
subject.retry_until subject.retry_until
end end
......
...@@ -46,8 +46,8 @@ describe QA::Support::Waiter do ...@@ -46,8 +46,8 @@ describe QA::Support::Waiter do
subject.wait_until subject.wait_until
end end
it 'sets raise_on_failure to false by default' do it 'sets raise_on_failure to true by default' do
expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: false)) expect(subject).to receive(:repeat_until).with(hash_including(raise_on_failure: true))
subject.wait_until subject.wait_until
end end
......
...@@ -11,7 +11,7 @@ describe 'Resolving all open threads in a merge request from an issue', :js do ...@@ -11,7 +11,7 @@ describe 'Resolving all open threads in a merge request from an issue', :js do
def resolve_all_discussions_link_selector def resolve_all_discussions_link_selector
text = "Resolve all threads in new issue" text = "Resolve all threads in new issue"
url = new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid) url = new_project_issue_path(project, merge_request_to_resolve_discussions_of: merge_request.iid)
%Q{a[data-original-title="#{text}"][href="#{url}"]} %Q{a[title="#{text}"][href="#{url}"]}
end end
describe 'as a user with access to the project' do describe 'as a user with access to the project' do
......
...@@ -11,7 +11,7 @@ describe 'Resolve an open thread in a merge request by creating an issue', :js d ...@@ -11,7 +11,7 @@ describe 'Resolve an open thread in a merge request by creating an issue', :js d
def resolve_discussion_selector def resolve_discussion_selector
title = 'Resolve this thread in a new issue' title = 'Resolve this thread in a new issue'
url = new_project_issue_path(project, discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid) url = new_project_issue_path(project, discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid)
"a[data-original-title=\"#{title}\"][href=\"#{url}\"]" "a[title=\"#{title}\"][href=\"#{url}\"]"
end end
describe 'As a user with access to the project' do describe 'As a user with access to the project' do
......
...@@ -16,7 +16,7 @@ describe 'Merge request > User edits assignees sidebar', :js do ...@@ -16,7 +16,7 @@ describe 'Merge request > User edits assignees sidebar', :js do
# DOM finders to simplify and improve readability # DOM finders to simplify and improve readability
let(:sidebar_assignee_block) { page.find('.js-issuable-sidebar .assignee') } let(:sidebar_assignee_block) { page.find('.js-issuable-sidebar .assignee') }
let(:sidebar_assignee_avatar_link) { sidebar_assignee_block.find_all('a').find { |a| a['href'].include? assignee.username } } let(:sidebar_assignee_avatar_link) { sidebar_assignee_block.find_all('a').find { |a| a['href'].include? assignee.username } }
let(:sidebar_assignee_tooltip) { sidebar_assignee_avatar_link['data-original-title'] || '' } let(:sidebar_assignee_tooltip) { sidebar_assignee_avatar_link['title'] || '' }
let(:sidebar_assignee_dropdown_item) { sidebar_assignee_block.find(".dropdown-menu li[data-user-id=\"#{assignee.id}\"]") } let(:sidebar_assignee_dropdown_item) { sidebar_assignee_block.find(".dropdown-menu li[data-user-id=\"#{assignee.id}\"]") }
let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item.find('a')['data-title'] || '' } let(:sidebar_assignee_dropdown_tooltip) { sidebar_assignee_dropdown_item.find('a')['data-title'] || '' }
......
...@@ -29,7 +29,7 @@ describe 'Merge request > User sees deployment widget', :js do ...@@ -29,7 +29,7 @@ describe 'Merge request > User sees deployment widget', :js do
wait_for_requests wait_for_requests
expect(page).to have_content("Deployed to #{environment.name}") expect(page).to have_content("Deployed to #{environment.name}")
expect(find('.js-deploy-time')['data-original-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium)) expect(find('.js-deploy-time')['title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
end end
context 'when a user created a new merge request with the same SHA' do context 'when a user created a new merge request with the same SHA' do
......
...@@ -112,7 +112,7 @@ describe 'User comments on a diff', :js do ...@@ -112,7 +112,7 @@ describe 'User comments on a diff', :js do
changes = sample_compare(expanded_changes).changes.last(expanded_changes.size) changes = sample_compare(expanded_changes).changes.last(expanded_changes.size)
page.within("[id='#{hash}']") do page.within("[id='#{hash}']") do
find("button[data-original-title='Show full file']").click find("button[title='Show full file']").click
wait_for_requests wait_for_requests
click_diff_line(find("[id='#{changes.first[:line_code]}']")) click_diff_line(find("[id='#{changes.first[:line_code]}']"))
......
...@@ -13,7 +13,7 @@ describe 'Environments page', :js do ...@@ -13,7 +13,7 @@ describe 'Environments page', :js do
end end
def stop_button_selector def stop_button_selector
%q{button[data-original-title="Stop environment"]} %q{button[title="Stop environment"]}
end end
describe 'page tabs' do describe 'page tabs' do
......
...@@ -217,7 +217,7 @@ describe 'Pipeline', :js do ...@@ -217,7 +217,7 @@ describe 'Pipeline', :js do
it 'includes the failure reason' do it 'includes the failure reason' do
page.within('#ci-badge-test') do page.within('#ci-badge-test') do
build_link = page.find('.js-pipeline-graph-job-link') build_link = page.find('.js-pipeline-graph-job-link')
expect(build_link['data-original-title']).to eq('test - failed - (unknown failure)') expect(build_link['title']).to eq('test - failed - (unknown failure)')
end end
end end
end end
......
...@@ -270,7 +270,7 @@ describe 'Pipelines', :js do ...@@ -270,7 +270,7 @@ describe 'Pipelines', :js do
it 'contains badge with tooltip which contains error' do it 'contains badge with tooltip which contains error' do
expect(pipeline).to have_yaml_errors expect(pipeline).to have_yaml_errors
expect(page).to have_selector( expect(page).to have_selector(
%Q{span[data-original-title="#{pipeline.yaml_errors}"]}) %Q{span[title="#{pipeline.yaml_errors}"]})
end end
it 'contains badge that indicates failure reason' do it 'contains badge that indicates failure reason' do
...@@ -280,7 +280,7 @@ describe 'Pipelines', :js do ...@@ -280,7 +280,7 @@ describe 'Pipelines', :js do
it 'contains badge with tooltip which contains failure reason' do it 'contains badge with tooltip which contains failure reason' do
expect(pipeline.failure_reason?).to eq true expect(pipeline.failure_reason?).to eq true
expect(page).to have_selector( expect(page).to have_selector(
%Q{span[data-original-title="#{pipeline.present.failure_reason}"]}) %Q{span[title="#{pipeline.present.failure_reason}"]})
end end
end end
...@@ -569,7 +569,7 @@ describe 'Pipelines', :js do ...@@ -569,7 +569,7 @@ describe 'Pipelines', :js do
within('.js-builds-dropdown-list') do within('.js-builds-dropdown-list') do
build_element = page.find('.mini-pipeline-graph-dropdown-item') build_element = page.find('.mini-pipeline-graph-dropdown-item')
expect(build_element['data-original-title']).to eq('build - failed - (unknown failure)') expect(build_element['title']).to eq('build - failed - (unknown failure)')
end end
end end
end end
......
...@@ -65,7 +65,7 @@ describe 'View on environment', :js do ...@@ -65,7 +65,7 @@ describe 'View on environment', :js do
within '.diffs' do within '.diffs' do
text = 'View on feature.review.example.com' text = 'View on feature.review.example.com'
url = 'http://feature.review.example.com/ruby/feature' url = 'http://feature.review.example.com/ruby/feature'
expect(page).to have_selector("a[data-original-title='#{text}'][href='#{url}']") expect(page).to have_selector("a[title='#{text}'][href='#{url}']")
end end
end end
end end
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
exports[`Remove cluster confirmation modal renders splitbutton with modal included 1`] = ` exports[`Remove cluster confirmation modal renders splitbutton with modal included 1`] = `
<div> <div>
<div <div
class="dropdown btn-group b-dropdown gl-dropdown" class="dropdown b-dropdown gl-dropdown btn-group"
> >
<button <button
class="btn btn-danger" class="btn btn-danger"
...@@ -31,7 +31,9 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ ...@@ -31,7 +31,9 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
role="menu" role="menu"
tabindex="-1" tabindex="-1"
> >
<li> <li
role="presentation"
>
<button <button
class="dropdown-item is-active" class="dropdown-item is-active"
role="menuitem" role="menuitem"
...@@ -47,14 +49,18 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ ...@@ -47,14 +49,18 @@ exports[`Remove cluster confirmation modal renders splitbutton with modal includ
</button> </button>
</li> </li>
<li> <li
role="presentation"
>
<hr <hr
aria-orientation="horizontal" aria-orientation="horizontal"
class="dropdown-divider" class="dropdown-divider"
role="separator" role="separator"
/> />
</li> </li>
<li> <li
role="presentation"
>
<button <button
class="dropdown-item" class="dropdown-item"
role="menuitem" role="menuitem"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::TcpChecker do describe Gitlab::TcpChecker, :permit_dns do
before do before do
@server = TCPServer.new('localhost', 0) @server = TCPServer.new('localhost', 0)
_, @port, _, @ip = @server.addr _, @port, _, @ip = @server.addr
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
describe Gitlab::UrlBlocker do describe Gitlab::UrlBlocker, :stub_invalid_dns_only do
include StubRequests include StubRequests
describe '#validate!' do describe '#validate!' do
......
# frozen_string_literal: true
require Rails.root.join("spec/support/helpers/dns_helpers")
RSpec.configure do |config|
config.include DnsHelpers
config.before do
block_dns!
end
config.before(:each, :permit_dns) do
permit_dns!
end
config.before(:each, :stub_invalid_dns_only) do
permit_dns!
stub_invalid_dns!
end
end
# frozen_string_literal: true
module DnsHelpers
def block_dns!
stub_all_dns!
stub_invalid_dns!
permit_local_dns!
end
def permit_dns!
allow(Addrinfo).to receive(:getaddrinfo).and_call_original
end
def stub_all_dns!
allow(Addrinfo).to receive(:getaddrinfo).with(anything, anything, nil, :STREAM).and_return([])
allow(Addrinfo).to receive(:getaddrinfo).with(anything, anything, nil, :STREAM, anything, anything).and_return([])
end
def stub_invalid_dns!
allow(Addrinfo).to receive(:getaddrinfo).with(/foobar\.\w|(\d{1,3}\.){4,}\d{1,3}/i, anything, nil, :STREAM) do
raise SocketError.new("getaddrinfo: Name or service not known")
end
end
def permit_local_dns!
local_addresses = /(127|10)\.0\.0\.\d{1,3}|(192\.168|172\.16)\.\d{1,3}\.\d{1,3}|0\.0\.0\.0|localhost/i
allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM).and_call_original
allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM, anything, anything).and_call_original
end
end
...@@ -8,7 +8,7 @@ shared_examples 'error tracking index page' do ...@@ -8,7 +8,7 @@ shared_examples 'error tracking index page' do
end end
within('div.error-list') do within('div.error-list') do
expect(page).to have_content('Error') expect(page).to have_content('Open errors')
expect(page).to have_content('Events') expect(page).to have_content('Events')
expect(page).to have_content('Users') expect(page).to have_content('Users')
expect(page).to have_content('Last Seen') expect(page).to have_content('Last Seen')
......
...@@ -20,6 +20,14 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name| ...@@ -20,6 +20,14 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
expect(response_dates).to eq(response_dates.sort.reverse) expect(response_dates).to eq(response_dates.sort.reverse)
end end
it 'fetches notes using parent path as id paremeter' do
parent_id = CGI.escape(parent.full_path)
get api("/#{parent_type}/#{parent_id}/#{noteable_type}/#{noteable[id_name]}/notes", user)
expect(response.status).to eq(200)
end
context '2 notes with equal created_at' do context '2 notes with equal created_at' do
before do before do
@first_note = Note.first @first_note = Note.first
......
...@@ -737,14 +737,14 @@ ...@@ -737,14 +737,14 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.90.0.tgz#e6fe0ca3d353fcdbd792c10d82444383c33f539d" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.90.0.tgz#e6fe0ca3d353fcdbd792c10d82444383c33f539d"
integrity sha512-6UikaIMGosmrDAd6Lf3QIJWDM4FwhoGIN+CJuFcWeHDMbZT69LnTabuGfvOQmp2+nlI68baRTSDufaux7m9Ajw== integrity sha512-6UikaIMGosmrDAd6Lf3QIJWDM4FwhoGIN+CJuFcWeHDMbZT69LnTabuGfvOQmp2+nlI68baRTSDufaux7m9Ajw==
"@gitlab/ui@^8.21.0": "@gitlab/ui@^9.0.0":
version "8.21.0" version "9.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-8.21.0.tgz#30869847251d525c8402487cea16886b43f134e9" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.0.0.tgz#16d637f47ba0537100fd1c6d452b56174b50171b"
integrity sha512-CLtpvF11aNOt+ttdE4xZTGM3sg124U/nYPrmGkre5FLcLqmSoK1LmRkflLHMUAwHWXz7CvxmSDZa2YshC3SsyQ== integrity sha512-OfP8UAticpqKkqbPBZ+7bbCBsd9Fxq3eL55Uq5nEwxJ8gGXm+nSc+HFnbzX/ryv0iz5+7nCI4DfIfgy9E4QAeQ==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.0.0-rc.27" bootstrap-vue "2.1.0"
copy-to-clipboard "^3.0.8" copy-to-clipboard "^3.0.8"
echarts "^4.2.1" echarts "^4.2.1"
highlight.js "^9.13.1" highlight.js "^9.13.1"
...@@ -925,14 +925,14 @@ ...@@ -925,14 +925,14 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@nuxt/opencollective@^0.2.2": "@nuxt/opencollective@^0.3.0":
version "0.2.2" version "0.3.0"
resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.2.2.tgz#17adc7d380457379cd14cbb64a435ea196cc4a6e" resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
integrity sha512-ie50SpS47L+0gLsW4yP23zI/PtjsDRglyozX2G09jeiUazC1AJlGPZo0JUs9iuCDUoIgsDEf66y7/bSfig0BpA== integrity sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==
dependencies: dependencies:
chalk "^2.4.1" chalk "^2.4.2"
consola "^2.3.0" consola "^2.10.1"
node-fetch "^2.3.0" node-fetch "^2.6.0"
"@sentry/browser@^5.10.2": "@sentry/browser@^5.10.2":
version "5.10.2" version "5.10.2"
...@@ -2061,18 +2061,18 @@ bonjour@^3.5.0: ...@@ -2061,18 +2061,18 @@ bonjour@^3.5.0:
multicast-dns "^6.0.1" multicast-dns "^6.0.1"
multicast-dns-service-types "^1.1.0" multicast-dns-service-types "^1.1.0"
bootstrap-vue@2.0.0-rc.27: bootstrap-vue@2.1.0:
version "2.0.0-rc.27" version "2.1.0"
resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.0.0-rc.27.tgz#884a46a71948d13c9729134cb564467f79a7b2b9" resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.1.0.tgz#41c0cd265a6cea14ffe29eeea71543ec396d1789"
integrity sha512-gXdpt2IsKbmC3SU0bf/RgldWwgrXK7G47yslOtkk4OA1z6fOzb2orM2vU5L8NCNZQomYax9LapRucv+8PByfdA== integrity sha512-dftb5fc42x7QLv814nN+3Cx8MMuCB+xrGQjOmSXH81ET0+yo7KYb4lUN3/pOnf+8Tkv8oaawZ1OOth5/AZfktg==
dependencies: dependencies:
"@nuxt/opencollective" "^0.2.2" "@nuxt/opencollective" "^0.3.0"
bootstrap "^4.3.1" bootstrap ">=4.3.1 <5.0.0"
popper.js "^1.15.0" popper.js "^1.16.0"
portal-vue "^2.1.5" portal-vue "^2.1.6"
vue-functional-data-merge "^3.1.0" vue-functional-data-merge "^3.1.0"
bootstrap@4.3.1, bootstrap@^4.3.1: bootstrap@4.3.1, "bootstrap@>=4.3.1 <5.0.0":
version "4.3.1" version "4.3.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac"
integrity sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag== integrity sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==
...@@ -2893,10 +2893,10 @@ connect@^3.6.0: ...@@ -2893,10 +2893,10 @@ connect@^3.6.0:
parseurl "~1.3.2" parseurl "~1.3.2"
utils-merge "1.0.1" utils-merge "1.0.1"
consola@^2.3.0: consola@^2.10.1:
version "2.11.3" version "2.10.1"
resolved "https://registry.yarnpkg.com/consola/-/consola-2.11.3.tgz#f7315836224c143ac5094b47fd4c816c2cd1560e" resolved "https://registry.yarnpkg.com/consola/-/consola-2.10.1.tgz#4693edba714677c878d520e4c7e4f69306b4b927"
integrity sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw== integrity sha512-4sxpH6SGFYLADfUip4vuY65f/gEogrzJoniVhNUYkJHtng0l8ZjnDCqxxrSVRHOHwKxsy8Vm5ONZh1wOR3/l/w==
console-browserify@^1.1.0: console-browserify@^1.1.0:
version "1.1.0" version "1.1.0"
...@@ -7964,7 +7964,7 @@ node-ensure@^0.0.0: ...@@ -7964,7 +7964,7 @@ node-ensure@^0.0.0:
resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7" resolved "https://registry.yarnpkg.com/node-ensure/-/node-ensure-0.0.0.tgz#ecae764150de99861ec5c810fd5d096b183932a7"
integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc= integrity sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=
node-fetch@^2.3.0: node-fetch@^2.6.0:
version "2.6.0" version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
...@@ -8800,15 +8800,15 @@ pofile@^1: ...@@ -8800,15 +8800,15 @@ pofile@^1:
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954" resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
integrity sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg== integrity sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg==
popper.js@^1.14.7, popper.js@^1.15.0: popper.js@^1.14.7, popper.js@^1.16.0:
version "1.16.0" version "1.16.0"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3"
integrity sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw== integrity sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==
portal-vue@^2.1.5, portal-vue@^2.1.6: portal-vue@^2.1.6:
version "2.1.7" version "2.1.6"
resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.7.tgz#ea08069b25b640ca08a5b86f67c612f15f4e4ad4" resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.6.tgz#a7d4790b14a79af7fd159a60ec88c30cddc6c639"
integrity sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g== integrity sha512-lvCF85D4e8whd0nN32D8FqKwwkk7nYUI3Ku8UAEx4Z1reomu75dv5evRUTZNaj1EalxxWNXiNl0EHRq36fG8WA==
portfinder@^1.0.24: portfinder@^1.0.24:
version "1.0.24" version "1.0.24"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment