mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			113 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			113 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
| import { test, expect } from '@grafana/plugin-e2e';
 | |
| 
 | |
| const MISSING_LABEL_FILTER_ERROR_MESSAGE = 'Select at least 1 label filter (label and value)';
 | |
| const dataSourceName = 'LokiBuilder';
 | |
| const finalQuery = 'rate({instance=~"instance1|instance2"} | logfmt | __error__=`` [$__auto]';
 | |
| 
 | |
| test.describe(
 | |
|   'Loki query builder',
 | |
|   {
 | |
|     tag: ['@various'],
 | |
|   },
 | |
|   () => {
 | |
|     test('should be able to use all modes', async ({ createDataSource, page, dashboardPage, selectors }) => {
 | |
|       await createDataSource({ type: 'loki', name: dataSourceName });
 | |
|       // Mock API responses
 | |
|       await page.route(/labels\?/, async (route) => {
 | |
|         await route.fulfill({
 | |
|           status: 200,
 | |
|           contentType: 'application/json',
 | |
|           body: JSON.stringify({ status: 'success', data: ['instance', 'job', 'source'] }),
 | |
|         });
 | |
|       });
 | |
| 
 | |
|       await page.route(/series?/, async (route) => {
 | |
|         await route.fulfill({
 | |
|           status: 200,
 | |
|           contentType: 'application/json',
 | |
|           body: JSON.stringify({ status: 'success', data: [{ instance: 'instance1' }] }),
 | |
|         });
 | |
|       });
 | |
| 
 | |
|       await page.route(/values/, async (route) => {
 | |
|         await route.fulfill({
 | |
|           status: 200,
 | |
|           contentType: 'application/json',
 | |
|           body: JSON.stringify({ status: 'success', data: ['instance1', 'instance2'] }),
 | |
|         });
 | |
|       });
 | |
| 
 | |
|       await page.route(/index\/stats/, async (route) => {
 | |
|         await route.fulfill({
 | |
|           status: 200,
 | |
|           contentType: 'application/json',
 | |
|           body: JSON.stringify({ streams: 2, chunks: 2660, bytes: 2721792, entries: 14408 }),
 | |
|         });
 | |
|       });
 | |
| 
 | |
|       // Go to Explore and choose Loki data source
 | |
|       await page.goto('/explore');
 | |
|       await dashboardPage.getByGrafanaSelector(selectors.components.DataSourcePicker.container).click();
 | |
|       await page.getByRole('button', { name: dataSourceName }).click();
 | |
| 
 | |
|       // Start in builder mode, click and choose query pattern
 | |
|       await page.getByTestId(selectors.components.QueryBuilder.queryPatterns).click();
 | |
|       await page.getByRole('button', { name: 'Log query starters' }).click();
 | |
|       await page.getByRole('button', { name: 'Use this query' }).first().click();
 | |
|       await expect(page.getByText('No pipeline errors')).toBeVisible();
 | |
|       await expect(page.getByText('{} | logfmt | __error__=``')).toBeVisible();
 | |
| 
 | |
|       // Add operation
 | |
|       await page.getByRole('button', { name: 'Operations', exact: true }).click();
 | |
|       await page.getByText('Range functions').click();
 | |
|       await page.getByText('Rate', { exact: true }).click();
 | |
|       await expect(page.getByText('rate({} | logfmt | __error__=`` [$__auto]')).toBeVisible();
 | |
| 
 | |
|       // Check for expected error
 | |
|       await expect(page.getByText(MISSING_LABEL_FILTER_ERROR_MESSAGE)).toBeVisible();
 | |
| 
 | |
|       // Add labels to remove error
 | |
|       await dashboardPage.getByGrafanaSelector(selectors.components.QueryBuilder.labelSelect).click();
 | |
|       await dashboardPage.getByGrafanaSelector(selectors.components.QueryBuilder.inputSelect).fill('instance');
 | |
|       await page.keyboard.press('Enter');
 | |
| 
 | |
|       const matchOperatorSelect = dashboardPage.getByGrafanaSelector(
 | |
|         selectors.components.QueryBuilder.matchOperatorSelect
 | |
|       );
 | |
|       await expect(matchOperatorSelect).toBeVisible();
 | |
|       await matchOperatorSelect.click({ force: true });
 | |
| 
 | |
|       const matchOperatorInput = matchOperatorSelect.locator('div').locator('input');
 | |
|       await matchOperatorInput.fill('=~');
 | |
|       await page.keyboard.press('Enter');
 | |
| 
 | |
|       const valueSelect = dashboardPage.getByGrafanaSelector(selectors.components.QueryBuilder.valueSelect);
 | |
|       await expect(valueSelect).toBeVisible();
 | |
|       await valueSelect.click();
 | |
| 
 | |
|       const valueInput = valueSelect.locator('div').locator('input');
 | |
|       await valueInput.fill('instance1');
 | |
|       await page.keyboard.press('Enter');
 | |
|       await valueInput.fill('instance2');
 | |
|       await page.keyboard.press('Enter');
 | |
| 
 | |
|       await expect(page.getByText(MISSING_LABEL_FILTER_ERROR_MESSAGE)).toBeHidden();
 | |
|       await expect(page.getByText(finalQuery)).toBeVisible();
 | |
| 
 | |
|       // Change to code editor
 | |
|       await page.getByRole('radio', { name: 'Code' }).click();
 | |
| 
 | |
|       // We need to test this manually because the final query is split into separate DOM elements
 | |
|       await expect(page.getByText('rate')).toBeVisible();
 | |
|       await expect(page.getByText('instance1|instance2')).toBeVisible();
 | |
|       await expect(page.getByText('logfmt')).toBeVisible();
 | |
|       await expect(page.getByText('__error__')).toBeVisible();
 | |
|       await expect(page.getByText('$__auto')).toBeVisible();
 | |
| 
 | |
|       // Checks the explain mode toggle
 | |
|       await page.getByText('Explain').click();
 | |
|       await expect(page.getByText('Fetch all log lines matching label filters.')).toBeVisible();
 | |
|     });
 | |
|   }
 | |
| );
 |