Commit 4aa227dd by Torkel Ödegaard Committed by GitHub

[Tech]: Start migrating to Jest for tests (#9610)

* tech: investigating karma + jest mix

* tech: migrating tests to jest

* tech: moved anoter test file to jest

* test: migrated two more test files to jest

* test: updated readme and made test fail to verify that it causes CI build failure

* tech: added code coverage for jest tests

* tech: testing codecov coverage

* tech: migrated more tests

* tech: migrated template srv to typescript and the tests to jest

* tech: minor build fix

* tech: build fixes

* build: another attempt at fixing go test with coverage
parent c4365e22
...@@ -12,6 +12,8 @@ awsconfig ...@@ -12,6 +12,8 @@ awsconfig
/tmp /tmp
vendor/phantomjs/phantomjs vendor/phantomjs/phantomjs
vendor/phantomjs/phantomjs.exe vendor/phantomjs/phantomjs.exe
profile.out
coverage.txt
docs/AWS_S3_BUCKET docs/AWS_S3_BUCKET
docs/GIT_BRANCH docs/GIT_BRANCH
......
...@@ -22,9 +22,10 @@ module.exports = function (grunt) { ...@@ -22,9 +22,10 @@ module.exports = function (grunt) {
} }
} }
config.coverage = grunt.option('coverage');
config.phjs = grunt.option('phjsToRelease'); config.phjs = grunt.option('phjsToRelease');
config.pkg.version = grunt.option('pkgVer') || config.pkg.version; config.pkg.version = grunt.option('pkgVer') || config.pkg.version;
console.log('Version', config.pkg.version); console.log('Version', config.pkg.version);
// load plugins // load plugins
......
[Grafana](https://grafana.com) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [![Go Report Card](https://goreportcard.com/badge/github.com/grafana/grafana)](https://goreportcard.com/report/github.com/grafana/grafana) [Grafana](https://grafana.com) [![Circle CI](https://circleci.com/gh/grafana/grafana.svg?style=svg)](https://circleci.com/gh/grafana/grafana) [![Go Report Card](https://goreportcard.com/badge/github.com/grafana/grafana)](https://goreportcard.com/report/github.com/grafana/grafana) [![codecov](https://codecov.io/gh/grafana/grafana/branch/master/graph/badge.svg)](https://codecov.io/gh/grafana/grafana)
================ ================
[Website](https://grafana.com) | [Website](https://grafana.com) |
[Twitter](https://twitter.com/grafana) | [Twitter](https://twitter.com/grafana) |
...@@ -81,6 +81,20 @@ You only need to add the options you want to override. Config files are applied ...@@ -81,6 +81,20 @@ You only need to add the options you want to override. Config files are applied
In your custom.ini uncomment (remove the leading `;`) sign. And set `app_mode = development`. In your custom.ini uncomment (remove the leading `;`) sign. And set `app_mode = development`.
### Running tests
- You can run backend Golang tests using "go test ./pkg/...".
- Execute all frontend tests with "npm run test"
Writing & watching frontend tests (we have two test runners)
- jest for all new tests that do not require browser context (React+more)
- Start watcher: `npm run jest`
- Jest will run all test files that end with the name ".jest.ts"
- karma + mocha is used for testing angularjs components. We do want to migrate these test to jest over time (if possible).
- Start watcher: `npm run karma`
- Karma+Mocha runs all files that end with the name "_specs.ts".
## Contribute ## Contribute
If you have any idea for an improvement or found a bug do not hesitate to open an issue. If you have any idea for an improvement or found a bug do not hesitate to open an issue.
...@@ -89,8 +103,8 @@ the kickass metrics & devops dashboard we all dream about! ...@@ -89,8 +103,8 @@ the kickass metrics & devops dashboard we all dream about!
## Plugin development ## Plugin development
Checkout the [Plugin Development Guide](http://docs.grafana.org/plugins/developing/development/) and checkout the [PLUGIN_DEV.md](https://github.com/grafana/grafana/blob/master/PLUGIN_DEV.md) file for changes in Grafana that relate to Checkout the [Plugin Development Guide](http://docs.grafana.org/plugins/developing/development/) and checkout the [PLUGIN_DEV.md](https://github.com/grafana/grafana/blob/master/PLUGIN_DEV.md) file for changes in Grafana that relate to
plugin development. plugin development.
## License ## License
......
...@@ -84,6 +84,20 @@ bra run ...@@ -84,6 +84,20 @@ bra run
You'll also need to run `npm run watch` to watch for changes to the front-end (typescript, html, sass) You'll also need to run `npm run watch` to watch for changes to the front-end (typescript, html, sass)
### Running tests
- You can run backend Golang tests using "go test ./pkg/...".
- Execute all frontend tests with "npm run test"
Writing & watching frontend tests (we have two test runners)
- jest for all new tests that do not require browser context (React+more)
- Start watcher: `npm run jest`
- Jest will run all test files that end with the name ".jest.ts"
- karma + mocha is used for testing angularjs components. We do want to migrate these test to jest over time (if possible).
- Start watcher: `npm run karma`
- Karma+Mocha runs all files that end with the name "_specs.ts".
## Creating optimized release packages ## Creating optimized release packages
This step builds linux packages and requires that fpm is installed. Install fpm via `gem install fpm`. This step builds linux packages and requires that fpm is installed. Install fpm via `gem install fpm`.
......
module.exports = {
verbose: false,
"transform": {
"^.+\\.tsx?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"moduleDirectories": ["<rootDir>node_modules", "<rootDir>/public"],
"roots": [
"<rootDir>/public"
],
"testRegex": "(\\.|/)(jest)\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json"
],
"setupFiles": [
"./public/test/jest-shim.ts",
"./public/test/jest-setup.ts"
]
};
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
"devDependencies": { "devDependencies": {
"@types/d3": "^4.10.1", "@types/d3": "^4.10.1",
"@types/enzyme": "^2.8.9", "@types/enzyme": "^2.8.9",
"@types/jest": "^21.1.4",
"@types/node": "^8.0.31", "@types/node": "^8.0.31",
"@types/react": "^16.0.5", "@types/react": "^16.0.5",
"@types/react-dom": "^15.5.4", "@types/react-dom": "^15.5.4",
...@@ -22,8 +23,8 @@ ...@@ -22,8 +23,8 @@
"babel-loader": "^7.1.2", "babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1", "babel-preset-es2015": "^6.24.1",
"css-loader": "^0.28.7", "css-loader": "^0.28.7",
"enzyme": "^3.0.0", "enzyme": "^3.1.0",
"enzyme-adapter-react-16": "^1.0.0", "enzyme-adapter-react-16": "^1.0.1",
"es6-promise": "^3.0.2", "es6-promise": "^3.0.2",
"es6-shim": "^0.35.3", "es6-shim": "^0.35.3",
"expect.js": "~0.2.0", "expect.js": "~0.2.0",
...@@ -53,11 +54,11 @@ ...@@ -53,11 +54,11 @@
"html-loader": "^0.5.1", "html-loader": "^0.5.1",
"html-webpack-plugin": "^2.30.1", "html-webpack-plugin": "^2.30.1",
"husky": "^0.14.3", "husky": "^0.14.3",
"jest": "^21.2.1",
"jshint-stylish": "~2.2.1", "jshint-stylish": "~2.2.1",
"json-loader": "^0.5.7", "json-loader": "^0.5.7",
"karma": "1.7.0", "karma": "1.7.0",
"karma-chrome-launcher": "~2.2.0", "karma-chrome-launcher": "~2.2.0",
"karma-coverage": "1.1.1",
"karma-expect": "~1.1.3", "karma-expect": "~1.1.3",
"karma-mocha": "~1.3.0", "karma-mocha": "~1.3.0",
"karma-phantomjs-launcher": "1.0.4", "karma-phantomjs-launcher": "1.0.4",
...@@ -82,6 +83,7 @@ ...@@ -82,6 +83,7 @@
"sinon": "1.17.6", "sinon": "1.17.6",
"systemjs": "0.20.19", "systemjs": "0.20.19",
"systemjs-plugin-css": "^0.1.36", "systemjs-plugin-css": "^0.1.36",
"ts-jest": "^21.1.3",
"ts-loader": "^2.3.7", "ts-loader": "^2.3.7",
"tslint": "^5.7.0", "tslint": "^5.7.0",
"tslint-loader": "^3.5.3", "tslint-loader": "^3.5.3",
...@@ -97,8 +99,10 @@ ...@@ -97,8 +99,10 @@
"watch": "./node_modules/.bin/webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js", "watch": "./node_modules/.bin/webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
"build": "./node_modules/.bin/grunt build", "build": "./node_modules/.bin/grunt build",
"test": "./node_modules/.bin/grunt test", "test": "./node_modules/.bin/grunt test",
"test-ci": "./node_modules/.bin/grunt test --coverage=true",
"lint": "./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --type-check", "lint": "./node_modules/.bin/tslint -c tslint.json --project tsconfig.json --type-check",
"watch-test": "./node_modules/grunt-cli/bin/grunt karma:dev" "karma": "./node_modules/grunt-cli/bin/grunt karma:dev",
"jest": "./node_modules/jest-cli/bin/jest --notify --watch"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
......
import { react2AngularDirective } from 'app/core/utils/react2angular';
import { PasswordStrength } from './ui/PasswordStrength';
export function registerAngularDirectives() {
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
}
...@@ -43,9 +43,11 @@ import {assignModelProperties} from './utils/model_utils'; ...@@ -43,9 +43,11 @@ import {assignModelProperties} from './utils/model_utils';
import {contextSrv} from './services/context_srv'; import {contextSrv} from './services/context_srv';
import {KeybindingSrv} from './services/keybindingSrv'; import {KeybindingSrv} from './services/keybindingSrv';
import {helpModal} from './components/help/help'; import {helpModal} from './components/help/help';
import {PasswordStrength} from './components/PasswordStrength';
import {JsonExplorer} from './components/json_explorer/json_explorer'; import {JsonExplorer} from './components/json_explorer/json_explorer';
import {NavModelSrv, NavModel} from './nav_model_srv'; import {NavModelSrv, NavModel} from './nav_model_srv';
import {registerAngularDirectives} from './angular_wrappers';
registerAngularDirectives();
export { export {
arrayJoin, arrayJoin,
...@@ -71,5 +73,4 @@ export { ...@@ -71,5 +73,4 @@ export {
JsonExplorer, JsonExplorer,
NavModelSrv, NavModelSrv,
NavModel, NavModel,
PasswordStrength,
}; };
...@@ -7,6 +7,8 @@ define([ ...@@ -7,6 +7,8 @@ define([
function (angular, require, coreModule, kbn) { function (angular, require, coreModule, kbn) {
'use strict'; 'use strict';
kbn = kbn.default;
coreModule.default.directive('tip', function($compile) { coreModule.default.directive('tip', function($compile) {
return { return {
restrict: 'E', restrict: 'E',
......
define([ define([
'../core_module', '../core_module',
'app/core/utils/kbn',
'app/core/utils/rangeutil', 'app/core/utils/rangeutil',
], ],
function (coreModule, kbn, rangeUtil) { function (coreModule, rangeUtil) {
'use strict'; 'use strict';
coreModule.default.directive('ngModelOnblur', function() { coreModule.default.directive('ngModelOnblur', function() {
......
import React from 'react'; import React from 'react';
import {describe, it, expect} from 'test/lib/common';
import {shallow} from 'enzyme'; import {shallow} from 'enzyme';
import {PasswordStrength} from '../components/PasswordStrength'; import {PasswordStrength} from '../ui/PasswordStrength';
describe('PasswordStrength', () => { describe('PasswordStrength', () => {
it('should have class bad if length below 4', () => { it('should have class bad if length below 4', () => {
const wrapper = shallow(<PasswordStrength password="asd" />); const wrapper = shallow(<PasswordStrength password="asd" />);
expect(wrapper.find(".password-strength-bad")).to.have.length(1); expect(wrapper.find(".password-strength-bad")).toHaveLength(1);
}); });
it('should have class ok if length below 8', () => { it('should have class ok if length below 8', () => {
const wrapper = shallow(<PasswordStrength password="asdasd" />); const wrapper = shallow(<PasswordStrength password="asdasd" />);
expect(wrapper.find(".password-strength-ok")).to.have.length(1); expect(wrapper.find(".password-strength-ok")).toHaveLength(1);
}); });
it('should have class good if length above 8', () => { it('should have class good if length above 8', () => {
const wrapper = shallow(<PasswordStrength password="asdaasdda" />); const wrapper = shallow(<PasswordStrength password="asdaasdda" />);
expect(wrapper.find(".password-strength-good")).to.have.length(1); expect(wrapper.find(".password-strength-good")).toHaveLength(1);
}); });
}); });
......
import {describe, beforeEach, afterEach, it, sinon, expect} from 'test/lib/common'; import sinon from 'sinon';
import * as dateMath from 'app/core/utils/datemath'; import * as dateMath from 'app/core/utils/datemath';
import moment from 'moment'; import moment from 'moment';
...@@ -13,25 +13,25 @@ describe("DateMath", () => { ...@@ -13,25 +13,25 @@ describe("DateMath", () => {
describe('errors', () => { describe('errors', () => {
it('should return undefined if passed something falsy', () => { it('should return undefined if passed something falsy', () => {
expect(dateMath.parse(false)).to.be(undefined); expect(dateMath.parse(false)).toBe(undefined);
}); });
it('should return undefined if I pass an operator besides [+-/]', () => { it('should return undefined if I pass an operator besides [+-/]', () => {
expect(dateMath.parse('now&1d')).to.be(undefined); expect(dateMath.parse('now&1d')).toBe(undefined);
}); });
it('should return undefined if I pass a unit besides' + spans.toString(), () => { it('should return undefined if I pass a unit besides' + spans.toString(), () => {
expect(dateMath.parse('now+5f')).to.be(undefined); expect(dateMath.parse('now+5f')).toBe(undefined);
}); });
it('should return undefined if rounding unit is not 1', () => { it('should return undefined if rounding unit is not 1', () => {
expect(dateMath.parse('now/2y')).to.be(undefined); expect(dateMath.parse('now/2y')).toBe(undefined);
expect(dateMath.parse('now/0.5y')).to.be(undefined); expect(dateMath.parse('now/0.5y')).toBe(undefined);
}); });
it('should not go into an infinite loop when missing a unit', () => { it('should not go into an infinite loop when missing a unit', () => {
expect(dateMath.parse('now-0')).to.be(undefined); expect(dateMath.parse('now-0')).toBe(undefined);
expect(dateMath.parse('now-00')).to.be(undefined); expect(dateMath.parse('now-00')).toBe(undefined);
}); });
}); });
...@@ -43,7 +43,7 @@ describe("DateMath", () => { ...@@ -43,7 +43,7 @@ describe("DateMath", () => {
expected.setMilliseconds(0); expected.setMilliseconds(0);
var startOfDay = dateMath.parse('now/d', false).valueOf(); var startOfDay = dateMath.parse('now/d', false).valueOf();
expect(startOfDay).to.be(expected.getTime()); expect(startOfDay).toBe(expected.getTime());
}); });
it("now/d on a utc dashboard should be start of the current day in UTC time", () => { it("now/d on a utc dashboard should be start of the current day in UTC time", () => {
...@@ -51,7 +51,7 @@ describe("DateMath", () => { ...@@ -51,7 +51,7 @@ describe("DateMath", () => {
var expected = new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0)); var expected = new Date(Date.UTC(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0));
var startOfDay = dateMath.parse('now/d', false, 'utc').valueOf(); var startOfDay = dateMath.parse('now/d', false, 'utc').valueOf();
expect(startOfDay).to.be(expected.getTime()); expect(startOfDay).toBe(expected.getTime());
}); });
describe('subtraction', () => { describe('subtraction', () => {
...@@ -69,11 +69,11 @@ describe("DateMath", () => { ...@@ -69,11 +69,11 @@ describe("DateMath", () => {
var thenEx = anchor + '||-5' + span; var thenEx = anchor + '||-5' + span;
it('should return 5' + span + ' ago', () => { it('should return 5' + span + ' ago', () => {
expect(dateMath.parse(nowEx).format(format)).to.eql(now.subtract(5, span).format(format)); expect(dateMath.parse(nowEx).format(format)).toEqual(now.subtract(5, span).format(format));
}); });
it('should return 5' + span + ' before ' + anchor, () => { it('should return 5' + span + ' before ' + anchor, () => {
expect(dateMath.parse(thenEx).format(format)).to.eql(anchored.subtract(5, span).format(format)); expect(dateMath.parse(thenEx).format(format)).toEqual(anchored.subtract(5, span).format(format));
}); });
}); });
...@@ -94,11 +94,11 @@ describe("DateMath", () => { ...@@ -94,11 +94,11 @@ describe("DateMath", () => {
_.each(spans, (span) => { _.each(spans, (span) => {
it('should round now to the beginning of the ' + span, function () { it('should round now to the beginning of the ' + span, function () {
expect(dateMath.parse('now/' + span).format(format)).to.eql(now.startOf(span).format(format)); expect(dateMath.parse('now/' + span).format(format)).toEqual(now.startOf(span).format(format));
}); });
it('should round now to the end of the ' + span, function () { it('should round now to the end of the ' + span, function () {
expect(dateMath.parse('now/' + span, true).format(format)).to.eql(now.endOf(span).format(format)); expect(dateMath.parse('now/' + span, true).format(format)).toEqual(now.endOf(span).format(format));
}); });
}); });
...@@ -109,27 +109,27 @@ describe("DateMath", () => { ...@@ -109,27 +109,27 @@ describe("DateMath", () => {
describe('isValid', () => { describe('isValid', () => {
it('should return false when invalid date text', () => { it('should return false when invalid date text', () => {
expect(dateMath.isValid('asd')).to.be(false); expect(dateMath.isValid('asd')).toBe(false);
}); });
it('should return true when valid date text', () => { it('should return true when valid date text', () => {
expect(dateMath.isValid('now-1h')).to.be(true); expect(dateMath.isValid('now-1h')).toBe(true);
}); });
}); });
describe('relative time to date parsing', function() { describe('relative time to date parsing', function() {
it('should handle negative time', function() { it('should handle negative time', function() {
var date = dateMath.parseDateMath('-2d', moment([2014, 1, 5])); var date = dateMath.parseDateMath('-2d', moment([2014, 1, 5]));
expect(date.valueOf()).to.equal(moment([2014, 1, 3]).valueOf()); expect(date.valueOf()).toEqual(moment([2014, 1, 3]).valueOf());
}); });
it('should handle multiple math expressions', function() { it('should handle multiple math expressions', function() {
var date = dateMath.parseDateMath('-2d-6h', moment([2014, 1, 5])); var date = dateMath.parseDateMath('-2d-6h', moment([2014, 1, 5]));
expect(date.valueOf()).to.equal(moment([2014, 1, 2, 18]).valueOf()); expect(date.valueOf()).toEqual(moment([2014, 1, 2, 18]).valueOf());
}); });
it('should return false when invalid expression', function() { it('should return false when invalid expression', function() {
var date = dateMath.parseDateMath('2', moment([2014, 1, 5])); var date = dateMath.parseDateMath('2', moment([2014, 1, 5]));
expect(date).to.equal(undefined); expect(date).toEqual(undefined);
}); });
}); });
......
import {describe, it, expect} from 'test/lib/common'; import {Emitter} from '../utils/emitter';
import {Emitter} from 'app/core/core';
describe("Emitter", () => { describe("Emitter", () => {
...@@ -20,8 +18,8 @@ describe("Emitter", () => { ...@@ -20,8 +18,8 @@ describe("Emitter", () => {
events.emit('test', null); events.emit('test', null);
expect(sub1Called).to.be(true); expect(sub1Called).toBe(true);
expect(sub2Called).to.be(true); expect(sub2Called).toBe(true);
}); });
it('when subscribing twice', () => { it('when subscribing twice', () => {
...@@ -37,7 +35,7 @@ describe("Emitter", () => { ...@@ -37,7 +35,7 @@ describe("Emitter", () => {
events.emit('test', null); events.emit('test', null);
expect(sub1Called).to.be(2); expect(sub1Called).toBe(2);
}); });
it('should handle errors', () => { it('should handle errors', () => {
...@@ -57,8 +55,8 @@ describe("Emitter", () => { ...@@ -57,8 +55,8 @@ describe("Emitter", () => {
try { events.emit('test', null); } catch (_) { } try { events.emit('test', null); } catch (_) { }
try { events.emit('test', null); } catch (_) {} try { events.emit('test', null); } catch (_) {}
expect(sub1Called).to.be(2); expect(sub1Called).toBe(2);
expect(sub2Called).to.be(0); expect(sub2Called).toBe(0);
}); });
}); });
}); });
......
import {describe, it, expect} from 'test/lib/common';
import flatten from 'app/core/utils/flatten'; import flatten from 'app/core/utils/flatten';
describe("flatten", () => { describe("flatten", () => {
...@@ -15,9 +13,9 @@ describe("flatten", () => { ...@@ -15,9 +13,9 @@ describe("flatten", () => {
} }
}, null); }, null);
expect(flattened['level1']).to.be('level1-value'); expect(flattened['level1']).toBe('level1-value');
expect(flattened['deeper.level2']).to.be('level2-value'); expect(flattened['deeper.level2']).toBe('level2-value');
expect(flattened['deeper.deeper.level3']).to.be('level3-value'); expect(flattened['deeper.deeper.level3']).toBe('level3-value');
}); });
}); });
......
import {describe, it, expect} from 'test/lib/common';
import * as rangeUtil from 'app/core/utils/rangeutil'; import * as rangeUtil from 'app/core/utils/rangeutil';
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
...@@ -9,100 +7,100 @@ describe("rangeUtil", () => { ...@@ -9,100 +7,100 @@ describe("rangeUtil", () => {
describe("Can get range grouped list of ranges", () => { describe("Can get range grouped list of ranges", () => {
it('when custom settings should return default range list', () => { it('when custom settings should return default range list', () => {
var groups = rangeUtil.getRelativeTimesList({time_options: []}, 'Last 5 minutes'); var groups = rangeUtil.getRelativeTimesList({time_options: []}, 'Last 5 minutes');
expect(_.keys(groups).length).to.be(4); expect(_.keys(groups).length).toBe(4);
expect(groups[3][0].active).to.be(true); expect(groups[3][0].active).toBe(true);
}); });
}); });
describe("Can get range text described", () => { describe("Can get range text described", () => {
it('should handle simple old expression with only amount and unit', () => { it('should handle simple old expression with only amount and unit', () => {
var info = rangeUtil.describeTextRange('5m'); var info = rangeUtil.describeTextRange('5m');
expect(info.display).to.be('Last 5 minutes'); expect(info.display).toBe('Last 5 minutes');
}); });
it('should have singular when amount is 1', () => { it('should have singular when amount is 1', () => {
var info = rangeUtil.describeTextRange('1h'); var info = rangeUtil.describeTextRange('1h');
expect(info.display).to.be('Last 1 hour'); expect(info.display).toBe('Last 1 hour');
}); });
it('should handle non default amount', () => { it('should handle non default amount', () => {
var info = rangeUtil.describeTextRange('13h'); var info = rangeUtil.describeTextRange('13h');
expect(info.display).to.be('Last 13 hours'); expect(info.display).toBe('Last 13 hours');
expect(info.from).to.be('now-13h'); expect(info.from).toBe('now-13h');
}); });
it('should handle non default future amount', () => { it('should handle non default future amount', () => {
var info = rangeUtil.describeTextRange('+3h'); var info = rangeUtil.describeTextRange('+3h');
expect(info.display).to.be('Next 3 hours'); expect(info.display).toBe('Next 3 hours');
expect(info.from).to.be('now'); expect(info.from).toBe('now');
expect(info.to).to.be('now+3h'); expect(info.to).toBe('now+3h');
}); });
it('should handle now/d', () => { it('should handle now/d', () => {
var info = rangeUtil.describeTextRange('now/d'); var info = rangeUtil.describeTextRange('now/d');
expect(info.display).to.be('Today so far'); expect(info.display).toBe('Today so far');
}); });
it('should handle now/w', () => { it('should handle now/w', () => {
var info = rangeUtil.describeTextRange('now/w'); var info = rangeUtil.describeTextRange('now/w');
expect(info.display).to.be('This week so far'); expect(info.display).toBe('This week so far');
}); });
it('should handle now/M', () => { it('should handle now/M', () => {
var info = rangeUtil.describeTextRange('now/M'); var info = rangeUtil.describeTextRange('now/M');
expect(info.display).to.be('This month so far'); expect(info.display).toBe('This month so far');
}); });
it('should handle now/y', () => { it('should handle now/y', () => {
var info = rangeUtil.describeTextRange('now/y'); var info = rangeUtil.describeTextRange('now/y');
expect(info.display).to.be('This year so far'); expect(info.display).toBe('This year so far');
}); });
}); });
describe("Can get date range described", () => { describe("Can get date range described", () => {
it('Date range with simple ranges', () => { it('Date range with simple ranges', () => {
var text = rangeUtil.describeTimeRange({from: 'now-1h', to: 'now'}); var text = rangeUtil.describeTimeRange({from: 'now-1h', to: 'now'});
expect(text).to.be('Last 1 hour'); expect(text).toBe('Last 1 hour');
}); });
it('Date range with rounding ranges', () => { it('Date range with rounding ranges', () => {
var text = rangeUtil.describeTimeRange({from: 'now/d+6h', to: 'now'}); var text = rangeUtil.describeTimeRange({from: 'now/d+6h', to: 'now'});
expect(text).to.be('now/d+6h to now'); expect(text).toBe('now/d+6h to now');
}); });
it('Date range with absolute to now', () => { it('Date range with absolute to now', () => {
var text = rangeUtil.describeTimeRange({from: moment([2014,10,10,2,3,4]), to: 'now'}); var text = rangeUtil.describeTimeRange({from: moment([2014,10,10,2,3,4]), to: 'now'});
expect(text).to.be('Nov 10, 2014 02:03:04 to a few seconds ago'); expect(text).toBe('Nov 10, 2014 02:03:04 to a few seconds ago');
}); });
it('Date range with absolute to relative', () => { it('Date range with absolute to relative', () => {
var text = rangeUtil.describeTimeRange({from: moment([2014,10,10,2,3,4]), to: 'now-1d'}); var text = rangeUtil.describeTimeRange({from: moment([2014,10,10,2,3,4]), to: 'now-1d'});
expect(text).to.be('Nov 10, 2014 02:03:04 to a day ago'); expect(text).toBe('Nov 10, 2014 02:03:04 to a day ago');
}); });
it('Date range with relative to absolute', () => { it('Date range with relative to absolute', () => {
var text = rangeUtil.describeTimeRange({from: 'now-7d', to: moment([2014,10,10,2,3,4])}); var text = rangeUtil.describeTimeRange({from: 'now-7d', to: moment([2014,10,10,2,3,4])});
expect(text).to.be('7 days ago to Nov 10, 2014 02:03:04'); expect(text).toBe('7 days ago to Nov 10, 2014 02:03:04');
}); });
it('Date range with non matching default ranges', () => { it('Date range with non matching default ranges', () => {
var text = rangeUtil.describeTimeRange({from: 'now-13h', to: 'now'}); var text = rangeUtil.describeTimeRange({from: 'now-13h', to: 'now'});
expect(text).to.be('Last 13 hours'); expect(text).toBe('Last 13 hours');
}); });
it('Date range with from and to both are in now-* format', () => { it('Date range with from and to both are in now-* format', () => {
var text = rangeUtil.describeTimeRange({from: 'now-6h', to: 'now-3h'}); var text = rangeUtil.describeTimeRange({from: 'now-6h', to: 'now-3h'});
expect(text).to.be('now-6h to now-3h'); expect(text).toBe('now-6h to now-3h');
}); });
it('Date range with from and to both are either in now-* or now/* format', () => { it('Date range with from and to both are either in now-* or now/* format', () => {
var text = rangeUtil.describeTimeRange({from: 'now/d+6h', to: 'now-3h'}); var text = rangeUtil.describeTimeRange({from: 'now/d+6h', to: 'now-3h'});
expect(text).to.be('now/d+6h to now-3h'); expect(text).toBe('now/d+6h to now-3h');
}); });
it('Date range with from and to both are either in now-* or now+* format', () => { it('Date range with from and to both are either in now-* or now+* format', () => {
var text = rangeUtil.describeTimeRange({from: 'now-6h', to: 'now+1h'}); var text = rangeUtil.describeTimeRange({from: 'now-6h', to: 'now+1h'});
expect(text).to.be('now-6h to now+1h'); expect(text).toBe('now-6h to now+1h');
}); });
}); });
......
import {describe, beforeEach, it, expect} from 'test/lib/common';
import TableModel from 'app/core/table_model'; import TableModel from 'app/core/table_model';
describe('when sorting table desc', () => { describe('when sorting table desc', () => {
...@@ -16,14 +14,14 @@ describe('when sorting table desc', () => { ...@@ -16,14 +14,14 @@ describe('when sorting table desc', () => {
}); });
it('should sort by time', () => { it('should sort by time', () => {
expect(table.rows[0][0]).to.be(105); expect(table.rows[0][0]).toBe(105);
expect(table.rows[1][0]).to.be(103); expect(table.rows[1][0]).toBe(103);
expect(table.rows[2][0]).to.be(100); expect(table.rows[2][0]).toBe(100);
}); });
it ('should mark column being sorted', () => { it ('should mark column being sorted', () => {
expect(table.columns[0].sort).to.be(true); expect(table.columns[0].sort).toBe(true);
expect(table.columns[0].desc).to.be(true); expect(table.columns[0].desc).toBe(true);
}); });
}); });
...@@ -42,9 +40,9 @@ describe('when sorting table asc', () => { ...@@ -42,9 +40,9 @@ describe('when sorting table asc', () => {
}); });
it('should sort by time', () => { it('should sort by time', () => {
expect(table.rows[0][1]).to.be(10); expect(table.rows[0][1]).toBe(10);
expect(table.rows[1][1]).to.be(11); expect(table.rows[1][1]).toBe(11);
expect(table.rows[2][1]).to.be(15); expect(table.rows[2][1]).toBe(15);
}); });
}); });
......
import {describe, beforeEach, it, expect} from 'test/lib/common';
import TimeSeries from 'app/core/time_series2'; import TimeSeries from 'app/core/time_series2';
describe("TimeSeries", function() { describe("TimeSeries", function() {
...@@ -19,14 +18,14 @@ describe("TimeSeries", function() { ...@@ -19,14 +18,14 @@ describe("TimeSeries", function() {
it('with connected style, should ignore nulls', function() { it('with connected style, should ignore nulls', function() {
series = new TimeSeries(testData); series = new TimeSeries(testData);
points = series.getFlotPairs('connected', yAxisFormats); points = series.getFlotPairs('connected', yAxisFormats);
expect(points.length).to.be(3); expect(points.length).toBe(3);
}); });
it('with null as zero style, should replace nulls with zero', function() { it('with null as zero style, should replace nulls with zero', function() {
series = new TimeSeries(testData); series = new TimeSeries(testData);
points = series.getFlotPairs('null as zero', yAxisFormats); points = series.getFlotPairs('null as zero', yAxisFormats);
expect(points.length).to.be(4); expect(points.length).toBe(4);
expect(points[1][1]).to.be(0); expect(points[1][1]).toBe(0);
}); });
it('if last is null current should pick next to last', function() { it('if last is null current should pick next to last', function() {
...@@ -34,7 +33,7 @@ describe("TimeSeries", function() { ...@@ -34,7 +33,7 @@ describe("TimeSeries", function() {
datapoints: [[10,1], [null, 2]] datapoints: [[10,1], [null, 2]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.current).to.be(10); expect(series.stats.current).toBe(10);
}); });
it('max value should work for negative values', function() { it('max value should work for negative values', function() {
...@@ -42,13 +41,13 @@ describe("TimeSeries", function() { ...@@ -42,13 +41,13 @@ describe("TimeSeries", function() {
datapoints: [[-10,1], [-4, 2]] datapoints: [[-10,1], [-4, 2]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.max).to.be(-4); expect(series.stats.max).toBe(-4);
}); });
it('average value should ignore nulls', function() { it('average value should ignore nulls', function() {
series = new TimeSeries(testData); series = new TimeSeries(testData);
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.avg).to.be(6.333333333333333); expect(series.stats.avg).toBe(6.333333333333333);
}); });
it('the delta value should account for nulls', function() { it('the delta value should account for nulls', function() {
...@@ -56,7 +55,7 @@ describe("TimeSeries", function() { ...@@ -56,7 +55,7 @@ describe("TimeSeries", function() {
datapoints: [[1,2],[3,3],[null,4],[10,5],[15,6]] datapoints: [[1,2],[3,3],[null,4],[10,5],[15,6]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.delta).to.be(14); expect(series.stats.delta).toBe(14);
}); });
it('the delta value should account for nulls on first', function() { it('the delta value should account for nulls on first', function() {
...@@ -64,7 +63,7 @@ describe("TimeSeries", function() { ...@@ -64,7 +63,7 @@ describe("TimeSeries", function() {
datapoints: [[null,2],[1,3],[10,4],[15,5]] datapoints: [[null,2],[1,3],[10,4],[15,5]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.delta).to.be(14); expect(series.stats.delta).toBe(14);
}); });
it('the delta value should account for nulls on last', function() { it('the delta value should account for nulls on last', function() {
...@@ -72,7 +71,7 @@ describe("TimeSeries", function() { ...@@ -72,7 +71,7 @@ describe("TimeSeries", function() {
datapoints: [[1,2],[5,3],[10,4],[null,5]] datapoints: [[1,2],[5,3],[10,4],[null,5]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.delta).to.be(9); expect(series.stats.delta).toBe(9);
}); });
it('the delta value should account for resets', function() { it('the delta value should account for resets', function() {
...@@ -80,7 +79,7 @@ describe("TimeSeries", function() { ...@@ -80,7 +79,7 @@ describe("TimeSeries", function() {
datapoints: [[1,2],[5,3],[10,4],[0,5],[10,6]] datapoints: [[1,2],[5,3],[10,4],[0,5],[10,6]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.delta).to.be(19); expect(series.stats.delta).toBe(19);
}); });
it('the delta value should account for resets on last', function() { it('the delta value should account for resets on last', function() {
...@@ -88,30 +87,30 @@ describe("TimeSeries", function() { ...@@ -88,30 +87,30 @@ describe("TimeSeries", function() {
datapoints: [[1,2],[2,3],[10,4],[8,5]] datapoints: [[1,2],[2,3],[10,4],[8,5]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.delta).to.be(17); expect(series.stats.delta).toBe(17);
}); });
it('the range value should be max - min', function() { it('the range value should be max - min', function() {
series = new TimeSeries(testData); series = new TimeSeries(testData);
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.range).to.be(9); expect(series.stats.range).toBe(9);
}); });
it('first value should ingone nulls', function() { it('first value should ingone nulls', function() {
series = new TimeSeries(testData); series = new TimeSeries(testData);
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.first).to.be(1); expect(series.stats.first).toBe(1);
series = new TimeSeries({ series = new TimeSeries({
datapoints: [[null,2],[1,3],[10,4],[8,5]] datapoints: [[null,2],[1,3],[10,4],[8,5]]
}); });
series.getFlotPairs('null', yAxisFormats); series.getFlotPairs('null', yAxisFormats);
expect(series.stats.first).to.be(1); expect(series.stats.first).toBe(1);
}); });
it('with null as zero style, average value should treat nulls as 0', function() { it('with null as zero style, average value should treat nulls as 0', function() {
series = new TimeSeries(testData); series = new TimeSeries(testData);
series.getFlotPairs('null as zero', yAxisFormats); series.getFlotPairs('null as zero', yAxisFormats);
expect(series.stats.avg).to.be(4.75); expect(series.stats.avg).toBe(4.75);
}); });
it('average value should be null if all values is null', function() { it('average value should be null if all values is null', function() {
...@@ -119,7 +118,7 @@ describe("TimeSeries", function() { ...@@ -119,7 +118,7 @@ describe("TimeSeries", function() {
datapoints: [[null,2],[null,3],[null,4],[null,5]] datapoints: [[null,2],[null,3],[null,4],[null,5]]
}); });
series.getFlotPairs('null'); series.getFlotPairs('null');
expect(series.stats.avg).to.be(null); expect(series.stats.avg).toBe(null);
}); });
}); });
...@@ -130,7 +129,7 @@ describe("TimeSeries", function() { ...@@ -130,7 +129,7 @@ describe("TimeSeries", function() {
}); });
it('should set hasMsResolution to false', function() { it('should set hasMsResolution to false', function() {
expect(series.hasMsResolution).to.be(false); expect(series.hasMsResolution).toBe(false);
}); });
}); });
...@@ -140,7 +139,7 @@ describe("TimeSeries", function() { ...@@ -140,7 +139,7 @@ describe("TimeSeries", function() {
}); });
it('should show millisecond resolution tooltip', function() { it('should show millisecond resolution tooltip', function() {
expect(series.hasMsResolution).to.be(true); expect(series.hasMsResolution).toBe(true);
}); });
}); });
...@@ -150,7 +149,7 @@ describe("TimeSeries", function() { ...@@ -150,7 +149,7 @@ describe("TimeSeries", function() {
}); });
it('should not show millisecond resolution tooltip', function() { it('should not show millisecond resolution tooltip', function() {
expect(series.hasMsResolution).to.be(false); expect(series.hasMsResolution).toBe(false);
}); });
}); });
}); });
...@@ -165,13 +164,13 @@ describe("TimeSeries", function() { ...@@ -165,13 +164,13 @@ describe("TimeSeries", function() {
it('missing datapoint with ms precision', function() { it('missing datapoint with ms precision', function() {
fakedata.datapoints[0] = [1337, 1234567890000]; fakedata.datapoints[0] = [1337, 1234567890000];
series = new TimeSeries(fakedata); series = new TimeSeries(fakedata);
expect(series.isMsResolutionNeeded()).to.be(false); expect(series.isMsResolutionNeeded()).toBe(false);
}); });
it('contains datapoint with ms precision', function() { it('contains datapoint with ms precision', function() {
fakedata.datapoints[0] = [1337, 1236547890001]; fakedata.datapoints[0] = [1337, 1236547890001];
series = new TimeSeries(fakedata); series = new TimeSeries(fakedata);
expect(series.isMsResolutionNeeded()).to.be(true); expect(series.isMsResolutionNeeded()).toBe(true);
}); });
}); });
...@@ -188,8 +187,8 @@ describe("TimeSeries", function() { ...@@ -188,8 +187,8 @@ describe("TimeSeries", function() {
}); });
it('should set fill zero, and enable points', function() { it('should set fill zero, and enable points', function() {
expect(series.lines.fill).to.be(0.001); expect(series.lines.fill).toBe(0.001);
expect(series.points.show).to.be(true); expect(series.points.show).toBe(true);
}); });
}); });
...@@ -200,8 +199,8 @@ describe("TimeSeries", function() { ...@@ -200,8 +199,8 @@ describe("TimeSeries", function() {
}); });
it('should disable lines, and enable bars', function() { it('should disable lines, and enable bars', function() {
expect(series.lines.show).to.be(false); expect(series.lines.show).toBe(false);
expect(series.bars.show).to.be(true); expect(series.bars.show).toBe(true);
}); });
}); });
...@@ -212,8 +211,8 @@ describe("TimeSeries", function() { ...@@ -212,8 +211,8 @@ describe("TimeSeries", function() {
}); });
it('should disable stack, and set lineWidth', function() { it('should disable stack, and set lineWidth', function() {
expect(series.stack).to.be(false); expect(series.stack).toBe(false);
expect(series.lines.lineWidth).to.be(5); expect(series.lines.lineWidth).toBe(5);
}); });
}); });
...@@ -224,9 +223,9 @@ describe("TimeSeries", function() { ...@@ -224,9 +223,9 @@ describe("TimeSeries", function() {
}); });
it('should enable dashes, set dashes lineWidth to 5 and lines lineWidth to 0', function() { it('should enable dashes, set dashes lineWidth to 5 and lines lineWidth to 0', function() {
expect(series.dashes.show).to.be(true); expect(series.dashes.show).toBe(true);
expect(series.dashes.lineWidth).to.be(5); expect(series.dashes.lineWidth).toBe(5);
expect(series.lines.lineWidth).to.be(0); expect(series.lines.lineWidth).toBe(0);
}); });
}); });
...@@ -237,7 +236,7 @@ describe("TimeSeries", function() { ...@@ -237,7 +236,7 @@ describe("TimeSeries", function() {
}); });
it('should disable line fill and add fillBelowTo', function() { it('should disable line fill and add fillBelowTo', function() {
expect(series.fillBelowTo).to.be('min'); expect(series.fillBelowTo).toBe('min');
}); });
}); });
...@@ -248,8 +247,8 @@ describe("TimeSeries", function() { ...@@ -248,8 +247,8 @@ describe("TimeSeries", function() {
}); });
it('should set pointradius, and set steppedLine', function() { it('should set pointradius, and set steppedLine', function() {
expect(series.points.radius).to.be(5); expect(series.points.radius).toBe(5);
expect(series.lines.steps).to.be(true); expect(series.lines.steps).toBe(true);
}); });
}); });
...@@ -260,7 +259,7 @@ describe("TimeSeries", function() { ...@@ -260,7 +259,7 @@ describe("TimeSeries", function() {
}); });
it('should match second series', function() { it('should match second series', function() {
expect(series.lines.show).to.be(false); expect(series.lines.show).toBe(false);
}); });
}); });
...@@ -271,11 +270,11 @@ describe("TimeSeries", function() { ...@@ -271,11 +270,11 @@ describe("TimeSeries", function() {
}); });
it('should set yaxis', function() { it('should set yaxis', function() {
expect(series.yaxis).to.be(2); expect(series.yaxis).toBe(2);
}); });
it('should set zindex', function() { it('should set zindex', function() {
expect(series.zindex).to.be(2); expect(series.zindex).toBe(2);
}); });
}); });
...@@ -288,11 +287,11 @@ describe("TimeSeries", function() { ...@@ -288,11 +287,11 @@ describe("TimeSeries", function() {
}); });
it('should format non-numeric values as empty string', function() { it('should format non-numeric values as empty string', function() {
expect(series.formatValue(null)).to.be(""); expect(series.formatValue(null)).toBe("");
expect(series.formatValue(undefined)).to.be(""); expect(series.formatValue(undefined)).toBe("");
expect(series.formatValue(NaN)).to.be(""); expect(series.formatValue(NaN)).toBe("");
expect(series.formatValue(Infinity)).to.be(""); expect(series.formatValue(Infinity)).toBe("");
expect(series.formatValue(-Infinity)).to.be(""); expect(series.formatValue(-Infinity)).toBe("");
}); });
}); });
......
define([
'./time_series2'
], function(timeSeries) {
'use strict';
// backward compatability hack;
return timeSeries.default;
});
import React from 'react'; import React from 'react';
import { react2AngularDirective } from 'app/core/utils/react2angular';
export interface IProps { export interface IProps {
password: string; password: string;
...@@ -33,5 +32,4 @@ export class PasswordStrength extends React.Component<IProps, any> { ...@@ -33,5 +32,4 @@ export class PasswordStrength extends React.Component<IProps, any> {
} }
} }
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
...@@ -15,7 +15,6 @@ define([ ...@@ -15,7 +15,6 @@ define([
'./unsavedChangesSrv', './unsavedChangesSrv',
'./unsaved_changes_modal', './unsaved_changes_modal',
'./timepicker/timepicker', './timepicker/timepicker',
'./graphiteImportCtrl',
'./impression_store', './impression_store',
'./upload', './upload',
'./import/dash_import', './import/dash_import',
......
...@@ -11,6 +11,8 @@ define([ ...@@ -11,6 +11,8 @@ define([
function (angular, moment, _, $, kbn, dateMath, impressionStore) { function (angular, moment, _, $, kbn, dateMath, impressionStore) {
'use strict'; 'use strict';
kbn = kbn.default;
var module = angular.module('grafana.services'); var module = angular.module('grafana.services');
module.service('dashboardLoaderSrv', function(backendSrv, module.service('dashboardLoaderSrv', function(backendSrv,
......
define([
'angular',
'lodash',
'app/core/utils/kbn'
],
function (angular, _, kbn) {
'use strict';
var module = angular.module('grafana.controllers');
module.controller('GraphiteImportCtrl', function($scope, datasourceSrv, dashboardSrv, $location) {
$scope.options = {};
$scope.init = function() {
$scope.datasources = [];
_.each(datasourceSrv.getAll(), function(ds) {
if (ds.type === 'graphite') {
$scope.options.sourceName = ds.name;
$scope.datasources.push(ds.name);
}
});
};
$scope.listAll = function() {
datasourceSrv.get($scope.options.sourceName).then(function(datasource) {
$scope.datasource = datasource;
$scope.datasource.listDashboards('').then(function(results) {
$scope.dashboards = results;
}, function(err) {
var message = err.message || err.statusText || 'Error';
$scope.appEvent('alert-error', ['Failed to load dashboard list from graphite', message]);
});
});
};
$scope.import = function(dashName) {
$scope.datasource.loadDashboard(dashName).then(function(results) {
if (!results.data || !results.data.state) {
throw { message: 'no dashboard state received from graphite' };
}
graphiteToGrafanaTranslator(results.data.state, $scope.datasource.name);
}, function(err) {
var message = err.message || err.statusText || 'Error';
$scope.appEvent('alert-error', ['Failed to load dashboard from graphite', message]);
});
};
function graphiteToGrafanaTranslator(state, datasource) {
var graphsPerRow = 2;
var rowHeight = 300;
var rowTemplate;
var currentRow;
var panel;
rowTemplate = {
title: '',
panels: [],
height: rowHeight
};
currentRow = angular.copy(rowTemplate);
var newDashboard = dashboardSrv.create({});
newDashboard.rows = [];
newDashboard.title = state.name;
newDashboard.rows.push(currentRow);
_.each(state.graphs, function(graph, index) {
if (currentRow.panels.length === graphsPerRow) {
currentRow = angular.copy(rowTemplate);
newDashboard.rows.push(currentRow);
}
panel = {
type: 'graph',
span: 12 / graphsPerRow,
title: graph[1].title,
targets: [],
datasource: datasource,
id: index + 1
};
_.each(graph[1].target, function(target) {
panel.targets.push({ target: target });
});
currentRow.panels.push(panel);
});
window.grafanaImportDashboard = newDashboard;
$location.path('/dashboard-import/' + kbn.slugifyForUrl(newDashboard.title));
}
});
});
...@@ -6,6 +6,8 @@ define([ ...@@ -6,6 +6,8 @@ define([
function (angular, _, kbn) { function (angular, _, kbn) {
'use strict'; 'use strict';
kbn = kbn.default;
angular angular
.module('grafana.services') .module('grafana.services')
.service('linkSrv', function(templateSrv, timeSrv) { .service('linkSrv', function(templateSrv, timeSrv) {
......
///<reference path="../../headers/common.d.ts" />
import _ from 'lodash'; import _ from 'lodash';
import {Variable, assignModelProperties, variableTypes} from './variable'; import {Variable, assignModelProperties, variableTypes} from './variable';
......
import './templateSrv';
import './editor_ctrl'; import './editor_ctrl';
import coreModule from 'app/core/core_module';
import {VariableSrv} from './variable_srv'; import { TemplateSrv } from './template_srv';
import {IntervalVariable} from './interval_variable'; import { VariableSrv } from './variable_srv';
import {QueryVariable} from './query_variable'; import { IntervalVariable } from './interval_variable';
import {DatasourceVariable} from './datasource_variable'; import { QueryVariable } from './query_variable';
import {CustomVariable} from './custom_variable'; import { DatasourceVariable } from './datasource_variable';
import {ConstantVariable} from './constant_variable'; import { CustomVariable } from './custom_variable';
import {AdhocVariable} from './adhoc_variable'; import { ConstantVariable } from './constant_variable';
import { AdhocVariable } from './adhoc_variable';
coreModule.service('templateSrv', TemplateSrv);
export { export {
TemplateSrv,
VariableSrv, VariableSrv,
IntervalVariable, IntervalVariable,
QueryVariable, QueryVariable,
......
///<reference path="../../headers/common.d.ts" />
import _ from 'lodash'; import _ from 'lodash';
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
import {Variable, containsVariable, assignModelProperties, variableTypes} from './variable'; import {Variable, containsVariable, assignModelProperties, variableTypes} from './variable';
......
import {describe, it, expect} from 'test/lib/common';
import {AdhocVariable} from '../adhoc_variable'; import {AdhocVariable} from '../adhoc_variable';
describe('AdhocVariable', function() { describe('AdhocVariable', function() {
...@@ -15,7 +13,7 @@ describe('AdhocVariable', function() { ...@@ -15,7 +13,7 @@ describe('AdhocVariable', function() {
] ]
}); });
var urlValue = variable.getValueForUrl(); var urlValue = variable.getValueForUrl();
expect(urlValue).to.eql(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]); expect(urlValue).toMatchObject(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]);
}); });
}); });
...@@ -26,17 +24,17 @@ describe('AdhocVariable', function() { ...@@ -26,17 +24,17 @@ describe('AdhocVariable', function() {
var variable = new AdhocVariable({}); var variable = new AdhocVariable({});
variable.setValueFromUrl(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]); variable.setValueFromUrl(["key1|=|value1", "key2|!=|value2", "key3|=|value3a__gfp__value3b__gfp__value3c"]);
expect(variable.filters[0].key).to.be('key1'); expect(variable.filters[0].key).toBe('key1');
expect(variable.filters[0].operator).to.be('='); expect(variable.filters[0].operator).toBe('=');
expect(variable.filters[0].value).to.be('value1'); expect(variable.filters[0].value).toBe('value1');
expect(variable.filters[1].key).to.be('key2'); expect(variable.filters[1].key).toBe('key2');
expect(variable.filters[1].operator).to.be('!='); expect(variable.filters[1].operator).toBe('!=');
expect(variable.filters[1].value).to.be('value2'); expect(variable.filters[1].value).toBe('value2');
expect(variable.filters[2].key).to.be('key3'); expect(variable.filters[2].key).toBe('key3');
expect(variable.filters[2].operator).to.be('='); expect(variable.filters[2].operator).toBe('=');
expect(variable.filters[2].value).to.be('value3a|value3b|value3c'); expect(variable.filters[2].value).toBe('value3a|value3b|value3c');
}); });
}); });
......
import {describe, it, expect} from 'test/lib/common';
import {QueryVariable} from '../query_variable'; import {QueryVariable} from '../query_variable';
describe('QueryVariable', () => { describe('QueryVariable', () => {
...@@ -8,14 +6,14 @@ describe('QueryVariable', () => { ...@@ -8,14 +6,14 @@ describe('QueryVariable', () => {
it('should set defaults', () => { it('should set defaults', () => {
var variable = new QueryVariable({}, null, null, null, null); var variable = new QueryVariable({}, null, null, null, null);
expect(variable.datasource).to.be(null); expect(variable.datasource).toBe(null);
expect(variable.refresh).to.be(0); expect(variable.refresh).toBe(0);
expect(variable.sort).to.be(0); expect(variable.sort).toBe(0);
expect(variable.name).to.be(''); expect(variable.name).toBe('');
expect(variable.hide).to.be(0); expect(variable.hide).toBe(0);
expect(variable.options.length).to.be(0); expect(variable.options.length).toBe(0);
expect(variable.multi).to.be(false); expect(variable.multi).toBe(false);
expect(variable.includeAll).to.be(false); expect(variable.includeAll).toBe(false);
}); });
it('get model should copy changes back to model', () => { it('get model should copy changes back to model', () => {
...@@ -26,11 +24,11 @@ describe('QueryVariable', () => { ...@@ -26,11 +24,11 @@ describe('QueryVariable', () => {
variable.sort = 50; variable.sort = 50;
var model = variable.getSaveModel(); var model = variable.getSaveModel();
expect(model.options.length).to.be(1); expect(model.options.length).toBe(1);
expect(model.options[0].text).to.be('test'); expect(model.options[0].text).toBe('test');
expect(model.datasource).to.be('google'); expect(model.datasource).toBe('google');
expect(model.regex).to.be('asd'); expect(model.regex).toBe('asd');
expect(model.sort).to.be(50); expect(model.sort).toBe(50);
}); });
it('if refresh != 0 then remove options in presisted mode', () => { it('if refresh != 0 then remove options in presisted mode', () => {
...@@ -39,7 +37,7 @@ describe('QueryVariable', () => { ...@@ -39,7 +37,7 @@ describe('QueryVariable', () => {
variable.refresh = 1; variable.refresh = 1;
var model = variable.getSaveModel(); var model = variable.getSaveModel();
expect(model.options.length).to.be(0); expect(model.options.length).toBe(0);
}); });
}); });
...@@ -67,14 +65,14 @@ describe('QueryVariable', () => { ...@@ -67,14 +65,14 @@ describe('QueryVariable', () => {
it('should return in same order', () => { it('should return in same order', () => {
var i = 0; var i = 0;
expect(result.length).to.be(11); expect(result.length).toBe(11);
expect(result[i++].text).to.be(''); expect(result[i++].text).toBe('');
expect(result[i++].text).to.be('0'); expect(result[i++].text).toBe('0');
expect(result[i++].text).to.be('1'); expect(result[i++].text).toBe('1');
expect(result[i++].text).to.be('3'); expect(result[i++].text).toBe('3');
expect(result[i++].text).to.be('4'); expect(result[i++].text).toBe('4');
expect(result[i++].text).to.be('5'); expect(result[i++].text).toBe('5');
expect(result[i++].text).to.be('6'); expect(result[i++].text).toBe('6');
}); });
}); });
}); });
......
import {describe, beforeEach, it, expect, angularMocks} from 'test/lib/common'; import { TemplateSrv } from '../template_srv';
import '../all';
import {Emitter} from 'app/core/core';
describe('templateSrv', function() { describe('templateSrv', function() {
var _templateSrv, _variableSrv; var _templateSrv;
beforeEach(angularMocks.module('grafana.core'));
beforeEach(angularMocks.module('grafana.services'));
beforeEach(angularMocks.module($provide => {
$provide.value('timeSrv', {});
$provide.value('datasourceSrv', {});
}));
beforeEach(angularMocks.inject(function(variableSrv, templateSrv) {
_templateSrv = templateSrv;
_variableSrv = variableSrv;
}));
function initTemplateSrv(variables) { function initTemplateSrv(variables) {
_variableSrv.init({ _templateSrv = new TemplateSrv();
templating: {list: variables}, _templateSrv.init(variables);
events: new Emitter(),
});
} }
describe('init', function() { describe('init', function() {
...@@ -32,7 +15,7 @@ describe('templateSrv', function() { ...@@ -32,7 +15,7 @@ describe('templateSrv', function() {
it('should initialize template data', function() { it('should initialize template data', function() {
var target = _templateSrv.replace('this.[[test]].filters'); var target = _templateSrv.replace('this.[[test]].filters');
expect(target).to.be('this.oogle.filters'); expect(target).toBe('this.oogle.filters');
}); });
}); });
...@@ -43,12 +26,12 @@ describe('templateSrv', function() { ...@@ -43,12 +26,12 @@ describe('templateSrv', function() {
it('should replace $test with scoped value', function() { it('should replace $test with scoped value', function() {
var target = _templateSrv.replace('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}}); var target = _templateSrv.replace('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}});
expect(target).to.be('this.mupp.filters'); expect(target).toBe('this.mupp.filters');
}); });
it('should replace $test with scoped text', function() { it('should replace $test with scoped text', function() {
var target = _templateSrv.replaceWithText('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}}); var target = _templateSrv.replaceWithText('this.$test.filters', {'test': {value: 'mupp', text: 'asd'}});
expect(target).to.be('this.asd.filters'); expect(target).toBe('this.asd.filters');
}); });
}); });
...@@ -63,17 +46,17 @@ describe('templateSrv', function() { ...@@ -63,17 +46,17 @@ describe('templateSrv', function() {
it('should return filters if datasourceName match', function() { it('should return filters if datasourceName match', function() {
var filters = _templateSrv.getAdhocFilters('oogle'); var filters = _templateSrv.getAdhocFilters('oogle');
expect(filters).to.eql([1]); expect(filters).toMatchObject([1]);
}); });
it('should return empty array if datasourceName does not match', function() { it('should return empty array if datasourceName does not match', function() {
var filters = _templateSrv.getAdhocFilters('oogleasdasd'); var filters = _templateSrv.getAdhocFilters('oogleasdasd');
expect(filters).to.eql([]); expect(filters).toMatchObject([]);
}); });
it('should return filters when datasourceName match via data source variable', function() { it('should return filters when datasourceName match via data source variable', function() {
var filters = _templateSrv.getAdhocFilters('logstash'); var filters = _templateSrv.getAdhocFilters('logstash');
expect(filters).to.eql([2]); expect(filters).toMatchObject([2]);
}); });
}); });
...@@ -84,17 +67,17 @@ describe('templateSrv', function() { ...@@ -84,17 +67,17 @@ describe('templateSrv', function() {
it('should replace $test with globbed value', function() { it('should replace $test with globbed value', function() {
var target = _templateSrv.replace('this.$test.filters', {}, 'glob'); var target = _templateSrv.replace('this.$test.filters', {}, 'glob');
expect(target).to.be('this.{value1,value2}.filters'); expect(target).toBe('this.{value1,value2}.filters');
}); });
it('should replace $test with piped value', function() { it('should replace $test with piped value', function() {
var target = _templateSrv.replace('this=$test', {}, 'pipe'); var target = _templateSrv.replace('this=$test', {}, 'pipe');
expect(target).to.be('this=value1|value2'); expect(target).toBe('this=value1|value2');
}); });
it('should replace $test with piped value', function() { it('should replace $test with piped value', function() {
var target = _templateSrv.replace('this=$test', {}, 'pipe'); var target = _templateSrv.replace('this=$test', {}, 'pipe');
expect(target).to.be('this=value1|value2'); expect(target).toBe('this=value1|value2');
}); });
}); });
...@@ -112,7 +95,7 @@ describe('templateSrv', function() { ...@@ -112,7 +95,7 @@ describe('templateSrv', function() {
it('should replace $test with formatted all value', function() { it('should replace $test with formatted all value', function() {
var target = _templateSrv.replace('this.$test.filters', {}, 'glob'); var target = _templateSrv.replace('this.$test.filters', {}, 'glob');
expect(target).to.be('this.{value1,value2}.filters'); expect(target).toBe('this.{value1,value2}.filters');
}); });
}); });
...@@ -131,12 +114,12 @@ describe('templateSrv', function() { ...@@ -131,12 +114,12 @@ describe('templateSrv', function() {
it('should replace $test with formatted all value', function() { it('should replace $test with formatted all value', function() {
var target = _templateSrv.replace('this.$test.filters', {}, 'glob'); var target = _templateSrv.replace('this.$test.filters', {}, 'glob');
expect(target).to.be('this.*.filters'); expect(target).toBe('this.*.filters');
}); });
it('should not escape custom all value', function() { it('should not escape custom all value', function() {
var target = _templateSrv.replace('this.$test', {}, 'regex'); var target = _templateSrv.replace('this.$test', {}, 'regex');
expect(target).to.be('this.*'); expect(target).toBe('this.*');
}); });
}); });
...@@ -144,49 +127,49 @@ describe('templateSrv', function() { ...@@ -144,49 +127,49 @@ describe('templateSrv', function() {
it('should properly escape $test with lucene escape sequences', function() { it('should properly escape $test with lucene escape sequences', function() {
initTemplateSrv([{type: 'query', name: 'test', current: {value: 'value/4' }}]); initTemplateSrv([{type: 'query', name: 'test', current: {value: 'value/4' }}]);
var target = _templateSrv.replace('this:$test', {}, 'lucene'); var target = _templateSrv.replace('this:$test', {}, 'lucene');
expect(target).to.be("this:value\\\/4"); expect(target).toBe("this:value\\\/4");
}); });
}); });
describe('format variable to string values', function() { describe('format variable to string values', function() {
it('single value should return value', function() { it('single value should return value', function() {
var result = _templateSrv.formatValue('test'); var result = _templateSrv.formatValue('test');
expect(result).to.be('test'); expect(result).toBe('test');
}); });
it('multi value and glob format should render glob string', function() { it('multi value and glob format should render glob string', function() {
var result = _templateSrv.formatValue(['test','test2'], 'glob'); var result = _templateSrv.formatValue(['test','test2'], 'glob');
expect(result).to.be('{test,test2}'); expect(result).toBe('{test,test2}');
}); });
it('multi value and lucene should render as lucene expr', function() { it('multi value and lucene should render as lucene expr', function() {
var result = _templateSrv.formatValue(['test','test2'], 'lucene'); var result = _templateSrv.formatValue(['test','test2'], 'lucene');
expect(result).to.be('("test" OR "test2")'); expect(result).toBe('("test" OR "test2")');
}); });
it('multi value and regex format should render regex string', function() { it('multi value and regex format should render regex string', function() {
var result = _templateSrv.formatValue(['test.','test2'], 'regex'); var result = _templateSrv.formatValue(['test.','test2'], 'regex');
expect(result).to.be('(test\\.|test2)'); expect(result).toBe('(test\\.|test2)');
}); });
it('multi value and pipe should render pipe string', function() { it('multi value and pipe should render pipe string', function() {
var result = _templateSrv.formatValue(['test','test2'], 'pipe'); var result = _templateSrv.formatValue(['test','test2'], 'pipe');
expect(result).to.be('test|test2'); expect(result).toBe('test|test2');
}); });
it('multi value and distributed should render distributed string', function() { it('multi value and distributed should render distributed string', function() {
var result = _templateSrv.formatValue(['test','test2'], 'distributed', { name: 'build' }); var result = _templateSrv.formatValue(['test','test2'], 'distributed', { name: 'build' });
expect(result).to.be('test,build=test2'); expect(result).toBe('test,build=test2');
}); });
it('multi value and distributed should render when not string', function() { it('multi value and distributed should render when not string', function() {
var result = _templateSrv.formatValue(['test'], 'distributed', { name: 'build' }); var result = _templateSrv.formatValue(['test'], 'distributed', { name: 'build' });
expect(result).to.be('test'); expect(result).toBe('test');
}); });
it('slash should be properly escaped in regex format', function() { it('slash should be properly escaped in regex format', function() {
var result = _templateSrv.formatValue('Gi3/14', 'regex'); var result = _templateSrv.formatValue('Gi3/14', 'regex');
expect(result).to.be('Gi3\\/14'); expect(result).toBe('Gi3\\/14');
}); });
}); });
...@@ -198,7 +181,7 @@ describe('templateSrv', function() { ...@@ -198,7 +181,7 @@ describe('templateSrv', function() {
it('should return true if exists', function() { it('should return true if exists', function() {
var result = _templateSrv.variableExists('$test'); var result = _templateSrv.variableExists('$test');
expect(result).to.be(true); expect(result).toBe(true);
}); });
}); });
...@@ -209,17 +192,17 @@ describe('templateSrv', function() { ...@@ -209,17 +192,17 @@ describe('templateSrv', function() {
it('should insert html', function() { it('should insert html', function() {
var result = _templateSrv.highlightVariablesAsHtml('$test'); var result = _templateSrv.highlightVariablesAsHtml('$test');
expect(result).to.be('<span class="template-variable">$test</span>'); expect(result).toBe('<span class="template-variable">$test</span>');
}); });
it('should insert html anywhere in string', function() { it('should insert html anywhere in string', function() {
var result = _templateSrv.highlightVariablesAsHtml('this $test ok'); var result = _templateSrv.highlightVariablesAsHtml('this $test ok');
expect(result).to.be('this <span class="template-variable">$test</span> ok'); expect(result).toBe('this <span class="template-variable">$test</span> ok');
}); });
it('should ignore if variables does not exist', function() { it('should ignore if variables does not exist', function() {
var result = _templateSrv.highlightVariablesAsHtml('this $google ok'); var result = _templateSrv.highlightVariablesAsHtml('this $google ok');
expect(result).to.be('this $google ok'); expect(result).toBe('this $google ok');
}); });
}); });
...@@ -230,19 +213,28 @@ describe('templateSrv', function() { ...@@ -230,19 +213,28 @@ describe('templateSrv', function() {
it('should set current value and update template data', function() { it('should set current value and update template data', function() {
var target = _templateSrv.replace('this.[[test]].filters'); var target = _templateSrv.replace('this.[[test]].filters');
expect(target).to.be('this.muuuu.filters'); expect(target).toBe('this.muuuu.filters');
}); });
}); });
describe('fillVariableValuesForUrl with multi value', function() { describe('fillVariableValuesForUrl with multi value', function() {
beforeEach(function() { beforeEach(function() {
initTemplateSrv([{type: 'query', name: 'test', current: { value: ['val1', 'val2'] }}]); initTemplateSrv([
{
type: 'query',
name: 'test',
current: { value: ['val1', 'val2'] },
getValueForUrl: function() {
return this.current.value;
}
}
]);
}); });
it('should set multiple url params', function() { it('should set multiple url params', function() {
var params = {}; var params = {};
_templateSrv.fillVariableValuesForUrl(params); _templateSrv.fillVariableValuesForUrl(params);
expect(params['var-test']).to.eql(['val1', 'val2']); expect(params['var-test']).toMatchObject(['val1', 'val2']);
}); });
}); });
...@@ -254,7 +246,7 @@ describe('templateSrv', function() { ...@@ -254,7 +246,7 @@ describe('templateSrv', function() {
it('should set scoped value as url params', function() { it('should set scoped value as url params', function() {
var params = {}; var params = {};
_templateSrv.fillVariableValuesForUrl(params, {'test': {value: 'val1'}}); _templateSrv.fillVariableValuesForUrl(params, {'test': {value: 'val1'}});
expect(params['var-test']).to.eql('val1'); expect(params['var-test']).toBe('val1');
}); });
}); });
...@@ -270,7 +262,7 @@ describe('templateSrv', function() { ...@@ -270,7 +262,7 @@ describe('templateSrv', function() {
it('should replace with text except for grafanaVariables', function() { it('should replace with text except for grafanaVariables', function() {
var target = _templateSrv.replaceWithText('Server: $server, period: $period'); var target = _templateSrv.replaceWithText('Server: $server, period: $period');
expect(target).to.be('Server: All, period: 13m'); expect(target).toBe('Server: All, period: 13m');
}); });
}); });
...@@ -281,7 +273,7 @@ describe('templateSrv', function() { ...@@ -281,7 +273,7 @@ describe('templateSrv', function() {
it('should replace $__interval_ms with interval milliseconds', function() { it('should replace $__interval_ms with interval milliseconds', function() {
var target = _templateSrv.replace('10 * $__interval_ms', {"__interval_ms": {text: "100", value: "100"}}); var target = _templateSrv.replace('10 * $__interval_ms', {"__interval_ms": {text: "100", value: "100"}});
expect(target).to.be('10 * 100'); expect(target).toBe('10 * 100');
}); });
}); });
......
///<reference path="../../headers/common.d.ts" />
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
import {assignModelProperties} from 'app/core/core'; import {assignModelProperties} from 'app/core/utils/model_utils';
export interface Variable { export interface Variable {
setValue(option); setValue(option);
......
...@@ -9,6 +9,8 @@ define([ ...@@ -9,6 +9,8 @@ define([
function (angular, _, moment, dateMath, kbn, templatingVariable) { function (angular, _, moment, dateMath, kbn, templatingVariable) {
'use strict'; 'use strict';
kbn = kbn.default;
/** @ngInject */ /** @ngInject */
function CloudWatchDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) { function CloudWatchDatasource(instanceSettings, $q, backendSrv, templateSrv, timeSrv) {
this.type = 'cloudwatch'; this.type = 'cloudwatch';
......
...@@ -7,6 +7,8 @@ define([ ...@@ -7,6 +7,8 @@ define([
function (angular, _, $, gfunc) { function (angular, _, $, gfunc) {
'use strict'; 'use strict';
gfunc = gfunc.default;
angular angular
.module('grafana.directives') .module('grafana.directives')
.directive('graphiteAddFunc', function($compile) { .directive('graphiteAddFunc', function($compile) {
......
declare var test: any;
export default test;
import {describe, it, expect} from 'test/lib/common';
import gfunc from '../gfunc'; import gfunc from '../gfunc';
describe('when creating func instance from func names', function() { describe('when creating func instance from func names', function() {
it('should return func instance', function() { it('should return func instance', function() {
var func = gfunc.createFuncInstance('sumSeries'); var func = gfunc.createFuncInstance('sumSeries');
expect(func).to.be.ok(); expect(func).toBeTruthy();
expect(func.def.name).to.equal('sumSeries'); expect(func.def.name).toEqual('sumSeries');
expect(func.def.params.length).to.equal(5); expect(func.def.params.length).toEqual(5);
expect(func.def.defaultParams.length).to.equal(1); expect(func.def.defaultParams.length).toEqual(1);
}); });
it('should return func instance with shortName', function() { it('should return func instance with shortName', function() {
var func = gfunc.createFuncInstance('sum'); var func = gfunc.createFuncInstance('sum');
expect(func).to.be.ok(); expect(func).toBeTruthy();
}); });
it('should return func instance from funcDef', function() { it('should return func instance from funcDef', function() {
var func = gfunc.createFuncInstance('sum'); var func = gfunc.createFuncInstance('sum');
var func2 = gfunc.createFuncInstance(func.def); var func2 = gfunc.createFuncInstance(func.def);
expect(func2).to.be.ok(); expect(func2).toBeTruthy();
}); });
it('func instance should have text representation', function() { it('func instance should have text representation', function() {
...@@ -27,7 +25,7 @@ describe('when creating func instance from func names', function() { ...@@ -27,7 +25,7 @@ describe('when creating func instance from func names', function() {
func.params[0] = 5; func.params[0] = 5;
func.params[1] = 'avg'; func.params[1] = 'avg';
func.updateText(); func.updateText();
expect(func.text).to.equal("groupByNode(5, avg)"); expect(func.text).toEqual("groupByNode(5, avg)");
}); });
}); });
...@@ -35,51 +33,51 @@ describe('when rendering func instance', function() { ...@@ -35,51 +33,51 @@ describe('when rendering func instance', function() {
it('should handle single metric param', function() { it('should handle single metric param', function() {
var func = gfunc.createFuncInstance('sumSeries'); var func = gfunc.createFuncInstance('sumSeries');
expect(func.render('hello.metric')).to.equal("sumSeries(hello.metric)"); expect(func.render('hello.metric')).toEqual("sumSeries(hello.metric)");
}); });
it('should include default params if options enable it', function() { it('should include default params if options enable it', function() {
var func = gfunc.createFuncInstance('scaleToSeconds', { withDefaultParams: true }); var func = gfunc.createFuncInstance('scaleToSeconds', { withDefaultParams: true });
expect(func.render('hello')).to.equal("scaleToSeconds(hello, 1)"); expect(func.render('hello')).toEqual("scaleToSeconds(hello, 1)");
}); });
it('should handle int or interval params with number', function() { it('should handle int or interval params with number', function() {
var func = gfunc.createFuncInstance('movingMedian'); var func = gfunc.createFuncInstance('movingMedian');
func.params[0] = '5'; func.params[0] = '5';
expect(func.render('hello')).to.equal("movingMedian(hello, 5)"); expect(func.render('hello')).toEqual("movingMedian(hello, 5)");
}); });
it('should handle int or interval params with interval string', function() { it('should handle int or interval params with interval string', function() {
var func = gfunc.createFuncInstance('movingMedian'); var func = gfunc.createFuncInstance('movingMedian');
func.params[0] = '5min'; func.params[0] = '5min';
expect(func.render('hello')).to.equal("movingMedian(hello, '5min')"); expect(func.render('hello')).toEqual("movingMedian(hello, '5min')");
}); });
it('should handle metric param and int param and string param', function() { it('should handle metric param and int param and string param', function() {
var func = gfunc.createFuncInstance('groupByNode'); var func = gfunc.createFuncInstance('groupByNode');
func.params[0] = 5; func.params[0] = 5;
func.params[1] = 'avg'; func.params[1] = 'avg';
expect(func.render('hello.metric')).to.equal("groupByNode(hello.metric, 5, 'avg')"); expect(func.render('hello.metric')).toEqual("groupByNode(hello.metric, 5, 'avg')");
}); });
it('should handle function with no metric param', function() { it('should handle function with no metric param', function() {
var func = gfunc.createFuncInstance('randomWalk'); var func = gfunc.createFuncInstance('randomWalk');
func.params[0] = 'test'; func.params[0] = 'test';
expect(func.render(undefined)).to.equal("randomWalk('test')"); expect(func.render(undefined)).toEqual("randomWalk('test')");
}); });
it('should handle function multiple series params', function() { it('should handle function multiple series params', function() {
var func = gfunc.createFuncInstance('asPercent'); var func = gfunc.createFuncInstance('asPercent');
func.params[0] = '#B'; func.params[0] = '#B';
expect(func.render('#A')).to.equal("asPercent(#A, #B)"); expect(func.render('#A')).toEqual("asPercent(#A, #B)");
}); });
}); });
describe('when requesting function categories', function() { describe('when requesting function categories', function() {
it('should return function categories', function() { it('should return function categories', function() {
var catIndex = gfunc.getCategories(); var catIndex = gfunc.getCategories('1.0');
expect(catIndex.Special.length).to.be.greaterThan(8); expect(catIndex.Special.length).toBeGreaterThan(8);
}); });
}); });
...@@ -87,14 +85,14 @@ describe('when updating func param', function() { ...@@ -87,14 +85,14 @@ describe('when updating func param', function() {
it('should update param value and update text representation', function() { it('should update param value and update text representation', function() {
var func = gfunc.createFuncInstance('summarize', { withDefaultParams: true }); var func = gfunc.createFuncInstance('summarize', { withDefaultParams: true });
func.updateParam('1h', 0); func.updateParam('1h', 0);
expect(func.params[0]).to.be('1h'); expect(func.params[0]).toBe('1h');
expect(func.text).to.be('summarize(1h, sum, false)'); expect(func.text).toBe('summarize(1h, sum, false)');
}); });
it('should parse numbers as float', function() { it('should parse numbers as float', function() {
var func = gfunc.createFuncInstance('scale'); var func = gfunc.createFuncInstance('scale');
func.updateParam('0.001', 0); func.updateParam('0.001', 0);
expect(func.params[0]).to.be('0.001'); expect(func.params[0]).toBe('0.001');
}); });
}); });
...@@ -102,24 +100,24 @@ describe('when updating func param with optional second parameter', function() { ...@@ -102,24 +100,24 @@ describe('when updating func param with optional second parameter', function() {
it('should update value and text', function() { it('should update value and text', function() {
var func = gfunc.createFuncInstance('aliasByNode'); var func = gfunc.createFuncInstance('aliasByNode');
func.updateParam('1', 0); func.updateParam('1', 0);
expect(func.params[0]).to.be('1'); expect(func.params[0]).toBe('1');
}); });
it('should slit text and put value in second param', function() { it('should slit text and put value in second param', function() {
var func = gfunc.createFuncInstance('aliasByNode'); var func = gfunc.createFuncInstance('aliasByNode');
func.updateParam('4,-5', 0); func.updateParam('4,-5', 0);
expect(func.params[0]).to.be('4'); expect(func.params[0]).toBe('4');
expect(func.params[1]).to.be('-5'); expect(func.params[1]).toBe('-5');
expect(func.text).to.be('aliasByNode(4, -5)'); expect(func.text).toBe('aliasByNode(4, -5)');
}); });
it('should remove second param when empty string is set', function() { it('should remove second param when empty string is set', function() {
var func = gfunc.createFuncInstance('aliasByNode'); var func = gfunc.createFuncInstance('aliasByNode');
func.updateParam('4,-5', 0); func.updateParam('4,-5', 0);
func.updateParam('', 1); func.updateParam('', 1);
expect(func.params[0]).to.be('4'); expect(func.params[0]).toBe('4');
expect(func.params[1]).to.be(undefined); expect(func.params[1]).toBe(undefined);
expect(func.text).to.be('aliasByNode(4)'); expect(func.text).toBe('aliasByNode(4)');
}); });
}); });
import {describe, it, expect} from 'test/lib/common';
import {Lexer} from '../lexer'; import {Lexer} from '../lexer';
describe('when lexing graphite expression', function() { describe('when lexing graphite expression', function() {
...@@ -7,120 +5,120 @@ describe('when lexing graphite expression', function() { ...@@ -7,120 +5,120 @@ describe('when lexing graphite expression', function() {
it('should tokenize metric expression', function() { it('should tokenize metric expression', function() {
var lexer = new Lexer('metric.test.*.asd.count'); var lexer = new Lexer('metric.test.*.asd.count');
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].value).to.be('metric'); expect(tokens[0].value).toBe('metric');
expect(tokens[1].value).to.be('.'); expect(tokens[1].value).toBe('.');
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens[4].type).to.be('identifier'); expect(tokens[4].type).toBe('identifier');
expect(tokens[4].pos).to.be(13); expect(tokens[4].pos).toBe(13);
}); });
it('should tokenize metric expression with dash', function() { it('should tokenize metric expression with dash', function() {
var lexer = new Lexer('metric.test.se1-server-*.asd.count'); var lexer = new Lexer('metric.test.se1-server-*.asd.count');
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[4].type).to.be('identifier'); expect(tokens[4].type).toBe('identifier');
expect(tokens[4].value).to.be('se1-server-*'); expect(tokens[4].value).toBe('se1-server-*');
}); });
it('should tokenize metric expression with dash2', function() { it('should tokenize metric expression with dash2', function() {
var lexer = new Lexer('net.192-168-1-1.192-168-1-9.ping_value.*'); var lexer = new Lexer('net.192-168-1-1.192-168-1-9.ping_value.*');
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].value).to.be('net'); expect(tokens[0].value).toBe('net');
expect(tokens[2].value).to.be('192-168-1-1'); expect(tokens[2].value).toBe('192-168-1-1');
}); });
it('should tokenize metric expression with equal sign', function() { it('should tokenize metric expression with equal sign', function() {
var lexer = new Lexer('apps=test'); var lexer = new Lexer('apps=test');
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].value).to.be('apps=test'); expect(tokens[0].value).toBe('apps=test');
}); });
it('simple function2', function() { it('simple function2', function() {
var lexer = new Lexer('offset(test.metric, -100)'); var lexer = new Lexer('offset(test.metric, -100)');
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens[4].type).to.be('identifier'); expect(tokens[4].type).toBe('identifier');
expect(tokens[6].type).to.be('number'); expect(tokens[6].type).toBe('number');
}); });
it('should tokenize metric expression with curly braces', function() { it('should tokenize metric expression with curly braces', function() {
var lexer = new Lexer('metric.se1-{first, second}.count'); var lexer = new Lexer('metric.se1-{first, second}.count');
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens.length).to.be(10); expect(tokens.length).toBe(10);
expect(tokens[3].type).to.be('{'); expect(tokens[3].type).toBe('{');
expect(tokens[4].value).to.be('first'); expect(tokens[4].value).toBe('first');
expect(tokens[5].value).to.be(','); expect(tokens[5].value).toBe(',');
expect(tokens[6].value).to.be('second'); expect(tokens[6].value).toBe('second');
}); });
it('should tokenize metric expression with number segments', function() { it('should tokenize metric expression with number segments', function() {
var lexer = new Lexer("metric.10.12_10.test"); var lexer = new Lexer("metric.10.12_10.test");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].type).to.be('identifier'); expect(tokens[0].type).toBe('identifier');
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens[2].value).to.be('10'); expect(tokens[2].value).toBe('10');
expect(tokens[4].value).to.be('12_10'); expect(tokens[4].value).toBe('12_10');
expect(tokens[4].type).to.be('identifier'); expect(tokens[4].type).toBe('identifier');
}); });
it('should tokenize metric expression with segment that start with number', function() { it('should tokenize metric expression with segment that start with number', function() {
var lexer = new Lexer("metric.001-server"); var lexer = new Lexer("metric.001-server");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].type).to.be('identifier'); expect(tokens[0].type).toBe('identifier');
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens.length).to.be(3); expect(tokens.length).toBe(3);
}); });
it('should tokenize func call with numbered metric and number arg', function() { it('should tokenize func call with numbered metric and number arg', function() {
var lexer = new Lexer("scale(metric.10, 15)"); var lexer = new Lexer("scale(metric.10, 15)");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].type).to.be('identifier'); expect(tokens[0].type).toBe('identifier');
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens[2].value).to.be('metric'); expect(tokens[2].value).toBe('metric');
expect(tokens[4].value).to.be('10'); expect(tokens[4].value).toBe('10');
expect(tokens[4].type).to.be('number'); expect(tokens[4].type).toBe('number');
expect(tokens[6].type).to.be('number'); expect(tokens[6].type).toBe('number');
}); });
it('should tokenize metric with template parameter', function() { it('should tokenize metric with template parameter', function() {
var lexer = new Lexer("metric.[[server]].test"); var lexer = new Lexer("metric.[[server]].test");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens[2].value).to.be('[[server]]'); expect(tokens[2].value).toBe('[[server]]');
expect(tokens[4].type).to.be('identifier'); expect(tokens[4].type).toBe('identifier');
}); });
it('should tokenize metric with question mark', function() { it('should tokenize metric with question mark', function() {
var lexer = new Lexer("metric.server_??.test"); var lexer = new Lexer("metric.server_??.test");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[2].type).to.be('identifier'); expect(tokens[2].type).toBe('identifier');
expect(tokens[2].value).to.be('server_??'); expect(tokens[2].value).toBe('server_??');
expect(tokens[4].type).to.be('identifier'); expect(tokens[4].type).toBe('identifier');
}); });
it('should handle error with unterminated string', function() { it('should handle error with unterminated string', function() {
var lexer = new Lexer("alias(metric, 'asd)"); var lexer = new Lexer("alias(metric, 'asd)");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[0].value).to.be('alias'); expect(tokens[0].value).toBe('alias');
expect(tokens[1].value).to.be('('); expect(tokens[1].value).toBe('(');
expect(tokens[2].value).to.be('metric'); expect(tokens[2].value).toBe('metric');
expect(tokens[3].value).to.be(','); expect(tokens[3].value).toBe(',');
expect(tokens[4].type).to.be('string'); expect(tokens[4].type).toBe('string');
expect(tokens[4].isUnclosed).to.be(true); expect(tokens[4].isUnclosed).toBe(true);
expect(tokens[4].pos).to.be(20); expect(tokens[4].pos).toBe(20);
}); });
it('should handle float parameters', function() { it('should handle float parameters', function() {
var lexer = new Lexer("alias(metric, 0.002)"); var lexer = new Lexer("alias(metric, 0.002)");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[4].type).to.be('number'); expect(tokens[4].type).toBe('number');
expect(tokens[4].value).to.be('0.002'); expect(tokens[4].value).toBe('0.002');
}); });
it('should handle bool parameters', function() { it('should handle bool parameters', function() {
var lexer = new Lexer("alias(metric, true, false)"); var lexer = new Lexer("alias(metric, true, false)");
var tokens = lexer.tokenize(); var tokens = lexer.tokenize();
expect(tokens[4].type).to.be('bool'); expect(tokens[4].type).toBe('bool');
expect(tokens[4].value).to.be('true'); expect(tokens[4].value).toBe('true');
expect(tokens[6].type).to.be('bool'); expect(tokens[6].type).toBe('bool');
}); });
}); });
///<reference path="../../../headers/common.d.ts" />
import {MetricsPanelCtrl} from 'app/plugins/sdk'; import {MetricsPanelCtrl} from 'app/plugins/sdk';
import _ from 'lodash'; import _ from 'lodash';
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
import TimeSeries from 'app/core/time_series'; import TimeSeries from 'app/core/time_series2';
import {axesEditor} from './axes_editor'; import {axesEditor} from './axes_editor';
import {heatmapDisplayEditor} from './display_editor'; import {heatmapDisplayEditor} from './display_editor';
import rendering from './rendering'; import rendering from './rendering';
import {convertToHeatMap, convertToCards, elasticHistogramToHeatmap, calculateBucketSize, getMinLog} from './heatmap_data_converter'; import {convertToHeatMap, convertToCards, elasticHistogramToHeatmap, calculateBucketSize } from './heatmap_data_converter';
let X_BUCKET_NUMBER_DEFAULT = 30; let X_BUCKET_NUMBER_DEFAULT = 30;
let Y_BUCKET_NUMBER_DEFAULT = 10; let Y_BUCKET_NUMBER_DEFAULT = 10;
...@@ -250,7 +248,6 @@ export class HeatmapCtrl extends MetricsPanelCtrl { ...@@ -250,7 +248,6 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
}); });
series.flotpairs = series.getFlotPairs(this.panel.nullPointMode); series.flotpairs = series.getFlotPairs(this.panel.nullPointMode);
series.minLog = getMinLog(series);
let datapoints = seriesData.datapoints || []; let datapoints = seriesData.datapoints || [];
if (datapoints && datapoints.length > 0) { if (datapoints && datapoints.length > 0) {
...@@ -266,7 +263,7 @@ export class HeatmapCtrl extends MetricsPanelCtrl { ...@@ -266,7 +263,7 @@ export class HeatmapCtrl extends MetricsPanelCtrl {
parseSeries(series) { parseSeries(series) {
let min = _.min(_.map(series, s => s.stats.min)); let min = _.min(_.map(series, s => s.stats.min));
let minLog = _.min(_.map(series, s => s.minLog)); let minLog = _.min(_.map(series, s => s.stats.logmin));
let max = _.max(_.map(series, s => s.stats.max)); let max = _.max(_.map(series, s => s.stats.max));
return { return {
......
///<reference path="../../../headers/common.d.ts" />
import _ from 'lodash'; import _ from 'lodash';
let VALUE_INDEX = 0; let VALUE_INDEX = 0;
...@@ -320,12 +318,6 @@ function convertToLogScaleValueBuckets(xBucket, yBucketSplitFactor, logBase) { ...@@ -320,12 +318,6 @@ function convertToLogScaleValueBuckets(xBucket, yBucketSplitFactor, logBase) {
return buckets; return buckets;
} }
// Get minimum non zero value.
function getMinLog(series) {
let values = _.compact(_.map(series.datapoints, p => p[0]));
return _.min(values);
}
/** /**
* Logarithm for custom base * Logarithm for custom base
* @param value * @param value
...@@ -432,7 +424,6 @@ export { ...@@ -432,7 +424,6 @@ export {
elasticHistogramToHeatmap, elasticHistogramToHeatmap,
convertToCards, convertToCards,
mergeZeroBuckets, mergeZeroBuckets,
getMinLog,
getValueBucketBound, getValueBucketBound,
isHeatmapDataEqual, isHeatmapDataEqual,
calculateBucketSize calculateBucketSize
......
///<reference path="../../../../headers/common.d.ts" />
import _ from 'lodash'; import _ from 'lodash';
import { describe, beforeEach, it, expect } from '../../../../../test/lib/common'; import { describe, beforeEach, it, expect } from '../../../../../test/lib/common';
import TimeSeries from 'app/core/time_series2'; import TimeSeries from 'app/core/time_series2';
...@@ -45,23 +43,23 @@ describe('isHeatmapDataEqual', () => { ...@@ -45,23 +43,23 @@ describe('isHeatmapDataEqual', () => {
let emptyValues = _.cloneDeep(ctx.heatmapA); let emptyValues = _.cloneDeep(ctx.heatmapA);
emptyValues['1422774000000'].buckets['1'].values = []; emptyValues['1422774000000'].buckets['1'].values = [];
expect(isHeatmapDataEqual(ctx.heatmapA, ctx.heatmapB)).to.be(true); expect(isHeatmapDataEqual(ctx.heatmapA, ctx.heatmapB)).toBe(true);
expect(isHeatmapDataEqual(ctx.heatmapB, ctx.heatmapA)).to.be(true); expect(isHeatmapDataEqual(ctx.heatmapB, ctx.heatmapA)).toBe(true);
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapC)).to.be(true); expect(isHeatmapDataEqual(ctx.heatmapA, heatmapC)).toBe(true);
expect(isHeatmapDataEqual(heatmapC, ctx.heatmapA)).to.be(true); expect(isHeatmapDataEqual(heatmapC, ctx.heatmapA)).toBe(true);
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapD)).to.be(false); expect(isHeatmapDataEqual(ctx.heatmapA, heatmapD)).toBe(false);
expect(isHeatmapDataEqual(heatmapD, ctx.heatmapA)).to.be(false); expect(isHeatmapDataEqual(heatmapD, ctx.heatmapA)).toBe(false);
expect(isHeatmapDataEqual(ctx.heatmapA, heatmapE)).to.be(false); expect(isHeatmapDataEqual(ctx.heatmapA, heatmapE)).toBe(false);
expect(isHeatmapDataEqual(heatmapE, ctx.heatmapA)).to.be(false); expect(isHeatmapDataEqual(heatmapE, ctx.heatmapA)).toBe(false);
expect(isHeatmapDataEqual(empty, ctx.heatmapA)).to.be(false); expect(isHeatmapDataEqual(empty, ctx.heatmapA)).toBe(false);
expect(isHeatmapDataEqual(ctx.heatmapA, empty)).to.be(false); expect(isHeatmapDataEqual(ctx.heatmapA, empty)).toBe(false);
expect(isHeatmapDataEqual(emptyValues, ctx.heatmapA)).to.be(false); expect(isHeatmapDataEqual(emptyValues, ctx.heatmapA)).toBe(false);
expect(isHeatmapDataEqual(ctx.heatmapA, emptyValues)).to.be(false); expect(isHeatmapDataEqual(ctx.heatmapA, emptyValues)).toBe(false);
}); });
}); });
...@@ -87,7 +85,7 @@ describe('calculateBucketSize', () => { ...@@ -87,7 +85,7 @@ describe('calculateBucketSize', () => {
it('should properly calculate bucket size', () => { it('should properly calculate bucket size', () => {
_.each(ctx.bounds_set, (b) => { _.each(ctx.bounds_set, (b) => {
let bucketSize = calculateBucketSize(b.bounds, ctx.logBase); let bucketSize = calculateBucketSize(b.bounds, ctx.logBase);
expect(bucketSize).to.be(b.size); expect(bucketSize).toBe(b.size);
}); });
}); });
}); });
...@@ -108,7 +106,7 @@ describe('calculateBucketSize', () => { ...@@ -108,7 +106,7 @@ describe('calculateBucketSize', () => {
it('should properly calculate bucket size', () => { it('should properly calculate bucket size', () => {
_.each(ctx.bounds_set, (b) => { _.each(ctx.bounds_set, (b) => {
let bucketSize = calculateBucketSize(b.bounds, ctx.logBase); let bucketSize = calculateBucketSize(b.bounds, ctx.logBase);
expect(isEqual(bucketSize, b.size)).to.be(true); expect(isEqual(bucketSize, b.size)).toBe(true);
}); });
}); });
}); });
...@@ -162,7 +160,7 @@ describe('HeatmapDataConverter', () => { ...@@ -162,7 +160,7 @@ describe('HeatmapDataConverter', () => {
}; };
let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase); let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase);
expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true); expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).toBe(true);
}); });
}); });
...@@ -190,7 +188,7 @@ describe('HeatmapDataConverter', () => { ...@@ -190,7 +188,7 @@ describe('HeatmapDataConverter', () => {
}; };
let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase); let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase);
expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true); expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).toBe(true);
}); });
}); });
}); });
...@@ -240,7 +238,7 @@ describe('ES Histogram converter', () => { ...@@ -240,7 +238,7 @@ describe('ES Histogram converter', () => {
}; };
let heatmap = elasticHistogramToHeatmap(ctx.series); let heatmap = elasticHistogramToHeatmap(ctx.series);
expect(heatmap).to.eql(expectedHeatmap); expect(heatmap).toMatchObject(expectedHeatmap);
}); });
}); });
}); });
...@@ -273,13 +271,13 @@ describe('convertToCards', () => { ...@@ -273,13 +271,13 @@ describe('convertToCards', () => {
{x: 1422774060000, y: 2, count: 2, values: [2, 3], yBounds: {}} {x: 1422774060000, y: 2, count: 2, values: [2, 3], yBounds: {}}
]; ];
let res = convertToCards(buckets); let res = convertToCards(buckets);
expect(res.cards).to.eql(expectedCards); expect(res.cards).toMatchObject(expectedCards);
}); });
it('should build proper cards stats', () => { it('should build proper cards stats', () => {
let expectedStats = {min: 1, max: 2}; let expectedStats = {min: 1, max: 2};
let res = convertToCards(buckets); let res = convertToCards(buckets);
expect(res.cardStats).to.eql(expectedStats); expect(res.cardStats).toMatchObject(expectedStats);
}); });
}); });
......
///<reference path="../../../headers/common.d.ts" />
import _ from 'lodash'; import _ from 'lodash';
import moment from 'moment'; import moment from 'moment';
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
......
import {describe, it, expect} from 'test/lib/common';
import _ from 'lodash'; import _ from 'lodash';
import TableModel from 'app/core/table_model'; import TableModel from 'app/core/table_model';
import {TableRenderer} from '../renderer'; import {TableRenderer} from '../renderer';
...@@ -92,84 +90,84 @@ describe('when rendering table', () => { ...@@ -92,84 +90,84 @@ describe('when rendering table', () => {
it('time column should be formated', () => { it('time column should be formated', () => {
var html = renderer.renderCell(0, 0, 1388556366666); var html = renderer.renderCell(0, 0, 1388556366666);
expect(html).to.be('<td>2014-01-01T06:06:06Z</td>'); expect(html).toBe('<td>2014-01-01T06:06:06Z</td>');
}); });
it('undefined time column should be rendered as -', () => { it('undefined time column should be rendered as -', () => {
var html = renderer.renderCell(0, 0, undefined); var html = renderer.renderCell(0, 0, undefined);
expect(html).to.be('<td>-</td>'); expect(html).toBe('<td>-</td>');
}); });
it('null time column should be rendered as -', () => { it('null time column should be rendered as -', () => {
var html = renderer.renderCell(0, 0, null); var html = renderer.renderCell(0, 0, null);
expect(html).to.be('<td>-</td>'); expect(html).toBe('<td>-</td>');
}); });
it('number column with unit specified should ignore style unit', () => { it('number column with unit specified should ignore style unit', () => {
var html = renderer.renderCell(5, 0, 1230); var html = renderer.renderCell(5, 0, 1230);
expect(html).to.be('<td>1.23 kbps</td>'); expect(html).toBe('<td>1.23 kbps</td>');
}); });
it('number column should be formated', () => { it('number column should be formated', () => {
var html = renderer.renderCell(1, 0, 1230); var html = renderer.renderCell(1, 0, 1230);
expect(html).to.be('<td>1.230 s</td>'); expect(html).toBe('<td>1.230 s</td>');
}); });
it('number style should ignore string values', () => { it('number style should ignore string values', () => {
var html = renderer.renderCell(1, 0, 'asd'); var html = renderer.renderCell(1, 0, 'asd');
expect(html).to.be('<td>asd</td>'); expect(html).toBe('<td>asd</td>');
}); });
it('colored cell should have style', () => { it('colored cell should have style', () => {
var html = renderer.renderCell(2, 0, 40); var html = renderer.renderCell(2, 0, 40);
expect(html).to.be('<td style="color:green">40.0</td>'); expect(html).toBe('<td style="color:green">40.0</td>');
}); });
it('colored cell should have style', () => { it('colored cell should have style', () => {
var html = renderer.renderCell(2, 0, 55); var html = renderer.renderCell(2, 0, 55);
expect(html).to.be('<td style="color:orange">55.0</td>'); expect(html).toBe('<td style="color:orange">55.0</td>');
}); });
it('colored cell should have style', () => { it('colored cell should have style', () => {
var html = renderer.renderCell(2, 0, 85); var html = renderer.renderCell(2, 0, 85);
expect(html).to.be('<td style="color:red">85.0</td>'); expect(html).toBe('<td style="color:red">85.0</td>');
}); });
it('unformated undefined should be rendered as string', () => { it('unformated undefined should be rendered as string', () => {
var html = renderer.renderCell(3, 0, 'value'); var html = renderer.renderCell(3, 0, 'value');
expect(html).to.be('<td>value</td>'); expect(html).toBe('<td>value</td>');
}); });
it('string style with escape html should return escaped html', () => { it('string style with escape html should return escaped html', () => {
var html = renderer.renderCell(4, 0, "&breaking <br /> the <br /> row"); var html = renderer.renderCell(4, 0, "&breaking <br /> the <br /> row");
expect(html).to.be('<td>&amp;breaking &lt;br /&gt; the &lt;br /&gt; row</td>'); expect(html).toBe('<td>&amp;breaking &lt;br /&gt; the &lt;br /&gt; row</td>');
}); });
it('undefined formater should return escaped html', () => { it('undefined formater should return escaped html', () => {
var html = renderer.renderCell(3, 0, "&breaking <br /> the <br /> row"); var html = renderer.renderCell(3, 0, "&breaking <br /> the <br /> row");
expect(html).to.be('<td>&amp;breaking &lt;br /&gt; the &lt;br /&gt; row</td>'); expect(html).toBe('<td>&amp;breaking &lt;br /&gt; the &lt;br /&gt; row</td>');
}); });
it('undefined value should render as -', () => { it('undefined value should render as -', () => {
var html = renderer.renderCell(3, 0, undefined); var html = renderer.renderCell(3, 0, undefined);
expect(html).to.be('<td></td>'); expect(html).toBe('<td></td>');
}); });
it('sanitized value should render as', () => { it('sanitized value should render as', () => {
var html = renderer.renderCell(6, 0, 'text <a href="http://google.com">link</a>'); var html = renderer.renderCell(6, 0, 'text <a href="http://google.com">link</a>');
expect(html).to.be('<td>sanitized</td>'); expect(html).toBe('<td>sanitized</td>');
}); });
it('Time column title should be Timestamp', () => { it('Time column title should be Timestamp', () => {
expect(table.columns[0].title).to.be('Timestamp'); expect(table.columns[0].title).toBe('Timestamp');
}); });
it('Value column title should be Val', () => { it('Value column title should be Val', () => {
expect(table.columns[1].title).to.be('Val'); expect(table.columns[1].title).toBe('Val');
}); });
it('Colored column title should be Colored', () => { it('Colored column title should be Colored', () => {
expect(table.columns[2].title).to.be('Colored'); expect(table.columns[2].title).toBe('Colored');
}); });
it('link should render as', () => { it('link should render as', () => {
...@@ -182,7 +180,7 @@ describe('when rendering table', () => { ...@@ -182,7 +180,7 @@ describe('when rendering table', () => {
</a> </a>
</td> </td>
`; `;
expect(normalize(html)).to.be(normalize(expectedHtml)); expect(normalize(html)).toBe(normalize(expectedHtml));
}); });
}); });
}); });
......
import {describe, beforeEach, it, expect} from 'test/lib/common';
import {transformers, transformDataToTable} from '../transformers'; import {transformers, transformDataToTable} from '../transformers';
describe('when transforming time series table', () => { describe('when transforming time series table', () => {
...@@ -29,18 +27,18 @@ describe('when transforming time series table', () => { ...@@ -29,18 +27,18 @@ describe('when transforming time series table', () => {
}); });
it('should return 3 rows', () => { it('should return 3 rows', () => {
expect(table.rows.length).to.be(3); expect(table.rows.length).toBe(3);
expect(table.rows[0][1]).to.be('series1'); expect(table.rows[0][1]).toBe('series1');
expect(table.rows[1][1]).to.be('series1'); expect(table.rows[1][1]).toBe('series1');
expect(table.rows[2][1]).to.be('series2'); expect(table.rows[2][1]).toBe('series2');
expect(table.rows[0][2]).to.be(12.12); expect(table.rows[0][2]).toBe(12.12);
}); });
it('should return 3 rows', () => { it('should return 3 rows', () => {
expect(table.columns.length).to.be(3); expect(table.columns.length).toBe(3);
expect(table.columns[0].text).to.be('Time'); expect(table.columns[0].text).toBe('Time');
expect(table.columns[1].text).to.be('Metric'); expect(table.columns[1].text).toBe('Metric');
expect(table.columns[2].text).to.be('Value'); expect(table.columns[2].text).toBe('Value');
}); });
}); });
...@@ -54,20 +52,20 @@ describe('when transforming time series table', () => { ...@@ -54,20 +52,20 @@ describe('when transforming time series table', () => {
}); });
it ('should return 3 columns', () => { it ('should return 3 columns', () => {
expect(table.columns.length).to.be(3); expect(table.columns.length).toBe(3);
expect(table.columns[0].text).to.be('Time'); expect(table.columns[0].text).toBe('Time');
expect(table.columns[1].text).to.be('series1'); expect(table.columns[1].text).toBe('series1');
expect(table.columns[2].text).to.be('series2'); expect(table.columns[2].text).toBe('series2');
}); });
it ('should return 2 rows', () => { it ('should return 2 rows', () => {
expect(table.rows.length).to.be(2); expect(table.rows.length).toBe(2);
expect(table.rows[0][1]).to.be(12.12); expect(table.rows[0][1]).toBe(12.12);
expect(table.rows[0][2]).to.be(16.12); expect(table.rows[0][2]).toBe(16.12);
}); });
it ('should be undefined when no value for timestamp', () => { it ('should be undefined when no value for timestamp', () => {
expect(table.rows[1][2]).to.be(undefined); expect(table.rows[1][2]).toBe(undefined);
}); });
}); });
...@@ -83,17 +81,17 @@ describe('when transforming time series table', () => { ...@@ -83,17 +81,17 @@ describe('when transforming time series table', () => {
}); });
it('should return 2 rows', () => { it('should return 2 rows', () => {
expect(table.rows.length).to.be(2); expect(table.rows.length).toBe(2);
expect(table.rows[0][0]).to.be('series1'); expect(table.rows[0][0]).toBe('series1');
expect(table.rows[0][1]).to.be(14.44); expect(table.rows[0][1]).toBe(14.44);
expect(table.rows[0][2]).to.be(12.12); expect(table.rows[0][2]).toBe(12.12);
}); });
it('should return 2 columns', () => { it('should return 2 columns', () => {
expect(table.columns.length).to.be(3); expect(table.columns.length).toBe(3);
expect(table.columns[0].text).to.be('Metric'); expect(table.columns[0].text).toBe('Metric');
expect(table.columns[1].text).to.be('Max'); expect(table.columns[1].text).toBe('Max');
expect(table.columns[2].text).to.be('Min'); expect(table.columns[2].text).toBe('Min');
}); });
}); });
...@@ -124,9 +122,9 @@ describe('when transforming time series table', () => { ...@@ -124,9 +122,9 @@ describe('when transforming time series table', () => {
describe('getColumns', function() { describe('getColumns', function() {
it('should return nested properties', function() { it('should return nested properties', function() {
var columns = transformers['json'].getColumns(rawData); var columns = transformers['json'].getColumns(rawData);
expect(columns[0].text).to.be('timestamp'); expect(columns[0].text).toBe('timestamp');
expect(columns[1].text).to.be('message'); expect(columns[1].text).toBe('message');
expect(columns[2].text).to.be('nested.level2'); expect(columns[2].text).toBe('nested.level2');
}); });
}); });
...@@ -136,17 +134,17 @@ describe('when transforming time series table', () => { ...@@ -136,17 +134,17 @@ describe('when transforming time series table', () => {
}); });
it ('should return 2 columns', () => { it ('should return 2 columns', () => {
expect(table.columns.length).to.be(3); expect(table.columns.length).toBe(3);
expect(table.columns[0].text).to.be('Timestamp'); expect(table.columns[0].text).toBe('Timestamp');
expect(table.columns[1].text).to.be('Message'); expect(table.columns[1].text).toBe('Message');
expect(table.columns[2].text).to.be('nested.level2'); expect(table.columns[2].text).toBe('nested.level2');
}); });
it ('should return 2 rows', () => { it ('should return 2 rows', () => {
expect(table.rows.length).to.be(1); expect(table.rows.length).toBe(1);
expect(table.rows[0][0]).to.be('time'); expect(table.rows[0][0]).toBe('time');
expect(table.rows[0][1]).to.be('message'); expect(table.rows[0][1]).toBe('message');
expect(table.rows[0][2]).to.be('level2-value'); expect(table.rows[0][2]).toBe('level2-value');
}); });
}); });
}); });
...@@ -169,16 +167,16 @@ describe('when transforming time series table', () => { ...@@ -169,16 +167,16 @@ describe('when transforming time series table', () => {
}); });
it ('should return 4 columns', () => { it ('should return 4 columns', () => {
expect(table.columns.length).to.be(4); expect(table.columns.length).toBe(4);
expect(table.columns[0].text).to.be('Time'); expect(table.columns[0].text).toBe('Time');
expect(table.columns[1].text).to.be('Title'); expect(table.columns[1].text).toBe('Title');
expect(table.columns[2].text).to.be('Text'); expect(table.columns[2].text).toBe('Text');
expect(table.columns[3].text).to.be('Tags'); expect(table.columns[3].text).toBe('Tags');
}); });
it ('should return 1 rows', () => { it ('should return 1 rows', () => {
expect(table.rows.length).to.be(1); expect(table.rows.length).toBe(1);
expect(table.rows[0][0]).to.be(1000); expect(table.rows[0][0]).toBe(1000);
}); });
}); });
......
///<reference path="../../../headers/common.d.ts" />
import _ from 'lodash'; import _ from 'lodash';
import flatten from '../../../core/utils/flatten'; import flatten from '../../../core/utils/flatten';
import TimeSeries from '../../../core/time_series2'; import TimeSeries from '../../../core/time_series2';
......
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
declare var global: NodeJS.Global;
(<any>global).requestAnimationFrame = (callback) => {
setTimeout(callback, 0);
};
(function() {
"use strict";
// Tun on full stack traces in errors to help debugging
Error.stackTraceLimit=Infinity;
window.__karma__.loaded = function() {};
System.config({
baseURL: '/base/',
defaultJSExtensions: true,
paths: {
'mousetrap': 'vendor/npm/mousetrap/mousetrap.js',
'eventemitter3': 'vendor/npm/eventemitter3/index.js',
'remarkable': 'vendor/npm/remarkable/dist/remarkable.js',
'tether': 'vendor/npm/tether/dist/js/tether.js',
'tether-drop': 'vendor/npm/tether-drop/dist/js/drop.js',
'moment': 'vendor/moment.js',
"jquery": "vendor/jquery/dist/jquery.js",
'lodash-src': 'vendor/lodash/dist/lodash.js',
"lodash": 'app/core/lodash_extended.js',
"angular": 'vendor/angular/angular.js',
'angular-mocks': 'vendor/angular-mocks/angular-mocks.js',
"bootstrap": "vendor/bootstrap/bootstrap.js",
'angular-route': 'vendor/angular-route/angular-route.js',
'angular-sanitize': 'vendor/angular-sanitize/angular-sanitize.js',
"angular-ui": "vendor/angular-ui/ui-bootstrap-tpls.js",
"angular-strap": "vendor/angular-other/angular-strap.js",
"angular-dragdrop": "vendor/angular-native-dragdrop/draganddrop.js",
"angular-bindonce": "vendor/angular-bindonce/bindonce.js",
"spectrum": "vendor/spectrum.js",
"bootstrap-tagsinput": "vendor/tagsinput/bootstrap-tagsinput.js",
"jquery.flot": "vendor/flot/jquery.flot",
"jquery.flot.pie": "vendor/flot/jquery.flot.pie",
"jquery.flot.selection": "vendor/flot/jquery.flot.selection",
"jquery.flot.stack": "vendor/flot/jquery.flot.stack",
"jquery.flot.stackpercent": "vendor/flot/jquery.flot.stackpercent",
"jquery.flot.time": "vendor/flot/jquery.flot.time",
"jquery.flot.crosshair": "vendor/flot/jquery.flot.crosshair",
"jquery.flot.fillbelow": "vendor/flot/jquery.flot.fillbelow",
"jquery.flot.gauge": "vendor/flot/jquery.flot.gauge",
"d3": "vendor/d3/d3.js",
"jquery.flot.dashes": "vendor/flot/jquery.flot.dashes",
"twemoji": "vendor/npm/twemoji/2/twemoji.amd.js",
"ace": "vendor/npm/ace-builds/src-noconflict/ace",
},
packages: {
app: {
defaultExtension: 'js',
},
vendor: {
defaultExtension: 'js',
},
},
map: {
},
meta: {
'vendor/angular/angular.js': {
format: 'global',
deps: ['jquery'],
exports: 'angular',
},
'vendor/angular-mocks/angular-mocks.js': {
format: 'global',
deps: ['angular'],
},
'vendor/npm/eventemitter3/index.js': {
format: 'cjs',
exports: 'EventEmitter'
},
'vendor/npm/mousetrap/mousetrap.js': {
format: 'global',
exports: 'Mousetrap'
},
'vendor/npm/ace-builds/src-noconflict/ace.js': {
format: 'global',
exports: 'ace'
},
}
});
function file2moduleName(filePath) {
return filePath.replace(/\\/g, '/')
.replace(/^\/base\//, '')
.replace(/\.\w*$/, '');
}
function onlySpecFiles(path) {
return /specs.*/.test(path);
}
window.grafanaBootData = {settings: {}};
var modules = ['angular', 'angular-mocks', 'app/app'];
var promises = modules.map(function(name) {
return System.import(name);
});
Promise.all(promises).then(function(deps) {
var angular = deps[0];
angular.module('grafana', ['ngRoute']);
angular.module('grafana.services', ['ngRoute', '$strap.directives']);
angular.module('grafana.panels', []);
angular.module('grafana.controllers', []);
angular.module('grafana.directives', []);
angular.module('grafana.filters', []);
angular.module('grafana.routes', ['ngRoute']);
// load specs
return Promise.all(
Object.keys(window.__karma__.files) // All files served by Karma.
.filter(onlySpecFiles)
.map(file2moduleName)
.map(function(path) {
// console.log(path);
return System.import(path);
}));
}).then(function() {
window.__karma__.start();
}, function(error) {
window.__karma__.error(error.stack || error);
}).catch(function(error) {
window.__karma__.error(error.stack || error);
});
})();
...@@ -16,8 +16,16 @@ rm -rf node_modules ...@@ -16,8 +16,16 @@ rm -rf node_modules
npm install -g yarn --quiet npm install -g yarn --quiet
yarn install --pure-lockfile --no-progress yarn install --pure-lockfile --no-progress
exit_if_fail npm test exit_if_fail npm run test-ci
exit_if_fail npm build exit_if_fail npm run build
# publish code coverage
echo "Publishing javascript code coverage"
bash <(curl -s https://codecov.io/bash) -cF javascript
rm -rf coverage
# npm install -g codecov
# codecov
# cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js
echo "running go fmt" echo "running go fmt"
exit_if_fail test -z "$(gofmt -s -l ./pkg | tee /dev/stderr)" exit_if_fail test -z "$(gofmt -s -l ./pkg | tee /dev/stderr)"
...@@ -29,4 +37,17 @@ echo "building binaries" ...@@ -29,4 +37,17 @@ echo "building binaries"
exit_if_fail go run build.go build exit_if_fail go run build.go build
echo "running go test" echo "running go test"
exit_if_fail go test -v ./pkg/...
set -e
echo "" > coverage.txt
for d in $(go list ./pkg/...); do
exit_if_fail go test -race -coverprofile=profile.out -covermode=atomic $d
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out
fi
done
echo "Publishing go code coverage"
bash <(curl -s https://codecov.io/bash) -cF go
...@@ -14,6 +14,7 @@ module.exports = function(grunt) { ...@@ -14,6 +14,7 @@ module.exports = function(grunt) {
'jshint', 'jshint',
'sasslint', 'sasslint',
'exec:tslint', 'exec:tslint',
"exec:jest",
'karma:test', 'karma:test',
'no-only-tests' 'no-only-tests'
]); ]);
......
module.exports = function(config, grunt) { module.exports = function(config, grunt) {
'use strict' 'use strict'
var coverage = '';
if (config.coverage) {
coverage = '--coverage';
}
return { return {
tslint : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json --type-check", tslint : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json",
jest : "node ./node_modules/jest-cli/bin/jest.js " + coverage,
}; };
}; };
...@@ -26,6 +26,10 @@ module.exports = merge(common, { ...@@ -26,6 +26,10 @@ module.exports = merge(common, {
] ]
}, },
devServer: {
stats: 'errors-only',
},
plugins: [ plugins: [
new ExtractTextPlugin({ new ExtractTextPlugin({
filename: 'grafana.[name].css', filename: 'grafana.[name].css',
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
"rules": { "rules": {
"no-string-throw": true, "no-string-throw": true,
"no-unused-expression": true, "no-unused-expression": true,
"no-unused-variable": true, "no-unused-variable": false,
"no-use-before-declare": false,
"no-duplicate-variable": true, "no-duplicate-variable": true,
"curly": true, "curly": true,
"class-name": true, "class-name": true,
...@@ -33,7 +34,6 @@ ...@@ -33,7 +34,6 @@
"no-string-literal": false, "no-string-literal": false,
"no-switch-case-fall-through": false, "no-switch-case-fall-through": false,
"no-trailing-whitespace": true, "no-trailing-whitespace": true,
"no-use-before-declare": true,
"no-var-keyword": false, "no-var-keyword": false,
"object-literal-sort-keys": false, "object-literal-sort-keys": false,
"one-line": [true, "one-line": [true,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment