Skip to content

Conversation

@ktx-akshay
Copy link
Collaborator

@ktx-akshay ktx-akshay commented Oct 28, 2024

Summary by CodeRabbit

  • New Features

    • Enhanced test coverage for dashboard UI with new Playwright tests focusing on the transpose feature and dynamic columns.
    • Added data-test attributes to various components in the General Settings for improved testability.
  • Bug Fixes

    • Improved consistency in the GitHub Actions workflow configuration for UI tests.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2024

Walkthrough

The pull request introduces updates to the GitHub Actions workflow for Playwright UI tests, including the addition of a new test file, dashboard-transpose.spec.js, to enhance test coverage. It also improves formatting consistency within the workflow configuration. Additionally, GeneralSettings.vue has been modified to include data-test attributes for better testability of UI components. The new test file contains a suite of tests focused on the dashboard's transpose feature, with various functions and test cases implemented to validate its functionality.

Changes

File Path Change Summary
.github/workflows/playwright.yml Added dashboard-transpose.spec.js to ui_integration_tests. Reformatted lines for consistency.
web/src/components/dashboards/settings/GeneralSettings.vue Added data-test attributes to several components for enhanced testability.
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js Introduced a new test suite with multiple test cases and functions to validate dashboard functionality.

Possibly related PRs

Suggested labels

✏️ Feature

Suggested reviewers

  • neha00290

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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:

  1. Consider using test sharding to run tests in parallel across multiple runners
  2. Add test retries for flaky tests
  3. 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: 3

And 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 code

The 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 consistency

Consider using consistent naming conventions for imported modules. Currently, logData (camelCase) and logsdata (all lowercase) differ in casing. For clarity and to follow best practices, you might want to standardize the variable names.


281-282: Avoid redundant comments

The comment ////////////////////////// does not add value to the code and can be removed to improve readability.

- //////////////////////////

732-842: Reconsider using test.skip without a reason

There are several tests marked with test.skip without 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 code

There 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

📥 Commits

Files that changed from the base of the PR and between cb6ac0a and d433bb4.

📒 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 suggestions

Make 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 suggestions

Make 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 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/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.js exists in the expected location

The file is present at tests/ui-testing/playwright-tests/dashboardtanspose.spec.js as 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 switching

In 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 defined

The code relies on environment variables like process.env["ZO_ROOT_USER_EMAIL"], process.env["ZO_ROOT_USER_PASSWORD"], and process.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:

Comment on lines 105 to 118
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;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve beforeEach hook implementation.

The hook needs several improvements:

  1. Use constants for timeout values
  2. Add error handling
  3. 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.

Suggested change
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;
}
});

Comment on lines 86 to 97
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");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Address FIXME comment and improve click handling.

The function needs several improvements:

  1. Remove or implement the FIXME comment
  2. Explain why force: true is needed
  3. 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.

Suggested change
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);
}

Comment on lines 41 to 62
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);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling and make stream name configurable.

The ingestion function needs improvements:

  1. Add error handling for the fetch request
  2. 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.

Suggested change
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;
}
}

Comment on lines 119 to 153
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();


});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve test case implementation and add assertions.

The test case needs several improvements:

  1. Remove commented code
  2. Use constants for timeout values
  3. Add assertions for updated values
  4. 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.

Suggested change
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();
});

Comment on lines 225 to 259
// 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());
}
Copy link
Contributor

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.

Comment on lines 81 to 111
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);
});
Copy link
Contributor

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 beforeAll block if they are only needed once per test suite.
  • Confirm that the orgNavigation promise is awaited at the correct place to prevent race conditions.

Comment on lines 284 to 286
const randomDashboardName = `Dashboard-${Math.floor(
Math.random() * 10000
)}`;
Copy link
Contributor

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();

Comment on lines 501 to 570
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();
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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 ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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**");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
await page.waitForURL(process.env["ZO_BASE_URL"] + "/web/dashboards**");
await page.waitForURL(new RegExp(`^${process.env["ZO_BASE_URL"]}/web/dashboards.*$`));

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 code

The 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 function removeUTFCharacters

The removeUTFCharacters function 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 function applyQueryButton

The applyQueryButton function 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

📥 Commits

Files that changed from the base of the PR and between d433bb4 and 8435ca8.

📒 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 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 (2)
.github/workflows/playwright.yml (1)

90-90: LGTM! Verify test file existence.

The addition of dashboardtranspose.spec.js to the test matrix aligns with the PR objectives.

Let's verify the test file exists:

✅ Verification successful

Test file verification successful

The dashboardtranspose.spec.js file exists at the expected location in tests/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: Ensure logData.logsUrl is defined and correct

The variable logData.logsUrl is 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.

Comment on lines 90 to 91
await page.waitForTimeout(3000);
await page.locator("[data-test='logs-search-bar-refresh-btn']").click({
Copy link
Contributor

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

Comment on lines 124 to 166
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);
});
Copy link
Contributor

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 ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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, " ");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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)

@ktx-vaidehi ktx-vaidehi force-pushed the test/dashboard-settings branch from dcf0e93 to 80a4996 Compare October 30, 2024 08:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Files that changed from the base of the PR and between 8435ca8 and 80a4996.

📒 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)

Comment on lines 5 to 6
const randomDashboardName =
"Dashboard_" + Math.random().toString(36).substr(2, 9);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Comment on lines 216 to 255
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);
}
Copy link
Contributor

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.

Comment on lines 161 to 163
.locator('[data-test="dashboard-config-table_transpose"] div')
.nth(2)
.click();
Copy link
Contributor

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📥 Commits

Files that changed from the base of the PR and between 80a4996 and 1ba40ed.

📒 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:

  1. The runner is properly configured in your GitHub organization/repository
  2. The runner has the necessary dependencies for Playwright tests
  3. 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-arm also 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);
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 30, 2024

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

Copy link
Collaborator

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

Copy link
Contributor

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?

Comment on lines 393 to 398
let errorMessage = '';
page.on('console', (msg) => {
if (msg.type() === 'error') {
errorMessage = msg.text();
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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

Comment on lines 5 to 6
const randomDashboardName =
"Dashboard_" + Math.random().toString(36).substr(2, 9);
Copy link
Contributor

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.

Suggested change
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, " ");
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required

Copy link
Contributor

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.

@ktx-vaidehi ktx-vaidehi force-pushed the test/dashboard-settings branch from 1ba40ed to 3047b15 Compare November 4, 2024 06:40
@ktx-vaidehi ktx-vaidehi changed the title test: dashboard settings test: dashboard table transpose Nov 4, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 like 18.x (matching the version used in the build step) or at least specify the major version like lts/hydrogen for better predictability.

-          node-version: lts/*
+          node-version: 18.x
tests/ui-testing/playwright-tests/dashboard-transpose.spec.js (1)

252-252: Fix typos in test title

The 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

📥 Commits

Reviewing files that changed from the base of the PR and between 1ba40ed and 3047b15.

📒 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:

  1. Verify that the test file exists in the correct location
  2. 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:

  1. The runner is properly configured and available
  2. The runner label is documented in the repository's workflow documentation
  3. Consider adding an actionlint.yaml configuration 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.yml and build-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)

Comment on lines 123 to 165
// 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);
});
Copy link
Contributor

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

Comment on lines +60 to +61
const response = await fetchResponse.json();
console.log(response);
Copy link
Contributor

@coderabbitai coderabbitai bot Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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);

Copy link
Collaborator

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

Copy link
Contributor

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 waitForDashboardPage function 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3047b15 and ad3443d.

📒 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)

Comment on lines +119 to +387
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();
});
Copy link
Contributor

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
});

Comment on lines +86 to +97
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");
}
Copy link
Contributor

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.

Suggested change
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}`);
}
}

@ktx-vaidehi ktx-vaidehi force-pushed the test/dashboard-settings branch from ad3443d to 540c1d7 Compare November 4, 2024 11:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 function

Consider 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 assertion

The 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

📥 Commits

Reviewing files that changed from the base of the PR and between ad3443d and 540c1d7.

📒 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:

  1. Grouping related test files (e.g., all dashboard tests together) for better parallelization
  2. 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:

  1. The runner is properly configured and available
  2. Document the runner requirements in the PR description
  3. 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.yml uses ubicloud-standard-8
  • unit-tests.yml uses ubicloud-standard-8
  • build-pr-image.yml and build-fork-pr-image.yml use 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.

@ktx-vaidehi ktx-vaidehi merged commit 0ca6524 into main Nov 4, 2024
28 checks passed
@ktx-vaidehi ktx-vaidehi deleted the test/dashboard-settings branch November 4, 2024 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants