#708 apply strictier linting rules (#717)

* #708 apply strictier linting rules and fix simple eslint bugs

* #708 fix eslint errors relate to promise

* #708 fix eslint import/no-extraneous-dependencies

* #708 fix eslint errors of react-hook

* #708 enable eslint check for typescript

---------

Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
This commit is contained in:
lethemanh
2026-04-01 22:15:10 +07:00
committed by GitHub
parent 2bff6aae78
commit cadfa70e60
321 changed files with 27452 additions and 27600 deletions
+134 -139
View File
@@ -1,224 +1,219 @@
import {
ResourceSearch,
Resource,
} from "@/components/Attendees/ResourceSearch";
import { searchUsers } from "@/features/User/userAPI";
import { act, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { renderWithProviders } from "../utils/Renderwithproviders";
import { ResourceSearch, Resource } from '@/components/Attendees/ResourceSearch'
import { searchUsers } from '@/features/User/userAPI'
import { act, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { renderWithProviders } from '../utils/Renderwithproviders'
jest.mock("@/features/User/userAPI");
const mockedSearchUsers = searchUsers as jest.MockedFunction<
typeof searchUsers
>;
jest.mock('@/features/User/userAPI')
const mockedSearchUsers = searchUsers as jest.MockedFunction<typeof searchUsers>
describe("ResourceSearch", () => {
describe('ResourceSearch', () => {
const baseResource: Resource = {
displayName: "Projector Room",
};
displayName: 'Projector Room'
}
function setup(
selectedResources: Resource[] = [],
props?: Partial<React.ComponentProps<typeof ResourceSearch>>
) {
const onChange = jest.fn();
const onChange = jest.fn()
renderWithProviders(
<ResourceSearch
objectTypes={["resource"]}
objectTypes={['resource']}
selectedResources={selectedResources}
onChange={onChange}
{...props}
/>
);
return { onChange };
)
return { onChange }
}
beforeEach(() => {
jest.useFakeTimers();
mockedSearchUsers.mockReset();
});
jest.useFakeTimers()
mockedSearchUsers.mockReset()
})
afterEach(() => {
jest.useRealTimers();
});
jest.useRealTimers()
})
it("calls searchUsers after debounce when typing", async () => {
it('calls searchUsers after debounce when typing', async () => {
mockedSearchUsers.mockResolvedValueOnce([
baseResource,
] as unknown as Awaited<ReturnType<typeof searchUsers>>);
setup();
baseResource
] as unknown as Awaited<ReturnType<typeof searchUsers>>)
setup()
const input = screen.getByRole("combobox");
await userEvent.type(input, "Room");
const input = screen.getByRole('combobox')
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
});
jest.advanceTimersByTime(300)
})
await waitFor(() => {
expect(mockedSearchUsers).toHaveBeenCalledWith("Room", ["resource"]);
});
});
expect(mockedSearchUsers).toHaveBeenCalledWith('Room', ['resource'])
})
})
it("renders search results and allows selection", async () => {
it('renders search results and allows selection', async () => {
mockedSearchUsers.mockResolvedValueOnce([
baseResource,
] as unknown as Awaited<ReturnType<typeof searchUsers>>);
const { onChange } = setup();
baseResource
] as unknown as Awaited<ReturnType<typeof searchUsers>>)
const { onChange } = setup()
const input = screen.getByRole("combobox");
await userEvent.type(input, "Room");
const input = screen.getByRole('combobox')
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
});
jest.advanceTimersByTime(300)
})
const option = await screen.findByText("Projector Room");
await userEvent.click(option);
const option = await screen.findByText('Projector Room')
await userEvent.click(option)
await waitFor(() => {
expect(onChange).toHaveBeenCalled();
});
});
expect(onChange).toHaveBeenCalled()
})
})
it("does not show already selected resources in options", async () => {
it('does not show already selected resources in options', async () => {
mockedSearchUsers.mockResolvedValueOnce([
baseResource,
] as unknown as Awaited<ReturnType<typeof searchUsers>>);
setup([baseResource]);
const input = screen.getByRole("combobox");
await userEvent.type(input, "Projector");
baseResource
] as unknown as Awaited<ReturnType<typeof searchUsers>>)
setup([baseResource])
const input = screen.getByRole('combobox')
await userEvent.type(input, 'Projector')
await act(async () => {
jest.advanceTimersByTime(300);
});
jest.advanceTimersByTime(300)
})
await waitFor(() => {
// It shouldn't be in the dropdown options anymore
const options = screen.queryAllByRole("option");
const options = screen.queryAllByRole('option')
expect(
options.find((opt) => opt.textContent === "Projector Room")
).toBeUndefined();
});
});
options.find(opt => opt.textContent === 'Projector Room')
).toBeUndefined()
})
})
it("respects disabled state", () => {
setup([], { disabled: true });
expect(screen.getByRole("combobox")).toBeDisabled();
});
it('respects disabled state', () => {
setup([], { disabled: true })
expect(screen.getByRole('combobox')).toBeDisabled()
})
it("no options doesn't show dropdown when input is empty", async () => {
mockedSearchUsers.mockResolvedValueOnce([
baseResource,
] as unknown as Awaited<ReturnType<typeof searchUsers>>);
setup();
const input = screen.getByRole("combobox");
baseResource
] as unknown as Awaited<ReturnType<typeof searchUsers>>)
setup()
const input = screen.getByRole('combobox')
await userEvent.type(input, "Room");
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
});
jest.advanceTimersByTime(300)
})
await waitFor(() => {
expect(screen.getByRole("listbox")).toBeInTheDocument();
});
expect(screen.getByRole('listbox')).toBeInTheDocument()
})
await userEvent.clear(input);
await userEvent.clear(input)
await waitFor(() => {
expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
});
});
expect(screen.queryByRole('listbox')).not.toBeInTheDocument()
})
})
it("shows 'No results' when search succeeds but returns empty array", async () => {
mockedSearchUsers.mockResolvedValueOnce([]);
setup();
mockedSearchUsers.mockResolvedValueOnce([])
setup()
const input = screen.getByRole("combobox");
await userEvent.type(input, "Room");
const input = screen.getByRole('combobox')
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
await Promise.resolve();
await Promise.resolve();
});
jest.advanceTimersByTime(300)
await Promise.resolve()
await Promise.resolve()
})
const noResults = await screen.findByText(
"resourceSearch.noResults",
'resourceSearch.noResults',
{},
{ timeout: 5000 }
);
expect(noResults).toBeInTheDocument();
});
)
expect(noResults).toBeInTheDocument()
})
it("clears options when search fails and shows error snackbar", async () => {
it('clears options when search fails and shows error snackbar', async () => {
mockedSearchUsers.mockResolvedValueOnce([
baseResource,
] as unknown as Awaited<ReturnType<typeof searchUsers>>);
setup();
baseResource
] as unknown as Awaited<ReturnType<typeof searchUsers>>)
setup()
const input = screen.getByRole("combobox");
await userEvent.type(input, "Room");
const input = screen.getByRole('combobox')
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
await Promise.resolve();
});
jest.advanceTimersByTime(300)
await Promise.resolve()
})
await waitFor(() => {
expect(screen.getByText("Projector Room")).toBeInTheDocument();
});
expect(screen.getByText('Projector Room')).toBeInTheDocument()
})
mockedSearchUsers.mockRejectedValueOnce(new Error("Network error"));
await userEvent.clear(input);
await userEvent.type(input, "Error");
mockedSearchUsers.mockRejectedValueOnce(new Error('Network error'))
await userEvent.clear(input)
await userEvent.type(input, 'Error')
await act(async () => {
jest.advanceTimersByTime(300);
await Promise.resolve();
});
jest.advanceTimersByTime(300)
await Promise.resolve()
})
const errorMessage = await screen.findByText("resourceSearch.searchError");
expect(errorMessage).toBeInTheDocument();
const errorMessage = await screen.findByText('resourceSearch.searchError')
expect(errorMessage).toBeInTheDocument()
expect(screen.queryByText("Projector Room")).not.toBeInTheDocument();
expect(screen.queryByText('Projector Room')).not.toBeInTheDocument()
mockedSearchUsers.mockResolvedValueOnce([
baseResource,
] as unknown as Awaited<ReturnType<typeof searchUsers>>);
await userEvent.clear(input);
await userEvent.type(input, "Room");
baseResource
] as unknown as Awaited<ReturnType<typeof searchUsers>>)
await userEvent.clear(input)
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
await Promise.resolve();
});
jest.advanceTimersByTime(300)
await Promise.resolve()
})
await waitFor(() => {
expect(screen.getByText("Projector Room")).toBeInTheDocument();
});
});
expect(screen.getByText('Projector Room')).toBeInTheDocument()
})
})
it("shows loading text when searching", async () => {
let resolveSearch: (value: Resource[]) => void;
const searchPromise = new Promise<Resource[]>((resolve) => {
resolveSearch = resolve;
});
it('shows loading text when searching', async () => {
let resolveSearch: (value: Resource[]) => void
const searchPromise = new Promise<Resource[]>(resolve => {
resolveSearch = resolve
})
mockedSearchUsers.mockReturnValueOnce(
searchPromise as unknown as ReturnType<typeof searchUsers>
);
setup();
)
setup()
const input = screen.getByRole("combobox");
await userEvent.type(input, "Room");
const input = screen.getByRole('combobox')
await userEvent.type(input, 'Room')
await act(async () => {
jest.advanceTimersByTime(300);
});
jest.advanceTimersByTime(300)
})
const loadingText = await screen.findByText(
"resourceSearch.loading",
'resourceSearch.loading',
{},
{ timeout: 5000 }
);
expect(loadingText).toBeInTheDocument();
)
expect(loadingText).toBeInTheDocument()
await act(async () => {
resolveSearch!([baseResource]);
await searchPromise;
});
});
});
resolveSearch!([baseResource])
await searchPromise
})
})
})