1import { dateTime, TimeRange } from '@grafana/data'; 2import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv'; 3import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput'; 4import { VariableAdapter, variableAdapters } from '../variables/adapters'; 5import { createQueryVariableAdapter } from '../variables/query/adapter'; 6import { createAdHocVariableAdapter } from '../variables/adhoc/adapter'; 7import { VariableModel } from '../variables/types'; 8import { FormatRegistryID } from './formatRegistry'; 9import { setDataSourceSrv } from '@grafana/runtime'; 10import { mockDataSource, MockDataSourceSrv } from '../alerting/unified/mocks'; 11 12variableAdapters.setInit(() => [ 13 (createQueryVariableAdapter() as unknown) as VariableAdapter<VariableModel>, 14 (createAdHocVariableAdapter() as unknown) as VariableAdapter<VariableModel>, 15]); 16 17describe('templateSrv', () => { 18 silenceConsoleOutput(); 19 let _templateSrv: any; 20 21 describe('init', () => { 22 beforeEach(() => { 23 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'oogle' } }]); 24 }); 25 26 it('should initialize template data', () => { 27 const target = _templateSrv.replace('this.[[test]].filters'); 28 expect(target).toBe('this.oogle.filters'); 29 }); 30 }); 31 32 describe('replace can pass scoped vars', () => { 33 beforeEach(() => { 34 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'oogle' } }]); 35 }); 36 37 it('scoped vars should support objects', () => { 38 const target = _templateSrv.replace('${series.name} ${series.nested.field}', { 39 series: { value: { name: 'Server1', nested: { field: 'nested' } } }, 40 }); 41 expect(target).toBe('Server1 nested'); 42 }); 43 44 it('built in vars should support objects', () => { 45 _templateSrv.setGlobalVariable('__dashboard', { 46 value: { name: 'hello' }, 47 }); 48 const target = _templateSrv.replace('${__dashboard.name}'); 49 expect(target).toBe('hello'); 50 }); 51 52 it('scoped vars should support objects with propert names with dot', () => { 53 const target = _templateSrv.replace('${series.name} ${series.nested["field.with.dot"]}', { 54 series: { value: { name: 'Server1', nested: { 'field.with.dot': 'nested' } } }, 55 }); 56 expect(target).toBe('Server1 nested'); 57 }); 58 59 it('scoped vars should support arrays of objects', () => { 60 const target = _templateSrv.replace('${series.rows[0].name} ${series.rows[1].name}', { 61 series: { value: { rows: [{ name: 'first' }, { name: 'second' }] } }, 62 }); 63 expect(target).toBe('first second'); 64 }); 65 66 it('should replace $test with scoped value', () => { 67 const target = _templateSrv.replace('this.$test.filters', { 68 test: { value: 'mupp', text: 'asd' }, 69 }); 70 expect(target).toBe('this.mupp.filters'); 71 }); 72 73 it('should replace ${test} with scoped value', () => { 74 const target = _templateSrv.replace('this.${test}.filters', { 75 test: { value: 'mupp', text: 'asd' }, 76 }); 77 expect(target).toBe('this.mupp.filters'); 78 }); 79 80 it('should replace ${test:glob} with scoped value', () => { 81 const target = _templateSrv.replace('this.${test:glob}.filters', { 82 test: { value: 'mupp', text: 'asd' }, 83 }); 84 expect(target).toBe('this.mupp.filters'); 85 }); 86 87 it('should replace $test with scoped text', () => { 88 const target = _templateSrv.replaceWithText('this.$test.filters', { 89 test: { value: 'mupp', text: 'asd' }, 90 }); 91 expect(target).toBe('this.asd.filters'); 92 }); 93 94 it('should replace ${test} with scoped text', () => { 95 const target = _templateSrv.replaceWithText('this.${test}.filters', { 96 test: { value: 'mupp', text: 'asd' }, 97 }); 98 expect(target).toBe('this.asd.filters'); 99 }); 100 101 it('should replace ${test.name} with scoped text', () => { 102 const target = _templateSrv.replaceWithText('this.${test.name}.filters', { 103 test: { value: { name: 'mupp' }, text: 'asd' }, 104 }); 105 expect(target).toBe('this.mupp.filters'); 106 }); 107 108 it('should not replace ${test:glob} with scoped text', () => { 109 const target = _templateSrv.replaceWithText('this.${test:glob}.filters', { 110 test: { value: 'mupp', text: 'asd' }, 111 }); 112 expect(target).toBe('this.mupp.filters'); 113 }); 114 }); 115 116 describe('getAdhocFilters', () => { 117 beforeEach(() => { 118 _templateSrv = initTemplateSrv([ 119 { 120 type: 'datasource', 121 name: 'ds', 122 current: { value: 'logstash', text: 'logstash' }, 123 }, 124 { type: 'adhoc', name: 'test', datasource: { uid: 'oogle' }, filters: [1] }, 125 { type: 'adhoc', name: 'test2', datasource: { uid: '$ds' }, filters: [2] }, 126 ]); 127 setDataSourceSrv( 128 new MockDataSourceSrv({ 129 oogle: mockDataSource({ 130 name: 'oogle', 131 uid: 'oogle', 132 }), 133 }) 134 ); 135 }); 136 137 it('should return filters if datasourceName match', () => { 138 const filters = _templateSrv.getAdhocFilters('oogle'); 139 expect(filters).toMatchObject([1]); 140 }); 141 142 it('should return empty array if datasourceName does not match', () => { 143 const filters = _templateSrv.getAdhocFilters('oogleasdasd'); 144 expect(filters).toMatchObject([]); 145 }); 146 147 it('should return filters when datasourceName match via data source variable', () => { 148 const filters = _templateSrv.getAdhocFilters('logstash'); 149 expect(filters).toMatchObject([2]); 150 }); 151 }); 152 153 describe('replace can pass multi / all format', () => { 154 beforeEach(() => { 155 _templateSrv = initTemplateSrv([ 156 { 157 type: 'query', 158 name: 'test', 159 current: { value: ['value1', 'value2'] }, 160 }, 161 ]); 162 }); 163 164 it('should replace $test with globbed value', () => { 165 const target = _templateSrv.replace('this.$test.filters', {}, 'glob'); 166 expect(target).toBe('this.{value1,value2}.filters'); 167 }); 168 169 describe('when the globbed variable only has one value', () => { 170 beforeEach(() => { 171 _templateSrv = initTemplateSrv([ 172 { 173 type: 'query', 174 name: 'test', 175 current: { value: ['value1'] }, 176 }, 177 ]); 178 }); 179 180 it('should not glob the value', () => { 181 const target = _templateSrv.replace('this.$test.filters', {}, 'glob'); 182 expect(target).toBe('this.value1.filters'); 183 }); 184 }); 185 186 it('should replace ${test} with globbed value', () => { 187 const target = _templateSrv.replace('this.${test}.filters', {}, 'glob'); 188 expect(target).toBe('this.{value1,value2}.filters'); 189 }); 190 191 it('should replace ${test:glob} with globbed value', () => { 192 const target = _templateSrv.replace('this.${test:glob}.filters', {}); 193 expect(target).toBe('this.{value1,value2}.filters'); 194 }); 195 196 it('should replace $test with piped value', () => { 197 const target = _templateSrv.replace('this=$test', {}, 'pipe'); 198 expect(target).toBe('this=value1|value2'); 199 }); 200 201 it('should replace ${test} with piped value', () => { 202 const target = _templateSrv.replace('this=${test}', {}, 'pipe'); 203 expect(target).toBe('this=value1|value2'); 204 }); 205 206 it('should replace ${test:pipe} with piped value', () => { 207 const target = _templateSrv.replace('this=${test:pipe}', {}); 208 expect(target).toBe('this=value1|value2'); 209 }); 210 211 it('should replace ${test:pipe} with piped value and $test with globbed value', () => { 212 const target = _templateSrv.replace('${test:pipe},$test', {}, 'glob'); 213 expect(target).toBe('value1|value2,{value1,value2}'); 214 }); 215 }); 216 217 describe('variable with all option', () => { 218 beforeEach(() => { 219 _templateSrv = initTemplateSrv([ 220 { 221 type: 'query', 222 name: 'test', 223 current: { value: '$__all' }, 224 options: [{ value: '$__all' }, { value: 'value1' }, { value: 'value2' }], 225 }, 226 ]); 227 }); 228 229 it('should replace $test with formatted all value', () => { 230 const target = _templateSrv.replace('this.$test.filters', {}, 'glob'); 231 expect(target).toBe('this.{value1,value2}.filters'); 232 }); 233 234 it('should replace ${test} with formatted all value', () => { 235 const target = _templateSrv.replace('this.${test}.filters', {}, 'glob'); 236 expect(target).toBe('this.{value1,value2}.filters'); 237 }); 238 239 it('should replace ${test:glob} with formatted all value', () => { 240 const target = _templateSrv.replace('this.${test:glob}.filters', {}); 241 expect(target).toBe('this.{value1,value2}.filters'); 242 }); 243 244 it('should replace ${test:pipe} with piped value and $test with globbed value', () => { 245 const target = _templateSrv.replace('${test:pipe},$test', {}, 'glob'); 246 expect(target).toBe('value1|value2,{value1,value2}'); 247 }); 248 249 it('should replace ${test:queryparam} with correct query parameter', () => { 250 const target = _templateSrv.replace('${test:queryparam}', {}); 251 expect(target).toBe('var-test=All'); 252 }); 253 }); 254 255 describe('variable with all option and custom value', () => { 256 beforeEach(() => { 257 _templateSrv = initTemplateSrv([ 258 { 259 type: 'query', 260 name: 'test', 261 current: { value: '$__all' }, 262 allValue: '*', 263 options: [{ value: 'value1' }, { value: 'value2' }], 264 }, 265 ]); 266 }); 267 268 it('should replace $test with formatted all value', () => { 269 const target = _templateSrv.replace('this.$test.filters', {}, 'glob'); 270 expect(target).toBe('this.*.filters'); 271 }); 272 273 it('should replace ${test} with formatted all value', () => { 274 const target = _templateSrv.replace('this.${test}.filters', {}, 'glob'); 275 expect(target).toBe('this.*.filters'); 276 }); 277 278 it('should replace ${test:glob} with formatted all value', () => { 279 const target = _templateSrv.replace('this.${test:glob}.filters', {}); 280 expect(target).toBe('this.*.filters'); 281 }); 282 283 it('should replace ${test:text} with "all" value', () => { 284 const target = _templateSrv.replace('this.${test:text}.filters', {}); 285 expect(target).toBe('this.All.filters'); 286 }); 287 288 it('should not escape custom all value', () => { 289 const target = _templateSrv.replace('this.$test', {}, 'regex'); 290 expect(target).toBe('this.*'); 291 }); 292 293 it('should replace ${test:queryparam} with correct query parameter', () => { 294 const target = _templateSrv.replace('${test:queryparam}', {}); 295 expect(target).toBe('var-test=All'); 296 }); 297 }); 298 299 describe('lucene format', () => { 300 it('should properly escape $test with lucene escape sequences', () => { 301 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'value/4' } }]); 302 const target = _templateSrv.replace('this:$test', {}, 'lucene'); 303 expect(target).toBe('this:value\\/4'); 304 }); 305 306 it('should properly escape ${test} with lucene escape sequences', () => { 307 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'value/4' } }]); 308 const target = _templateSrv.replace('this:${test}', {}, 'lucene'); 309 expect(target).toBe('this:value\\/4'); 310 }); 311 312 it('should properly escape ${test:lucene} with lucene escape sequences', () => { 313 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'value/4' } }]); 314 const target = _templateSrv.replace('this:${test:lucene}', {}); 315 expect(target).toBe('this:value\\/4'); 316 }); 317 }); 318 319 describe('html format', () => { 320 it('should encode values html escape sequences', () => { 321 _templateSrv = initTemplateSrv([ 322 { type: 'query', name: 'test', current: { value: '<script>alert(asd)</script>' } }, 323 ]); 324 const target = _templateSrv.replace('$test', {}, 'html'); 325 expect(target).toBe('<script>alert(asd)</script>'); 326 }); 327 }); 328 329 describe('format variable to string values', () => { 330 it('single value should return value', () => { 331 const result = _templateSrv.formatValue('test'); 332 expect(result).toBe('test'); 333 }); 334 335 it('should use glob format when unknown format provided', () => { 336 let result = _templateSrv.formatValue('test', 'nonexistentformat'); 337 expect(result).toBe('test'); 338 result = _templateSrv.formatValue(['test', 'test1'], 'nonexistentformat'); 339 expect(result).toBe('{test,test1}'); 340 }); 341 342 it('multi value and glob format should render glob string', () => { 343 const result = _templateSrv.formatValue(['test', 'test2'], 'glob'); 344 expect(result).toBe('{test,test2}'); 345 }); 346 347 it('multi value and lucene should render as lucene expr', () => { 348 const result = _templateSrv.formatValue(['test', 'test2'], 'lucene'); 349 expect(result).toBe('("test" OR "test2")'); 350 }); 351 352 it('multi value and regex format should render regex string', () => { 353 const result = _templateSrv.formatValue(['test.', 'test2'], 'regex'); 354 expect(result).toBe('(test\\.|test2)'); 355 }); 356 357 it('multi value and pipe should render pipe string', () => { 358 const result = _templateSrv.formatValue(['test', 'test2'], 'pipe'); 359 expect(result).toBe('test|test2'); 360 }); 361 362 it('multi value and distributed should render distributed string', () => { 363 const result = _templateSrv.formatValue(['test', 'test2'], 'distributed', { 364 name: 'build', 365 }); 366 expect(result).toBe('test,build=test2'); 367 }); 368 369 it('multi value and distributed should render when not string', () => { 370 const result = _templateSrv.formatValue(['test'], 'distributed', { 371 name: 'build', 372 }); 373 expect(result).toBe('test'); 374 }); 375 376 it('multi value and csv format should render csv string', () => { 377 const result = _templateSrv.formatValue(['test', 'test2'], 'csv'); 378 expect(result).toBe('test,test2'); 379 }); 380 381 it('multi value and percentencode format should render percent-encoded string', () => { 382 const result = _templateSrv.formatValue(['foo()bar BAZ', 'test2'], 'percentencode'); 383 expect(result).toBe('%7Bfoo%28%29bar%20BAZ%2Ctest2%7D'); 384 }); 385 386 it('slash should be properly escaped in regex format', () => { 387 const result = _templateSrv.formatValue('Gi3/14', 'regex'); 388 expect(result).toBe('Gi3\\/14'); 389 }); 390 391 it('single value and singlequote format should render string with value enclosed in single quotes', () => { 392 const result = _templateSrv.formatValue('test', 'singlequote'); 393 expect(result).toBe("'test'"); 394 }); 395 396 it('multi value and singlequote format should render string with values enclosed in single quotes', () => { 397 const result = _templateSrv.formatValue(['test', "test'2"], 'singlequote'); 398 expect(result).toBe("'test','test\\'2'"); 399 }); 400 401 it('single value and doublequote format should render string with value enclosed in double quotes', () => { 402 const result = _templateSrv.formatValue('test', 'doublequote'); 403 expect(result).toBe('"test"'); 404 }); 405 406 it('multi value and doublequote format should render string with values enclosed in double quotes', () => { 407 const result = _templateSrv.formatValue(['test', 'test"2'], 'doublequote'); 408 expect(result).toBe('"test","test\\"2"'); 409 }); 410 411 it('single value and sqlstring format should render string with value enclosed in single quotes', () => { 412 const result = _templateSrv.formatValue("test'value", 'sqlstring'); 413 expect(result).toBe(`'test''value'`); 414 }); 415 416 it('multi value and sqlstring format should render string with values enclosed in single quotes', () => { 417 const result = _templateSrv.formatValue(['test', "test'value2"], 'sqlstring'); 418 expect(result).toBe(`'test','test''value2'`); 419 }); 420 421 it('raw format should leave value intact and do no escaping', () => { 422 const result = _templateSrv.formatValue("'test\n", 'raw'); 423 expect(result).toBe("'test\n"); 424 }); 425 }); 426 427 describe('can check if variable exists', () => { 428 beforeEach(() => { 429 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'oogle' } }]); 430 }); 431 432 it('should return true if $test exists', () => { 433 const result = _templateSrv.variableExists('$test'); 434 expect(result).toBe(true); 435 }); 436 437 it('should return true if $test exists in string', () => { 438 const result = _templateSrv.variableExists('something $test something'); 439 expect(result).toBe(true); 440 }); 441 442 it('should return true if [[test]] exists in string', () => { 443 const result = _templateSrv.variableExists('something [[test]] something'); 444 expect(result).toBe(true); 445 }); 446 447 it('should return true if [[test:csv]] exists in string', () => { 448 const result = _templateSrv.variableExists('something [[test:csv]] something'); 449 expect(result).toBe(true); 450 }); 451 452 it('should return true if ${test} exists in string', () => { 453 const result = _templateSrv.variableExists('something ${test} something'); 454 expect(result).toBe(true); 455 }); 456 457 it('should return true if ${test:raw} exists in string', () => { 458 const result = _templateSrv.variableExists('something ${test:raw} something'); 459 expect(result).toBe(true); 460 }); 461 462 it('should return null if there are no variables in string', () => { 463 const result = _templateSrv.variableExists('string without variables'); 464 expect(result).toBe(false); 465 }); 466 }); 467 468 describe('can highlight variables in string', () => { 469 beforeEach(() => { 470 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'oogle' } }]); 471 }); 472 473 it('should insert html', () => { 474 const result = _templateSrv.highlightVariablesAsHtml('$test'); 475 expect(result).toBe('<span class="template-variable">$test</span>'); 476 }); 477 478 it('should insert html anywhere in string', () => { 479 const result = _templateSrv.highlightVariablesAsHtml('this $test ok'); 480 expect(result).toBe('this <span class="template-variable">$test</span> ok'); 481 }); 482 483 it('should ignore if variables does not exist', () => { 484 const result = _templateSrv.highlightVariablesAsHtml('this $google ok'); 485 expect(result).toBe('this $google ok'); 486 }); 487 }); 488 489 describe('updateIndex with simple value', () => { 490 beforeEach(() => { 491 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: 'muuuu' } }]); 492 }); 493 494 it('should set current value and update template data', () => { 495 const target = _templateSrv.replace('this.[[test]].filters'); 496 expect(target).toBe('this.muuuu.filters'); 497 }); 498 }); 499 500 describe('replaceWithText', () => { 501 beforeEach(() => { 502 _templateSrv = initTemplateSrv([ 503 { 504 type: 'query', 505 name: 'server', 506 current: { value: '{asd,asd2}', text: 'All' }, 507 }, 508 { 509 type: 'interval', 510 name: 'period', 511 current: { value: '$__auto_interval_interval', text: 'auto' }, 512 }, 513 { 514 type: 'textbox', 515 name: 'empty_on_init', 516 current: { value: '', text: '' }, 517 }, 518 { 519 type: 'custom', 520 name: 'foo', 521 current: { value: 'constructor', text: 'constructor' }, 522 }, 523 ]); 524 _templateSrv.setGrafanaVariable('$__auto_interval_interval', '13m'); 525 _templateSrv.updateIndex(); 526 }); 527 528 it('should replace with text except for grafanaVariables', () => { 529 const target = _templateSrv.replaceWithText('Server: $server, period: $period'); 530 expect(target).toBe('Server: All, period: 13m'); 531 }); 532 533 it('should replace empty string-values with an empty string', () => { 534 const target = _templateSrv.replaceWithText('Hello $empty_on_init'); 535 expect(target).toBe('Hello '); 536 }); 537 538 it('should not return a string representation of a constructor property', () => { 539 const target = _templateSrv.replaceWithText('$foo'); 540 expect(target).not.toBe('function Object() { [native code] }'); 541 expect(target).toBe('constructor'); 542 }); 543 }); 544 545 describe('replaceWithText can pass all / multi value', () => { 546 beforeEach(() => { 547 _templateSrv = initTemplateSrv([ 548 { 549 type: 'query', 550 name: 'server', 551 current: { value: ['server1', 'server2'], text: ['Server 1', 'Server 2'] }, 552 }, 553 { 554 type: 'textbox', 555 name: 'empty_on_init', 556 current: { value: '', text: '' }, 557 }, 558 { 559 type: 'query', 560 name: 'databases', 561 current: { value: '$__all', text: '' }, 562 options: [{ value: '$__all' }, { value: 'db1', text: 'Database 1' }, { value: 'db2', text: 'Database 2' }], 563 }, 564 { 565 type: 'custom', 566 name: 'custom_all_value', 567 allValue: 'CUSTOM_ALL', 568 current: { value: '$__all', text: '' }, 569 options: [{ value: '$__all' }, { value: 'A-Value', text: 'This A' }, { value: 'B-Value', text: 'This B' }], 570 }, 571 ]); 572 _templateSrv.updateIndex(); 573 }); 574 575 it('should replace with text with variable label', () => { 576 const target = _templateSrv.replaceWithText('Server: $server'); 577 expect(target).toBe('Server: Server 1 + Server 2'); 578 }); 579 580 it('should replace empty string-values with an empty string', () => { 581 const target = _templateSrv.replaceWithText('Hello $empty_on_init'); 582 expect(target).toBe('Hello '); 583 }); 584 585 it('should replace $__all with All', () => { 586 const target = _templateSrv.replaceWithText('Db: $databases'); 587 expect(target).toBe('Db: All'); 588 }); 589 590 it('should replace $__all with All for values with custom all', () => { 591 const target = _templateSrv.replaceWithText('Custom: $custom_all_value'); 592 expect(target).toBe('Custom: All'); 593 }); 594 }); 595 596 describe('built in interval variables', () => { 597 beforeEach(() => { 598 _templateSrv = initTemplateSrv([]); 599 }); 600 601 it('should replace $__interval_ms with interval milliseconds', () => { 602 const target = _templateSrv.replace('10 * $__interval_ms', { 603 __interval_ms: { text: '100', value: '100' }, 604 }); 605 expect(target).toBe('10 * 100'); 606 }); 607 }); 608 609 describe('date formating', () => { 610 beforeEach(() => { 611 _templateSrv = initTemplateSrv([], { 612 from: dateTime(1594671549254), 613 to: dateTime(1595237229747), 614 } as TimeRange); 615 }); 616 617 it('should replace ${__from} with ms epoch value', () => { 618 const target = _templateSrv.replace('${__from}'); 619 expect(target).toBe('1594671549254'); 620 }); 621 622 it('should replace ${__from:date:seconds} with epoch in seconds', () => { 623 const target = _templateSrv.replace('${__from:date:seconds}'); 624 expect(target).toBe('1594671549'); 625 }); 626 627 it('should replace ${__from:date} with iso date', () => { 628 const target = _templateSrv.replace('${__from:date}'); 629 expect(target).toBe('2020-07-13T20:19:09.254Z'); 630 }); 631 632 it('should replace ${__from:date:iso} with iso date', () => { 633 const target = _templateSrv.replace('${__from:date:iso}'); 634 expect(target).toBe('2020-07-13T20:19:09.254Z'); 635 }); 636 637 it('should replace ${__from:date:YYYY-MM} using custom format', () => { 638 const target = _templateSrv.replace('${__from:date:YYYY-MM}'); 639 expect(target).toBe('2020-07'); 640 }); 641 }); 642 643 describe('handle objects gracefully', () => { 644 beforeEach(() => { 645 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value: { test: 'A' } } }]); 646 }); 647 648 it('should not pass object to custom function', () => { 649 let passedValue: any = null; 650 _templateSrv.replace('this.${test}.filters', {}, (value: any) => { 651 passedValue = value; 652 }); 653 654 expect(passedValue).toBe('[object Object]'); 655 }); 656 }); 657 658 describe('handle objects gracefully and call toString if defined', () => { 659 beforeEach(() => { 660 const value = { test: 'A', toString: () => 'hello' }; 661 _templateSrv = initTemplateSrv([{ type: 'query', name: 'test', current: { value } }]); 662 }); 663 664 it('should not pass object to custom function', () => { 665 let passedValue: any = null; 666 _templateSrv.replace('this.${test}.filters', {}, (value: any) => { 667 passedValue = value; 668 }); 669 670 expect(passedValue).toBe('hello'); 671 }); 672 }); 673 674 describe('adhoc variables', () => { 675 beforeEach(() => { 676 _templateSrv = initTemplateSrv([ 677 { 678 type: 'adhoc', 679 name: 'adhoc', 680 filters: [ 681 { 682 condition: '', 683 key: 'alertstate', 684 operator: '=', 685 value: 'firing', 686 }, 687 { 688 condition: '', 689 key: 'alertname', 690 operator: '=', 691 value: 'ExampleAlertAlwaysFiring', 692 }, 693 ], 694 }, 695 ]); 696 }); 697 698 it(`should not be handled by any registry items except for queryparam`, () => { 699 const registryItems = Object.values(FormatRegistryID); 700 for (const registryItem of registryItems) { 701 if (registryItem === FormatRegistryID.queryParam) { 702 continue; 703 } 704 705 const firstTarget = _templateSrv.replace(`\${adhoc:${registryItem}}`, {}); 706 expect(firstTarget).toBe(''); 707 708 const secondTarget = _templateSrv.replace('${adhoc}', {}, registryItem); 709 expect(secondTarget).toBe(''); 710 } 711 }); 712 }); 713 714 describe('queryparam', () => { 715 beforeEach(() => { 716 _templateSrv = initTemplateSrv([ 717 { 718 type: 'query', 719 name: 'single', 720 current: { value: 'value1' }, 721 options: [{ value: 'value1' }, { value: 'value2' }], 722 }, 723 { 724 type: 'query', 725 name: 'multi', 726 current: { value: ['value1', 'value2'] }, 727 options: [{ value: 'value1' }, { value: 'value2' }], 728 }, 729 { 730 type: 'adhoc', 731 name: 'adhoc', 732 filters: [ 733 { 734 condition: '', 735 key: 'alertstate', 736 operator: '=', 737 value: 'firing', 738 }, 739 { 740 condition: '', 741 key: 'alertname', 742 operator: '=', 743 value: 'ExampleAlertAlwaysFiring', 744 }, 745 ], 746 }, 747 ]); 748 }); 749 750 it('query variable with single value with queryparam format should return correct queryparam', () => { 751 const target = _templateSrv.replace(`\${single:queryparam}`, {}); 752 expect(target).toBe('var-single=value1'); 753 }); 754 755 it('query variable with single value with queryparam format and scoped vars should return correct queryparam', () => { 756 const target = _templateSrv.replace(`\${single:queryparam}`, { single: { value: 'value1', text: 'value1' } }); 757 expect(target).toBe('var-single=value1'); 758 }); 759 760 it('query variable with single value and queryparam format should return correct queryparam', () => { 761 const target = _templateSrv.replace('${single}', {}, 'queryparam'); 762 expect(target).toBe('var-single=value1'); 763 }); 764 765 it('query variable with single value and queryparam format and scoped vars should return correct queryparam', () => { 766 const target = _templateSrv.replace('${single}', { single: { value: 'value1', text: 'value1' } }, 'queryparam'); 767 expect(target).toBe('var-single=value1'); 768 }); 769 770 it('query variable with multi value with queryparam format should return correct queryparam', () => { 771 const target = _templateSrv.replace(`\${multi:queryparam}`, {}); 772 expect(target).toBe('var-multi=value1&var-multi=value2'); 773 }); 774 775 it('query variable with multi value with queryparam format and scoped vars should return correct queryparam', () => { 776 const target = _templateSrv.replace(`\${multi:queryparam}`, { multi: { value: 'value2', text: 'value2' } }); 777 expect(target).toBe('var-multi=value2'); 778 }); 779 780 it('query variable with multi value and queryparam format should return correct queryparam', () => { 781 const target = _templateSrv.replace('${multi}', {}, 'queryparam'); 782 expect(target).toBe('var-multi=value1&var-multi=value2'); 783 }); 784 785 it('query variable with multi value and queryparam format and scoped vars should return correct queryparam', () => { 786 const target = _templateSrv.replace('${multi}', { multi: { value: 'value2', text: 'value2' } }, 'queryparam'); 787 expect(target).toBe('var-multi=value2'); 788 }); 789 790 it('query variable with adhoc value with queryparam format should return correct queryparam', () => { 791 const target = _templateSrv.replace(`\${adhoc:queryparam}`, {}); 792 expect(target).toBe('var-adhoc=alertstate%7C%3D%7Cfiring&var-adhoc=alertname%7C%3D%7CExampleAlertAlwaysFiring'); 793 }); 794 795 it('query variable with adhoc value with queryparam format should return correct queryparam', () => { 796 const target = _templateSrv.replace(`\${adhoc:queryparam}`, { adhoc: { value: 'value2', text: 'value2' } }); 797 expect(target).toBe('var-adhoc=value2'); 798 }); 799 800 it('query variable with adhoc value and queryparam format should return correct queryparam', () => { 801 const target = _templateSrv.replace('${adhoc}', {}, 'queryparam'); 802 expect(target).toBe('var-adhoc=alertstate%7C%3D%7Cfiring&var-adhoc=alertname%7C%3D%7CExampleAlertAlwaysFiring'); 803 }); 804 805 it('query variable with adhoc value and queryparam format should return correct queryparam', () => { 806 const target = _templateSrv.replace('${adhoc}', { adhoc: { value: 'value2', text: 'value2' } }, 'queryparam'); 807 expect(target).toBe('var-adhoc=value2'); 808 }); 809 }); 810}); 811