gitlab-org--gitlab-foss/spec/frontend/jobs/store/utils_spec.js

601 lines
17 KiB
JavaScript

import {
logLinesParser,
logLinesParserLegacy,
updateIncrementalJobLog,
parseHeaderLine,
parseLine,
addDurationToHeader,
isCollapsibleSection,
findOffsetAndRemove,
getIncrementalLineNumber,
} from '~/jobs/store/utils';
import {
utilsMockData,
originalTrace,
regularIncremental,
regularIncrementalRepeated,
headerTrace,
headerTraceIncremental,
collapsibleTrace,
collapsibleTraceIncremental,
multipleCollapsibleSectionsMockData,
backwardsCompatibilityTrace,
} from '../components/log/mock_data';
describe('Jobs Store Utils', () => {
describe('parseHeaderLine', () => {
it('returns a new object with the header keys and the provided line parsed', () => {
const headerLine = { content: [{ text: 'foo' }] };
const parsedHeaderLine = parseHeaderLine(headerLine, 2);
expect(parsedHeaderLine).toEqual({
isClosed: false,
isHeader: true,
line: {
...headerLine,
lineNumber: 2,
},
lines: [],
});
});
it('pre-closes a section when specified in options', () => {
const headerLine = { content: [{ text: 'foo' }], section_options: { collapsed: 'true' } };
const parsedHeaderLine = parseHeaderLine(headerLine, 2);
expect(parsedHeaderLine.isClosed).toBe(true);
});
});
describe('parseLine', () => {
it('returns a new object with the lineNumber key added to the provided line object', () => {
const line = { content: [{ text: 'foo' }] };
const parsed = parseLine(line, 1);
expect(parsed.content).toEqual(line.content);
expect(parsed.lineNumber).toEqual(1);
});
});
describe('addDurationToHeader', () => {
const duration = {
offset: 106,
content: [],
section: 'prepare-script',
section_duration: '00:03',
};
it('adds the section duration to the correct header', () => {
const parsed = [
{
isClosed: false,
isHeader: true,
line: {
section: 'prepare-script',
content: [{ text: 'foo' }],
},
lines: [],
},
{
isClosed: false,
isHeader: true,
line: {
section: 'foo-bar',
content: [{ text: 'foo' }],
},
lines: [],
},
];
addDurationToHeader(parsed, duration);
expect(parsed[0].line.section_duration).toEqual(duration.section_duration);
expect(parsed[1].line.section_duration).toEqual(undefined);
});
it('does not add the section duration when the headers do not match', () => {
const parsed = [
{
isClosed: false,
isHeader: true,
line: {
section: 'bar-foo',
content: [{ text: 'foo' }],
},
lines: [],
},
{
isClosed: false,
isHeader: true,
line: {
section: 'foo-bar',
content: [{ text: 'foo' }],
},
lines: [],
},
];
addDurationToHeader(parsed, duration);
expect(parsed[0].line.section_duration).toEqual(undefined);
expect(parsed[1].line.section_duration).toEqual(undefined);
});
it('does not add when content has no headers', () => {
const parsed = [
{
section: 'bar-foo',
content: [{ text: 'foo' }],
lineNumber: 1,
},
{
section: 'foo-bar',
content: [{ text: 'foo' }],
lineNumber: 2,
},
];
addDurationToHeader(parsed, duration);
expect(parsed[0].line).toEqual(undefined);
expect(parsed[1].line).toEqual(undefined);
});
});
describe('isCollapsibleSection', () => {
const header = {
isHeader: true,
line: {
section: 'foo',
},
};
const line = {
lineNumber: 1,
section: 'foo',
content: [],
};
it('returns true when line belongs to the last section', () => {
expect(isCollapsibleSection([header], header, { section: 'foo', content: [] })).toEqual(true);
});
it('returns false when last line was not an header', () => {
expect(isCollapsibleSection([line], line, { section: 'bar' })).toEqual(false);
});
it('returns false when accumulator is empty', () => {
expect(isCollapsibleSection([], { isHeader: true }, { section: 'bar' })).toEqual(false);
});
it('returns false when section_duration is defined', () => {
expect(isCollapsibleSection([header], header, { section_duration: '10:00' })).toEqual(false);
});
it('returns false when `section` is not a match', () => {
expect(isCollapsibleSection([header], header, { section: 'bar' })).toEqual(false);
});
it('returns false when no parameters are provided', () => {
expect(isCollapsibleSection()).toEqual(false);
});
});
describe('logLinesParserLegacy', () => {
let result;
beforeEach(() => {
result = logLinesParserLegacy(utilsMockData);
});
describe('regular line', () => {
it('adds a lineNumber property with correct index', () => {
expect(result[0].lineNumber).toEqual(0);
expect(result[1].line.lineNumber).toEqual(1);
});
});
describe('collapsible section', () => {
it('adds a `isClosed` property', () => {
expect(result[1].isClosed).toEqual(false);
});
it('adds a `isHeader` property', () => {
expect(result[1].isHeader).toEqual(true);
});
it('creates a lines array property with the content of the collapsible section', () => {
expect(result[1].lines.length).toEqual(2);
expect(result[1].lines[0].content).toEqual(utilsMockData[2].content);
expect(result[1].lines[1].content).toEqual(utilsMockData[3].content);
});
});
describe('section duration', () => {
it('adds the section information to the header section', () => {
expect(result[1].line.section_duration).toEqual(utilsMockData[4].section_duration);
});
it('does not add section duration as a line', () => {
expect(result[1].lines.includes(utilsMockData[4])).toEqual(false);
});
});
});
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('backwards compatibility', () => {
beforeEach(() => {
result = logLinesParser(backwardsCompatibilityTrace);
});
it('should return an object with a parsedLines prop', () => {
expect(result).toEqual(
expect.objectContaining({
parsedLines: expect.any(Array),
}),
);
expect(result.parsedLines).toHaveLength(1);
});
});
});
describe('findOffsetAndRemove', () => {
describe('when last item is header', () => {
const existingLog = [
{
isHeader: true,
isClosed: false,
line: { content: [{ text: 'bar' }], offset: 10, lineNumber: 1 },
},
];
describe('and matches the offset', () => {
it('returns an array with the item removed', () => {
const newData = [{ offset: 10, content: [{ text: 'foobar' }] }];
const result = findOffsetAndRemove(newData, existingLog);
expect(result).toEqual([]);
});
});
describe('and does not match the offset', () => {
it('returns the provided existing log', () => {
const newData = [{ offset: 110, content: [{ text: 'foobar' }] }];
const result = findOffsetAndRemove(newData, existingLog);
expect(result).toEqual(existingLog);
});
});
});
describe('when last item is a regular line', () => {
const existingLog = [{ content: [{ text: 'bar' }], offset: 10, lineNumber: 1 }];
describe('and matches the offset', () => {
it('returns an array with the item removed', () => {
const newData = [{ offset: 10, content: [{ text: 'foobar' }] }];
const result = findOffsetAndRemove(newData, existingLog);
expect(result).toEqual([]);
});
});
describe('and does not match the fofset', () => {
it('returns the provided old log', () => {
const newData = [{ offset: 101, content: [{ text: 'foobar' }] }];
const result = findOffsetAndRemove(newData, existingLog);
expect(result).toEqual(existingLog);
});
});
});
describe('when last item is nested', () => {
const existingLog = [
{
isHeader: true,
isClosed: false,
lines: [{ offset: 101, content: [{ text: 'foobar' }], lineNumber: 2 }],
line: {
offset: 10,
lineNumber: 1,
section_duration: '10:00',
},
},
];
describe('and matches the offset', () => {
it('returns an array with the last nested line item removed', () => {
const newData = [{ offset: 101, content: [{ text: 'foobar' }] }];
const result = findOffsetAndRemove(newData, existingLog);
expect(result[0].lines).toEqual([]);
});
});
describe('and does not match the offset', () => {
it('returns the provided old log', () => {
const newData = [{ offset: 120, content: [{ text: 'foobar' }] }];
const result = findOffsetAndRemove(newData, existingLog);
expect(result).toEqual(existingLog);
});
});
});
describe('when no data is provided', () => {
it('returns an empty array', () => {
const result = findOffsetAndRemove();
expect(result).toEqual([]);
});
});
});
describe('getIncrementalLineNumber', () => {
describe('when last line is 0', () => {
it('returns 1', () => {
const log = [
{
content: [],
lineNumber: 0,
},
];
expect(getIncrementalLineNumber(log)).toEqual(1);
});
});
describe('with unnested line', () => {
it('returns the lineNumber of the last item in the array', () => {
const log = [
{
content: [],
lineNumber: 10,
},
{
content: [],
lineNumber: 101,
},
];
expect(getIncrementalLineNumber(log)).toEqual(102);
});
});
describe('when last line is the header section', () => {
it('returns the lineNumber of the last item in the array', () => {
const log = [
{
content: [],
lineNumber: 10,
},
{
isHeader: true,
line: {
lineNumber: 101,
content: [],
},
lines: [],
},
];
expect(getIncrementalLineNumber(log)).toEqual(102);
});
});
describe('when last line is a nested line', () => {
it('returns the lineNumber of the last item in the nested array', () => {
const log = [
{
content: [],
lineNumber: 10,
},
{
isHeader: true,
line: {
lineNumber: 101,
content: [],
},
lines: [
{
lineNumber: 102,
content: [],
},
{ lineNumber: 103, content: [] },
],
},
];
expect(getIncrementalLineNumber(log)).toEqual(104);
});
});
});
describe('updateIncrementalJobLog', () => {
describe('without repeated section', () => {
it('concats and parses both arrays', () => {
const oldLog = logLinesParserLegacy(originalTrace);
const result = updateIncrementalJobLog(regularIncremental, oldLog);
expect(result).toEqual([
{
offset: 1,
content: [
{
text: 'Downloading',
},
],
lineNumber: 0,
},
{
offset: 2,
content: [
{
text: 'log line',
},
],
lineNumber: 1,
},
]);
});
});
describe('with regular line repeated offset', () => {
it('updates the last line and formats with the incremental part', () => {
const oldLog = logLinesParserLegacy(originalTrace);
const result = updateIncrementalJobLog(regularIncrementalRepeated, oldLog);
expect(result).toEqual([
{
offset: 1,
content: [
{
text: 'log line',
},
],
lineNumber: 0,
},
]);
});
});
describe('with header line repeated', () => {
it('updates the header line and formats with the incremental part', () => {
const oldLog = logLinesParserLegacy(headerTrace);
const result = updateIncrementalJobLog(headerTraceIncremental, oldLog);
expect(result).toEqual([
{
isClosed: false,
isHeader: true,
line: {
offset: 1,
section_header: true,
content: [
{
text: 'updated log line',
},
],
section: 'section',
lineNumber: 0,
},
lines: [],
},
]);
});
});
describe('with collapsible line repeated', () => {
it('updates the collapsible line and formats with the incremental part', () => {
const oldLog = logLinesParserLegacy(collapsibleTrace);
const result = updateIncrementalJobLog(collapsibleTraceIncremental, oldLog);
expect(result).toEqual([
{
isClosed: false,
isHeader: true,
line: {
offset: 1,
section_header: true,
content: [
{
text: 'log line',
},
],
section: 'section',
lineNumber: 0,
},
lines: [
{
offset: 2,
content: [
{
text: 'updated log line',
},
],
section: 'section',
lineNumber: 1,
},
],
},
]);
});
});
});
});