diff --git a/config/machine.json b/config/machine.json index 05c51f5..dce20c6 100644 --- a/config/machine.json +++ b/config/machine.json @@ -358,7 +358,58 @@ "fillOpacity": 10 } }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.min$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.max$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -404,7 +455,58 @@ "fillOpacity": 10 } }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.min$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.max$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -462,7 +564,58 @@ "fillOpacity": 10 } }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.min$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.max$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + } + ] }, "gridPos": { "h": 8, @@ -508,7 +661,58 @@ "fillOpacity": 10 } }, - "overrides": [] + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.min$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "orange" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": ".+\\.max$" + }, + "properties": [ + { + "id": "custom.lineStyle", + "value": { + "fill": "dash", + "dash": [ + 10, + 10 + ] + } + }, + { + "id": "color", + "value": { + "mode": "fixed", + "fixedColor": "red" + } + } + ] + } + ] }, "gridPos": { "h": 8, diff --git a/test/basic/slice38-dashed-bounds.basic.test.js b/test/basic/slice38-dashed-bounds.basic.test.js new file mode 100644 index 0000000..2960663 --- /dev/null +++ b/test/basic/slice38-dashed-bounds.basic.test.js @@ -0,0 +1,43 @@ +'use strict'; + +const test = require('node:test'); +const assert = require('node:assert/strict'); + +const DashboardApi = require('../../src/specificClass.js'); + +test('rotatingMachine template carries byRegexp dashed overrides for .min/.max', () => { + const api = new DashboardApi({}); + const dash = api.loadTemplate('machine'); + const ts = dash.panels.filter((p) => p.type === 'timeseries'); + assert.ok(ts.length >= 1, 'has at least one timeseries panel'); + + for (const panel of ts) { + const overrides = panel?.fieldConfig?.overrides || []; + const minOv = overrides.find( + (o) => o.matcher?.id === 'byRegexp' && /\.min\$/.test(o.matcher?.options || '') + ); + const maxOv = overrides.find( + (o) => o.matcher?.id === 'byRegexp' && /\.max\$/.test(o.matcher?.options || '') + ); + assert.ok(minOv, `panel "${panel.title}" missing .min override`); + assert.ok(maxOv, `panel "${panel.title}" missing .max override`); + + const lineStyle = minOv.properties.find((p) => p.id === 'custom.lineStyle'); + assert.equal(lineStyle?.value?.fill, 'dash', '.min override sets dashed lineStyle'); + assert.deepEqual(lineStyle?.value?.dash, [10, 10], '.min override sets dash pattern [10,10]'); + } +}); + +test('dashed overrides are forward-compatible: no effect when fields absent', () => { + // The byRegexp matcher only affects series whose name ends in .min/.max. + // When the node doesn't emit those fields, the override has no effect on + // the rendered panel — series simply don't appear. Verified by the + // matcher pattern being a strict regex. + const api = new DashboardApi({}); + const dash = api.loadTemplate('machine'); + const ts = dash.panels.filter((p) => p.type === 'timeseries')[0]; + const minOv = ts.fieldConfig.overrides.find( + (o) => o.matcher?.id === 'byRegexp' && /\.min\$/.test(o.matcher.options || '') + ); + assert.match(minOv.matcher.options, /\$$/, 'matcher anchored to end of name'); +});