@ -5,6 +5,7 @@ import {
DataQueryRequest ,
DataSourceInstanceSettings ,
dateTime ,
FieldType ,
MutableDataFrame ,
} from '@grafana/data' ;
import { FetchResponse , setBackendSrv } from '@grafana/runtime' ;
@ -17,7 +18,7 @@ import { MySqlDatasource } from '../MySqlDatasource';
import { MySQLOptions } from '../types' ;
describe ( 'MySQLDatasource' , ( ) = > {
const setupTex tContext = ( response : unknown ) = > {
const setupTes tContext = ( response : unknown ) = > {
jest . clearAllMocks ( ) ;
setBackendSrv ( backendSrv ) ;
const fetchMock = jest . spyOn ( backendSrv , 'fetch' ) ;
@ -55,7 +56,7 @@ describe('MySQLDatasource', () => {
] ,
} as unknown as DataQueryRequest < SQLQuery > ;
const { ds , fetchMock } = setupTex tContext ( { } ) ;
const { ds , fetchMock } = setupTes tContext ( { } ) ;
await expect ( ds . query ( options ) ) . toEmitValuesWith ( ( received ) = > {
expect ( received [ 0 ] ) . toEqual ( { data : [ ] } ) ;
@ -64,6 +65,132 @@ describe('MySQLDatasource', () => {
} ) ;
} ) ;
describe ( 'When runSql returns an empty dataframe' , ( ) = > {
let ds : MySqlDatasource ;
const response = {
results : {
tempvar : {
refId : 'tempvar' ,
frames : [ ] ,
} ,
} ,
} ;
beforeEach ( async ( ) = > {
ds = setupTestContext ( response ) . ds ;
} ) ;
it ( 'should return an empty array when metricFindQuery is called' , async ( ) = > {
const query = 'select * from atable' ;
const results = await ds . metricFindQuery ( query ) ;
expect ( results . length ) . toBe ( 0 ) ;
} ) ;
it ( 'should return an empty array when fetchDatasets is called' , async ( ) = > {
const results = await ds . fetchDatasets ( ) ;
expect ( results . length ) . toBe ( 0 ) ;
} ) ;
it ( 'should return an empty array when fetchTables is called' , async ( ) = > {
const results = await ds . fetchTables ( ) ;
expect ( results . length ) . toBe ( 0 ) ;
} ) ;
it ( 'should return an empty array when fetchFields is called' , async ( ) = > {
const query : SQLQuery = {
refId : 'refId' ,
table : 'schema.table' ,
dataset : 'dataset' ,
} ;
const results = await ds . fetchFields ( query ) ;
expect ( results . length ) . toBe ( 0 ) ;
} ) ;
} ) ;
describe ( 'When runSql returns a populated dataframe' , ( ) = > {
it ( 'should return a list of datasets when fetchDatasets is called' , async ( ) = > {
const fetchDatasetsResponse = {
results : {
datasets : {
refId : 'datasets' ,
frames : [
dataFrameToJSON (
new MutableDataFrame ( {
fields : [ { name : 'name' , type : FieldType . string , values : [ 'test1' , 'test2' , 'test3' ] } ] ,
} )
) ,
] ,
} ,
} ,
} ;
const { ds } = setupTestContext ( fetchDatasetsResponse ) ;
const results = await ds . fetchDatasets ( ) ;
expect ( results . length ) . toBe ( 3 ) ;
expect ( results ) . toEqual ( [ 'test1' , 'test2' , 'test3' ] ) ;
} ) ;
it ( 'should return a list of tables when fetchTables is called' , async ( ) = > {
const fetchTableResponse = {
results : {
tables : {
refId : 'tables' ,
frames : [
dataFrameToJSON (
new MutableDataFrame ( {
fields : [ { name : 'table_name' , type : FieldType . string , values : [ 'test1' , 'test2' , 'test3' ] } ] ,
} )
) ,
] ,
} ,
} ,
} ;
const { ds } = setupTestContext ( fetchTableResponse ) ;
const results = await ds . fetchTables ( ) ;
expect ( results . length ) . toBe ( 3 ) ;
expect ( results ) . toEqual ( [ 'test1' , 'test2' , 'test3' ] ) ;
} ) ;
it ( 'should return a list of fields when fetchFields is called' , async ( ) = > {
const fetchFieldsResponse = {
results : {
fields : {
refId : 'fields' ,
frames : [
dataFrameToJSON (
new MutableDataFrame ( {
fields : [
{ name : 'column_name' , type : FieldType . string , values : [ 'test1' , 'test2' , 'test3' ] } ,
{ name : 'data_type' , type : FieldType . string , values : [ 'int' , 'char' , 'bool' ] } ,
] ,
} )
) ,
] ,
} ,
} ,
} ;
const { ds } = setupTestContext ( fetchFieldsResponse ) ;
const sqlQuery : SQLQuery = {
refId : 'fields' ,
table : 'table' ,
dataset : 'dataset' ,
} ;
const results = await ds . fetchFields ( sqlQuery ) ;
expect ( results . length ) . toBe ( 3 ) ;
expect ( results [ 0 ] . label ) . toBe ( 'test1' ) ;
expect ( results [ 0 ] . value ) . toBe ( 'test1' ) ;
expect ( results [ 0 ] . type ) . toBe ( 'int' ) ;
expect ( results [ 1 ] . label ) . toBe ( 'test2' ) ;
expect ( results [ 1 ] . value ) . toBe ( 'test2' ) ;
expect ( results [ 1 ] . type ) . toBe ( 'char' ) ;
expect ( results [ 2 ] . label ) . toBe ( 'test3' ) ;
expect ( results [ 2 ] . value ) . toBe ( 'test3' ) ;
expect ( results [ 2 ] . type ) . toBe ( 'bool' ) ;
} ) ;
} ) ;
describe ( 'When performing metricFindQuery that returns multiple string fields' , ( ) = > {
const query = 'select * from atable' ;
const response = {
@ -88,7 +215,7 @@ describe('MySQLDatasource', () => {
} ;
it ( 'should return list of all string field values' , async ( ) = > {
const { ds } = setupTex tContext ( response ) ;
const { ds } = setupTes tContext ( response ) ;
const results = await ds . metricFindQuery ( query , { } ) ;
expect ( results . length ) . toBe ( 6 ) ;
@ -121,7 +248,7 @@ describe('MySQLDatasource', () => {
} ;
it ( 'should return list of all column values' , async ( ) = > {
const { ds , fetchMock } = setupTex tContext ( response ) ;
const { ds , fetchMock } = setupTes tContext ( response ) ;
const results = await ds . metricFindQuery ( query , { searchFilter : 'aTit' } ) ;
expect ( fetchMock ) . toBeCalledTimes ( 1 ) ;
@ -156,7 +283,7 @@ describe('MySQLDatasource', () => {
} ;
it ( 'should return list of all column values' , async ( ) = > {
const { ds , fetchMock } = setupTex tContext ( response ) ;
const { ds , fetchMock } = setupTes tContext ( response ) ;
const results = await ds . metricFindQuery ( query , { } ) ;
expect ( fetchMock ) . toBeCalledTimes ( 1 ) ;
@ -189,7 +316,7 @@ describe('MySQLDatasource', () => {
} ;
it ( 'should return list of as text, value' , async ( ) = > {
const { ds } = setupTex tContext ( response ) ;
const { ds } = setupTes tContext ( response ) ;
const results = await ds . metricFindQuery ( query , { } ) ;
expect ( results . length ) . toBe ( 3 ) ;
@ -224,7 +351,7 @@ describe('MySQLDatasource', () => {
} ;
it ( 'should return list of all field values as text' , async ( ) = > {
const { ds } = setupTex tContext ( response ) ;
const { ds } = setupTes tContext ( response ) ;
const results = await ds . metricFindQuery ( query , { } ) ;
expect ( results ) . toEqual ( [
@ -262,7 +389,7 @@ describe('MySQLDatasource', () => {
} ;
it ( 'should return list of unique keys' , async ( ) = > {
const { ds } = setupTex tContext ( response ) ;
const { ds } = setupTes tContext ( response ) ;
const results = await ds . metricFindQuery ( query , { } ) ;
expect ( results . length ) . toBe ( 1 ) ;
@ -274,28 +401,28 @@ describe('MySQLDatasource', () => {
describe ( 'When interpolating variables' , ( ) = > {
describe ( 'and value is a string' , ( ) = > {
it ( 'should return an unquoted value' , ( ) = > {
const { ds , variable } = setupTex tContext ( { } ) ;
const { ds , variable } = setupTes tContext ( { } ) ;
expect ( ds . interpolateVariable ( 'abc' , variable ) ) . toEqual ( 'abc' ) ;
} ) ;
} ) ;
describe ( 'and value is a number' , ( ) = > {
it ( 'should return an unquoted value' , ( ) = > {
const { ds , variable } = setupTex tContext ( { } ) ;
const { ds , variable } = setupTes tContext ( { } ) ;
expect ( ds . interpolateVariable ( 1000 , variable ) ) . toEqual ( 1000 ) ;
} ) ;
} ) ;
describe ( 'and value is an array of strings' , ( ) = > {
it ( 'should return comma separated quoted values' , ( ) = > {
const { ds , variable } = setupTex tContext ( { } ) ;
const { ds , variable } = setupTes tContext ( { } ) ;
expect ( ds . interpolateVariable ( [ 'a' , 'b' , 'c' ] , variable ) ) . toEqual ( "'a','b','c'" ) ;
} ) ;
} ) ;
describe ( 'and variable allows multi-value and value is a string' , ( ) = > {
it ( 'should return a quoted value' , ( ) = > {
const { ds , variable } = setupTex tContext ( { } ) ;
const { ds , variable } = setupTes tContext ( { } ) ;
variable . multi = true ;
expect ( ds . interpolateVariable ( 'abc' , variable ) ) . toEqual ( "'abc'" ) ;
} ) ;
@ -303,7 +430,7 @@ describe('MySQLDatasource', () => {
describe ( 'and variable contains single quote' , ( ) = > {
it ( 'should return a quoted value' , ( ) = > {
const { ds , variable } = setupTex tContext ( { } ) ;
const { ds , variable } = setupTes tContext ( { } ) ;
variable . multi = true ;
expect ( ds . interpolateVariable ( "a'bc" , variable ) ) . toEqual ( "'a''bc'" ) ;
} ) ;
@ -311,7 +438,7 @@ describe('MySQLDatasource', () => {
describe ( 'and variable allows all and value is a string' , ( ) = > {
it ( 'should return a quoted value' , ( ) = > {
const { ds , variable } = setupTex tContext ( { } ) ;
const { ds , variable } = setupTes tContext ( { } ) ;
variable . includeAll = true ;
expect ( ds . interpolateVariable ( 'abc' , variable ) ) . toEqual ( "'abc'" ) ;
} ) ;
@ -320,7 +447,7 @@ describe('MySQLDatasource', () => {
describe ( 'targetContainsTemplate' , ( ) = > {
it ( 'given query that contains template variable it should return true' , ( ) = > {
const { ds , templateSrv } = setupTex tContext ( { } ) ;
const { ds , templateSrv } = setupTes tContext ( { } ) ;
const rawSql = ` SELECT
$__timeGroup ( createdAt , '$summarize' ) as time_sec ,
avg ( value ) as value ,
@ -347,7 +474,7 @@ describe('MySQLDatasource', () => {
} ) ;
it ( 'given query that only contains global template variable it should return false' , ( ) = > {
const { ds , templateSrv } = setupTex tContext ( { } ) ;
const { ds , templateSrv } = setupTes tContext ( { } ) ;
const rawSql = ` SELECT
$__timeGroup ( createdAt , '$__interval' ) as time_sec ,
avg ( value ) as value ,