diff options
author | Luke Bennett <lukeeeebennettplus@gmail.com> | 2019-04-07 03:26:58 +0100 |
---|---|---|
committer | Luke Bennett <lbennett@gitlab.com> | 2019-04-07 12:25:06 +0100 |
commit | 97b8853d617060fe38c861360181ef83321727e2 (patch) | |
tree | b090ec78e998455fb008ff4034afca83ffee8012 /spec/frontend/serverless/components | |
parent | c62ef08a40b6213b8df3fe47a1c6104d0d693a8e (diff) | |
download | gitlab-ce-97b8853d617060fe38c861360181ef83321727e2.tar.gz |
Move karma serverless tests to jest for isolation
These tests cause master failures because of an overflow
in vue-test-utils sync watcher setup.
Diffstat (limited to 'spec/frontend/serverless/components')
8 files changed, 514 insertions, 0 deletions
diff --git a/spec/frontend/serverless/components/area_spec.js b/spec/frontend/serverless/components/area_spec.js new file mode 100644 index 00000000000..2be6ac3d268 --- /dev/null +++ b/spec/frontend/serverless/components/area_spec.js @@ -0,0 +1,121 @@ +import { shallowMount } from '@vue/test-utils'; +import Area from '~/serverless/components/area.vue'; +import { mockNormalizedMetrics } from '../mock_data'; + +describe('Area component', () => { + const mockWidgets = 'mockWidgets'; + const mockGraphData = mockNormalizedMetrics; + let areaChart; + + beforeEach(() => { + areaChart = shallowMount(Area, { + propsData: { + graphData: mockGraphData, + containerWidth: 0, + }, + slots: { + default: mockWidgets, + }, + }); + }); + + afterEach(() => { + areaChart.destroy(); + }); + + it('renders chart title', () => { + expect(areaChart.find({ ref: 'graphTitle' }).text()).toBe(mockGraphData.title); + }); + + it('contains graph widgets from slot', () => { + expect(areaChart.find({ ref: 'graphWidgets' }).text()).toBe(mockWidgets); + }); + + describe('methods', () => { + describe('formatTooltipText', () => { + const mockDate = mockNormalizedMetrics.queries[0].result[0].values[0].time; + const generateSeriesData = type => ({ + seriesData: [ + { + componentSubType: type, + value: [mockDate, 4], + }, + ], + value: mockDate, + }); + + describe('series is of line type', () => { + beforeEach(() => { + areaChart.vm.formatTooltipText(generateSeriesData('line')); + }); + + it('formats tooltip title', () => { + expect(areaChart.vm.tooltipPopoverTitle).toBe('28 Feb 2019, 11:11AM'); + }); + + it('formats tooltip content', () => { + expect(areaChart.vm.tooltipPopoverContent).toBe('Invocations (requests): 4'); + }); + }); + + it('verify default interval value of 1', () => { + expect(areaChart.vm.getInterval).toBe(1); + }); + }); + + describe('onResize', () => { + const mockWidth = 233; + + beforeEach(() => { + spyOn(Element.prototype, 'getBoundingClientRect').and.callFake(() => ({ + width: mockWidth, + })); + areaChart.vm.onResize(); + }); + + it('sets area chart width', () => { + expect(areaChart.vm.width).toBe(mockWidth); + }); + }); + }); + + describe('computed', () => { + describe('chartData', () => { + it('utilizes all data points', () => { + expect(Object.keys(areaChart.vm.chartData)).toEqual(['requests']); + expect(areaChart.vm.chartData.requests.length).toBe(2); + }); + + it('creates valid data', () => { + const data = areaChart.vm.chartData.requests; + + expect( + data.filter( + datum => new Date(datum.time).getTime() > 0 && typeof datum.value === 'number', + ).length, + ).toBe(data.length); + }); + }); + + describe('generateSeries', () => { + it('utilizes correct time data', () => { + expect(areaChart.vm.generateSeries.data).toEqual([ + ['2019-02-28T11:11:38.756Z', 0], + ['2019-02-28T11:12:38.756Z', 0], + ]); + }); + }); + + describe('xAxisLabel', () => { + it('constructs a label for the chart x-axis', () => { + expect(areaChart.vm.xAxisLabel).toBe('invocations / minute'); + }); + }); + + describe('yAxisLabel', () => { + it('constructs a label for the chart y-axis', () => { + expect(areaChart.vm.yAxisLabel).toBe('Invocations (requests)'); + }); + }); + }); +}); diff --git a/spec/frontend/serverless/components/environment_row_spec.js b/spec/frontend/serverless/components/environment_row_spec.js new file mode 100644 index 00000000000..932d712dbec --- /dev/null +++ b/spec/frontend/serverless/components/environment_row_spec.js @@ -0,0 +1,70 @@ +import environmentRowComponent from '~/serverless/components/environment_row.vue'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; + +import { mockServerlessFunctions, mockServerlessFunctionsDiffEnv } from '../mock_data'; +import { translate } from '~/serverless/utils'; + +const createComponent = (localVue, env, envName) => + shallowMount(environmentRowComponent, { localVue, propsData: { env, envName } }).vm; + +describe('environment row component', () => { + describe('default global cluster case', () => { + let localVue; + let vm; + + beforeEach(() => { + localVue = createLocalVue(); + vm = createComponent(localVue, translate(mockServerlessFunctions)['*'], '*'); + }); + + afterEach(() => vm.$destroy()); + + it('has the correct envId', () => { + expect(vm.envId).toEqual('env-global'); + }); + + it('is open by default', () => { + expect(vm.isOpenClass).toEqual({ 'is-open': true }); + }); + + it('generates correct output', () => { + expect(vm.$el.id).toEqual('env-global'); + expect(vm.$el.classList.contains('is-open')).toBe(true); + expect(vm.$el.querySelector('div.title').innerHTML.trim()).toEqual('*'); + }); + + it('opens and closes correctly', () => { + expect(vm.isOpen).toBe(true); + + vm.toggleOpen(); + + expect(vm.isOpen).toBe(false); + }); + }); + + describe('default named cluster case', () => { + let vm; + let localVue; + + beforeEach(() => { + localVue = createLocalVue(); + vm = createComponent(localVue, translate(mockServerlessFunctionsDiffEnv).test, 'test'); + }); + + afterEach(() => vm.$destroy()); + + it('has the correct envId', () => { + expect(vm.envId).toEqual('env-test'); + }); + + it('is open by default', () => { + expect(vm.isOpenClass).toEqual({ 'is-open': true }); + }); + + it('generates correct output', () => { + expect(vm.$el.id).toEqual('env-test'); + expect(vm.$el.classList.contains('is-open')).toBe(true); + expect(vm.$el.querySelector('div.title').innerHTML.trim()).toEqual('test'); + }); + }); +}); diff --git a/spec/frontend/serverless/components/function_details_spec.js b/spec/frontend/serverless/components/function_details_spec.js new file mode 100644 index 00000000000..a29d4a296ef --- /dev/null +++ b/spec/frontend/serverless/components/function_details_spec.js @@ -0,0 +1,113 @@ +import Vuex from 'vuex'; + +import functionDetailsComponent from '~/serverless/components/function_details.vue'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { createStore } from '~/serverless/store'; + +describe('functionDetailsComponent', () => { + let localVue; + let component; + let store; + + beforeEach(() => { + localVue = createLocalVue(); + localVue.use(Vuex); + + store = createStore(); + }); + + afterEach(() => { + component.vm.$destroy(); + }); + + describe('Verify base functionality', () => { + const serviceStub = { + name: 'test', + description: 'a description', + environment: '*', + url: 'http://service.com/test', + namespace: 'test-ns', + podcount: 0, + metricsUrl: '/metrics', + }; + + it('has a name, description, URL, and no pods loaded', () => { + component = shallowMount(functionDetailsComponent, { + localVue, + store, + propsData: { + func: serviceStub, + hasPrometheus: false, + clustersPath: '/clusters', + helpPath: '/help', + }, + }); + + expect( + component.vm.$el.querySelector('.serverless-function-name').innerHTML.trim(), + ).toContain('test'); + + expect( + component.vm.$el.querySelector('.serverless-function-description').innerHTML.trim(), + ).toContain('a description'); + + expect(component.vm.$el.querySelector('p').innerHTML.trim()).toContain( + 'No pods loaded at this time.', + ); + }); + + it('has a pods loaded', () => { + serviceStub.podcount = 1; + + component = shallowMount(functionDetailsComponent, { + localVue, + store, + propsData: { + func: serviceStub, + hasPrometheus: false, + clustersPath: '/clusters', + helpPath: '/help', + }, + }); + + expect(component.vm.$el.querySelector('p').innerHTML.trim()).toContain('1 pod in use'); + }); + + it('has multiple pods loaded', () => { + serviceStub.podcount = 3; + + component = shallowMount(functionDetailsComponent, { + localVue, + store, + propsData: { + func: serviceStub, + hasPrometheus: false, + clustersPath: '/clusters', + helpPath: '/help', + }, + }); + + expect(component.vm.$el.querySelector('p').innerHTML.trim()).toContain('3 pods in use'); + }); + + it('can support a missing description', () => { + serviceStub.description = null; + + component = shallowMount(functionDetailsComponent, { + localVue, + store, + propsData: { + func: serviceStub, + hasPrometheus: false, + clustersPath: '/clusters', + helpPath: '/help', + }, + }); + + expect( + component.vm.$el.querySelector('.serverless-function-description').querySelector('div') + .innerHTML.length, + ).toEqual(0); + }); + }); +}); diff --git a/spec/frontend/serverless/components/function_row_spec.js b/spec/frontend/serverless/components/function_row_spec.js new file mode 100644 index 00000000000..3987e1753bd --- /dev/null +++ b/spec/frontend/serverless/components/function_row_spec.js @@ -0,0 +1,26 @@ +import functionRowComponent from '~/serverless/components/function_row.vue'; +import { shallowMount } from '@vue/test-utils'; + +import { mockServerlessFunction } from '../mock_data'; + +const createComponent = func => shallowMount(functionRowComponent, { propsData: { func } }).vm; + +describe('functionRowComponent', () => { + it('Parses the function details correctly', () => { + const vm = createComponent(mockServerlessFunction); + + expect(vm.$el.querySelector('b').innerHTML).toEqual(mockServerlessFunction.name); + expect(vm.$el.querySelector('span').innerHTML).toEqual(mockServerlessFunction.image); + expect(vm.$el.querySelector('timeago-stub').getAttribute('time')).not.toBe(null); + + vm.$destroy(); + }); + + it('handles clicks correctly', () => { + const vm = createComponent(mockServerlessFunction); + + expect(vm.checkClass(vm.$el.querySelector('p'))).toBe(true); // check somewhere inside the row + + vm.$destroy(); + }); +}); diff --git a/spec/frontend/serverless/components/functions_spec.js b/spec/frontend/serverless/components/functions_spec.js new file mode 100644 index 00000000000..c32978ea58a --- /dev/null +++ b/spec/frontend/serverless/components/functions_spec.js @@ -0,0 +1,101 @@ +import Vuex from 'vuex'; + +import functionsComponent from '~/serverless/components/functions.vue'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import { createStore } from '~/serverless/store'; +import { mockServerlessFunctions } from '../mock_data'; + +describe('functionsComponent', () => { + let component; + let store; + let localVue; + + beforeEach(() => { + localVue = createLocalVue(); + localVue.use(Vuex); + + store = createStore(); + }); + + afterEach(() => { + component.vm.$destroy(); + }); + + it('should render empty state when Knative is not installed', () => { + component = shallowMount(functionsComponent, { + localVue, + store, + propsData: { + installed: false, + clustersPath: '', + helpPath: '', + statusPath: '', + }, + sync: false, + }); + + expect(component.vm.$el.querySelector('emptystate-stub')).not.toBe(null); + }); + + it('should render a loading component', () => { + store.dispatch('requestFunctionsLoading'); + component = shallowMount(functionsComponent, { + localVue, + store, + propsData: { + installed: true, + clustersPath: '', + helpPath: '', + statusPath: '', + }, + sync: false, + }); + + expect(component.vm.$el.querySelector('glloadingicon-stub')).not.toBe(null); + }); + + it('should render empty state when there is no function data', () => { + store.dispatch('receiveFunctionsNoDataSuccess'); + component = shallowMount(functionsComponent, { + localVue, + store, + propsData: { + installed: true, + clustersPath: '', + helpPath: '', + statusPath: '', + }, + sync: false, + }); + + expect( + component.vm.$el + .querySelector('.empty-state, .js-empty-state') + .classList.contains('js-empty-state'), + ).toBe(true); + + expect(component.vm.$el.querySelector('.state-title, .text-center').innerHTML.trim()).toEqual( + 'No functions available', + ); + }); + + it('should render the functions list', () => { + component = shallowMount(functionsComponent, { + localVue, + store, + propsData: { + installed: true, + clustersPath: '', + helpPath: '', + statusPath: '', + }, + sync: false, + }); + + component.vm.$store.dispatch('receiveFunctionsSuccess', mockServerlessFunctions); + + return component.vm.$nextTick().then(() => { + expect(component.vm.$el.querySelector('environmentrow-stub')).not.toBe(null); + }); + }); +}); diff --git a/spec/frontend/serverless/components/missing_prometheus_spec.js b/spec/frontend/serverless/components/missing_prometheus_spec.js new file mode 100644 index 00000000000..77aca03772b --- /dev/null +++ b/spec/frontend/serverless/components/missing_prometheus_spec.js @@ -0,0 +1,37 @@ +import missingPrometheusComponent from '~/serverless/components/missing_prometheus.vue'; +import { shallowMount } from '@vue/test-utils'; + +const createComponent = missingData => + shallowMount(missingPrometheusComponent, { + propsData: { + clustersPath: '/clusters', + helpPath: '/help', + missingData, + }, + }).vm; + +describe('missingPrometheusComponent', () => { + let vm; + + afterEach(() => { + vm.$destroy(); + }); + + it('should render missing prometheus message', () => { + vm = createComponent(false); + + expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain( + 'Function invocation metrics require Prometheus to be installed first.', + ); + + expect(vm.$el.querySelector('glbutton-stub').getAttribute('variant')).toEqual('success'); + }); + + it('should render no prometheus data message', () => { + vm = createComponent(true); + + expect(vm.$el.querySelector('.state-description').innerHTML.trim()).toContain( + 'Invocation metrics loading or not available at this time.', + ); + }); +}); diff --git a/spec/frontend/serverless/components/pod_box_spec.js b/spec/frontend/serverless/components/pod_box_spec.js new file mode 100644 index 00000000000..69ac1a2bb5f --- /dev/null +++ b/spec/frontend/serverless/components/pod_box_spec.js @@ -0,0 +1,22 @@ +import podBoxComponent from '~/serverless/components/pod_box.vue'; +import { shallowMount } from '@vue/test-utils'; + +const createComponent = count => + shallowMount(podBoxComponent, { + propsData: { + count, + }, + }).vm; + +describe('podBoxComponent', () => { + it('should render three boxes', () => { + const count = 3; + const vm = createComponent(count); + const rects = vm.$el.querySelectorAll('rect'); + + expect(rects.length).toEqual(3); + expect(parseInt(rects[2].getAttribute('x'), 10)).toEqual(40); + + vm.$destroy(); + }); +}); diff --git a/spec/frontend/serverless/components/url_spec.js b/spec/frontend/serverless/components/url_spec.js new file mode 100644 index 00000000000..08c3e4146b1 --- /dev/null +++ b/spec/frontend/serverless/components/url_spec.js @@ -0,0 +1,24 @@ +import Vue from 'vue'; +import urlComponent from '~/serverless/components/url.vue'; +import { shallowMount } from '@vue/test-utils'; + +const createComponent = uri => + shallowMount(Vue.extend(urlComponent), { + propsData: { + uri, + }, + }).vm; + +describe('urlComponent', () => { + it('should render correctly', () => { + const uri = 'http://testfunc.apps.example.com'; + const vm = createComponent(uri); + + expect(vm.$el.classList.contains('clipboard-group')).toBe(true); + expect(vm.$el.querySelector('clipboardbutton-stub').getAttribute('text')).toEqual(uri); + + expect(vm.$el.querySelector('.url-text-field').innerHTML).toEqual(uri); + + vm.$destroy(); + }); +}); |