@ -16,470 +16,578 @@ import { initTemplateSrv } from '../../../../test/helpers/initTemplateSrv';
import { ContextSrv , setContextSrv } from '../../../core/services/context_srv' ;
import { setLinkSrv } from '../../panel/panellinks/link_srv' ;
import { getFieldLinksForExplore } from './links' ;
describe ( 'getFieldLinksForExplore' , ( ) = > {
beforeEach ( ( ) = > {
setTemplateSrv (
initTemplateSrv ( 'key' , [
{ type : 'custom' , name : 'emptyVar' , current : { value : null } } ,
{ type : 'custom' , name : 'num' , current : { value : 1 } } ,
{ type : 'custom' , name : 'test' , current : { value : 'foo' } } ,
] )
) ;
} ) ;
it ( 'returns correct link model for external link' , ( ) = > {
const { field , range } = setup ( {
title : 'external' ,
url : 'http://regionalhost' ,
} ) ;
const links = getFieldLinksForExplore ( {
field ,
rowIndex : ROW_WITH_TEXT_VALUE.index ,
splitOpenFn : jest.fn ( ) ,
range ,
import { getFieldLinksForExplore , getVariableUsageInfo } from './links' ;
describe ( 'explore links utils' , ( ) = > {
describe ( 'getFieldLinksForExplore' , ( ) = > {
beforeEach ( ( ) = > {
setTemplateSrv (
initTemplateSrv ( 'key' , [
{ type : 'custom' , name : 'emptyVar' , current : { value : null } } ,
{ type : 'custom' , name : 'num' , current : { value : 1 } } ,
{ type : 'custom' , name : 'test' , current : { value : 'foo' } } ,
] )
) ;
} ) ;
expect ( links [ 0 ] . href ) . toBe ( 'http://regionalhost' ) ;
expect ( links [ 0 ] . title ) . toBe ( 'external' ) ;
} ) ;
it ( 'returns generates title for external link' , ( ) = > {
const { field , range } = setup ( {
title : '' ,
url : 'http://regionalhost' ,
} ) ;
const links = getFieldLinksForExplore ( {
field ,
rowIndex : ROW_WITH_TEXT_VALUE.index ,
splitOpenFn : jest.fn ( ) ,
range ,
it ( 'returns correct link model for external link' , ( ) = > {
const { field , range } = setup ( {
title : 'external' ,
url : 'http://regionalhost' ,
} ) ;
const links = getFieldLinksForExplore ( {
field ,
rowIndex : ROW_WITH_TEXT_VALUE.index ,
splitOpenFn : jest.fn ( ) ,
range ,
} ) ;
expect ( links [ 0 ] . href ) . toBe ( 'http://regionalhost' ) ;
expect ( links [ 0 ] . title ) . toBe ( 'external' ) ;
} ) ;
expect ( links [ 0 ] . href ) . toBe ( 'http://regionalhost' ) ;
expect ( links [ 0 ] . title ) . toBe ( 'regionalhost' ) ;
} ) ;
it ( 'returns generates title for external link' , ( ) = > {
const { field , range } = setup ( {
title : '' ,
url : 'http://regionalhost' ,
} ) ;
const links = getFieldLinksForExplore ( {
field ,
rowIndex : ROW_WITH_TEXT_VALUE.index ,
splitOpenFn : jest.fn ( ) ,
range ,
} ) ;
expect ( links [ 0 ] . href ) . toBe ( 'http://regionalhost' ) ;
expect ( links [ 0 ] . title ) . toBe ( 'regionalhost' ) ;
} ) ;
it ( 'returns correct link model for internal link' , ( ) = > {
const { field , range } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1' } ,
it ( 'returns correct link model for internal link' , ( ) = > {
const { field , range } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
panelsState : {
trace : {
spanId : 'abcdef' ,
} ,
} ,
} ,
} ) ;
const splitfn = jest . fn ( ) ;
const links = getFieldLinksForExplore ( {
field ,
rowIndex : ROW_WITH_TEXT_VALUE.index ,
splitOpenFn : splitfn ,
range ,
} ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1"}],"panelsState":{"trace":{"spanId":"abcdef"}}}'
) } `
) ;
expect ( links [ 0 ] . title ) . toBe ( 'test_ds' ) ;
if ( links [ 0 ] . onClick ) {
links [ 0 ] . onClick ( { } ) ;
}
expect ( splitfn ) . toBeCalledWith ( {
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
query : { query : 'query_1' } ,
range ,
panelsState : {
trace : {
spanId : 'abcdef' ,
} ,
} ,
} ,
} ) ;
} ) ;
const splitfn = jest . fn ( ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , splitOpenFn : splitfn , range } ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1"}],"panelsState":{"trace":{"spanId":"abcdef"}}}'
) } `
) ;
expect ( links [ 0 ] . title ) . toBe ( 'test_ds' ) ;
if ( links [ 0 ] . onClick ) {
links [ 0 ] . onClick ( { } ) ;
}
expect ( splitfn ) . toBeCalledWith ( {
datasourceUid : 'uid_1' ,
query : { query : 'query_1' } ,
range ,
panelsState : {
trace : {
spanId : 'abcdef' ,
it ( 'returns correct link model for external link when user does not have access to explore' , ( ) = > {
const { field , range } = setup (
{
title : 'external' ,
url : 'http://regionalhost' ,
} ,
} ,
} ) ;
} ) ;
false
) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range } ) ;
it ( 'returns correct link model for external link when user does not have access to explore' , ( ) = > {
const { field , range } = setup (
{
title : 'external' ,
url : 'http://regionalhost' ,
} ,
false
) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range } ) ;
expect ( links [ 0 ] . href ) . toBe ( 'http://regionalhost' ) ;
expect ( links [ 0 ] . title ) . toBe ( 'external' ) ;
} ) ;
expect ( links [ 0 ] . href ) . toBe ( 'http://regionalhost' ) ;
expect ( links [ 0 ] . title ) . toBe ( 'external' ) ;
} ) ;
it ( 'returns no internal links if when user does not have access to explore' , ( ) = > {
const { field , range } = setup (
{
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ,
false
) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range } ) ;
expect ( links ) . toHaveLength ( 0 ) ;
} ) ;
it ( 'returns no internal links if when user does not have access to explore' , ( ) = > {
const { field , range } = setup (
{
it ( 'returns internal links when target contains __data template variables' , ( ) = > {
const { field , range , dataFrame } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1' } ,
query : { query : 'query_1-${__data.fields.flux-dimensions} ' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ,
false
) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range } ) ;
expect ( links ) . toHaveLength ( 0 ) ;
} ) ;
it ( 'returns internal links when target contains __data template variables' , ( ) = > {
const { field , range , dataFrame } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${__data.fields.flux-dimensions}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links when target contains targetField template variable' , ( ) = > {
const { field , range , dataFrame } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${__targetField}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo"}]}'
) } `
) ;
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links when target contains field name template variable' , ( ) = > {
// field cannot be hyphenated, change field name to non-hyphenated
const noHyphenLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${fluxDimensions}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ;
const { field , range , dataFrame } = setup ( noHyphenLink , true , {
name : 'fluxDimensions' ,
type : FieldType . string ,
values : new ArrayVector ( [ ROW_WITH_TEXT_VALUE . value , ROW_WITH_NULL_VALUE . value ] ) ,
config : {
links : [ noHyphenLink ] ,
} ,
it ( 'returns internal links when target contains targetField template variable' , ( ) = > {
const { field , range , dataFrame } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${__targetField}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo"}]}'
) } `
) ;
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links when target contains other field name template variables' , ( ) = > {
// field cannot be hyphenated, change field name to non-hyphenated
const noHyphenLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${fluxDimensions}-${fluxDimension2}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ;
const { field , range , dataFrame } = setup (
noHyphenLink ,
true ,
{
it ( 'returns internal links when target contains field name template variable' , ( ) = > {
// field cannot be hyphenated, change field name to non-hyphenated
const noHyphenLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${fluxDimensions}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ;
const { field , range , dataFrame } = setup ( noHyphenLink , true , {
name : 'fluxDimensions' ,
type : FieldType . string ,
values : new ArrayVector ( [ ROW_WITH_TEXT_VALUE . value , ROW_WITH_NULL_VALUE . value ] ) ,
config : {
links : [ noHyphenLink ] ,
} ,
} ,
[
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links when target contains other field name template variables' , ( ) = > {
// field cannot be hyphenated, change field name to non-hyphenated
const noHyphenLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${fluxDimensions}-${fluxDimension2}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ;
const { field , range , dataFrame } = setup (
noHyphenLink ,
true ,
{
name : 'fluxDimension2' ,
name : 'fluxDimensions ' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'foo2' , ROW_WITH_NULL_VALUE . value ] ) ,
values : new ArrayVector ( [ ROW_WITH_TEXT_VALUE . value , ROW_WITH_NULL_VALUE . value ] ) ,
config : {
links : [ noHyphenLink ] ,
} ,
} ,
]
) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo-foo2"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with logfmt and regex transformation' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} env=${environment}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [
{ type : SupportedTransformationTypes . Logfmt } ,
{ type : SupportedTransformationTypes . Regex , expression : 'host=(dev|prod)' , mapValue : 'environment' } ,
] ,
} ,
} ;
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=foo host=dev-001' , 'application=bar host=prod-003' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
[
{
name : 'fluxDimension2' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'foo2' , ROW_WITH_NULL_VALUE . value ] ) ,
config : {
links : [ noHyphenLink ] ,
} ,
} ,
]
) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_TEXT_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"query_1-foo-foo2"}]}'
) } `
) ;
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=foo env=dev}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=bar env=prod}"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with logfmt and regex transformation' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} env=${environment}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [
{ type : SupportedTransformationTypes . Logfmt } ,
{ type : SupportedTransformationTypes . Regex , expression : 'host=(dev|prod)' , mapValue : 'environment' } ,
] ,
} ,
} ;
it ( 'returns internal links with 2 unnamed regex transformations and use the last transformation' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{env=${msg}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [
{ type : SupportedTransformationTypes . Regex , expression : 'fieldA=(asparagus|broccoli)' } ,
{ type : SupportedTransformationTypes . Regex , expression : 'fieldB=(apple|banana)' } ,
] ,
} ,
} ;
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'fieldA=asparagus fieldB=banana' , 'fieldA=broccoli fieldB=apple' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=foo host=dev-001' , 'application=bar host=prod-003' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=foo env=dev}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=bar env=prod}"}]}'
) } `
) ;
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{env=banana}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{env=apple}"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with 2 unnamed regex transformations and use the last transformation' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{env=${msg}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [
{ type : SupportedTransformationTypes . Regex , expression : 'fieldA=(asparagus|broccoli)' } ,
{ type : SupportedTransformationTypes . Regex , expression : 'fieldB=(apple|banana)' } ,
] ,
} ,
} ;
it ( 'returns internal links with logfmt with stringified booleans' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} isOnline=${online}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [ { type : SupportedTransformationTypes . Logfmt } ] ,
} ,
} ;
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=foo online=true' , 'application=bar online=false' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'fieldA=asparagus fieldB=banana' , 'fieldA=broccoli fieldB=apple' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{env=banana}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{env=apple}"}]}'
) } `
) ;
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=foo isOnline=true}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=bar isOnline=false}"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with logfmt with stringified booleans' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} isOnline=${online}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [ { type : SupportedTransformationTypes . Logfmt } ] ,
} ,
} ;
it ( 'returns internal links with logfmt with correct data on transformation-defined field' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [ { type : SupportedTransformationTypes . Logfmt , field : 'fieldNamedInTransformation' } ] ,
} ,
} ;
// fieldWithLink has the transformation, but the transformation has defined fieldNamedInTransformation as its field to transform
const { field , range , dataFrame } = setup (
transformationLink ,
true ,
{
name : 'fieldWithLink' ,
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=link' , 'application=link2 ' ] ) ,
values : new ArrayVector ( [ 'application=foo online=true' , 'application=bar online=false' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
} ,
[
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=foo isOnline=true}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=bar isOnline=false}"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with logfmt with correct data on transformation-defined field' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [ { type : SupportedTransformationTypes . Logfmt , field : 'fieldNamedInTransformation' } ] ,
} ,
} ;
// fieldWithLink has the transformation, but the transformation has defined fieldNamedInTransformation as its field to transform
const { field , range , dataFrame } = setup (
transformationLink ,
true ,
{
name : 'fieldNamedInTransformation' ,
name : 'fieldWithLink ' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=transform' , 'application=transform2' ] ) ,
config : { } ,
values : new ArrayVector ( [ 'application=link' , 'application=link2' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
} ,
]
) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=transform}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=transform2}"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with regex named capture groups' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} env=${environment}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [
[
{
type : SupportedTransformationTypes . Regex ,
expression : '(?=.*(?<application>(grafana|loki)))(?=.*(?<environment>(dev|prod)))' ,
name : 'fieldNamedInTransformation' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=transform' , 'application=transform2' ] ) ,
config : { } ,
} ,
] ,
} ,
} ;
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'foo loki prod' , 'dev bar grafana' , 'prod grafana foo' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
]
) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=transform}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=transform2}"}]}'
) } `
) ;
} ) ;
it ( 'returns internal links with regex named capture groups' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} env=${environment}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [
{
type : SupportedTransformationTypes . Regex ,
expression : '(?=.*(?<application>(grafana|loki)))(?=.*(?<environment>(dev|prod)))' ,
} ,
] ,
} ,
} ;
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'foo loki prod' , 'dev bar grafana' , 'prod grafana foo' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 2 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=loki env=prod}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=grafana env=dev}"}]}'
) } `
) ;
expect ( links [ 2 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 2 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=grafana env=prod}"}]}'
) } `
) ;
} ) ;
it ( 'returns no internal links when target contains empty template variables' , ( ) = > {
const { field , range , dataFrame } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${__data.fields.flux-dimensions}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_NULL_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 0 ) ;
} ) ;
const links = [
getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 1 , range , dataFrame } ) ,
getFieldLinksForExplore ( { field , rowIndex : 2 , range , dataFrame } ) ,
] ;
expect ( links [ 0 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 0 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=loki env=prod}"}]}'
) } `
) ;
expect ( links [ 1 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 1 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=grafana env=dev}"}]}'
) } `
) ;
expect ( links [ 2 ] ) . toHaveLength ( 1 ) ;
expect ( links [ 2 ] [ 0 ] . href ) . toBe (
` /explore?left= ${ encodeURIComponent (
'{"range":{"from":"now-1h","to":"now"},"datasource":"uid_1","queries":[{"query":"http_requests{app=grafana env=prod}"}]}'
) } `
) ;
it ( 'does not return internal links when not all query variables are matched' , ( ) = > {
const transformationLink : DataLink = {
title : '' ,
url : '' ,
internal : {
query : { query : 'http_requests{app=${application} env=${diffVar}}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
transformations : [ { type : SupportedTransformationTypes . Logfmt } ] ,
} ,
} ;
const { field , range , dataFrame } = setup ( transformationLink , true , {
name : 'msg' ,
type : FieldType . string ,
values : new ArrayVector ( [ 'application=foo host=dev-001' ] ) ,
config : {
links : [ transformationLink ] ,
} ,
} ) ;
const links = [ getFieldLinksForExplore ( { field , rowIndex : 0 , range , dataFrame } ) ] ;
expect ( links [ 0 ] ) . toHaveLength ( 0 ) ;
} ) ;
} ) ;
it ( 'returns no internal links when target contains empty template variables' , ( ) = > {
const { field , range , dataFrame } = setup ( {
title : '' ,
url : '' ,
internal : {
query : { query : 'query_1-${__data.fields.flux-dimensions}' } ,
datasourceUid : 'uid_1' ,
datasourceName : 'test_ds' ,
} ,
describe ( 'getVariableUsageInfo' , ( ) = > {
it ( 'returns true when query contains variables and all variables are used' , ( ) = > {
const dataLink = {
url : '' ,
title : '' ,
internal : {
datasourceUid : 'uid' ,
datasourceName : 'dsName' ,
query : { query : 'test ${testVal}' } ,
} ,
} ;
const scopedVars = {
testVal : { text : '' , value : 'val1' } ,
} ;
const varMapMock = jest . fn ( ) . mockReturnValue ( { testVal : scopedVars.testVal.value } ) ;
const dataLinkRtnVal = getVariableUsageInfo ( dataLink , scopedVars , varMapMock ) . allVariablesDefined ;
expect ( dataLinkRtnVal ) . toBe ( true ) ;
} ) ;
it ( 'returns false when query contains variables and no variables are used' , ( ) = > {
const dataLink = {
url : '' ,
title : '' ,
internal : {
datasourceUid : 'uid' ,
datasourceName : 'dsName' ,
query : { query : 'test ${diffVar}' } ,
} ,
} ;
const scopedVars = {
testVal : { text : '' , value : 'val1' } ,
} ;
const varMapMock = jest . fn ( ) . mockReturnValue ( { diffVar : null } ) ;
const dataLinkRtnVal = getVariableUsageInfo ( dataLink , scopedVars , varMapMock ) . allVariablesDefined ;
expect ( dataLinkRtnVal ) . toBe ( false ) ;
} ) ;
it ( 'returns false when query contains variables and some variables are used' , ( ) = > {
const dataLink = {
url : '' ,
title : '' ,
internal : {
datasourceUid : 'uid' ,
datasourceName : 'dsName' ,
query : { query : 'test ${testVal} ${diffVar}' } ,
} ,
} ;
const scopedVars = {
testVal : { text : '' , value : 'val1' } ,
} ;
const varMapMock = jest . fn ( ) . mockReturnValue ( { testVal : 'val1' , diffVar : null } ) ;
const dataLinkRtnVal = getVariableUsageInfo ( dataLink , scopedVars , varMapMock ) . allVariablesDefined ;
expect ( dataLinkRtnVal ) . toBe ( false ) ;
} ) ;
it ( 'returns true when query contains no variables' , ( ) = > {
const dataLink = {
url : '' ,
title : '' ,
internal : {
datasourceUid : 'uid' ,
datasourceName : 'dsName' ,
query : { query : 'test' } ,
} ,
} ;
const scopedVars = {
testVal : { text : '' , value : 'val1' } ,
} ;
const varMapMock = jest . fn ( ) . mockReturnValue ( { } ) ;
const dataLinkRtnVal = getVariableUsageInfo ( dataLink , scopedVars , varMapMock ) . allVariablesDefined ;
expect ( dataLinkRtnVal ) . toBe ( true ) ;
} ) ;
const links = getFieldLinksForExplore ( { field , rowIndex : ROW_WITH_NULL_VALUE.index , range , dataFrame } ) ;
expect ( links ) . toHaveLength ( 0 ) ;
} ) ;
} ) ;