Skip to content
Merged
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
19151d1
fix: fixed Add Metrics to Tree Chart (#29158)
SBIN2010 Oct 22, 2024
35aaeb6
fix: clear modal after CSS templates is added
SBIN2010 Oct 22, 2024
db3afda
Revert "fix: clear modal after CSS templates is added"
SBIN2010 Oct 23, 2024
9eea2e6
fix: tree metrics exclude validator
SBIN2010 Nov 25, 2024
3930c95
Merge branch 'apache:master' into master
SBIN2010 Mar 11, 2025
b355212
Merge branch 'apache:master' into master
SBIN2010 Mar 18, 2025
7200d6c
Merge branch 'apache:master' into master
SBIN2010 Mar 20, 2025
3049a3d
Merge branch 'apache:master' into master
SBIN2010 Mar 25, 2025
247aef8
Merge branch 'apache:master' into master
SBIN2010 Apr 2, 2025
b4678ec
Merge branch 'apache:master' into master
SBIN2010 Apr 4, 2025
0ae844d
Merge branch 'apache:master' into master
SBIN2010 Jul 1, 2025
49fc529
Merge branch 'apache:master' into master
SBIN2010 Jul 10, 2025
601dde2
fix: revert #30679
SBIN2010 Mar 25, 2025
66823a5
Merge branch 'apache:master' into master
SBIN2010 Jul 12, 2025
4f59629
Merge branch 'apache:master' into master
SBIN2010 Jul 16, 2025
a7ce4e9
Merge branch 'apache:master' into master
SBIN2010 Jul 20, 2025
1bf4fdd
fix
SBIN2010 Jul 20, 2025
1241867
Merge branch 'apache:master' into master
SBIN2010 Jul 31, 2025
045cf6b
Merge branch 'apache:master' into master
SBIN2010 Aug 2, 2025
acdba8a
Merge branch 'apache:master' into master
SBIN2010 Aug 10, 2025
4fb89c2
Merge branch 'apache:master' into master
SBIN2010 Aug 15, 2025
f47d28b
Merge branch 'apache:master' into master
SBIN2010 Aug 18, 2025
3bdf337
Merge branch 'apache:master' into master
SBIN2010 Aug 19, 2025
780a5d6
Merge branch 'apache:master' into master
SBIN2010 Aug 24, 2025
3c339df
Merge branch 'apache:master' into master
SBIN2010 Aug 25, 2025
798b7a6
Merge branch 'apache:master' into master
SBIN2010 Aug 30, 2025
2db564e
Merge branch 'apache:master' into master
SBIN2010 Sep 3, 2025
a58cfad
Merge branch 'apache:master' into master
SBIN2010 Sep 5, 2025
9ea0d2f
Merge branch 'apache:master' into master
SBIN2010 Sep 8, 2025
c6bbf53
Merge branch 'apache:master' into master
SBIN2010 Sep 9, 2025
5214e7a
Merge branch 'apache:master' into master
SBIN2010 Sep 15, 2025
d98105c
Merge branch 'apache:master' into master
SBIN2010 Sep 17, 2025
30b1576
Merge branch 'apache:master' into master
SBIN2010 Sep 19, 2025
4aaa27c
Merge branch 'apache:master' into master
SBIN2010 Sep 23, 2025
25c1987
Merge branch 'apache:master' into master
SBIN2010 Sep 24, 2025
c3854cb
Merge branch 'apache:master' into master
SBIN2010 Oct 1, 2025
e1c4909
Merge branch 'apache:master' into master
SBIN2010 Oct 1, 2025
b1897dd
fix: test
SBIN2010 Oct 1, 2025
f3e973f
fix: test
SBIN2010 Oct 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,115 +22,116 @@ import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { act } from 'spec/helpers/testing-library';

const history = createMemoryHistory({
let history = createMemoryHistory({
initialEntries: ['/dashboard'],
});

beforeEach(() => {
history = createMemoryHistory({ initialEntries: ['/dashboard'] });
});
Comment on lines +25 to +31
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

beforeEach should work on a flat structure as well right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, beforeEach works perfectly fine with a flat test structure.
It runs before each test - every test gets a fresh history instance

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but i don't quite understand this change still? If const was working before do we need this let and reassign in beforeEach?


const wrapper = ({ children }: { children: React.ReactNode }) => (
<Router history={history}>{children}</Router>
);

// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('useUnsavedChangesPrompt', () => {
test('should not show modal initially', () => {
const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave: jest.fn(),
}),
{ wrapper },
);

expect(result.current.showModal).toBe(false);
});
test('should not show modal initially', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test isolation failure

The PR removes the describe block wrapper and converts tests to standalone test functions, but this creates a critical test isolation issue. All tests now share the same history instance and wrapper configuration, which can cause test pollution where state from one test affects subsequent tests. The history object accumulates navigation state across tests, and the shared wrapper component may retain state. This will lead to flaky tests and false positives/negatives in CI/CD pipelines. Add proper test isolation by reinitializing the history instance before each test using beforeEach.

Code suggestion
Check the AI-generated fix before applying
 -
 -const history = createMemoryHistory({
 -  initialEntries: ['/dashboard'],
 -});
 -
 +let history = createMemoryHistory({
 +  initialEntries: ['/dashboard'],
 +});
 +
 +beforeEach(() => {
 +  history = createMemoryHistory({ initialEntries: ['/dashboard'] });
 +});
 +

Code Review Run #c65c3d


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave: jest.fn(),
}),
{ wrapper },
);

expect(result.current.showModal).toBe(false);
});

test('should block navigation and show modal if there are unsaved changes', () => {
const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave: jest.fn(),
}),
{ wrapper },
);

// Simulate blocked navigation
act(() => {
const unblock = history.block((tx: any) => tx);
unblock();
history.push('/another-page');
});

expect(result.current.showModal).toBe(true);
test('should block navigation and show modal if there are unsaved changes', () => {
const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave: jest.fn(),
}),
{ wrapper },
);

// Simulate blocked navigation
act(() => {
const unblock = history.block((tx: any) => tx);
unblock();
history.push('/another-page');
});

test('should trigger onSave and hide modal on handleSaveAndCloseModal', async () => {
const onSave = jest.fn().mockResolvedValue(undefined);
expect(result.current.showModal).toBe(true);
});

const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave,
}),
{ wrapper },
);
test('should trigger onSave and hide modal on handleSaveAndCloseModal', async () => {
const onSave = jest.fn().mockResolvedValue(undefined);

await act(async () => {
await result.current.handleSaveAndCloseModal();
});
const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave,
}),
{ wrapper },
);

expect(onSave).toHaveBeenCalled();
expect(result.current.showModal).toBe(false);
await act(async () => {
await result.current.handleSaveAndCloseModal();
});

test('should trigger manual save and not show modal again', async () => {
const onSave = jest.fn().mockResolvedValue(undefined);
expect(onSave).toHaveBeenCalled();
expect(result.current.showModal).toBe(false);
});

test('should trigger manual save and not show modal again', async () => {
const onSave = jest.fn().mockResolvedValue(undefined);

const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave,
}),
{ wrapper },
);

const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave,
}),
{ wrapper },
);
act(() => {
result.current.triggerManualSave();
});

act(() => {
result.current.triggerManualSave();
});
expect(onSave).toHaveBeenCalled();
expect(result.current.showModal).toBe(false);
});

expect(onSave).toHaveBeenCalled();
expect(result.current.showModal).toBe(false);
test('should close modal when handleConfirmNavigation is called', () => {
const onSave = jest.fn();

const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave,
}),
{ wrapper },
);

// First, trigger navigation to show the modal
act(() => {
const unblock = history.block((tx: any) => tx);
unblock();
history.push('/another-page');
});

it('should close modal when handleConfirmNavigation is called', () => {
const onSave = jest.fn();

const { result } = renderHook(
() =>
useUnsavedChangesPrompt({
hasUnsavedChanges: true,
onSave,
}),
{ wrapper },
);

// First, trigger navigation to show the modal
act(() => {
const unblock = history.block((tx: any) => tx);
unblock();
history.push('/another-page');
});

expect(result.current.showModal).toBe(true);

// Then call handleConfirmNavigation to discard changes
act(() => {
result.current.handleConfirmNavigation();
});

expect(result.current.showModal).toBe(false);
expect(result.current.showModal).toBe(true);

// Then call handleConfirmNavigation to discard changes
act(() => {
result.current.handleConfirmNavigation();
});

expect(result.current.showModal).toBe(false);
});
Loading