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:
Diffstat (limited to 'spec/frontend/ci/job_details/store/utils_spec.js')
-rw-r--r--spec/frontend/ci/job_details/store/utils_spec.js683
1 files changed, 232 insertions, 451 deletions
diff --git a/spec/frontend/ci/job_details/store/utils_spec.js b/spec/frontend/ci/job_details/store/utils_spec.js
index 8fc4eeb0ca8..6105c53a306 100644
--- a/spec/frontend/ci/job_details/store/utils_spec.js
+++ b/spec/frontend/ci/job_details/store/utils_spec.js
@@ -1,524 +1,305 @@
+import { logLinesParser } from '~/ci/job_details/store/utils';
+
import {
- logLinesParser,
- updateIncrementalJobLog,
- parseHeaderLine,
- parseLine,
- addDurationToHeader,
- isCollapsibleSection,
- findOffsetAndRemove,
- getNextLineNumber,
-} from '~/ci/job_details/store/utils';
-import {
- mockJobLog,
- originalTrace,
- regularIncremental,
- regularIncrementalRepeated,
- headerTrace,
- headerTraceIncremental,
- collapsibleTrace,
- collapsibleTraceIncremental,
+ mockJobLines,
+ mockEmptySection,
+ mockContentSection,
+ mockContentSectionClosed,
+ mockContentSectionHiddenDuration,
+ mockContentSubsection,
+ mockTruncatedBottomSection,
+ mockTruncatedTopSection,
} 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);
+ describe('logLinesParser', () => {
+ it('parses plain lines', () => {
+ const result = logLinesParser(mockJobLines);
- expect(parsedHeaderLine).toEqual({
- isClosed: false,
- isHeader: true,
- line: {
- ...headerLine,
- lineNumber: 2,
- },
- lines: [],
+ expect(result).toEqual({
+ lines: [
+ {
+ offset: 0,
+ content: [
+ {
+ text: 'Running with gitlab-runner 12.1.0 (de7731dd)',
+ style: 'term-fg-l-cyan term-bold',
+ },
+ ],
+ lineNumber: 1,
+ },
+ {
+ offset: 1001,
+ content: [{ text: ' on docker-auto-scale-com 8a6210b8' }],
+ lineNumber: 2,
+ },
+ ],
+ sections: {},
});
});
- 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);
- });
-
- it('expands all pre-closed sections if hash is present', () => {
- const headerLine = { content: [{ text: 'foo' }], section_options: { collapsed: 'true' } };
-
- const parsedHeaderLine = parseHeaderLine(headerLine, 2, '#L33');
-
- expect(parsedHeaderLine.isClosed).toBe(false);
- });
- });
-
- 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);
- });
- });
+ it('parses an empty section', () => {
+ const result = logLinesParser(mockEmptySection);
- 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' }],
+ expect(result).toEqual({
+ lines: [
+ {
+ offset: 1002,
+ content: [
+ {
+ text: 'Resolving secrets',
+ style: 'term-fg-l-cyan term-bold',
+ },
+ ],
+ lineNumber: 1,
+ section: 'resolve-secrets',
+ isHeader: true,
},
- lines: [],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- section: 'foo-bar',
- content: [{ text: 'foo' }],
+ ],
+ sections: {
+ 'resolve-secrets': {
+ startLineNumber: 1,
+ endLineNumber: 1,
+ duration: '00:00',
+ isClosed: false,
},
- 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' }],
+ it('parses a section with content', () => {
+ const result = logLinesParser(mockContentSection);
+
+ expect(result).toEqual({
+ lines: [
+ {
+ content: [{ text: 'Using Docker executor with image dev.gitlab.org3' }],
+ isHeader: true,
+ lineNumber: 1,
+ offset: 1004,
+ section: 'prepare-executor',
},
- lines: [],
- },
- {
- isClosed: false,
- isHeader: true,
- line: {
- section: 'foo-bar',
- content: [{ text: 'foo' }],
+ {
+ content: [{ text: 'Docker executor with image registry.gitlab.com ...' }],
+ lineNumber: 2,
+ offset: 1005,
+ section: 'prepare-executor',
+ },
+ {
+ content: [{ style: 'term-fg-l-green', text: 'Starting service ...' }],
+ lineNumber: 3,
+ offset: 1006,
+ section: 'prepare-executor',
+ },
+ ],
+ sections: {
+ 'prepare-executor': {
+ startLineNumber: 1,
+ endLineNumber: 3,
+ duration: '00:09',
+ isClosed: false,
},
- 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('logLinesParser', () => {
- let result;
-
- beforeEach(() => {
- result = logLinesParser(mockJobLog);
- });
-
- describe('regular line', () => {
- it('adds a lineNumber property with correct index', () => {
- expect(result[0].lineNumber).toEqual(1);
- expect(result[1].lineNumber).toEqual(2);
- expect(result[2].line.lineNumber).toEqual(3);
- expect(result[3].line.lineNumber).toEqual(4);
- expect(result[3].lines[0].lineNumber).toEqual(5);
- expect(result[3].lines[1].lineNumber).toEqual(6);
});
});
- describe('collapsible section', () => {
- it('adds a `isClosed` property', () => {
- expect(result[2].isClosed).toEqual(false);
- expect(result[3].isClosed).toEqual(false);
- });
-
- it('adds a `isHeader` property', () => {
- expect(result[2].isHeader).toEqual(true);
- expect(result[3].isHeader).toEqual(true);
- });
+ it('parses a closed section with content', () => {
+ const result = logLinesParser(mockContentSectionClosed);
- it('creates a lines array property with the content of the collapsible section', () => {
- expect(result[3].lines.length).toEqual(2);
- expect(result[3].lines[0].content).toEqual(mockJobLog[5].content);
- expect(result[3].lines[1].content).toEqual(mockJobLog[6].content);
+ expect(result.sections['mock-closed-section']).toMatchObject({
+ isClosed: true,
});
});
- describe('section duration', () => {
- it('adds the section information to the header section', () => {
- expect(result[2].line.section_duration).toEqual(mockJobLog[3].section_duration);
- expect(result[3].line.section_duration).toEqual(mockJobLog[7].section_duration);
- });
-
- it('does not add section duration as a line', () => {
- expect(result[2].lines.includes(mockJobLog[5])).toEqual(false);
- expect(result[3].lines.includes(mockJobLog[9])).toEqual(false);
- });
- });
- });
-
- 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([]);
- });
- });
+ it('parses a closed section as open when hash is present', () => {
+ const result = logLinesParser(mockContentSectionClosed, {}, '#L1');
- 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);
- });
+ expect(result.sections['mock-closed-section']).toMatchObject({
+ isClosed: false,
});
});
- 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' }] }];
+ it('parses a section with a hidden duration', () => {
+ const result = logLinesParser(mockContentSectionHiddenDuration);
- 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);
- });
+ expect(result.sections['mock-hidden-duration-section']).toMatchObject({
+ hideDuration: true,
+ duration: '00:09',
});
});
- describe('when no data is provided', () => {
- it('returns an empty array', () => {
- const result = findOffsetAndRemove();
- expect(result).toEqual([]);
- });
- });
- });
-
- describe('getNextLineNumber', () => {
- describe('when there is no previous log', () => {
- it('returns 1', () => {
- expect(getNextLineNumber([])).toEqual(1);
- expect(getNextLineNumber(undefined)).toEqual(1);
- });
- });
+ it('parses a section with a sub section', () => {
+ const result = logLinesParser(mockContentSubsection);
- describe('when last line is 1', () => {
- it('returns 1', () => {
- const log = [
+ expect(result).toEqual({
+ lines: [
{
- content: [],
+ offset: 0,
+ content: [{ text: 'Line 1' }],
lineNumber: 1,
+ section: 'mock-section',
+ isHeader: true,
},
- ];
-
- expect(getNextLineNumber(log)).toEqual(2);
- });
- });
-
- describe('with unnested line', () => {
- it('returns the lineNumber of the last item in the array', () => {
- const log = [
{
- content: [],
- lineNumber: 10,
+ offset: 1002,
+ content: [{ text: 'Line 2 - section content' }],
+ lineNumber: 2,
+ section: 'mock-section',
},
{
- content: [],
- lineNumber: 101,
+ offset: 1003,
+ content: [{ text: 'Line 3 - sub section header' }],
+ lineNumber: 3,
+ section: 'sub-section',
+ isHeader: true,
},
- ];
-
- expect(getNextLineNumber(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,
+ offset: 1004,
+ content: [{ text: 'Line 4 - sub section content' }],
+ lineNumber: 4,
+ section: 'sub-section',
},
{
+ offset: 1005,
+ content: [{ text: 'Line 5 - sub sub section header with no content' }],
+ lineNumber: 5,
+ section: 'sub-sub-section',
isHeader: true,
- line: {
- lineNumber: 101,
- content: [],
- },
- lines: [],
},
- ];
-
- expect(getNextLineNumber(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,
+ offset: 1007,
+ content: [{ text: 'Line 6 - sub section content 2' }],
+ lineNumber: 6,
+ section: 'sub-section',
},
{
- isHeader: true,
- line: {
- lineNumber: 101,
- content: [],
- },
- lines: [
- {
- lineNumber: 102,
- content: [],
- },
- { lineNumber: 103, content: [] },
- ],
+ offset: 1009,
+ content: [{ text: 'Line 7 - section content' }],
+ lineNumber: 7,
+ section: 'mock-section',
+ },
+ {
+ offset: 1011,
+ content: [{ text: 'Job succeeded' }],
+ lineNumber: 8,
+ },
+ ],
+ sections: {
+ 'mock-section': {
+ startLineNumber: 1,
+ endLineNumber: 7,
+ duration: '00:59',
+ isClosed: false,
},
- ];
+ 'sub-section': {
+ startLineNumber: 3,
+ endLineNumber: 6,
+ duration: '00:29',
+ isClosed: false,
+ },
+ 'sub-sub-section': {
+ startLineNumber: 5,
+ endLineNumber: 5,
+ duration: '00:00',
+ isClosed: false,
+ },
+ },
+ });
+ });
- expect(getNextLineNumber(log)).toEqual(104);
+ it('parsing repeated lines returns the same result', () => {
+ const result1 = logLinesParser(mockJobLines);
+ const result2 = logLinesParser(mockJobLines, {
+ currentLines: result1.lines,
+ currentSections: result1.sections,
});
+
+ // `toBe` is used to ensure objects do not change and trigger Vue reactivity
+ expect(result1.lines).toBe(result2.lines);
+ expect(result1.sections).toBe(result2.sections);
});
- });
- describe('updateIncrementalJobLog', () => {
- describe('without repeated section', () => {
- it('concats and parses both arrays', () => {
- const oldLog = logLinesParser(originalTrace);
- const result = updateIncrementalJobLog(regularIncremental, oldLog);
+ it('discards repeated lines and adds new ones', () => {
+ const result1 = logLinesParser(mockContentSection);
+ const result2 = logLinesParser(
+ [
+ ...mockContentSection,
+ {
+ content: [{ text: 'offset is too low, is ignored' }],
+ offset: 500,
+ },
+ {
+ content: [{ text: 'one new line' }],
+ offset: 1007,
+ },
+ ],
+ {
+ currentLines: result1.lines,
+ currentSections: result1.sections,
+ },
+ );
- expect(result).toEqual([
+ expect(result2).toEqual({
+ lines: [
{
- offset: 1,
- content: [
- {
- text: 'Downloading',
- },
- ],
+ content: [{ text: 'Using Docker executor with image dev.gitlab.org3' }],
+ isHeader: true,
lineNumber: 1,
+ offset: 1004,
+ section: 'prepare-executor',
},
{
- offset: 2,
- content: [
- {
- text: 'log line',
- },
- ],
+ content: [{ text: 'Docker executor with image registry.gitlab.com ...' }],
lineNumber: 2,
+ offset: 1005,
+ section: 'prepare-executor',
},
- ]);
- });
- });
-
- describe('with regular line repeated offset', () => {
- it('updates the last line and formats with the incremental part', () => {
- const oldLog = logLinesParser(originalTrace);
- const result = updateIncrementalJobLog(regularIncrementalRepeated, oldLog);
-
- expect(result).toEqual([
{
- offset: 1,
- content: [
- {
- text: 'log line',
- },
- ],
- lineNumber: 1,
+ content: [{ style: 'term-fg-l-green', text: 'Starting service ...' }],
+ lineNumber: 3,
+ offset: 1006,
+ section: 'prepare-executor',
+ },
+ {
+ content: [{ text: 'one new line' }],
+ lineNumber: 4,
+ offset: 1007,
},
- ]);
+ ],
+ sections: {
+ 'prepare-executor': {
+ startLineNumber: 1,
+ endLineNumber: 3,
+ duration: '00:09',
+ isClosed: false,
+ },
+ },
});
});
- describe('with header line repeated', () => {
- it('updates the header line and formats with the incremental part', () => {
- const oldLog = logLinesParser(headerTrace);
- const result = updateIncrementalJobLog(headerTraceIncremental, oldLog);
+ it('parses an interrupted job', () => {
+ const result = logLinesParser(mockTruncatedBottomSection);
- expect(result).toEqual([
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'updated log line',
- },
- ],
- section: 'section',
- lineNumber: 1,
- },
- lines: [],
- },
- ]);
+ expect(result.sections).toEqual({
+ 'mock-section': {
+ startLineNumber: 1,
+ endLineNumber: Infinity,
+ duration: null,
+ isClosed: false,
+ },
});
});
- describe('with collapsible line repeated', () => {
- it('updates the collapsible line and formats with the incremental part', () => {
- const oldLog = logLinesParser(collapsibleTrace);
- const result = updateIncrementalJobLog(collapsibleTraceIncremental, oldLog);
+ it('parses the ending of an incomplete section', () => {
+ const result = logLinesParser(mockTruncatedTopSection);
- expect(result).toEqual([
- {
- isClosed: false,
- isHeader: true,
- line: {
- offset: 1,
- section_header: true,
- content: [
- {
- text: 'log line',
- },
- ],
- section: 'section',
- lineNumber: 1,
- },
- lines: [
- {
- offset: 2,
- content: [
- {
- text: 'updated log line',
- },
- ],
- section: 'section',
- lineNumber: 2,
- },
- ],
- },
- ]);
+ expect(result.sections).toEqual({
+ 'mock-section': {
+ startLineNumber: 0,
+ endLineNumber: 2,
+ duration: '00:59',
+ isClosed: false,
+ },
});
});
});