import { act, waitFor } from '@testing-library/react';
import React from 'react';
import { BehaviorSubject } from 'rxjs';
import { DeckRuntimeContext } from '@spinnaker/core';
import { renderHookHarness } from '../../../../core/src/utils/testUtils/hookHarness';
import { useAmazonLoadBalancerDetails } from './amazonLoadBalancerDetails';
import { RequestBuilder } from '../../../../core/src/api/ApiService';
describe('useAmazonLoadBalancerDetails', () => {
const defaultHttpClient = RequestBuilder.defaultHttpClient;
let runtimeServices: any;
const RuntimeWrapper = ({ children }: React.PropsWithChildren<{}>) => (
{children}
);
beforeEach(() => {
runtimeServices = {};
});
afterEach(() => {
RequestBuilder.defaultHttpClient = defaultHttpClient;
});
it('does not refetch details when an unrelated state update re-renders with a new autoClose callback', async () => {
const loadBalancer = {
account: 'test',
name: 'frontend',
provider: 'aws',
region: 'us-east-1',
loadBalancerType: 'classic',
subnets: [],
} as any;
const status$ = new BehaviorSubject({
status: 'FETCHED',
loaded: true,
lastRefresh: 1,
data: [loadBalancer],
});
const app = {
getDataSource: vi.fn().mockReturnValue({
status$,
refresh: vi.fn(),
}),
} as any;
const get = vi.fn().mockReturnValue(new Promise(() => undefined));
RequestBuilder.defaultHttpClient = { get } as any;
runtimeServices.securityGroupReader = {
getApplicationSecurityGroup: vi.fn(),
};
const props = {
app,
loadBalancerParams: { accountId: 'test', name: 'frontend', provider: 'aws', region: 'us-east-1' },
autoClose: () => undefined,
} as any;
const hook = renderHookHarness(useAmazonLoadBalancerDetails, props, { wrapper: RuntimeWrapper });
await waitFor(() => expect(get).toHaveBeenCalledTimes(1));
hook.rerenderHook({ ...props, autoClose: () => undefined });
expect(get).toHaveBeenCalledTimes(1);
});
it('does not update state after unmount when details loading finishes', async () => {
const loadBalancer = {
account: 'test',
name: 'frontend',
provider: 'aws',
region: 'us-east-1',
loadBalancerType: 'classic',
subnets: [],
} as any;
const status$ = new BehaviorSubject({
status: 'FETCHED',
loaded: true,
lastRefresh: 1,
data: [loadBalancer],
});
const app = {
getDataSource: vi.fn().mockReturnValue({
status$,
refresh: vi.fn(),
}),
} as any;
let resolveDetails: (details: any[]) => void = () => undefined;
const detailsRequest = new Promise((resolve) => {
resolveDetails = resolve;
});
const get = vi.fn().mockReturnValue(detailsRequest);
const consoleError = vi.spyOn(console, 'error').mockReturnValue(undefined);
RequestBuilder.defaultHttpClient = { get } as any;
runtimeServices.securityGroupReader = {
getApplicationSecurityGroup: vi.fn(),
};
const hook = renderHookHarness(
useAmazonLoadBalancerDetails,
{
app,
loadBalancerParams: { accountId: 'test', name: 'frontend', provider: 'aws', region: 'us-east-1' },
autoClose: () => undefined,
} as any,
{ wrapper: RuntimeWrapper },
);
await waitFor(() => expect(get).toHaveBeenCalledTimes(1));
hook.unmount();
await act(async () => {
resolveDetails([]);
await detailsRequest;
});
const unmountedStateUpdateWarning = consoleError.mock.calls.some(([message]) =>
String(message).includes('unmounted component'),
);
expect(unmountedStateUpdateWarning).toBe(false);
});
});