Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit660dfba

Browse files
test: Dashboard Joins and Nested Functions e2e tests (#9685)
### **PR Type**Tests, Enhancement---### **Description**This PR adds comprehensive E2E tests for Dashboard Joins and DashboardFunctions features, along with supporting page object helpers.#### Key Changes:- **Dashboard Joins Tests**: 8 consolidated multi-panel tests coveringINNER/LEFT/RIGHT joins, conditions, aggregations, field selection,filters, dynamic operations, persistence, and error handling- **Dashboard Functions Tests**: 2 multi-panel tests covering basic(COUNT, COUNT-DISTINCT, AVG, SUM) and advanced (Multiple Y-axis, MIN,MAX) aggregation functions- **New `JoinHelper` class**: Provides methods for configuring jointypes, streams, conditions, and operators- **Enhanced `ChartTypeSelector`**: Added Y-axis function configurationmethods and stream selection with retry mechanism- **Org Context Fix**: Navigate directly to dashboards with`org_identifier` parameter to ensure correct API context---### **Test Coverage**#### Dashboard Joins Tests (`dashboard-join.spec.js`) - 8 Tests| # | Test Name | Panels | Coverage | Tags ||---|-----------|--------|----------|------|| 1 | Core Join Types - INNER, LEFT, RIGHT | 3 | INNER JOIN (11 rows),LEFT JOIN (12 rows), RIGHT JOIN (5 rows) | `@dashboard-joins`, `@smoke`,`@P0` || 2 | Join Conditions & Multi-Join | 3 | Multiple AND conditions, 3-wayjoin, OR conditions | `@dashboard-joins`, `@dashboard-joins-conditions`,`@P1` || 3 | Aggregation Functions | 4 | Basic aggregation, SUM-like grouping,AVG-like grouping, COUNT grouping | `@dashboard-joins`,`@dashboard-joins-aggregation`, `@P1` || 4 | Field Selection | 4 | response_time_ms, country, bytes, request_idfields | `@dashboard-joins`, `@dashboard-joins-fields`, `@P2` || 5 | Filters & Edge Cases | 6 | Join with filter, LEFT JOIN with NULLs,session duration, not-equal (!=), greater-than (>), self-join |`@dashboard-joins`, `@dashboard-joins-filters`, `@P2` || 6 | Dynamic Join Operations & UI Validation | 1 | Add/remove joins,change join types, modify conditions | `@dashboard-joins`,`@dashboard-joins-dynamic`, `@P2` || 7 | Persistence - Save and Reload Dashboard | 1 | Save panel, navigateaway, reload, verify join config persisted | `@dashboard-joins`,`@dashboard-joins-persistence`, `@P2` || 8 | Error Handling & Recovery | 1 | Incomplete join handling, recoveryfrom invalid state | `@dashboard-joins`, `@dashboard-joins-errors`,`@P3` |#### Dashboard Functions Tests (`dashboard-nested-functions.spec.js`) -2 Tests| # | Test Name | Panels | Coverage | Tags ||---|-----------|--------|----------|------|| 1 | Basic Aggregation Functions | 4 | COUNT, COUNT-DISTINCT, AVG, SUMfunctions | `@dashboard-functions`, `@dashboard-functions-basic`, `@P1`|| 2 | Advanced Aggregation Functions | 2 | Multiple Y-axis (COUNT + SUM+ AVG), MIN + MAX functions | `@dashboard-functions`,`@dashboard-functions-advanced`, `@P2` |---### **New Page Object Methods**#### `JoinHelper` (`dashboard-joins.js`)| Method | Description ||--------|-------------|| `addJoin()` | Open add join popup || `selectJoinType(type)` | Select INNER/LEFT/RIGHT/FULL/CROSS join || `selectJoinStream(streamName)` | Select stream to join with || `selectLeftField(field)` | Select left side join field || `selectRightField(field)` | Select right side join field || `selectOperator(operator)` | Select =, !=, <, >, <=, >= operator || `addCondition()` | Add another join condition || `saveJoin()` | Save join configuration || `removeJoin(index)` | Remove a join by index || `verifyJoinChipVisible(stream, index)` | Verify join chip displayscorrectly |#### `ChartTypeSelector` (`dashboard-chart.js`)| Method | Description ||--------|-------------|| `selectStream(name, retries)` | Select stream with retry mechanism || `configureYAxisFunction(alias, func)` | Configure Y-axis aggregationfunction || `verifyYAxisLabel(alias, func)` | Verify Y-axis label shows function || `openYAxisFunctionPopup(alias)` | Open Y-axis configuration popup || `selectFunction(name)` | Select aggregation function from dropdown |#### `DashboardPanelActions` (`dashboard-panel-actions.js`)| Method | Description ||--------|-------------|| `addNextPanel()` | Add another panel after saving || `getTableRowCount()` | Get count of data rows in table || `verifyChartRenders(expect)` | Verify chart/table renders || `savePanel()` | Save panel with networkidle wait |---### **Test Data**Test data files located in `test-data/` directory:- `joins/test_app_users.json` - 5 user records- `joins/test_web_requests.json` - 12 web request records - `joins/test_sessions.json` - 8 session records- `dashboard-functions/test_records.json` - 7 records with user_name andscore fields---### **Fixes Included**| Issue | Fix ||-------|-----|| Org context mismatch on remote environments | Navigate to`/web/dashboards?org_identifier=${ORGNAME}` || Streams not appearing in dropdown | Page reload after dashboardcreation to refresh stream list || Save panel race condition | Added `waitForLoadState("networkidle")`after save click || Stream selection timing | Retry mechanism with debug logging || Test 5 timeout | Increased to 5 minutes for 6-panel test |---<details><summary><h3>File Walkthrough</h3></summary><table><thead><tr><th></th><th align="left">Relevantfiles</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>5files</summary><table><tr><td><strong>dashboard-chart.js</strong><dd><code>Enhance streamselection and add Y-axis function methods</code>&nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-573a312576fce62d8e14f2bbb5f9b7d9a552d746304dce3d79862edddd24de76">+106/-14</a></td></tr><tr><td><strong>dashboard-create.js</strong><dd><code>Add smart paneladdition for empty and existing dashboards</code></dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-c3c5add2b934580a91a79bb580634b70e2376b0452113008a0911102db3863e2">+25/-1</a>&nbsp;&nbsp; </td></tr><tr><td><strong>dashboard-joins.js</strong><dd><code>New JoinHelper forconfiguring and validating joins</code>&nbsp; &nbsp; &nbsp; &nbsp;</dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-f88eb0cf951ec45e97befde5c83a2c187bb46db3f6cb27bc0cb88d48c5f45b78">+351/-0</a>&nbsp;</td></tr><tr><td><strong>dashboard-panel-actions.js</strong><dd><code>Add next-panel,row count and chart render verifications</code>&nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-d29713fdcc11cbc93bda29da5261da389226cd718e4292a1c2cd96629f573a80">+76/-1</a>&nbsp;&nbsp; </td></tr><tr><td><strong>global-setup.js</strong><dd><code>Include org_identifier inlogin navigation URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-06323dad7214f86b41b62e121e716eeea0054bc4d950c6bcf4a0efe53894acc8">+4/-3</a>&nbsp;&nbsp; &nbsp; </td></tr></table></details></td></tr><tr><td><strong>Tests</strong></td><td><details><summary>6files</summary><table><tr><td><strong>dashboard-join.spec.js</strong><dd><code>Consolidateddashboard joins feature E2E tests</code>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-552f4ba6f199ade20dbab2c54b8573422fd644587ed1575262a7aa34f8041174">+1160/-0</a></td></tr><tr><td><strong>dashboard-nested-functions.spec.js</strong><dd><code>Multi-paneldashboard functions E2E tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-d2a9855da60f5fd3820832815036c368a680e2885033ad1a7a2bcbd060e2a750">+372/-0</a>&nbsp;</td></tr><tr><td><strong>test_records.json</strong><dd><code>Add test data fordashboard functions tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-3a09d97f4091ae2f4dc97ebc14199c5d94efb878a6ebfa7da686cad5450ddda0">+7/-0</a>&nbsp;&nbsp; &nbsp; </td></tr><tr><td><strong>test_app_users.json</strong><dd><code>Add user data fordashboard joins tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-7c5af3decd88c4f9031fd83282844872f4a0a65eea2b51a46aac849aa4a5c129">+7/-0</a>&nbsp;&nbsp; &nbsp; </td></tr><tr><td><strong>test_sessions.json</strong><dd><code>Add session data fordashboard joins tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-836e072600882ffa58662a4867ac17d2ce799dd338daac585203ccaa01275e3c">+10/-0</a>&nbsp;&nbsp; </td></tr><tr><td><strong>test_web_requests.json</strong><dd><code>Add web requestdata for dashboard joins tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-1c4b00b1929e9a01de1cb8129161c49dc1563a5dde1c4b5e770a307245155382">+14/-0</a>&nbsp;&nbsp; </td></tr></table></details></td></tr><tr><td><strong>Configurationchanges</strong></td><td><details><summary>1 files</summary><table><tr><td><strong>cleanup.spec.js</strong><dd><code>Extend cleanup regex forjoin and function test streams</code>&nbsp; &nbsp; </dd></td><td><ahref="https://github.com/openobserve/openobserve/pull/9685/files#diff-c214275a512fa285a7e4f2ab61dfcb42d71a0436b0e4241f94d7b45693587983">+8/-1</a>&nbsp;&nbsp; &nbsp; </td></tr></table></details></td></tr></tbody></table></details>------------Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent06ab605 commit660dfba

File tree

17 files changed

+2443
-22
lines changed

17 files changed

+2443
-22
lines changed

‎.claude/.clauderc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
- **Always run non-release builds**: Use `cargo build` without the `--release` flag for all builds
88
- **Never build the UI**: The UI is running in dev mode separately, so skip any `npm run build` or UI build steps
99
- **Use debug profile**: When running cargo commands (build, test, run, etc.), always use the debug/non-release profile
10-
- **Always check env file for anyenviornment variables**:/Users/ashishkolhe/Documents/github/openobserve/.env
10+
- **Always check env file for anyenvironment variables**: .env (in project root)
1111

1212
These instructions apply to all cargo operations unless explicitly told otherwise by the user.

‎.github/workflows/playwright.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ jobs:
179179
"dashboard-tabs-setting.spec.js",
180180
"dashboard-variables-setting.spec.js",
181181
"dashboard-transpose.spec.js",
182+
"dashboard-join.spec.js",
183+
"dashboard-nested-functions.spec.js",
182184
]
183185
-testfolder:"Dashboards-Charts"
184186
browser:"chrome"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{"user_id":1,"user_name":"Alice","email":"alice@test.com","score":85 },
3+
{"user_id":2,"user_name":"Bob","email":"bob@test.com","score":92 },
4+
{"user_id":3,"user_name":"Charlie","email":"charlie@test.com","score":78 },
5+
{"user_id":4,"user_name":"Diana","email":"diana@test.com","score":95 },
6+
{"user_id":5,"user_name":"Eve","email":"eve@test.com","score":88 }
7+
]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{"user_id":"U001","name":"Alice Johnson","email":"alice@example.com","plan":"premium","country":"USA","created_at":"2024-01-15"},
3+
{"user_id":"U002","name":"Bob Smith","email":"bob@example.com","plan":"free","country":"UK","created_at":"2024-02-20"},
4+
{"user_id":"U003","name":"Charlie Brown","email":"charlie@example.com","plan":"premium","country":"Canada","created_at":"2024-03-10"},
5+
{"user_id":"U004","name":"Diana Prince","email":"diana@example.com","plan":"enterprise","country":"USA","created_at":"2024-04-05"},
6+
{"user_id":"U005","name":"Eve Wilson","email":"eve@example.com","plan":"free","country":"Australia","created_at":"2024-05-12"}
7+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{"session_id":"S001","user_id":"U001","device":"desktop","browser":"Chrome","os":"Windows","duration_mins":45},
3+
{"session_id":"S002","user_id":"U001","device":"mobile","browser":"Safari","os":"iOS","duration_mins":12},
4+
{"session_id":"S003","user_id":"U002","device":"desktop","browser":"Firefox","os":"MacOS","duration_mins":30},
5+
{"session_id":"S004","user_id":"U003","device":"tablet","browser":"Chrome","os":"Android","duration_mins":22},
6+
{"session_id":"S005","user_id":"U004","device":"desktop","browser":"Edge","os":"Windows","duration_mins":60},
7+
{"session_id":"S006","user_id":"U005","device":"mobile","browser":"Chrome","os":"Android","duration_mins":8},
8+
{"session_id":"S007","user_id":"U001","device":"desktop","browser":"Chrome","os":"Windows","duration_mins":90},
9+
{"session_id":"S008","user_id":"U999","device":"desktop","browser":"Chrome","os":"Linux","duration_mins":5}
10+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{"request_id":"R001","user_id":"U001","session_id":"S001","method":"GET","path":"/dashboard","status":200,"response_time_ms":120,"bytes":4500},
3+
{"request_id":"R002","user_id":"U001","session_id":"S001","method":"POST","path":"/api/data","status":201,"response_time_ms":350,"bytes":1200},
4+
{"request_id":"R003","user_id":"U002","session_id":"S003","method":"GET","path":"/profile","status":200,"response_time_ms":80,"bytes":3200},
5+
{"request_id":"R004","user_id":"U003","session_id":"S004","method":"GET","path":"/settings","status":200,"response_time_ms":95,"bytes":2800},
6+
{"request_id":"R005","user_id":"U003","session_id":"S004","method":"PUT","path":"/api/settings","status":500,"response_time_ms":2500,"bytes":500},
7+
{"request_id":"R006","user_id":"U004","session_id":"S005","method":"GET","path":"/admin","status":200,"response_time_ms":150,"bytes":8000},
8+
{"request_id":"R007","user_id":"U004","session_id":"S005","method":"DELETE","path":"/api/users/123","status":204,"response_time_ms":200,"bytes":0},
9+
{"request_id":"R008","user_id":"U005","session_id":"S006","method":"GET","path":"/home","status":200,"response_time_ms":60,"bytes":2500},
10+
{"request_id":"R009","user_id":"U001","session_id":"S007","method":"GET","path":"/reports","status":403,"response_time_ms":45,"bytes":800},
11+
{"request_id":"R010","user_id":"U999","session_id":"S008","method":"GET","path":"/login","status":401,"response_time_ms":30,"bytes":600},
12+
{"request_id":"R011","user_id":"U002","session_id":"S003","method":"POST","path":"/api/upload","status":413,"response_time_ms":100,"bytes":200},
13+
{"request_id":"R012","user_id":"U001","session_id":"S002","method":"GET","path":"/mobile/home","status":200,"response_time_ms":180,"bytes":1800}
14+
]
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import{expect}from"playwright/test";
2+
importlogDatafrom"../../fixtures/log.json";
3+
consttestLogger=require('../../playwright-tests/utils/test-logger.js');
4+
5+
// Function to wait for the dashboard page to load
6+
exportconstwaitForDashboardPage=asyncfunction(page){
7+
// If already on the dashboard page, skip waiting for navigation
8+
if(!page.url().includes("/web/dashboards")){
9+
awaitpage.waitForURL(/\/web\/dashboards.*/,{timeout:30000});
10+
}
11+
12+
// Additional wait for page to stabilize
13+
awaitpage.waitForTimeout(1000);
14+
15+
// Wait for either the API response or the dashboard table to appear
16+
// Use Promise.race to succeed on whichever happens first
17+
try{
18+
awaitPromise.race([
19+
// Wait for API response
20+
page.waitForResponse(
21+
(response)=>
22+
/\/api\/.*\/dashboards/.test(response.url())&&
23+
response.status()===200,
24+
{timeout:30000}
25+
),
26+
// OR wait for dashboard table to be visible
27+
page.waitForSelector('[data-test="dashboard-table"]',{
28+
state:'visible',
29+
timeout:30000
30+
}),
31+
// OR wait for import button to be visible (in case we're on import page)
32+
page.waitForSelector('[data-test="dashboard-import"]',{
33+
state:'visible',
34+
timeout:30000
35+
}),
36+
]);
37+
}catch(err){
38+
// If all options fail, log the error but check if we're actually on the page
39+
testLogger.warn("Dashboard page load check failed, verifying page state",{error:err.message});
40+
41+
// Check if we're actually on the dashboard page by verifying URL
42+
if(page.url().includes("/web/dashboards")){
43+
testLogger.info("URL indicates we're on dashboard page, continuing");
44+
}else{
45+
thrownewError("Dashboard page did not load as expected: "+err.message);
46+
}
47+
}
48+
49+
// Final wait for stability
50+
awaitpage.waitForTimeout(1000);
51+
};
52+
53+
exportconstapplyQueryButton=asyncfunction(page){
54+
constsearch=page.waitForResponse(logData.applyQuery);
55+
awaitpage.waitForTimeout(3000);
56+
awaitpage.locator("[data-test='logs-search-bar-refresh-btn']").click({
57+
force:true,
58+
});
59+
awaitexpect.poll(async()=>(awaitsearch).status()).toBe(200);
60+
};
61+
62+
exportasyncfunctiondeleteDashboard(page,dashboardName){
63+
testLogger.info('Deleting dashboard',{ dashboardName});
64+
65+
// Wait for page to be fully loaded
66+
// Wait for either the Dashboard API or Folder API (whichever comes first)
67+
awaitPromise.race([
68+
page.waitForResponse(
69+
(response)=>{
70+
consturl=response.url();
71+
return(
72+
(/\/api\/.*\/dashboards/.test(url)||
73+
/\/api\/.*\/folders/.test(url))&&
74+
response.status()===200
75+
);
76+
},
77+
{timeout:20000}
78+
),
79+
page.waitForSelector('[data-test="dashboard-table"]',{timeout:20000}),
80+
]);
81+
82+
// const dashboardRow = page.locator(`//tr[.//td[text()="${dashboardName}"]]`);
83+
// await expect(dashboardRow).toBeVisible(); // Ensure the row is visible
84+
constdashboardRow=page
85+
.locator('//tr[.//div[@title="'+dashboardName+'"]]')
86+
.nth(0);
87+
88+
constdeleteButton=dashboardRow.locator('[data-test="dashboard-delete"]');
89+
awaitdeleteButton.click();
90+
91+
// Wait for the confirmation text to ensure dialog is fully rendered
92+
awaitpage.getByText('Are you sure you want to delete the dashboard?').waitFor({
93+
state:'visible',
94+
timeout:10000
95+
});
96+
97+
// Wait for button to be truly stable using waitForFunction
98+
awaitpage.waitForFunction(
99+
()=>{
100+
constdialog=document.querySelector('[data-test="dialog-box"]');
101+
if(!dialog)returnfalse;
102+
103+
// Find the confirm button with data-test attribute inside dialog
104+
constbutton=dialog.querySelector('[data-test="confirm-button"]');
105+
if(!button)returnfalse;
106+
107+
// Check if button is stable (has computed style and is not animating)
108+
constrect=button.getBoundingClientRect();
109+
constisStable=rect.width>0&&rect.height>0&&
110+
button.offsetParent!==null&&
111+
!button.disabled&&
112+
window.getComputedStyle(button).visibility==='visible';
113+
114+
returnisStable;
115+
},
116+
{timeout:15000,polling:100}
117+
);
118+
119+
testLogger.debug('Confirm button found and is stable');
120+
121+
// Additional small wait for any final animations
122+
awaitpage.waitForTimeout(500);
123+
124+
// Set up API listener BEFORE clicking
125+
constdeleteResponsePromise=page.waitForResponse(
126+
async(response)=>{
127+
consturl=response.url();
128+
constmethod=response.request().method();
129+
130+
// Check if this is a DELETE request to dashboards endpoint
131+
constisDeleteEndpoint=method==='DELETE'&&
132+
/\/api\/.*\/dashboards\/\d+/.test(url);
133+
134+
if(isDeleteEndpoint){
135+
testLogger.debug(`Delete API called:${url} - Status:${response.status()}`);
136+
137+
// Verify response body contains success message
138+
try{
139+
constbody=awaitresponse.json();
140+
if(body.code===200&&body.message==='Dashboard deleted'){
141+
testLogger.info('Delete API confirmed: Dashboard deleted');
142+
returntrue;
143+
}
144+
}catch(e){
145+
// If we can't parse JSON, just check status code
146+
returnresponse.status()===200||response.status()===204;
147+
}
148+
}
149+
150+
returnfalse;
151+
},
152+
{timeout:20000}
153+
).catch((error)=>{
154+
testLogger.warn(`Delete API timeout:${error.message}`);
155+
returnnull;// Return null if timeout, don't throw
156+
});
157+
158+
// Click the button using evaluate to avoid detachment issues
159+
awaitpage.evaluate(()=>{
160+
constdialog=document.querySelector('[data-test="dialog-box"]');
161+
constbutton=dialog?.querySelector('[data-test="confirm-button"]');
162+
if(button){
163+
button.click();
164+
}
165+
});
166+
167+
testLogger.info('Clicked confirm button using evaluate');
168+
169+
// Wait for API response
170+
constdeleteResponse=awaitdeleteResponsePromise;
171+
172+
if(deleteResponse){
173+
testLogger.info('Dashboard deleted successfully');
174+
}
175+
176+
// Verify the success message appears
177+
awaitpage.getByText("Dashboard deleted successfully").waitFor({
178+
state:'visible',
179+
timeout:10000
180+
}).catch(()=>{
181+
testLogger.info('Success message not visible or disappeared quickly');
182+
});
183+
184+
// Ensure the dashboard row is removed from the table
185+
// await expect(dashboardRow).not.toBeVisible({ timeout: 5000 });
186+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// ingestion.js
2+
importlogsdatafrom"../../test-data/logs_data.json";
3+
importgeoMapdatafrom"../../test-data/geo_map.json";
4+
importdashboardChartJsonDatafrom"../../test-data/dashboard_chart_json.json";
5+
// Using require() for testLogger as it exports via module.exports (CommonJS)
6+
consttestLogger=require('../../playwright-tests/utils/test-logger.js');
7+
8+
// Exported function to remove UTF characters
9+
constremoveUTFCharacters=(text)=>{
10+
// Remove UTF characters using regular expression
11+
returntext.replace(/[^\x00-\x7F]/g," ");
12+
};
13+
14+
// Function to retrieve authentication token (to be implemented securely)
15+
constgetAuthToken=async()=>{
16+
constbasicAuthCredentials=Buffer.from(
17+
`${process.env["ZO_ROOT_USER_EMAIL"]}:${process.env["ZO_ROOT_USER_PASSWORD"]}`
18+
).toString("base64");
19+
return`Basic${basicAuthCredentials}`;
20+
};
21+
22+
// Common ingestion helper - extracts shared logic for all ingestion functions
23+
constingestData=async(streamName,data,errorContext="Ingestion")=>{
24+
if(!process.env["ORGNAME"]||!process.env["INGESTION_URL"]){
25+
thrownewError("Required environment variables are not set");
26+
}
27+
28+
constorgId=process.env["ORGNAME"];
29+
30+
try{
31+
constheaders={
32+
"Content-Type":"application/json",
33+
Authorization:awaitgetAuthToken(),
34+
};
35+
36+
constfetchResponse=awaitfetch(
37+
`${process.env.INGESTION_URL}/api/${orgId}/${streamName}/_json`,
38+
{
39+
method:"POST",
40+
headers,
41+
body:JSON.stringify(data),
42+
}
43+
);
44+
45+
if(!fetchResponse.ok){
46+
constresponseText=awaitfetchResponse.text().catch(()=>'Unable to read response');
47+
thrownewError(
48+
`HTTP error! status:${fetchResponse.status}, response:${responseText}`
49+
);
50+
}
51+
52+
returnawaitfetchResponse.json();
53+
}catch(error){
54+
testLogger.error(`${errorContext} failed`,{ error});
55+
throwerror;
56+
}
57+
};
58+
59+
// page is passed here to access the page object (currently not used)
60+
exportconstingestion=async(page,streamName="e2e_automate")=>{
61+
returningestData(streamName,logsdata,"Ingestion");
62+
};
63+
64+
// Ingestion function for Geomap and Maps chart
65+
constingestionForMaps=async(page,streamName="geojson")=>{
66+
returningestData(streamName,geoMapdata,"Maps ingestion");
67+
};
68+
69+
// Ingestion function for Dashboard Chart JSON data
70+
constingestionForDashboardChartJson=async(page,streamName="kubernetes")=>{
71+
returningestData(streamName,dashboardChartJsonData,"Dashboard Chart JSON ingestion");
72+
};
73+
74+
// Export only the required functions
75+
export{ingestionForMaps,ingestionForDashboardChartJson,getAuthToken,removeUTFCharacters};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// dashLogin.js
2+
exportconstlogin=async(page)=>{
3+
awaitpage.goto(process.env["ZO_BASE_URL"],{waitUntil:"networkidle"});
4+
5+
if(awaitpage.getByText('Login as internal user').isVisible()){
6+
awaitpage.getByText('Login as internal user').click();
7+
}
8+
awaitpage.waitForSelector('[data-test="login-user-id"]',{timeout:10000});
9+
awaitpage
10+
.locator('[data-test="login-user-id"]')
11+
.fill(process.env["ZO_ROOT_USER_EMAIL"]);
12+
13+
constwaitForLogin=page.waitForResponse(
14+
(response)=>
15+
response.url().includes("/auth/login")&&response.status()===200
16+
);
17+
18+
awaitpage
19+
.locator('[data-test="login-password"]')
20+
.fill(process.env["ZO_ROOT_USER_PASSWORD"]);
21+
awaitpage.locator('[data-cy="login-sign-in"]').click();
22+
23+
awaitwaitForLogin;
24+
25+
awaitpage.waitForURL(process.env["ZO_BASE_URL"]+"/web/",{
26+
waitUntil:"networkidle",
27+
});
28+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp