Skip to content

Fix flaky tests in CI #7528

@ggdouglas

Description

@ggdouglas

Problem

There are a few tests that routinely flake on Blueprint's CI. These tests do not appear to flake when when run locally.

Source: https://app.circleci.com/insights/github/palantir/blueprint/workflows/compile_lint_test_dist_deploy/tests?branch=develop

Popover

  • <Popover> focus management when shouldReturnFocusOnClose={true} moves focus to overlay when opened
  • <Popover> "after each" hook for "moves focus to overlay when opened

describe("focus management when shouldReturnFocusOnClose={true}", () => {
const targetClassName = "test-target";
const commonProps: Partial<PopoverProps> = {
className: targetClassName,
interactionKind: PopoverInteractionKind.CLICK,
shouldReturnFocusOnClose: true,
transitionDuration: 0,
usePortal: true,
};
it("moves focus to overlay when opened", done => {
function handleOpened() {
assert.notEqual(document.activeElement, document.body, "body element should not have focus");
assert.isNotNull(
document.activeElement?.closest(`.${Classes.OVERLAY}`),
"focus should be inside overlay",
);
done();
}
wrapper = renderPopover({ ...commonProps, onOpened: handleOpened });
React.act(() => wrapper!.targetButton.focus());
wrapper.simulateTarget("click");
});
it("returns focus to target element when closed", async () => {
wrapper = renderPopover(commonProps);
React.act(() => wrapper!.targetButton.focus());
assert.strictEqual(
document.activeElement,
wrapper.targetElement.querySelector("button"),
"button should have document focus",
);
wrapper.simulateTarget("click");
// wait for it to open, then click again to close
await waitFor(() => {
wrapper!.update();
wrapper!.assertIsOpen(true);
});
wrapper.simulateTarget("click");
await waitFor(() => {
wrapper!.update();
wrapper!.assertIsOpen(false);
assert.notEqual(document.activeElement, document.body, "body element should not have focus");
assert.isNotNull(document.activeElement?.closest(`.${targetClassName}`), "focus should be on target");
});
});
});

Overlay2

  • <Overlay2> lifecycle methods called as expected

it("lifecycle methods called as expected", async () => {
// these lifecycles are passed directly to CSSTransition from react-transition-group
// so we do not need to test these extensively. one integration test should do.
const onClosed = spy();
const onClosing = spy();
const onOpened = spy();
const onOpening = spy();
wrapper = mountWrapper(
<OverlayWrapper
{...{ onClosed, onClosing, onOpened, onOpening }}
isOpen={true}
usePortal={false}
// transition duration shorter than timeout below to ensure it's done
transitionDuration={8}
>
{createOverlayContents()}
</OverlayWrapper>,
);
assert.isTrue(onOpening.calledOnce, "onOpening");
assert.isFalse(onOpened.calledOnce, "onOpened not called yet");
await sleep(10);
// on*ed called after transition completes
assert.isTrue(onOpened.calledOnce, "onOpened");
wrapper.setProps({ isOpen: false });
// on*ing called immediately when prop changes
assert.isTrue(onClosing.calledOnce, "onClosing");
assert.isFalse(onClosed.calledOnce, "onClosed not called yet");
await sleep(10);
assert.isTrue(onClosed.calledOnce, "onOpened");
});

Table

Solution

Investigate targeted fixes for these tests. Alternatively/additionally, we could/should investigate rewriting these tests with React Testing Library for future maintenance, stability, and compatibility.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions