diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 12:55:51 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 12:55:51 +0300 |
commit | e8d2c2579383897a1dd7f9debd359abe8ae8373d (patch) | |
tree | c42be41678c2586d49a75cabce89322082698334 /spec/frontend/jobs | |
parent | fc845b37ec3a90aaa719975f607740c22ba6a113 (diff) |
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'spec/frontend/jobs')
-rw-r--r-- | spec/frontend/jobs/components/empty_state_spec.js | 1 | ||||
-rw-r--r-- | spec/frontend/jobs/components/job_app_spec.js | 8 | ||||
-rw-r--r-- | spec/frontend/jobs/components/log/collapsible_section_spec.js | 9 | ||||
-rw-r--r-- | spec/frontend/jobs/components/log/line_spec.js | 30 | ||||
-rw-r--r-- | spec/frontend/jobs/components/log/log_spec.js | 91 | ||||
-rw-r--r-- | spec/frontend/jobs/components/log/mock_data.js | 65 | ||||
-rw-r--r-- | spec/frontend/jobs/components/manual_variables_form_spec.js | 15 | ||||
-rw-r--r-- | spec/frontend/jobs/components/sidebar_detail_row_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/jobs/store/mutations_spec.js | 94 | ||||
-rw-r--r-- | spec/frontend/jobs/store/utils_spec.js | 95 |
10 files changed, 393 insertions, 17 deletions
diff --git a/spec/frontend/jobs/components/empty_state_spec.js b/spec/frontend/jobs/components/empty_state_spec.js index c9de110ce06..9738fd14275 100644 --- a/spec/frontend/jobs/components/empty_state_spec.js +++ b/spec/frontend/jobs/components/empty_state_spec.js @@ -9,7 +9,6 @@ describe('Empty State', () => { illustrationSizeClass: 'svg-430', title: 'This job has not started yet', playable: false, - variablesSettingsUrl: '', }; const createWrapper = (props) => { diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js index 3fcefde1aba..1f4dd7d6216 100644 --- a/spec/frontend/jobs/components/job_app_spec.js +++ b/spec/frontend/jobs/components/job_app_spec.js @@ -24,6 +24,7 @@ describe('Job App', () => { let store; let wrapper; let mock; + let origGon; const initSettings = { endpoint: `${TEST_HOST}jobs/123.json`, @@ -37,7 +38,6 @@ describe('Job App', () => { deploymentHelpUrl: 'help/deployment', codeQualityHelpPath: '/help/code_quality', runnerSettingsUrl: 'settings/ci-cd/runners', - variablesSettingsUrl: 'settings/ci-cd/variables', terminalPath: 'jobs/123/terminal', projectPath: 'user-name/project-name', subscriptionsMoreMinutesUrl: 'https://customers.gitlab.com/buy_pipeline_minutes', @@ -86,11 +86,17 @@ describe('Job App', () => { beforeEach(() => { mock = new MockAdapter(axios); store = createStore(); + + origGon = window.gon; + + window.gon = { features: { infinitelyCollapsibleSections: false } }; // NOTE: All of this passes with the feature flag }); afterEach(() => { wrapper.destroy(); mock.restore(); + + window.gon = origGon; }); describe('while loading', () => { diff --git a/spec/frontend/jobs/components/log/collapsible_section_spec.js b/spec/frontend/jobs/components/log/collapsible_section_spec.js index 66f22162c97..4e23a3ba7b8 100644 --- a/spec/frontend/jobs/components/log/collapsible_section_spec.js +++ b/spec/frontend/jobs/components/log/collapsible_section_spec.js @@ -4,6 +4,7 @@ import { collapsibleSectionClosed, collapsibleSectionOpened } from './mock_data' describe('Job Log Collapsible Section', () => { let wrapper; + let origGon; const traceEndpoint = 'jobs/335'; @@ -18,8 +19,16 @@ describe('Job Log Collapsible Section', () => { }); }; + beforeEach(() => { + origGon = window.gon; + + window.gon = { features: { infinitelyCollapsibleSections: false } }; // NOTE: This also works with true + }); + afterEach(() => { wrapper.destroy(); + + window.gon = origGon; }); describe('with closed section', () => { diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js index 367154e7f82..d184696cd1f 100644 --- a/spec/frontend/jobs/components/log/line_spec.js +++ b/spec/frontend/jobs/components/log/line_spec.js @@ -94,6 +94,16 @@ describe('Job Log Line', () => { expect(findLinkAttributeByIndex(0).href).toBe(queryUrl); }); + it('renders links that have brackets `[]` in their parameters', () => { + const url = `${httpUrl}?label_name[]=frontend`; + + createComponent(mockProps({ text: url })); + + expect(findLine().text()).toBe(url); + expect(findLinks().at(0).text()).toBe(url); + expect(findLinks().at(0).attributes('href')).toBe(url); + }); + it('renders multiple links surrounded by text', () => { createComponent( mockProps({ text: `Well, my HTTP url: ${httpUrl} and my HTTPS url: ${httpsUrl}` }), @@ -125,6 +135,26 @@ describe('Job Log Line', () => { expect(findLinkAttributeByIndex(4).href).toBe(httpsUrl); }); + it('renders multiple links surrounded by brackets', () => { + createComponent(mockProps({ text: `(${httpUrl}) <${httpUrl}> {${httpsUrl}}` })); + expect(findLine().text()).toBe( + '(http://example.com) <http://example.com> {https://example.com}', + ); + + const links = findLinks(); + + expect(links).toHaveLength(3); + + expect(links.at(0).text()).toBe(httpUrl); + expect(links.at(0).attributes('href')).toBe(httpUrl); + + expect(links.at(1).text()).toBe(httpUrl); + expect(links.at(1).attributes('href')).toBe(httpUrl); + + expect(links.at(2).text()).toBe(httpsUrl); + expect(links.at(2).attributes('href')).toBe(httpsUrl); + }); + it('renders text with symbols in it', () => { const text = 'apt-get update < /dev/null > /dev/null'; createComponent(mockProps({ text })); diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js index b7aff1f3e3b..99fb6846ce5 100644 --- a/spec/frontend/jobs/components/log/log_spec.js +++ b/spec/frontend/jobs/components/log/log_spec.js @@ -1,7 +1,7 @@ import { mount, createLocalVue } from '@vue/test-utils'; import Vuex from 'vuex'; import Log from '~/jobs/components/log/log.vue'; -import { logLinesParser } from '~/jobs/store/utils'; +import { logLinesParserLegacy, logLinesParser } from '~/jobs/store/utils'; import { jobLog } from './mock_data'; describe('Job Log', () => { @@ -9,6 +9,7 @@ describe('Job Log', () => { let actions; let state; let store; + let origGon; const localVue = createLocalVue(); localVue.use(Vuex); @@ -25,8 +26,12 @@ describe('Job Log', () => { toggleCollapsibleLine: () => {}, }; + origGon = window.gon; + + window.gon = { features: { infinitelyCollapsibleSections: false } }; + state = { - trace: logLinesParser(jobLog), + trace: logLinesParserLegacy(jobLog), traceEndpoint: 'jobs/id', }; @@ -40,6 +45,88 @@ describe('Job Log', () => { afterEach(() => { wrapper.destroy(); + + window.gon = origGon; + }); + + const findCollapsibleLine = () => wrapper.find('.collapsible-line'); + + describe('line numbers', () => { + it('renders a line number for each open line', () => { + expect(wrapper.find('#L1').text()).toBe('1'); + expect(wrapper.find('#L2').text()).toBe('2'); + expect(wrapper.find('#L3').text()).toBe('3'); + }); + + it('links to the provided path and correct line number', () => { + expect(wrapper.find('#L1').attributes('href')).toBe(`${state.traceEndpoint}#L1`); + }); + }); + + describe('collapsible sections', () => { + it('renders a clickable header section', () => { + expect(findCollapsibleLine().attributes('role')).toBe('button'); + }); + + it('renders an icon with the open state', () => { + expect(findCollapsibleLine().find('[data-testid="angle-down-icon"]').exists()).toBe(true); + }); + + describe('on click header section', () => { + it('calls toggleCollapsibleLine', () => { + jest.spyOn(wrapper.vm, 'toggleCollapsibleLine'); + + findCollapsibleLine().trigger('click'); + + expect(wrapper.vm.toggleCollapsibleLine).toHaveBeenCalled(); + }); + }); + }); +}); + +describe('Job Log, infinitelyCollapsibleSections feature flag enabled', () => { + let wrapper; + let actions; + let state; + let store; + let origGon; + + const localVue = createLocalVue(); + localVue.use(Vuex); + + const createComponent = () => { + wrapper = mount(Log, { + localVue, + store, + }); + }; + + beforeEach(() => { + actions = { + toggleCollapsibleLine: () => {}, + }; + + origGon = window.gon; + + window.gon = { features: { infinitelyCollapsibleSections: true } }; + + state = { + trace: logLinesParser(jobLog).parsedLines, + traceEndpoint: 'jobs/id', + }; + + store = new Vuex.Store({ + actions, + state, + }); + + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + + window.gon = origGon; }); const findCollapsibleLine = () => wrapper.find('.collapsible-line'); diff --git a/spec/frontend/jobs/components/log/mock_data.js b/spec/frontend/jobs/components/log/mock_data.js index eb8c4fe8bc9..76c35703106 100644 --- a/spec/frontend/jobs/components/log/mock_data.js +++ b/spec/frontend/jobs/components/log/mock_data.js @@ -58,6 +58,71 @@ export const utilsMockData = [ }, ]; +export const multipleCollapsibleSectionsMockData = [ + { + offset: 1001, + content: [{ text: ' on docker-auto-scale-com 8a6210b8' }], + }, + { + offset: 1002, + content: [ + { + text: 'Executing "step_script" stage of the job script', + }, + ], + section: 'step-script', + section_header: true, + }, + { + offset: 1003, + content: [{ text: 'sleep 60' }], + section: 'step-script', + }, + { + offset: 1004, + content: [ + { + text: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam lorem dolor, congue ac condimentum vitae', + }, + ], + section: 'step-script', + }, + { + offset: 1005, + content: [{ text: 'executing...' }], + section: 'step-script', + }, + { + offset: 1006, + content: [{ text: '1st collapsible section' }], + section: 'collapsible-1', + section_header: true, + }, + { + offset: 1007, + content: [ + { + text: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam lorem dolor, congue ac condimentum vitae', + }, + ], + section: 'collapsible-1', + }, + { + offset: 1008, + content: [], + section: 'collapsible-1', + section_duration: '01:00', + }, + { + offset: 1009, + content: [], + section: 'step-script', + section_duration: '10:00', + }, +]; + export const originalTrace = [ { offset: 1, diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js index 376a822dde5..7e42ee957d3 100644 --- a/spec/frontend/jobs/components/manual_variables_form_spec.js +++ b/spec/frontend/jobs/components/manual_variables_form_spec.js @@ -1,3 +1,4 @@ +import { GlSprintf, GlLink } from '@gitlab/ui'; import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; import Vue from 'vue'; import Vuex from 'vuex'; @@ -18,7 +19,6 @@ describe('Manual Variables Form', () => { method: 'post', button_title: 'Trigger this manual action', }, - variablesSettingsUrl: '/settings', }; const createComponent = ({ props = {}, mountFn = shallowMount } = {}) => { @@ -33,15 +33,19 @@ describe('Manual Variables Form', () => { propsData: { ...requiredProps, ...props }, localVue, store, + stubs: { + GlSprintf, + }, }), ); }; const findInputKey = () => wrapper.findComponent({ ref: 'inputKey' }); const findInputValue = () => wrapper.findComponent({ ref: 'inputSecretValue' }); + const findHelpText = () => wrapper.findComponent(GlSprintf); + const findHelpLink = () => wrapper.findComponent(GlLink); const findTriggerBtn = () => wrapper.findByTestId('trigger-manual-job-btn'); - const findHelpText = () => wrapper.findByTestId('form-help-text'); const findDeleteVarBtn = () => wrapper.findByTestId('delete-variable-btn'); const findCiVariableKey = () => wrapper.findByTestId('ci-variable-key'); const findCiVariableValue = () => wrapper.findByTestId('ci-variable-value'); @@ -62,11 +66,10 @@ describe('Manual Variables Form', () => { }); it('renders help text with provided link', () => { - expect(findHelpText().text()).toBe( - 'Specify variable values to be used in this run. The values specified in CI/CD settings will be used as default', + expect(findHelpText().exists()).toBe(true); + expect(findHelpLink().attributes('href')).toBe( + '/help/ci/variables/index#add-a-cicd-variable-to-a-project', ); - - expect(wrapper.find('a').attributes('href')).toBe(requiredProps.variablesSettingsUrl); }); describe('when adding a new variable', () => { diff --git a/spec/frontend/jobs/components/sidebar_detail_row_spec.js b/spec/frontend/jobs/components/sidebar_detail_row_spec.js index bae4d6cf837..43f2e022dd8 100644 --- a/spec/frontend/jobs/components/sidebar_detail_row_spec.js +++ b/spec/frontend/jobs/components/sidebar_detail_row_spec.js @@ -7,7 +7,7 @@ describe('Sidebar detail row', () => { const title = 'this is the title'; const value = 'this is the value'; - const helpUrl = '/help/ci/runners/README.html'; + const helpUrl = '/help/ci/runners/index.html'; const findHelpLink = () => wrapper.findComponent(GlLink); diff --git a/spec/frontend/jobs/store/mutations_spec.js b/spec/frontend/jobs/store/mutations_spec.js index 1c7e45dfb3d..159315330e4 100644 --- a/spec/frontend/jobs/store/mutations_spec.js +++ b/spec/frontend/jobs/store/mutations_spec.js @@ -4,12 +4,21 @@ import state from '~/jobs/store/state'; describe('Jobs Store Mutations', () => { let stateCopy; + let origGon; const html = 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- : Writing /builds/ab89e95b0fa0b9272ea0c797b76908f24d36992630e9325273a4ce3.png<br>I'; beforeEach(() => { stateCopy = state(); + + origGon = window.gon; + + window.gon = { features: { infinitelyCollapsibleSections: false } }; + }); + + afterEach(() => { + window.gon = origGon; }); describe('SET_JOB_ENDPOINT', () => { @@ -267,3 +276,88 @@ describe('Jobs Store Mutations', () => { }); }); }); + +describe('Job Store mutations, feature flag ON', () => { + let stateCopy; + let origGon; + + const html = + 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- : Writing /builds/ab89e95b0fa0b9272ea0c797b76908f24d36992630e9325273a4ce3.png<br>I'; + + beforeEach(() => { + stateCopy = state(); + + origGon = window.gon; + + window.gon = { features: { infinitelyCollapsibleSections: true } }; + }); + + afterEach(() => { + window.gon = origGon; + }); + + describe('RECEIVE_TRACE_SUCCESS', () => { + describe('with new job log', () => { + describe('log.lines', () => { + describe('when append is true', () => { + it('sets the parsed log ', () => { + mutations[types.RECEIVE_TRACE_SUCCESS](stateCopy, { + append: true, + size: 511846, + complete: true, + lines: [ + { + offset: 1, + content: [{ text: 'Running with gitlab-runner 11.12.1 (5a147c92)' }], + }, + ], + }); + + expect(stateCopy.trace).toEqual([ + { + offset: 1, + content: [{ text: 'Running with gitlab-runner 11.12.1 (5a147c92)' }], + lineNumber: 1, + }, + ]); + }); + }); + + describe('when lines are defined', () => { + it('sets the parsed log ', () => { + mutations[types.RECEIVE_TRACE_SUCCESS](stateCopy, { + append: false, + size: 511846, + complete: true, + lines: [ + { offset: 0, content: [{ text: 'Running with gitlab-runner 11.11.1 (5a147c92)' }] }, + ], + }); + + expect(stateCopy.trace).toEqual([ + { + offset: 0, + content: [{ text: 'Running with gitlab-runner 11.11.1 (5a147c92)' }], + lineNumber: 1, + }, + ]); + }); + }); + + describe('when lines are null', () => { + it('sets the default value', () => { + mutations[types.RECEIVE_TRACE_SUCCESS](stateCopy, { + append: true, + html, + size: 511846, + complete: false, + lines: null, + }); + + expect(stateCopy.trace).toEqual([]); + }); + }); + }); + }); + }); +}); diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js index e50d304bb08..35ac2945ab5 100644 --- a/spec/frontend/jobs/store/utils_spec.js +++ b/spec/frontend/jobs/store/utils_spec.js @@ -1,5 +1,6 @@ import { logLinesParser, + logLinesParserLegacy, updateIncrementalTrace, parseHeaderLine, parseLine, @@ -17,6 +18,7 @@ import { headerTraceIncremental, collapsibleTrace, collapsibleTraceIncremental, + multipleCollapsibleSectionsMockData, } from '../components/log/mock_data'; describe('Jobs Store Utils', () => { @@ -175,11 +177,11 @@ describe('Jobs Store Utils', () => { expect(isCollapsibleSection()).toEqual(false); }); }); - describe('logLinesParser', () => { + describe('logLinesParserLegacy', () => { let result; beforeEach(() => { - result = logLinesParser(utilsMockData); + result = logLinesParserLegacy(utilsMockData); }); describe('regular line', () => { @@ -216,6 +218,87 @@ describe('Jobs Store Utils', () => { }); }); + describe('logLinesParser', () => { + let result; + + beforeEach(() => { + result = logLinesParser(utilsMockData); + }); + + describe('regular line', () => { + it('adds a lineNumber property with correct index', () => { + expect(result.parsedLines[0].lineNumber).toEqual(1); + expect(result.parsedLines[1].line.lineNumber).toEqual(2); + }); + }); + + describe('collapsible section', () => { + it('adds a `isClosed` property', () => { + expect(result.parsedLines[1].isClosed).toEqual(false); + }); + + it('adds a `isHeader` property', () => { + expect(result.parsedLines[1].isHeader).toEqual(true); + }); + + it('creates a lines array property with the content of the collapsible section', () => { + expect(result.parsedLines[1].lines.length).toEqual(2); + expect(result.parsedLines[1].lines[0].content).toEqual(utilsMockData[2].content); + expect(result.parsedLines[1].lines[1].content).toEqual(utilsMockData[3].content); + }); + }); + + describe('section duration', () => { + it('adds the section information to the header section', () => { + expect(result.parsedLines[1].line.section_duration).toEqual( + utilsMockData[4].section_duration, + ); + }); + + it('does not add section duration as a line', () => { + expect(result.parsedLines[1].lines.includes(utilsMockData[4])).toEqual(false); + }); + }); + + describe('multiple collapsible sections', () => { + beforeEach(() => { + result = logLinesParser(multipleCollapsibleSectionsMockData); + }); + + it('should contain a section inside another section', () => { + const innerSection = [ + { + isClosed: false, + isHeader: true, + line: { + content: [{ text: '1st collapsible section' }], + lineNumber: 6, + offset: 1006, + section: 'collapsible-1', + section_duration: '01:00', + section_header: true, + }, + lines: [ + { + content: [ + { + text: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam lorem dolor, congue ac condimentum vitae', + }, + ], + lineNumber: 7, + offset: 1007, + section: 'collapsible-1', + }, + ], + }, + ]; + + expect(result.parsedLines[1].lines).toEqual(expect.arrayContaining(innerSection)); + }); + }); + }); + describe('findOffsetAndRemove', () => { describe('when last item is header', () => { const existingLog = [ @@ -391,7 +474,7 @@ describe('Jobs Store Utils', () => { describe('updateIncrementalTrace', () => { describe('without repeated section', () => { it('concats and parses both arrays', () => { - const oldLog = logLinesParser(originalTrace); + const oldLog = logLinesParserLegacy(originalTrace); const result = updateIncrementalTrace(regularIncremental, oldLog); expect(result).toEqual([ @@ -419,7 +502,7 @@ describe('Jobs Store Utils', () => { describe('with regular line repeated offset', () => { it('updates the last line and formats with the incremental part', () => { - const oldLog = logLinesParser(originalTrace); + const oldLog = logLinesParserLegacy(originalTrace); const result = updateIncrementalTrace(regularIncrementalRepeated, oldLog); expect(result).toEqual([ @@ -438,7 +521,7 @@ describe('Jobs Store Utils', () => { describe('with header line repeated', () => { it('updates the header line and formats with the incremental part', () => { - const oldLog = logLinesParser(headerTrace); + const oldLog = logLinesParserLegacy(headerTrace); const result = updateIncrementalTrace(headerTraceIncremental, oldLog); expect(result).toEqual([ @@ -464,7 +547,7 @@ describe('Jobs Store Utils', () => { describe('with collapsible line repeated', () => { it('updates the collapsible line and formats with the incremental part', () => { - const oldLog = logLinesParser(collapsibleTrace); + const oldLog = logLinesParserLegacy(collapsibleTrace); const result = updateIncrementalTrace(collapsibleTraceIncremental, oldLog); expect(result).toEqual([ |