2022-06-29 04:04:27 -05:00
import { e2e } from '@grafana/e2e' ;
2022-08-11 10:57:10 -05:00
const MISSING_LABEL_FILTER_ERROR_MESSAGE = 'Select at least 1 label filter (label and value)' ;
2022-06-29 04:04:27 -05:00
const dataSourceName = 'LokiBuilder' ;
const addDataSource = ( ) = > {
e2e . flows . addDataSource ( {
type : 'Loki' ,
2023-09-05 01:59:13 -05:00
expectedAlertMessage : 'Unable to connect with Loki. Please check the server logs for more details.' ,
2022-06-29 04:04:27 -05:00
name : dataSourceName ,
form : ( ) = > {
2023-08-14 07:42:14 -05:00
e2e ( ) . get ( '#connection-url' ) . type ( 'http://loki-url:3100' ) ;
2022-06-29 04:04:27 -05:00
} ,
} ) ;
} ;
2023-08-03 09:27:23 -05:00
const finalQuery = 'rate({instance=~"instance1|instance2"} | logfmt | __error__=`` [$__auto]' ;
2022-09-30 08:27:48 -05:00
2022-06-29 04:04:27 -05:00
describe ( 'Loki query builder' , ( ) = > {
beforeEach ( ( ) = > {
e2e . flows . login ( 'admin' , 'admin' ) ;
e2e ( )
. request ( { url : ` ${ e2e . env ( 'BASE_URL' ) } /api/datasources/name/ ${ dataSourceName } ` , failOnStatusCode : false } )
. then ( ( response ) = > {
if ( response . isOkStatusCode ) {
return ;
}
addDataSource ( ) ;
} ) ;
} ) ;
it ( 'should be able to use all modes' , ( ) = > {
2023-06-02 05:35:11 -05:00
e2e ( )
. intercept ( /labels\?/ , ( req ) = > {
req . reply ( { status : 'success' , data : [ 'instance' , 'job' , 'source' ] } ) ;
} )
. as ( 'labelsRequest' ) ;
2022-06-29 04:04:27 -05:00
e2e ( ) . intercept ( /series?/ , ( req ) = > {
req . reply ( { status : 'success' , data : [ { instance : 'instance1' } ] } ) ;
} ) ;
2023-06-02 05:35:11 -05:00
e2e ( )
. intercept ( /values/ , ( req ) = > {
req . reply ( { status : 'success' , data : [ 'instance1' , 'instance2' ] } ) ;
} )
. as ( 'valuesRequest' ) ;
2022-06-29 04:04:27 -05:00
// Go to Explore and choose Loki data source
e2e . pages . Explore . visit ( ) ;
e2e . components . DataSourcePicker . container ( ) . should ( 'be.visible' ) . click ( ) ;
e2e ( ) . contains ( dataSourceName ) . scrollIntoView ( ) . should ( 'be.visible' ) . click ( ) ;
// Start in builder mode, click and choose query pattern
2022-09-26 07:03:13 -05:00
e2e . components . QueryBuilder . queryPatterns ( ) . click ( ) ;
e2e ( ) . contains ( 'Log query starters' ) . click ( ) ;
e2e ( ) . contains ( 'Use this query' ) . click ( ) ;
2022-06-29 04:04:27 -05:00
e2e ( ) . contains ( 'No pipeline errors' ) . should ( 'be.visible' ) ;
e2e ( ) . contains ( 'Logfmt' ) . should ( 'be.visible' ) ;
e2e ( ) . contains ( '{} | logfmt | __error__=``' ) . should ( 'be.visible' ) ;
// Add operation
e2e ( ) . contains ( 'Operations' ) . should ( 'be.visible' ) . click ( ) ;
e2e ( ) . contains ( 'Range functions' ) . should ( 'be.visible' ) . click ( ) ;
e2e ( ) . contains ( 'Rate' ) . should ( 'be.visible' ) . click ( ) ;
2023-08-03 09:27:23 -05:00
e2e ( ) . contains ( 'rate({} | logfmt | __error__=`` [$__auto]' ) . should ( 'be.visible' ) ;
2022-06-29 04:04:27 -05:00
// Check for expected error
2022-08-11 10:57:10 -05:00
e2e ( ) . contains ( MISSING_LABEL_FILTER_ERROR_MESSAGE ) . should ( 'be.visible' ) ;
2022-06-29 04:04:27 -05:00
// Add labels to remove error
2023-06-02 05:35:11 -05:00
e2e . components . QueryBuilder . labelSelect ( ) . should ( 'be.visible' ) . click ( ) ;
// wait until labels are loaded and set on the component before starting to type
e2e ( ) . wait ( '@labelsRequest' ) ;
e2e ( ) . wait ( 100 ) ;
e2e . components . QueryBuilder . labelSelect ( ) . type ( 'instance{enter}' ) ;
2022-06-29 04:04:27 -05:00
e2e . components . QueryBuilder . matchOperatorSelect ( ) . should ( 'be.visible' ) . click ( ) . type ( '=~{enter}' ) ;
2023-06-02 05:35:11 -05:00
e2e . components . QueryBuilder . valueSelect ( ) . should ( 'be.visible' ) . click ( ) ;
e2e ( ) . wait ( '@valuesRequest' ) ;
e2e ( ) . wait ( 100 ) ;
e2e . components . QueryBuilder . valueSelect ( ) . type ( 'instance1{enter}' ) . type ( 'instance2{enter}' ) ;
2022-08-11 10:57:10 -05:00
e2e ( ) . contains ( MISSING_LABEL_FILTER_ERROR_MESSAGE ) . should ( 'not.exist' ) ;
2022-06-29 04:04:27 -05:00
e2e ( ) . contains ( finalQuery ) . should ( 'be.visible' ) ;
2022-09-30 08:27:48 -05:00
// Change to code editor
e2e ( ) . contains ( 'label' , 'Code' ) . click ( ) ;
// We need to test this manually because the final query is split into separate DOM elements using e2e().contains(finalQuery).should('be.visible'); does not detect the query.
e2e ( ) . contains ( 'rate' ) . should ( 'be.visible' ) ;
e2e ( ) . contains ( 'instance1|instance2' ) . should ( 'be.visible' ) ;
e2e ( ) . contains ( 'logfmt' ) . should ( 'be.visible' ) ;
e2e ( ) . contains ( '__error__' ) . should ( 'be.visible' ) ;
2023-08-03 09:27:23 -05:00
e2e ( ) . contains ( '$__auto' ) . should ( 'be.visible' ) ;
2022-09-30 08:27:48 -05:00
// Checks the explain mode toggle
2022-06-29 04:04:27 -05:00
e2e ( ) . contains ( 'label' , 'Explain' ) . click ( ) ;
2022-09-30 08:27:48 -05:00
e2e ( ) . contains ( 'Fetch all log lines matching label filters.' ) . should ( 'be.visible' ) ;
2022-06-29 04:04:27 -05:00
} ) ;
} ) ;