DashboardModel.repeat.test.ts 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. import _ from 'lodash';
  2. import { DashboardModel } from '../state/DashboardModel';
  3. import { expect } from 'test/lib/common';
  4. jest.mock('app/core/services/context_srv', () => ({}));
  5. describe('given dashboard with panel repeat', () => {
  6. let dashboard;
  7. beforeEach(() => {
  8. const dashboardJSON = {
  9. panels: [
  10. { id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 } },
  11. { id: 2, repeat: 'apps', repeatDirection: 'h', gridPos: { x: 0, y: 1, h: 2, w: 8 } },
  12. ],
  13. templating: {
  14. list: [
  15. {
  16. name: 'apps',
  17. current: {
  18. text: 'se1, se2, se3',
  19. value: ['se1', 'se2', 'se3'],
  20. },
  21. options: [
  22. { text: 'se1', value: 'se1', selected: true },
  23. { text: 'se2', value: 'se2', selected: true },
  24. { text: 'se3', value: 'se3', selected: true },
  25. { text: 'se4', value: 'se4', selected: false },
  26. ],
  27. },
  28. ],
  29. },
  30. };
  31. dashboard = new DashboardModel(dashboardJSON);
  32. dashboard.processRepeats();
  33. });
  34. it('should repeat panels when row is expanding', () => {
  35. expect(dashboard.panels.length).toBe(4);
  36. // toggle row
  37. dashboard.toggleRow(dashboard.panels[0]);
  38. expect(dashboard.panels.length).toBe(1);
  39. // change variable
  40. dashboard.templating.list[0].options[2].selected = false;
  41. dashboard.templating.list[0].current = {
  42. text: 'se1, se2',
  43. value: ['se1', 'se2'],
  44. };
  45. // toggle row back
  46. dashboard.toggleRow(dashboard.panels[0]);
  47. expect(dashboard.panels.length).toBe(3);
  48. });
  49. });
  50. describe('given dashboard with panel repeat in horizontal direction', () => {
  51. let dashboard;
  52. beforeEach(() => {
  53. dashboard = new DashboardModel({
  54. panels: [
  55. {
  56. id: 2,
  57. repeat: 'apps',
  58. repeatDirection: 'h',
  59. gridPos: { x: 0, y: 0, h: 2, w: 24 },
  60. },
  61. ],
  62. templating: {
  63. list: [
  64. {
  65. name: 'apps',
  66. current: {
  67. text: 'se1, se2, se3',
  68. value: ['se1', 'se2', 'se3'],
  69. },
  70. options: [
  71. { text: 'se1', value: 'se1', selected: true },
  72. { text: 'se2', value: 'se2', selected: true },
  73. { text: 'se3', value: 'se3', selected: true },
  74. { text: 'se4', value: 'se4', selected: false },
  75. ],
  76. },
  77. ],
  78. },
  79. });
  80. dashboard.processRepeats();
  81. });
  82. it('should repeat panel 3 times', () => {
  83. expect(dashboard.panels.length).toBe(3);
  84. });
  85. it('should mark panel repeated', () => {
  86. expect(dashboard.panels[0].repeat).toBe('apps');
  87. expect(dashboard.panels[1].repeatPanelId).toBe(2);
  88. });
  89. it('should set scopedVars on panels', () => {
  90. expect(dashboard.panels[0].scopedVars.apps.value).toBe('se1');
  91. expect(dashboard.panels[1].scopedVars.apps.value).toBe('se2');
  92. expect(dashboard.panels[2].scopedVars.apps.value).toBe('se3');
  93. });
  94. it('should place on first row and adjust width so all fit', () => {
  95. expect(dashboard.panels[0].gridPos).toMatchObject({
  96. x: 0,
  97. y: 0,
  98. h: 2,
  99. w: 8,
  100. });
  101. expect(dashboard.panels[1].gridPos).toMatchObject({
  102. x: 8,
  103. y: 0,
  104. h: 2,
  105. w: 8,
  106. });
  107. expect(dashboard.panels[2].gridPos).toMatchObject({
  108. x: 16,
  109. y: 0,
  110. h: 2,
  111. w: 8,
  112. });
  113. });
  114. describe('After a second iteration', () => {
  115. beforeEach(() => {
  116. dashboard.panels[0].fill = 10;
  117. dashboard.processRepeats();
  118. });
  119. it('reused panel should copy properties from source', () => {
  120. expect(dashboard.panels[1].fill).toBe(10);
  121. });
  122. it('should have same panel count', () => {
  123. expect(dashboard.panels.length).toBe(3);
  124. });
  125. });
  126. describe('After a second iteration with different variable', () => {
  127. beforeEach(() => {
  128. dashboard.templating.list.push({
  129. name: 'server',
  130. current: { text: 'se1, se2, se3', value: ['se1'] },
  131. options: [{ text: 'se1', value: 'se1', selected: true }],
  132. });
  133. dashboard.panels[0].repeat = 'server';
  134. dashboard.processRepeats();
  135. });
  136. it('should remove scopedVars value for last variable', () => {
  137. expect(dashboard.panels[0].scopedVars.apps).toBe(undefined);
  138. });
  139. it('should have new variable value in scopedVars', () => {
  140. expect(dashboard.panels[0].scopedVars.server.value).toBe('se1');
  141. });
  142. });
  143. describe('After a second iteration and selected values reduced', () => {
  144. beforeEach(() => {
  145. dashboard.templating.list[0].options[1].selected = false;
  146. dashboard.processRepeats();
  147. });
  148. it('should clean up repeated panel', () => {
  149. expect(dashboard.panels.length).toBe(2);
  150. });
  151. });
  152. describe('After a second iteration and panel repeat is turned off', () => {
  153. beforeEach(() => {
  154. dashboard.panels[0].repeat = null;
  155. dashboard.processRepeats();
  156. });
  157. it('should clean up repeated panel', () => {
  158. expect(dashboard.panels.length).toBe(1);
  159. });
  160. it('should remove scoped vars from reused panel', () => {
  161. expect(dashboard.panels[0].scopedVars).toBe(undefined);
  162. });
  163. });
  164. });
  165. describe('given dashboard with panel repeat in vertical direction', () => {
  166. let dashboard;
  167. beforeEach(() => {
  168. dashboard = new DashboardModel({
  169. panels: [
  170. { id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 } },
  171. { id: 2, repeat: 'apps', repeatDirection: 'v', gridPos: { x: 5, y: 1, h: 2, w: 8 } },
  172. { id: 3, type: 'row', gridPos: { x: 0, y: 3, h: 1, w: 24 } },
  173. ],
  174. templating: {
  175. list: [
  176. {
  177. name: 'apps',
  178. current: {
  179. text: 'se1, se2, se3',
  180. value: ['se1', 'se2', 'se3'],
  181. },
  182. options: [
  183. { text: 'se1', value: 'se1', selected: true },
  184. { text: 'se2', value: 'se2', selected: true },
  185. { text: 'se3', value: 'se3', selected: true },
  186. { text: 'se4', value: 'se4', selected: false },
  187. ],
  188. },
  189. ],
  190. },
  191. });
  192. dashboard.processRepeats();
  193. });
  194. it('should place on items on top of each other and keep witdh', () => {
  195. expect(dashboard.panels[0].gridPos).toMatchObject({ x: 0, y: 0, h: 1, w: 24 }); // first row
  196. expect(dashboard.panels[1].gridPos).toMatchObject({ x: 5, y: 1, h: 2, w: 8 });
  197. expect(dashboard.panels[2].gridPos).toMatchObject({ x: 5, y: 3, h: 2, w: 8 });
  198. expect(dashboard.panels[3].gridPos).toMatchObject({ x: 5, y: 5, h: 2, w: 8 });
  199. expect(dashboard.panels[4].gridPos).toMatchObject({ x: 0, y: 7, h: 1, w: 24 }); // last row
  200. });
  201. });
  202. describe('given dashboard with row repeat and panel repeat in horizontal direction', () => {
  203. let dashboard, dashboardJSON;
  204. beforeEach(() => {
  205. dashboardJSON = {
  206. panels: [
  207. { id: 1, type: 'row', repeat: 'region', gridPos: { x: 0, y: 0, h: 1, w: 24 } },
  208. { id: 2, type: 'graph', repeat: 'app', gridPos: { x: 0, y: 1, h: 2, w: 6 } },
  209. ],
  210. templating: {
  211. list: [
  212. {
  213. name: 'region',
  214. current: {
  215. text: 'reg1, reg2',
  216. value: ['reg1', 'reg2'],
  217. },
  218. options: [{ text: 'reg1', value: 'reg1', selected: true }, { text: 'reg2', value: 'reg2', selected: true }],
  219. },
  220. {
  221. name: 'app',
  222. current: {
  223. text: 'se1, se2, se3, se4, se5, se6',
  224. value: ['se1', 'se2', 'se3', 'se4', 'se5', 'se6'],
  225. },
  226. options: [
  227. { text: 'se1', value: 'se1', selected: true },
  228. { text: 'se2', value: 'se2', selected: true },
  229. { text: 'se3', value: 'se3', selected: true },
  230. { text: 'se4', value: 'se4', selected: true },
  231. { text: 'se5', value: 'se5', selected: true },
  232. { text: 'se6', value: 'se6', selected: true },
  233. ],
  234. },
  235. ],
  236. },
  237. };
  238. dashboard = new DashboardModel(dashboardJSON);
  239. dashboard.processRepeats(false);
  240. });
  241. it('should panels in self row', () => {
  242. const panelTypes = _.map(dashboard.panels, 'type');
  243. expect(panelTypes).toEqual([
  244. 'row',
  245. 'graph',
  246. 'graph',
  247. 'graph',
  248. 'graph',
  249. 'graph',
  250. 'graph',
  251. 'row',
  252. 'graph',
  253. 'graph',
  254. 'graph',
  255. 'graph',
  256. 'graph',
  257. 'graph',
  258. ]);
  259. });
  260. it('should be placed in their places', () => {
  261. expect(dashboard.panels[0].gridPos).toMatchObject({ x: 0, y: 0, h: 1, w: 24 }); // 1st row
  262. expect(dashboard.panels[1].gridPos).toMatchObject({ x: 0, y: 1, h: 2, w: 6 });
  263. expect(dashboard.panels[2].gridPos).toMatchObject({ x: 6, y: 1, h: 2, w: 6 });
  264. expect(dashboard.panels[3].gridPos).toMatchObject({ x: 12, y: 1, h: 2, w: 6 });
  265. expect(dashboard.panels[4].gridPos).toMatchObject({ x: 18, y: 1, h: 2, w: 6 });
  266. expect(dashboard.panels[5].gridPos).toMatchObject({ x: 0, y: 3, h: 2, w: 6 }); // next row
  267. expect(dashboard.panels[6].gridPos).toMatchObject({ x: 6, y: 3, h: 2, w: 6 });
  268. expect(dashboard.panels[7].gridPos).toMatchObject({ x: 0, y: 5, h: 1, w: 24 });
  269. expect(dashboard.panels[8].gridPos).toMatchObject({ x: 0, y: 6, h: 2, w: 6 }); // 2nd row
  270. expect(dashboard.panels[9].gridPos).toMatchObject({ x: 6, y: 6, h: 2, w: 6 });
  271. expect(dashboard.panels[10].gridPos).toMatchObject({ x: 12, y: 6, h: 2, w: 6 });
  272. expect(dashboard.panels[11].gridPos).toMatchObject({ x: 18, y: 6, h: 2, w: 6 }); // next row
  273. expect(dashboard.panels[12].gridPos).toMatchObject({ x: 0, y: 8, h: 2, w: 6 });
  274. expect(dashboard.panels[13].gridPos).toMatchObject({ x: 6, y: 8, h: 2, w: 6 });
  275. });
  276. });
  277. describe('given dashboard with row repeat', () => {
  278. let dashboard, dashboardJSON;
  279. beforeEach(() => {
  280. dashboardJSON = {
  281. panels: [
  282. {
  283. id: 1,
  284. type: 'row',
  285. gridPos: { x: 0, y: 0, h: 1, w: 24 },
  286. repeat: 'apps',
  287. },
  288. { id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 1, w: 6 } },
  289. { id: 3, type: 'graph', gridPos: { x: 6, y: 1, h: 1, w: 6 } },
  290. { id: 4, type: 'row', gridPos: { x: 0, y: 2, h: 1, w: 24 } },
  291. { id: 5, type: 'graph', gridPos: { x: 0, y: 3, h: 1, w: 12 } },
  292. ],
  293. templating: {
  294. list: [
  295. {
  296. name: 'apps',
  297. current: {
  298. text: 'se1, se2',
  299. value: ['se1', 'se2'],
  300. },
  301. options: [
  302. { text: 'se1', value: 'se1', selected: true },
  303. { text: 'se2', value: 'se2', selected: true },
  304. { text: 'se3', value: 'se3', selected: false },
  305. ],
  306. },
  307. ],
  308. },
  309. };
  310. dashboard = new DashboardModel(dashboardJSON);
  311. dashboard.processRepeats();
  312. });
  313. it('should not repeat only row', () => {
  314. const panelTypes = _.map(dashboard.panels, 'type');
  315. expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph', 'row', 'graph']);
  316. });
  317. it('should set scopedVars for each panel', () => {
  318. dashboardJSON.templating.list[0].options[2].selected = true;
  319. dashboard = new DashboardModel(dashboardJSON);
  320. dashboard.processRepeats();
  321. expect(dashboard.panels[1].scopedVars).toMatchObject({
  322. apps: { text: 'se1', value: 'se1' },
  323. });
  324. expect(dashboard.panels[4].scopedVars).toMatchObject({
  325. apps: { text: 'se2', value: 'se2' },
  326. });
  327. const scopedVars = _.compact(
  328. _.map(dashboard.panels, panel => {
  329. return panel.scopedVars ? panel.scopedVars.apps.value : null;
  330. })
  331. );
  332. expect(scopedVars).toEqual(['se1', 'se1', 'se1', 'se2', 'se2', 'se2', 'se3', 'se3', 'se3']);
  333. });
  334. it('should repeat only configured row', () => {
  335. expect(dashboard.panels[6].id).toBe(4);
  336. expect(dashboard.panels[7].id).toBe(5);
  337. });
  338. it('should repeat only row if it is collapsed', () => {
  339. dashboardJSON.panels = [
  340. {
  341. id: 1,
  342. type: 'row',
  343. collapsed: true,
  344. repeat: 'apps',
  345. gridPos: { x: 0, y: 0, h: 1, w: 24 },
  346. panels: [
  347. { id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 1, w: 6 } },
  348. { id: 3, type: 'graph', gridPos: { x: 6, y: 1, h: 1, w: 6 } },
  349. ],
  350. },
  351. { id: 4, type: 'row', gridPos: { x: 0, y: 1, h: 1, w: 24 } },
  352. { id: 5, type: 'graph', gridPos: { x: 0, y: 2, h: 1, w: 12 } },
  353. ];
  354. dashboard = new DashboardModel(dashboardJSON);
  355. dashboard.processRepeats();
  356. const panelTypes = _.map(dashboard.panels, 'type');
  357. expect(panelTypes).toEqual(['row', 'row', 'row', 'graph']);
  358. expect(dashboard.panels[0].panels).toHaveLength(2);
  359. expect(dashboard.panels[1].panels).toHaveLength(2);
  360. });
  361. it('should properly repeat multiple rows', () => {
  362. dashboardJSON.panels = [
  363. {
  364. id: 1,
  365. type: 'row',
  366. gridPos: { x: 0, y: 0, h: 1, w: 24 },
  367. repeat: 'apps',
  368. }, // repeat
  369. { id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 1, w: 6 } },
  370. { id: 3, type: 'graph', gridPos: { x: 6, y: 1, h: 1, w: 6 } },
  371. { id: 4, type: 'row', gridPos: { x: 0, y: 2, h: 1, w: 24 } }, // don't touch
  372. { id: 5, type: 'graph', gridPos: { x: 0, y: 3, h: 1, w: 12 } },
  373. {
  374. id: 6,
  375. type: 'row',
  376. gridPos: { x: 0, y: 4, h: 1, w: 24 },
  377. repeat: 'hosts',
  378. }, // repeat
  379. { id: 7, type: 'graph', gridPos: { x: 0, y: 5, h: 1, w: 6 } },
  380. { id: 8, type: 'graph', gridPos: { x: 6, y: 5, h: 1, w: 6 } },
  381. ];
  382. dashboardJSON.templating.list.push({
  383. name: 'hosts',
  384. current: {
  385. text: 'backend01, backend02',
  386. value: ['backend01', 'backend02'],
  387. },
  388. options: [
  389. { text: 'backend01', value: 'backend01', selected: true },
  390. { text: 'backend02', value: 'backend02', selected: true },
  391. { text: 'backend03', value: 'backend03', selected: false },
  392. ],
  393. });
  394. dashboard = new DashboardModel(dashboardJSON);
  395. dashboard.processRepeats();
  396. const panelTypes = _.map(dashboard.panels, 'type');
  397. expect(panelTypes).toEqual([
  398. 'row',
  399. 'graph',
  400. 'graph',
  401. 'row',
  402. 'graph',
  403. 'graph',
  404. 'row',
  405. 'graph',
  406. 'row',
  407. 'graph',
  408. 'graph',
  409. 'row',
  410. 'graph',
  411. 'graph',
  412. ]);
  413. expect(dashboard.panels[0].scopedVars['apps'].value).toBe('se1');
  414. expect(dashboard.panels[1].scopedVars['apps'].value).toBe('se1');
  415. expect(dashboard.panels[3].scopedVars['apps'].value).toBe('se2');
  416. expect(dashboard.panels[4].scopedVars['apps'].value).toBe('se2');
  417. expect(dashboard.panels[8].scopedVars['hosts'].value).toBe('backend01');
  418. expect(dashboard.panels[9].scopedVars['hosts'].value).toBe('backend01');
  419. expect(dashboard.panels[11].scopedVars['hosts'].value).toBe('backend02');
  420. expect(dashboard.panels[12].scopedVars['hosts'].value).toBe('backend02');
  421. });
  422. it('should assign unique ids for repeated panels', () => {
  423. dashboardJSON.panels = [
  424. {
  425. id: 1,
  426. type: 'row',
  427. collapsed: true,
  428. repeat: 'apps',
  429. gridPos: { x: 0, y: 0, h: 1, w: 24 },
  430. panels: [
  431. { id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 1, w: 6 } },
  432. { id: 3, type: 'graph', gridPos: { x: 6, y: 1, h: 1, w: 6 } },
  433. ],
  434. },
  435. { id: 4, type: 'row', gridPos: { x: 0, y: 1, h: 1, w: 24 } },
  436. { id: 5, type: 'graph', gridPos: { x: 0, y: 2, h: 1, w: 12 } },
  437. ];
  438. dashboard = new DashboardModel(dashboardJSON);
  439. dashboard.processRepeats();
  440. const panelIds = _.flattenDeep(
  441. _.map(dashboard.panels, panel => {
  442. let ids = [];
  443. if (panel.panels && panel.panels.length) {
  444. ids = _.map(panel.panels, 'id');
  445. }
  446. ids.push(panel.id);
  447. return ids;
  448. })
  449. );
  450. expect(panelIds.length).toEqual(_.uniq(panelIds).length);
  451. });
  452. it('should place new panels in proper order', () => {
  453. dashboardJSON.panels = [
  454. { id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 }, repeat: 'apps' },
  455. { id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 3, w: 12 } },
  456. { id: 3, type: 'graph', gridPos: { x: 6, y: 1, h: 4, w: 12 } },
  457. { id: 4, type: 'graph', gridPos: { x: 0, y: 5, h: 2, w: 12 } },
  458. ];
  459. dashboard = new DashboardModel(dashboardJSON);
  460. dashboard.processRepeats();
  461. const panelTypes = _.map(dashboard.panels, 'type');
  462. expect(panelTypes).toEqual(['row', 'graph', 'graph', 'graph', 'row', 'graph', 'graph', 'graph']);
  463. const panelYPositions = _.map(dashboard.panels, p => p.gridPos.y);
  464. expect(panelYPositions).toEqual([0, 1, 1, 5, 7, 8, 8, 12]);
  465. });
  466. });
  467. describe('given dashboard with row and panel repeat', () => {
  468. let dashboard, dashboardJSON;
  469. beforeEach(() => {
  470. dashboardJSON = {
  471. panels: [
  472. {
  473. id: 1,
  474. type: 'row',
  475. repeat: 'region',
  476. gridPos: { x: 0, y: 0, h: 1, w: 24 },
  477. },
  478. { id: 2, type: 'graph', repeat: 'app', gridPos: { x: 0, y: 1, h: 1, w: 6 } },
  479. ],
  480. templating: {
  481. list: [
  482. {
  483. name: 'region',
  484. current: {
  485. text: 'reg1, reg2',
  486. value: ['reg1', 'reg2'],
  487. },
  488. options: [
  489. { text: 'reg1', value: 'reg1', selected: true },
  490. { text: 'reg2', value: 'reg2', selected: true },
  491. { text: 'reg3', value: 'reg3', selected: false },
  492. ],
  493. },
  494. {
  495. name: 'app',
  496. current: {
  497. text: 'se1, se2',
  498. value: ['se1', 'se2'],
  499. },
  500. options: [
  501. { text: 'se1', value: 'se1', selected: true },
  502. { text: 'se2', value: 'se2', selected: true },
  503. { text: 'se3', value: 'se3', selected: false },
  504. ],
  505. },
  506. ],
  507. },
  508. };
  509. dashboard = new DashboardModel(dashboardJSON);
  510. dashboard.processRepeats();
  511. });
  512. it('should repeat row and panels for each row', () => {
  513. const panelTypes = _.map(dashboard.panels, 'type');
  514. expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
  515. });
  516. it('should clean up old repeated panels', () => {
  517. dashboardJSON.panels = [
  518. {
  519. id: 1,
  520. type: 'row',
  521. repeat: 'region',
  522. gridPos: { x: 0, y: 0, h: 1, w: 24 },
  523. },
  524. { id: 2, type: 'graph', repeat: 'app', gridPos: { x: 0, y: 1, h: 1, w: 6 } },
  525. { id: 3, type: 'graph', repeatPanelId: 2, repeatIteration: 101, gridPos: { x: 7, y: 1, h: 1, w: 6 } },
  526. {
  527. id: 11,
  528. type: 'row',
  529. repeatPanelId: 1,
  530. repeatIteration: 101,
  531. gridPos: { x: 0, y: 2, h: 1, w: 24 },
  532. },
  533. { id: 12, type: 'graph', repeatPanelId: 2, repeatIteration: 101, gridPos: { x: 0, y: 3, h: 1, w: 6 } },
  534. ];
  535. dashboard = new DashboardModel(dashboardJSON);
  536. dashboard.processRepeats();
  537. const panelTypes = _.map(dashboard.panels, 'type');
  538. expect(panelTypes).toEqual(['row', 'graph', 'graph', 'row', 'graph', 'graph']);
  539. });
  540. it('should set scopedVars for each row', () => {
  541. dashboard = new DashboardModel(dashboardJSON);
  542. dashboard.processRepeats();
  543. expect(dashboard.panels[0].scopedVars).toMatchObject({
  544. region: { text: 'reg1', value: 'reg1' },
  545. });
  546. expect(dashboard.panels[3].scopedVars).toMatchObject({
  547. region: { text: 'reg2', value: 'reg2' },
  548. });
  549. });
  550. it('should set panel-repeat variable for each panel', () => {
  551. dashboard = new DashboardModel(dashboardJSON);
  552. dashboard.processRepeats();
  553. expect(dashboard.panels[1].scopedVars).toMatchObject({
  554. app: { text: 'se1', value: 'se1' },
  555. });
  556. expect(dashboard.panels[2].scopedVars).toMatchObject({
  557. app: { text: 'se2', value: 'se2' },
  558. });
  559. expect(dashboard.panels[4].scopedVars).toMatchObject({
  560. app: { text: 'se1', value: 'se1' },
  561. });
  562. expect(dashboard.panels[5].scopedVars).toMatchObject({
  563. app: { text: 'se2', value: 'se2' },
  564. });
  565. });
  566. it('should set row-repeat variable for each panel', () => {
  567. dashboard = new DashboardModel(dashboardJSON);
  568. dashboard.processRepeats();
  569. expect(dashboard.panels[1].scopedVars).toMatchObject({
  570. region: { text: 'reg1', value: 'reg1' },
  571. });
  572. expect(dashboard.panels[2].scopedVars).toMatchObject({
  573. region: { text: 'reg1', value: 'reg1' },
  574. });
  575. expect(dashboard.panels[4].scopedVars).toMatchObject({
  576. region: { text: 'reg2', value: 'reg2' },
  577. });
  578. expect(dashboard.panels[5].scopedVars).toMatchObject({
  579. region: { text: 'reg2', value: 'reg2' },
  580. });
  581. });
  582. it('should repeat panels when row is expanding', () => {
  583. dashboard = new DashboardModel(dashboardJSON);
  584. dashboard.processRepeats();
  585. expect(dashboard.panels.length).toBe(6);
  586. // toggle row
  587. dashboard.toggleRow(dashboard.panels[0]);
  588. dashboard.toggleRow(dashboard.panels[1]);
  589. expect(dashboard.panels.length).toBe(2);
  590. // change variable
  591. dashboard.templating.list[1].current.value = ['se1', 'se2', 'se3'];
  592. // toggle row back
  593. dashboard.toggleRow(dashboard.panels[1]);
  594. expect(dashboard.panels.length).toBe(4);
  595. });
  596. });