test(cypress): add dashboards reader test

pull/5911/head
k3yi0 2022-04-25 11:08:30 +02:00
parent ce9ce5b3ab
commit f0edb61f83
6 changed files with 211 additions and 29 deletions

View File

@ -4,10 +4,11 @@
"video": false,
"env": {
"ALLOW_SCREENSHOT": true,
"url": "https://localhost:8086",
"influxDBURL": "https://localhost:8086",
"username": "admin",
"password": "admin",
"connectionName": "E1M1",
"insecureSkipVerify": true
"insecureSkipVerify": true,
"oauth2ServerURL": "http://localhost:8087"
}
}

19
ui/cypress/index.d.ts vendored
View File

@ -1,22 +1,35 @@
/* eslint @typescript-eslint/no-unused-vars: "off" */
import 'jest'
import {
getByTestID,
cutConnections,
removeConnections,
createConnection,
createDashboard,
deleteDashboards,
createDashboardWithCell,
OAuthLogin,
OAuthLogout,
createUser,
deleteUser,
createOrg,
deleteOrg
} from './support/commands'
declare global {
namespace Cypress {
interface Chainable {
getByTestID: typeof getByTestID
cutConnections: typeof cutConnections
removeConnections: typeof removeConnections
createConnection: typeof createConnection
createDashboard: typeof createDashboard
deleteDashboards: typeof deleteDashboards
createDashboardWithCell: typeof createDashboardWithCell
OAuthLogin: typeof OAuthLogin
OAuthLogout: typeof OAuthLogout
createUser: typeof createUser
deleteUser: typeof deleteUser
createOrg: typeof createOrg
deleteOrg: typeof deleteOrg
}
}
}

View File

@ -1,7 +1,8 @@
describe('dashboards', () => {
describe('Use Dashboards', () => {
beforeEach(() => {
cy.OAuthLogin('test')
cy.deleteDashboards()
cy.cutConnections()
cy.removeConnections()
cy.createConnection()
cy.get('@connections').then(connections => {
cy.fixture('routes').then(({dashboards}) => {
@ -38,4 +39,41 @@ describe('dashboards', () => {
})
.should('not.exist')
})
describe('Use Dashboards as reader', () => {
let query = `SELECT mean("pointsWritten") AS "mean_pointsWritten"
FROM "_internal"."monitor"."localStore"
WHERE time > :dashboardTime: AND time < :upperDashboardTime:
GROUP BY time(:interval:) FILL(null)`
beforeEach(() => {
cy.OAuthLogin('test')
cy.deleteUser('Reader')
cy.deleteDashboards()
cy.removeConnections()
cy.createConnection()
cy.createDashboardWithCell(query)
cy.createUser('Reader', 'oauth-mock', 'oauth2')
cy.OAuthLogout()
cy.OAuthLogin('Reader')
cy.visit('/')
})
it('use dashboards as user with reader role', () => {
cy.getByTestID('sidebar').should('not.exist')
cy.getByTestID('import-dashboard--button').should('not.exist')
cy.getByTestID('create-dashboard-button').should('not.exist')
cy.getByTestID('dashboard-filter--input').type('Empty')
cy.getByTestID('dashboard-panel').should('have.text', `Looks like you dont have any dashboards`)
cy.getByTestID('dashboard-filter--input').clear().type('Dashboard')
cy.getByTestID('Unnamed Dashboard').click()
cy.get('.dashboard-empty--menu').should('not.exist')
cy.getByTestID('add-cell').should('not.exist')
cy.getByTestID('show-variables--button').click()
cy.getByTestID('add-template-variable').should('not.exist')
cy.getByTestID('show-annotations--button').click()
cy.getByTestID('add-annotation--button').should('not.exist')
cy.getByTestID('add-annotation-filter--button').should('not.exist')
})
})
})

View File

@ -1,10 +1,10 @@
describe('query builder', () => {
beforeEach(() => {
cy.OAuthLogin('test')
cy.deleteDashboards()
cy.cutConnections()
cy.removeConnections()
cy.createConnection()
cy.createDashboard()
cy.get('@connections').then(connections => {
cy.get('@dashboards').then(dashboards => {
cy.fixture('routes').then(routes => {

View File

@ -1,6 +1,7 @@
describe('Welcome Page', () => {
beforeEach(() => {
cy.cutConnections()
cy.OAuthLogin('test')
cy.removeConnections()
cy.visit('/')
})

View File

@ -1,4 +1,4 @@
import {addMatchImageSnapshotCommand} from 'cypress-image-snapshot/command'
import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot/command'
declare namespace Cypress {
interface Chainable<Subject> {
@ -15,7 +15,7 @@ addMatchImageSnapshotCommand({
customSnapshotsDir: '../ui/cypress/snapshots',
failureThreshold: 0.75, // threshold for entire image
failureThresholdType: 'percent', // percent of image or number of pixels
customDiffConfig: {threshold: 0.75}, // threshold for each pixel
customDiffConfig: { threshold: 0.75 }, // threshold for each pixel
capture: 'viewport', // capture viewport in screenshot
})
@ -35,18 +35,43 @@ export const getByTestID = (
options?: Partial<
Cypress.Loggable & Cypress.Timeoutable & Cypress.Withinable & Cypress.Shadow
>
): Cypress.Chainable => {
): globalThis.Cypress.Chainable<JQuery<HTMLElement>> => {
return cy.get(`[data-test="${dataTest}"]`, options)
}
// Function sends HTTP POST request to OAuth2 Mock server in order to change user information
const changeUserInfo: Function = (name: string): void => {
const xhttp: XMLHttpRequest = new XMLHttpRequest()
const url: string = Cypress.env('oauth2ServerURL') + '/config'
const body = {
"userinfo": {
"name": name,
"email": name + "@oauth2.mock"
}
}
xhttp.open('POST', url)
xhttp.setRequestHeader('Content-Type', 'application/json')
xhttp.send(JSON.stringify(body))
}
export const OAuthLogin = (name: string) => {
changeUserInfo(name)
return cy.visit('/oauth/oauth-mock/login')
}
export const OAuthLogout = () => {
return cy.visit('/oauth/oauth-mock/logout')
}
// Change enviromental values in cypress.json
export const createConnection = (url: string = Cypress.env('url')) => {
export const createConnection = (url?: string) => {
return cy
.request({
method: 'POST',
url: '/chronograf/v1/sources',
body: {
url: url,
url: url ?? Cypress.env('influxDBURL'),
username: Cypress.env('username'),
password: Cypress.env('password'),
name: Cypress.env('connectionName'),
@ -58,7 +83,7 @@ export const createConnection = (url: string = Cypress.env('url')) => {
})
}
export const cutConnections = () => {
export const removeConnections = () => {
return cy.request('GET', '/chronograf/v1/sources').then(response => {
response.body.sources.forEach(connection => {
cy.request('DELETE', `${connection.links.self}`)
@ -66,14 +91,15 @@ export const cutConnections = () => {
})
}
export const createDashboard = (name: string = 'Default Dashboard') => {
cy.fixture('routes').then(({dashboards}) => {
export const createDashboard = (name?: string) => {
return cy
.fixture('routes').then(({ dashboards }) => {
return cy
.request({
method: 'POST',
url: `/chronograf/v1${dashboards}`,
body: {
name: name,
name: name ?? 'Default Dashboard',
},
})
.then(() => {
@ -85,34 +111,137 @@ export const createDashboard = (name: string = 'Default Dashboard') => {
export const deleteDashboards = () => {
return cy
.request('GET', '/chronograf/v1/dashboards')
.then(({body: responseBody}) => {
responseBody.dashboards.forEach(dashboard => {
.then(({ body: response }) => {
response.dashboards.forEach(dashboard => {
cy.request('DELETE', `${dashboard.links.self}`)
})
})
.then(() => {
wrapDashboards()
})
}
export const createDashboardWithCell = (
query?: string,
dashboardName?: string,
cellName?: string,
xPosition?: number,
yPosition?: number,
cellWidth?: number,
cellHeight?: number,
) => {
return cy
.request({
method: 'POST',
url: `/chronograf/v1/dashboards/`,
body: {
"cells": [
{
"x": xPosition ?? 0,
"y": yPosition ?? 0,
"w": cellWidth ?? 8,
"h": cellHeight ?? 4,
"name": cellName ?? "Unnamed Cell",
"queries": [
{
"query": query,
"db": Cypress.env('connectionName'),
"label": "%",
}
]
}
],
name: dashboardName ?? "Unnamed Dashboard"
}
})
}
export const createUser = (
userName: string,
provider: string,
scheme: string,
organization?: string,
role?: string
) => {
return cy.request({
method: 'POST',
url: '/chronograf/v1/users',
body: {
"name": userName + "@oauth2.mock",
"provider": provider,
"roles": [{
"name": role ?? "reader",
"organization": organization ?? "default"
}],
"scheme": scheme,
}
})
}
export const deleteUser = (name: string) => {
const userName = name + '@oauth2.mock'
return cy
.request('GET', '/chronograf/v1/users')
.then(({ body: response }) => {
response.users.forEach(user => {
if (userName == user.name) {
cy.request('DELETE', user.links.self)
}
})
})
}
function wrapConnections(): Cypress.Chainable {
export const createOrg = (orgName: string, defaultRole: string) => {
return cy.request({
method: 'POST',
url: '/chronograf/v1/organizations',
body: {
"defaultRole": defaultRole,
"name": orgName
}
})
.then(() => {
wrapOrgs()
})
}
export const deleteOrg = (id: string) => {
return cy.request('DELETE', `/chronograf/v1/organizations/${id}`)
}
function wrapConnections() {
return cy
.request({
method: 'GET',
url: '/chronograf/v1/sources',
})
.then(response => {
const connections = response.body.sources
.then(({ body: response }) => {
const connections = response.sources
cy.wrap(connections).as('connections')
})
}
function wrapDashboards(): Cypress.Chainable {
return cy.request('GET', '/chronograf/v1/dashboards').then(response => {
const dashboards = response.body.dashboards
cy.wrap(dashboards).as('dashboards')
function wrapDashboards() {
return cy.request('GET', '/chronograf/v1/dashboards').then(({ body: response }) => {
cy.wrap(response.dashboards).as('dashboards')
})
}
function wrapOrgs() {
return cy.request('GET', '/chronograf/v1/organizations').then(({ body: response }) => {
cy.wrap(response.organizations).as('orgs')
})
}
Cypress.Commands.add('getByTestID', getByTestID)
Cypress.Commands.add('createConnection', createConnection)
Cypress.Commands.add('cutConnections', cutConnections)
Cypress.Commands.add('removeConnections', removeConnections)
Cypress.Commands.add('createDashboard', createDashboard)
Cypress.Commands.add('deleteDashboards', deleteDashboards)
Cypress.Commands.add('createDashboardWithCell', createDashboardWithCell)
Cypress.Commands.add('OAuthLogin', OAuthLogin)
Cypress.Commands.add('OAuthLogout', OAuthLogout)
Cypress.Commands.add('createUser', createUser)
Cypress.Commands.add('deleteUser', deleteUser)
Cypress.Commands.add('createOrg', createOrg)
Cypress.Commands.add('deleteOrg', deleteOrg)