@@ -2,6 +2,7 @@ import {expect, test} from '@playwright/test';
22
33import { backend } from '../../utils/constants' ;
44import { NodesPage } from '../nodes/NodesPage' ;
5+ import { NodePage } from '../nodes/NodePage' ;
56import { ClusterNodesTable } from '../paginatedTable/paginatedTable' ;
67
78test . describe ( 'Test Nodes page' , async ( ) => {
@@ -193,3 +194,153 @@ test.describe('Test Nodes Paginated Table', async () => {
193194 expect ( hostValues . length ) . toBeGreaterThan ( 0 ) ;
194195 } ) ;
195196} ) ;
197+
198+ test . describe ( 'Test Node Page Threads Tab' , async ( ) => {
199+ test ( 'Threads tab is hidden when node has no thread data' , async ( { page} ) => {
200+ // Mock the node API to return no thread data
201+ await page . route ( `${ backend } /viewer/json/sysinfo?*` , async ( route ) => {
202+ await route . fulfill ( {
203+ json : {
204+ SystemStateInfo : [ {
205+ Host : 'localhost' ,
206+ NodeId : 1 ,
207+ SystemState : 1 , // Green
208+ Version : 'test-version' ,
209+ } ] ,
210+ // No Threads property
211+ }
212+ } ) ;
213+ } ) ;
214+
215+ const nodesPage = new NodesPage ( page ) ;
216+ await nodesPage . goto ( ) ;
217+
218+ // Get first node ID to navigate to
219+ const paginatedTable = new ClusterNodesTable ( page ) ;
220+ await paginatedTable . waitForTableToLoad ( ) ;
221+ await paginatedTable . waitForTableData ( ) ;
222+
223+ // Click on first node to navigate to node page
224+ const firstRowLink = page . locator ( '.ydb-paginated-table__table tbody tr:first-child a' ) . first ( ) ;
225+ await firstRowLink . click ( ) ;
226+
227+ // Wait for navigation to complete
228+ await page . waitForURL ( / \/ n o d e \/ \d + / ) ;
229+
230+ const nodeId = await page . url ( ) . match ( / \/ n o d e \/ ( \d + ) / ) ?. [ 1 ] ;
231+ expect ( nodeId ) . toBeDefined ( ) ;
232+
233+ const nodePage = new NodePage ( page , nodeId ! ) ;
234+ await nodePage . waitForNodePageLoad ( ) ;
235+
236+ // Verify threads tab is not visible
237+ const isThreadsTabVisible = await nodePage . isThreadsTabVisible ( ) ;
238+ expect ( isThreadsTabVisible ) . toBe ( false ) ;
239+
240+ // Verify other tabs are still visible
241+ const tabNames = await nodePage . getAllTabNames ( ) ;
242+ expect ( tabNames ) . toContain ( 'Tablets' ) ;
243+ expect ( tabNames ) . not . toContain ( 'Threads' ) ;
244+ } ) ;
245+
246+ test ( 'Threads tab is visible when node has thread data' , async ( { page} ) => {
247+ // Mock the node API to return thread data
248+ await page . route ( `${ backend } /viewer/json/sysinfo?*` , async ( route ) => {
249+ await route . fulfill ( {
250+ json : {
251+ SystemStateInfo : [ {
252+ Host : 'localhost' ,
253+ NodeId : 1 ,
254+ SystemState : 1 , // Green
255+ Version : 'test-version' ,
256+ } ] ,
257+ Threads : [ {
258+ Name : 'TestPool' ,
259+ Threads : 4
260+ } ]
261+ }
262+ } ) ;
263+ } ) ;
264+
265+ const nodesPage = new NodesPage ( page ) ;
266+ await nodesPage . goto ( ) ;
267+
268+ // Get first node ID to navigate to
269+ const paginatedTable = new ClusterNodesTable ( page ) ;
270+ await paginatedTable . waitForTableToLoad ( ) ;
271+ await paginatedTable . waitForTableData ( ) ;
272+
273+ // Click on first node to navigate to node page
274+ const firstRowLink = page . locator ( '.ydb-paginated-table__table tbody tr:first-child a' ) . first ( ) ;
275+ await firstRowLink . click ( ) ;
276+
277+ // Wait for navigation to complete
278+ await page . waitForURL ( / \/ n o d e \/ \d + / ) ;
279+
280+ const nodeId = await page . url ( ) . match ( / \/ n o d e \/ ( \d + ) / ) ?. [ 1 ] ;
281+ expect ( nodeId ) . toBeDefined ( ) ;
282+
283+ const nodePage = new NodePage ( page , nodeId ! ) ;
284+ await nodePage . waitForNodePageLoad ( ) ;
285+
286+ // Verify threads tab is visible
287+ const isThreadsTabVisible = await nodePage . isThreadsTabVisible ( ) ;
288+ expect ( isThreadsTabVisible ) . toBe ( true ) ;
289+
290+ // Verify can click on threads tab
291+ await nodePage . clickThreadsTab ( ) ;
292+ await page . waitForURL ( / \/ n o d e \/ \d + \/ t h r e a d s / ) ;
293+
294+ // Verify other tabs are also visible
295+ const tabNames = await nodePage . getAllTabNames ( ) ;
296+ expect ( tabNames ) . toContain ( 'Tablets' ) ;
297+ expect ( tabNames ) . toContain ( 'Threads' ) ;
298+ } ) ;
299+
300+ test ( 'Threads tab is hidden when node has empty thread array' , async ( { page} ) => {
301+ // Mock the node API to return empty thread data
302+ await page . route ( `${ backend } /viewer/json/sysinfo?*` , async ( route ) => {
303+ await route . fulfill ( {
304+ json : {
305+ SystemStateInfo : [ {
306+ Host : 'localhost' ,
307+ NodeId : 1 ,
308+ SystemState : 1 , // Green
309+ Version : 'test-version' ,
310+ } ] ,
311+ Threads : [ ] // Empty array
312+ }
313+ } ) ;
314+ } ) ;
315+
316+ const nodesPage = new NodesPage ( page ) ;
317+ await nodesPage . goto ( ) ;
318+
319+ // Get first node ID to navigate to
320+ const paginatedTable = new ClusterNodesTable ( page ) ;
321+ await paginatedTable . waitForTableToLoad ( ) ;
322+ await paginatedTable . waitForTableData ( ) ;
323+
324+ // Click on first node to navigate to node page
325+ const firstRowLink = page . locator ( '.ydb-paginated-table__table tbody tr:first-child a' ) . first ( ) ;
326+ await firstRowLink . click ( ) ;
327+
328+ // Wait for navigation to complete
329+ await page . waitForURL ( / \/ n o d e \/ \d + / ) ;
330+
331+ const nodeId = await page . url ( ) . match ( / \/ n o d e \/ ( \d + ) / ) ?. [ 1 ] ;
332+ expect ( nodeId ) . toBeDefined ( ) ;
333+
334+ const nodePage = new NodePage ( page , nodeId ! ) ;
335+ await nodePage . waitForNodePageLoad ( ) ;
336+
337+ // Verify threads tab is not visible
338+ const isThreadsTabVisible = await nodePage . isThreadsTabVisible ( ) ;
339+ expect ( isThreadsTabVisible ) . toBe ( false ) ;
340+
341+ // Verify other tabs are still visible
342+ const tabNames = await nodePage . getAllTabNames ( ) ;
343+ expect ( tabNames ) . toContain ( 'Tablets' ) ;
344+ expect ( tabNames ) . not . toContain ( 'Threads' ) ;
345+ } ) ;
346+ } ) ;
0 commit comments