mirror of
https://github.com/SigNoz/signoz.git
synced 2026-07-27 16:30:34 +01:00
Compare commits
11 Commits
nv/migrati
...
fix/tansta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95ed4d126a | ||
|
|
8b488a5f89 | ||
|
|
1785774a42 | ||
|
|
1210415e00 | ||
|
|
dc399e64dc | ||
|
|
972171493e | ||
|
|
94034a1c1c | ||
|
|
77e09040bf | ||
|
|
a63bc71c6b | ||
|
|
056e48a265 | ||
|
|
25cc65ace2 |
@@ -438,7 +438,11 @@ function LogDetailInner({
|
||||
destroyOnClose
|
||||
closeIcon={<X size={16} style={{ marginTop: Spacing.MARGIN_1 }} />}
|
||||
>
|
||||
<div className="log-detail-drawer__content" data-log-detail-ignore="true">
|
||||
<div
|
||||
className="log-detail-drawer__content"
|
||||
data-log-detail-ignore="true"
|
||||
data-testid="log-detail-drawer"
|
||||
>
|
||||
<div className="log-detail-drawer__log">
|
||||
<Divider type="vertical" className={cx('log-type-indicator', logType)} />
|
||||
<Tooltip
|
||||
|
||||
@@ -88,6 +88,7 @@ function TanStackCustomTableRow<TData, TItemKey = string>({
|
||||
{...props}
|
||||
className={rowClassName}
|
||||
style={rowStyle}
|
||||
data-testid={context?.getRowTestId?.(rowData)}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={clearHovered}
|
||||
>
|
||||
@@ -154,6 +155,12 @@ function areTableRowPropsEqual<TData, TItemKey = string>(
|
||||
return false;
|
||||
}
|
||||
|
||||
const prevTestId = prev.context?.getRowTestId?.(prevData) ?? '';
|
||||
const nextTestId = next.context?.getRowTestId?.(nextData) ?? '';
|
||||
if (prevTestId !== nextTestId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const prevStyle = prev.context?.getRowStyle?.(prevData);
|
||||
const nextStyle = next.context?.getRowStyle?.(nextData);
|
||||
if (prevStyle !== nextStyle) {
|
||||
|
||||
@@ -33,7 +33,6 @@ function TanStackRowCellsInner<TData, TItemKey = string>({
|
||||
// Stable references via destructuring, keep them as is
|
||||
const onRowClick = context?.onRowClick;
|
||||
const onRowClickNewTab = context?.onRowClickNewTab;
|
||||
const onRowDeactivate = context?.onRowDeactivate;
|
||||
const isRowActive = context?.isRowActive;
|
||||
const getRowKeyData = context?.getRowKeyData;
|
||||
const rowIndex = row.index;
|
||||
@@ -52,21 +51,9 @@ function TanStackRowCellsInner<TData, TItemKey = string>({
|
||||
}
|
||||
|
||||
const isActive = isRowActive?.(rowData) ?? false;
|
||||
if (isActive && onRowDeactivate) {
|
||||
onRowDeactivate();
|
||||
} else {
|
||||
onRowClick?.(rowData, itemKey);
|
||||
}
|
||||
onRowClick?.(rowData, itemKey, { isActive });
|
||||
},
|
||||
[
|
||||
isRowActive,
|
||||
onRowDeactivate,
|
||||
onRowClick,
|
||||
onRowClickNewTab,
|
||||
rowData,
|
||||
getRowKeyData,
|
||||
rowIndex,
|
||||
],
|
||||
[isRowActive, onRowClick, onRowClickNewTab, rowData, getRowKeyData, rowIndex],
|
||||
);
|
||||
|
||||
if (itemKind === 'expansion') {
|
||||
@@ -120,7 +107,6 @@ function areRowCellsPropsEqual<TData>(
|
||||
prev.columnVisibilityKey === next.columnVisibilityKey &&
|
||||
prev.context?.onRowClick === next.context?.onRowClick &&
|
||||
prev.context?.onRowClickNewTab === next.context?.onRowClickNewTab &&
|
||||
prev.context?.onRowDeactivate === next.context?.onRowDeactivate &&
|
||||
prev.context?.isRowActive === next.context?.isRowActive &&
|
||||
prev.context?.getRowKeyData === next.context?.getRowKeyData &&
|
||||
prev.context?.renderRowActions === next.context?.renderRowActions &&
|
||||
|
||||
@@ -92,11 +92,11 @@ function TanStackTableInner<TData, TItemKey = string>(
|
||||
getGroupKey,
|
||||
getRowStyle,
|
||||
getRowClassName,
|
||||
getRowTestId,
|
||||
isRowActive,
|
||||
renderRowActions,
|
||||
onRowClick,
|
||||
onRowClickNewTab,
|
||||
onRowDeactivate,
|
||||
onSort,
|
||||
activeRowIndex,
|
||||
renderExpandedRow,
|
||||
@@ -378,11 +378,11 @@ function TanStackTableInner<TData, TItemKey = string>(
|
||||
() => ({
|
||||
getRowStyle,
|
||||
getRowClassName,
|
||||
getRowTestId,
|
||||
isRowActive,
|
||||
renderRowActions,
|
||||
onRowClick,
|
||||
onRowClickNewTab,
|
||||
onRowDeactivate,
|
||||
renderExpandedRow,
|
||||
getRowKeyData,
|
||||
colCount: visibleColumnsCount,
|
||||
@@ -396,11 +396,11 @@ function TanStackTableInner<TData, TItemKey = string>(
|
||||
[
|
||||
getRowStyle,
|
||||
getRowClassName,
|
||||
getRowTestId,
|
||||
isRowActive,
|
||||
renderRowActions,
|
||||
onRowClick,
|
||||
onRowClickNewTab,
|
||||
onRowDeactivate,
|
||||
renderExpandedRow,
|
||||
getRowKeyData,
|
||||
visibleColumnsCount,
|
||||
|
||||
@@ -85,7 +85,9 @@ describe('TanStackRowCells', () => {
|
||||
</table>,
|
||||
);
|
||||
await user.click(screen.getAllByRole('cell')[0]);
|
||||
expect(onRowClick).toHaveBeenCalledWith({ id: 'r1' }, 'r1');
|
||||
expect(onRowClick).toHaveBeenCalledWith({ id: 'r1' }, 'r1', {
|
||||
isActive: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('fires onRowClick with empty itemKey when getRowKeyData is not provided', async () => {
|
||||
@@ -117,17 +119,19 @@ describe('TanStackRowCells', () => {
|
||||
</table>,
|
||||
);
|
||||
await user.click(screen.getAllByRole('cell')[0]);
|
||||
expect(onRowClick).toHaveBeenCalledWith({ id: 'r1' }, '');
|
||||
expect(onRowClick).toHaveBeenCalledWith({ id: 'r1' }, '', {
|
||||
isActive: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls onRowDeactivate instead of onRowClick when row is active', async () => {
|
||||
it('calls onRowClick with isActive: true when the row is active', async () => {
|
||||
// The table no longer owns open/close — it reports the active state and the
|
||||
// consumer routes the click. An active row must still fire onRowClick.
|
||||
const user = userEvent.setup();
|
||||
const onRowClick = jest.fn();
|
||||
const onRowDeactivate = jest.fn();
|
||||
const ctx: TableRowContext<Row> = {
|
||||
colCount: 1,
|
||||
onRowClick,
|
||||
onRowDeactivate,
|
||||
isRowActive: () => true,
|
||||
getRowKeyData: () => ({ finalKey: 'r1', itemKey: 'r1' }),
|
||||
hasSingleColumn: false,
|
||||
@@ -152,8 +156,44 @@ describe('TanStackRowCells', () => {
|
||||
</table>,
|
||||
);
|
||||
await user.click(screen.getAllByRole('cell')[0]);
|
||||
expect(onRowDeactivate).toHaveBeenCalled();
|
||||
expect(onRowClick).not.toHaveBeenCalled();
|
||||
expect(onRowClick).toHaveBeenCalledWith({ id: 'r1' }, 'r1', {
|
||||
isActive: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls onRowClick with isActive: false when the row is not active', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onRowClick = jest.fn();
|
||||
const ctx: TableRowContext<Row> = {
|
||||
colCount: 1,
|
||||
onRowClick,
|
||||
isRowActive: () => false,
|
||||
getRowKeyData: () => ({ finalKey: 'r1', itemKey: 'r1' }),
|
||||
hasSingleColumn: false,
|
||||
columnOrderKey: '',
|
||||
columnVisibilityKey: '',
|
||||
};
|
||||
const row = buildMockRow([{ id: 'body' }]);
|
||||
render(
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<TanStackRowCells<Row>
|
||||
row={row as never}
|
||||
context={ctx}
|
||||
itemKind="row"
|
||||
hasSingleColumn={false}
|
||||
columnOrderKey=""
|
||||
columnVisibilityKey=""
|
||||
/>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>,
|
||||
);
|
||||
await user.click(screen.getAllByRole('cell')[0]);
|
||||
expect(onRowClick).toHaveBeenCalledWith({ id: 'r1' }, 'r1', {
|
||||
isActive: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('does not render renderRowActions before hover', () => {
|
||||
|
||||
@@ -611,6 +611,7 @@ describe('TanStackTableView Integration', () => {
|
||||
expect(onRowClick).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: '1', name: 'Item 1' }),
|
||||
'1',
|
||||
{ isActive: false },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -639,6 +640,7 @@ describe('TanStackTableView Integration', () => {
|
||||
expect(onRowClick).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: '1', name: 'Item 1' }),
|
||||
{ id: '1', name: 'Item 1' },
|
||||
{ isActive: false },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -659,15 +661,15 @@ describe('TanStackTableView Integration', () => {
|
||||
expect(row).toHaveClass('tableRowActive');
|
||||
});
|
||||
|
||||
it('calls onRowDeactivate when clicking active row', async () => {
|
||||
it('calls onRowClick with isActive: true when clicking the active row', async () => {
|
||||
// The consumer owns open/close routing — the table just reports the
|
||||
// active state via the click context.
|
||||
const user = userEvent.setup();
|
||||
const onRowClick = jest.fn();
|
||||
const onRowDeactivate = jest.fn();
|
||||
|
||||
renderTanStackTable({
|
||||
props: {
|
||||
onRowClick,
|
||||
onRowDeactivate,
|
||||
isRowActive: (row) => row.id === '1',
|
||||
},
|
||||
});
|
||||
@@ -678,8 +680,11 @@ describe('TanStackTableView Integration', () => {
|
||||
|
||||
await user.click(screen.getByText('Item 1'));
|
||||
|
||||
expect(onRowDeactivate).toHaveBeenCalled();
|
||||
expect(onRowClick).not.toHaveBeenCalled();
|
||||
expect(onRowClick).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: '1' }),
|
||||
expect.anything(),
|
||||
{ isActive: true },
|
||||
);
|
||||
});
|
||||
|
||||
it('opens in new tab on ctrl+click', async () => {
|
||||
|
||||
@@ -116,9 +116,11 @@ export * from './useTableParams';
|
||||
* getItemKey={(row) => row.id}
|
||||
* isRowActive={(row) => row.id === selectedId}
|
||||
* activeRowIndex={selectedIndex}
|
||||
* onRowClick={(row, itemKey) => setSelectedId(itemKey)}
|
||||
* // The table reports the click + the row's active state; the consumer owns open/close.
|
||||
* onRowClick={(row, itemKey, { isActive }) =>
|
||||
* setSelectedId(isActive ? undefined : itemKey)
|
||||
* }
|
||||
* onRowClickNewTab={(row, itemKey) => openInNewTab(itemKey)}
|
||||
* onRowDeactivate={() => setSelectedId(undefined)}
|
||||
* getRowClassName={(row) => (row.severity === 'error' ? 'row-error' : '')}
|
||||
* getRowStyle={(row) => (row.dimmed ? { opacity: 0.5 } : {})}
|
||||
* renderRowActions={(row) => <Button size="small">Open</Button>}
|
||||
|
||||
@@ -81,15 +81,19 @@ export type FlatItem<TData> =
|
||||
| { kind: 'row'; row: TanStackRowType<TData> }
|
||||
| { kind: 'expansion'; row: TanStackRowType<TData> };
|
||||
|
||||
export type RowClickContext = {
|
||||
isActive: boolean;
|
||||
};
|
||||
|
||||
export type TableRowContext<TData, TItemKey = string> = {
|
||||
getRowStyle?: (row: TData) => CSSProperties;
|
||||
getRowClassName?: (row: TData) => string;
|
||||
getRowTestId?: (row: TData) => string;
|
||||
isRowActive?: (row: TData) => boolean;
|
||||
renderRowActions?: (row: TData) => ReactNode;
|
||||
onRowClick?: (row: TData, itemKey: TItemKey) => void;
|
||||
onRowClick?: (row: TData, itemKey: TItemKey, context: RowClickContext) => void;
|
||||
/** Called when ctrl+click or cmd+click on a row */
|
||||
onRowClickNewTab?: (row: TData, itemKey: TItemKey) => void;
|
||||
onRowDeactivate?: () => void;
|
||||
renderExpandedRow?: (
|
||||
row: TData,
|
||||
rowKey: string,
|
||||
@@ -178,12 +182,12 @@ export type TanStackTableProps<TData, TItemKey = string> = {
|
||||
getGroupKey?: (row: TData) => Record<string, string>;
|
||||
getRowStyle?: (row: TData) => CSSProperties;
|
||||
getRowClassName?: (row: TData) => string;
|
||||
getRowTestId?: (row: TData) => string;
|
||||
isRowActive?: (row: TData) => boolean;
|
||||
renderRowActions?: (row: TData) => ReactNode;
|
||||
onRowClick?: (row: TData, itemKey: TItemKey) => void;
|
||||
onRowClick?: (row: TData, itemKey: TItemKey, context: RowClickContext) => void;
|
||||
/** Called when ctrl+click or cmd+click on a row */
|
||||
onRowClickNewTab?: (row: TData, itemKey: TItemKey) => void;
|
||||
onRowDeactivate?: () => void;
|
||||
activeRowIndex?: number;
|
||||
renderExpandedRow?: (
|
||||
row: TData,
|
||||
|
||||
@@ -60,3 +60,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logs-linked-row td {
|
||||
background-color: var(--row-active-bg) !important;
|
||||
}
|
||||
|
||||
@@ -204,6 +204,9 @@ function LiveLogsList({
|
||||
data={formattedLogs}
|
||||
isLoading={false}
|
||||
isRowActive={(log): boolean => log.id === activeLog?.id}
|
||||
getRowClassName={(log): string =>
|
||||
log.id === activeLogId ? 'logs-linked-row' : ''
|
||||
}
|
||||
getRowStyle={(log): CSSProperties =>
|
||||
({
|
||||
'--row-active-bg': getRowBackgroundColor(
|
||||
@@ -216,10 +219,13 @@ function LiveLogsList({
|
||||
),
|
||||
}) as CSSProperties
|
||||
}
|
||||
onRowClick={(log): void => {
|
||||
handleSetActiveLog(log);
|
||||
onRowClick={(log, _itemKey, { isActive }): void => {
|
||||
if (isActive) {
|
||||
handleCloseLogDetail();
|
||||
} else {
|
||||
handleSetActiveLog(log);
|
||||
}
|
||||
}}
|
||||
onRowDeactivate={handleCloseLogDetail}
|
||||
activeRowIndex={activeLogIndex}
|
||||
renderRowActions={(log): ReactNode => (
|
||||
<LogLinesActionButtons
|
||||
|
||||
@@ -323,3 +323,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logs-linked-row td {
|
||||
background-color: var(--row-active-bg) !important;
|
||||
}
|
||||
|
||||
@@ -211,9 +211,11 @@ function LogsExplorerList({
|
||||
data={logs}
|
||||
isLoading={isLoading || isFetching}
|
||||
onEndReached={onEndReached}
|
||||
isRowActive={(log): boolean =>
|
||||
log.id === activeLog?.id || log.id === activeLogId
|
||||
isRowActive={(log): boolean => log.id === activeLog?.id}
|
||||
getRowClassName={(log): string =>
|
||||
log.id === activeLogId ? 'logs-linked-row' : ''
|
||||
}
|
||||
getRowTestId={(log): string => `logs-table-row-${log.id}`}
|
||||
getRowStyle={(log): CSSProperties =>
|
||||
({
|
||||
'--row-active-bg': getRowBackgroundColor(
|
||||
@@ -226,10 +228,13 @@ function LogsExplorerList({
|
||||
),
|
||||
}) as CSSProperties
|
||||
}
|
||||
onRowClick={(log): void => {
|
||||
handleSetActiveLog(log);
|
||||
onRowClick={(log, _itemKey, { isActive }): void => {
|
||||
if (isActive) {
|
||||
handleCloseLogDetail();
|
||||
} else {
|
||||
handleSetActiveLog(log);
|
||||
}
|
||||
}}
|
||||
onRowDeactivate={handleCloseLogDetail}
|
||||
activeRowIndex={activeLogIndex}
|
||||
renderRowActions={(log): ReactNode => (
|
||||
<LogLinesActionButtons
|
||||
@@ -282,6 +287,7 @@ function LogsExplorerList({
|
||||
options.maxLines,
|
||||
options.fontSize,
|
||||
activeLogIndex,
|
||||
activeLogId,
|
||||
logs,
|
||||
onEndReached,
|
||||
getItemContent,
|
||||
|
||||
112
tests/e2e/helpers/logs-explorer.ts
Normal file
112
tests/e2e/helpers/logs-explorer.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { expect, type Locator, type Page } from '@playwright/test';
|
||||
|
||||
import { dismissQuickFiltersAnnouncement } from './quick-filters';
|
||||
|
||||
const LOGS_EXPLORER_PATH = '/logs/logs-explorer';
|
||||
|
||||
const RELATIVE_TIME = '6h';
|
||||
|
||||
const FORMAT_OPTIONS_TEST_ID = 'periscope-btn-format-options';
|
||||
|
||||
const ROW_TEST_ID_PREFIX = 'logs-table-row-';
|
||||
|
||||
const LOG_DETAIL_DRAWER_TEST_ID = 'log-detail-drawer';
|
||||
export const LINKED_ROW_CLASS = 'logs-linked-row';
|
||||
|
||||
type LogsFormat = 'Raw' | 'Default' | 'Column';
|
||||
|
||||
const FORMAT_MODES: Record<LogsFormat, string> = {
|
||||
Raw: 'raw',
|
||||
Default: 'list',
|
||||
Column: 'table',
|
||||
};
|
||||
|
||||
export async function gotoLogsExplorer(page: Page): Promise<void> {
|
||||
await dismissQuickFiltersAnnouncement(page);
|
||||
await page.goto(`${LOGS_EXPLORER_PATH}?relativeTime=${RELATIVE_TIME}`);
|
||||
await expect(page.getByTestId(FORMAT_OPTIONS_TEST_ID)).toBeVisible();
|
||||
}
|
||||
|
||||
export async function setLogsFormat(
|
||||
page: Page,
|
||||
format: LogsFormat,
|
||||
): Promise<void> {
|
||||
const trigger = page.getByTestId(FORMAT_OPTIONS_TEST_ID);
|
||||
const popover = page.locator('.format-options-popover');
|
||||
const appliedMode = new RegExp(`%22format%22%3A%22${FORMAT_MODES[format]}%22`);
|
||||
|
||||
await expect(async () => {
|
||||
if (!(await popover.isVisible())) {
|
||||
await trigger.click();
|
||||
await expect(popover).toBeVisible();
|
||||
}
|
||||
await popover
|
||||
.locator('.menu-items .item')
|
||||
.filter({ hasText: format })
|
||||
.click();
|
||||
await expect(page).toHaveURL(appliedMode, { timeout: 3_000 });
|
||||
}).toPass({ timeout: 20_000 });
|
||||
|
||||
await trigger.click();
|
||||
await expect(popover).toBeHidden();
|
||||
}
|
||||
|
||||
export function logsTableRows(page: Page): Locator {
|
||||
return page.locator(`[data-testid^="${ROW_TEST_ID_PREFIX}"]`);
|
||||
}
|
||||
|
||||
export function logsTableRow(page: Page, logId: string): Locator {
|
||||
return page.getByTestId(`${ROW_TEST_ID_PREFIX}${logId}`);
|
||||
}
|
||||
|
||||
export function highlightedLogsTableRows(page: Page): Locator {
|
||||
return logsTableRows(page).and(page.locator(`.${LINKED_ROW_CLASS}`));
|
||||
}
|
||||
|
||||
export function unhighlightedLogsTableRows(page: Page): Locator {
|
||||
return page.locator(
|
||||
`[data-testid^="${ROW_TEST_ID_PREFIX}"]:not(.${LINKED_ROW_CLASS})`,
|
||||
);
|
||||
}
|
||||
|
||||
export function activeLogIdFromUrl(page: Page): string {
|
||||
const value = new URL(page.url()).searchParams.get('activeLogId');
|
||||
if (!value) {
|
||||
throw new Error(`No activeLogId in URL: ${page.url()}`);
|
||||
}
|
||||
return value.replace(/"/g, '');
|
||||
}
|
||||
|
||||
export function logDetailsDrawer(page: Page): Locator {
|
||||
return page.getByTestId(LOG_DETAIL_DRAWER_TEST_ID);
|
||||
}
|
||||
|
||||
export async function clickRowFirstCell(row: Locator): Promise<void> {
|
||||
await row.locator('td').first().click();
|
||||
}
|
||||
|
||||
export async function openLogDetailsFromRow(row: Locator): Promise<void> {
|
||||
await clickRowFirstCell(row);
|
||||
await expect(logDetailsDrawer(row.page())).toBeVisible();
|
||||
}
|
||||
|
||||
export async function openContextView(page: Page): Promise<void> {
|
||||
await page
|
||||
.locator('.views-tabs')
|
||||
.getByText('Context', { exact: true })
|
||||
.click();
|
||||
await expect(contextLogItems(page).first()).toBeVisible();
|
||||
}
|
||||
|
||||
function contextLogItems(page: Page): Locator {
|
||||
return page.locator('.context-log-renderer__item');
|
||||
}
|
||||
|
||||
export async function openFirstContextLogInNewTab(page: Page): Promise<Page> {
|
||||
const [newPage] = await Promise.all([
|
||||
page.context().waitForEvent('page'),
|
||||
contextLogItems(page).first().click(),
|
||||
]);
|
||||
await newPage.waitForLoadState();
|
||||
return newPage;
|
||||
}
|
||||
49
tests/e2e/tests/logs-explorer/linked-row-click.spec.ts
Normal file
49
tests/e2e/tests/logs-explorer/linked-row-click.spec.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { expect, test } from '../../fixtures/auth';
|
||||
import {
|
||||
activeLogIdFromUrl,
|
||||
clickRowFirstCell,
|
||||
gotoLogsExplorer,
|
||||
highlightedLogsTableRows,
|
||||
LINKED_ROW_CLASS,
|
||||
logDetailsDrawer,
|
||||
logsTableRow,
|
||||
logsTableRows,
|
||||
openFirstContextLogInNewTab,
|
||||
openContextView,
|
||||
openLogDetailsFromRow,
|
||||
setLogsFormat,
|
||||
unhighlightedLogsTableRows,
|
||||
} from '../../helpers/logs-explorer';
|
||||
|
||||
test.describe('Logs Explorer — linked row in Column format', () => {
|
||||
test('TC-01 the linked row in a newly opened tab is highlighted and toggles the details drawer on click', async ({
|
||||
authedPage: page,
|
||||
}) => {
|
||||
await gotoLogsExplorer(page);
|
||||
await setLogsFormat(page, 'Column');
|
||||
|
||||
const rows = logsTableRows(page);
|
||||
await expect(rows.first()).toBeVisible();
|
||||
await expect(highlightedLogsTableRows(page)).toHaveCount(0);
|
||||
|
||||
await openLogDetailsFromRow(rows.first());
|
||||
await openContextView(page);
|
||||
|
||||
const linkedTab = await openFirstContextLogInNewTab(page);
|
||||
await expect(linkedTab).toHaveURL(/activeLogId=/);
|
||||
|
||||
const linkedLogId = activeLogIdFromUrl(linkedTab);
|
||||
const linkedRow = logsTableRow(linkedTab, linkedLogId);
|
||||
await expect(linkedRow).toBeVisible();
|
||||
await expect(linkedRow).toHaveClass(new RegExp(LINKED_ROW_CLASS));
|
||||
|
||||
await expect(highlightedLogsTableRows(linkedTab)).toHaveCount(1);
|
||||
await expect(unhighlightedLogsTableRows(linkedTab).first()).toBeVisible();
|
||||
|
||||
await expect(logDetailsDrawer(linkedTab)).toBeHidden();
|
||||
await openLogDetailsFromRow(linkedRow);
|
||||
|
||||
await clickRowFirstCell(linkedRow);
|
||||
await expect(logDetailsDrawer(linkedTab)).toBeHidden();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user