summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-12-06 09:06:39 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-12-06 09:06:39 +0000
commitcd15d0e6c32da7f69689c7cff2e90aeda33b8318 (patch)
tree8343899f0873ab05f3eadca72c5f6e0a653a12ac /spec
parentdd6afb4b4785ed1889defc6d7bb8ef114dd4eb50 (diff)
downloadgitlab-ce-cd15d0e6c32da7f69689c7cff2e90aeda33b8318.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/factories/error_tracking/detailed_error.rb12
-rw-r--r--spec/features/issues/user_creates_confidential_merge_request_spec.rb2
-rw-r--r--spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap30
-rw-r--r--spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb62
-rw-r--r--spec/graphql/types/error_tracking/sentry_detailed_error_type_spec.rb37
-rw-r--r--spec/graphql/types/project_type_spec.rb3
-rw-r--r--spec/javascripts/vue_shared/components/bar_chart_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/ci_badge_link_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/ci_icon_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/deprecated_modal_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js3
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js3
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js3
-rw-r--r--spec/javascripts/vue_shared/components/file_finder/index_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/file_finder/item_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/file_row_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/header_ci_component_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/icon_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/loading_button_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/markdown/toolbar_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/navigation_tabs_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/panel_resizer_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/pikaday_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/project_avatar/default_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/smart_virtual_list_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js3
-rw-r--r--spec/javascripts/vue_shared/components/toggle_button_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js2
-rw-r--r--spec/javascripts/vue_shared/translate_spec.js2
-rw-r--r--spec/models/concerns/issuable_spec.rb46
-rw-r--r--spec/presenters/sentry_detailed_error_presenter_spec.rb29
-rw-r--r--spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb69
39 files changed, 281 insertions, 83 deletions
diff --git a/spec/factories/error_tracking/detailed_error.rb b/spec/factories/error_tracking/detailed_error.rb
index cf7de2ece96..0fee329b808 100644
--- a/spec/factories/error_tracking/detailed_error.rb
+++ b/spec/factories/error_tracking/detailed_error.rb
@@ -2,13 +2,13 @@
FactoryBot.define do
factory :detailed_error_tracking_error, class: Gitlab::ErrorTracking::DetailedError do
- id { 'id' }
+ id { '1' }
title { 'title' }
type { 'error' }
user_count { 1 }
count { 2 }
- first_seen { Time.now }
- last_seen { Time.now }
+ first_seen { Time.now.iso8601 }
+ last_seen { Time.now.iso8601 }
message { 'message' }
culprit { 'culprit' }
external_url { 'http://example.com/id' }
@@ -18,7 +18,11 @@ FactoryBot.define do
project_slug { 'project_name' }
short_id { 'ID' }
status { 'unresolved' }
- frequency { [] }
+ frequency do
+ [
+ [Time.now.to_i, 10]
+ ]
+ end
first_release_last_commit { '68c914da9' }
last_release_last_commit { '9ad419c86' }
first_release_short_version { 'abc123' }
diff --git a/spec/features/issues/user_creates_confidential_merge_request_spec.rb b/spec/features/issues/user_creates_confidential_merge_request_spec.rb
index 838c0a6349c..84f358061e6 100644
--- a/spec/features/issues/user_creates_confidential_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_confidential_merge_request_spec.rb
@@ -29,7 +29,7 @@ describe 'User creates confidential merge request on issue page', :js do
click_button 'Create confidential merge request'
page.within '.create-confidential-merge-request-dropdown-menu' do
- expect(page).to have_content('No forks available to you')
+ expect(page).to have_content('No forks are available to you')
end
end
end
diff --git a/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap b/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
index 3c603c7f573..d69a9f90d65 100644
--- a/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
+++ b/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
@@ -15,19 +15,12 @@ exports[`Confidential merge request project form group component renders empty s
class="text-muted mt-1 mb-0"
>
- No forks available to you.
+ No forks are available to you.
<br />
- <span>
- To protect this issue's confidentiality,
- <a
- class="help-link"
- href="https://test.com"
- >
- fork the project
- </a>
- and set the forks visibility to private.
- </span>
+ <glsprintf-stub
+ message="To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
+ />
<gllink-stub
class="w-auto p-0 d-inline-block text-primary bg-transparent"
@@ -65,19 +58,12 @@ exports[`Confidential merge request project form group component renders fork dr
class="text-muted mt-1 mb-0"
>
- No forks available to you.
+ No forks are available to you.
<br />
- <span>
- To protect this issue's confidentiality,
- <a
- class="help-link"
- href="https://test.com"
- >
- fork the project
- </a>
- and set the forks visibility to private.
- </span>
+ <glsprintf-stub
+ message="To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
+ />
<gllink-stub
class="w-auto p-0 d-inline-block text-primary bg-transparent"
diff --git a/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
new file mode 100644
index 00000000000..5e7f18636ec
--- /dev/null
+++ b/spec/graphql/resolvers/error_tracking/sentry_detailed_error_resolver_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::ErrorTracking::SentryDetailedErrorResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+
+ let(:issue_details_service) { spy('ErrorTracking::IssueDetailsService') }
+
+ before do
+ project.add_developer(current_user)
+
+ allow(ErrorTracking::IssueDetailsService)
+ .to receive(:new)
+ .and_return issue_details_service
+ end
+
+ describe '#resolve' do
+ let(:args) { { id: issue_global_id(1234) } }
+ it 'fetches the data via the sentry API' do
+ resolve_error(args)
+
+ expect(issue_details_service).to have_received(:execute)
+ end
+
+ context 'error matched' do
+ let(:detailed_error) { build(:detailed_error_tracking_error) }
+
+ before do
+ allow(issue_details_service).to receive(:execute)
+ .and_return({ issue: detailed_error })
+ end
+
+ it 'resolves to a detailed error' do
+ expect(resolve_error(args)).to eq detailed_error
+ end
+
+ it 'assigns the gitlab project' do
+ expect(resolve_error(args).gitlab_project).to eq project
+ end
+ end
+
+ it 'resolves to nil if no match' do
+ allow(issue_details_service).to receive(:execute)
+ .and_return({ issue: nil })
+
+ result = resolve_error(args)
+ expect(result).to eq nil
+ end
+ end
+
+ def resolve_error(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+
+ def issue_global_id(issue_id)
+ Gitlab::ErrorTracking::DetailedError.new(id: issue_id).to_global_id.to_s
+ end
+end
diff --git a/spec/graphql/types/error_tracking/sentry_detailed_error_type_spec.rb b/spec/graphql/types/error_tracking/sentry_detailed_error_type_spec.rb
new file mode 100644
index 00000000000..3576adb5272
--- /dev/null
+++ b/spec/graphql/types/error_tracking/sentry_detailed_error_type_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GitlabSchema.types['SentryDetailedError'] do
+ it { expect(described_class.graphql_name).to eq('SentryDetailedError') }
+
+ it { expect(described_class).to require_graphql_authorizations(:read_sentry_issue) }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ id
+ sentryId
+ title
+ type
+ userCount
+ count
+ firstSeen
+ lastSeen
+ message
+ culprit
+ externalUrl
+ sentryProjectId
+ sentryProjectName
+ sentryProjectSlug
+ shortId
+ status
+ frequency
+ firstReleaseLastCommit
+ lastReleaseLastCommit
+ firstReleaseShortVersion
+ lastReleaseShortVersion
+ ]
+
+ is_expected.to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 19a433f090e..8a697b1bcae 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -22,8 +22,7 @@ describe GitlabSchema.types['Project'] do
only_allow_merge_if_pipeline_succeeds request_access_enabled
only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled
namespace group statistics repository merge_requests merge_request issues
- issue pipelines
- removeSourceBranchAfterMerge
+ issue pipelines removeSourceBranchAfterMerge sentryDetailedError
]
is_expected.to have_graphql_fields(*expected_fields)
diff --git a/spec/javascripts/vue_shared/components/bar_chart_spec.js b/spec/javascripts/vue_shared/components/bar_chart_spec.js
index 8f753876e44..8f673c146ec 100644
--- a/spec/javascripts/vue_shared/components/bar_chart_spec.js
+++ b/spec/javascripts/vue_shared/components/bar_chart_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import BarChart from '~/vue_shared/components/bar_chart.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import BarChart from '~/vue_shared/components/bar_chart.vue';
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
diff --git a/spec/javascripts/vue_shared/components/ci_badge_link_spec.js b/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
index 42481f8c334..367e07d3ad3 100644
--- a/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
+++ b/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import ciBadge from '~/vue_shared/components/ci_badge_link.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import ciBadge from '~/vue_shared/components/ci_badge_link.vue';
describe('CI Badge Link Component', () => {
let CIBadge;
diff --git a/spec/javascripts/vue_shared/components/ci_icon_spec.js b/spec/javascripts/vue_shared/components/ci_icon_spec.js
index b59a7d7544f..9486d7d4f23 100644
--- a/spec/javascripts/vue_shared/components/ci_icon_spec.js
+++ b/spec/javascripts/vue_shared/components/ci_icon_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import ciIcon from '~/vue_shared/components/ci_icon.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import ciIcon from '~/vue_shared/components/ci_icon.vue';
describe('CI Icon component', () => {
const Component = Vue.extend(ciIcon);
diff --git a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
index 16997e9dc67..e3f6609f128 100644
--- a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import contentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL } from 'spec/test_constants';
+import axios from '~/lib/utils/axios_utils';
+import contentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
import '~/behaviors/markdown/render_gfm';
describe('ContentViewer', () => {
diff --git a/spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js b/spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js
index 64fb984d9fc..e031583b43a 100644
--- a/spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js
+++ b/spec/javascripts/vue_shared/components/deprecated_modal_2_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import Vue from 'vue';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
const modalComponent = Vue.extend(DeprecatedModal2);
diff --git a/spec/javascripts/vue_shared/components/deprecated_modal_spec.js b/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
index be75be92158..d6c10e32794 100644
--- a/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
+++ b/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import Vue from 'vue';
-import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
const modalComponent = Vue.extend(DeprecatedModal);
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
index 1acd6b3ebe7..c743f1f6ad7 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import diffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
+import diffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
describe('DiffViewer', () => {
const requiredProps = {
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
index 0cb26d5000b..81f194395ef 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import imageDiffViewer from '~/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
+import imageDiffViewer from '~/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue';
describe('ImageDiffViewer', () => {
const requiredProps = {
diff --git a/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js b/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
index 2fc4943de30..b00fa785a0e 100644
--- a/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
+++ b/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import dropdownButtonComponent from '~/vue_shared/components/dropdown/dropdown_button.vue';
-
import { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper';
+import dropdownButtonComponent from '~/vue_shared/components/dropdown/dropdown_button.vue';
const defaultLabel = 'Select';
const customLabel = 'Select project';
diff --git a/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js b/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
index 445ab0cb40e..402de2a8788 100644
--- a/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
+++ b/spec/javascripts/vue_shared/components/dropdown/dropdown_hidden_input_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import dropdownHiddenInputComponent from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import dropdownHiddenInputComponent from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import { mockLabels } from './mock_data';
diff --git a/spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js b/spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js
index 551520721e5..456f310d10c 100644
--- a/spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js
+++ b/spec/javascripts/vue_shared/components/dropdown/dropdown_search_input_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import dropdownSearchInputComponent from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
-
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import dropdownSearchInputComponent from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
const componentConfig = {
placeholderText: 'Search something',
diff --git a/spec/javascripts/vue_shared/components/file_finder/index_spec.js b/spec/javascripts/vue_shared/components/file_finder/index_spec.js
index bae4741f652..7ded228d3ea 100644
--- a/spec/javascripts/vue_shared/components/file_finder/index_spec.js
+++ b/spec/javascripts/vue_shared/components/file_finder/index_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Mousetrap from 'mousetrap';
-import FindFileComponent from '~/vue_shared/components/file_finder/index.vue';
-import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import { file } from 'spec/ide/helpers';
import timeoutPromise from 'spec/helpers/set_timeout_promise_helper';
+import FindFileComponent from '~/vue_shared/components/file_finder/index.vue';
+import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
describe('File finder item spec', () => {
const Component = Vue.extend(FindFileComponent);
diff --git a/spec/javascripts/vue_shared/components/file_finder/item_spec.js b/spec/javascripts/vue_shared/components/file_finder/item_spec.js
index c1511643a9d..e18d0a46223 100644
--- a/spec/javascripts/vue_shared/components/file_finder/item_spec.js
+++ b/spec/javascripts/vue_shared/components/file_finder/item_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
import { file } from 'spec/ide/helpers';
+import ItemComponent from '~/vue_shared/components/file_finder/item.vue';
import createComponent from '../../../helpers/vue_mount_component_helper';
describe('File finder item spec', () => {
diff --git a/spec/javascripts/vue_shared/components/file_row_spec.js b/spec/javascripts/vue_shared/components/file_row_spec.js
index 7da69e3fa84..2d80099fafe 100644
--- a/spec/javascripts/vue_shared/components/file_row_spec.js
+++ b/spec/javascripts/vue_shared/components/file_row_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
+import { file } from 'spec/ide/helpers';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from '~/ide/components/file_row_extra.vue';
-import { file } from 'spec/ide/helpers';
import mountComponent from '../../helpers/vue_mount_component_helper';
describe('File row component', () => {
diff --git a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
index 3d251426b5a..0bb4a04557b 100644
--- a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
+++ b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import component from '~/vue_shared/components/filtered_search_dropdown.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import component from '~/vue_shared/components/filtered_search_dropdown.vue';
describe('Filtered search dropdown', () => {
const Component = Vue.extend(component);
diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
index 2b059e5e9f4..7bd5e5a64b1 100644
--- a/spec/javascripts/vue_shared/components/header_ci_component_spec.js
+++ b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import headerCi from '~/vue_shared/components/header_ci_component.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import headerCi from '~/vue_shared/components/header_ci_component.vue';
describe('Header CI Component', () => {
let HeaderCi;
diff --git a/spec/javascripts/vue_shared/components/icon_spec.js b/spec/javascripts/vue_shared/components/icon_spec.js
index ecaef414464..5a3e483fb03 100644
--- a/spec/javascripts/vue_shared/components/icon_spec.js
+++ b/spec/javascripts/vue_shared/components/icon_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
-import Icon from '~/vue_shared/components/icon.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mount } from '@vue/test-utils';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import Icon from '~/vue_shared/components/icon.vue';
describe('Sprite Icon Component', function() {
describe('Initialization', function() {
diff --git a/spec/javascripts/vue_shared/components/loading_button_spec.js b/spec/javascripts/vue_shared/components/loading_button_spec.js
index db89d4a934c..6b03c354e01 100644
--- a/spec/javascripts/vue_shared/components/loading_button_spec.js
+++ b/spec/javascripts/vue_shared/components/loading_button_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import loadingButton from '~/vue_shared/components/loading_button.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import loadingButton from '~/vue_shared/components/loading_button.vue';
const LABEL = 'Hello';
diff --git a/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js b/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
index e6c7abd9d3b..288eb40cc76 100644
--- a/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import toolbar from '~/vue_shared/components/markdown/toolbar.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import toolbar from '~/vue_shared/components/markdown/toolbar.vue';
describe('toolbar', () => {
let vm;
diff --git a/spec/javascripts/vue_shared/components/navigation_tabs_spec.js b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
index 462bfc10664..beb980a6556 100644
--- a/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
+++ b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import navigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import navigationTabs from '~/vue_shared/components/navigation_tabs.vue';
describe('navigation tabs component', () => {
let vm;
diff --git a/spec/javascripts/vue_shared/components/panel_resizer_spec.js b/spec/javascripts/vue_shared/components/panel_resizer_spec.js
index caabe3aa260..d65ee8eeb2d 100644
--- a/spec/javascripts/vue_shared/components/panel_resizer_spec.js
+++ b/spec/javascripts/vue_shared/components/panel_resizer_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import panelResizer from '~/vue_shared/components/panel_resizer.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import panelResizer from '~/vue_shared/components/panel_resizer.vue';
describe('Panel Resizer component', () => {
let vm;
diff --git a/spec/javascripts/vue_shared/components/pikaday_spec.js b/spec/javascripts/vue_shared/components/pikaday_spec.js
index 61f05e7a230..b787ba7596f 100644
--- a/spec/javascripts/vue_shared/components/pikaday_spec.js
+++ b/spec/javascripts/vue_shared/components/pikaday_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import datePicker from '~/vue_shared/components/pikaday.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import datePicker from '~/vue_shared/components/pikaday.vue';
describe('datePicker', () => {
let vm;
diff --git a/spec/javascripts/vue_shared/components/project_avatar/default_spec.js b/spec/javascripts/vue_shared/components/project_avatar/default_spec.js
index 5fed3f4b892..2ec19ebf80e 100644
--- a/spec/javascripts/vue_shared/components/project_avatar/default_spec.js
+++ b/spec/javascripts/vue_shared/components/project_avatar/default_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import ProjectAvatarDefault from '~/vue_shared/components/project_avatar/default.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { projectData } from 'spec/ide/mock_data';
-import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
import { TEST_HOST } from 'spec/test_constants';
+import { getFirstCharacterCapitalized } from '~/lib/utils/text_utility';
+import ProjectAvatarDefault from '~/vue_shared/components/project_avatar/default.vue';
describe('ProjectAvatarDefault component', () => {
const Component = Vue.extend(ProjectAvatarDefault);
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
index 47964a1702a..271ae1b645f 100644
--- a/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/javascripts/vue_shared/components/project_selector/project_list_item_spec.js
@@ -1,6 +1,6 @@
-import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { trimText } from 'spec/helpers/text_helper';
+import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
const localVue = createLocalVue();
diff --git a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
index 323a0f03017..6815da31436 100644
--- a/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/javascripts/vue_shared/components/project_selector/project_selector_spec.js
@@ -1,11 +1,11 @@
import Vue from 'vue';
import _ from 'underscore';
-import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
-import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import { trimText } from 'spec/helpers/text_helper';
+import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
+import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
const localVue = createLocalVue();
diff --git a/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js b/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
index e723fead65e..47ebdc505c9 100644
--- a/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
+++ b/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import SmartVirtualScrollList from '~/vue_shared/components/smart_virtual_list.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import SmartVirtualScrollList from '~/vue_shared/components/smart_virtual_list.vue';
describe('Toggle Button', () => {
let vm;
diff --git a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
index 073d111989c..e4db67f5b18 100644
--- a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
+++ b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
@@ -1,8 +1,7 @@
import Vue from 'vue';
-import stackedProgressBarComponent from '~/vue_shared/components/stacked_progress_bar.vue';
-
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import stackedProgressBarComponent from '~/vue_shared/components/stacked_progress_bar.vue';
const createComponent = config => {
const Component = Vue.extend(stackedProgressBarComponent);
diff --git a/spec/javascripts/vue_shared/components/toggle_button_spec.js b/spec/javascripts/vue_shared/components/toggle_button_spec.js
index 444ca451534..ea0a89a3ab5 100644
--- a/spec/javascripts/vue_shared/components/toggle_button_spec.js
+++ b/spec/javascripts/vue_shared/components/toggle_button_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import toggleButton from '~/vue_shared/components/toggle_button.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import toggleButton from '~/vue_shared/components/toggle_button.vue';
describe('Toggle Button', () => {
let vm;
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
index 9152fa8e12f..31644416439 100644
--- a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
+++ b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
-import UserAvatarSvg from '~/vue_shared/components/user_avatar/user_avatar_svg.vue';
import avatarSvg from 'icons/_icon_random.svg';
+import UserAvatarSvg from '~/vue_shared/components/user_avatar/user_avatar_svg.vue';
const UserAvatarSvgComponent = Vue.extend(UserAvatarSvg);
diff --git a/spec/javascripts/vue_shared/translate_spec.js b/spec/javascripts/vue_shared/translate_spec.js
index 0aaa4050cba..adca7cd64a1 100644
--- a/spec/javascripts/vue_shared/translate_spec.js
+++ b/spec/javascripts/vue_shared/translate_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
import Jed from 'jed';
+import { trimText } from 'spec/helpers/text_helper';
import locale from '~/locale';
import Translate from '~/vue_shared/translate';
-import { trimText } from 'spec/helpers/text_helper';
describe('Vue translate filter', () => {
let el;
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 4a6a9026f77..76a3a825978 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Issuable do
+ include ProjectForksHelper
+
let(:issuable_class) { Issue }
let(:issue) { create(:issue, title: 'An issue', description: 'A description') }
let(:user) { create(:user) }
@@ -855,6 +857,7 @@ describe Issuable do
describe 'release scopes' do
let_it_be(:project) { create(:project) }
+ let(:forked_project) { fork_project(project) }
let_it_be(:release_1) { create(:release, tag: 'v1.0', project: project) }
let_it_be(:release_2) { create(:release, tag: 'v2.0', project: project) }
@@ -875,52 +878,65 @@ describe Issuable do
let_it_be(:issue_5) { create(:issue, milestone: milestone_6, project: project) }
let_it_be(:issue_6) { create(:issue, project: project) }
- let_it_be(:items) { Issue.all }
+ let(:mr_1) { create(:merge_request, milestone: milestone_1, target_project: project, source_project: project) }
+ let(:mr_2) { create(:merge_request, milestone: milestone_3, target_project: project, source_project: forked_project) }
+ let(:mr_3) { create(:merge_request, source_project: project) }
+
+ let_it_be(:issue_items) { Issue.all }
+ let(:mr_items) { MergeRequest.all }
describe '#without_release' do
- it 'returns the issues not tied to any milestone and the ones tied to milestone with no release' do
- expect(items.without_release).to contain_exactly(issue_5, issue_6)
+ it 'returns the issues or mrs not tied to any milestone and the ones tied to milestone with no release' do
+ expect(issue_items.without_release).to contain_exactly(issue_5, issue_6)
+ expect(mr_items.without_release).to contain_exactly(mr_3)
end
end
describe '#any_release' do
- it 'returns all issues tied to a release' do
- expect(items.any_release).to contain_exactly(issue_1, issue_2, issue_3, issue_4)
+ it 'returns all issues or all mrs tied to a release' do
+ expect(issue_items.any_release).to contain_exactly(issue_1, issue_2, issue_3, issue_4)
+ expect(mr_items.any_release).to contain_exactly(mr_1, mr_2)
end
end
describe '#with_release' do
- it 'returns the issues tied a specfic release' do
- expect(items.with_release('v1.0', project.id)).to contain_exactly(issue_1, issue_2, issue_3)
+ it 'returns the issues tied to a specfic release' do
+ expect(issue_items.with_release('v1.0', project.id)).to contain_exactly(issue_1, issue_2, issue_3)
+ end
+
+ it 'returns the mrs tied to a specific release' do
+ expect(mr_items.with_release('v1.0', project.id)).to contain_exactly(mr_1)
end
context 'when a release has a milestone with one issue and another one with no issue' do
it 'returns that one issue' do
- expect(items.with_release('v2.0', project.id)).to contain_exactly(issue_3)
+ expect(issue_items.with_release('v2.0', project.id)).to contain_exactly(issue_3)
end
context 'when the milestone with no issue is added as a filter' do
it 'returns an empty list' do
- expect(items.with_release('v2.0', project.id).with_milestone('m3')).to be_empty
+ expect(issue_items.with_release('v2.0', project.id).with_milestone('m3')).to be_empty
end
end
context 'when the milestone with the issue is added as a filter' do
it 'returns this issue' do
- expect(items.with_release('v2.0', project.id).with_milestone('m2')).to contain_exactly(issue_3)
+ expect(issue_items.with_release('v2.0', project.id).with_milestone('m2')).to contain_exactly(issue_3)
end
end
end
- context 'when there is no issue under a specific release' do
- it 'returns no issue' do
- expect(items.with_release('v4.0', project.id)).to be_empty
+ context 'when there is no issue or mr under a specific release' do
+ it 'returns no issue or no mr' do
+ expect(issue_items.with_release('v4.0', project.id)).to be_empty
+ expect(mr_items.with_release('v4.0', project.id)).to be_empty
end
end
context 'when a non-existent release tag is passed in' do
- it 'returns no issue' do
- expect(items.with_release('v999.0', project.id)).to be_empty
+ it 'returns no issue or no mr' do
+ expect(issue_items.with_release('v999.0', project.id)).to be_empty
+ expect(mr_items.with_release('v999.0', project.id)).to be_empty
end
end
end
diff --git a/spec/presenters/sentry_detailed_error_presenter_spec.rb b/spec/presenters/sentry_detailed_error_presenter_spec.rb
new file mode 100644
index 00000000000..e483b6d41a1
--- /dev/null
+++ b/spec/presenters/sentry_detailed_error_presenter_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe SentryDetailedErrorPresenter do
+ let(:error) { build(:detailed_error_tracking_error) }
+ let(:presenter) { described_class.new(error) }
+
+ describe '#frequency' do
+ subject { presenter.frequency }
+
+ it 'returns an array of frequency structs' do
+ expect(subject).to include(a_kind_of(SentryDetailedErrorPresenter::FrequencyStruct))
+ end
+
+ it 'converts the times into UTC time objects' do
+ time = subject.first.time
+
+ expect(time).to be_a(Time)
+ expect(time.strftime('%z')).to eq '+0000'
+ end
+
+ it 'returns the correct counts' do
+ count = subject.first.count
+
+ expect(count).to eq error.frequency.first[1]
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
new file mode 100644
index 00000000000..d10380dab3a
--- /dev/null
+++ b/spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'getting a detailed sentry error' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project_setting) { create(:project_error_tracking_setting, project: project) }
+ let_it_be(:current_user) { project.owner }
+ let_it_be(:sentry_detailed_error) { build(:detailed_error_tracking_error) }
+ let(:sentry_gid) { sentry_detailed_error.to_global_id.to_s }
+ let(:fields) do
+ <<~QUERY
+ #{all_graphql_fields_for('SentryDetailedError'.classify)}
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('sentryDetailedError', { id: sentry_gid }, fields)
+ )
+ end
+
+ let(:error_data) { graphql_data['project']['sentryDetailedError'] }
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
+ context 'when data is loading via reactive cache' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it "is expected to return an empty error" do
+ expect(error_data).to eq nil
+ end
+ end
+
+ context 'reactive cache returns data' do
+ before do
+ expect_any_instance_of(ErrorTracking::ProjectErrorTrackingSetting)
+ .to receive(:issue_details)
+ .and_return({ issue: sentry_detailed_error })
+
+ post_graphql(query, current_user: current_user)
+ end
+
+ it "is expected to return a valid error" do
+ expect(error_data['id']).to eql sentry_gid
+ expect(error_data['sentryId']).to eql sentry_detailed_error.id.to_s
+ expect(error_data['status']).to eql sentry_detailed_error.status.upcase
+ expect(error_data['firstSeen']).to eql sentry_detailed_error.first_seen
+ expect(error_data['lastSeen']).to eql sentry_detailed_error.last_seen
+ end
+
+ it 'is expected to return the frequency correctly' do
+ expect(error_data['frequency'].count).to eql sentry_detailed_error.frequency.count
+
+ first_frequency = error_data['frequency'].first
+ expect(Time.parse(first_frequency['time'])).to eql Time.at(sentry_detailed_error.frequency[0][0], in: 0)
+ expect(first_frequency['count']).to eql sentry_detailed_error.frequency[0][1]
+ end
+ end
+end