Commit 1f829bfb authored by Jose Vargas's avatar Jose Vargas

Correct feature flag style inconsistencies

This also adds some more tests for the log specs
to ensure the new linesParser function works as intended
parent fad69502
<script>
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF } from '../../constants';
import LogLine from './line.vue';
import LogLineHeader from './line_header.vue';
......@@ -9,6 +11,7 @@ export default {
LogLineHeader,
CollapsibleLogSection: () => import('./collapsible_section.vue'),
},
mixins: [glFeatureFlagsMixin()],
props: {
section: {
type: Object,
......@@ -23,8 +26,8 @@ export default {
badgeDuration() {
return this.section.line && this.section.line.section_duration;
},
infinitelyNestedCollapsibleSections() {
return gon.features.infinitelyCollapsibleSections;
infinitelyCollapsibleSectionsFlag() {
return this.glFeatures?.[INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF];
},
},
methods: {
......@@ -44,7 +47,7 @@ export default {
@toggleLine="handleOnClickCollapsibleLine(section)"
/>
<template v-if="!section.isClosed">
<template v-if="infinitelyNestedCollapsibleSections">
<template v-if="infinitelyCollapsibleSectionsFlag">
<template v-for="line in section.lines">
<collapsible-log-section
v-if="line.isHeader"
......
<script>
import { INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF } from '../../constants';
export default {
functional: true,
props: {
......@@ -14,7 +16,7 @@ export default {
render(h, { props }) {
const { lineNumber, path } = props;
const parsedLineNumber = gon.features?.infinitelyCollapsibleSections
const parsedLineNumber = gon.features?.[INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF]
? lineNumber
: lineNumber + 1;
const lineId = `L${parsedLineNumber}`;
......
......@@ -24,3 +24,5 @@ export const JOB_RETRY_FORWARD_DEPLOYMENT_MODAL = {
};
export const SUCCESS_STATUS = 'SUCCESS';
export const INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF = 'infinitelyCollapsibleSections';
import Vue from 'vue';
import { INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF } from '../constants';
import * as types from './mutation_types';
import { logLinesParser, logLinesParserNew, updateIncrementalTrace } from './utils';
import { logLinesParser, logLinesParserLegacy, updateIncrementalTrace } from './utils';
export default {
[types.SET_JOB_ENDPOINT](state, endpoint) {
......@@ -20,7 +21,8 @@ export default {
},
[types.RECEIVE_TRACE_SUCCESS](state, log = {}) {
const infinitelyCollapsibleSectionsFlag = gon.features.infinitelyCollapsibleSections;
const infinitelyCollapsibleSectionsFlag =
gon.features?.[INFINITELY_NESTED_COLLAPSIBLE_SECTIONS_FF];
if (log.state) {
state.traceState = log.state;
}
......@@ -28,7 +30,7 @@ export default {
if (log.append) {
if (infinitelyCollapsibleSectionsFlag) {
if (log.lines) {
const parsedResult = logLinesParserNew(
const parsedResult = logLinesParser(
log.lines,
state.auxiliaryPartialTraceHelpers,
state.trace,
......@@ -48,11 +50,11 @@ export default {
// will be set to `null`
if (infinitelyCollapsibleSectionsFlag) {
const parsedResult = logLinesParserNew(log.lines);
const parsedResult = logLinesParser(log.lines);
state.trace = parsedResult.parsedLines;
state.auxiliaryPartialTraceHelpers = parsedResult.auxiliaryPartialTraceHelpers;
} else {
state.trace = log.lines ? logLinesParser(log.lines) : state.trace;
state.trace = log.lines ? logLinesParserLegacy(log.lines) : state.trace;
}
state.traceSize = log.size || state.traceSize;
......
......@@ -104,7 +104,7 @@ export const getIncrementalLineNumber = (acc) => {
* @param Array accumulator
* @returns Array parsed log lines
*/
export const logLinesParser = (lines = [], accumulator = []) =>
export const logLinesParserLegacy = (lines = [], accumulator = []) =>
lines.reduce(
(acc, line, index) => {
const lineNumber = accumulator.length > 0 ? getIncrementalLineNumber(acc) : index;
......@@ -131,7 +131,7 @@ export const logLinesParser = (lines = [], accumulator = []) =>
[...accumulator],
);
export const logLinesParserNew = (lines = [], previousTraceState = {}, prevParsedLines = []) => {
export const logLinesParser = (lines = [], previousTraceState = {}, prevParsedLines = []) => {
let currentLine = previousTraceState?.prevLineCount ? previousTraceState.prevLineCount : 0;
let currentHeader = previousTraceState?.currentHeader ? previousTraceState.currentHeader : null;
let isPreviousLineHeader = previousTraceState?.isPreviousLineHeader
......@@ -142,7 +142,7 @@ export const logLinesParserNew = (lines = [], previousTraceState = {}, prevParse
for (let i = 0; i < lines.length; i += 1) {
const line = lines[i];
// First runs we can use the current index, later runs we have to retrieve the last number of lines
// First run we can use the current index, later runs we have to retrieve the last number of lines
currentLine = previousTraceState?.prevLineCount ? currentLine + 1 : i + 1;
if (line.section_header && !isPreviousLineHeader) {
......@@ -156,9 +156,13 @@ export const logLinesParserNew = (lines = [], previousTraceState = {}, prevParse
sectionsQueue.push(currentHeader);
currentHeader = parseHeaderLine(line, currentLine); // Let's parse the incoming header line
} else if (line.section && !line.section_duration) {
// We're inside a collapsible section and want to parse a standard line
if (currentHeader?.index) {
// If the current section header is only an index, add the line as part of the lines
// array of the current collapsible section
parsedLines[currentHeader.index].lines.push(parseLine(line, currentLine));
} else {
// Otherwise add it to the innermost collapsible section lines array
currentHeader.lines.push(parseLine(line, currentLine));
}
} else if (line.section && line.section_duration) {
......@@ -246,5 +250,5 @@ export const findOffsetAndRemove = (newLog = [], oldParsed = []) => {
export const updateIncrementalTrace = (newLog = [], oldParsed = []) => {
const parsedLog = findOffsetAndRemove(newLog, oldParsed);
return logLinesParser(newLog, parsedLog);
return logLinesParserLegacy(newLog, parsedLog);
};
---
name: infinitely_collapsible_sections
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65496
rollout_issue_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335297
milestone: '14.1'
type: development
group: group::pipeline execution
......
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', () => {
......@@ -28,10 +28,90 @@ describe('Job Log', () => {
origGon = window.gon;
window.gon = { features: { infinitelyCollapsibleSections: false } }; // NOTE: This also passes with the feature flag set to ON
window.gon = { features: { infinitelyCollapsibleSections: false } };
state = {
trace: logLinesParser(jobLog),
trace: logLinesParserLegacy(jobLog),
traceEndpoint: 'jobs/id',
};
store = new Vuex.Store({
actions,
state,
});
createComponent();
});
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, 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',
};
......
import {
logLinesParser,
logLinesParserNew,
logLinesParserLegacy,
updateIncrementalTrace,
parseHeaderLine,
parseLine,
......@@ -177,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', () => {
......@@ -218,11 +218,11 @@ describe('Jobs Store Utils', () => {
});
});
describe('logLinesParserNew', () => {
describe('logLinesParser', () => {
let result;
beforeEach(() => {
result = logLinesParserNew(utilsMockData);
result = logLinesParser(utilsMockData);
});
describe('regular line', () => {
......@@ -262,7 +262,7 @@ describe('Jobs Store Utils', () => {
describe('multiple collapsible sections', () => {
beforeEach(() => {
result = logLinesParserNew(multipleCollapsibleSectionsMockData);
result = logLinesParser(multipleCollapsibleSectionsMockData);
});
it('should contain a section inside another section', () => {
......@@ -474,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([
......@@ -502,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([
......@@ -521,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([
......@@ -547,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([
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment