From 35694a76efbff0ebff57c1af7c6ecbc0a8365fc2 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed Date: Wed, 1 Aug 2018 17:11:29 +0200 Subject: [PATCH 1/4] Class to function. Half tests passing --- .../app/features/dashboard/shareModalCtrl.ts | 180 +++++++++--------- .../dashboard/specs/share_modal_ctrl.jest.ts | 154 +++++++++++++++ 2 files changed, 243 insertions(+), 91 deletions(-) create mode 100644 public/app/features/dashboard/specs/share_modal_ctrl.jest.ts diff --git a/public/app/features/dashboard/shareModalCtrl.ts b/public/app/features/dashboard/shareModalCtrl.ts index 985c20f03b2..c32c2a79190 100644 --- a/public/app/features/dashboard/shareModalCtrl.ts +++ b/public/app/features/dashboard/shareModalCtrl.ts @@ -2,120 +2,118 @@ import angular from 'angular'; import config from 'app/core/config'; import moment from 'moment'; -export class ShareModalCtrl { - /** @ngInject */ - constructor($scope, $rootScope, $location, $timeout, timeSrv, templateSrv, linkSrv) { - $scope.options = { - forCurrent: true, - includeTemplateVars: true, - theme: 'current', - }; - $scope.editor = { index: $scope.tabIndex || 0 }; +/** @ngInject */ +export function ShareModalCtrl($scope, $rootScope, $location, $timeout, timeSrv, templateSrv, linkSrv) { + $scope.options = { + forCurrent: true, + includeTemplateVars: true, + theme: 'current', + }; + $scope.editor = { index: $scope.tabIndex || 0 }; - $scope.init = function() { - $scope.modeSharePanel = $scope.panel ? true : false; + $scope.init = function() { + $scope.modeSharePanel = $scope.panel ? true : false; - $scope.tabs = [{ title: 'Link', src: 'shareLink.html' }]; + $scope.tabs = [{ title: 'Link', src: 'shareLink.html' }]; - if ($scope.modeSharePanel) { - $scope.modalTitle = 'Share Panel'; - $scope.tabs.push({ title: 'Embed', src: 'shareEmbed.html' }); - } else { - $scope.modalTitle = 'Share'; - } + if ($scope.modeSharePanel) { + $scope.modalTitle = 'Share Panel'; + $scope.tabs.push({ title: 'Embed', src: 'shareEmbed.html' }); + } else { + $scope.modalTitle = 'Share'; + } - if (!$scope.dashboard.meta.isSnapshot) { - $scope.tabs.push({ title: 'Snapshot', src: 'shareSnapshot.html' }); - } + if (!$scope.dashboard.meta.isSnapshot) { + $scope.tabs.push({ title: 'Snapshot', src: 'shareSnapshot.html' }); + } - if (!$scope.dashboard.meta.isSnapshot && !$scope.modeSharePanel) { - $scope.tabs.push({ title: 'Export', src: 'shareExport.html' }); - } + if (!$scope.dashboard.meta.isSnapshot && !$scope.modeSharePanel) { + $scope.tabs.push({ title: 'Export', src: 'shareExport.html' }); + } - $scope.buildUrl(); - }; + $scope.buildUrl(); + }; - $scope.buildUrl = function() { - var baseUrl = $location.absUrl(); - var queryStart = baseUrl.indexOf('?'); + $scope.buildUrl = function() { + var baseUrl = $location.absUrl(); + var queryStart = baseUrl.indexOf('?'); - if (queryStart !== -1) { - baseUrl = baseUrl.substring(0, queryStart); - } + if (queryStart !== -1) { + baseUrl = baseUrl.substring(0, queryStart); + } - var params = angular.copy($location.search()); + var params = angular.copy($location.search()); - var range = timeSrv.timeRange(); - params.from = range.from.valueOf(); - params.to = range.to.valueOf(); - params.orgId = config.bootData.user.orgId; + var range = timeSrv.timeRange(); + params.from = range.from.valueOf(); + params.to = range.to.valueOf(); + params.orgId = config.bootData.user.orgId; - if ($scope.options.includeTemplateVars) { - templateSrv.fillVariableValuesForUrl(params); - } + if ($scope.options.includeTemplateVars) { + templateSrv.fillVariableValuesForUrl(params); + } - if (!$scope.options.forCurrent) { - delete params.from; - delete params.to; - } + if (!$scope.options.forCurrent) { + delete params.from; + delete params.to; + } - if ($scope.options.theme !== 'current') { - params.theme = $scope.options.theme; - } + if ($scope.options.theme !== 'current') { + params.theme = $scope.options.theme; + } - if ($scope.modeSharePanel) { - params.panelId = $scope.panel.id; - params.fullscreen = true; - } else { - delete params.panelId; - delete params.fullscreen; - } - - $scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params); - - var soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/'); - soloUrl = soloUrl.replace(config.appSubUrl + '/d/', config.appSubUrl + '/d-solo/'); + if ($scope.modeSharePanel) { + params.panelId = $scope.panel.id; + params.fullscreen = true; + } else { + delete params.panelId; delete params.fullscreen; - delete params.edit; - soloUrl = linkSrv.addParamsToUrl(soloUrl, params); + } - $scope.iframeHtml = ''; + $scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params); - $scope.imageUrl = soloUrl.replace( - config.appSubUrl + '/dashboard-solo/', - config.appSubUrl + '/render/dashboard-solo/' - ); - $scope.imageUrl = $scope.imageUrl.replace(config.appSubUrl + '/d-solo/', config.appSubUrl + '/render/d-solo/'); - $scope.imageUrl += '&width=1000&height=500' + $scope.getLocalTimeZone(); - }; + var soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/'); + soloUrl = soloUrl.replace(config.appSubUrl + '/d/', config.appSubUrl + '/d-solo/'); + delete params.fullscreen; + delete params.edit; + soloUrl = linkSrv.addParamsToUrl(soloUrl, params); - // This function will try to return the proper full name of the local timezone - // Chrome does not handle the timezone offset (but phantomjs does) - $scope.getLocalTimeZone = function() { - let utcOffset = '&tz=UTC' + encodeURIComponent(moment().format('Z')); + $scope.iframeHtml = ''; - // Older browser does not the internationalization API - if (!(window).Intl) { - return utcOffset; - } + $scope.imageUrl = soloUrl.replace( + config.appSubUrl + '/dashboard-solo/', + config.appSubUrl + '/render/dashboard-solo/' + ); + $scope.imageUrl = $scope.imageUrl.replace(config.appSubUrl + '/d-solo/', config.appSubUrl + '/render/d-solo/'); + $scope.imageUrl += '&width=1000&height=500' + $scope.getLocalTimeZone(); + }; - const dateFormat = (window).Intl.DateTimeFormat(); - if (!dateFormat.resolvedOptions) { - return utcOffset; - } + // This function will try to return the proper full name of the local timezone + // Chrome does not handle the timezone offset (but phantomjs does) + $scope.getLocalTimeZone = function() { + let utcOffset = '&tz=UTC' + encodeURIComponent(moment().format('Z')); - const options = dateFormat.resolvedOptions(); - if (!options.timeZone) { - return utcOffset; - } + // Older browser does not the internationalization API + if (!(window).Intl) { + return utcOffset; + } - return '&tz=' + encodeURIComponent(options.timeZone); - }; + const dateFormat = (window).Intl.DateTimeFormat(); + if (!dateFormat.resolvedOptions) { + return utcOffset; + } - $scope.getShareUrl = function() { - return $scope.shareUrl; - }; - } + const options = dateFormat.resolvedOptions(); + if (!options.timeZone) { + return utcOffset; + } + + return '&tz=' + encodeURIComponent(options.timeZone); + }; + + $scope.getShareUrl = function() { + return $scope.shareUrl; + }; } angular.module('grafana.controllers').controller('ShareModalCtrl', ShareModalCtrl); diff --git a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts new file mode 100644 index 00000000000..47b2a2189cd --- /dev/null +++ b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts @@ -0,0 +1,154 @@ +import '../shareModalCtrl'; +import { ShareModalCtrl } from '../shareModalCtrl'; +import config from 'app/core/config'; +import { LinkSrv } from 'app/features/panellinks/link_srv'; + +describe('ShareModalCtrl', () => { + var ctx = { + timeSrv: { + timeRange: () => { + return { from: new Date(1000), to: new Date(2000) }; + }, + }, + $location: { + absUrl: () => 'http://server/#!/test', + search: () => { + return { from: '', to: '' }; + }, + }, + scope: { + dashboard: { + meta: { + isSnapshot: true, + }, + }, + }, + templateSrv: { + fillVariableValuesForUrl: () => {}, + }, + }; + // function setTime(range) { + // ctx.timeSrv.timeRange = () => range; + // } + + beforeEach(() => { + config.bootData = { + user: { + orgId: 1, + }, + }; + }); + + // setTime({ from: new Date(1000), to: new Date(2000) }); + + // beforeEach(angularMocks.module('grafana.controllers')); + // beforeEach(angularMocks.module('grafana.services')); + // beforeEach( + // angularMocks.module(function($compileProvider) { + // $compileProvider.preAssignBindingsEnabled(true); + // }) + // ); + + // beforeEach(ctx.providePhase()); + + // beforeEach(ctx.createControllerPhase('ShareModalCtrl')); + beforeEach(() => { + ctx.ctrl = new ShareModalCtrl( + ctx.scope, + {}, + ctx.$location, + {}, + ctx.timeSrv, + ctx.templateSrv, + new LinkSrv({}, ctx.stimeSrv) + ); + }); + + describe('shareUrl with current time range and panel', () => { + it('should generate share url absolute time', () => { + // ctx.$location.path('/test'); + ctx.scope.panel = { id: 22 }; + + ctx.scope.init(); + expect(ctx.scope.shareUrl).toBe('http://server/#!/test?from=1000&to=2000&orgId=1&panelId=22&fullscreen'); + }); + + it('should generate render url', () => { + ctx.$location.absUrl = () => 'http://dashboards.grafana.com/d/abcdefghi/my-dash'; + + ctx.scope.panel = { id: 22 }; + + ctx.scope.init(); + var base = 'http://dashboards.grafana.com/render/d-solo/abcdefghi/my-dash'; + var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC'; + expect(ctx.scope.imageUrl).toContain(base + params); + }); + + it('should generate render url for scripted dashboard', () => { + ctx.$location.absUrl = () => 'http://dashboards.grafana.com/dashboard/script/my-dash.js'; + + ctx.scope.panel = { id: 22 }; + + ctx.scope.init(); + var base = 'http://dashboards.grafana.com/render/dashboard-solo/script/my-dash.js'; + var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC'; + expect(ctx.scope.imageUrl).toContain(base + params); + }); + + it('should remove panel id when no panel in scope', () => { + // ctx.$location.path('/test'); + ctx.$location.absUrl = () => 'http://server/#!/test'; + ctx.scope.options.forCurrent = true; + ctx.scope.panel = null; + + ctx.scope.init(); + expect(ctx.scope.shareUrl).toBe('http://server/#!/test?from=1000&to=2000&orgId=1'); + }); + + it('should add theme when specified', () => { + // ctx.$location.path('/test'); + ctx.scope.options.theme = 'light'; + ctx.scope.panel = null; + + ctx.scope.init(); + expect(ctx.scope.shareUrl).toBe('http://server/#!/test?from=1000&to=2000&orgId=1&theme=light'); + }); + + it('should remove fullscreen from image url when is first param in querystring and modeSharePanel is true', () => { + ctx.$location.absUrl = () => 'http://server/#!/test?fullscreen&edit'; + ctx.scope.modeSharePanel = true; + ctx.scope.panel = { id: 1 }; + + ctx.scope.buildUrl(); + + expect(ctx.scope.shareUrl).toContain('?fullscreen&edit&from=1000&to=2000&orgId=1&panelId=1'); + expect(ctx.scope.imageUrl).toContain('?from=1000&to=2000&orgId=1&panelId=1&width=1000&height=500&tz=UTC'); + }); + + it('should remove edit from image url when is first param in querystring and modeSharePanel is true', () => { + ctx.$location.absUrl = () => 'http://server/#!/test?edit&fullscreen'; + ctx.scope.modeSharePanel = true; + ctx.scope.panel = { id: 1 }; + + ctx.scope.buildUrl(); + + expect(ctx.scope.shareUrl).toContain('?edit&fullscreen&from=1000&to=2000&orgId=1&panelId=1'); + expect(ctx.scope.imageUrl).toContain('?from=1000&to=2000&orgId=1&panelId=1&width=1000&height=500&tz=UTC'); + }); + + it('should include template variables in url', () => { + ctx.$location.absUrl = () => 'http://server/#!/test'; + ctx.scope.options.includeTemplateVars = true; + + ctx.templateSrv.fillVariableValuesForUrl = function(params) { + params['var-app'] = 'mupp'; + params['var-server'] = 'srv-01'; + }; + + ctx.scope.buildUrl(); + expect(ctx.scope.shareUrl).toContain( + 'http://server/#!/test?from=1000&to=2000&orgId=1&var-app=mupp&var-server=srv-01' + ); + }); + }); +}); From 38422ce8a4128da4c4ff7370d5a3e7becaf0e588 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed Date: Fri, 3 Aug 2018 14:37:31 +0200 Subject: [PATCH 2/4] All tests passing --- .../dashboard/specs/share_modal_ctrl.jest.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts index 47b2a2189cd..31f09a6c08a 100644 --- a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts +++ b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts @@ -27,6 +27,14 @@ describe('ShareModalCtrl', () => { fillVariableValuesForUrl: () => {}, }, }; + + (window).Intl.DateTimeFormat = () => { + return { + resolvedOptions: () => { + return { timeZone: 'UTC' }; + }, + }; + }; // function setTime(range) { // ctx.timeSrv.timeRange = () => range; // } @@ -48,10 +56,6 @@ describe('ShareModalCtrl', () => { // $compileProvider.preAssignBindingsEnabled(true); // }) // ); - - // beforeEach(ctx.providePhase()); - - // beforeEach(ctx.createControllerPhase('ShareModalCtrl')); beforeEach(() => { ctx.ctrl = new ShareModalCtrl( ctx.scope, @@ -115,6 +119,9 @@ describe('ShareModalCtrl', () => { }); it('should remove fullscreen from image url when is first param in querystring and modeSharePanel is true', () => { + ctx.$location.search = () => { + return { fullscreen: true, edit: true }; + }; ctx.$location.absUrl = () => 'http://server/#!/test?fullscreen&edit'; ctx.scope.modeSharePanel = true; ctx.scope.panel = { id: 1 }; @@ -126,6 +133,9 @@ describe('ShareModalCtrl', () => { }); it('should remove edit from image url when is first param in querystring and modeSharePanel is true', () => { + ctx.$location.search = () => { + return { edit: true, fullscreen: true }; + }; ctx.$location.absUrl = () => 'http://server/#!/test?edit&fullscreen'; ctx.scope.modeSharePanel = true; ctx.scope.panel = { id: 1 }; @@ -137,6 +147,9 @@ describe('ShareModalCtrl', () => { }); it('should include template variables in url', () => { + ctx.$location.search = () => { + return {}; + }; ctx.$location.absUrl = () => 'http://server/#!/test'; ctx.scope.options.includeTemplateVars = true; From be7b663369386689a62801b06bfaaafabaff8e52 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed Date: Fri, 3 Aug 2018 14:40:44 +0200 Subject: [PATCH 3/4] Cleanup --- .../dashboard/specs/share_modal_ctrl.jest.ts | 16 --- .../dashboard/specs/share_modal_ctrl_specs.ts | 122 ------------------ 2 files changed, 138 deletions(-) delete mode 100644 public/app/features/dashboard/specs/share_modal_ctrl_specs.ts diff --git a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts index 31f09a6c08a..e5b5340aca5 100644 --- a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts +++ b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts @@ -35,9 +35,6 @@ describe('ShareModalCtrl', () => { }, }; }; - // function setTime(range) { - // ctx.timeSrv.timeRange = () => range; - // } beforeEach(() => { config.bootData = { @@ -45,18 +42,7 @@ describe('ShareModalCtrl', () => { orgId: 1, }, }; - }); - // setTime({ from: new Date(1000), to: new Date(2000) }); - - // beforeEach(angularMocks.module('grafana.controllers')); - // beforeEach(angularMocks.module('grafana.services')); - // beforeEach( - // angularMocks.module(function($compileProvider) { - // $compileProvider.preAssignBindingsEnabled(true); - // }) - // ); - beforeEach(() => { ctx.ctrl = new ShareModalCtrl( ctx.scope, {}, @@ -100,7 +86,6 @@ describe('ShareModalCtrl', () => { }); it('should remove panel id when no panel in scope', () => { - // ctx.$location.path('/test'); ctx.$location.absUrl = () => 'http://server/#!/test'; ctx.scope.options.forCurrent = true; ctx.scope.panel = null; @@ -110,7 +95,6 @@ describe('ShareModalCtrl', () => { }); it('should add theme when specified', () => { - // ctx.$location.path('/test'); ctx.scope.options.theme = 'light'; ctx.scope.panel = null; diff --git a/public/app/features/dashboard/specs/share_modal_ctrl_specs.ts b/public/app/features/dashboard/specs/share_modal_ctrl_specs.ts deleted file mode 100644 index fc70a54a41c..00000000000 --- a/public/app/features/dashboard/specs/share_modal_ctrl_specs.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { describe, beforeEach, it, expect, sinon, angularMocks } from 'test/lib/common'; -import helpers from 'test/specs/helpers'; -import '../shareModalCtrl'; -import config from 'app/core/config'; -import 'app/features/panellinks/link_srv'; - -describe('ShareModalCtrl', function() { - var ctx = new helpers.ControllerTestContext(); - - function setTime(range) { - ctx.timeSrv.timeRange = sinon.stub().returns(range); - } - - beforeEach(function() { - config.bootData = { - user: { - orgId: 1, - }, - }; - }); - - setTime({ from: new Date(1000), to: new Date(2000) }); - - beforeEach(angularMocks.module('grafana.controllers')); - beforeEach(angularMocks.module('grafana.services')); - beforeEach( - angularMocks.module(function($compileProvider) { - $compileProvider.preAssignBindingsEnabled(true); - }) - ); - - beforeEach(ctx.providePhase()); - - beforeEach(ctx.createControllerPhase('ShareModalCtrl')); - - describe('shareUrl with current time range and panel', function() { - it('should generate share url absolute time', function() { - ctx.$location.path('/test'); - ctx.scope.panel = { id: 22 }; - - ctx.scope.init(); - expect(ctx.scope.shareUrl).to.be('http://server/#!/test?from=1000&to=2000&orgId=1&panelId=22&fullscreen'); - }); - - it('should generate render url', function() { - ctx.$location.$$absUrl = 'http://dashboards.grafana.com/d/abcdefghi/my-dash'; - - ctx.scope.panel = { id: 22 }; - - ctx.scope.init(); - var base = 'http://dashboards.grafana.com/render/d-solo/abcdefghi/my-dash'; - var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC'; - expect(ctx.scope.imageUrl).to.contain(base + params); - }); - - it('should generate render url for scripted dashboard', function() { - ctx.$location.$$absUrl = 'http://dashboards.grafana.com/dashboard/script/my-dash.js'; - - ctx.scope.panel = { id: 22 }; - - ctx.scope.init(); - var base = 'http://dashboards.grafana.com/render/dashboard-solo/script/my-dash.js'; - var params = '?from=1000&to=2000&orgId=1&panelId=22&width=1000&height=500&tz=UTC'; - expect(ctx.scope.imageUrl).to.contain(base + params); - }); - - it('should remove panel id when no panel in scope', function() { - ctx.$location.path('/test'); - ctx.scope.options.forCurrent = true; - ctx.scope.panel = null; - - ctx.scope.init(); - expect(ctx.scope.shareUrl).to.be('http://server/#!/test?from=1000&to=2000&orgId=1'); - }); - - it('should add theme when specified', function() { - ctx.$location.path('/test'); - ctx.scope.options.theme = 'light'; - ctx.scope.panel = null; - - ctx.scope.init(); - expect(ctx.scope.shareUrl).to.be('http://server/#!/test?from=1000&to=2000&orgId=1&theme=light'); - }); - - it('should remove fullscreen from image url when is first param in querystring and modeSharePanel is true', function() { - ctx.$location.url('/test?fullscreen&edit'); - ctx.scope.modeSharePanel = true; - ctx.scope.panel = { id: 1 }; - - ctx.scope.buildUrl(); - - expect(ctx.scope.shareUrl).to.contain('?fullscreen&edit&from=1000&to=2000&orgId=1&panelId=1'); - expect(ctx.scope.imageUrl).to.contain('?from=1000&to=2000&orgId=1&panelId=1&width=1000&height=500&tz=UTC'); - }); - - it('should remove edit from image url when is first param in querystring and modeSharePanel is true', function() { - ctx.$location.url('/test?edit&fullscreen'); - ctx.scope.modeSharePanel = true; - ctx.scope.panel = { id: 1 }; - - ctx.scope.buildUrl(); - - expect(ctx.scope.shareUrl).to.contain('?edit&fullscreen&from=1000&to=2000&orgId=1&panelId=1'); - expect(ctx.scope.imageUrl).to.contain('?from=1000&to=2000&orgId=1&panelId=1&width=1000&height=500&tz=UTC'); - }); - - it('should include template variables in url', function() { - ctx.$location.path('/test'); - ctx.scope.options.includeTemplateVars = true; - - ctx.templateSrv.fillVariableValuesForUrl = function(params) { - params['var-app'] = 'mupp'; - params['var-server'] = 'srv-01'; - }; - - ctx.scope.buildUrl(); - expect(ctx.scope.shareUrl).to.be( - 'http://server/#!/test?from=1000&to=2000&orgId=1&var-app=mupp&var-server=srv-01' - ); - }); - }); -}); From fa6d25af72f8191dc67f2948c6748def69b1a8c1 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed Date: Fri, 3 Aug 2018 14:44:40 +0200 Subject: [PATCH 4/4] Remove comment --- public/app/features/dashboard/specs/share_modal_ctrl.jest.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts index e5b5340aca5..35261256566 100644 --- a/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts +++ b/public/app/features/dashboard/specs/share_modal_ctrl.jest.ts @@ -56,7 +56,6 @@ describe('ShareModalCtrl', () => { describe('shareUrl with current time range and panel', () => { it('should generate share url absolute time', () => { - // ctx.$location.path('/test'); ctx.scope.panel = { id: 22 }; ctx.scope.init();