summaryrefslogtreecommitdiff
path: root/spec/frontend/serverless/components
diff options
context:
space:
mode:
authorLuke Bennett <lukeeeebennettplus@gmail.com>2019-04-07 03:26:58 +0100
committerLuke Bennett <lbennett@gitlab.com>2019-04-07 12:25:06 +0100
commit97b8853d617060fe38c861360181ef83321727e2 (patch)
treeb090ec78e998455fb008ff4034afca83ffee8012 /spec/frontend/serverless/components
parentc62ef08a40b6213b8df3fe47a1c6104d0d693a8e (diff)
downloadgitlab-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')
-rw-r--r--spec/frontend/serverless/components/area_spec.js121
-rw-r--r--spec/frontend/serverless/components/environment_row_spec.js70
-rw-r--r--spec/frontend/serverless/components/function_details_spec.js113
-rw-r--r--spec/frontend/serverless/components/function_row_spec.js26
-rw-r--r--spec/frontend/serverless/components/functions_spec.js101
-rw-r--r--spec/frontend/serverless/components/missing_prometheus_spec.js37
-rw-r--r--spec/frontend/serverless/components/pod_box_spec.js22
-rw-r--r--spec/frontend/serverless/components/url_spec.js24
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();
+ });
+});