diff --git a/public/app/plugins/datasource/mysql/specs/datasource.test.ts b/public/app/plugins/datasource/mysql/specs/datasource.test.ts index b4848bc6d82..335823e8594 100644 --- a/public/app/plugins/datasource/mysql/specs/datasource.test.ts +++ b/public/app/plugins/datasource/mysql/specs/datasource.test.ts @@ -13,14 +13,13 @@ import { FetchResponse, setBackendSrv } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__ import { SQLQuery } from 'app/features/plugins/sql/types'; import { makeVariable } from 'app/features/plugins/sql/utils/testHelpers'; -import { TemplateSrv } from 'app/features/templating/template_srv'; import { MySqlDatasource } from '../MySqlDatasource'; import { MySQLOptions } from '../types'; describe('MySQLDatasource', () => { const defaultRange = getDefaultTimeRange(); // it does not matter what value this has - const setupTestContext = (response: unknown) => { + const setupTestContext = (response: unknown, templateSrv?: unknown) => { jest.clearAllMocks(); setBackendSrv(backendSrv); const fetchMock = jest.spyOn(backendSrv, 'fetch'); @@ -29,14 +28,19 @@ describe('MySQLDatasource', () => { defaultProject: 'testproject', }, } as unknown as DataSourceInstanceSettings; - const templateSrv: TemplateSrv = new TemplateSrv(); const variable = makeVariable('id1', 'name1'); fetchMock.mockImplementation((options) => of(createFetchResponse(response))); const ds = new MySqlDatasource(instanceSettings); - Reflect.set(ds, 'templateSrv', templateSrv); + if (templateSrv !== undefined) { + Reflect.set(ds, 'templateSrv', templateSrv); + } - return { ds, variable, templateSrv, fetchMock }; + return { ds, variable, fetchMock }; + }; + + const simpleTemplateSrv = { + replace: (text: string) => text, }; describe('When performing a query with hidden target', () => { @@ -68,7 +72,6 @@ describe('MySQLDatasource', () => { }); describe('When runSql returns an empty dataframe', () => { - let ds: MySqlDatasource; const response = { results: { tempvar: { @@ -78,27 +81,27 @@ describe('MySQLDatasource', () => { }, }; - beforeEach(async () => { - ds = setupTestContext(response).ds; - }); - it('should return an empty array when metricFindQuery is called', async () => { + const ds = setupTestContext(response, simpleTemplateSrv).ds; const query = 'select * from atable'; const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results.length).toBe(0); }); it('should return an empty array when fetchDatasets is called', async () => { + const ds = setupTestContext(response).ds; const results = await ds.fetchDatasets(); expect(results.length).toBe(0); }); it('should return an empty array when fetchTables is called', async () => { + const ds = setupTestContext(response).ds; const results = await ds.fetchTables(); expect(results.length).toBe(0); }); it('should return an empty array when fetchFields is called', async () => { + const ds = setupTestContext(response).ds; const query: SQLQuery = { refId: 'refId', table: 'schema.table', @@ -217,7 +220,7 @@ describe('MySQLDatasource', () => { }; it('should return list of all string field values', async () => { - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results.length).toBe(6); @@ -250,7 +253,19 @@ describe('MySQLDatasource', () => { }; it('should return list of all column values', async () => { - const { ds, fetchMock } = setupTestContext(response); + const templateSrv = { + replace: (text: string, scopedVars: unknown) => { + expect(text).toBe("select title from atable where title LIKE '$__searchFilter'"); + expect(scopedVars).toStrictEqual({ + __searchFilter: { + value: 'aTit%', + text: '', + }, + }); + return "select title from atable where title LIKE 'aTit%'"; + }, + }; + const { ds, fetchMock } = setupTestContext(response, templateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange, searchFilter: 'aTit' }); expect(fetchMock).toBeCalledTimes(1); @@ -285,7 +300,19 @@ describe('MySQLDatasource', () => { }; it('should return list of all column values', async () => { - const { ds, fetchMock } = setupTestContext(response); + const templateSrv = { + replace: (text: string, scopedVars: unknown) => { + expect(text).toBe("select title from atable where title LIKE '$__searchFilter'"); + expect(scopedVars).toStrictEqual({ + __searchFilter: { + value: '%', + text: '', + }, + }); + return "select title from atable where title LIKE '%'"; + }, + }; + const { ds, fetchMock } = setupTestContext(response, templateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(fetchMock).toBeCalledTimes(1); @@ -318,7 +345,7 @@ describe('MySQLDatasource', () => { }; it('should return list of as text, value', async () => { - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results.length).toBe(3); @@ -353,7 +380,7 @@ describe('MySQLDatasource', () => { }; it('should return list of all field values as text', async () => { - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results).toEqual([ @@ -391,7 +418,7 @@ describe('MySQLDatasource', () => { }; it('should return list of unique keys', async () => { - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results.length).toBe(1); @@ -449,7 +476,6 @@ describe('MySQLDatasource', () => { describe('targetContainsTemplate', () => { it('given query that contains template variable it should return true', () => { - const { ds, templateSrv } = setupTestContext({}); const rawSql = `SELECT $__timeGroup(createdAt,'$summarize') as time_sec, avg(value) as value, @@ -468,15 +494,23 @@ describe('MySQLDatasource', () => { rawQuery: true, refId: '', }; - templateSrv.init([ - { type: 'query', name: 'summarize', current: { value: '1m' } }, - { type: 'query', name: 'host', current: { value: 'a' } }, - ]); + // a fake template server: + // it assumes there are two template variables defined: + // - summarize + // - host + const templateSrv = { + containsTemplate: (text: string) => { + // when the text arrives here, it has been already pre-processed + // by the sql datasource, sql-specific variables have been removed + expect(text).toBe(rawSql.replace(/\$__time(Filter)?/g, '')); + return true; + }, + }; + const { ds } = setupTestContext({}, templateSrv); expect(ds.targetContainsTemplate(query)).toBeTruthy(); }); it('given query that only contains global template variable it should return false', () => { - const { ds, templateSrv } = setupTestContext({}); const rawSql = `SELECT $__timeGroup(createdAt,'$__interval') as time_sec, avg(value) as value, @@ -493,10 +527,19 @@ describe('MySQLDatasource', () => { rawQuery: true, refId: '', }; - templateSrv.init([ - { type: 'query', name: 'summarize', current: { value: '1m' } }, - { type: 'query', name: 'host', current: { value: 'a' } }, - ]); + // a fake template server: + // it assumes there are two template variables defined: + // - summarize + // - host + const templateSrv = { + containsTemplate: (text: string) => { + // when the text arrives here, it has been already pre-processed + // by the sql datasource, sql-specific variables have been removed + expect(text).toBe(rawSql.replace(/\$__time(Filter)?/g, '')); + return false; + }, + }; + const { ds } = setupTestContext({}, templateSrv); expect(ds.targetContainsTemplate(query)).toBeFalsy(); }); }); diff --git a/public/app/plugins/datasource/postgres/datasource.test.ts b/public/app/plugins/datasource/postgres/datasource.test.ts index 8af4f043af8..da814d026a9 100644 --- a/public/app/plugins/datasource/postgres/datasource.test.ts +++ b/public/app/plugins/datasource/postgres/datasource.test.ts @@ -16,7 +16,6 @@ import { FetchResponse } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__ import { QueryFormat, SQLQuery } from 'app/features/plugins/sql/types'; import { makeVariable } from 'app/features/plugins/sql/utils/testHelpers'; -import { TemplateSrv } from 'app/features/templating/template_srv'; import { PostgresDatasource } from './datasource'; import { PostgresOptions } from './types'; @@ -39,7 +38,7 @@ jest.mock('@grafana/runtime/src/services', () => ({ describe('PostgreSQLDatasource', () => { const defaultRange = getDefaultTimeRange(); // it does not matter what value this has const fetchMock = jest.spyOn(backendSrv, 'fetch'); - const setupTestContext = (data: unknown, mock?: Observable>) => { + const setupTestContext = (data: unknown, mock?: Observable>, templateSrv?: unknown) => { jest.clearAllMocks(); const defaultMock = () => mock ?? of(createFetchResponse(data)); fetchMock.mockImplementation(defaultMock); @@ -48,11 +47,12 @@ describe('PostgreSQLDatasource', () => { defaultProject: 'testproject', }, } as unknown as DataSourceInstanceSettings; - const templateSrv: TemplateSrv = new TemplateSrv(); const variable = makeVariable('id1', 'name1'); const ds = new PostgresDatasource(instanceSettings); - Reflect.set(ds, 'templateSrv', templateSrv); - return { ds, templateSrv, variable }; + if (templateSrv !== undefined) { + Reflect.set(ds, 'templateSrv', templateSrv); + } + return { ds, variable }; }; // https://rxjs-dev.firebaseapp.com/guide/testing/marble-testing @@ -80,6 +80,10 @@ describe('PostgreSQLDatasource', () => { }); }; + const simpleTemplateSrv = { + replace: (text: string) => text, + }; + describe('When performing a time series query', () => { it('should transform response correctly', () => { const options: DataQueryRequest = { @@ -296,7 +300,6 @@ describe('PostgreSQLDatasource', () => { }); describe('When runSql returns an empty dataframe', () => { - let ds: PostgresDatasource; const response = { results: { tempvar: { @@ -306,32 +309,33 @@ describe('PostgreSQLDatasource', () => { }, }; - beforeEach(async () => { - ds = setupTestContext(response).ds; - }); - it('should return an empty array when metricFindQuery is called', async () => { + const ds = setupTestContext(response, undefined, simpleTemplateSrv).ds; const query = 'select * from atable'; const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results.length).toBe(0); }); it('should return an empty array when fetchTables is called', async () => { + const ds = setupTestContext(response).ds; const results = await ds.fetchTables(); expect(results.length).toBe(0); }); it('should return empty string when getVersion is called', async () => { + const ds = setupTestContext(response).ds; const results = await ds.getVersion(); expect(results).toBe(''); }); it('should return undefined when getTimescaleDBVersion is called', async () => { + const ds = setupTestContext(response).ds; const results = await ds.getTimescaleDBVersion(); expect(results).toBe(undefined); }); it('should return an empty array when fetchFields is called', async () => { + const ds = setupTestContext(response).ds; const query: SQLQuery = { refId: 'refId', table: 'schema.table', @@ -474,7 +478,7 @@ describe('PostgreSQLDatasource', () => { }, }; - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, undefined, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results.length).toBe(6); @@ -507,7 +511,20 @@ describe('PostgreSQLDatasource', () => { }, }; - const { ds } = setupTestContext(response); + const templateSrv = { + replace: (text: string, scopedVars: unknown) => { + expect(text).toBe("select title from atable where title LIKE '$__searchFilter'"); + expect(scopedVars).toStrictEqual({ + __searchFilter: { + value: 'aTit%', + text: '', + }, + }); + return "select title from atable where title LIKE 'aTit%'"; + }, + }; + + const { ds } = setupTestContext(response, undefined, templateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange, searchFilter: 'aTit' }); expect(fetchMock).toBeCalledTimes(1); @@ -549,7 +566,20 @@ describe('PostgreSQLDatasource', () => { }, }; - const { ds } = setupTestContext(response); + const templateSrv = { + replace: (text: string, scopedVars: unknown) => { + expect(text).toBe("select title from atable where title LIKE '$__searchFilter'"); + expect(scopedVars).toStrictEqual({ + __searchFilter: { + value: '%', + text: '', + }, + }); + return "select title from atable where title LIKE '%'"; + }, + }; + + const { ds } = setupTestContext(response, undefined, templateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(fetchMock).toBeCalledTimes(1); @@ -588,7 +618,7 @@ describe('PostgreSQLDatasource', () => { }, }, }; - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, undefined, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results).toEqual([ @@ -622,7 +652,7 @@ describe('PostgreSQLDatasource', () => { }, }, }; - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, undefined, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results).toEqual([ @@ -659,7 +689,7 @@ describe('PostgreSQLDatasource', () => { }, }, }; - const { ds } = setupTestContext(response); + const { ds } = setupTestContext(response, undefined, simpleTemplateSrv); const results = await ds.metricFindQuery(query, { range: defaultRange }); expect(results).toEqual([{ text: 'aTitle', value: 'same' }]); @@ -733,12 +763,20 @@ describe('PostgreSQLDatasource', () => { refId: 'A', rawQuery: true, }; - const { templateSrv, ds } = setupTestContext({}); - templateSrv.init([ - { type: 'query', name: 'summarize', current: { value: '1m' } }, - { type: 'query', name: 'host', current: { value: 'a' } }, - ]); + // a fake template server: + // it assumes there are two template variables defined: + // - summarize + // - host + const templateSrv = { + containsTemplate: (text: string) => { + // when the text arrives here, it has been already pre-processed + // by the sql datasource, sql-specific variables have been removed + expect(text).toBe(rawSql.replace(/\$__time(Filter)?/g, '')); + return true; + }, + }; + const { ds } = setupTestContext({}, undefined, templateSrv); expect(ds.targetContainsTemplate(query)).toBeTruthy(); }); @@ -760,12 +798,19 @@ describe('PostgreSQLDatasource', () => { refId: 'A', rawQuery: true, }; - const { templateSrv, ds } = setupTestContext({}); - - templateSrv.init([ - { type: 'query', name: 'summarize', current: { value: '1m' } }, - { type: 'query', name: 'host', current: { value: 'a' } }, - ]); + // a fake template server: + // it assumes there are two template variables defined: + // - summarize + // - host + const templateSrv = { + containsTemplate: (text: string) => { + // when the text arrives here, it has been already pre-processed + // by the sql datasource, sql-specific variables has been removed + expect(text).toBe(rawSql.replace(/\$__time(Filter)?/g, '')); + return false; + }, + }; + const { ds } = setupTestContext({}, undefined, templateSrv); expect(ds.targetContainsTemplate(query)).toBeFalsy(); });