diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index f97c8ae1f748ff1ef1b367a23629364b5e0cd875..8703796b1163e11e3b94e324cbd74f8b414405ab 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -1,4 +1,5 @@
diff --git a/app/assets/javascripts/snippets/queries/snippet.blob.query.graphql b/app/assets/javascripts/snippets/queries/snippet.blob.query.graphql
new file mode 100644
index 0000000000000000000000000000000000000000..785c88c185a1f7560647f15530ecaef05c8b1b5a
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/snippet.blob.query.graphql
@@ -0,0 +1,24 @@
+#import '~/graphql_shared/fragments/blobviewer.fragment.graphql'
+
+query SnippetBlobFull($ids: [ID!]) {
+ snippets(ids: $ids) {
+ edges {
+ node {
+ id
+ blob {
+ binary
+ name
+ path
+ rawPath
+ size
+ simpleViewer {
+ ...BlobViewer
+ }
+ richViewer {
+ ...BlobViewer
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/controllers/projects/registry/tags_controller.rb b/app/controllers/projects/registry/tags_controller.rb
index e572c56adf5f25926bca63efe446d88993e263ce..c42e3f6bdba048f29cc88718ec18f51017426a09 100644
--- a/app/controllers/projects/registry/tags_controller.rb
+++ b/app/controllers/projects/registry/tags_controller.rb
@@ -31,12 +31,7 @@ module Projects
end
def bulk_destroy
- unless params[:ids].present?
- head :bad_request
- return
- end
-
- tag_names = params[:ids] || []
+ tag_names = params.require(:ids) || []
if tag_names.size > LIMIT
head :bad_request
return
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index ed5e39478f1b4ad25b1c80910babc244893c2c70..c54687c432c3a46b5908d1ba741262598d9861d5 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -117,8 +117,10 @@ class RegistrationsController < Devise::RegistrationsController
end
def after_inactive_sign_up_path_for(resource)
+ # With the current `allow_unconfirmed_access_for` Devise setting in config/initializers/8_devise.rb,
+ # this method is never called. Leaving this here in case that value is set to 0.
Gitlab::AppLogger.info(user_created_message)
- dashboard_projects_path
+ users_almost_there_path
end
private
diff --git a/app/graphql/types/commit_type.rb b/app/graphql/types/commit_type.rb
index 392e3ae41c5b6f324f01c1f6c4a45d14587be42e..eb25e3651a8f49fedbbecbcfe0c4ded371a8489a 100644
--- a/app/graphql/types/commit_type.rb
+++ b/app/graphql/types/commit_type.rb
@@ -26,6 +26,11 @@ module Types
description: 'Rendered HTML of the commit signature'
field :author_name, type: GraphQL::STRING_TYPE, null: true,
description: 'Commit authors name'
+ field :author_gravatar, type: GraphQL::STRING_TYPE, null: true,
+ description: 'Commit authors gravatar',
+ resolve: -> (commit, args, context) do
+ GravatarService.new.execute(commit.author_email, 40)
+ end
# models/commit lazy loads the author by email
field :author, type: Types::UserType, null: true,
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 94b99835a53a1d713f87d79e8a53ea9ecc593ee8..bb59fc937b155c59f9bd8f7232fec91235b1c929 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -216,7 +216,7 @@ module Ci
end
end
- after_transition created: :pending do |pipeline|
+ after_transition created: any - [:failed] do |pipeline|
next unless pipeline.bridge_triggered?
next if pipeline.bridge_waiting?
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 9542f8c9766f6c9f70fdef1f491fe6c588c8260c..7496ca97d56bf9e5eafdcec4ec9c13d7ec8031e6 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,7 +1,7 @@
- page_title _('CI / CD Charts')
-#js-project-pipelines-charts-app{ data: { counts: @counts, success_ratio: success_ratio(@counts), times_chart: { labels: @charts[:pipeline_times].labels, values: @charts[:pipeline_times].pipeline_times } } }
-
-#charts.ci-charts
- %hr
- = render 'projects/pipelines/charts/pipelines'
+#js-project-pipelines-charts-app{ data: { counts: @counts, success_ratio: success_ratio(@counts),
+ times_chart: { labels: @charts[:pipeline_times].labels, values: @charts[:pipeline_times].pipeline_times },
+ last_week_chart: { labels: @charts[:week].labels, totals: @charts[:week].total, success: @charts[:week].success },
+ last_month_chart: { labels: @charts[:month].labels, totals: @charts[:month].total, success: @charts[:month].success },
+ last_year_chart: { labels: @charts[:year].labels, totals: @charts[:year].total, success: @charts[:year].success } } }
diff --git a/app/views/projects/pipelines/charts/_pipelines.haml b/app/views/projects/pipelines/charts/_pipelines.haml
deleted file mode 100644
index afff9e82e450b576f60912038966a0bad5b2531b..0000000000000000000000000000000000000000
--- a/app/views/projects/pipelines/charts/_pipelines.haml
+++ /dev/null
@@ -1,37 +0,0 @@
-%h4.mt-4.mb-4= _("Pipelines charts")
-%p
-
- %span.legend-success
- = icon("circle")
- = s_("Pipeline|success")
-
- %span.legend-all
- = icon("circle")
- = s_("Pipeline|all")
-
-.prepend-top-default
- %p.light
- = _("Pipelines for last week")
- (#{date_from_to(Date.today - 7.days, Date.today)})
- %div
- %canvas#weekChart{ height: 200 }
-
-.prepend-top-default
- %p.light
- = _("Pipelines for last month")
- (#{date_from_to(Date.today - 30.days, Date.today)})
- %div
- %canvas#monthChart{ height: 200 }
-
-.prepend-top-default
- %p.light
- = _("Pipelines for last year")
- %div
- %canvas#yearChart.padded{ height: 250 }
-
--# haml-lint:disable InlineJavaScript
-%script#pipelinesChartsData{ type: "application/json" }
- - chartData = []
- - [:week, :month, :year].each do |scope|
- - chartData.push({ 'scope' => scope, 'labels' => @charts[scope].labels, 'totalValues' => @charts[scope].total, 'successValues' => @charts[scope].success })
- = chartData.to_json.html_safe
diff --git a/changelogs/unreleased/196183-convert-pipelines-last-week-chart-to-echarts.yml b/changelogs/unreleased/196183-convert-pipelines-last-week-chart-to-echarts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a2a4e57c67705e78b888a53b392aa43ef65e3a95
--- /dev/null
+++ b/changelogs/unreleased/196183-convert-pipelines-last-week-chart-to-echarts.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate CI CD pipelines charts to ECharts
+merge_request: 24057
+author:
+type: changed
diff --git a/changelogs/unreleased/fix-upstream-bridge-stuck-when-non-pending-pipelines.yml b/changelogs/unreleased/fix-upstream-bridge-stuck-when-non-pending-pipelines.yml
new file mode 100644
index 0000000000000000000000000000000000000000..eed4e811092088c1a7275a23f5bb2fd9b88cc16f
--- /dev/null
+++ b/changelogs/unreleased/fix-upstream-bridge-stuck-when-non-pending-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Fix upstream bridge stuck when downstream pipeline is not pending
+merge_request: 24665
+author:
+type: fixed
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index c8a91d830a08f9752fc688dd95b81df8bce44478..c0600d45d13c942e410fb8887ff595d0ec0fdf81 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -165,6 +165,11 @@ type Commit {
"""
author: User
+ """
+ Commit authors gravatar
+ """
+ authorGravatar: String
+
"""
Commit authors name
"""
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 08b84a1ca3587d3c7ce41ac5f915f98eedbeeba1..5b80c8d74a630dd2a19af21be098a828357e801d 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -13259,6 +13259,20 @@
"isDeprecated": false,
"deprecationReason": null
},
+ {
+ "name": "authorGravatar",
+ "description": "Commit authors gravatar",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
{
"name": "authorName",
"description": "Commit authors name",
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 5e0b7465c20f0d9a27388c763292253340288d2e..ee3c05eb6a074fa22fbf696e8cbdcfe3d4a3a6dc 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -54,6 +54,7 @@ An emoji awarded by a user.
| Name | Type | Description |
| --- | ---- | ---------- |
| `author` | User | Author of the commit |
+| `authorGravatar` | String | Commit authors gravatar |
| `authorName` | String | Commit authors name |
| `authoredDate` | Time | Timestamp of when the commit was authored |
| `description` | String | Description of the commit message |
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index f5630209f497a360d9c29183b361318040797972..8298d57582719a1157133519d4ff3f4cd4c11755 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -11419,6 +11419,9 @@ msgstr ""
msgid "Live preview"
msgstr ""
+msgid "Loading blob"
+msgstr ""
+
msgid "Loading contribution stats for group members"
msgstr ""
@@ -13672,10 +13675,10 @@ msgstr ""
msgid "Pipelines emails"
msgstr ""
-msgid "Pipelines for last month"
+msgid "Pipelines for last month (%{oneMonthAgo} - %{today})"
msgstr ""
-msgid "Pipelines for last week"
+msgid "Pipelines for last week (%{oneWeekAgo} - %{today})"
msgstr ""
msgid "Pipelines for last year"
@@ -13759,6 +13762,9 @@ msgstr ""
msgid "Pipeline|Coverage"
msgstr ""
+msgid "Pipeline|Date"
+msgstr ""
+
msgid "Pipeline|Detached merge request pipeline"
msgstr ""
@@ -13780,6 +13786,9 @@ msgstr ""
msgid "Pipeline|Pipeline"
msgstr ""
+msgid "Pipeline|Pipelines"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -13816,18 +13825,12 @@ msgstr ""
msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
msgstr ""
-msgid "Pipeline|all"
-msgstr ""
-
msgid "Pipeline|for"
msgstr ""
msgid "Pipeline|on"
msgstr ""
-msgid "Pipeline|success"
-msgstr ""
-
msgid "Pipeline|with stage"
msgstr ""
diff --git a/package.json b/package.json
index c259a7dfb682cc4f2c12ed0c626eed731e77eb05..3a5f4edb4efe6d8ee44fd6a2041142a27875ea24 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.6.2",
"@gitlab/svgs": "^1.96.0",
- "@gitlab/ui": "^9.4.1",
+ "@gitlab/ui": "^9.6.0",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
"@sourcegraph/code-host-integration": "0.0.30",
diff --git a/qa/qa/flow/saml.rb b/qa/qa/flow/saml.rb
index 0b9f9f94fbd8aee09673197bede7c08bb6451317..676be2beb012e0f5dac00035a6be96b2a398f5fb 100644
--- a/qa/qa/flow/saml.rb
+++ b/qa/qa/flow/saml.rb
@@ -38,7 +38,9 @@ module QA
def visit_saml_sso_settings(group, direct: false)
if direct
- page.visit "#{group.web_url}/-/saml"
+ url = "#{group.web_url}/-/saml"
+ Runtime::Logger.debug("Visiting url \"#{url}\" directly")
+ page.visit url
else
group.visit!
diff --git a/qa/qa/runtime/feature.rb b/qa/qa/runtime/feature.rb
index 9cb2c925b1923956fadfc59543fd2d83244b166b..5e948b5b850662778b5a5732b240674586dca06d 100644
--- a/qa/qa/runtime/feature.rb
+++ b/qa/qa/runtime/feature.rb
@@ -48,6 +48,12 @@ module QA
feature && feature["state"] == "on"
end
+ def get_features
+ request = Runtime::API::Request.new(api_client, "/features")
+ response = get(request.url)
+ response.body
+ end
+
private
def api_client
@@ -76,12 +82,6 @@ module QA
raise SetFeatureError, "Setting feature flag #{key} to #{value} failed with `#{response}`."
end
end
-
- def get_features
- request = Runtime::API::Request.new(api_client, "/features")
- response = get(request.url)
- response.body
- end
end
end
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index e36d87a72242e37976b3f1e141263b1880ac9007..8d79e505e5ddf4fc09855e18d235f2338bce85c2 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -77,14 +77,32 @@ describe RegistrationsController do
context 'when send_user_confirmation_email is true' do
before do
stub_application_setting(send_user_confirmation_email: true)
- allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
- it 'authenticates the user and sends a confirmation email' do
- post(:create, params: user_params)
+ context 'when a grace period is active for confirming the email address' do
+ before do
+ allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
+ end
+
+ it 'sends a confirmation email and redirects to the dashboard' do
+ post(:create, params: user_params)
+
+ expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
+ expect(response).to redirect_to(dashboard_projects_path)
+ end
+ end
- expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
- expect(response).to redirect_to(dashboard_projects_path)
+ context 'when no grace period is active for confirming the email address' do
+ before do
+ allow(User).to receive(:allow_unconfirmed_access_for).and_return 0
+ end
+
+ it 'sends a confirmation email and redirects to the almost there page' do
+ post(:create, params: user_params)
+
+ expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
+ expect(response).to redirect_to(users_almost_there_path)
+ end
end
end
diff --git a/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
new file mode 100644
index 0000000000000000000000000000000000000000..b77ca28b9d8d84b4eb83392bf5c540e2c85d93d7
--- /dev/null
+++ b/spec/frontend/blob/components/__snapshots__/blob_header_spec.js.snap
@@ -0,0 +1,25 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Blob Header Default Actions rendering matches the snapshot 1`] = `
+
+`;
diff --git a/spec/frontend/blob/components/blob_header_default_actions_spec.js b/spec/frontend/blob/components/blob_header_default_actions_spec.js
index 348d68514a35c1d81db08d8c7e8aa971a10bb702..fe0edffd12d02a643c2689d0fcfded6173107a19 100644
--- a/spec/frontend/blob/components/blob_header_default_actions_spec.js
+++ b/spec/frontend/blob/components/blob_header_default_actions_spec.js
@@ -4,9 +4,11 @@ import {
BTN_COPY_CONTENTS_TITLE,
BTN_DOWNLOAD_TITLE,
BTN_RAW_TITLE,
+ RICH_BLOB_VIEWER,
} from '~/blob/components/constants';
import { GlButtonGroup, GlButton } from '@gitlab/ui';
import { Blob } from './mock_data';
+import eventHub from '~/blob/event_hub';
describe('Blob Header Default Actions', () => {
let wrapper;
@@ -14,10 +16,11 @@ describe('Blob Header Default Actions', () => {
let buttons;
const hrefPrefix = 'http://localhost';
- function createComponent(props = {}) {
+ function createComponent(blobProps = {}, propsData = {}) {
wrapper = mount(BlobHeaderActions, {
propsData: {
- blob: Object.assign({}, Blob, props),
+ blob: Object.assign({}, Blob, blobProps),
+ ...propsData,
},
});
}
@@ -51,14 +54,30 @@ describe('Blob Header Default Actions', () => {
it('correct href attribute on Download button', () => {
expect(buttons.at(2).vm.$el.href).toBe(`${hrefPrefix}${Blob.rawPath}?inline=false`);
});
+
+ it('does not render "Copy file contents" button as disables if the viewer is Simple', () => {
+ expect(buttons.at(0).attributes('disabled')).toBeUndefined();
+ });
+
+ it('renders "Copy file contents" button as disables if the viewer is Rich', () => {
+ createComponent(
+ {},
+ {
+ activeViewer: RICH_BLOB_VIEWER,
+ },
+ );
+ buttons = wrapper.findAll(GlButton);
+
+ expect(buttons.at(0).attributes('disabled')).toBeTruthy();
+ });
});
describe('functionally', () => {
it('emits an event when a Copy Contents button is clicked', () => {
- jest.spyOn(wrapper.vm, '$emit');
+ jest.spyOn(eventHub, '$emit');
buttons.at(0).vm.$emit('click');
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('copy');
+ expect(eventHub.$emit).toHaveBeenCalledWith('copy');
});
});
});
diff --git a/spec/frontend/blob/components/blob_header_spec.js b/spec/frontend/blob/components/blob_header_spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..7d1443fb06927852a056ed1bdb42940affd96e3b
--- /dev/null
+++ b/spec/frontend/blob/components/blob_header_spec.js
@@ -0,0 +1,133 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import BlobHeader from '~/blob/components/blob_header.vue';
+import ViewerSwitcher from '~/blob/components/blob_header_viewer_switcher.vue';
+import DefaultActions from '~/blob/components/blob_header_default_actions.vue';
+import BlobFilepath from '~/blob/components/blob_header_filepath.vue';
+import eventHub from '~/blob/event_hub';
+
+import { Blob } from './mock_data';
+
+describe('Blob Header Default Actions', () => {
+ let wrapper;
+
+ function createComponent(blobProps = {}, options = {}, propsData = {}, shouldMount = false) {
+ const method = shouldMount ? mount : shallowMount;
+ wrapper = method.call(this, BlobHeader, {
+ propsData: {
+ blob: Object.assign({}, Blob, blobProps),
+ ...propsData,
+ },
+ ...options,
+ });
+ }
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('rendering', () => {
+ const slots = {
+ prepend: 'Foo Prepend',
+ actions: 'Actions Bar',
+ };
+
+ it('matches the snapshot', () => {
+ createComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('renders all components', () => {
+ createComponent();
+ expect(wrapper.find(ViewerSwitcher).exists()).toBe(true);
+ expect(wrapper.find(DefaultActions).exists()).toBe(true);
+ expect(wrapper.find(BlobFilepath).exists()).toBe(true);
+ });
+
+ it('does not render viewer switcher if the blob has only the simple viewer', () => {
+ createComponent({
+ richViewer: null,
+ });
+ expect(wrapper.find(ViewerSwitcher).exists()).toBe(false);
+ });
+
+ it('does not render viewer switcher if a corresponding prop is passed', () => {
+ createComponent(
+ {},
+ {},
+ {
+ hideViewerSwitcher: true,
+ },
+ );
+ expect(wrapper.find(ViewerSwitcher).exists()).toBe(false);
+ });
+
+ it('does not render default actions is corresponding prop is passed', () => {
+ createComponent(
+ {},
+ {},
+ {
+ hideDefaultActions: true,
+ },
+ );
+ expect(wrapper.find(DefaultActions).exists()).toBe(false);
+ });
+
+ Object.keys(slots).forEach(slot => {
+ it('renders the slots', () => {
+ const slotContent = slots[slot];
+ createComponent(
+ {},
+ {
+ scopedSlots: {
+ [slot]: `
${slotContent}`,
+ },
+ },
+ {},
+ true,
+ );
+ expect(wrapper.text()).toContain(slotContent);
+ });
+ });
+ });
+
+ describe('functionality', () => {
+ const newViewer = 'Foo Bar';
+
+ it('listens to "switch-view" event when viewer switcher is shown and updates activeViewer', () => {
+ expect(wrapper.vm.showViewerSwitcher).toBe(true);
+ eventHub.$emit('switch-viewer', newViewer);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.activeViewer).toBe(newViewer);
+ });
+ });
+
+ it('does not update active viewer if the switcher is not shown', () => {
+ const activeViewer = 'Alpha Beta';
+ createComponent(
+ {},
+ {
+ data() {
+ return {
+ activeViewer,
+ };
+ },
+ },
+ {
+ hideViewerSwitcher: true,
+ },
+ );
+
+ expect(wrapper.vm.showViewerSwitcher).toBe(false);
+ eventHub.$emit('switch-viewer', newViewer);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.activeViewer).toBe(activeViewer);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
index ff0b005f441a3585e50ca73e131e539c2b5b049f..88e9eeea994c9d409236b514849b9f1004f5bcae 100644
--- a/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
+++ b/spec/frontend/blob/components/blob_header_viewer_switcher_spec.js
@@ -8,14 +8,16 @@ import {
} from '~/blob/components/constants';
import { GlButtonGroup, GlButton } from '@gitlab/ui';
import { Blob } from './mock_data';
+import eventHub from '~/blob/event_hub';
describe('Blob Header Viewer Switcher', () => {
let wrapper;
- function createComponent(props = {}) {
+ function createComponent(blobProps = {}, propsData = {}) {
wrapper = mount(BlobHeaderViewerSwitcher, {
propsData: {
- blob: Object.assign({}, Blob, props),
+ blob: Object.assign({}, Blob, blobProps),
+ ...propsData,
},
});
}
@@ -25,14 +27,9 @@ describe('Blob Header Viewer Switcher', () => {
});
describe('intiialization', () => {
- it('is initialized with rich viewer as preselected when richViewer exists', () => {
+ it('is initialized with simple viewer as active', () => {
createComponent();
- expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
- });
-
- it('is initialized with simple viewer as preselected when richViewer does not exists', () => {
- createComponent({ richViewer: null });
- expect(wrapper.vm.viewer).toBe(SIMPLE_BLOB_VIEWER);
+ expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER);
});
});
@@ -63,47 +60,43 @@ describe('Blob Header Viewer Switcher', () => {
let simpleBtn;
let richBtn;
- beforeEach(() => {
- createComponent();
+ function factory(propsOptions = {}) {
+ createComponent({}, propsOptions);
buttons = wrapper.findAll(GlButton);
simpleBtn = buttons.at(0);
richBtn = buttons.at(1);
- });
+
+ jest.spyOn(eventHub, '$emit');
+ }
it('does not switch the viewer if the selected one is already active', () => {
- jest.spyOn(wrapper.vm, '$emit');
+ factory();
+ expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER);
+ simpleBtn.vm.$emit('click');
+ expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER);
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
+
+ it('emits an event when a Rich Viewer button is clicked', () => {
+ factory();
+ expect(wrapper.vm.activeViewer).toBe(SIMPLE_BLOB_VIEWER);
- expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
richBtn.vm.$emit('click');
- expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
- expect(wrapper.vm.$emit).not.toHaveBeenCalled();
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('switch-viewer', RICH_BLOB_VIEWER);
+ });
});
it('emits an event when a Simple Viewer button is clicked', () => {
- jest.spyOn(wrapper.vm, '$emit');
-
+ factory({
+ activeViewer: RICH_BLOB_VIEWER,
+ });
simpleBtn.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.viewer).toBe(SIMPLE_BLOB_VIEWER);
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('switch-viewer', SIMPLE_BLOB_VIEWER);
+ expect(eventHub.$emit).toHaveBeenCalledWith('switch-viewer', SIMPLE_BLOB_VIEWER);
});
});
-
- it('emits an event when a Rich Viewer button is clicked', () => {
- jest.spyOn(wrapper.vm, '$emit');
-
- wrapper.setData({ viewer: SIMPLE_BLOB_VIEWER });
-
- return wrapper.vm
- .$nextTick()
- .then(() => {
- richBtn.vm.$emit('click');
- })
- .then(() => {
- expect(wrapper.vm.viewer).toBe(RICH_BLOB_VIEWER);
- expect(wrapper.vm.$emit).toHaveBeenCalledWith('switch-viewer', RICH_BLOB_VIEWER);
- });
- });
});
});
diff --git a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
index 184d0321dc1b5422e5f539fab882ecb2702c1dcf..a4a0b98de1b119c8b7f9a0107ed80de0bea8c281 100644
--- a/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
+++ b/spec/frontend/contributors/component/__snapshots__/contributors_spec.js.snap
@@ -22,6 +22,7 @@ exports[`Contributors charts should render charts when loading completed and the
legendmaxtext="Max"
option="[object Object]"
thresholds=""
+ width="0"
/>
@@ -29,7 +30,7 @@ exports[`Contributors charts should render charts when loading completed and the
class="row"
>