Creates base components for new job log
Creates a link component, a line component and a clickable line component to handle the new job log format
This commit is contained in:
parent
0da3257c35
commit
be449e23e3
|
@ -0,0 +1,28 @@
|
||||||
|
<script>
|
||||||
|
import LineNumber from './line_number.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
LineNumber,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
line: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="line">
|
||||||
|
<line-number :line-number="line.lineNumber" :path="path" />
|
||||||
|
<span v-for="(content, i) in line.content" :key="i" class="line-text" :class="content.style">{{
|
||||||
|
content.text
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<script>
|
||||||
|
import Icon from '~/vue_shared/components/icon.vue';
|
||||||
|
import LineNumber from './line_number.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Icon,
|
||||||
|
LineNumber,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
line: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
isClosed: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
iconName() {
|
||||||
|
return this.isClosed ? 'angle-right' : 'angle-down';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleOnClick() {
|
||||||
|
this.$emit('toggleLine');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="line collapsible-line" role="button" @click="handleOnClick">
|
||||||
|
<icon :name="iconName" class="arrow" />
|
||||||
|
<line-number :line-number="line.lineNumber" :path="path" />
|
||||||
|
<span v-for="(content, i) in line.content" :key="i" class="line-text" :class="content.style">{{
|
||||||
|
content.text
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,52 @@
|
||||||
|
<script>
|
||||||
|
import { GlLink } from '@gitlab/ui';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GlLink,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
lineNumber: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* Builds the url for each line number
|
||||||
|
*
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
buildLineNumber() {
|
||||||
|
return `${this.path}#${this.lineNumberId}`;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Array indexes start with 0, so we add 1
|
||||||
|
* to create the line number
|
||||||
|
*
|
||||||
|
* @returns {Number} the line number
|
||||||
|
*/
|
||||||
|
parsedLineNumber() {
|
||||||
|
return this.lineNumber + 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the anchor for each link
|
||||||
|
*
|
||||||
|
* @returns {String}
|
||||||
|
*/
|
||||||
|
lineNumberId() {
|
||||||
|
return `L${this.parsedLineNumber}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<gl-link :id="lineNumberId" class="line-number" :href="buildLineNumber">{{
|
||||||
|
parsedLineNumber
|
||||||
|
}}</gl-link>
|
||||||
|
</template>
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Creates base components for the new job log
|
||||||
|
merge_request:
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { mount } from '@vue/test-utils';
|
||||||
|
import LineHeader from '~/jobs/components/log/line_header.vue';
|
||||||
|
import LineNumber from '~/jobs/components/log/line_number.vue';
|
||||||
|
|
||||||
|
describe('Job Log Header Line', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
line: {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
text: 'Running with gitlab-runner 12.1.0 (de7731dd)',
|
||||||
|
style: 'term-fg-l-green',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lineNumber: 0,
|
||||||
|
},
|
||||||
|
isClosed: true,
|
||||||
|
path: '/jashkenas/underscore/-/jobs/335',
|
||||||
|
};
|
||||||
|
|
||||||
|
const createComponent = (props = {}) => {
|
||||||
|
wrapper = mount(LineHeader, {
|
||||||
|
sync: false,
|
||||||
|
propsData: {
|
||||||
|
...props,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('line', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the line number component', () => {
|
||||||
|
expect(wrapper.contains(LineNumber)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a span the provided text', () => {
|
||||||
|
expect(wrapper.find('span').text()).toBe(data.line.content[0].text);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the provided style as a class attribute', () => {
|
||||||
|
expect(wrapper.find('span').classes()).toContain(data.line.content[0].style);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when isCloses is true', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent({ ...data, isClosed: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets icon name to be angle-right', () => {
|
||||||
|
expect(wrapper.vm.iconName).toEqual('angle-right');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when isCloses is false', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent({ ...data, isClosed: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets icon name to be angle-down', () => {
|
||||||
|
expect(wrapper.vm.iconName).toEqual('angle-down');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('on click', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits toggleLine event', () => {
|
||||||
|
wrapper.trigger('click');
|
||||||
|
|
||||||
|
expect(wrapper.emitted().toggleLine.length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import LineNumber from '~/jobs/components/log/line_number.vue';
|
||||||
|
|
||||||
|
describe('Job Log Line Number', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
lineNumber: 0,
|
||||||
|
path: '/jashkenas/underscore/-/jobs/335',
|
||||||
|
};
|
||||||
|
|
||||||
|
const createComponent = (props = {}) => {
|
||||||
|
wrapper = shallowMount(LineNumber, {
|
||||||
|
sync: false,
|
||||||
|
propsData: {
|
||||||
|
...props,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders incremented lineNunber by 1', () => {
|
||||||
|
expect(wrapper.text()).toBe('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders link with lineNumber as an ID', () => {
|
||||||
|
expect(wrapper.attributes().id).toBe('L1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('links to the provided path with line number as anchor', () => {
|
||||||
|
expect(wrapper.attributes().href).toBe(`${data.path}#L1`);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import Line from '~/jobs/components/log/line.vue';
|
||||||
|
import LineNumber from '~/jobs/components/log/line_number.vue';
|
||||||
|
|
||||||
|
describe('Job Log Line', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
line: {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
text: 'Running with gitlab-runner 12.1.0 (de7731dd)',
|
||||||
|
style: 'term-fg-l-green',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lineNumber: 0,
|
||||||
|
},
|
||||||
|
path: '/jashkenas/underscore/-/jobs/335',
|
||||||
|
};
|
||||||
|
|
||||||
|
const createComponent = (props = {}) => {
|
||||||
|
wrapper = shallowMount(Line, {
|
||||||
|
sync: false,
|
||||||
|
propsData: {
|
||||||
|
...props,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
createComponent(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
wrapper.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the line number component', () => {
|
||||||
|
expect(wrapper.contains(LineNumber)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a span the provided text', () => {
|
||||||
|
expect(wrapper.find('span').text()).toBe(data.line.content[0].text);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the provided style as a class attribute', () => {
|
||||||
|
expect(wrapper.find('span').classes()).toContain(data.line.content[0].style);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue