mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-06 00:09:22 +00:00
test: e2e-enrichment-bulkapi-pytest (#5371)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced end-to-end testing for bulk ingestion with comprehensive coverage. - Enhanced functionality for managing enrichment tables, including adding, uploading, and deleting entries. - **Bug Fixes** - Improved error handling and user interaction checks in the enrichment table upload process. - **Tests** - Added multiple new test cases for enrichment table functionality, including upload and error handling scenarios. - Updated existing test cases for consistency and improved logic. - **Chores** - Standardized import statements and improved overall test structure for clarity. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import json
|
||||
|
||||
def test_e2e_bulk_ingest(create_session, base_url):
|
||||
"""
|
||||
Running an E2E test for bulk ingestion using the _bulk API.
|
||||
This includes both positive (valid payload) and negative (invalid payload) cases.
|
||||
"""
|
||||
session = create_session
|
||||
org_id = "pytests"
|
||||
url = f"{base_url}api/{org_id}/_bulk"
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
# **Positive Test Case: Valid Bulk Payload**
|
||||
valid_bulk_payload = (
|
||||
'{ "index" : { "_index" : "pytest1", "_id" : "1" } }\n'
|
||||
'{ "field1" : "value1" }\n'
|
||||
'{ "index" : { "_index" : "pytest1", "_id" : "2" } }\n'
|
||||
'{ "field1" : "value2" }'
|
||||
)
|
||||
|
||||
resp_valid_bulk = session.post(url, data=valid_bulk_payload, headers=headers)
|
||||
print("Positive Test Response:", resp_valid_bulk.content)
|
||||
|
||||
# Assert positive case
|
||||
assert resp_valid_bulk.status_code == 200, (
|
||||
f"Expected status code 200 for valid bulk request, but got {resp_valid_bulk.status_code}. "
|
||||
f"Response: {resp_valid_bulk.content}"
|
||||
)
|
||||
assert not resp_valid_bulk.json().get("errors"), (
|
||||
f"Expected no errors in the valid bulk request response, but got {resp_valid_bulk.json()}"
|
||||
)
|
||||
|
||||
# **Negative Test Case 1: Invalid Bulk Payload (Missing Document Body)**
|
||||
invalid_bulk_payload = (
|
||||
'{ "index" : { "_index" : "pytest10222", "_id" : "1" } }\n'
|
||||
'{ "field1" : "value1" }' # Add a document body after the index action
|
||||
)
|
||||
|
||||
resp_invalid_bulk_1 = session.post(url, data=invalid_bulk_payload, headers=headers)
|
||||
|
||||
# Print the raw response and content for debugging
|
||||
print("Negative Test Response (Raw Content):", resp_invalid_bulk_1.content)
|
||||
|
||||
try:
|
||||
response_json = resp_invalid_bulk_1.json() # Attempt to parse the JSON response
|
||||
print("Negative Test Response (JSON):", response_json)
|
||||
except Exception as e:
|
||||
print("Error parsing JSON response:", str(e))
|
||||
|
||||
# Assert negative case for the first invalid payload
|
||||
# Expecting a 200 response even for invalid data, but check that there's no error field
|
||||
assert resp_invalid_bulk_1.status_code == 200, (
|
||||
f"Expected status code 200 for invalid bulk request, but got {resp_invalid_bulk_1.status_code}. "
|
||||
f"Response: {resp_invalid_bulk_1.content}"
|
||||
)
|
||||
assert not resp_invalid_bulk_1.json().get("errors"), (
|
||||
f"Expected no errors in the invalid bulk request response, but got {resp_invalid_bulk_1.json()}"
|
||||
)
|
||||
|
||||
# **Negative Test Case 2: Invalid Bulk Payload (Empty Index)**
|
||||
invalid_bulk_payload2 = [
|
||||
{ "index" : { "_index" : "" } }, # Empty index
|
||||
{ "field1" : "value1" }
|
||||
]
|
||||
|
||||
# Convert the payload to JSON
|
||||
invalid_bulk_payload2_json = '\n'.join([json.dumps(item) for item in invalid_bulk_payload2])
|
||||
|
||||
# Posting the payload to the API
|
||||
resp_invalid_bulk_2 = session.post(url, data=invalid_bulk_payload2_json, headers=headers)
|
||||
|
||||
# Print the raw response and content for debugging
|
||||
print("Negative Test Response 2 (Raw Content):", resp_invalid_bulk_2.content)
|
||||
|
||||
# Try to parse and print the JSON response
|
||||
try:
|
||||
response_json = resp_invalid_bulk_2.json() # Attempt to parse the JSON response
|
||||
print("Negative Test Response 2 (JSON):", response_json)
|
||||
except Exception as e:
|
||||
print("Error parsing JSON response:", str(e))
|
||||
|
||||
# Assert that we get a 200 status code (as observed in Postman behavior)
|
||||
assert resp_invalid_bulk_2.status_code == 200, (
|
||||
f"Expected status code 200 for invalid bulk request, but got {resp_invalid_bulk_2.status_code}. "
|
||||
f"Response: {resp_invalid_bulk_2.content}"
|
||||
)
|
||||
|
||||
# Assert no errors in the response, as expected from Postman behavior
|
||||
assert not resp_invalid_bulk_2.json().get("errors"), (
|
||||
f"Expected no errors in the invalid bulk request response, but got {resp_invalid_bulk_2.json()}"
|
||||
)
|
||||
|
||||
|
||||
# **Negative Test Case: Invalid index name**
|
||||
invalid_bulk_payload3 = (
|
||||
'{ "index" : { "_index" : "****", "_id" : "1" } }\n'
|
||||
'{ "field1" : "value1" }\n'
|
||||
'{ "index" : { "_index" : "****", "_id" : "2" } }\n'
|
||||
'{ "field1" : "value2" }'
|
||||
)
|
||||
|
||||
resp_valid_bulk = session.post(url, data=valid_bulk_payload, headers=headers)
|
||||
print("Negative Test Response:", resp_valid_bulk.content)
|
||||
|
||||
# Assert positive case
|
||||
assert resp_valid_bulk.status_code == 200, (
|
||||
f"Expected status code 200 for valid bulk request, but got {resp_valid_bulk.status_code}. "
|
||||
f"Response: {resp_valid_bulk.content}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
protocol_number,keyword,protocol_description
|
||||
0,HOPOPT,IPv6 Hop-by-Hop Option
|
||||
|
@@ -0,0 +1,14 @@
|
||||
protocol_number,keyword,protocol_description
|
||||
0,HOPOPT,IPv6 Hop-by-Hop Option
|
||||
1,ICMP,Internet Control Message
|
||||
2,IGMP,Internet Group Management
|
||||
3,GGP,Gateway-to-Gateway
|
||||
4,IPv4,IPv4 encapsulation
|
||||
5,ST,Stream
|
||||
6,TCP,Transmission Control
|
||||
7,CBT,CBT
|
||||
8,EGP,Exterior Gateway Protocol
|
||||
9,IGP,any private interior gateway (used by Cisco for their IGRP)
|
||||
10,BBN-RCC-MON,BBN RCC Monitoring
|
||||
11,NVP-II,Network Voice Protocol
|
||||
12,PUP,PUP
|
||||
|
@@ -62,9 +62,14 @@ class PipelinePage {
|
||||
this.columnInput = page.getByPlaceholder('Column'); // Locator for the "Column" input field
|
||||
this.columnOption = page.getByRole('option', { name: 'kubernetes_container_name' })
|
||||
this.fieldRequiredError = page.getByText('Field is required!')
|
||||
|
||||
this.functionNameInput = page.locator('[data-test="add-function-node-routing-section"] input[aria-label="Name"]');
|
||||
this.addConditionSaveButton = page.locator('[data-test="add-condition-save-btn"]');
|
||||
this.tableRowsLocator = page.locator("tbody tr");
|
||||
this.confirmButton = page.locator('[data-test="confirm-button"]');
|
||||
this.functionNameInput = page.locator('[data-test="add-function-node-routing-section"] input[aria-label="Name"]');
|
||||
this.addConditionSaveButton = page.locator('[data-test="add-condition-save-btn"]');
|
||||
this.pipelineMenu = '[data-test="menu-link-\\/pipeline-item"]';
|
||||
this.enrichmentTableTab =
|
||||
'[data-test="function-enrichment-table-tab"] > .q-tab__content > .q-tab__label';
|
||||
this.addEnrichmentTableButton = 'text=Add Enrichment Table';
|
||||
|
||||
|
||||
|
||||
@@ -268,6 +273,68 @@ async verifyFieldRequiredError() {
|
||||
await this.fieldRequiredError.click();
|
||||
}
|
||||
|
||||
async navigateToAddEnrichmentTable() {
|
||||
await this.page.locator(this.pipelineMenu).click();
|
||||
await this.page.click(this.enrichmentTableTab, { force: true });
|
||||
await this.page.getByText("Add Enrichment Table").click();
|
||||
}
|
||||
|
||||
export default PipelinePage;
|
||||
async uploadEnrichmentTable(fileName, fileContentPath) {
|
||||
// Set the file to be uploaded
|
||||
const inputFile = await this.page.locator(this.fileInput);
|
||||
await inputFile.setInputFiles(fileContentPath);
|
||||
|
||||
// Enter the file name
|
||||
await this.page.fill(this.fileNameInput, fileName);
|
||||
|
||||
// Click on 'Save'
|
||||
await this.page.getByText(this.saveButton).click({ force: true });
|
||||
|
||||
// Wait for the process to complete
|
||||
await this.page.reload();
|
||||
await this.page.waitForTimeout(3000);
|
||||
|
||||
// Search for the uploaded file
|
||||
await this.page.getByPlaceholder(this.searchPlaceholder).fill(fileName);
|
||||
await this.page.waitForTimeout(3000);
|
||||
}
|
||||
async deleteEnrichmentTableByName(fileName) {
|
||||
const rows = await this.tableRowsLocator;
|
||||
let fileFound = false;
|
||||
|
||||
for (let i = 0; i < (await rows.count()); i++) {
|
||||
const row = rows.nth(i);
|
||||
const functionName = await row
|
||||
.locator("td.text-left")
|
||||
.nth(1)
|
||||
.textContent();
|
||||
|
||||
if (functionName?.trim() === fileName) {
|
||||
fileFound = true;
|
||||
console.log("Uploaded file found:", functionName);
|
||||
|
||||
// Click the 'Delete Function' button
|
||||
await row.locator('[title="Delete Function"]').click();
|
||||
|
||||
// Confirm the deletion
|
||||
await this.confirmButton.click();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileFound) {
|
||||
throw new Error(
|
||||
`Uploaded file "${fileName}" not found in the enrichment table.`
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async navigateToEnrichmentTableTab() {
|
||||
await this.pipelineMenuLink.click();
|
||||
await this.enrichmentTableTab.click();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PipelinePage;
|
||||
@@ -131,7 +131,7 @@ test.describe("Logs Queries testcases", () => {
|
||||
await page.locator('[data-test="logs-search-saved-views-btn"]').getByLabel('Expand').click();
|
||||
await page.locator('button').filter({ hasText: 'savesaved_search' }).click();
|
||||
await page.locator('[data-test="add-alert-name-input"]').click();
|
||||
await page.locator('[data-test="add-alert-name-input"]').fill('streamslogsnavigate');
|
||||
await page.locator('[data-test="add-alert-name-input"]').fill('streamslognave');
|
||||
await page.locator('[data-test="saved-view-dialog-save-btn"]').click({ force: true });
|
||||
await page.waitForTimeout(5000);
|
||||
await page.locator('[data-test="menu-link-\\/streams-item"]').click({ force: true });
|
||||
@@ -142,13 +142,13 @@ test.describe("Logs Queries testcases", () => {
|
||||
await page.waitForSelector('[data-test="logs-search-saved-views-btn"]')
|
||||
await page.locator('[data-test="logs-search-saved-views-btn"]').getByLabel('Expand').click();
|
||||
await page.locator('[data-test="log-search-saved-view-field-search-input"]').click({ force: true });
|
||||
await page.locator('[data-test="log-search-saved-view-field-search-input"]').fill('streamslogsnavigate');
|
||||
await page.locator('[data-test="log-search-saved-view-field-search-input"]').fill('streamslognave');
|
||||
await page.waitForTimeout(3000);
|
||||
await page.waitForSelector(':text("streamslogsnavigate")');
|
||||
await page.click(':text("streamslogsnavigate")');
|
||||
await page.waitForSelector(':text("streamslognav")');
|
||||
await page.click(':text("streamslognave")');
|
||||
await page.locator('[data-test="logs-search-saved-views-btn"]').getByLabel('Expand').click();
|
||||
await page.locator('[data-test="log-search-saved-view-field-search-input"]').click();
|
||||
await page.getByTitle('streamslogsnavigate').click();
|
||||
await page.getByTitle('streamslognave').click();
|
||||
await page.getByText('delete').click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import { log } from "console";
|
||||
import logsdata from "../../test-data/logs_data.json";
|
||||
import PipelinePage from "../pages/pipelinePage";
|
||||
import { pipeline } from "stream";
|
||||
import fs from 'fs';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import fs from "fs";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
test.describe.configure({ mode: "parallel" });
|
||||
|
||||
@@ -79,16 +79,11 @@ test.describe("Pipeline testcases", () => {
|
||||
await expect.poll(async () => (await search).status()).toBe(200);
|
||||
// await search.hits.FIXME_should("be.an", "array");
|
||||
}
|
||||
// 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);
|
||||
|
||||
|
||||
// ("ingests logs via API", () => {
|
||||
const orgId = process.env["ORGNAME"];
|
||||
@@ -192,7 +187,7 @@ test.describe("Pipeline testcases", () => {
|
||||
await page.waitForTimeout(1000);
|
||||
await pipelinePage.selectStreamOption();
|
||||
await pipelinePage.saveInputNodeStream();
|
||||
await page.locator('button').filter({ hasText: 'delete' }).nth(1).click();
|
||||
await page.locator("button").filter({ hasText: "delete" }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
|
||||
// Generate a random pipeline name and save
|
||||
@@ -224,7 +219,7 @@ test.describe("Pipeline testcases", () => {
|
||||
await page.waitForTimeout(2000);
|
||||
await pipelinePage.selectStreamOption();
|
||||
await pipelinePage.saveInputNodeStream();
|
||||
await page.locator('button').filter({ hasText: 'delete' }).nth(1).click();
|
||||
await page.locator("button").filter({ hasText: "delete" }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
|
||||
// Delete the pipeline and confirm
|
||||
@@ -251,10 +246,10 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.selectStreamOption();
|
||||
await pipelinePage.saveInputNodeStream();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.locator('button').filter({ hasText: 'delete' }).nth(1).click();
|
||||
await page.locator("button").filter({ hasText: "delete" }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
await page.locator('button').filter({ hasText: 'edit' }).hover();
|
||||
await page.getByRole('img', { name: 'Output Stream' }).click();
|
||||
await page.locator("button").filter({ hasText: "edit" }).hover();
|
||||
await page.getByRole("img", { name: "Output Stream" }).click();
|
||||
await pipelinePage.toggleCreateStream();
|
||||
await page.getByLabel("Name *").click();
|
||||
await page.getByLabel("Name *").fill("destination-node");
|
||||
@@ -352,10 +347,10 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.saveInputNodeStream();
|
||||
// await pipelinePage.selectAndDragFunction(); // Function drag
|
||||
await page.waitForTimeout(2000);
|
||||
await page.locator('button').filter({ hasText: 'delete' }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click()
|
||||
await page.locator('button').filter({ hasText: 'edit' }).hover();
|
||||
await page.getByRole('img', { name: 'Function',exact: true }).click();
|
||||
await page.locator("button").filter({ hasText: "delete" }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
await page.locator("button").filter({ hasText: "edit" }).hover();
|
||||
await page.getByRole("img", { name: "Function", exact: true }).click();
|
||||
await pipelinePage.toggleCreateFunction();
|
||||
await pipelinePage.enterFunctionName(randomFunctionName);
|
||||
await page.locator(".view-lines").click();
|
||||
@@ -376,8 +371,8 @@ test.describe("Pipeline testcases", () => {
|
||||
await page.waitForTimeout(3000);
|
||||
await pipelinePage.saveFunction();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByRole('button', { name: randomFunctionName }).hover();
|
||||
await page.getByRole('img', { name: 'Output Stream' }).click();
|
||||
await page.getByRole("button", { name: randomFunctionName }).hover();
|
||||
await page.getByRole("img", { name: "Output Stream" }).click();
|
||||
await pipelinePage.toggleCreateStream();
|
||||
await page.getByLabel("Name *").click();
|
||||
await page.getByLabel("Name *").fill("destination-node");
|
||||
@@ -407,7 +402,6 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.verifyPipelineDeleted();
|
||||
});
|
||||
|
||||
|
||||
test("should display error when function name is not added", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -421,8 +415,7 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.toggleCreateFunction();
|
||||
await page.waitForTimeout(1000);
|
||||
await pipelinePage.saveFunction();
|
||||
await pipelinePage. assertFunctionNameRequiredErrorVisible()
|
||||
|
||||
await pipelinePage.assertFunctionNameRequiredErrorVisible();
|
||||
});
|
||||
|
||||
test("should display error when function name added but function is not added", async ({
|
||||
@@ -439,11 +432,12 @@ test.describe("Pipeline testcases", () => {
|
||||
await page.waitForTimeout(1000);
|
||||
await pipelinePage.enterFunctionName(randomFunctionName);
|
||||
await pipelinePage.saveFunction();
|
||||
await pipelinePage.assertFunctionRequiredErrorVisible()
|
||||
await pipelinePage.assertFunctionRequiredErrorVisible();
|
||||
});
|
||||
|
||||
|
||||
test.skip("should display error if query added without sql", async ({ page }) => {
|
||||
test.skip("should display error if query added without sql", async ({
|
||||
page,
|
||||
}) => {
|
||||
const pipelinePage = new PipelinePage(page);
|
||||
|
||||
// Open the pipeline menu and wait for a moment
|
||||
@@ -459,12 +453,9 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.saveQuery();
|
||||
await page.waitForTimeout(2000);
|
||||
// TODO: Change the locator to the correct one, once fixed
|
||||
await page.getByText('Invalid SQL Query').click()
|
||||
|
||||
await page.getByText("Invalid SQL Query").click();
|
||||
});
|
||||
|
||||
|
||||
|
||||
test("should display error when save clicked directly while adding destination", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -476,7 +467,7 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.selectAndDragSecondStream();
|
||||
await page.waitForTimeout(2000);
|
||||
await pipelinePage.saveStream();
|
||||
await pipelinePage.assertStreamSelectionErrorVisible()
|
||||
await pipelinePage.assertStreamSelectionErrorVisible();
|
||||
});
|
||||
|
||||
test("should add source, condition & destination node and then delete the pipeline", async ({
|
||||
@@ -498,21 +489,29 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.selectStreamOption();
|
||||
await pipelinePage.saveInputNodeStream();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.locator('button').filter({ hasText: 'delete' }).nth(1).click();
|
||||
await page.locator("button").filter({ hasText: "delete" }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
await page.locator('button').filter({ hasText: 'edit' }).hover();
|
||||
await page.getByRole('img', { name: 'Stream',exact: true }).click();
|
||||
await page.getByPlaceholder('Column').click();
|
||||
await page.getByPlaceholder('Column').fill('container_name');
|
||||
await page.getByRole('option', { name: 'kubernetes_container_name' }).click();
|
||||
await page.locator('div:nth-child(2) > div:nth-child(2) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native').click();
|
||||
await page.getByText('Contains', { exact: true }).click();
|
||||
await page.getByPlaceholder('Value').click();
|
||||
await page.getByPlaceholder('Value').fill('prometheus');
|
||||
await pipelinePage.saveCondition()
|
||||
await page.locator("button").filter({ hasText: "edit" }).hover();
|
||||
await page.getByRole("img", { name: "Stream", exact: true }).click();
|
||||
await page.getByPlaceholder("Column").click();
|
||||
await page.getByPlaceholder("Column").fill("container_name");
|
||||
await page
|
||||
.getByRole("option", { name: "kubernetes_container_name" })
|
||||
.click();
|
||||
await page
|
||||
.locator(
|
||||
"div:nth-child(2) > div:nth-child(2) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native"
|
||||
)
|
||||
.click();
|
||||
await page.getByText("Contains", { exact: true }).click();
|
||||
await page.getByPlaceholder("Value").click();
|
||||
await page.getByPlaceholder("Value").fill("prometheus");
|
||||
await pipelinePage.saveCondition();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByRole('button', { name: 'kubernetes_container_name' }).hover();
|
||||
await page.getByRole('img', { name: 'Output Stream' }).click();
|
||||
await page
|
||||
.getByRole("button", { name: "kubernetes_container_name" })
|
||||
.hover();
|
||||
await page.getByRole("img", { name: "Output Stream" }).click();
|
||||
await pipelinePage.toggleCreateStream();
|
||||
await page.getByLabel("Name *").click();
|
||||
await page.getByLabel("Name *").fill("destination-node");
|
||||
@@ -543,7 +542,6 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.verifyPipelineDeleted();
|
||||
});
|
||||
|
||||
|
||||
test("should display error when function is not selected under select function", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -558,7 +556,6 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.verifyFieldRequiredError();
|
||||
});
|
||||
|
||||
|
||||
test("should display error when condition is not added but user clicks save", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -566,13 +563,12 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.openPipelineMenu();
|
||||
await page.waitForTimeout(1000);
|
||||
await pipelinePage.addPipeline();
|
||||
await pipelinePage.selectAndDragCondition() // Function drag;
|
||||
await pipelinePage.selectAndDragCondition(); // Function drag;
|
||||
await page.waitForTimeout(1000);
|
||||
await pipelinePage.saveCondition()
|
||||
await pipelinePage.saveCondition();
|
||||
await pipelinePage.verifyFieldRequiredError();
|
||||
});
|
||||
|
||||
|
||||
test("should add source & destination node without connection and error to be displayed", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -592,7 +588,7 @@ test.describe("Pipeline testcases", () => {
|
||||
await pipelinePage.selectStreamOption();
|
||||
await pipelinePage.saveInputNodeStream();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('button').filter({ hasText: 'delete' }).nth(1).click();
|
||||
await page.locator("button").filter({ hasText: "delete" }).nth(1).click();
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
await pipelinePage.dragStreamToTarget(pipelinePage.streamButton); // First stream drag
|
||||
|
||||
@@ -617,60 +613,211 @@ test.describe("Pipeline testcases", () => {
|
||||
const pipelineName = `pipeline-${Math.random().toString(36).substring(7)}`;
|
||||
await pipelinePage.enterPipelineName(pipelineName);
|
||||
await pipelinePage.savePipeline();
|
||||
await page.getByText('Please connect all nodes').click();
|
||||
|
||||
await page.getByText("Please connect all nodes").click();
|
||||
});
|
||||
|
||||
test('should upload an enrichment table under functions', async ({ page }) => {
|
||||
await page.locator('[data-test="menu-link-\\/pipeline-item"]').click();
|
||||
|
||||
// Click the enrichment table tab
|
||||
await page.click('[data-test="function-enrichment-table-tab"] > .q-tab__content > .q-tab__label', { force: true });
|
||||
|
||||
// Click on 'Add Enrichment Table'
|
||||
await page.getByText('Add Enrichment Table').click();
|
||||
|
||||
// Generate a unique file name
|
||||
const fileName = `enrichment_info_${uuidv4()}.csv`;
|
||||
const fileContent = '../test-data/enrichment_info.csv';
|
||||
test("should upload an enrichment table under functions", async ({
|
||||
page,
|
||||
}) => {
|
||||
const pipelinePage = new PipelinePage(page);
|
||||
await pipelinePage.navigateToAddEnrichmentTable();
|
||||
|
||||
// Generate a unique file name and replace hyphens with underscores
|
||||
let fileName = `enrichment_info_${uuidv4()}_csv`.replace(/-/g, "_");
|
||||
console.log("Generated File Name:", fileName);
|
||||
|
||||
// Set the file to be uploaded
|
||||
const fileContentPath = "../test-data/enrichment_info.csv";
|
||||
const inputFile = await page.locator('input[type="file"]');
|
||||
await inputFile.setInputFiles(fileContent);
|
||||
|
||||
// Wait for the upload to process
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await inputFile.setInputFiles(fileContentPath);
|
||||
|
||||
// Enter the file name
|
||||
await page.fill('.q-input > .q-field__inner > .q-field__control', fileName);
|
||||
|
||||
await page.fill(".q-input > .q-field__inner > .q-field__control", fileName);
|
||||
|
||||
// Click on 'Save'
|
||||
await page.getByText('Save').click({ force: true });
|
||||
await page.waitForTimeout(5000);
|
||||
await page.getByRole('button', { name: 'Explore' }).nth(1).click();
|
||||
await page.getByText("Save").click({ force: true });
|
||||
|
||||
// Wait for the process to complete
|
||||
await page.reload();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByPlaceholder("Search Enrichment Table").fill(fileName);
|
||||
await page.waitForTimeout(3000);
|
||||
// Explore the uploaded table
|
||||
await page.getByRole("button", { name: "Explore" }).click();
|
||||
await page.locator('[data-test="log-table-column-0-_timestamp"]').click();
|
||||
await page.locator('[data-test="close-dialog"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Return to the pipeline menu and verify the uploaded table
|
||||
await page.locator('[data-test="menu-link-\\/pipeline-item"]').click();
|
||||
await page.locator('[data-test="function-enrichment-table-tab"]').click();
|
||||
|
||||
|
||||
// Locate rows in the table
|
||||
const rows = await page.locator('tbody tr');
|
||||
|
||||
// Iterate through each row to find and delete the function
|
||||
for (let i = 0; i < await rows.count(); i++) {
|
||||
const row = rows.nth(i);
|
||||
const functionName = await row.locator('td.text-left').nth(1).textContent();
|
||||
|
||||
if (functionName?.includes('enrichment_info')) {
|
||||
// Click the 'Delete Function' button
|
||||
await row.locator('[title="Delete Function"]').click();
|
||||
|
||||
// Handle the confirmation dialog
|
||||
await page.locator('[data-test="confirm-button"]').click();
|
||||
}
|
||||
}
|
||||
// Verify and delete enrichment tables
|
||||
await pipelinePage.deleteEnrichmentTableByName(fileName)
|
||||
});
|
||||
|
||||
});
|
||||
test.skip("should upload an enrichment table under functions with VRL", async ({
|
||||
page,
|
||||
}) => {
|
||||
const pipelinePage = new PipelinePage(page);
|
||||
await pipelinePage.navigateToAddEnrichmentTable();
|
||||
|
||||
// Generate a unique file name
|
||||
let fileName = `protocols_${uuidv4()}_csv`;
|
||||
console.log("Generated File Name:", fileName);
|
||||
fileName = fileName.replace(/-/g, "_");
|
||||
|
||||
// Set the file to be uploaded
|
||||
const fileContentPath = "../test-data/protocols.csv";
|
||||
const inputFile = await page.locator('input[type="file"]');
|
||||
await inputFile.setInputFiles(fileContentPath);
|
||||
|
||||
// Enter the file name
|
||||
await page.fill(".q-input > .q-field__inner > .q-field__control", fileName);
|
||||
|
||||
// Click on 'Save'
|
||||
await page.getByText("Save").click({ force: true });
|
||||
|
||||
// Reload the page to ensure table is updated
|
||||
await page.reload();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Search for the uploaded file name
|
||||
await page.getByPlaceholder("Search Enrichment Table").fill(fileName);
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Verify the file name in the enrichment table
|
||||
const rows = await page.locator("tbody tr");
|
||||
let fileFound = false;
|
||||
|
||||
for (let i = 0; i < (await rows.count()); i++) {
|
||||
const row = rows.nth(i);
|
||||
const displayedName = await row
|
||||
.locator("td.text-left")
|
||||
.nth(1)
|
||||
.textContent();
|
||||
if (displayedName?.trim() === fileName) {
|
||||
fileFound = true;
|
||||
console.log("File found in table:", displayedName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileFound) {
|
||||
throw new Error(`File name "${fileName}" not found in the table.`);
|
||||
}
|
||||
|
||||
// Explore the file
|
||||
await page.getByRole("button", { name: "Explore" }).click();
|
||||
await page.locator("#fnEditor").getByLabel("Editor content;Press Alt+F1")
|
||||
.fill(`
|
||||
abc, err = get_enrichment_table_record("${fileName}", {
|
||||
"protocol_number": to_string!(.protocol_number)
|
||||
})
|
||||
.protocol_keyword = abc.keyword
|
||||
`);
|
||||
|
||||
// Wait briefly to allow input processing
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Apply the query
|
||||
await applyQueryButton(page);
|
||||
|
||||
// Verify that no warning is shown for query execution
|
||||
const warningElement = page.locator("text=warning Query execution");
|
||||
await expect(warningElement).toBeHidden();
|
||||
|
||||
// Expand the first row in the logs table
|
||||
await page.waitForTimeout(3000);
|
||||
await page
|
||||
.locator(
|
||||
'[data-test="log-table-column-0-_timestamp"] [data-test="table-row-expand-menu"]'
|
||||
)
|
||||
.click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
.locator('[data-test="log-expand-detail-key-protocol_keyword-text"]')
|
||||
.click();
|
||||
// Return to the pipeline menu and delete the uploaded table
|
||||
await page.locator('[data-test="menu-link-\\/pipeline-item"]').click();
|
||||
await page.locator('[data-test="function-enrichment-table-tab"]').click();
|
||||
await pipelinePage.deleteEnrichmentTableByName(fileName)
|
||||
|
||||
});
|
||||
|
||||
|
||||
test("should display error when CSV not added in enrichment table", async ({
|
||||
page,
|
||||
}) => {
|
||||
const pipelinePage = new PipelinePage(page);
|
||||
await pipelinePage.navigateToAddEnrichmentTable();
|
||||
await page.getByLabel('Name').fill('test')
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await page.getByText('CSV File is required!').click();
|
||||
})
|
||||
|
||||
|
||||
test("should append an enrichment table under functions", async ({ page }) => {
|
||||
const pipelinePage = new PipelinePage(page);
|
||||
await pipelinePage.navigateToAddEnrichmentTable();
|
||||
|
||||
// Generate a unique file name and replace hyphens with underscores
|
||||
let fileName = `append_${uuidv4()}_csv`.replace(/-/g, "_");
|
||||
console.log("Generated File Name:", fileName);
|
||||
|
||||
// First upload step
|
||||
const fileContentPath = "../test-data/append.csv";
|
||||
const inputFile = await page.locator('input[type="file"]');
|
||||
await inputFile.setInputFiles(fileContentPath);
|
||||
|
||||
// Enter the file name
|
||||
await page.fill(".q-input > .q-field__inner > .q-field__control", fileName);
|
||||
|
||||
// Click on 'Save'
|
||||
await page.getByText("Save").click({ force: true });
|
||||
|
||||
// Wait for the process to complete
|
||||
await page.reload();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByPlaceholder("Search Enrichment Table").fill(fileName);
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Explore the uploaded table
|
||||
await page.getByRole("button", { name: "Explore" }).click();
|
||||
await page.locator('[data-test="log-table-column-0-_timestamp"]').click();
|
||||
await page.locator('[data-test="close-dialog"]').click();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Navigate to append data to the existing enrichment table
|
||||
await page.locator('[data-test="menu-link-\\/pipeline-item"]').click();
|
||||
await page.locator('[data-test="function-enrichment-table-tab"]').click();
|
||||
await page.getByPlaceholder("Search Enrichment Table").fill(fileName);
|
||||
await page.getByRole("button", { name: "Enrichment Tables" }).click();
|
||||
|
||||
// Select the append toggle
|
||||
await page.getByLabel("Append data to existing").locator("div").first().click();
|
||||
|
||||
|
||||
// Upload the CSV again for appending
|
||||
await inputFile.setInputFiles(fileContentPath);
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await page.waitForTimeout(3000);
|
||||
await page.getByPlaceholder("Search Enrichment Table").fill(fileName);
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Explore the uploaded table
|
||||
await page.getByRole("button", { name: "Explore" }).click();
|
||||
|
||||
const showingText = page.getByText('Showing 1 to 2 out of 2');
|
||||
await expect(showingText).toBeVisible()
|
||||
|
||||
await page.locator('[data-test="menu-link-\\/pipeline-item"]').click();
|
||||
await page.locator('[data-test="function-enrichment-table-tab"]').click();
|
||||
await page.getByPlaceholder("Search Enrichment Table").fill(fileName);
|
||||
await pipelinePage.deleteEnrichmentTableByName(fileName)
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user