test: table type dashboard (#3677)

- Verify if table  type dashboard is created
- Verify if timezone selected as Asia/Calcuta and timestamp on UI is as
per selected timezone
- Verify if user is able to change timezone to Europe/Zurich
- Verify if the timezone is updated to changed timezone

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Introduced timestamp comparison tests across different timezones on
dashboards.

- **Tests**
- Added new helper functions for test cases to streamline request
sending and timestamp formatting.
- Cleaned up and optimized existing test cases by removing unused and
commented-out code.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: ktx-abhay <abhay.padamani@kiara.tech>
This commit is contained in:
Neha P
2024-06-05 11:36:19 +05:30
committed by GitHub
co-authored by ktx-abhay
parent 762b4d5a59
commit 43e5d4e647
4 changed files with 209 additions and 76 deletions
+30
View File
@@ -10,6 +10,8 @@
"license": "ISC",
"dependencies": {
"@google-cloud/local-auth": "^2.1.0",
"date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"dotenv": "^16.4.5",
"googleapis": "^105.0.0",
"pixelmatch": "^5.3.0",
@@ -834,6 +836,23 @@
"node": ">=0.10"
}
},
"node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/date-fns-tz": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.1.3.tgz",
"integrity": "sha512-ZfbMu+nbzW0mEzC8VZrLiSWvUIaI3aRHeq33mTe7Y38UctKukgqPR4nTDwcwS4d64Gf8GghnVsroBuMY3eiTeA==",
"peerDependencies": {
"date-fns": "^3.0.0"
}
},
"node_modules/dateformat": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
@@ -3872,6 +3891,17 @@
"assert-plus": "^1.0.0"
}
},
"date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww=="
},
"date-fns-tz": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.1.3.tgz",
"integrity": "sha512-ZfbMu+nbzW0mEzC8VZrLiSWvUIaI3aRHeq33mTe7Y38UctKukgqPR4nTDwcwS4d64Gf8GghnVsroBuMY3eiTeA==",
"requires": {}
},
"dateformat": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
+2
View File
@@ -18,6 +18,8 @@
},
"dependencies": {
"@google-cloud/local-auth": "^2.1.0",
"date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"dotenv": "^16.4.5",
"googleapis": "^105.0.0",
"pixelmatch": "^5.3.0",
+175 -63
View File
@@ -2,9 +2,11 @@ import { test, expect } from "@playwright/test";
import logData from "../../ui-testing/cypress/fixtures/log.json";
import { log } from "console";
import logsdata from "../../test-data/logs_data.json";
import { toZonedTime } from "date-fns-tz";
test.describe.configure({ mode: "parallel" });
const folderName = `Folder ${Date.now()}`;
const dashboardName = `AutomatedDashboard${Date.now()}`;
async function login(page) {
await page.goto(process.env["ZO_BASE_URL"]);
@@ -704,20 +706,44 @@ test.describe("Sanity testcases", () => {
.click();
});
test("should check JSON responses for successful:1 with timestamp 15 mins before", async ({
page,
request,
}) => {
const orgId = process.env["ORGNAME"];
const streamName = "e2e_automate";
const getHeaders = () => {
const basicAuthCredentials = Buffer.from(
`${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}`
).toString("base64");
const headers = {
return {
Authorization: `Basic ${basicAuthCredentials}`,
"Content-Type": "application/json",
};
};
// Helper function to get ingestion URL
const getIngestionUrl = (orgId, streamName) => {
return `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`;
};
// Helper function to send POST request
const sendRequest = async (page, url, payload, headers) => {
return await page.evaluate(
async ({ url, headers, payload }) => {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
});
return await response.json();
},
{ url, headers, payload }
);
};
test("should check JSON responses for successful:1 with timestamp 15 mins before", async ({
page,
}) => {
const orgId = process.env["ORGNAME"];
const streamName = "e2e_automate";
const headers = getHeaders();
const ingestionUrl = getIngestionUrl(orgId, streamName);
// First payload
const payload1 = [
@@ -741,32 +767,12 @@ test.describe("Sanity testcases", () => {
},
];
// Function to send POST request
const sendRequest = async (url, payload) => {
return await page.evaluate(
async ({ url, headers, payload }) => {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
});
return await response.json();
},
{ url, headers, payload }
);
};
// URLs for the final requests
const ingestionUrl = `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`;
const url1 = ingestionUrl;
const url2 = ingestionUrl;
// Sending first request
const response1 = await sendRequest(url1, payload1);
const response1 = await sendRequest(page, ingestionUrl, payload1, headers);
console.log(response1);
// Sending second request
const response2 = await sendRequest(url2, payload2);
const response2 = await sendRequest(page, ingestionUrl, payload2, headers);
console.log(response2);
// Assertions
@@ -776,18 +782,11 @@ test.describe("Sanity testcases", () => {
test("should display error if timestamp past the ingestion time limit", async ({
page,
request,
}) => {
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 headers = getHeaders();
const ingestionUrl = getIngestionUrl(orgId, streamName);
// First payload
const payload1 = [
@@ -799,8 +798,8 @@ test.describe("Sanity testcases", () => {
},
];
// Second payload with timestamp 15 minutes before
const timestamp = Date.now() - 6 * 60 * 60 * 1000; // 15 minutes before
// Second payload with timestamp 6 hours before
const timestamp = Date.now() - 6 * 60 * 60 * 1000; // 6 hours before
const payload2 = [
{
level: "info",
@@ -811,32 +810,12 @@ test.describe("Sanity testcases", () => {
},
];
// Function to send POST request
const sendRequest = async (url, payload) => {
return await page.evaluate(
async ({ url, headers, payload }) => {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
});
return await response.json();
},
{ url, headers, payload }
);
};
// URLs for the final requests
const ingestionUrl = `${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`;
const url1 = ingestionUrl;
const url2 = ingestionUrl;
// Sending first request
const response1 = await sendRequest(url1, payload1);
const response1 = await sendRequest(page, ingestionUrl, payload1, headers);
console.log(response1);
// Sending second request
const response2 = await sendRequest(url2, payload2);
const response2 = await sendRequest(page, ingestionUrl, payload2, headers);
console.log(response2);
// Assertions
@@ -844,7 +823,140 @@ test.describe("Sanity testcases", () => {
expect(response2.status[0].successful).toBe(0);
expect(response2.status[0].failed).toBe(1);
expect(response2.status[0].error).toBe(
'Too old data, only last 5 hours data can be ingested. Data discarded. You can adjust ingestion max time by setting the environment variable ZO_INGEST_ALLOWED_UPTO=<max_hours>'
"Too old data, only last 5 hours data can be ingested. Data discarded. You can adjust ingestion max time by setting the environment variable ZO_INGEST_ALLOWED_UPTO=<max_hours>"
);
});
const formatDate = (date) => {
const year = String(date.getFullYear());
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
test("should compare time displayed in table dashboard after changing timezone and then delete it ", async ({ page }) => {
const orgId = process.env["ORGNAME"];
const streamName = "e2e_tabledashboard";
const headers = getHeaders();
const ingestionUrl = getIngestionUrl(orgId, streamName);
const timestamp = parseInt(Date.now() / 10000) * 10000 - 10 * 60 * 1000; // 10 minutes before
// First payload
const payload1 = [
{
level: "info",
job: "test",
log: "test message for openobserve",
e2e: "1",
_timestamp: timestamp,
},
];
// Sending first request
const response1 = await sendRequest(page, ingestionUrl, payload1, headers);
console.log(response1);
await page.locator('[data-test="menu-link-\\/dashboards-item"]').click();
await page.waitForTimeout(5000);
await page.locator('[data-test="dashboard-add"]').click();
await page.waitForTimeout(5000);
await page.locator('[data-test="add-dashboard-name"]').click();
await page.locator('[data-test="add-dashboard-name"]').fill(dashboardName);
await page.locator('[data-test="dashboard-add-submit"]').click();
await page.waitForTimeout(2000);
await page
.locator('[data-test="dashboard-if-no-panel-add-panel-btn"]')
.click();
await page.waitForTimeout(3000);
await page.locator('[data-test="selected-chart-table-item"] img').click();
await page.locator('[data-test="index-dropdown-stream"]').click();
await page
.locator('[data-test="index-dropdown-stream"]')
.fill("e2e_tabledashboard");
await page.getByRole("option", { name: "e2e_tabledashboard" }).click({force:true});
await page.waitForTimeout(5000);
await page
.locator(
'[data-test="field-list-item-logs-e2e_tabledashboard-e2e"] [data-test="dashboard-add-y-data"]'
)
.click();
await page
.locator(
'[data-test="field-list-item-logs-e2e_tabledashboard-job"] [data-test="dashboard-add-y-data"]'
)
.click();
await page
.locator(
'[data-test="field-list-item-logs-e2e_tabledashboard-_timestamp"] [data-test="dashboard-add-x-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("sanitydash");
await page.waitForTimeout(2000);
await page.locator('[data-test="dashboard-panel-save"]').click();
await page.waitForTimeout(2000);
// // Change timezone to Asia/Calcutta
await page.locator('[data-test="date-time-btn"]').click();
await page.locator('[data-test="datetime-timezone-select"]').click();
await page
.locator('[data-test="datetime-timezone-select"]')
.fill("Asia/Calcutta");
await page.getByText("Asia/Calcutta", { exact: true }).click();
await page.waitForTimeout(200);
// NOTE: pass selected timezone
const calcuttaTime = toZonedTime(new Date(timestamp), "Asia/Calcutta");
const displayedTimestampCalcutta = formatDate(calcuttaTime);
console.log(displayedTimestampCalcutta);
await page.waitForTimeout(2000);
// Verify the displayed time in Asia/Calcutta
const timeCellCalcutta = await page
.getByRole("cell", { name: displayedTimestampCalcutta })
.textContent();
expect(timeCellCalcutta).toBe(displayedTimestampCalcutta);
await page.waitForTimeout(1000);
// Change timezone to Europe/Zurich
await page.locator('[data-test="date-time-btn"]').click();
await page.locator('[data-test="date-time-btn"]').click();
await page.locator('[data-test="datetime-timezone-select"]').click();
await page
.locator('[data-test="datetime-timezone-select"]')
.fill("Europe/Zurich");
await page.getByText("Europe/Zurich", { exact: true }).click();
await page.waitForTimeout(200);
// Convert the timestamp to the required format in Europe/Zurich
const zurichTime = toZonedTime(new Date(timestamp), "Europe/Zurich");
const displayedTimestampZurich = formatDate(zurichTime);
console.log(displayedTimestampZurich);
// Verify the displayed time in Europe/Zurich
const timeCellZurich = await page
.getByRole("cell", { name: displayedTimestampZurich })
.textContent();
expect(timeCellZurich).toBe(displayedTimestampZurich);
await page.waitForTimeout(2000);
await page
.locator('[data-test="dashboard-edit-panel-sanitydash-dropdown"]')
.click();
await page.locator('[data-test="dashboard-delete-panel"]').click();
await page.locator('[data-test="confirm-button"]').click();
await page
.locator("#q-notify div")
.filter({ hasText: "check_circlePanel deleted" })
.nth(3)
.click();
await page.locator('[data-test="dashboard-back-btn"]');
await page.locator('[data-test="dashboard-back-btn"]').click();
await page
.getByRole("row", { name: dashboardName })
.locator('[data-test="dashboard-delete"]')
.click();
await page.locator('[data-test="confirm-button"]').click();
});
});
@@ -73,16 +73,9 @@ test.describe("Schema testcases", () => {
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");
await expect.poll(async () => (await search).status()).toBe(200);
}
// tebefore(async function () {
// // logData("log");
// // const data = page;
// // logData = data;
// console.log("--logData--", logData);
// });
test.beforeEach(async ({ page }) => {
await login(page);
await page.waitForTimeout(5000)
@@ -94,7 +87,6 @@ test.describe("Schema testcases", () => {
const allsearch = page.waitForResponse("**/api/default/_search**");
await selectStreamAndStreamTypeForLogs(page,logData.Stream);
await applyQueryButton(page);
// const streams = page.waitForResponse("**/api/default/streams**");
});
test('stream schema settings updated to be displayed under logs', async ({ page }) => {
@@ -192,13 +184,10 @@ test.describe("Schema testcases", () => {
await page.waitForTimeout(2000);
await page.locator('button').filter({ hasText: 'close' }).click()
await page.waitForTimeout(1000);
// await page.getByPlaceholder('Search Stream').click();
// await page.getByPlaceholder('Search Stream').fill('e2e_automate');
await page.getByRole('button', { name: 'Stream Detail' }).first().click();
await page.locator('[data-test="tab-schemaFields"]').click();
await page.locator('[data-test="schema-stream-delete-kubernetes_annotations_kubectl_kubernetes_io_default_container-field-fts-key-checkbox"]').click();
await page.locator('[data-test="schema-stream-delete-kubernetes_annotations_kubernetes_io_psp-field-fts-key-checkbox"]').click();
// await page.locator('[data-test="schema-stream-delete-oooo-field-fts-key-checkbox"]').click();
await page.locator('[data-test="schema-add-field-button"]').click();
await page.locator('[data-test="schema-update-settings-button"]').click();