Files
Shrinath RaoandClaude Opus 4.5 660dfbabaf test: Dashboard Joins and Nested Functions e2e tests (#9685)
### **PR Type**
Tests, Enhancement

---

### **Description**

This PR adds comprehensive E2E tests for Dashboard Joins and Dashboard
Functions features, along with supporting page object helpers.

#### Key Changes:
- **Dashboard Joins Tests**: 8 consolidated multi-panel tests covering
INNER/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 join
types, streams, conditions, and operators
- **Enhanced `ChartTypeSelector`**: Added Y-axis function configuration
methods 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-way
join, 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_id
fields | `@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, navigate
away, reload, verify join config persisted | `@dashboard-joins`,
`@dashboard-joins-persistence`, `@P2` |
| 8 | Error Handling & Recovery | 1 | Incomplete join handling, recovery
from 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, SUM
functions | `@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 displays
correctly |

#### `ChartTypeSelector` (`dashboard-chart.js`)
| Method | Description |
|--------|-------------|
| `selectStream(name, retries)` | Select stream with retry mechanism |
| `configureYAxisFunction(alias, func)` | Configure Y-axis aggregation
function |
| `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 and
score 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 dashboard
creation 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">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>5
files</summary><table>
<tr>
<td><strong>dashboard-chart.js</strong><dd><code>Enhance stream
selection and add Y-axis function methods</code>&nbsp; </dd></td>
<td><a
href="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 panel
addition for empty and existing dashboards</code></dd></td>
<td><a
href="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 for
configuring and validating joins</code>&nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="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><a
href="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 in
login navigation URL</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="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>6
files</summary><table>
<tr>
<td><strong>dashboard-join.spec.js</strong><dd><code>Consolidated
dashboard joins feature E2E tests</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="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-panel
dashboard functions E2E tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; </dd></td>
<td><a
href="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 for
dashboard functions tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="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 for
dashboard joins tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></td>
<td><a
href="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 for
dashboard joins tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></td>
<td><a
href="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 request
data for dashboard joins tests</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td>
<td><a
href="https://github.com/openobserve/openobserve/pull/9685/files#diff-1c4b00b1929e9a01de1cb8129161c49dc1563a5dde1c4b5e770a307245155382">+14/-0</a>&nbsp;
&nbsp; </td>
</tr>
</table></details></td></tr><tr><td><strong>Configuration
changes</strong></td><td><details><summary>1 files</summary><table>
<tr>
<td><strong>cleanup.spec.js</strong><dd><code>Extend cleanup regex for
join and function test streams</code>&nbsp; &nbsp; </dd></td>
<td><a
href="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>
2025-12-19 07:30:12 +05:30

15 lines
1.9 KiB
JSON

[
{"request_id": "R001", "user_id": "U001", "session_id": "S001", "method": "GET", "path": "/dashboard", "status": 200, "response_time_ms": 120, "bytes": 4500},
{"request_id": "R002", "user_id": "U001", "session_id": "S001", "method": "POST", "path": "/api/data", "status": 201, "response_time_ms": 350, "bytes": 1200},
{"request_id": "R003", "user_id": "U002", "session_id": "S003", "method": "GET", "path": "/profile", "status": 200, "response_time_ms": 80, "bytes": 3200},
{"request_id": "R004", "user_id": "U003", "session_id": "S004", "method": "GET", "path": "/settings", "status": 200, "response_time_ms": 95, "bytes": 2800},
{"request_id": "R005", "user_id": "U003", "session_id": "S004", "method": "PUT", "path": "/api/settings", "status": 500, "response_time_ms": 2500, "bytes": 500},
{"request_id": "R006", "user_id": "U004", "session_id": "S005", "method": "GET", "path": "/admin", "status": 200, "response_time_ms": 150, "bytes": 8000},
{"request_id": "R007", "user_id": "U004", "session_id": "S005", "method": "DELETE", "path": "/api/users/123", "status": 204, "response_time_ms": 200, "bytes": 0},
{"request_id": "R008", "user_id": "U005", "session_id": "S006", "method": "GET", "path": "/home", "status": 200, "response_time_ms": 60, "bytes": 2500},
{"request_id": "R009", "user_id": "U001", "session_id": "S007", "method": "GET", "path": "/reports", "status": 403, "response_time_ms": 45, "bytes": 800},
{"request_id": "R010", "user_id": "U999", "session_id": "S008", "method": "GET", "path": "/login", "status": 401, "response_time_ms": 30, "bytes": 600},
{"request_id": "R011", "user_id": "U002", "session_id": "S003", "method": "POST", "path": "/api/upload", "status": 413, "response_time_ms": 100, "bytes": 200},
{"request_id": "R012", "user_id": "U001", "session_id": "S002", "method": "GET", "path": "/mobile/home", "status": 200, "response_time_ms": 180, "bytes": 1800}
]