From 381cdee8af42047aefb0708f7903e178a043fed0 Mon Sep 17 00:00:00 2001 From: Sriramajeyam Sugumaran <153843+yesoreyeram@users.noreply.github.com> Date: Thu, 18 Jan 2024 07:12:01 +0000 Subject: [PATCH 1/6] removed old cypress based e2e tests --- cypress_skip/e2e/api.cy.ts | 220 --------------------- cypress_skip/e2e/csv.cy.ts | 41 ---- cypress_skip/e2e/explore.cy.ts | 22 --- cypress_skip/e2e/json.cy.ts | 53 ----- cypress_skip/e2e/tsv.cy.ts | 35 ---- cypress_skip/e2e/uql.cyx.ts | 27 --- cypress_skip/e2e/utils/api.ts | 21 -- cypress_skip/e2e/utils/editorFieldCheck.ts | 30 --- cypress_skip/e2e/utils/explore.ts | 20 -- cypress_skip/e2e/utils/login.ts | 10 - cypress_skip/support/commands.ts | 41 ---- cypress_skip/support/e2e.ts | 20 -- cypress_skip/tsconfig.json | 8 - cypress_skip/types.d.ts | 1 - 14 files changed, 549 deletions(-) delete mode 100644 cypress_skip/e2e/api.cy.ts delete mode 100644 cypress_skip/e2e/csv.cy.ts delete mode 100644 cypress_skip/e2e/explore.cy.ts delete mode 100644 cypress_skip/e2e/json.cy.ts delete mode 100644 cypress_skip/e2e/tsv.cy.ts delete mode 100644 cypress_skip/e2e/uql.cyx.ts delete mode 100644 cypress_skip/e2e/utils/api.ts delete mode 100644 cypress_skip/e2e/utils/editorFieldCheck.ts delete mode 100644 cypress_skip/e2e/utils/explore.ts delete mode 100644 cypress_skip/e2e/utils/login.ts delete mode 100644 cypress_skip/support/commands.ts delete mode 100644 cypress_skip/support/e2e.ts delete mode 100644 cypress_skip/tsconfig.json delete mode 100644 cypress_skip/types.d.ts diff --git a/cypress_skip/e2e/api.cy.ts b/cypress_skip/e2e/api.cy.ts deleted file mode 100644 index 8288cee4..00000000 --- a/cypress_skip/e2e/api.cy.ts +++ /dev/null @@ -1,220 +0,0 @@ -import { request, query } from './utils/api'; -import type { InfinityQuery } from './../../src/types'; - -describe('sanity check', () => { - it('health check', () => { - request('/datasources/2/health').then((res) => { - // @ts-ignore - cy.wrap(res.body).snapshot(); - }); - }); -}); - -describe('test the backend response', () => { - const queries: { name: string; query: Partial> }[] = [ - { - name: 'backend json query', - query: { - type: 'json', - parser: 'backend', - source: 'inline', - data: JSON.stringify([ - { name: 'foo', age: 30 }, - { name: 'bar', age: 17 }, - ]), - }, - }, - { - name: 'backend csv query', - query: { - type: 'csv', - parser: 'backend', - source: 'inline', - data: 'name,age\nfoo,30\nbar,17', - }, - }, - { - name: 'backend tsv query', - query: { - type: 'tsv', - parser: 'backend', - source: 'inline', - data: 'name age\nfoo 30\nbar 17', - }, - }, - { - name: 'backend graphql query', - query: { - type: 'graphql', - parser: 'backend', - source: 'inline', - data: JSON.stringify([ - { name: 'foo', age: 30 }, - { name: 'bar', age: 17 }, - ]), - }, - }, - { - name: 'backend xml query', - query: { - type: 'xml', - parser: 'backend', - source: 'inline', - data: ` foo 30 bar 17 `, - }, - }, - { - name: 'backend xml query with root selector and columns', - query: { - type: 'xml', - parser: 'backend', - source: 'inline', - data: ` foo 30 bar 17 `, - root_selector: 'root.row', - columns: [ - { - text: 'Age', - selector: 'age', - type: 'number', - }, - { - text: 'Name', - selector: 'name', - type: 'string', - }, - ], - }, - }, - { - name: 'backend html query', - query: { - type: 'html', - parser: 'backend', - source: 'inline', - data: `
name age
foo 30
bar 17
`, - }, - }, - { - name: 'backend html query with root selector and columns', - query: { - type: 'html', - parser: 'backend', - source: 'inline', - data: `
name age
foo 30
bar 17
`, - root_selector: 'table.tbody.tr', - columns: [ - { - text: 'Name', - selector: 'td.0', - type: 'string', - }, - { - text: 'Age', - selector: 'td.1.#content', - type: 'number', - }, - ], - }, - }, - ]; - queries.forEach((q) => { - it(q.name, () => { - query(q.query).then((res) => { - cy.wrap({ - ...res.body.results['A'].frames[0], - schema: { - ...res.body.results['A'].frames[0].schema, - meta: { - ...res.body.results['A'].frames[0].schema.meta, - custom: { - ...res.body.results['A'].frames[0].schema.meta.custom, - duration: 0, - }, - }, - }, - // @ts-ignore - }).snapshot(); - }); - }); - }); -}); - -describe('test the uql response', () => { - const queries: { name: string; query: Partial> }[] = [ - { - name: 'uql json query', - query: { - type: 'json', - parser: 'uql', - source: 'inline', - uql: 'parse-json', - data: JSON.stringify([ - { name: 'foo', age: 30 }, - { name: 'bar', age: 17 }, - ]), - }, - }, - { - name: 'uql csv query', - query: { - type: 'csv', - parser: 'uql', - source: 'inline', - uql: 'parse-csv', - data: 'name,age\nfoo,30\nbar,17', - }, - }, - { - name: 'uql tsv query', - query: { - type: 'tsv', - parser: 'uql', - source: 'inline', - data: 'name age\nfoo 30\nbar 17', - }, - }, - { - name: 'uql graphql query', - query: { - type: 'graphql', - parser: 'uql', - source: 'inline', - uql: 'parse-json', - data: JSON.stringify([ - { name: 'foo', age: 30 }, - { name: 'bar', age: 17 }, - ]), - }, - }, - { - name: 'uql xml query', - query: { - type: 'xml', - parser: 'uql', - source: 'inline', - uql: 'parse-json', - data: ` foo 30 bar 17 `, - }, - }, - ]; - queries.forEach((q) => { - it(q.name, () => { - query(q.query).then((res) => { - cy.wrap({ - ...res.body.results['A'].frames[0], - schema: { - ...res.body.results['A'].frames[0].schema, - meta: { - ...res.body.results['A'].frames[0].schema.meta, - custom: { - ...res.body.results['A'].frames[0].schema.meta.custom, - duration: 0, - }, - }, - }, - // @ts-ignore - }).snapshot(); - }); - }); - }); -}); diff --git a/cypress_skip/e2e/csv.cy.ts b/cypress_skip/e2e/csv.cy.ts deleted file mode 100644 index 376ebc11..00000000 --- a/cypress_skip/e2e/csv.cy.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { login } from './utils/login'; -import { checkDropdownValue, changeDropdownValue, checkInputContent } from './utils/editorFieldCheck'; -import { checkExploreTableContent, runExploreQuery } from './utils/explore'; -import type { InfinityQuery } from '../../src/types/query.types'; - -const visitExplorePage = (query: Partial = {}) => { - cy.visit('/explore', { qs: { left: JSON.stringify({ datasource: 'Infinity', queries: [query] }) } }); -}; - -describe('explore', () => { - it.skip('should able to run CSV queries correctly', () => { - login(); - visitExplorePage({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv' }); - - checkDropdownValue('Type', 'CSV'); - checkDropdownValue('Parser', 'Default'); - checkDropdownValue('Source', 'URL'); - checkInputContent('URL', 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv'); - checkDropdownValue('Format', 'Table'); - runExploreQuery(); - checkExploreTableContent(['Leanne Graham'].join('')); - cy.contains(`Parsing options & Result fields`); - cy.contains(`Computed columns, Filter, Group by`).should('not.exist'); - cy.contains(`UQL Query`).should('not.exist'); - cy.contains(`GROQ Query`).should('not.exist'); - - changeDropdownValue('Parser', 'Backend'); - checkExploreTableContent(['Leanne Graham'].join('')); - cy.contains(`Parsing options & Result fields`); - cy.contains(`Computed columns, Filter, Group by`); - cy.contains(`UQL Query`).should('not.exist'); - cy.contains(`GROQ Query`).should('not.exist'); - - changeDropdownValue('Parser', 'UQL'); - checkExploreTableContent(['Leanne Graham'].join('')); - cy.contains(`Parsing options & Result fields`).should('not.exist'); - cy.contains(`Computed columns, Filter, Group by`).should('not.exist'); - cy.contains(`UQL`); - cy.contains(`GROQ Query`).should('not.exist'); - }); -}); diff --git a/cypress_skip/e2e/explore.cy.ts b/cypress_skip/e2e/explore.cy.ts deleted file mode 100644 index 47070cd7..00000000 --- a/cypress_skip/e2e/explore.cy.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { login } from './utils/login'; -import { checkDropdownValue, checkInputContent } from './utils/editorFieldCheck'; -import { checkExploreTableContent, runExploreQuery } from './utils/explore'; -import type { InfinityQuery } from './../../src/types/query.types'; - -const visitExplorePage = (query: Partial = {}) => { - cy.visit('/explore', { qs: { left: JSON.stringify({ datasource: 'Infinity', queries: [query] }) } }); -}; - -describe('explore', () => { - it.skip('should able to run default queries correctly', () => { - login(); - visitExplorePage(); - checkDropdownValue('Type', 'JSON'); - checkDropdownValue('Parser', 'Default'); - checkDropdownValue('Source', 'URL'); - checkInputContent('URL', 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.json'); - checkDropdownValue('Format', 'Table'); - runExploreQuery(); - checkExploreTableContent(['age', 'country', 'name', 'occupation', 'salary', '38', 'USA', 'Leanne Graham', 'Devops Engineer', '3000'].join('')); - }); -}); diff --git a/cypress_skip/e2e/json.cy.ts b/cypress_skip/e2e/json.cy.ts deleted file mode 100644 index 76ba8c6f..00000000 --- a/cypress_skip/e2e/json.cy.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { login } from './utils/login'; -import { checkDropdownValue, changeDropdownValue, checkInputContent } from './utils/editorFieldCheck'; -import { checkExploreTableContent, runExploreQuery } from './utils/explore'; -import type { InfinityQuery } from '../../src/types/query.types'; - -const visitExplorePage = (query: Partial = {}) => { - cy.visit('/explore', { qs: { left: JSON.stringify({ datasource: 'Infinity', queries: [query] }) } }); -}; - -describe('explore', () => { - it.skip('should able to run JSON queries correctly', () => { - login(); - visitExplorePage(); - // Default query should work without any error - checkDropdownValue('Type', 'JSON'); - checkDropdownValue('Parser', 'Default'); - checkDropdownValue('Source', 'URL'); - checkInputContent('URL', 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.json'); - checkDropdownValue('Format', 'Table'); - runExploreQuery(); - checkExploreTableContent('Leanne Graham'); - cy.contains(`Parsing options & Result fields`); - cy.contains(`Computed columns, Filter, Group by`).should('not.exist'); - // JSON query with backend should work - changeDropdownValue('Parser', 'Backend'); - runExploreQuery(); - checkExploreTableContent('Leanne Graham'); - cy.contains(`Parsing options & Result fields`); - cy.contains(`Computed columns, Filter, Group by`); - // JSON query with UQL should work - changeDropdownValue('Parser', 'UQL'); - runExploreQuery(); - checkExploreTableContent('Leanne Graham'); - cy.contains(`UQL Query`); - cy.contains(`Parsing options & Result fields`).should('not.exist'); - cy.contains(`Computed columns, Filter, Group by`).should('not.exist'); - cy.contains(`GROQ Query`).should('not.exist'); - // JSON query with GROQ should work - changeDropdownValue('Parser', 'GROQ'); - runExploreQuery(); - checkExploreTableContent('Leanne Graham'); - cy.contains(`GROQ Query`); - cy.contains(`Parsing options & Result fields`).should('not.exist'); - cy.contains(`Computed columns, Filter, Group by`).should('not.exist'); - cy.contains(`UQL Query`).should('not.exist'); - // CSV with default parser should work - // changeDropdownValue('Type', 'CSV'); - // checkExploreError('Invalid Opening Quote: a quote is found inside a field at line 3'); - // changeInputContent('URL', 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv'); - // changeDropdownValue('Parser', 'Default'); - // checkExploreTableContent('Leanne Graham'); - }); -}); diff --git a/cypress_skip/e2e/tsv.cy.ts b/cypress_skip/e2e/tsv.cy.ts deleted file mode 100644 index 6978c82c..00000000 --- a/cypress_skip/e2e/tsv.cy.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { login } from './utils/login'; -import { checkDropdownValue, changeDropdownValue, checkInputContent } from './utils/editorFieldCheck'; -import { runExploreQuery, checkExploreTableContent } from './utils/explore'; -import type { InfinityQuery } from '../../src/types/query.types'; - -const visitExplorePage = (query: Partial = {}) => { - cy.visit('/explore', { qs: { left: JSON.stringify({ datasource: 'Infinity', queries: [query] }) } }); -}; - -describe('explore', () => { - it.skip('should able to run TSV queries correctly', () => { - login(); - visitExplorePage({ type: 'tsv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.tsv' }); - - checkDropdownValue('Type', 'TSV'); - checkDropdownValue('Parser', 'Default'); - checkDropdownValue('Source', 'URL'); - checkInputContent('URL', 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.tsv'); - checkDropdownValue('Format', 'Table'); - runExploreQuery(); - checkExploreTableContent(['Leanne Graham'].join('')); - cy.contains(`Parsing options & Result fields`); - cy.contains(`Computed columns, Filter, Group by`).should('not.exist'); - cy.contains(`UQL Query`).should('not.exist'); - cy.contains(`GROQ Query`).should('not.exist'); - - changeDropdownValue('Parser', 'Backend'); - runExploreQuery(); - checkExploreTableContent(['Leanne Graham'].join('')); - cy.contains(`Parsing options & Result fields`); - cy.contains(`Computed columns, Filter, Group by`); - cy.contains(`UQL Query`).should('not.exist'); - cy.contains(`GROQ Query`).should('not.exist'); - }); -}); diff --git a/cypress_skip/e2e/uql.cyx.ts b/cypress_skip/e2e/uql.cyx.ts deleted file mode 100644 index 5523188e..00000000 --- a/cypress_skip/e2e/uql.cyx.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { login } from './utils/login'; -import { checkDropdownValue } from './utils/editorFieldCheck'; -import { checkExploreTableContent, runExploreQuery } from './utils/explore'; -import type { InfinityQuery } from '../../src/types/query.types'; - -const visitExplorePage = (query: Partial = {}) => { - cy.visit('/explore', { qs: { left: JSON.stringify({ datasource: 'Infinity', queries: [query] }) } }); -}; - -describe('explore', () => { - beforeEach(() => { - cy.viewport(1792, 1017); - login(); - }); - it.skip('should able to run UQL queries correctly', () => { - visitExplorePage({ type: 'uql', source: 'inline', data: `a,b,c\n1,2,3\n4,5,6`, uql: `parse-csv | summarize count() | project "count"` }); - checkDropdownValue('Type', 'UQL'); - checkDropdownValue('Source', 'Inline'); - runExploreQuery(); - checkExploreTableContent(`result2`); - visitExplorePage({ type: 'uql', source: 'inline', data: `a,b,c\n1,2,3\n4,5,6`, uql: `parse-csv | summarize "mean"=mean("b") | project "mean"` }); - checkDropdownValue('Type', 'UQL'); - checkDropdownValue('Source', 'Inline'); - runExploreQuery(); - checkExploreTableContent(`result12.5`); - }); -}); diff --git a/cypress_skip/e2e/utils/api.ts b/cypress_skip/e2e/utils/api.ts deleted file mode 100644 index 69549aff..00000000 --- a/cypress_skip/e2e/utils/api.ts +++ /dev/null @@ -1,21 +0,0 @@ -declare const Buffer: any; - -export const request = (url: string) => { - return cy.request({ - headers: { Authorization: 'Basic ' + new Buffer.from('infinity' + ':' + 'infinity').toString('base64') }, - url: `/api${url}`, - }); -}; - -export const query = (query: object, props: { from?: number; to?: number; datasource_uid?: string; datasource_type?: string; username?: string; password?: string } = {}) => { - const { from = 100, to = 200, datasource_uid = 'Infinity', datasource_type = 'yesoreyeram-infinity-datasource', username = 'infinity', password = 'infinity' } = props; - return cy.request({ - url: `/api/ds/query`, - method: 'post', - headers: { - Authorization: 'Basic ' + new Buffer.from(username + ':' + password).toString('base64'), - 'content-type': 'application/json', - }, - body: { from: from.toString(), to: to.toString(), queries: [{ refId: 'A', datasource: { uid: datasource_uid, type: datasource_type }, ...query }] }, - }); -}; diff --git a/cypress_skip/e2e/utils/editorFieldCheck.ts b/cypress_skip/e2e/utils/editorFieldCheck.ts deleted file mode 100644 index 4fd81c31..00000000 --- a/cypress_skip/e2e/utils/editorFieldCheck.ts +++ /dev/null @@ -1,30 +0,0 @@ -export const checkDropdownValue = (fieldName: string, text: string, timeout = 30 * 1000, wait = 0) => { - cy.get(`[data-testid="infinity-query-field-wrapper-${fieldName.replace(/\ /g, '-').toLowerCase()}"]`).within(($el) => { - cy.contains(text, { timeout }); - }); - cy.wait(wait); -}; - -export const changeDropdownValue = (fieldName: string, text: string, timeout = 30 * 1000, wait = 0) => { - if (fieldName === 'Parser' && text === 'Backend') { - cy.wait(1 * 1000); - } - cy.get(`[data-testid="infinity-query-field-wrapper-${fieldName.replace(/\ /g, '-').toLowerCase()}"]`).within(($el) => { - cy.get('[class$="-input-suffix"]').click(); - cy.get('input').type(`${text}{enter}`); - }); - cy.wait(wait); - cy.contains(text); -}; - -export const checkInputContent = (fieldName: string, text: string, timeout = 30 * 1000, wait = 0) => { - cy.get(`[data-testid="infinity-query-field-wrapper-${fieldName.replace(/\ /g, '-').toLowerCase()}"] input`).should('have.value', text); - cy.wait(wait); -}; - -export const changeInputContent = (fieldName: string, text: string, timeout = 30 * 1000, wait = 0) => { - cy.get(`[data-testid="infinity-query-field-wrapper-${fieldName.replace(/\ /g, '-').toLowerCase()}"] input`) - .clear() - .type(Cypress.platform === 'darwin' ? `{cmd+a}{del}${text}` : `{ctrl+a}{del}${text}`); - cy.wait(wait); -}; diff --git a/cypress_skip/e2e/utils/explore.ts b/cypress_skip/e2e/utils/explore.ts deleted file mode 100644 index f1dc622b..00000000 --- a/cypress_skip/e2e/utils/explore.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const runExploreQuery = (wait = 3 * 1000) => { - cy.get(`[data-testid="data-testid RefreshPicker run button"]`).focus().click(); - cy.wait(wait); -}; - -export const checkExploreTableContent = (check: string = '', wait = 1 * 1000) => { - runExploreQuery(); - cy.contains('Query error').should('not.exist'); - cy.get(`[aria-label="Explore Table"]`).contains(check); - cy.wait(wait); -}; - -export const checkExploreError = (check = '', wait = 1 * 1000) => { - runExploreQuery(); - cy.contains('Query error'); - if (check) { - cy.contains(check); - } - cy.wait(wait); -}; diff --git a/cypress_skip/e2e/utils/login.ts b/cypress_skip/e2e/utils/login.ts deleted file mode 100644 index 8c866966..00000000 --- a/cypress_skip/e2e/utils/login.ts +++ /dev/null @@ -1,10 +0,0 @@ -const timeout = 30 * 1000; -export const login = () => { - cy.viewport(1792, 1017); - cy.visit('/login', { timeout }); - cy.contains('Welcome to Grafana', { timeout }); - cy.get(`[aria-label="${'Username input field'}"]`, { timeout }).should('be.visible').type('infinity'); - cy.get(`[aria-label="${'Password input field'}"]`, { timeout }).should('be.visible').type('infinity'); - cy.get(`[aria-label="${'Login button'}"]`, { timeout }).click(); - cy.get('.login-page', { timeout }).should('not.exist'); -}; diff --git a/cypress_skip/support/commands.ts b/cypress_skip/support/commands.ts deleted file mode 100644 index 3ded8bed..00000000 --- a/cypress_skip/support/commands.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as snapshot from '@cypress/snapshot'; - -snapshot.register(); - -/// -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -// -// declare global { -// namespace Cypress { -// interface Chainable { -// login(email: string, password: string): Chainable -// drag(subject: string, options?: Partial): Chainable -// dismiss(subject: string, options?: Partial): Chainable -// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable -// } -// } -// } diff --git a/cypress_skip/support/e2e.ts b/cypress_skip/support/e2e.ts deleted file mode 100644 index f80f74f8..00000000 --- a/cypress_skip/support/e2e.ts +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/e2e.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') \ No newline at end of file diff --git a/cypress_skip/tsconfig.json b/cypress_skip/tsconfig.json deleted file mode 100644 index 812775f5..00000000 --- a/cypress_skip/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "@grafana/toolkit/src/config/tsconfig.plugin.json", - "include": ["**/*.ts"], - "compilerOptions": { - "baseUrl": "../node_modules", - "types": ["cypress", "node"] - } -} diff --git a/cypress_skip/types.d.ts b/cypress_skip/types.d.ts deleted file mode 100644 index 467674f2..00000000 --- a/cypress_skip/types.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module '@cypress/snapshot'; From 8a9417ef91d7b0fd20bd3ffac58aa2843777a6de Mon Sep 17 00:00:00 2001 From: Sriramajeyam Sugumaran <153843+yesoreyeram@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:35:49 +0000 Subject: [PATCH 2/6] base E2E test suite using playwright --- .github/workflows/e2e.yml | 73 +++++++++++++++++++++++++++++ .gitignore | 7 ++- .nvmrc | 2 +- docker-compose.yaml | 4 +- e2e/auth.setup.ts | 5 ++ e2e/query.spec.ts | 80 ++++++++++++++++++++++++++++++++ e2e/query.ts | 33 +++++++++++++ package.json | 5 +- playwright.config.ts | 25 ++++++++++ yarn.lock | 97 +++++++++++++++++++++++++++++---------- 10 files changed, 302 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/e2e.yml create mode 100644 e2e/auth.setup.ts create mode 100644 e2e/query.spec.ts create mode 100644 e2e/query.ts create mode 100644 playwright.config.ts diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 00000000..4e19d842 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,73 @@ +name: E2E Tests +on: + pull_request: + path-ignore: + - 'docs/**' + branches: + - main + push: + path-ignore: + - 'docs/**' + branches: + - main +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Go environment + uses: actions/setup-go@v4 + with: + go-version: '1.21.6' + - name: Test backend + uses: magefile/mage-action@v2 + with: + version: latest + args: coverage + - name: Build backend + uses: magefile/mage-action@v2 + with: + version: latest + args: buildAll + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 20 + - name: Install dependencies + run: npm install -g yarn && yarn install --frozen-lockfile; + - name: Spellcheck + run: | + yarn spellcheck; + - name: Build Frontend + run: | + yarn build; + - name: Start the docker container for E2E + run: | + docker-compose pull + docker-compose up -d + - name: Wait for grafana to start + uses: nev7n/wait_for_response@v1 + with: + url: 'http://localhost:3000/' + responseCode: 200 + timeout: 20000 + interval: 500 + - name: Install Playwright Browsers + run: yarn playwright install --with-deps + - name: Run E2E tests + run: yarn test:e2e + - name: Run E2E artifacts + uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 + - name: Stop the docker container + if: always() + run: docker-compose down diff --git a/.gitignore b/.gitignore index 40c4ed47..9a2fdf47 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,9 @@ website/next-env.d.ts work/ yarn-debug.log* yarn-error.log* -docker/blocks/tempo/tempo-data \ No newline at end of file +docker/blocks/tempo/tempo-data +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +/playwright/.auth/ \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index 3c032078..209e3ef4 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18 +20 diff --git a/docker-compose.yaml b/docker-compose.yaml index a91e9364..026bc0fa 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -16,8 +16,8 @@ services: - GF_DEFAULT_APP_MODE=development - GF_AUTH_ANONYMOUS_ENABLED=true - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - - GF_SECURITY_ADMIN_USER=infinity - - GF_SECURITY_ADMIN_PASSWORD=infinity + # - GF_SECURITY_ADMIN_USER=infinity + # - GF_SECURITY_ADMIN_PASSWORD=infinity - GF_SECURITY_ANGULAR_SUPPORT_ENABLED=false - GF_SECURITY_CSRF_ALWAYS_CHECK=true - GF_ENTERPRISE_LICENSE_TEXT=$GF_ENTERPRISE_LICENSE_TEXT diff --git a/e2e/auth.setup.ts b/e2e/auth.setup.ts new file mode 100644 index 00000000..42402bae --- /dev/null +++ b/e2e/auth.setup.ts @@ -0,0 +1,5 @@ +import { test as setup } from '@grafana/plugin-e2e'; + +setup('authenticate', async ({ login }) => { + await login(); +}); diff --git a/e2e/query.spec.ts b/e2e/query.spec.ts new file mode 100644 index 00000000..b2bac827 --- /dev/null +++ b/e2e/query.spec.ts @@ -0,0 +1,80 @@ +import { test, expect } from '@grafana/plugin-e2e'; +import { runQuery } from './query'; + +test('test type:json source:url', async ({ page, panelEditPage }) => { + await panelEditPage.datasource.set('Infinity'); + await panelEditPage.setVisualization('Table'); + const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); + + let frames = await runQuery(page, panelEditPage, queryEditorRow, {}); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly + expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered + + frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'backend' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly + expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered + + frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'uql' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly + expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered + + frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'groq' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('groq'); // Ensure the parser type passed correctly + expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered +}); + +test('test type:csv source:url', async ({ page, panelEditPage }) => { + await panelEditPage.datasource.set('Infinity'); + await panelEditPage.setVisualization('Table'); + const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); + + let frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly + expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered + + frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'backend' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly + expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered + + frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'uql' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly + expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend + await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered +}); + +test('test type:xml source:url', async ({ page, panelEditPage }) => { + await panelEditPage.datasource.set('Infinity'); + await panelEditPage.setVisualization('Table'); + const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); + + let frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml' }); + expect(frames.results['A'].frames[0].schema.name).toBe('A'); + expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly + expect((frames.results['A'].frames[0].schema.meta.custom.data || '').includes('Leanne GrahamLeanne Graham) => { + if (query.type) { + const typeDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-type'] input`); + await typeDropdown.clear(); + await typeDropdown.fill(query.type || 'json'); + await page.keyboard.press('Enter'); + } + if (query.source) { + const sourceDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-source'] input`); + await sourceDropdown.clear(); + await sourceDropdown.fill(query.source || 'url'); + await page.keyboard.press('Enter'); + } + if (query.parser) { + const parserDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-parser'] input`); + await parserDropdown.clear(); + await parserDropdown.fill(query.parser || 'simple'); + await page.keyboard.press('Enter'); + } + if (query.url) { + const urlTextBox = await locator.locator(`[data-testid='infinity-query-field-wrapper-url'] input`); + await urlTextBox.clear(); + await urlTextBox.fill(query.url || 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.json'); + await page.keyboard.press('Enter'); + } + const res = await panelEditPage.refreshPanel(); + await expect(panelEditPage).not.toHavePanelError(); + const frames = await res.json(); + return frames; +}; diff --git a/package.json b/package.json index f4feedb4..9cad8924 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "spellcheck": "cspell -c cspell.config.json \"**/*.{ts,tsx,js,go,md,mdx,yml,yaml,json,scss,css}\"", "test": "jest --watch --onlyChanged", "test:ci": "jest --passWithNoTests --maxWorkers 4", + "test:e2e": "yarn playwright test", "build": "webpack -c ./webpack.config.ts --env production", "dev": "webpack -w -c ./webpack.config.ts --env development", "watch": "yarn dev", @@ -67,7 +68,9 @@ "@changesets/cli": "^2.26.1", "@changesets/types": "^5.2.1", "@grafana/eslint-config": "^6.0.1", + "@grafana/plugin-e2e": "^0.9.0", "@grafana/tsconfig": "^1.2.0-rc1", + "@playwright/test": "^1.41.0", "@swc/core": "1.3.75", "@swc/helpers": "^0.4.12", "@swc/jest": "^0.2.23", @@ -87,7 +90,7 @@ "eslint": "8.18.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jsdoc": "^39.3.3", + "eslint-plugin-jsdoc": "^48.0.2", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..583aa39f --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,25 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + testDir: './e2e', + fullyParallel: true, + forbidOnly: !!process.env.CI, // eslint-disable-line no-undef + retries: process.env.CI ? 2 : 0, // eslint-disable-line no-undef + workers: process.env.CI ? 1 : undefined, // eslint-disable-line no-undef + reporter: 'list', + use: { + baseURL: 'http://localhost:3000', + trace: 'on-first-retry', + }, + projects: [ + { + name: 'authenticate', + testMatch: [/.*auth\.setup\.ts/], + }, + { + name: 'query', + use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json' }, + dependencies: ['authenticate'], + }, + ], +}); diff --git a/yarn.lock b/yarn.lock index 020d5ee6..8e09cfd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -915,15 +915,6 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== -"@es-joy/jsdoccomment@~0.36.1": - version "0.36.1" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.36.1.tgz#c37db40da36e4b848da5fd427a74bae3b004a30f" - integrity sha512-922xqFsTpHs6D0BUiG4toiyPOMc8/jafnWKxz1KWgS4XzKPy2qXf1Pe6UFuNSCQqt6tOuhAWXBNuuyUhJmw9Vg== - dependencies: - comment-parser "1.3.1" - esquery "^1.4.0" - jsdoc-type-pratt-parser "~3.1.0" - "@es-joy/jsdoccomment@~0.39.4": version "0.39.4" resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz#6b8a62e9b3077027837728818d3c4389a898b392" @@ -933,6 +924,15 @@ esquery "^1.5.0" jsdoc-type-pratt-parser "~4.0.0" +"@es-joy/jsdoccomment@~0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz#4a2f7db42209c0425c71a1476ef1bdb6dcd836f6" + integrity sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw== + dependencies: + comment-parser "1.4.1" + esquery "^1.5.0" + jsdoc-type-pratt-parser "~4.0.0" + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1108,6 +1108,14 @@ ua-parser-js "^1.0.32" web-vitals "^3.1.1" +"@grafana/plugin-e2e@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@grafana/plugin-e2e/-/plugin-e2e-0.9.0.tgz#573226381274b70a370cda1aadfa9b304e3e216b" + integrity sha512-6Pk3OzfTFF2fagd37QZoxqMNhft4ILd0jAIR53bhDkZ/tK3zXP5oL16zPMP0AYVY6tqwNuzqhQmY89xkGj0/CA== + dependencies: + semver "^7.5.4" + uuid "^9.0.1" + "@grafana/runtime@9.5.15": version "9.5.15" resolved "https://registry.yarnpkg.com/@grafana/runtime/-/runtime-9.5.15.tgz#71cbce20101c656d3e070d8b2496e8def6df18ef" @@ -1710,6 +1718,13 @@ resolved "https://registry.yarnpkg.com/@petamoriken/float16/-/float16-3.8.4.tgz#cd3c02a7fe39f10ae3dd24ed33bd082053aadd66" integrity sha512-kB+NJ5Br56ZhElKsf0pM7/PQfrDdDVMRz8f0JM6eVOGE+L89z9hwcst9QvWBBnazzuqGTGtPsJNZoQ1JdNiGSQ== +"@playwright/test@^1.41.0": + version "1.41.0" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.41.0.tgz#b083e976295f1fe039c15d451c66554d7f37278c" + integrity sha512-Grvzj841THwtpBOrfiHOeYTJQxDRnKofMSzCiV8XeyLWu3o89qftQ4BCKfkziJhSUQRd0utKhrddtIsiraIwmw== + dependencies: + playwright "1.41.0" + "@popperjs/core@2.11.6": version "2.11.6" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" @@ -3654,6 +3669,11 @@ comment-parser@1.3.1: resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.3.1.tgz#3d7ea3adaf9345594aedee6563f422348f165c1b" integrity sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA== +comment-parser@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" + integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== + complex.js@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.1.1.tgz#0675dac8e464ec431fb2ab7d30f41d889fb25c31" @@ -4786,18 +4806,20 @@ eslint-plugin-jsdoc@46.2.6: semver "^7.5.1" spdx-expression-parse "^3.0.1" -eslint-plugin-jsdoc@^39.3.3: - version "39.9.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.9.1.tgz#e9ce1723411fd7ea0933b3ef0dd02156ae3068e2" - integrity sha512-Rq2QY6BZP2meNIs48aZ3GlIlJgBqFCmR55+UBvaDkA3ZNQ0SvQXOs2QKkubakEijV8UbIVbVZKsOVN8G3MuqZw== +eslint-plugin-jsdoc@^48.0.2: + version "48.0.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.2.tgz#b843107e8caec57b8b463f04797be3b30d6a52da" + integrity sha512-CBFl5Jc7+jlV36RwDm+PQ8Uw5r28pn2/uW/OaB+Gw5bFwn4Py/1eYMZ3hGf9S4meUFZ/sRvS+hVif2mRAp6WqQ== dependencies: - "@es-joy/jsdoccomment" "~0.36.1" - comment-parser "1.3.1" + "@es-joy/jsdoccomment" "~0.41.0" + are-docs-informative "^0.0.2" + comment-parser "1.4.1" debug "^4.3.4" escape-string-regexp "^4.0.0" - esquery "^1.4.0" - semver "^7.3.8" - spdx-expression-parse "^3.0.1" + esquery "^1.5.0" + is-builtin-module "^3.2.1" + semver "^7.5.4" + spdx-expression-parse "^4.0.0" eslint-plugin-jsx-a11y@^6.5.1: version "6.8.0" @@ -5336,6 +5358,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -6624,11 +6651,6 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsdoc-type-pratt-parser@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz#a4a56bdc6e82e5865ffd9febc5b1a227ff28e67e" - integrity sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw== - jsdoc-type-pratt-parser@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" @@ -7543,6 +7565,20 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +playwright-core@1.41.0: + version "1.41.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.41.0.tgz#dbda9c3948df28a8deae76cc90b424e47174f9d7" + integrity sha512-UGKASUhXmvqm2Lxa1fNr8sFwAtqjpgBRr9jQ7XBI8Rn5uFiEowGUGwrruUQsVPIom4bk7Lt+oLGpXobnXzrBIw== + +playwright@1.41.0: + version "1.41.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.41.0.tgz#77ab5f3a5fde479522167f74a5070e72ce884bff" + integrity sha512-XOsfl5ZtAik/T9oek4V0jAypNlaCNzuKOwVhqhgYT3os6kH34PzbRb74F0VWcLYa5WFdnmxl7qyAHBXvPv7lqQ== + dependencies: + playwright-core "1.41.0" + optionalDependencies: + fsevents "2.3.2" + portfinder@^1.0.17: version "1.0.32" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" @@ -8546,7 +8582,7 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1, semver@^7.5.3, semver@^7.5.4: +semver@^7.3.5, semver@^7.3.7, semver@^7.5.1, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -8827,6 +8863,14 @@ spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" +spdx-expression-parse@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794" + integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + spdx-license-ids@^3.0.0: version "3.0.16" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz#a14f64e0954f6e25cc6587bd4f392522db0d998f" @@ -9535,6 +9579,11 @@ uuid@9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" From 5f954f4247ec026b7ff917da97106003cbedf4fc Mon Sep 17 00:00:00 2001 From: Sriramajeyam Sugumaran <153843+yesoreyeram@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:44:15 +0000 Subject: [PATCH 3/6] updated github workflow --- .github/workflows/e2e.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 4e19d842..e72fc1cd 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -3,13 +3,9 @@ on: pull_request: path-ignore: - 'docs/**' - branches: - - main push: path-ignore: - 'docs/**' - branches: - - main concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true From 5db0d7aad95f0e24cb2fe8e42169787f291de526 Mon Sep 17 00:00:00 2001 From: Sriramajeyam Sugumaran <153843+yesoreyeram@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:09:01 +0000 Subject: [PATCH 4/6] simplified the params --- e2e/query.spec.ts | 26 +++++++++++++------------- e2e/query.ts | 4 +++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/e2e/query.spec.ts b/e2e/query.spec.ts index b2bac827..d3b9c598 100644 --- a/e2e/query.spec.ts +++ b/e2e/query.spec.ts @@ -4,27 +4,27 @@ import { runQuery } from './query'; test('test type:json source:url', async ({ page, panelEditPage }) => { await panelEditPage.datasource.set('Infinity'); await panelEditPage.setVisualization('Table'); - const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); + const options = { page, panelEditPage }; - let frames = await runQuery(page, panelEditPage, queryEditorRow, {}); + let frames = await runQuery({}, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered - frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'backend' }); + frames = await runQuery({ parser: 'backend' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered - frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'uql' }); + frames = await runQuery({ parser: 'uql' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered - frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'groq' }); + frames = await runQuery({ parser: 'groq' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('groq'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend @@ -34,21 +34,21 @@ test('test type:json source:url', async ({ page, panelEditPage }) => { test('test type:csv source:url', async ({ page, panelEditPage }) => { await panelEditPage.datasource.set('Infinity'); await panelEditPage.setVisualization('Table'); - const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); + const options = { page, panelEditPage }; - let frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv' }); + let frames = await runQuery({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered - frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'backend' }); + frames = await runQuery({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'backend' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered - frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'uql' }); + frames = await runQuery({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'uql' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend @@ -58,21 +58,21 @@ test('test type:csv source:url', async ({ page, panelEditPage }) => { test('test type:xml source:url', async ({ page, panelEditPage }) => { await panelEditPage.datasource.set('Infinity'); await panelEditPage.setVisualization('Table'); - const queryEditorRow = await panelEditPage.getQueryEditorRow('A'); + const options = { page, panelEditPage }; - let frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml' }); + let frames = await runQuery({ type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml' }, options); expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly expect((frames.results['A'].frames[0].schema.meta.custom.data || '').includes('Leanne GrahamLeanne Graham) => { +export const runQuery = async (query: Record, options: { page: Page; panelEditPage: PanelEditPage }) => { + const { page, panelEditPage } = options; + const locator = await panelEditPage.getQueryEditorRow('A'); if (query.type) { const typeDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-type'] input`); await typeDropdown.clear(); From f45c8dd06db6f3c19731a16a15a617da0efc59a9 Mon Sep 17 00:00:00 2001 From: Sriramajeyam Sugumaran <153843+yesoreyeram@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:28:29 +0000 Subject: [PATCH 5/6] updated playwright report type --- playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.ts b/playwright.config.ts index 583aa39f..9f123783 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, // eslint-disable-line no-undef retries: process.env.CI ? 2 : 0, // eslint-disable-line no-undef workers: process.env.CI ? 1 : undefined, // eslint-disable-line no-undef - reporter: 'list', + reporter: 'html', use: { baseURL: 'http://localhost:3000', trace: 'on-first-retry', From 690ee207f8a7de50d1e78c7e19206e606fe7226a Mon Sep 17 00:00:00 2001 From: Sriramajeyam Sugumaran <153843+yesoreyeram@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:58:15 +0000 Subject: [PATCH 6/6] updated reporters --- e2e/query.spec.ts | 10 ---------- playwright.config.ts | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/e2e/query.spec.ts b/e2e/query.spec.ts index d3b9c598..497e8e85 100644 --- a/e2e/query.spec.ts +++ b/e2e/query.spec.ts @@ -7,25 +7,21 @@ test('test type:json source:url', async ({ page, panelEditPage }) => { const options = { page, panelEditPage }; let frames = await runQuery({}, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered frames = await runQuery({ parser: 'backend' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered frames = await runQuery({ parser: 'uql' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered frames = await runQuery({ parser: 'groq' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('groq'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered @@ -37,19 +33,16 @@ test('test type:csv source:url', async ({ page, panelEditPage }) => { const options = { page, panelEditPage }; let frames = await runQuery({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered frames = await runQuery({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'backend' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered frames = await runQuery({ type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'uql' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered @@ -61,19 +54,16 @@ test('test type:xml source:url', async ({ page, panelEditPage }) => { const options = { page, panelEditPage }; let frames = await runQuery({ type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml' }, options); - expect(frames.results['A'].frames[0].schema.name).toBe('A'); expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly expect((frames.results['A'].frames[0].schema.meta.custom.data || '').includes('Leanne GrahamLeanne Graham