Skip to content

Commit

Permalink
chore: Fixes flakiness in expandable rows integ test (#2882)
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-kot authored Oct 16, 2024
1 parent 075e9bd commit 5496d3e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 16 deletions.
35 changes: 26 additions & 9 deletions pages/table/expandable-rows-test.page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useContext, useEffect, useRef, useState } from 'react';
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { isEqual } from 'lodash';

import { useCollection } from '@cloudscape-design/collection-hooks';
Expand Down Expand Up @@ -31,11 +31,15 @@ import messages from '~components/i18n/messages/all.en';
import SpaceBetween from '~components/space-between';

import AppContext, { AppContextType } from '../app/app-context';
import { enhanceWindow, WindowWithFlushResponse } from '../common/flush-response';
import { ariaLabels, getHeaderCounterText, Instance } from './expandable-rows/common';
import { createColumns, createPreferences, filteringProperties } from './expandable-rows/expandable-rows-configs';
import { allInstances } from './expandable-rows/expandable-rows-data';
import { EmptyState, getMatchesCountText, renderAriaLive } from './shared-configs';

declare const window: WindowWithFlushResponse;
enhanceWindow();

type LoadingState = Map<string, { pages: number; status: TableProps.LoadingStatus }>;

type PageContext = React.Context<
Expand All @@ -51,6 +55,7 @@ type PageContext = React.Context<
useProgressiveLoading: boolean;
useServerMock: boolean;
emulateServerError: boolean;
manualServerMock: boolean;
}>
>;

Expand Down Expand Up @@ -195,6 +200,18 @@ const NESTED_PAGE_SIZE = 2;
function useTableData() {
const settings = usePageSettings();
const delay = settings.useServerMock ? SERVER_DELAY : 0;
const getServerResponse = useCallback(
(cb: () => void) => {
if (settings.manualServerMock) {
window.__pendingCallbacks.push(cb);
return () => {};
} else {
const timerRef = setTimeout(cb, delay);
return () => clearTimeout(timerRef);
}
},
[delay, settings.manualServerMock]
);

const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
Expand All @@ -204,13 +221,13 @@ function useTableData() {
useEffect(() => {
setLoading(true);
setError(false);
setTimeout(() => {
return getServerResponse(() => {
setReadyInstances(allInstances);
setLoading(false);
setError(settings.emulateServerError);
}, delay);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [delay, setLoading, setError, setReadyInstances]);
}, [getServerResponse, setLoading, setError, setReadyInstances]);

const collectionResult = useCollection(readyInstances, {
pagination: settings.usePagination ? { pageSize: ROOT_PAGE_SIZE } : undefined,
Expand Down Expand Up @@ -245,14 +262,13 @@ function useTableData() {
useEffect(() => {
setLoading(true);
setError(false);
const timeoutId = setTimeout(() => {
return getServerResponse(() => {
setLoading(false);
setReadyItems(memoItems);
setError(settings.emulateServerError);
}, delay);
return () => clearTimeout(timeoutId);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [delay, memoItems, setLoading, setError, setReadyItems]);
}, [getServerResponse, memoItems, setLoading, setError, setReadyItems]);

// Decorate path options to only show the last node and not the full path.
collectionResult.propertyFilterProps.filteringOptions = collectionResult.propertyFilterProps.filteringOptions.map(
Expand All @@ -277,7 +293,7 @@ function useTableData() {
const loadItems = (id: string) => {
setLoadingState(nextLoading(id));
if (delay) {
setTimeout(() => setLoadingState(settings.emulateServerError ? nextError(id) : nextPending(id)), delay);
getServerResponse(() => setLoadingState(settings.emulateServerError ? nextError(id) : nextPending(id)));
} else {
setLoadingState(nextPending(id));
}
Expand Down Expand Up @@ -355,6 +371,7 @@ function usePageSettings() {
useProgressiveLoading: urlParams.useProgressiveLoading ?? true,
groupResources: urlParams.groupResources ?? true,
useServerMock: urlParams.useServerMock ?? false,
manualServerMock: urlParams.manualServerMock ?? false,
emulateServerError: urlParams.emulateServerError ?? false,
setUrlParams,
};
Expand Down
23 changes: 16 additions & 7 deletions src/table/__integ__/expandable-rows.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { BasePageObject } from '@cloudscape-design/browser-test-tools/page-objects';

import useBrowser from '@cloudscape-design/browser-test-tools/use-browser';

import createWrapper from '../../../lib/components/test-utils/selectors';
import { AsyncResponsePage } from '../../__integ__/page-objects/async-response-page';

const tableWrapper = createWrapper().findTable();

Expand All @@ -15,17 +16,18 @@ interface TestPageOptions {
describe('Expandable rows', () => {
const setupTest = (
{ useProgressiveLoading = false, useServerMock = false }: TestPageOptions,
testFn: (page: BasePageObject) => Promise<void>
testFn: (page: AsyncResponsePage) => Promise<void>
) => {
return useBrowser(async browser => {
const page = new BasePageObject(browser);
const page = new AsyncResponsePage(browser);
await page.setWindowSize({ width: 1200, height: 1000 });
const query = new URLSearchParams({
useProgressiveLoading: String(useProgressiveLoading),
useServerMock: String(useServerMock),
manualServerMock: String(useServerMock),
});
await browser.url(`#/light/table/expandable-rows-test?${query.toString()}`);
await page.waitForVisible(tableWrapper.findBodyCell(2, 1).toSelector());
await page.waitForVisible(tableWrapper.findColumnHeaders().get(1).toSelector());
await testFn(page);
});
};
Expand All @@ -52,11 +54,16 @@ describe('Expandable rows', () => {
const page3Toggle = tableWrapper.findExpandToggle(6);
const getRowsCount = () => page.getElementsCount(tableWrapper.findRows().toSelector());

// no data initially
await expect(getRowsCount()).resolves.toBe(0);

// 10 data rows + 1 loader row
await expect(getRowsCount()).resolves.toBe(10 + 1);
await page.flushResponse();
await page.waitForAssertion(() => expect(getRowsCount()).resolves.toBe(10 + 1));

// Expand target cluster
await page.click(tableWrapper.findExpandToggle(1).toSelector());
await page.flushResponse();
await page.waitForAssertion(() => expect(getRowsCount()).resolves.toBe(12 + 2));

// Navigate to the target cluster loader
Expand All @@ -66,14 +73,16 @@ describe('Expandable rows', () => {
// Trigger target cluster load-more
await page.keys(['Enter']);
// Ensure state change occurs and the focus stays on the same cell (next load-more)
await page.waitForAssertion(() => expect(page.getFocusedElementText()).resolves.toBe('Loading items'));
await page.waitForAssertion(() => expect(page.getFocusedElementText()).resolves.toContain('Loading items'));
await page.flushResponse();
await page.waitForAssertion(() => expect(page.isFocused(page2Toggle.toSelector())).resolves.toBe(true));
await page.waitForAssertion(() => expect(getRowsCount()).resolves.toBe(14 + 2));

// Trigger subsequent loading
await page.keys(['ArrowDown', 'ArrowDown', 'Enter']);
// Ensure state change occurs and the focus stays on the same cell (last cluster's expand toggle)
await page.waitForAssertion(() => expect(page.getFocusedElementText()).resolves.toBe('Loading items'));
await page.waitForAssertion(() => expect(page.getFocusedElementText()).resolves.toContain('Loading items'));
await page.flushResponse();
await page.waitForAssertion(() => expect(page.isFocused(page3Toggle.toSelector())).resolves.toBe(true));
await page.waitForAssertion(() => expect(getRowsCount()).resolves.toBe(15 + 1));
})
Expand Down

0 comments on commit 5496d3e

Please sign in to comment.