diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 1830b3eb161..e9a3c8059f8 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -18,6 +18,7 @@ import ( ) func TestMiddlewareContext(t *testing.T) { + setting.ERR_TEMPLATE_NAME = "error-template" Convey("Given the grafana middleware", t, func() { middlewareScenario("middleware should add context to injector", func(sc *scenarioContext) { diff --git a/pkg/middleware/recovery.go b/pkg/middleware/recovery.go index 456bc91354e..eef07c8c24a 100644 --- a/pkg/middleware/recovery.go +++ b/pkg/middleware/recovery.go @@ -138,7 +138,7 @@ func Recovery() macaron.Handler { c.JSON(500, resp) } else { - c.HTML(500, "error") + c.HTML(500, setting.ERR_TEMPLATE_NAME) } } }() diff --git a/pkg/middleware/recovery_test.go b/pkg/middleware/recovery_test.go index 4bbedbc3b21..c92150f3b7d 100644 --- a/pkg/middleware/recovery_test.go +++ b/pkg/middleware/recovery_test.go @@ -8,11 +8,14 @@ import ( "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/session" + "github.com/grafana/grafana/pkg/setting" . "github.com/smartystreets/goconvey/convey" "gopkg.in/macaron.v1" ) func TestRecoveryMiddleware(t *testing.T) { + setting.ERR_TEMPLATE_NAME = "error-template" + Convey("Given an api route that panics", t, func() { apiURL := "/api/whatever" recoveryScenario("recovery middleware should return json", apiURL, func(sc *scenarioContext) { @@ -50,6 +53,7 @@ func recoveryScenario(desc string, url string, fn scenarioFunc) { sc := &scenarioContext{ url: url, } + viewsPath, _ := filepath.Abs("../../public/views") sc.m = macaron.New() diff --git a/pkg/models/context.go b/pkg/models/context.go index 262f6550954..c78028665a6 100644 --- a/pkg/models/context.go +++ b/pkg/models/context.go @@ -36,7 +36,7 @@ func (ctx *ReqContext) Handle(status int, title string, err error) { ctx.Data["AppSubUrl"] = setting.AppSubUrl ctx.Data["Theme"] = "dark" - ctx.HTML(status, "error") + ctx.HTML(status, setting.ERR_TEMPLATE_NAME) } func (ctx *ReqContext) JsonOK(message string) { diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 9e8f6fec9a8..afae642f5b3 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -38,6 +38,10 @@ const ( APP_NAME_ENTERPRISE = "Grafana Enterprise" ) +var ( + ERR_TEMPLATE_NAME = "error" +) + var ( // App settings. Env = DEV diff --git a/public/app/features/dashboard/specs/panel_model.test.ts b/public/app/features/dashboard/specs/panel_model.test.ts new file mode 100644 index 00000000000..b1e31ce3f91 --- /dev/null +++ b/public/app/features/dashboard/specs/panel_model.test.ts @@ -0,0 +1,72 @@ +import _ from 'lodash'; +import { PanelModel } from '../panel_model'; + +describe('PanelModel', () => { + describe('when creating new panel model', () => { + let model; + + beforeEach(() => { + model = new PanelModel({}); + }); + + it('should apply defaults', () => { + expect(model.gridPos.h).toBe(3); + }); + + it('getSaveModel should remove defaults', () => { + const saveModel = model.getSaveModel(); + expect(saveModel.gridPos).toBe(undefined); + }); + + it('getSaveModel should remove nonPersistedProperties', () => { + const saveModel = model.getSaveModel(); + expect(saveModel.events).toBe(undefined); + }); + + describe('when calling applyDefaults', () => { + beforeEach(() => { + const defaults = { + myName: 'My name', + myBool1: true, + myBool2: false, + myNumber: 0, + nestedObj: { + myName: 'nested name', + myBool1: true, + myBool2: false, + myNumber: 0, + }, + }; + model.applyDefaults(defaults); + }); + + it('Should apply defaults', () => { + expect(model.myName).toBe('My name'); + expect(model.myBool1).toBe(true); + expect(model.myBool2).toBe(false); + expect(model.myNumber).toBe(0); + expect(model.nestedObj.myName).toBe('nested name'); + expect(model.nestedObj.myBool1).toBe(true); + expect(model.nestedObj.myBool2).toBe(false); + expect(model.nestedObj.myNumber).toBe(0); + }); + + it('getSaveModel should remove them', () => { + const saveModel = model.getSaveModel(); + expect(saveModel.myName).toBe(undefined); + expect(saveModel.nestedObj).toBe(undefined); + }); + + it('getSaveModel should remove only unchanged defaults', () => { + model.myName = 'changed'; + model.nestedObj.myBool2 = true; + + const saveModel = model.getSaveModel(); + + expect(saveModel.myName).toBe('changed'); + expect(saveModel.nestedObj.myBool2).toBe(true); + expect(saveModel.nestedObj.myBool1).toBe(undefined); + }); + }); + }); +}); diff --git a/public/views/error.template.html b/public/views/error-template.html similarity index 100% rename from public/views/error.template.html rename to public/views/error-template.html diff --git a/public/views/index.template.html b/public/views/index-template.html similarity index 100% rename from public/views/index.template.html rename to public/views/index-template.html diff --git a/scripts/webpack/webpack.common.js b/scripts/webpack/webpack.common.js index 7da6c3559bf..ae7222e8374 100644 --- a/scripts/webpack/webpack.common.js +++ b/scripts/webpack/webpack.common.js @@ -47,7 +47,7 @@ module.exports = { }, { test: /\.html$/, - exclude: /(index|error)\.template\.html/, + exclude: /(index|error)\-template\.html/, use: [ { loader: 'ngtemplate-loader?relativeTo=' + (path.resolve(__dirname, '../../public')) + '&prefix=public' }, { diff --git a/scripts/webpack/webpack.dev.js b/scripts/webpack/webpack.dev.js index 456cc277f2f..228df79b3f8 100644 --- a/scripts/webpack/webpack.dev.js +++ b/scripts/webpack/webpack.dev.js @@ -84,12 +84,12 @@ module.exports = merge(common, { }), new HtmlWebpackPlugin({ filename: path.resolve(__dirname, '../../public/views/error.html'), - template: path.resolve(__dirname, '../../public/views/error.template.html'), + template: path.resolve(__dirname, '../../public/views/error-template.html'), inject: 'false', }), new HtmlWebpackPlugin({ filename: path.resolve(__dirname, '../../public/views/index.html'), - template: path.resolve(__dirname, '../../public/views/index.template.html'), + template: path.resolve(__dirname, '../../public/views/index-template.html'), inject: 'body', chunks: ['manifest', 'vendor', 'app'], }), diff --git a/scripts/webpack/webpack.hot.js b/scripts/webpack/webpack.hot.js index 0305a6f465c..dd3cc8c1190 100644 --- a/scripts/webpack/webpack.hot.js +++ b/scripts/webpack/webpack.hot.js @@ -87,7 +87,7 @@ module.exports = merge(common, { new CleanWebpackPlugin('../public/build', { allowExternal: true }), new HtmlWebpackPlugin({ filename: path.resolve(__dirname, '../../public/views/index.html'), - template: path.resolve(__dirname, '../../public/views/index.template.html'), + template: path.resolve(__dirname, '../../public/views/index-template.html'), inject: 'body', alwaysWriteToDisk: true }), diff --git a/scripts/webpack/webpack.prod.js b/scripts/webpack/webpack.prod.js index c4b4b27245e..5d3ffa61219 100644 --- a/scripts/webpack/webpack.prod.js +++ b/scripts/webpack/webpack.prod.js @@ -76,13 +76,13 @@ module.exports = merge(common, { new ngAnnotatePlugin(), new HtmlWebpackPlugin({ filename: path.resolve(__dirname, '../../public/views/index.html'), - template: path.resolve(__dirname, '../../public/views/index.template.html'), + template: path.resolve(__dirname, '../../public/views/index-template.html'), inject: 'body', chunks: ['vendor', 'app'], }), new HtmlWebpackPlugin({ filename: path.resolve(__dirname, '../../public/views/error.html'), - template: path.resolve(__dirname, '../../public/views/error.template.html'), + template: path.resolve(__dirname, '../../public/views/error-template.html'), inject: false, }), function () {