11import { test , expect , Page , Locator } from '@playwright/test' ;
22
33const GRAFANA_CLIENT = 'grafana-client' ;
4+ const GRAFANA_VERSION = process . env . GRAFANA_VERSION || '9.5.0' ;
5+ const GRAFANA_MAJOR = parseInt ( GRAFANA_VERSION . split ( '.' ) [ 0 ] , 10 ) ;
6+ const isNewGrafana = GRAFANA_MAJOR >= 10 ;
47
5- // Helper: resolves across Grafana 9.x (aria-label) and 11.x (data-testid)
6- function byLabelOrTestId ( page : Page , label : string ) : Locator {
7- return page . getByLabel ( label ) . or ( page . getByTestId ( `data-testid ${ label } ` ) ) ;
8+ // Grafana 9.x uses aria-label, 10+ uses data-testid
9+ function sel ( page : Page , name : string ) : Locator {
10+ return isNewGrafana
11+ ? page . getByTestId ( `data-testid ${ name } ` )
12+ : page . getByLabel ( name ) ;
813}
914
1015async function login ( page : Page ) {
1116 await page . goto ( 'http://localhost:3000/login' ) ;
12- await byLabelOrTestId ( page , 'Username input field' ) . fill ( 'admin' ) ;
13- await byLabelOrTestId ( page , 'Password input field' ) . fill ( 'admin' ) ;
14- await byLabelOrTestId ( page , 'Login button' ) . click ( ) ;
15- await byLabelOrTestId ( page , 'Skip change password button' ) . click ( ) ;
17+ await sel ( page , 'Username input field' ) . fill ( 'admin' ) ;
18+ await sel ( page , 'Password input field' ) . fill ( 'admin' ) ;
19+ await sel ( page , 'Login button' ) . click ( ) ;
20+ await sel ( page , 'Skip change password button' ) . click ( ) ;
21+ await page . waitForLoadState ( 'networkidle' ) ;
1622}
1723
1824async function goToTrinoSettings ( page : Page ) {
19- await byLabelOrTestId ( page , 'Toggle menu' ) . click ( ) ;
25+ await sel ( page , 'Toggle menu' ) . click ( ) ;
2026 await page . getByRole ( 'link' , { name : 'Connections' } ) . click ( ) ;
2127 await page . getByRole ( 'link' , { name : 'Trino' } ) . click ( ) ;
22- // Grafana 9.x: "Create a Trino data source"; 11.x: "Add new data source"
23- await page . getByText ( 'Create a Trino data source' )
24- . or ( page . getByRole ( 'button' , { name : 'Add new data source' } ) )
25- . click ( ) ;
28+ if ( isNewGrafana ) {
29+ await page . getByRole ( 'button' , { name : 'Add new data source' } ) . click ( ) ;
30+ } else {
31+ await page . getByText ( 'Create a Trino data source' ) . click ( ) ;
32+ }
2633}
2734
2835async function setupDataSourceWithAccessToken ( page : Page ) {
29- await byLabelOrTestId ( page , 'Datasource HTTP settings url' ) . fill ( 'http://trino:8080' ) ;
30- // 9.x: div text is "Impersonate logged in userAccess token"; 11.x: "Impersonate logged in user"
31- await page . locator ( 'div' ) . filter ( { hasText : / ^ I m p e r s o n a t e l o g g e d i n u s e r ( A c c e s s t o k e n ) ? $ / } ) . getByLabel ( 'Toggle switch' ) . click ( ) ;
36+ await sel ( page , 'Datasource HTTP settings url' ) . fill ( 'http://trino:8080' ) ;
37+ if ( isNewGrafana ) {
38+ await page . locator ( 'div' ) . filter ( { hasText : / ^ I m p e r s o n a t e l o g g e d i n u s e r $ / } ) . getByLabel ( 'Toggle switch' ) . click ( ) ;
39+ } else {
40+ await page . locator ( 'div' ) . filter ( { hasText : / ^ I m p e r s o n a t e l o g g e d i n u s e r A c c e s s t o k e n $ / } ) . getByLabel ( 'Toggle switch' ) . click ( ) ;
41+ }
3242 await page . locator ( 'div' ) . filter ( { hasText : / ^ A c c e s s t o k e n $ / } ) . locator ( 'input[type="password"]' ) . fill ( 'aaa' ) ;
33- await byLabelOrTestId ( page , 'Data source settings page Save and Test button' ) . click ( ) ;
34- await page . waitForSelector ( '[role="alert"], [data-testid="data-testid Alert success"] ' , { timeout : 10000 } ) ;
43+ await sel ( page , 'Data source settings page Save and Test button' ) . click ( ) ;
44+ await page . waitForSelector ( '[role="alert"]' , { timeout : 10000 } ) ;
3545}
3646
3747async function setupDataSourceWithClientCredentials ( page : Page , clientId : string ) {
38- await byLabelOrTestId ( page , 'Datasource HTTP settings url' ) . fill ( 'http://trino:8080' ) ;
48+ await sel ( page , 'Datasource HTTP settings url' ) . fill ( 'http://trino:8080' ) ;
3949 await page . locator ( 'div' ) . filter ( { hasText : / ^ T o k e n U R L $ / } ) . locator ( 'input' ) . fill ( 'http://keycloak:8080/realms/trino-realm/protocol/openid-connect/token' ) ;
4050 await page . locator ( 'div' ) . filter ( { hasText : / ^ C l i e n t i d $ / } ) . locator ( 'input' ) . fill ( clientId ) ;
4151 await page . locator ( 'div' ) . filter ( { hasText : / ^ C l i e n t s e c r e t $ / } ) . locator ( 'input[type="password"]' ) . fill ( 'grafana-secret' ) ;
4252 await page . locator ( 'div' ) . filter ( { hasText : / ^ I m p e r s o n a t i o n u s e r $ / } ) . locator ( 'input' ) . fill ( 'service-account-grafana-client' ) ;
43- await byLabelOrTestId ( page , 'Data source settings page Save and Test button' ) . click ( ) ;
44- await page . waitForSelector ( '[role="alert"], [data-testid="data-testid Alert success"] ' , { timeout : 10000 } ) ;
53+ await sel ( page , 'Data source settings page Save and Test button' ) . click ( ) ;
54+ await page . waitForSelector ( '[role="alert"]' , { timeout : 10000 } ) ;
4555}
4656
4757async function runQueryAndCheckResults ( page : Page ) {
48- // "Explore" text in 9.x, "Explore data" label in 11.x
49- await page . getByText ( 'Explore' , { exact : true } ) . or ( page . getByLabel ( 'Explore data' ) ) . click ( ) ;
58+ if ( isNewGrafana ) {
59+ await page . getByLabel ( 'Explore data' ) . click ( ) ;
60+ } else {
61+ await page . getByText ( 'Explore' , { exact : true } ) . click ( ) ;
62+ }
5063 await page . getByTestId ( 'data-testid TimePicker Open Button' ) . click ( ) ;
51- await byLabelOrTestId ( page , 'Time Range from field' ) . fill ( '1995-01-01' ) ;
52- await byLabelOrTestId ( page , 'Time Range to field' ) . fill ( '1995-12-31' ) ;
64+ await sel ( page , 'Time Range from field' ) . fill ( '1995-01-01' ) ;
65+ await sel ( page , 'Time Range to field' ) . fill ( '1995-12-31' ) ;
5366 await page . getByTestId ( 'data-testid TimePicker submit button' ) . click ( ) ;
54- // Format dropdown: use combobox role (works in both 9.x and 11.x)
55- await page . getByRole ( 'combobox' , { name : 'Format as' } ) . click ( ) ;
56- await page . getByText ( 'Table' , { exact : true } ) . or ( page . getByRole ( 'option' , { name : 'Table' } ) ) . click ( ) ;
67+ if ( isNewGrafana ) {
68+ await page . locator ( 'div' ) . filter ( { hasText : / ^ F o r m a t a s C h o o s e $ / } ) . locator ( 'svg' ) . click ( ) ;
69+ await page . getByRole ( 'option' , { name : 'Table' } ) . click ( ) ;
70+ await page . getByTestId ( 'data-testid Code editor container' ) . click ( ) ;
71+ } else {
72+ await page . getByRole ( 'combobox' , { name : 'Format as' } ) . click ( ) ;
73+ await page . getByRole ( 'option' , { name : 'Table' } ) . click ( ) ;
74+ }
5775 await page . getByTestId ( 'data-testid RefreshPicker run button' ) . click ( ) ;
58- await expect ( page . getByTestId ( 'data-testid table body' ) ) . toContainText ( / .* 1 9 9 5 - 0 1 - 1 9 0 .: 0 0 : 0 0 .* / ) ;
76+ await expect ( page . getByTestId ( 'data-testid table body' ) ) . toContainText ( / .* 1 9 9 5 - 0 1 - 1 9 0 .: 0 0 : 0 0 .* / , { timeout : 30000 } ) ;
5977}
6078
6179test ( 'test with access token' , async ( { page } ) => {
@@ -76,17 +94,19 @@ test('test client credentials flow with wrong credentials', async ({ page }) =>
7694 await login ( page ) ;
7795 await goToTrinoSettings ( page ) ;
7896 await setupDataSourceWithClientCredentials ( page , "some-wrong-client" ) ;
79- // After Save & Test with wrong credentials, an error alert should appear
80- const errorAlert = page . locator ( '[role="alert"]' ) . filter ( { hasText : / e r r o r | f a i l e d | E r r o r / i } ) ;
81- await expect ( errorAlert . first ( ) ) . toBeVisible ( { timeout : 10000 } ) ;
97+ // Alert is already visible (setupDataSourceWithClientCredentials waits for it).
98+ // Verify it is NOT the success message.
99+ await expect ( page . locator ( '[role="alert"]' ) . first ( ) ) . toBeVisible ( { timeout : 10000 } ) ;
100+ await expect ( page . locator ( '[role="alert"]' ) . filter ( { hasText : 'Data source is working' } ) ) . toHaveCount ( 0 ) ;
82101} ) ;
83102
84103test ( 'test client credentials flow with configured access token' , async ( { page } ) => {
85104 await login ( page ) ;
86105 await goToTrinoSettings ( page ) ;
87106 await page . locator ( 'div' ) . filter ( { hasText : / ^ A c c e s s t o k e n $ / } ) . locator ( 'input[type="password"]' ) . fill ( 'aaa' ) ;
88107 await setupDataSourceWithClientCredentials ( page , GRAFANA_CLIENT ) ;
89- // After Save & Test with both access token and client credentials, an error alert should appear
90- const errorAlert = page . locator ( '[role="alert"]' ) . filter ( { hasText : / e r r o r | f a i l e d | E r r o r / i } ) ;
91- await expect ( errorAlert . first ( ) ) . toBeVisible ( { timeout : 10000 } ) ;
108+ // Alert is already visible (setupDataSourceWithClientCredentials waits for it).
109+ // Verify it is NOT the success message.
110+ await expect ( page . locator ( '[role="alert"]' ) . first ( ) ) . toBeVisible ( { timeout : 10000 } ) ;
111+ await expect ( page . locator ( '[role="alert"]' ) . filter ( { hasText : 'Data source is working' } ) ) . toHaveCount ( 0 ) ;
92112} ) ;
0 commit comments