* Broken dash repro * Fix V16 migration to preserve panels when rows array is empty - Fixed bug where panels were deleted when migrating dashboards with empty rows array - Updated v16.go to match frontend implementation behavior - Added test case for empty rows scenario in v16_test.go - Renamed test files to v16.empty-rows-and-panels-array.json for clarity - All migration tests passing (419 test cases)
1465 lines
31 KiB
Go
1465 lines
31 KiB
Go
package schemaversion_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
|
)
|
|
|
|
func TestV16(t *testing.T) {
|
|
tests := []migrationTestCase{
|
|
{
|
|
name: "should handle repeatIteration null",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
map[string]interface{}{
|
|
"collapse": false,
|
|
"showTitle": true,
|
|
"title": "Overview",
|
|
"type": "row",
|
|
"repeat": nil,
|
|
"repeatIteration": nil,
|
|
"repeatRowId": nil,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"type": "stat",
|
|
"span": 12,
|
|
"title": "Customer Stats",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
// The stat panel should be processed and added
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"type": "stat",
|
|
"title": "Customer Stats",
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 24,
|
|
"h": 7, // default height
|
|
},
|
|
},
|
|
// The row panel should be created because showTitle is true
|
|
map[string]interface{}{
|
|
"id": 3, // Next ID after max panel ID (2)
|
|
"type": "row",
|
|
"title": "Overview",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 7, // default height
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should create proper grid",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ collapse: false, height: 8 }, [[6], [6]])
|
|
map[string]interface{}{
|
|
"collapse": false,
|
|
"height": 304, // 8 * 38 (PANEL_HEIGHT_STEP)
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should add special row panel if row is collapsed",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ collapse: true, height: 8 }, [[6], [6]])
|
|
map[string]interface{}{
|
|
"collapse": true,
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
// createRow({ height: 8 }, [[12]])
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 4, // Next ID after max panel ID (3)
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": true,
|
|
"repeat": "",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 2,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5, // Next ID after row panel (4)
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should add special row panel if row has visible title",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ showTitle: true, title: 'Row', height: 8 }, [[6], [6]])
|
|
map[string]interface{}{
|
|
"showTitle": true,
|
|
"title": "Row",
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
// createRow({ height: 8 }, [[12]])
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4, // Next ID after max panel ID (3)
|
|
"type": "row",
|
|
"title": "Row",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 10,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5, // Next ID after row panel (4)
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 9,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should not add row panel if row has not visible title or not collapsed",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
map[string]interface{}{
|
|
"collapse": true,
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 1,
|
|
},
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 3,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 5,
|
|
},
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"collapse": true,
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 6,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
// First row: collapsed row (panels go in collapsed row's panels array, row panel added after)
|
|
map[string]interface{}{
|
|
"id": 7,
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": true,
|
|
"repeat": "",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
// Second row: normal row (regular panel first, then row panel)
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 2,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 8,
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
// Third row: normal row (regular panels first, then row panel)
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 11,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 19,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 19,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 9,
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 10,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
// Fourth row: collapsed row (panels go in collapsed row's panels array, row panel added after)
|
|
map[string]interface{}{
|
|
"id": 10,
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": true,
|
|
"repeat": "",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 6,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 28,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 27,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should add all rows if even one collapsed or titled row is present",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ collapse: true, height: 8 }, [[6], [6]])
|
|
map[string]interface{}{
|
|
"collapse": true,
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
// createRow({ height: 8 }, [[12]])
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 4, // Next ID after max panel ID (3)
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": true,
|
|
"repeat": "",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 2,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5, // Next ID after row panel (4)
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should properly place panels with fixed height",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ height: 6 }, [[6], [6, 3], [6, 3]])
|
|
map[string]interface{}{
|
|
"height": 228, // 6 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"height": 114, // 3 * 38
|
|
"id": 2,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"height": 114, // 3 * 38
|
|
"id": 3,
|
|
},
|
|
},
|
|
},
|
|
// createRow({ height: 6 }, [[4], [4], [4, 3], [4, 3]])
|
|
map[string]interface{}{
|
|
"height": 228, // 6 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"id": 5,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"height": 114, // 3 * 38
|
|
"id": 6,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"height": 114, // 3 * 38
|
|
"id": 7,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 12,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 12,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 3,
|
|
"w": 12,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 6,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 6,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 6,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 16,
|
|
"y": 6,
|
|
"w": 8,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 7,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 16,
|
|
"y": 9,
|
|
"w": 8,
|
|
"h": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should place panel to the right side of panel having bigger height",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ height: 6 }, [[4], [2, 3], [4, 6], [2, 3], [2, 3]])
|
|
map[string]interface{}{
|
|
"height": 228, // 6 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 2,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"height": 228, // 6 * 38
|
|
"id": 3,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 5,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"height": 228, // 6 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 3,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should fill current row if it possible",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ height: 9 }, [[4], [2, 3], [4, 6], [2, 3], [2, 3], [8, 3]])
|
|
map[string]interface{}{
|
|
"height": 342, // 9 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 2,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"height": 228, // 6 * 38
|
|
"id": 3,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 5,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 8,
|
|
"height": 114, // 3 * 38
|
|
"id": 6,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 9,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"height": 228, // 6 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 3,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 6,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 6,
|
|
"w": 16,
|
|
"h": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should fill current row if it possible (2)",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ height: 8 }, [[4], [2, 3], [4, 6], [2, 3], [2, 3], [8, 3]])
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 2,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"height": 228, // 6 * 38
|
|
"id": 3,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 5,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 8,
|
|
"height": 114, // 3 * 38
|
|
"id": 6,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"height": 228, // 6 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 3,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 6,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 6,
|
|
"w": 16,
|
|
"h": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should fill current row if panel height more than row height",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ height: 6 }, [[4], [2, 3], [4, 8], [2, 3], [2, 3]])
|
|
map[string]interface{}{
|
|
"height": 228, // 6 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 2,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 4,
|
|
"height": 304, // 8 * 38
|
|
"id": 3,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 2,
|
|
"height": 114, // 3 * 38
|
|
"id": 5,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 8,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"height": 304, // 8 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 8,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 0,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"height": 114, // 3 * 38
|
|
"gridPos": map[string]interface{}{
|
|
"x": 20,
|
|
"y": 3,
|
|
"w": 4,
|
|
"h": 3,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should wrap panels to multiple rows",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
// createRow({ height: 6 }, [[6], [6], [12], [6], [3], [3]])
|
|
map[string]interface{}{
|
|
"height": 228, // 6 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 2,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 3,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 4,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 3,
|
|
"id": 5,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 3,
|
|
"id": 6,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 12,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 0,
|
|
"w": 12,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 6,
|
|
"w": 24,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 12,
|
|
"w": 12,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 5,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 12,
|
|
"w": 6,
|
|
"h": 6,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 6,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 18,
|
|
"y": 12,
|
|
"w": 6,
|
|
"h": 6,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should add repeated row if repeat set",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
map[string]interface{}{
|
|
"showTitle": true,
|
|
"title": "Row",
|
|
"height": 304, // 8 * 38
|
|
"repeat": "server",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 12,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
// Panel from first row
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
// Repeated row panel (comes after its panels)
|
|
map[string]interface{}{
|
|
"id": 3,
|
|
"type": "row",
|
|
"title": "Row",
|
|
"collapsed": false,
|
|
"repeat": "server",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
// Panel from second row
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 10,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
// Second row panel (comes after its panels)
|
|
map[string]interface{}{
|
|
"id": 4,
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": false,
|
|
"repeat": "",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 9,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should ignore repeated row",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
map[string]interface{}{
|
|
"showTitle": true,
|
|
"title": "Row1",
|
|
"height": 304, // 8 * 38
|
|
"repeat": "server",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"showTitle": true,
|
|
"title": "Row2",
|
|
"height": 304, // 8 * 38
|
|
"repeatIteration": 12313,
|
|
"repeatRowId": 1,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 3, // Next ID after max panel ID (2)
|
|
"type": "row",
|
|
"title": "Row1",
|
|
"collapsed": false,
|
|
"repeat": "server",
|
|
"panels": []interface{}{},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should assign id",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{
|
|
map[string]interface{}{
|
|
"collapse": true,
|
|
"height": 304, // 8 * 38
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
"id": 1,
|
|
},
|
|
map[string]interface{}{
|
|
"span": 6,
|
|
// no id - should be assigned
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 3, // Next ID after max panel ID (1) and assigned panel ID (2)
|
|
"type": "row",
|
|
"title": "",
|
|
"collapsed": true,
|
|
"repeat": "",
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2, // Should be assigned the next available ID
|
|
"gridPos": map[string]interface{}{
|
|
"x": 12,
|
|
"y": 1,
|
|
"w": 12,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"x": 0,
|
|
"y": 0,
|
|
"w": 24,
|
|
"h": 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "should preserve existing panels when rows array is empty",
|
|
input: map[string]interface{}{
|
|
"schemaVersion": 15,
|
|
"rows": []interface{}{},
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"type": "graph",
|
|
"title": "Existing Panel",
|
|
"datasource": map[string]interface{}{
|
|
"uid": "test-ds",
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"h": 8,
|
|
"w": 12,
|
|
"x": 0,
|
|
"y": 0,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"type": "stat",
|
|
"title": "Another Panel",
|
|
"gridPos": map[string]interface{}{
|
|
"h": 8,
|
|
"w": 12,
|
|
"x": 12,
|
|
"y": 0,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]interface{}{
|
|
"schemaVersion": 16,
|
|
// panels should be preserved exactly as they were
|
|
"panels": []interface{}{
|
|
map[string]interface{}{
|
|
"id": 1,
|
|
"type": "graph",
|
|
"title": "Existing Panel",
|
|
"datasource": map[string]interface{}{
|
|
"uid": "test-ds",
|
|
},
|
|
"gridPos": map[string]interface{}{
|
|
"h": 8,
|
|
"w": 12,
|
|
"x": 0,
|
|
"y": 0,
|
|
},
|
|
},
|
|
map[string]interface{}{
|
|
"id": 2,
|
|
"type": "stat",
|
|
"title": "Another Panel",
|
|
"gridPos": map[string]interface{}{
|
|
"h": 8,
|
|
"w": 12,
|
|
"x": 12,
|
|
"y": 0,
|
|
},
|
|
},
|
|
},
|
|
// rows field should be removed
|
|
},
|
|
},
|
|
}
|
|
|
|
runMigrationTests(t, tests, schemaversion.V16)
|
|
}
|