diff options
Diffstat (limited to 'spec')
18 files changed, 484 insertions, 75 deletions
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index e36d87a7224..8d79e505e5d 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 00000000000..b77ca28b9d8 --- /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`] = ` +<div + class="js-file-title file-title-flex-parent" +> + <blob-filepath-stub + blob="[object Object]" + /> + + <div + class="file-actions d-none d-sm-block" + > + <viewer-switcher-stub + activeviewer="rich" + blob="[object Object]" + /> + + <default-actions-stub + activeviewer="rich" + blob="[object Object]" + /> + </div> +</div> +`; 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 348d68514a3..fe0edffd12d 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 00000000000..7d1443fb069 --- /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]: `<span>${slotContent}</span>`, + }, + }, + {}, + 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 ff0b005f441..88e9eeea994 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 184d0321dc1..a4a0b98de1b 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" /> </div> @@ -29,7 +30,7 @@ exports[`Contributors charts should render charts when loading completed and the class="row" > <div - class="col-6" + class="col-lg-6 col-12" > <h4> John @@ -39,15 +40,18 @@ exports[`Contributors charts should render charts when loading completed and the 2 commits (jawnnypoo@gmail.com) </p> - <glareachart-stub - data="[object Object]" - height="216" - includelegendavgmax="true" - legendaveragetext="Avg" - legendmaxtext="Max" - option="[object Object]" - thresholds="" - /> + <div> + <glareachart-stub + data="[object Object]" + height="216" + includelegendavgmax="true" + legendaveragetext="Avg" + legendmaxtext="Max" + option="[object Object]" + thresholds="" + width="0" + /> + </div> </div> </div> </div> diff --git a/spec/frontend/contributors/component/contributors_spec.js b/spec/frontend/contributors/component/contributors_spec.js index 3e4924ed906..24816e4e8ac 100644 --- a/spec/frontend/contributors/component/contributors_spec.js +++ b/spec/frontend/contributors/component/contributors_spec.js @@ -1,5 +1,5 @@ import Vue from 'vue'; -import { shallowMount } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { createStore } from '~/contributors/stores'; import axios from '~/lib/utils/axios_utils'; @@ -22,7 +22,7 @@ function factory() { mock.onGet().reply(200, chartData); store = createStore(); - wrapper = shallowMount(Component, { + wrapper = mount(Component, { propsData: { endpoint, branch, diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap new file mode 100644 index 00000000000..c15971912dd --- /dev/null +++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/pipelines_area_chart_spec.js.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PipelinesAreaChart matches the snapshot 1`] = ` +<div + class="prepend-top-default" +> + <p> + Some title + </p> + + <div> + <glareachart-stub + data="[object Object],[object Object]" + height="300" + legendaveragetext="Avg" + legendmaxtext="Max" + option="[object Object]" + thresholds="" + width="0" + /> + </div> +</div> +`; diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js index 8aeeb4d5d7d..883f2bec5f7 100644 --- a/spec/frontend/projects/pipelines/charts/components/app_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js @@ -2,7 +2,14 @@ import { shallowMount } from '@vue/test-utils'; import { GlColumnChart } from '@gitlab/ui/dist/charts'; import Component from '~/projects/pipelines/charts/components/app.vue'; import StatisticsList from '~/projects/pipelines/charts/components/statistics_list.vue'; -import { counts, timesChartData } from '../mock_data'; +import PipelinesAreaChart from '~/projects/pipelines/charts/components/pipelines_area_chart.vue'; +import { + counts, + timesChartData, + areaChartData as lastWeekChartData, + areaChartData as lastMonthChartData, + lastYearChartData, +} from '../mock_data'; describe('ProjectsPipelinesChartsApp', () => { let wrapper; @@ -12,6 +19,9 @@ describe('ProjectsPipelinesChartsApp', () => { propsData: { counts, timesChartData, + lastWeekChartData, + lastMonthChartData, + lastYearChartData, }, }); }); @@ -39,4 +49,24 @@ describe('ProjectsPipelinesChartsApp', () => { expect(chart.props('option')).toBe(wrapper.vm.$options.timesChartOptions); }); }); + + describe('pipelines charts', () => { + it('displays 3 area charts', () => { + expect(wrapper.findAll(PipelinesAreaChart).length).toBe(3); + }); + + describe('displays individual correctly', () => { + it('renders with the correct data', () => { + const charts = wrapper.findAll(PipelinesAreaChart); + + for (let i = 0; i < charts.length; i += 1) { + const chart = charts.at(i); + + expect(chart.exists()).toBeTruthy(); + expect(chart.props('chartData')).toBe(wrapper.vm.areaCharts[i].data); + expect(chart.text()).toBe(wrapper.vm.areaCharts[i].title); + } + }); + }); + }); }); diff --git a/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js b/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js new file mode 100644 index 00000000000..aea25903023 --- /dev/null +++ b/spec/frontend/projects/pipelines/charts/components/pipelines_area_chart_spec.js @@ -0,0 +1,30 @@ +import { mount } from '@vue/test-utils'; +import Component from '~/projects/pipelines/charts/components/pipelines_area_chart.vue'; +import { transformedAreaChartData } from '../mock_data'; + +describe('PipelinesAreaChart', () => { + let wrapper; + + beforeEach(() => { + wrapper = mount(Component, { + propsData: { + chartData: transformedAreaChartData, + }, + slots: { + default: 'Some title', + }, + stubs: { + GlAreaChart: true, + }, + }); + }); + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('matches the snapshot', () => { + expect(wrapper.element).toMatchSnapshot(); + }); +}); diff --git a/spec/frontend/projects/pipelines/charts/mock_data.js b/spec/frontend/projects/pipelines/charts/mock_data.js index 93e53125679..db5164c8f99 100644 --- a/spec/frontend/projects/pipelines/charts/mock_data.js +++ b/spec/frontend/projects/pipelines/charts/mock_data.js @@ -9,3 +9,25 @@ export const timesChartData = { labels: ['as1234', 'kh423hy', 'ji56bvg', 'th23po'], values: [5, 3, 7, 4], }; + +export const areaChartData = { + labels: ['01 Jan', '02 Jan', '03 Jan', '04 Jan', '05 Jan'], + totals: [4, 6, 3, 6, 7], + success: [3, 5, 3, 3, 5], +}; + +export const lastYearChartData = { + ...areaChartData, + labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], +}; + +export const transformedAreaChartData = [ + { + name: 'all', + data: [['01 Jan', 4], ['02 Jan', 6], ['03 Jan', 3], ['04 Jan', 6], ['05 Jan', 7]], + }, + { + name: 'success', + data: [['01 Jan', 3], ['02 Jan', 3], ['03 Jan', 3], ['04 Jan', 3], ['05 Jan', 5]], + }, +]; diff --git a/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap b/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap index c5f5ea68d9e..687ff709fd7 100644 --- a/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap +++ b/spec/frontend/registry/shared/components/__snapshots__/expiration_policy_fields_spec.js.snap @@ -18,6 +18,7 @@ exports[`Expiration Policy Form renders 1`] = ` id="expiration-policy-toggle" labeloff="Toggle Status: OFF" labelon="Toggle Status: ON" + labelposition="hidden" /> <span diff --git a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap index 22e353dddc5..49feae0884e 100644 --- a/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap +++ b/spec/frontend/repository/components/table/__snapshots__/row_spec.js.snap @@ -48,3 +48,52 @@ exports[`Repository table row component renders table row 1`] = ` </td> </tr> `; + +exports[`Repository table row component renders table row for path with special character 1`] = ` +<tr + class="tree-item file_1" +> + <td + class="tree-item-file-name" + > + <i + aria-label="file" + class="fa fa-fw fa-file-text-o" + role="img" + /> + + <a + class="str-truncated" + href="https://test.com" + > + + test + + </a> + + <!----> + + <!----> + + <!----> + </td> + + <td + class="d-none d-sm-table-cell tree-commit" + > + <gl-skeleton-loading-stub + class="h-auto" + lines="1" + /> + </td> + + <td + class="tree-time-ago text-right" + > + <gl-skeleton-loading-stub + class="ml-auto h-auto w-50" + lines="1" + /> + </td> +</tr> +`; diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js index 71709e7dd83..fec9ba3aa2e 100644 --- a/spec/frontend/repository/components/table/row_spec.js +++ b/spec/frontend/repository/components/table/row_spec.js @@ -51,6 +51,20 @@ describe('Repository table row component', () => { }); }); + it('renders table row for path with special character', () => { + factory({ + id: '1', + sha: '123', + path: 'test$/test', + type: 'file', + currentPath: 'test$', + }); + + return vm.vm.$nextTick().then(() => { + expect(vm.element).toMatchSnapshot(); + }); + }); + it.each` type | component | componentName ${'tree'} | ${RouterLinkStub} | ${'RouterLink'} diff --git a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_spec.js.snap b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_spec.js.snap index d5546021430..955716ccbca 100644 --- a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_spec.js.snap +++ b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_spec.js.snap @@ -49,6 +49,7 @@ exports[`self monitor component When the self monitor project has not been creat <gl-toggle-stub labeloff="Toggle Status: OFF" labelon="Toggle Status: ON" + labelposition="hidden" name="self-monitor-toggle" /> </gl-form-group-stub> diff --git a/spec/frontend/snippets/components/snippet_blob_view_spec.js b/spec/frontend/snippets/components/snippet_blob_view_spec.js index 8401c08b1da..efc1c6dcef9 100644 --- a/spec/frontend/snippets/components/snippet_blob_view_spec.js +++ b/spec/frontend/snippets/components/snippet_blob_view_spec.js @@ -1,5 +1,7 @@ import { shallowMount } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; import SnippetBlobView from '~/snippets/components/snippet_blob_view.vue'; +import BlobHeader from '~/blob/components/blob_header.vue'; import BlobEmbeddable from '~/blob/components/blob_embeddable.vue'; import { SNIPPET_VISIBILITY_PRIVATE, @@ -15,7 +17,15 @@ describe('Blob Embeddable', () => { visibilityLevel: SNIPPET_VISIBILITY_PUBLIC, }; - function createComponent(props = {}) { + function createComponent(props = {}, loading = false) { + const $apollo = { + queries: { + blob: { + loading, + }, + }, + }; + wrapper = shallowMount(SnippetBlobView, { propsData: { snippet: { @@ -23,32 +33,44 @@ describe('Blob Embeddable', () => { ...props, }, }, + mocks: { $apollo }, }); + + wrapper.vm.$apollo.queries.blob.loading = false; } afterEach(() => { wrapper.destroy(); }); - it('renders blob-embeddable component', () => { - createComponent(); - expect(wrapper.find(BlobEmbeddable).exists()).toBe(true); - }); - - it('does not render blob-embeddable for internal snippet', () => { - createComponent({ - visibilityLevel: SNIPPET_VISIBILITY_INTERNAL, + describe('rendering', () => { + it('renders correct components', () => { + createComponent(); + expect(wrapper.find(BlobEmbeddable).exists()).toBe(true); + expect(wrapper.find(BlobHeader).exists()).toBe(true); }); - expect(wrapper.find(BlobEmbeddable).exists()).toBe(false); - createComponent({ - visibilityLevel: SNIPPET_VISIBILITY_PRIVATE, + it.each([SNIPPET_VISIBILITY_INTERNAL, SNIPPET_VISIBILITY_PRIVATE, 'foo'])( + 'does not render blob-embeddable by default', + visibilityLevel => { + createComponent({ + visibilityLevel, + }); + expect(wrapper.find(BlobEmbeddable).exists()).toBe(false); + }, + ); + + it('does render blob-embeddable for public snippet', () => { + createComponent({ + visibilityLevel: SNIPPET_VISIBILITY_PUBLIC, + }); + expect(wrapper.find(BlobEmbeddable).exists()).toBe(true); }); - expect(wrapper.find(BlobEmbeddable).exists()).toBe(false); - createComponent({ - visibilityLevel: 'foo', + it('shows loading icon while blob data is in flight', () => { + createComponent({}, true); + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + expect(wrapper.find('.snippet-file-content').exists()).toBe(false); }); - expect(wrapper.find(BlobEmbeddable).exists()).toBe(false); }); }); diff --git a/spec/graphql/types/commit_type_spec.rb b/spec/graphql/types/commit_type_spec.rb index 1c3b46ecfde..f5f99229f3a 100644 --- a/spec/graphql/types/commit_type_spec.rb +++ b/spec/graphql/types/commit_type_spec.rb @@ -10,7 +10,8 @@ describe GitlabSchema.types['Commit'] do it 'contains attributes related to commit' do expect(described_class).to have_graphql_fields( :id, :sha, :title, :description, :message, :authored_date, - :author_name, :author, :web_url, :latest_pipeline, :pipelines, :signature_html + :author_name, :author_gravatar, :author, :web_url, :latest_pipeline, + :pipelines, :signature_html ) end end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 6efec87464b..42d304d9116 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -2953,6 +2953,30 @@ describe Ci::Pipeline, :mailer do create(:ci_sources_pipeline, pipeline: pipeline, source_job: bridge) end + context 'when downstream pipeline status transitions to pending' do + it 'updates bridge status ' do + expect(pipeline).to receive(:update_bridge_status!).once + + pipeline.run! + end + end + + context 'when the status of downstream pipeline transitions to waiting_for_resource' do + it 'updates bridge status ' do + expect(pipeline).to receive(:update_bridge_status!).once + + pipeline.request_resource! + end + end + + context 'when the status of downstream pipeline transitions to failed' do + it 'does not update bridge status ' do + expect(pipeline).not_to receive(:update_bridge_status!) + + pipeline.drop! + end + end + describe '#bridge_triggered?' do it 'is a pipeline triggered by a bridge' do expect(pipeline).to be_bridge_triggered |