Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 12:55:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 12:55:51 +0300
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /spec/frontend/jobs
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (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.js1
-rw-r--r--spec/frontend/jobs/components/job_app_spec.js8
-rw-r--r--spec/frontend/jobs/components/log/collapsible_section_spec.js9
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js30
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js91
-rw-r--r--spec/frontend/jobs/components/log/mock_data.js65
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js15
-rw-r--r--spec/frontend/jobs/components/sidebar_detail_row_spec.js2
-rw-r--r--spec/frontend/jobs/store/mutations_spec.js94
-rw-r--r--spec/frontend/jobs/store/utils_spec.js95
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([