-
Notifications
You must be signed in to change notification settings - Fork 715
test: dashboard table transpose #4925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe pull request introduces updates to the GitHub Actions workflow for Playwright UI tests, including the addition of a new test file, Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
🧹 Outside diff range and nitpick comments (12)
.github/workflows/playwright.yml (2)
90-90: Fix formatting: Add space after comma in array.The array items should be separated by comma and space for better readability.
- ["sanity.spec.js", "alerts.spec.js", "schema.spec.js", "logspage.spec.js", "logsqueries.spec.js", "logsquickmode.spec.js", "multiselect-stream.spec.js", "pipeline.spec.js", "dashboardtype.spec.js", "dashboard.spec.js", "visualize.spec.js", "unflattened.spec.js","secondsPrecisionAdded.spec.js", "dashboardtanspose.spec.js"] + ["sanity.spec.js", "alerts.spec.js", "schema.spec.js", "logspage.spec.js", "logsqueries.spec.js", "logsquickmode.spec.js", "multiselect-stream.spec.js", "pipeline.spec.js", "dashboardtype.spec.js", "dashboard.spec.js", "visualize.spec.js", "unflattened.spec.js", "secondsPrecisionAdded.spec.js", "dashboardtanspose.spec.js"]🧰 Tools
🪛 yamllint
[warning] 90-90: too few spaces after comma
(commas)
Line range hint
1-150: Consider workflow optimizations for better efficiency.A few suggestions to improve the workflow:
- Consider using test sharding to run tests in parallel across multiple runners
- Add test retries for flaky tests
- Consider caching Playwright browsers to speed up the workflow
Here's how you can implement these improvements:
ui_integration_tests: name: playwright_ui_integration_tests needs: [build_binary] runs-on: labels: ubuntu-latest container: image: mcr.microsoft.com/playwright:v1.42.1-jammy options: --user root strategy: matrix: browser: [chrome] + # Shard tests across multiple runners + shardIndex: [1, 2, 3] + shardTotal: [3] testfilename: ["sanity.spec.js", "alerts.spec.js", "schema.spec.js", "logspage.spec.js", "logsqueries.spec.js", "logsquickmode.spec.js", "multiselect-stream.spec.js", "pipeline.spec.js", "dashboardtype.spec.js", "dashboard.spec.js", "visualize.spec.js", "unflattened.spec.js", "secondsPrecisionAdded.spec.js", "dashboardtanspose.spec.js"] + # Add retry for flaky tests + fail-fast: false + max-parallel: 3And in the test command:
- cd tests/ui-testing && npm ci && npx playwright test ./playwright-tests/${{ matrix.testfilename }} + cd tests/ui-testing && npm ci && npx playwright test ./playwright-tests/${{ matrix.testfilename }} --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --retries=2🧰 Tools
🪛 yamllint
[error] 89-89: trailing spaces
(trailing-spaces)
[warning] 90-90: too few spaces after comma
(commas)
[error] 91-91: trailing spaces
(trailing-spaces)
tests/ui-testing/playwright-tests/dashboardsettings.spec.js (4)
5-6: Consider using a more readable random name generator.The current random string might be hard to identify in test logs. Consider using a more descriptive format.
-const randomDashboardName = - "Dashboard_" + Math.random().toString(36).substr(2, 9); +const randomDashboardName = `Dashboard_Test_${new Date().getTime().toString().slice(-6)}`;
12-12: Remove commented code.Clean up unused commented code to improve readability.
81-85: Clean up commented code and improve regex documentation.Remove commented console.log and add documentation for the regex pattern.
function removeUTFCharacters(text) { - // console.log(text, "tex"); - // Remove UTF characters using regular expression + // Remove non-ASCII characters to ensure compatibility return text.replace(/[^\x00-\x7F]/g, " "); }🧰 Tools
🪛 Biome
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
98-104: Remove unused commented code block.Remove the entire commented code block to improve readability.
web/src/components/dashboards/settings/GeneralSettings.vue (1)
84-84: LGTM! Well-named test attribute for save action.The data-test attribute follows the naming convention and clearly identifies the save button for testing.
Consider adding data-test attributes to other interactive elements for comprehensive testing:
<q-toggle v-model="dashboardData.showDynamicFilters" label="Show Dynamic Filters" + data-test="dashboard-general-setting-dynamic-filters" ></q-toggle> <DateTimePickerDashboard v-show="store.state.printMode === false" ref="dateTimePicker" class="dashboard-icons q-my-sm" size="sm" :initialTimezone="initialTimezone" v-model="dateTimeValue" :auto-apply-dashboard="true" + data-test="dashboard-general-setting-datetime-picker" />tests/ui-testing/playwright-tests/dashboardtanspose.spec.js (1)
98-105: Remove unnecessary commented-out codeThe commented-out code from lines 98 to 105 is unnecessary and should be removed to improve code readability.
tests/ui-testing/playwright-tests/unitest.spec.js (4)
2-3: Improve variable naming consistencyConsider using consistent naming conventions for imported modules. Currently,
logData(camelCase) andlogsdata(all lowercase) differ in casing. For clarity and to follow best practices, you might want to standardize the variable names.
281-282: Avoid redundant commentsThe comment
//////////////////////////does not add value to the code and can be removed to improve readability.- //////////////////////////
732-842: Reconsider usingtest.skipwithout a reasonThere are several tests marked with
test.skipwithout an explanation. It's helpful to provide a reason for skipping a test, so future maintainers understand the context.For example:
test.skip("should create the specified URL using the DrillDown feature", async ({ page }) => { // Reason for skipping: The feature is under development. // Test implementation... });
731-1212: Remove commented-out codeThere is a significant amount of commented-out code towards the end of the file. Removing unused code can improve readability and maintainability.
Example:
- // await page.getByText('Defaultchevron_leftchevron_rightadd')).toBeVisible({ timeout: 30000 });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
- .github/workflows/playwright.yml (1 hunks)
- tests/ui-testing/playwright-tests/dashboardsettings.spec.js (1 hunks)
- tests/ui-testing/playwright-tests/dashboardtanspose.spec.js (1 hunks)
- tests/ui-testing/playwright-tests/unitest.spec.js (1 hunks)
- web/src/components/dashboards/settings/GeneralSettings.vue (4 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
tests/ui-testing/playwright-tests/dashboardsettings.spec.js (1)
Pattern
**/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
tests/ui-testing/playwright-tests/dashboardtanspose.spec.js (1)
Pattern
**/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
tests/ui-testing/playwright-tests/unitest.spec.js (1)
Pattern
**/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
🪛 yamllint
.github/workflows/playwright.yml
[warning] 90-90: too few spaces after comma
(commas)
🪛 Biome
tests/ui-testing/playwright-tests/dashboardsettings.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
tests/ui-testing/playwright-tests/dashboardtanspose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
🔇 Additional comments (6)
.github/workflows/playwright.yml (1)
90-90: Verify the new test file exists.Let's ensure the newly added test file is present in the repository.
✅ Verification successful
Test file
dashboardtanspose.spec.jsexists in the expected locationThe file is present at
tests/ui-testing/playwright-tests/dashboardtanspose.spec.jsas required.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the existence of the new test file # Test: Check if the file exists in the ui-testing directory fd "dashboardtanspose.spec.js" tests/ui-testing/playwright-tests/Length of output: 125
🧰 Tools
🪛 yamllint
[warning] 90-90: too few spaces after comma
(commas)
web/src/components/dashboards/settings/GeneralSettings.vue (3)
33-33: LGTM! Clear and well-structured test attribute.The data-test attribute follows a clear hierarchical naming convention that will help in UI testing.
46-46: LGTM! Consistent test attribute naming.The data-test attribute maintains consistency with the naming pattern used in other form elements.
73-73: LGTM! Well-named test attribute for cancel action.The data-test attribute follows the naming convention and clearly identifies the cancel button for testing.
tests/ui-testing/playwright-tests/unitest.spec.js (2)
571-640: Check for potential flakiness in chart type switchingIn the test for changing the chart type, there are multiple rapid interactions and short timeouts. Ensure that these interactions are stable and that the elements are available before each action to prevent flaky tests.
Ensure that you are waiting for necessary elements to be visible before interacting with them:
await expect(page.locator('[data-test="selected-chart-area-item"]')).toBeVisible(); await page.locator('[data-test="selected-chart-area-item"]').click();
84-107: Ensure environment variables are definedThe code relies on environment variables like
process.env["ZO_ROOT_USER_EMAIL"],process.env["ZO_ROOT_USER_PASSWORD"], andprocess.env.INGESTION_URL. To prevent runtime errors, ensure that these environment variables are properly defined before running the tests.You can check the environment variables with the following script:
| test.beforeEach(async ({ page }) => { | ||
| console.log("running before each"); | ||
| await login(page); | ||
| await page.waitForTimeout(1000); | ||
| await ingestion(page); | ||
| await page.waitForTimeout(2000); | ||
|
|
||
| // just to make sure org is set | ||
| const orgNavigation = page.goto( | ||
| `${logData.logsUrl}?org_identifier=${process.env["ORGNAME"]}` | ||
| ); | ||
|
|
||
| await orgNavigation; | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve beforeEach hook implementation.
The hook needs several improvements:
- Use constants for timeout values
- Add error handling
- Add comments explaining the timeouts
+const LOGIN_WAIT_TIMEOUT = 1000;
+const INGESTION_WAIT_TIMEOUT = 2000;
+
test.beforeEach(async ({ page }) => {
- console.log("running before each");
try {
await login(page);
- await page.waitForTimeout(1000);
+ await page.waitForTimeout(LOGIN_WAIT_TIMEOUT); // Wait for login to settle
await ingestion(page);
- await page.waitForTimeout(2000);
+ await page.waitForTimeout(INGESTION_WAIT_TIMEOUT); // Wait for ingestion to complete
// just to make sure org is set
const orgNavigation = page.goto(
`${logData.logsUrl}?org_identifier=${process.env["ORGNAME"]}`
);
await orgNavigation;
+ } catch (error) {
+ console.error('Test setup failed:', error);
+ throw error;
+ }
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test.beforeEach(async ({ page }) => { | |
| console.log("running before each"); | |
| await login(page); | |
| await page.waitForTimeout(1000); | |
| await ingestion(page); | |
| await page.waitForTimeout(2000); | |
| // just to make sure org is set | |
| const orgNavigation = page.goto( | |
| `${logData.logsUrl}?org_identifier=${process.env["ORGNAME"]}` | |
| ); | |
| await orgNavigation; | |
| }); | |
| const LOGIN_WAIT_TIMEOUT = 1000; | |
| const INGESTION_WAIT_TIMEOUT = 2000; | |
| test.beforeEach(async ({ page }) => { | |
| try { | |
| await login(page); | |
| await page.waitForTimeout(LOGIN_WAIT_TIMEOUT); // Wait for login to settle | |
| await ingestion(page); | |
| await page.waitForTimeout(INGESTION_WAIT_TIMEOUT); // Wait for ingestion to complete | |
| // just to make sure org is set | |
| const orgNavigation = page.goto( | |
| `${logData.logsUrl}?org_identifier=${process.env["ORGNAME"]}` | |
| ); | |
| await orgNavigation; | |
| } catch (error) { | |
| console.error('Test setup failed:', error); | |
| throw error; | |
| } | |
| }); |
| async function applyQueryButton(page) { | ||
| // click on the run query button | ||
| // Type the value of a variable into an input field | ||
| const search = page.waitForResponse(logData.applyQuery); | ||
| await page.waitForTimeout(3000); | ||
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ | ||
| force: true, | ||
| }); | ||
| // get the data from the search variable | ||
| await expect.poll(async () => (await search).status()).toBe(200); | ||
| // await search.hits.FIXME_should("be.an", "array"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Address FIXME comment and improve click handling.
The function needs several improvements:
- Remove or implement the FIXME comment
- Explain why force: true is needed
- Consider using a constant for the timeout value
+const QUERY_WAIT_TIMEOUT = 3000;
+
async function applyQueryButton(page) {
- // click on the run query button
- // Type the value of a variable into an input field
const search = page.waitForResponse(logData.applyQuery);
- await page.waitForTimeout(3000);
+ await page.waitForTimeout(QUERY_WAIT_TIMEOUT);
+ // Force click needed due to possible overlay elements
await page.locator("[data-test='logs-search-bar-refresh-btn']").click({
force: true,
});
- // get the data from the search variable
await expect.poll(async () => (await search).status()).toBe(200);
- // await search.hits.FIXME_should("be.an", "array");
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async function applyQueryButton(page) { | |
| // click on the run query button | |
| // Type the value of a variable into an input field | |
| const search = page.waitForResponse(logData.applyQuery); | |
| await page.waitForTimeout(3000); | |
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ | |
| force: true, | |
| }); | |
| // get the data from the search variable | |
| await expect.poll(async () => (await search).status()).toBe(200); | |
| // await search.hits.FIXME_should("be.an", "array"); | |
| } | |
| const QUERY_WAIT_TIMEOUT = 3000; | |
| async function applyQueryButton(page) { | |
| const search = page.waitForResponse(logData.applyQuery); | |
| await page.waitForTimeout(QUERY_WAIT_TIMEOUT); | |
| // Force click needed due to possible overlay elements | |
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ | |
| force: true, | |
| }); | |
| await expect.poll(async () => (await search).status()).toBe(200); | |
| } |
| async function ingestion(page) { | ||
| const orgId = process.env["ORGNAME"]; | ||
| const streamName = "e2e_automate"; | ||
| const basicAuthCredentials = Buffer.from( | ||
| `${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}` | ||
| ).toString('base64'); | ||
|
|
||
| const headers = { | ||
| "Authorization": `Basic ${basicAuthCredentials}`, | ||
| "Content-Type": "application/json", | ||
| }; | ||
| const fetchResponse = await fetch( | ||
| `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`, | ||
| { | ||
| method: "POST", | ||
| headers: headers, | ||
| body: JSON.stringify(logsdata), | ||
| } | ||
| ); | ||
| const response = await fetchResponse.json(); | ||
| console.log(response); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling and make stream name configurable.
The ingestion function needs improvements:
- Add error handling for the fetch request
- Make the stream name configurable instead of hardcoding
-async function ingestion(page) {
+async function ingestion(page, streamName = 'e2e_automate') {
const orgId = process.env["ORGNAME"];
- const streamName = "e2e_automate";
const basicAuthCredentials = Buffer.from(
`${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}`
).toString('base64');
const headers = {
"Authorization": `Basic ${basicAuthCredentials}`,
"Content-Type": "application/json",
};
- const fetchResponse = await fetch(
- `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`,
- {
- method: "POST",
- headers: headers,
- body: JSON.stringify(logsdata),
- }
- );
- const response = await fetchResponse.json();
- console.log(response);
+ try {
+ const fetchResponse = await fetch(
+ `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`,
+ {
+ method: "POST",
+ headers: headers,
+ body: JSON.stringify(logsdata),
+ }
+ );
+ if (!fetchResponse.ok) {
+ throw new Error(`HTTP error! status: ${fetchResponse.status}`);
+ }
+ const response = await fetchResponse.json();
+ return response;
+ } catch (error) {
+ console.error('Ingestion failed:', error);
+ throw error;
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async function ingestion(page) { | |
| const orgId = process.env["ORGNAME"]; | |
| const streamName = "e2e_automate"; | |
| const basicAuthCredentials = Buffer.from( | |
| `${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}` | |
| ).toString('base64'); | |
| const headers = { | |
| "Authorization": `Basic ${basicAuthCredentials}`, | |
| "Content-Type": "application/json", | |
| }; | |
| const fetchResponse = await fetch( | |
| `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`, | |
| { | |
| method: "POST", | |
| headers: headers, | |
| body: JSON.stringify(logsdata), | |
| } | |
| ); | |
| const response = await fetchResponse.json(); | |
| console.log(response); | |
| } | |
| async function ingestion(page, streamName = 'e2e_automate') { | |
| const orgId = process.env["ORGNAME"]; | |
| const basicAuthCredentials = Buffer.from( | |
| `${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}` | |
| ).toString('base64'); | |
| const headers = { | |
| "Authorization": `Basic ${basicAuthCredentials}`, | |
| "Content-Type": "application/json", | |
| }; | |
| try { | |
| const fetchResponse = await fetch( | |
| `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`, | |
| { | |
| method: "POST", | |
| headers: headers, | |
| body: JSON.stringify(logsdata), | |
| } | |
| ); | |
| if (!fetchResponse.ok) { | |
| throw new Error(`HTTP error! status: ${fetchResponse.status}`); | |
| } | |
| const response = await fetchResponse.json(); | |
| return response; | |
| } catch (error) { | |
| console.error('Ingestion failed:', error); | |
| throw error; | |
| } | |
| } |
| test('should successfully update the general settings using the default duration time', async ({ page }) => { | ||
|
|
||
|
|
||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
|
|
||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
| await page.locator('[data-test="dashboard-setting-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-general-setting-name"]').click(); | ||
|
|
||
| await page.locator('[data-test="dashboard-general-setting-name"]').click(); | ||
| // await page.locator('[data-test="dashboard-general-setting-name"]').press('Control+a'); | ||
| // await page.locator('[data-test="dashboard-general-setting-name"]').fill('test123'); | ||
| await page.locator('[data-test="dashboard-general-setting-name"]').fill(''); | ||
| await page.locator('[data-test="dashboard-general-setting-name"]').fill('test123'); | ||
|
|
||
| await page.locator('[data-test="dashboard-general-setting-description"]').click(); | ||
| await page.locator('[data-test="dashboard-general-setting-description"]').fill('mdkjnsd'); | ||
|
|
||
| await page.waitForTimeout(1000); | ||
| await page.locator('#q-portal--dialog--3 [data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-30-m-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-general-setting-save-btn"]').click(); | ||
| await expect(page.getByText('Dashboard updated')).toBeVisible(); | ||
| await page.getByRole('button', { name: 'Past 30 Minutes' }).click(); | ||
| await page.locator('[data-test="date-time-relative-15-m-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-general-setting-save-btn"]').click(); | ||
|
|
||
|
|
||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve test case implementation and add assertions.
The test case needs several improvements:
- Remove commented code
- Use constants for timeout values
- Add assertions for updated values
- Reduce duplicate operations
+const SETTINGS_UPDATE_TIMEOUT = 1000;
+
test('should successfully update the general settings using the default duration time', async ({ page }) => {
await page.locator('[data-test="menu-link-\\/dashboards-item"]').click();
await waitForDashboardPage(page);
await page.locator('[data-test="dashboard-add"]').click();
await page.locator('[data-test="add-dashboard-name"]').click();
await page
.locator('[data-test="add-dashboard-name"]')
.fill(randomDashboardName);
await page.locator('[data-test="dashboard-add-submit"]').click();
await page.locator('[data-test="dashboard-setting-btn"]').click();
- await page.locator('[data-test="dashboard-general-setting-name"]').click();
- await page.locator('[data-test="dashboard-general-setting-name"]').click();
- // await page.locator('[data-test="dashboard-general-setting-name"]').press('Control+a');
- // await page.locator('[data-test="dashboard-general-setting-name"]').fill('test123');
+ const newName = 'test123';
+ const newDescription = 'mdkjnsd';
+
await page.locator('[data-test="dashboard-general-setting-name"]').fill('');
- await page.locator('[data-test="dashboard-general-setting-name"]').fill('test123');
+ await page.locator('[data-test="dashboard-general-setting-name"]').fill(newName);
await page.locator('[data-test="dashboard-general-setting-description"]').click();
- await page.locator('[data-test="dashboard-general-setting-description"]').fill('mdkjnsd');
+ await page.locator('[data-test="dashboard-general-setting-description"]').fill(newDescription);
- await page.waitForTimeout(1000);
+ await page.waitForTimeout(SETTINGS_UPDATE_TIMEOUT);
await page.locator('#q-portal--dialog--3 [data-test="date-time-btn"]').click();
await page.locator('[data-test="date-time-relative-30-m-btn"]').click();
await page.locator('[data-test="dashboard-general-setting-save-btn"]').click();
await expect(page.getByText('Dashboard updated')).toBeVisible();
+
+ // Add assertions for updated values
+ await expect(page.locator('[data-test="dashboard-general-setting-name"]')).toHaveValue(newName);
+ await expect(page.locator('[data-test="dashboard-general-setting-description"]')).toHaveValue(newDescription);
+
await page.getByRole('button', { name: 'Past 30 Minutes' }).click();
await page.locator('[data-test="date-time-relative-15-m-btn"]').click();
await page.locator('[data-test="dashboard-general-setting-save-btn"]').click();
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test('should successfully update the general settings using the default duration time', async ({ page }) => { | |
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | |
| await waitForDashboardPage(page); | |
| await page.locator('[data-test="dashboard-add"]').click(); | |
| await page.locator('[data-test="add-dashboard-name"]').click(); | |
| await page | |
| .locator('[data-test="add-dashboard-name"]') | |
| .fill(randomDashboardName); | |
| await page.locator('[data-test="dashboard-add-submit"]').click(); | |
| await page.locator('[data-test="dashboard-setting-btn"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-name"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-name"]').click(); | |
| // await page.locator('[data-test="dashboard-general-setting-name"]').press('Control+a'); | |
| // await page.locator('[data-test="dashboard-general-setting-name"]').fill('test123'); | |
| await page.locator('[data-test="dashboard-general-setting-name"]').fill(''); | |
| await page.locator('[data-test="dashboard-general-setting-name"]').fill('test123'); | |
| await page.locator('[data-test="dashboard-general-setting-description"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-description"]').fill('mdkjnsd'); | |
| await page.waitForTimeout(1000); | |
| await page.locator('#q-portal--dialog--3 [data-test="date-time-btn"]').click(); | |
| await page.locator('[data-test="date-time-relative-30-m-btn"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-save-btn"]').click(); | |
| await expect(page.getByText('Dashboard updated')).toBeVisible(); | |
| await page.getByRole('button', { name: 'Past 30 Minutes' }).click(); | |
| await page.locator('[data-test="date-time-relative-15-m-btn"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-save-btn"]').click(); | |
| }); | |
| const SETTINGS_UPDATE_TIMEOUT = 1000; | |
| test('should successfully update the general settings using the default duration time', async ({ page }) => { | |
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | |
| await waitForDashboardPage(page); | |
| await page.locator('[data-test="dashboard-add"]').click(); | |
| await page.locator('[data-test="add-dashboard-name"]').click(); | |
| await page | |
| .locator('[data-test="add-dashboard-name"]') | |
| .fill(randomDashboardName); | |
| await page.locator('[data-test="dashboard-add-submit"]').click(); | |
| await page.locator('[data-test="dashboard-setting-btn"]').click(); | |
| const newName = 'test123'; | |
| const newDescription = 'mdkjnsd'; | |
| await page.locator('[data-test="dashboard-general-setting-name"]').fill(''); | |
| await page.locator('[data-test="dashboard-general-setting-name"]').fill(newName); | |
| await page.locator('[data-test="dashboard-general-setting-description"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-description"]').fill(newDescription); | |
| await page.waitForTimeout(SETTINGS_UPDATE_TIMEOUT); | |
| await page.locator('#q-portal--dialog--3 [data-test="date-time-btn"]').click(); | |
| await page.locator('[data-test="date-time-relative-30-m-btn"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-save-btn"]').click(); | |
| await expect(page.getByText('Dashboard updated')).toBeVisible(); | |
| // Add assertions for updated values | |
| await expect(page.locator('[data-test="dashboard-general-setting-name"]')).toHaveValue(newName); | |
| await expect(page.locator('[data-test="dashboard-general-setting-description"]')).toHaveValue(newDescription); | |
| await page.getByRole('button', { name: 'Past 30 Minutes' }).click(); | |
| await page.locator('[data-test="date-time-relative-15-m-btn"]').click(); | |
| await page.locator('[data-test="dashboard-general-setting-save-btn"]').click(); | |
| }); |
| // Helper function to validate data before and after the transpose action | ||
| async function validateDynamicDataBeforeAndAfterAction(page) { | ||
| // Step 1: Capture the first dynamic date and value before the action | ||
| // const initialDateElement = await page | ||
| // .getByRole("cell", { name: /.*-.*-.* .*/ }) | ||
| // .first(); | ||
| const initialValueElement = await page | ||
| .getByRole("cell", { name: /\d+\.\d+/ }) | ||
| .first(); | ||
|
|
||
| // const initialDate = await initialDateElement.textContent(); | ||
| const initialValue = await initialValueElement.textContent(); | ||
|
|
||
| // Perform transpose and apply action | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
|
|
||
| // Step 2: Capture the first dynamic date and value after the action | ||
| // const finalDateElement = await page | ||
| // .getByRole("cell", { name: /.*-.*-.* .*/ }) | ||
| // .first(); | ||
| const finalValueElement = await page | ||
| .getByRole("cell", { name: /\d+\.\d+/ }) | ||
| .first(); | ||
|
|
||
| // const finalDate = await finalDateElement.textContent(); | ||
| const finalValue = await finalValueElement.textContent(); | ||
|
|
||
| // Step 3: Assert that the data is the same before and after the action | ||
| // expect(finalDate.trim()).toBe(initialDate.trim()); | ||
| expect(finalValue.trim()).toBe(initialValue.trim()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Define helper function outside the test scope
The validateDynamicDataBeforeAndAfterAction function is defined within a test case. Move it outside to make it reusable across multiple tests.
| test.beforeEach(async ({ page }) => { | ||
| await login(page); | ||
|
|
||
| const orgNavigation = page.goto( | ||
| `${logData.logsUrl}?org_identifier=${process.env["ORGNAME"]}` | ||
| ); | ||
|
|
||
| const orgId = process.env["ORGNAME"]; | ||
| const streamName = "e2e_automate"; | ||
| const basicAuthCredentials = Buffer.from( | ||
| `${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}` | ||
| ).toString("base64"); | ||
|
|
||
| const headers = { | ||
| Authorization: `Basic ${basicAuthCredentials}`, | ||
| "Content-Type": "application/json", | ||
| }; | ||
|
|
||
| const fetchResponse = await fetch( | ||
| `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`, | ||
| { | ||
| method: "POST", | ||
| headers: headers, | ||
| body: JSON.stringify(logsdata), | ||
| } | ||
| ); | ||
| const response = await fetchResponse.json(); | ||
|
|
||
| await orgNavigation; | ||
| console.log(response); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Streamline the beforeEach setup
The beforeEach block performs several asynchronous operations, including navigation and API calls. To improve test performance and reliability, consider the following:
- Ensure that all asynchronous operations are awaited properly.
- Check if some of the setup steps can be moved to a
beforeAllblock if they are only needed once per test suite. - Confirm that the
orgNavigationpromise is awaited at the correct place to prevent race conditions.
| const randomDashboardName = `Dashboard-${Math.floor( | ||
| Math.random() * 10000 | ||
| )}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid code duplication when generating random dashboard names
The pattern for generating random dashboard names is repeated multiple times. Consider creating a utility function to generate unique dashboard names to adhere to the DRY (Don't Repeat Yourself) principle.
Example:
function generateRandomDashboardName() {
return `Dashboard-${Math.floor(Math.random() * 10000)}`;
}
// Usage:
const randomDashboardName = generateRandomDashboardName();| test("should update t`he chart with the results of a custom SQL query", async ({ | ||
| page, | ||
| }) => { | ||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| await page | ||
| .locator('[data-test="dashboard-if-no-panel-add-panel-btn"]') | ||
| .click(); | ||
| await page | ||
| .locator('[data-test="dashboard-x-item-_timestamp-remove"]') | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-customSql"]').click(); | ||
|
|
||
| // Focus on the first line of the editor | ||
| await page.locator(".view-line").first().click(); | ||
| await page | ||
| .locator('[data-test="dashboard-panel-query-editor"]') | ||
| .getByLabel("Editor content;Press Alt+F1") | ||
| .fill( | ||
| 'SELECT histogram(_timestamp) as "x_axis_1", count(_timestamp) as "y_axis_1", kubernetes_container_name as "breakdown_1" FROM "e2e_automate" GROUP BY x_axis_1, breakdown_1' | ||
| ); | ||
|
|
||
| // Fill the custom SQL query | ||
| await page.keyboard.type( | ||
| 'SELECT histogram(_timestamp) as "x_axis_1", count(_timestamp) as "y_axis_1", kubernetes_container_name as "breakdown_1" FROM "e2e_automate" GROUP BY x_axis_1, breakdown_1' | ||
| ); | ||
| await page.waitForTimeout(400); | ||
|
|
||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-x_axis_1"] [data-test="dashboard-add-x-data"]' | ||
| ) | ||
| .click(); | ||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-y_axis_1"] [data-test="dashboard-add-y-data"]' | ||
| ) | ||
| .click(); | ||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-breakdown_1"] [data-test="dashboard-add-b-data"]' | ||
| ) | ||
| .click(); | ||
|
|
||
| await page.waitForTimeout(200); | ||
|
|
||
| await page.locator('[data-test="dashboard-apply"]'); //.toBeVisible(); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-30-m-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-3-h-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.waitForTimeout(400); | ||
| await expect( | ||
| page.locator('[data-test="dashboard-panel-name"]') | ||
| ).toBeVisible(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-panel-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-panel-save"]').click(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure randomDashboardName is defined within the test scope
In the test starting at line 501, randomDashboardName is used without being defined in the scope of the test. This may lead to a ReferenceError.
Define randomDashboardName at the beginning of the test:
test("should update the chart with the results of a custom SQL query", async ({ page }) => {
const randomDashboardName = generateRandomDashboardName();
// Rest of the test code...
});| await orgNavigation; | ||
| console.log(response); | ||
| }); | ||
| test("111111Should not show an error when edit the AND and OR condition dashboard ", async ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean up test name formatting
The test name appears to have leading numbers "111111Should not show an error when edit the AND and OR condition dashboard", which might be unintentional. Removing these numbers can improve readability.
Update the test name:
- test("111111Should not show an error when edit the AND and OR condition dashboard ", async ({
+ test("Should not show an error when editing the AND and OR condition dashboard", async ({📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test("111111Should not show an error when edit the AND and OR condition dashboard ", async ({ | |
| test("Should not show an error when editing the AND and OR condition dashboard", async ({ |
| (response) => | ||
| /\/api\/.+\/dashboards/.test(response.url()) && response.status() === 200 | ||
| ); | ||
| await page.waitForURL(process.env["ZO_BASE_URL"] + "/web/dashboards**"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use regular expressions for URL matching in waitForURL
The waitForURL method may not interpret the glob pattern "**" as intended. Instead of using "**" at the end of the URL, consider using a regular expression for more precise URL matching.
You can modify the code as follows:
- await page.waitForURL(process.env["ZO_BASE_URL"] + "/web/dashboards**");
+ await page.waitForURL(new RegExp(`^${process.env["ZO_BASE_URL"]}/web/dashboards.*$`));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await page.waitForURL(process.env["ZO_BASE_URL"] + "/web/dashboards**"); | |
| await page.waitForURL(new RegExp(`^${process.env["ZO_BASE_URL"]}/web/dashboards.*$`)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (4)
.github/workflows/playwright.yml (1)
90-90: Fix spacing after comma in test files array.For consistency with YAML formatting standards, add a space after each comma in the array.
- ["sanity.spec.js", "alerts.spec.js", "schema.spec.js", "logspage.spec.js", "logsqueries.spec.js", "logsquickmode.spec.js", "multiselect-stream.spec.js", "pipeline.spec.js", "dashboardtype.spec.js", "dashboard.spec.js", "visualize.spec.js", "unflattened.spec.js","secondsPrecisionAdded.spec.js", "dashboardtranspose.spec.js"] + ["sanity.spec.js", "alerts.spec.js", "schema.spec.js", "logspage.spec.js", "logsqueries.spec.js", "logsquickmode.spec.js", "multiselect-stream.spec.js", "pipeline.spec.js", "dashboardtype.spec.js", "dashboard.spec.js", "visualize.spec.js", "unflattened.spec.js", "secondsPrecisionAdded.spec.js", "dashboardtranspose.spec.js"]🧰 Tools
🪛 yamllint
[warning] 90-90: too few spaces after comma
(commas)
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (3)
98-104: Remove unnecessary commented-out codeThe commented-out code appears to be leftover and is not serving any purpose. Removing it will enhance code readability.
Apply this diff to clean up the code:
-// tebefore(async function () { -// // logData("log"); -// // const data = page; -// // logData = data; - -// console.log("--logData--", logData); -// });
81-85: Remove unused functionremoveUTFCharactersThe
removeUTFCharactersfunction is defined but not used anywhere in the code. Consider removing it to simplify the codebase.Apply this diff to remove the unused function:
-function removeUTFCharacters(text) { - // console.log(text, "tex"); - // Remove UTF characters using regular expression - return text.replace(/[^\x00-\x7F]/g, " "); -}🧰 Tools
🪛 Biome
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
86-97: Remove unused functionapplyQueryButtonThe
applyQueryButtonfunction is not invoked in the code. Removing unused code helps maintain clarity.Apply this diff to remove the function:
-async function applyQueryButton(page) { - // click on the run query button - // Type the value of a variable into an input field - const search = page.waitForResponse(logData.applyQuery); - await page.waitForTimeout(3000); - await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ - force: true, - }); - // get the data from the search variable - await expect.poll(async () => (await search).status()).toBe(200); - // await search.hits.FIXME_should("be.an", "array"); -}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- .github/workflows/playwright.yml (1 hunks)
- tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (1)
Pattern
**/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
🪛 yamllint
.github/workflows/playwright.yml
[warning] 90-90: too few spaces after comma
(commas)
🪛 Biome
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
🔇 Additional comments (2)
.github/workflows/playwright.yml (1)
90-90: LGTM! Verify test file existence.The addition of
dashboardtranspose.spec.jsto the test matrix aligns with the PR objectives.Let's verify the test file exists:
✅ Verification successful
Test file verification successful
The
dashboardtranspose.spec.jsfile exists at the expected location intests/ui-testing/playwright-tests/, confirming the test matrix update is valid.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the new test file exists # Expected: File should exist in the playwright-tests directory fd "dashboardtranspose.spec.js" tests/ui-testing/playwright-tests/Length of output: 127
🧰 Tools
🪛 yamllint
[warning] 90-90: too few spaces after comma
(commas)
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (1)
113-115: EnsurelogData.logsUrlis defined and correctThe variable
logData.logsUrlis used to navigate, but it's essential to verify that this value is defined correctly in the imported JSON. An undefined or incorrect URL could cause navigation errors.
| await page.waitForTimeout(3000); | ||
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace arbitrary timeouts with explicit waits
Using await page.waitForTimeout(...) can lead to flaky tests. Instead, wait for specific elements or responses to ensure tests are stable and efficient.
Example change:
-await page.waitForTimeout(2000);
+await page.waitForSelector('[data-test="desired-element"]', { state: 'visible' });Also applies to: 110-110, 165-165, 210-211, 220-221, 349-350, 378-379, 433-434, 449-450, 461-462
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
|
|
||
| // Create a new dashboard | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| // Add panel to the dashboard | ||
| await page | ||
| .locator('[data-test="dashboard-if-no-panel-add-panel-btn"]') | ||
| .click(); | ||
| await page | ||
| .locator("label") | ||
| .filter({ hasText: "Streamarrow_drop_down" }) | ||
| .locator("i") | ||
| .click(); | ||
| await page.getByRole("option", { name: "e2e_automate" }).click(); | ||
|
|
||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_container_name"] [data-test="dashboard-add-y-data"]' | ||
| ) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').fill("bhj"); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-6-w-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="selected-chart-table-item"] img').click(); | ||
| await page.getByRole("cell", { name: "Kubernetes Container Name" }).click(); | ||
| await page.locator('[data-test="dashboard-sidebar"]').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.waitForTimeout(1000); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Refactor repeated code into helper functions
The code for navigating, creating dashboards, and adding panels is repeated across multiple tests. Refactoring these into helper functions will improve maintainability and reduce duplication.
Consider creating helper functions like createDashboard(page, dashboardName) and addPanelToDashboard(page).
Also applies to: 170-221, 266-318, 323-397, 402-465
| } | ||
| }); | ||
|
|
||
| test("verify if desible the Tanspose button chart should be Default format ", async ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct typos in the test description
The test description contains typographical errors: "desible" should be "disable", and "Tanspose" should be "Transpose".
Apply this diff to fix the typos:
-test("verify if desible the Tanspose button chart should be Default format ", async ({
+test("verify if disabling the Transpose button chart should be in default format ", async ({📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test("verify if desible the Tanspose button chart should be Default format ", async ({ | |
| test("verify if disabling the Transpose button chart should be in default format ", async ({ |
| function removeUTFCharacters(text) { | ||
| // console.log(text, "tex"); | ||
| // Remove UTF characters using regular expression | ||
| return text.replace(/[^\x00-\x7F]/g, " "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve the regular expression issue in removeUTFCharacters function
The regular expression /[^\x00-\x7F]/g may cause unexpected behavior due to the inclusion of control characters like \x00. Consider updating the regex to exclude control characters explicitly.
Apply this diff to fix the issue:
-return text.replace(/[^\x00-\x7F]/g, " ");
+return text.replace(/[^\x20-\x7E]/g, " ");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return text.replace(/[^\x00-\x7F]/g, " "); | |
| return text.replace(/[^\x20-\x7E]/g, " "); |
🧰 Tools
🪛 Biome
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
dcf0e93 to
80a4996
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (4)
.github/workflows/playwright.yml (1)
90-90: Fix YAML formatting for better readability.
The test files array could benefit from proper spacing after commas for improved readability.
Apply this formatting:
- ["sanity.spec.js","alerts.spec.js","schema.spec.js","logspage.spec.js","logsqueries.spec.js","logsquickmode.spec.js","multiselect-stream.spec.js","pipeline.spec.js","dashboardtype.spec.js","dashboard.spec.js","visualize.spec.js","unflattened.spec.js","secondsPrecisionAdded.spec.js","dashboardtranspose.spec.js"]
+ ["sanity.spec.js", "alerts.spec.js", "schema.spec.js", "logspage.spec.js", "logsqueries.spec.js", "logsquickmode.spec.js", "multiselect-stream.spec.js", "pipeline.spec.js", "dashboardtype.spec.js", "dashboard.spec.js", "visualize.spec.js", "unflattened.spec.js", "secondsPrecisionAdded.spec.js", "dashboardtranspose.spec.js"]🧰 Tools
🪛 yamllint
[warning] 90-90: too few spaces after comma
(commas)
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (3)
81-85: Unused function removeUTFCharacters
The function removeUTFCharacters is defined but not used. If it's not needed, consider removing it to keep the code clean.
🧰 Tools
🪛 Biome
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
86-97: Unused function applyQueryButton
The function applyQueryButton is defined but not used in the code. If it's unnecessary, consider removing it to improve code maintainability.
98-104: Remove commented-out code
There is commented-out code that appears to be obsolete. Removing it can improve code readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
- .github/workflows/playwright.yml (1 hunks)
- tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (1 hunks)
- web/src/components/dashboards/settings/GeneralSettings.vue (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/src/components/dashboards/settings/GeneralSettings.vue
🧰 Additional context used
📓 Path-based instructions (1)
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js (1)
Pattern **/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestions
Make sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
🪛 yamllint
.github/workflows/playwright.yml
[warning] 90-90: too few spaces after comma
(commas)
🪛 Biome
tests/ui-testing/playwright-tests/dashboardtranspose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
🔇 Additional comments (1)
.github/workflows/playwright.yml (1)
90-90: LGTM! Test file addition looks good.
The new test file "dashboardtranspose.spec.js" has been properly integrated into the matrix of UI tests, maintaining consistency with the existing test suite structure.
🧰 Tools
🪛 yamllint
[warning] 90-90: too few spaces after comma
(commas)
| const randomDashboardName = | ||
| "Dashboard_" + Math.random().toString(36).substr(2, 9); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential conflict with randomDashboardName in parallel tests
Since tests are configured to run in parallel, using a single randomDashboardName across all tests could lead to naming conflicts. Consider generating a unique dashboard name within each test to avoid potential collisions.
| async function validateTableDataBeforeAndAfterTranspose(page) { | ||
| // Step 1: Capture headers and initial data from the table | ||
| const headers = await page.$$eval('[data-test="dashboard-panel-table"] thead tr th', (headerCells) => | ||
| headerCells.map(cell => cell.textContent.trim().replace(/^arrow_upward/, "")) // Remove "arrow_upward" prefix | ||
| ); | ||
|
|
||
| const initialData = await page.$$eval('[data-test="dashboard-panel-table"] tbody tr', (rows) => | ||
| rows | ||
| .map(row => Array.from(row.querySelectorAll("td"), cell => cell.textContent.trim())) | ||
| .filter(row => row.length > 0 && row.some(cell => cell !== "")) | ||
| ); | ||
|
|
||
| // Step 2: Perform transpose by simulating the transpose button click | ||
| await page.locator('[data-test="dashboard-config-table_transpose"] div').nth(2).click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.waitForTimeout(2000); | ||
|
|
||
| // Step 3: Capture transposed data from the table | ||
| const transposedData = await page.$$eval('[data-test="dashboard-panel-table"] tr', (rows) => | ||
| rows | ||
| .map(row => Array.from(row.querySelectorAll("td"), cell => cell.textContent.trim())) | ||
| .filter(row => row.length > 0 && row.some(cell => cell !== "")) | ||
| ); | ||
|
|
||
| console.log("transposedData", JSON.stringify(transposedData, null, 2)); | ||
|
|
||
| // Step 4: Flatten `initialData` by pairing each namespace header with its value, excluding the empty namespace | ||
| const flattenedInitialData = headers.slice(1).map((namespace, index) => [namespace, initialData[0][index + 1]]); | ||
| console.log("Flattened Initial Data (Unsorted)", JSON.stringify(flattenedInitialData, null, 2)); | ||
|
|
||
| // Step 5: Sort both `flattenedInitialData` and `transposedData` for comparison | ||
| const sortedFlattenedInitialData = flattenedInitialData.sort((a, b) => a[0].localeCompare(b[0])); | ||
| const sortedTransposedData = transposedData.sort((a, b) => a[0].localeCompare(b[0])); | ||
|
|
||
| console.log("Sorted Flattened Initial Data", JSON.stringify(sortedFlattenedInitialData, null, 2)); | ||
| console.log("Sorted Transposed Data", JSON.stringify(sortedTransposedData, null, 2)); | ||
|
|
||
| // Step 6: Directly compare sorted arrays | ||
| expect(sortedTransposedData).toEqual(sortedFlattenedInitialData); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract validateTableDataBeforeAndAfterTranspose for reuse
The helper function validateTableDataBeforeAndAfterTranspose is defined inside a test case. Consider moving it outside the test function so it can be reused by other tests.
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .nth(2) | ||
| .click(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid using index-based selectors like .nth(2)
Using index-based selectors can make tests brittle if the DOM structure changes. Consider using more specific selectors or data attributes to reliably target elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (3)
.github/workflows/playwright.yml (1)
88-104: LGTM! Consider documenting test file organization.
The test matrix is well-structured, and the addition of dashboard-transpose.spec.js aligns with the PR objectives.
Consider adding a comment block above the matrix explaining the test file organization and any dependencies between test files, which would help maintainers understand the optimal test execution order.
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
98-104: Remove commented-out code to improve readability
The block of commented-out code is unnecessary and can be removed for cleaner code.
Apply this diff to remove the commented code:
- // tebefore(async function () {
- // // logData("log");
- // // const data = page;
- // // logData = data;
-
- // console.log("--logData--", logData);
- // });86-97: Consider removing unused function applyQueryButton
The function applyQueryButton is defined but not used anywhere in the code.
If this function is not needed, consider removing it to keep the codebase clean.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- .github/workflows/playwright.yml (5 hunks)
- tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1)
Pattern **/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestions
Make sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
🪛 actionlint
.github/workflows/playwright.yml
35-35: label "ubicloud-standard-8" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
🪛 Biome
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
🔇 Additional comments (4)
.github/workflows/playwright.yml (2)
127-127: LGTM! Good choice using LTS version.
Using lts/* is a good practice as it ensures you're always using the latest LTS version of Node.js, providing a good balance between stability and features.
34-36: Verify the custom runner label configuration.
The ubicloud-standard-8 label is not a standard GitHub-hosted runner label. If this is a custom self-hosted runner, ensure that:
- The runner is properly configured in your GitHub organization/repository
- The runner has the necessary dependencies for Playwright tests
- The runner is consistently available for CI/CD
✅ Verification successful
Custom runner label is consistently used across workflows
The ubicloud-standard-8 label appears to be an intentionally configured custom runner that is consistently used across multiple workflow files. The evidence shows:
- It's used in core workflows: unit tests, Playwright tests, and build processes
- There's a variant
ubicloud-standard-8-armalso in use - The build fork PR workflow has a conditional that defaults to this runner for non-fork cases
This appears to be a deliberate infrastructure choice rather than a misconfiguration. The review comment concern can be dismissed.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the runner configuration in the repository
# Check for any other workflow files using the same runner
rg -l "ubicloud-standard-8" .github/workflows/
Length of output: 191
Script:
#!/bin/bash
# Check the context of how this runner is used in other workflows
for file in $(rg -l "ubicloud-standard-8" .github/workflows/); do
echo "=== $file ==="
rg -B2 -A2 "ubicloud-standard-8" "$file"
done
# Also check for any documentation about custom runners
fd README.md | xargs rg -i "ubicloud|runner"
Length of output: 1704
🧰 Tools
🪛 actionlint
35-35: label "ubicloud-standard-8" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
81-85: Verify the necessity of removeUTFCharacters function
The function removeUTFCharacters might be unnecessary if it's not used in the code.
Check if this function is required or can be removed.
🧰 Tools
🪛 Biome
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
113-115: Ensure logData.logsUrl is defined before use
The variable logData.logsUrl is used but may not be defined or may lead to unexpected results if logsUrl is missing from logData.
Run the following script to check if logsUrl exists in logData:
✅ Verification successful
logData.logsUrl is properly defined and safe to use
The verification shows that logData.logsUrl is properly defined in the log.json fixture file with the value "/web/logs". The property is being used correctly in the code and there's no risk of it being undefined or causing unexpected results.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify if 'logsUrl' is defined in 'logData'
# Test: Check for 'logsUrl' property in logData
ast-grep --pattern '$const logData = $_' ../cypress/fixtures/log.json | grep 'logsUrl'
Length of output: 162
Script:
#!/bin/bash
# Let's first find where logData is defined and used
rg "logData" -A 3 -B 3
# Also search for any log-related fixtures or configuration
fd "log" --type f
Length of output: 63602
Script:
#!/bin/bash
# Let's check the content of the log.json file that's being imported
cat tests/ui-testing/cypress/fixtures/log.json
Length of output: 2137
| async function login(page) { | ||
| await page.goto(process.env["ZO_BASE_URL"], { waitUntil: "networkidle" }); | ||
| // await page.getByText('Login as internal user').click(); | ||
| await page.waitForTimeout(1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid using fixed timeouts; use explicit waits instead
Using waitForTimeout can lead to flaky tests and increased execution time. Replace fixed delays with explicit waits for conditions or elements.
For example, replace:
await page.waitForTimeout(1000);With a wait for a specific element or condition:
await page.waitForSelector('selector', { state: 'visible' });Also applies to: 90-90, 108-108, 110-110, 165-165, 201-201, 209-209, 231-231, 368-368, 425-425, 431-431
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We plan to this at all places in another PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ktx-kirtan, understood. Since this change applies in multiple places, would you like me to open a GitHub issue to track it for a future PR?
| let errorMessage = ''; | ||
| page.on('console', (msg) => { | ||
| if (msg.type() === 'error') { | ||
| errorMessage = msg.text(); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct possible syntax errors in console error handling
Ensure that the error handling logic correctly captures and asserts console errors.
Apply this diff to fix the error handling:
-let errorMessage = '';
+let errorMessage = '';
page.on('console', (msg) => {
if (msg.type() === 'error') {
- errorMessage = msg.text();
+ errorMessage += msg.text() + '\n';
}
});
-// Assert no error occurred
-expect(errorMessage).toBe('');
+// Assert no error occurred
expect(errorMessage.trim()).toBe('');This ensures that all error messages are captured, and the assertion checks the trimmed error message.
Also applies to: 438-438
| const randomDashboardName = | ||
| "Dashboard_" + Math.random().toString(36).substr(2, 9); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace deprecated substr with slice for string manipulation
The substr method is deprecated. Consider using slice for better compatibility and future-proofing.
Apply this diff to replace substr with slice:
const randomDashboardName =
- "Dashboard_" + Math.random().toString(36).substr(2, 9);
+ "Dashboard_" + Math.random().toString(36).slice(2, 11);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const randomDashboardName = | |
| "Dashboard_" + Math.random().toString(36).substr(2, 9); | |
| const randomDashboardName = | |
| "Dashboard_" + Math.random().toString(36).slice(2, 11); |
| function removeUTFCharacters(text) { | ||
| // console.log(text, "tex"); | ||
| // Remove UTF characters using regular expression | ||
| return text.replace(/[^\x00-\x7F]/g, " "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the regular expression to exclude control characters
The regular expression includes control characters, which may lead to unexpected behavior. Modify the regex to correctly exclude non-ASCII characters without including control characters.
Apply this diff to fix the regular expression:
-return text.replace(/[^\x00-\x7F]/g, " ");
+return text.replace(/[^\x20-\x7E]/g, " ");This change updates the range to exclude control characters (hex codes 00-1F and 7F).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return text.replace(/[^\x00-\x7F]/g, " "); | |
| return text.replace(/[^\x20-\x7E]/g, " "); |
🧰 Tools
🪛 Biome
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ktx-kirtan, understood. Thank you for the clarification.
✏️ Learnings added
Learnt from: ktx-kirtan
PR: openobserve/openobserve#4925
File: tests/ui-testing/playwright-tests/dashboard-transpose.spec.js:84-84
Timestamp: 2024-11-04T10:09:24.814Z
Learning: In `tests/ui-testing/playwright-tests/dashboard-transpose.spec.js`, when removing UTF characters from text, the regular expression `/[^\x00-\x7F]/g` is required, even though it includes control characters.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
1ba40ed to
3047b15
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (2)
.github/workflows/playwright.yml (1)
127-127: Consider using a more specific Node.js version range.While using
lts/*ensures you get the latest LTS version, it might lead to unexpected behavior when a new LTS version is released. Consider using a more specific version range like18.x(matching the version used in the build step) or at least specify the major version likelts/hydrogenfor better predictability.- node-version: lts/* + node-version: 18.xtests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1)
252-252: Fix typos in test titleThe test title contains multiple spelling errors.
Apply this diff:
- test("verify if desible the Tanspose button chart should be Default format ", async ({ + test("verify if disable the Transpose button chart should be in default format", async ({
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
.github/workflows/playwright.yml(5 hunks)tests/ui-testing/playwright-tests/dashboard-transpose.spec.js(1 hunks)web/src/components/dashboards/settings/GeneralSettings.vue(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/src/components/dashboards/settings/GeneralSettings.vue
🧰 Additional context used
📓 Path-based instructions (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1)
Pattern **/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestions
Make sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
🪛 actionlint
.github/workflows/playwright.yml
35-35: label "ubicloud-standard-8" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
🪛 Biome
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
🔇 Additional comments (2)
.github/workflows/playwright.yml (2)
88-104: Verify the new test file integration.
The addition of dashboard-transpose.spec.js looks good. To ensure proper integration:
- Verify that the test file exists in the correct location
- Check if it follows the same patterns as other dashboard test files
#!/bin/bash
# Check if the test file exists and compare its structure with other dashboard tests
echo "Checking test file existence and structure..."
fd "dashboard.*spec.js" tests/ui-testing/playwright-tests/ -x echo "Found test file: {}"
# Compare structure with other dashboard tests
echo -e "\nComparing with other dashboard test patterns..."
rg -l "test\('.*dashboard.*'" tests/ui-testing/playwright-tests/34-36: Verify the custom runner label configuration.
The runner label ubicloud-standard-8 is not a standard GitHub-hosted runner label. If this is a custom self-hosted runner, please ensure:
- The runner is properly configured and available
- The runner label is documented in the repository's workflow documentation
- Consider adding an
actionlint.yamlconfiguration file to suppress the warning for custom labels
Alternatively, if you intended to use a GitHub-hosted runner, consider using standard labels like ubuntu-latest-8-cores for an 8-core runner.
✅ Verification successful
Let me gather more information about the runner configuration by checking other workflow files and documentation.
Based on the results, I can now generate the final response since we have sufficient evidence that the Ubicloud runner configuration is consistently used across multiple workflow files and is working successfully in recent workflow runs.
Custom runner label is valid and consistently used
The ubicloud-standard-8 runner label is correctly configured and actively used across multiple workflow files in the repository:
- Found in
.github/workflows/unit-tests.yml - Similar Ubicloud runner configurations in
build-fork-pr-image.ymlandbuild-pr-image.yml - Recent workflow runs show successful completions with this configuration
The initial concern about an unknown runner label can be dismissed as this appears to be an intentional, working setup for the project's CI infrastructure.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if there's any documentation about custom runners
rg -l "ubicloud-standard-8" .github/
Length of output: 767
Script:
#!/bin/bash
# Check for runner configuration in other workflow files and docs
echo "Checking workflow files for runner configuration patterns..."
rg -l "runs-on.*ubicloud" .github/
rg -l "labels:.*ubicloud" .github/
echo -e "\nChecking for runner documentation..."
fd "README|CONTRIBUTING|SETUP|DEVELOPMENT" -e md -x cat {} | rg -l "ubicloud"
echo -e "\nChecking recent workflow runs..."
gh run list --workflow=playwright.yml --limit 5 --json status,conclusion,headBranch
Length of output: 1100
🧰 Tools
🪛 actionlint
35-35: label "ubicloud-standard-8" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
| // Navigate to dashboards | ||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
|
|
||
| // Create a new dashboard | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| // Add panel to the dashboard | ||
| await page | ||
| .locator('[data-test="dashboard-if-no-panel-add-panel-btn"]') | ||
| .click(); | ||
| await page | ||
| .locator("label") | ||
| .filter({ hasText: "Streamarrow_drop_down" }) | ||
| .locator("i") | ||
| .click(); | ||
| await page.getByRole("option", { name: "e2e_automate" }).click(); | ||
|
|
||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_container_name"] [data-test="dashboard-add-y-data"]' | ||
| ) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').fill("bhj"); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-6-w-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="selected-chart-table-item"] img').click(); | ||
| await page.getByRole("cell", { name: "Kubernetes Container Name" }).click(); | ||
| await page.locator('[data-test="dashboard-sidebar"]').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.waitForTimeout(1000); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reduce code duplication by extracting common setup
The dashboard creation and panel addition steps are duplicated across all test cases. Extract these steps into a helper function to improve maintainability.
Create a helper function like this:
async function setupDashboardWithPanel(page, panelName) {
await page.locator('[data-test="menu-link-\\/dashboards-item"]').click();
await waitForDashboardPage(page);
// Create dashboard
await page.locator('[data-test="dashboard-add"]').click();
await page.locator('[data-test="add-dashboard-name"]').fill(randomDashboardName);
await page.locator('[data-test="dashboard-add-submit"]').click();
// Add panel
await page.locator('[data-test="dashboard-if-no-panel-add-panel-btn"]').click();
await page.locator("label").filter({ hasText: "Streamarrow_drop_down" }).locator("i").click();
await page.getByRole("option", { name: "e2e_automate" }).click();
if (panelName) {
await page.locator('[data-test="dashboard-panel-name"]').fill(panelName);
}
}Then use it in your tests:
test("should verify that the Transpose toggle button is working correctly", async ({ page }) => {
await setupDashboardWithPanel(page, "bhj");
// Continue with test-specific steps
});Also applies to: 168-250, 252-308, 310-387, 389-439
| const response = await fetchResponse.json(); | ||
| console.log(response); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove sensitive data logging
The response from the ingestion API might contain sensitive information. Remove the console.log or ensure sensitive data is redacted before logging.
Apply this diff:
- const response = await fetchResponse.json();
- console.log(response);
+ const response = await fetchResponse.json();
+ // Log only necessary non-sensitive information
+ console.log('Ingestion completed with status:', fetchResponse.status);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const response = await fetchResponse.json(); | |
| console.log(response); | |
| const response = await fetchResponse.json(); | |
| // Log only necessary non-sensitive information | |
| console.log('Ingestion completed with status:', fetchResponse.status); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't contain any sensitive data. We will remove this in next PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ktx-kirtan, understood. Since the response doesn't contain any sensitive data, logging it is acceptable. Looking forward to the updates in the next PR.
(^・ω・^)
✏️ Learnings added
Learnt from: ktx-kirtan
PR: openobserve/openobserve#4925
File: tests/ui-testing/playwright-tests/dashboard-transpose.spec.js:60-61
Timestamp: 2024-11-04T09:56:01.639Z
Learning: In `tests/ui-testing/playwright-tests/dashboard-transpose.spec.js`, the response from the ingestion API does not contain sensitive data, so logging it is acceptable.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (2)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
5-6: Consider using a more robust random name generator.The current implementation might occasionally generate names that are too short or not unique enough.
-const randomDashboardName = - "Dashboard_" + Math.random().toString(36).slice(2, 11); +const randomDashboardName = + "Dashboard_" + Math.random().toString(36).slice(2, 11) + "_" + Date.now();
64-77: Consider adding retry mechanism for dashboard loading.The
waitForDashboardPagefunction could be more resilient by adding a retry mechanism with timeout.async function waitForDashboardPage(page) { + const maxRetries = 3; + const retryInterval = 1000; + let retries = 0; + + while (retries < maxRetries) { const dashboardListApi = page.waitForResponse( (response) => /\/api\/.+\/dashboards/.test(response.url()) && response.status() === 200 ); await page.waitForURL(process.env["ZO_BASE_URL"] + "/web/dashboards**"); try { await page.waitForSelector(`text="Please wait while loading dashboards..."`, { state: "hidden", }); await dashboardListApi; break; } catch (error) { if (retries === maxRetries - 1) throw error; retries++; await page.waitForTimeout(retryInterval); } + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1)
Pattern **/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestions
Make sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
📓 Learnings (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
Learnt from: ktx-kirtan
PR: openobserve/openobserve#4925
File: tests/ui-testing/playwright-tests/dashboard-transpose.spec.js:84-84
Timestamp: 2024-11-04T10:09:25.987Z
Learning: In `tests/ui-testing/playwright-tests/dashboard-transpose.spec.js`, when removing UTF characters from text, the regular expression `/[^\x00-\x7F]/g` is required, even though it includes control characters.
Learnt from: ktx-kirtan
PR: openobserve/openobserve#4925
File: tests/ui-testing/playwright-tests/dashboard-transpose.spec.js:60-61
Timestamp: 2024-11-04T09:56:01.929Z
Learning: In `tests/ui-testing/playwright-tests/dashboard-transpose.spec.js`, the response from the ingestion API does not contain sensitive data, so logging it is acceptable.
🪛 Biome
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
| test("should verify that the transpose toggle button is working correctly", async ({ | ||
| page, | ||
| browser, | ||
| }) => { | ||
| // Navigate to dashboards | ||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
|
|
||
| // Create a new dashboard | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| // Add panel to the dashboard | ||
| await page | ||
| .locator('[data-test="dashboard-if-no-panel-add-panel-btn"]') | ||
| .click(); | ||
| await page | ||
| .locator("label") | ||
| .filter({ hasText: "Streamarrow_drop_down" }) | ||
| .locator("i") | ||
| .click(); | ||
| await page.getByRole("option", { name: "e2e_automate" }).click(); | ||
|
|
||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_container_name"] [data-test="dashboard-add-y-data"]' | ||
| ) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').fill("bhj"); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-6-w-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="selected-chart-table-item"] img').click(); | ||
| await page.getByRole("cell", { name: "Kubernetes Container Name" }).click(); | ||
| await page.locator('[data-test="dashboard-sidebar"]').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| }); | ||
|
|
||
| test("should display the correct data before and after transposing in the table chart", async ({ | ||
| page, | ||
| }) => { | ||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
|
|
||
| // Create a new dashboard | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| // Add panel to the dashboard | ||
| await page.locator('[data-test="dashboard-if-no-panel-add-panel-btn"]').click(); | ||
| await page.locator("label").filter({ hasText: "Streamarrow_drop_down" }).locator("i").click(); | ||
| await page.getByRole("option", { name: "e2e_automate" }).click(); | ||
| await page | ||
| .locator('[data-test="dashboard-x-item-_timestamp-remove"]') | ||
| .click(); | ||
|
|
||
| await page | ||
| .locator('[data-test="field-list-item-logs-e2e_automate-kubernetes_namespace_name"] [data-test="dashboard-add-x-data"]') | ||
| .click(); | ||
| await page | ||
| .locator('[data-test="field-list-item-logs-e2e_automate-kubernetes_container_name"] [data-test="dashboard-add-y-data"]') | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').fill("test"); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
|
|
||
| await page.locator('[data-test="date-time-relative-6-w-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
|
|
||
| await page.waitForTimeout(2000); | ||
|
|
||
| // Select table chart and perform transpose | ||
| await page.locator('[data-test="selected-chart-table-item"] img').click(); | ||
| await page.getByRole("cell", { name: "Kubernetes Container Name" }).click(); | ||
| await page.locator('[data-test="dashboard-sidebar"]').click(); | ||
| await page.locator('[data-test="dashboard-config-table_transpose"] div').nth(2).click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.waitForTimeout(2000); | ||
|
|
||
| // Validate data consistency before and after transpose | ||
| await validateTableDataBeforeAndAfterTranspose(page); | ||
|
|
||
| // Helper function to validate table data before and after transposing | ||
| // Helper function to dynamically transpose data and validate it | ||
| async function validateTableDataBeforeAndAfterTranspose(page) { | ||
| // Step 1: Capture headers and initial data from the table | ||
| const headers = await page.$$eval('[data-test="dashboard-panel-table"] thead tr th', (headerCells) => | ||
| headerCells.map(cell => cell.textContent.trim().replace(/^arrow_upward/, "")) // Remove "arrow_upward" prefix | ||
| ); | ||
|
|
||
| const initialData = await page.$$eval('[data-test="dashboard-panel-table"] tbody tr', (rows) => | ||
| rows | ||
| .map(row => Array.from(row.querySelectorAll("td"), cell => cell.textContent.trim())) | ||
| .filter(row => row.length > 0 && row.some(cell => cell !== "")) | ||
| ); | ||
|
|
||
| // Step 2: Perform transpose by simulating the transpose button click | ||
| await page.locator('[data-test="dashboard-config-table_transpose"] div').nth(2).click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.waitForTimeout(2000); | ||
|
|
||
| // Step 3: Capture transposed data from the table | ||
| const transposedData = await page.$$eval('[data-test="dashboard-panel-table"] tr', (rows) => | ||
| rows | ||
| .map(row => Array.from(row.querySelectorAll("td"), cell => cell.textContent.trim())) | ||
| .filter(row => row.length > 0 && row.some(cell => cell !== "")) | ||
| ); | ||
|
|
||
| // Step 4: Flatten `initialData` by pairing each namespace header with its value, excluding the empty namespace | ||
| const flattenedInitialData = headers.slice(1).map((namespace, index) => [namespace, initialData[0][index + 1]]); | ||
|
|
||
| // Step 5: Sort both `flattenedInitialData` and `transposedData` for comparison | ||
| const sortedFlattenedInitialData = flattenedInitialData.sort((a, b) => a[0].localeCompare(b[0])); | ||
| const sortedTransposedData = transposedData.sort((a, b) => a[0].localeCompare(b[0])); | ||
|
|
||
| // Step 6: Directly compare sorted arrays | ||
| expect(sortedTransposedData).toEqual(sortedFlattenedInitialData); | ||
| } | ||
| }); | ||
|
|
||
| test("should verify that the transpose toggle button is working correctly ", async ({ | ||
| page, | ||
| }) => { | ||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
|
|
||
| // Create a new dashboard | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| // Add panel to the dashboard | ||
| await page | ||
| .locator('[data-test="dashboard-if-no-panel-add-panel-btn"]') | ||
| .click(); | ||
| await page | ||
| .locator("label") | ||
| .filter({ hasText: "Streamarrow_drop_down" }) | ||
| .locator("i") | ||
| .click(); | ||
| await page.getByRole("option", { name: "e2e_automate" }).click(); | ||
|
|
||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_container_name"] [data-test="dashboard-add-y-data"]' | ||
| ) | ||
| .click(); | ||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_docker_id"] [data-test="dashboard-add-b-data"]' | ||
| ) | ||
| .click(); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-6-w-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="selected-chart-table-item"] img').click(); | ||
| await page.locator('[data-test="dashboard-sidebar"]').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .first() | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_transpose"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await expect( | ||
| page.getByRole("cell", { name: "Kubernetes Container Name" }) | ||
| ).toBeVisible(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').fill("test"); | ||
| await page.locator('[data-test="dashboard-panel-save"]').click(); | ||
| }); | ||
|
|
||
| test("should verify that when dynamic columns are enabled, the VRL function should display correctly", async ({ | ||
| page, | ||
| }) => { | ||
| await page.locator('[data-test="menu-link-\\/dashboards-item"]').click(); | ||
| await waitForDashboardPage(page); | ||
|
|
||
| // Create a new dashboard | ||
| await page.locator('[data-test="dashboard-add"]').click(); | ||
| await page.locator('[data-test="add-dashboard-name"]').click(); | ||
| await page | ||
| .locator('[data-test="add-dashboard-name"]') | ||
| .fill(randomDashboardName); | ||
| await page.locator('[data-test="dashboard-add-submit"]').click(); | ||
|
|
||
| // Add panel to the dashboard | ||
| await page | ||
| .locator('[data-test="dashboard-if-no-panel-add-panel-btn"]') | ||
| .click(); | ||
| await page | ||
| .locator("label") | ||
| .filter({ hasText: "Streamarrow_drop_down" }) | ||
| .locator("i") | ||
| .click(); | ||
| await page.getByRole("option", { name: "e2e_automate" }).click(); | ||
|
|
||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_container_name"] [data-test="dashboard-add-y-data"]' | ||
| ) | ||
| .click(); | ||
| await page | ||
| .locator( | ||
| '[data-test="field-list-item-logs-e2e_automate-kubernetes_docker_id"] [data-test="dashboard-add-b-data"]' | ||
| ) | ||
| .click(); | ||
| await page.locator('[data-test="date-time-btn"]').click(); | ||
| await page.locator('[data-test="date-time-relative-6-w-btn"]').click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await page.locator('[data-test="dashboard-sidebar"]').click(); | ||
| await page.locator('[data-test="selected-chart-table-item"] img').click(); | ||
| await page | ||
| .locator('[data-test="dashboard-config-table_dynamic_columns"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page | ||
| .locator('[data-test="logs-search-bar-show-query-toggle-btn"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page | ||
| .locator( | ||
| "#fnEditor > .monaco-editor > .overflow-guard > div:nth-child(2) > .lines-content > .view-lines > .view-line" | ||
| ) | ||
| .click(); | ||
| await page | ||
| .locator('[data-test="dashboard-vrl-function-editor"]') | ||
| .getByLabel("Editor content;Press Alt+F1") | ||
| .fill(".vrl=100"); | ||
|
|
||
| await page.waitForTimeout(2000); | ||
|
|
||
| await page | ||
| .locator('[data-test="dashboard-config-table_dynamic_columns"] div') | ||
| .nth(2) | ||
| .click(); | ||
|
|
||
| await page | ||
| .locator('[data-test="dashboard-config-table_dynamic_columns"] div') | ||
| .nth(2) | ||
| .click(); | ||
| await page.locator('[data-test="dashboard-apply"]').click(); | ||
| await expect( | ||
| page | ||
| .locator('[data-test="dashboard-panel-table"]') | ||
| .getByRole("cell", { name: "vrl" }) | ||
| ).toBeVisible(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').click(); | ||
| await page.locator('[data-test="dashboard-panel-name"]').fill("test"); | ||
| await page.locator('[data-test="dashboard-panel-save"]').click(); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract common dashboard setup into helper functions.
There's significant code duplication in dashboard and panel setup across test cases. Consider extracting these into reusable helper functions.
async function setupDashboard(page, dashboardName) {
await page.locator('[data-test="menu-link-\\/dashboards-item"]').click();
await waitForDashboardPage(page);
await page.locator('[data-test="dashboard-add"]').click();
await page.locator('[data-test="add-dashboard-name"]').fill(dashboardName);
await page.locator('[data-test="dashboard-add-submit"]').click();
}
async function setupPanel(page, options = {}) {
const {
streamName = "e2e_automate",
panelName = "test",
enableTranspose = false,
enableDynamicColumns = false
} = options;
await page.locator('[data-test="dashboard-if-no-panel-add-panel-btn"]').click();
// ... rest of the panel setup code
}Then use these in your tests:
test("should verify transpose functionality", async ({ page }) => {
await setupDashboard(page, randomDashboardName);
await setupPanel(page, {
enableTranspose: true,
panelName: "bhj"
});
// ... test-specific assertions
});| async function applyQueryButton(page) { | ||
| // click on the run query button | ||
| // Type the value of a variable into an input field | ||
| const search = page.waitForResponse(logData.applyQuery); | ||
| await page.waitForTimeout(3000); | ||
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ | ||
| force: true, | ||
| }); | ||
| // get the data from the search variable | ||
| await expect.poll(async () => (await search).status()).toBe(200); | ||
| // await search.hits.FIXME_should("be.an", "array"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve error handling in applyQueryButton function.
The function could benefit from better error handling and timeout configuration.
async function applyQueryButton(page) {
- const search = page.waitForResponse(logData.applyQuery);
- await page.waitForTimeout(3000);
- await page.locator("[data-test='logs-search-bar-refresh-btn']").click({
- force: true,
- });
- await expect.poll(async () => (await search).status()).toBe(200);
+ const search = page.waitForResponse(logData.applyQuery, { timeout: 5000 });
+ try {
+ await page.locator("[data-test='logs-search-bar-refresh-btn']").click();
+ const response = await search;
+ expect(response.status()).toBe(200);
+ return response;
+ } catch (error) {
+ throw new Error(`Failed to apply query: ${error.message}`);
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async function applyQueryButton(page) { | |
| // click on the run query button | |
| // Type the value of a variable into an input field | |
| const search = page.waitForResponse(logData.applyQuery); | |
| await page.waitForTimeout(3000); | |
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click({ | |
| force: true, | |
| }); | |
| // get the data from the search variable | |
| await expect.poll(async () => (await search).status()).toBe(200); | |
| // await search.hits.FIXME_should("be.an", "array"); | |
| } | |
| async function applyQueryButton(page) { | |
| const search = page.waitForResponse(logData.applyQuery, { timeout: 5000 }); | |
| try { | |
| await page.locator("[data-test='logs-search-bar-refresh-btn']").click(); | |
| const response = await search; | |
| expect(response.status()).toBe(200); | |
| return response; | |
| } catch (error) { | |
| throw new Error(`Failed to apply query: ${error.message}`); | |
| } | |
| } |
ad3443d to
540c1d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
5-6: Extract random string generation to a utility functionConsider moving the random dashboard name generation to a reusable utility function for better maintainability.
+function generateRandomString(prefix = '') { + return `${prefix}_${Math.random().toString(36).slice(2, 11)}`; +} + -const randomDashboardName = - "Dashboard_" + Math.random().toString(36).slice(2, 11); +const randomDashboardName = generateRandomString('Dashboard');
389-435: Improve error handling assertionThe current error assertion doesn't distinguish between different types of errors. Consider enhancing the error handling:
- let errorMessage = ''; + const errors = { + console: [], + page: [] + }; page.on('console', (msg) => { if (msg.type() === 'error') { - errorMessage += msg.text() + '\n'; + errors.console.push(msg.text()); } }); + page.on('pageerror', (error) => { + errors.page.push(error.message); + }); // ... test steps ... - expect(errorMessage).toBe(''); + expect(errors.console).toHaveLength(0); + expect(errors.page).toHaveLength(0);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (3)
.github/workflows/playwright.yml(5 hunks)tests/ui-testing/playwright-tests/dashboard-transpose.spec.js(1 hunks)web/src/components/dashboards/settings/GeneralSettings.vue(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/src/components/dashboards/settings/GeneralSettings.vue
🧰 Additional context used
📓 Path-based instructions (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1)
Pattern **/*.js: You are a smart javascript/typescript pull request reviewer.
You are going to review all the javascript/typescript files.
Be concise, and add a brief explanation to your suggestions
Make sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
📓 Learnings (1)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
Learnt from: ktx-kirtan
PR: openobserve/openobserve#4925
File: tests/ui-testing/playwright-tests/dashboard-transpose.spec.js:84-84
Timestamp: 2024-11-04T10:09:25.987Z
Learning: In `tests/ui-testing/playwright-tests/dashboard-transpose.spec.js`, when removing UTF characters from text, the regular expression `/[^\x00-\x7F]/g` is required, even though it includes control characters.
Learnt from: ktx-kirtan
PR: openobserve/openobserve#4925
File: tests/ui-testing/playwright-tests/dashboard-transpose.spec.js:60-61
Timestamp: 2024-11-04T09:56:01.929Z
Learning: In `tests/ui-testing/playwright-tests/dashboard-transpose.spec.js`, the response from the ingestion API does not contain sensitive data, so logging it is acceptable.
🪛 actionlint
.github/workflows/playwright.yml
35-35: label "ubicloud-standard-8" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
🪛 Biome
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js
[error] 84-84: Unexpected control character in a regular expression.
Control characters are unusual and potentially incorrect inputs, so they are disallowed.
(lint/suspicious/noControlCharactersInRegex)
🔇 Additional comments (5)
.github/workflows/playwright.yml (3)
127-127: Good choice using LTS version!
Using lts/* is a good practice as it ensures you're always using the latest LTS version of Node.js, providing a good balance between stability and features.
88-105: Consider optimizing test execution with file grouping.
The test matrix has been updated with the new dashboard-transpose.spec.js test. Consider:
- Grouping related test files (e.g., all dashboard tests together) for better parallelization
- Adding comments to indicate test groups/categories
#!/bin/bash
# Verify the new test file exists
echo "Checking for dashboard-transpose.spec.js..."
fd "dashboard-transpose.spec.js" tests/ui-testing/playwright-tests/
# Check average test execution times to help with grouping
echo "Checking test execution history..."
git log -p --all -S "dashboard-transpose.spec.js" tests/ui-testing/playwright-tests/Consider reorganizing the test files array for better maintainability:
testfilename:
[
# Core functionality tests
"sanity.spec.js",
# Feature-specific tests
"alerts.spec.js",
"schema.spec.js",
# Logs-related tests
"logspage.spec.js",
"logsqueries.spec.js",
"logsquickmode.spec.js",
# Stream and pipeline tests
"multiselect-stream.spec.js",
"pipeline.spec.js",
# Dashboard and visualization tests
"dashboardtype.spec.js",
"dashboard.spec.js",
"dashboard-transpose.spec.js",
"visualize.spec.js",
# Data handling tests
"unflattened.spec.js",
"secondsPrecisionAdded.spec.js",
]34-36: Verify the custom runner label configuration.
The ubicloud-standard-8 label is not a standard GitHub-hosted runner label. If this is a custom self-hosted runner, please ensure:
- The runner is properly configured and available
- Document the runner requirements in the PR description
- Consider adding a fallback to standard GitHub runners
✅ Verification successful
Let me gather more information about the workflow configurations to better understand the runner setup.
Custom Ubicloud runners are consistently used across workflows
The ubicloud-standard-8 label is actually a valid configuration as evidenced by its usage across multiple workflow files:
playwright.ymlusesubicloud-standard-8unit-tests.ymlusesubicloud-standard-8build-pr-image.ymlandbuild-fork-pr-image.ymluse various Ubicloud runners (ubicloud-standard-4,ubicloud-standard-8-arm,ubicloud-standard-2-arm)
This appears to be an established pattern in the repository for using Ubicloud-provided runners, with appropriate fallbacks to Ubuntu runners where needed. The configuration is consistent with the repository's CI/CD infrastructure.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if there are other workflows using this runner label
rg -l "ubicloud-standard-8" .github/workflows/
Length of output: 390
Script:
#!/bin/bash
# Check all workflow files for runner configurations and labels
echo "Checking all workflow files for runner configurations:"
rg -A 2 "runs-on:" .github/workflows/
# Check if there's any documentation about custom runners
echo -e "\nChecking for runner documentation in README or docs:"
fd -e md -e txt -d 2 . | xargs rg -l "runner|ubicloud"
Length of output: 3799
🧰 Tools
🪛 actionlint
35-35: label "ubicloud-standard-8" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-14.0", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-13.0", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "macos-12.0", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (2)
86-97: Skip review: Past comment exists
13-13: 🛠️ Refactor suggestion
Replace fixed timeout with explicit wait
Using waitForTimeout can lead to flaky tests. Consider waiting for a specific condition instead.
- await page.waitForTimeout(1000);
+ await page.waitForSelector('[data-cy="login-user-id"]', { state: 'visible' });Likely invalid or redundant comment.
Summary by CodeRabbit
New Features
data-testattributes to various components in the General Settings for improved testability.Bug Fixes