Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -12,7 +12,6 @@ import {
isFetchingTemplatesSelector,
} from "selectors/templatesSelectors";
import BuildingBlock from "../BuildingBlock";
import FixedHeightTemplate from "../Template/FixedHeightTemplate";
import RequestTemplate from "../Template/RequestTemplate";
import LoadingScreen from "../TemplatesModal/LoadingScreen";
import {
Expand All @@ -25,6 +24,7 @@ import {
TemplateGrid,
Wrapper,
} from "./StyledComponents";
import FixedHeightTemplate from "../Template/FixedHeightTemplate";

interface StartWithTemplateListProps {
isForkingEnabled: boolean;
Expand Down
105 changes: 105 additions & 0 deletions app/client/src/pages/Templates/Template/TemplateCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React from "react";
import "@testing-library/jest-dom";
import { render, screen, fireEvent } from "@testing-library/react";
import { ThemeProvider } from "styled-components";
import { lightTheme } from "selectors/themeSelectors";
import { TemplateLayout } from ".";
import { Router } from "react-router";
import history from "utils/history";
import { templateIdUrl } from "@appsmith/RouteBuilder";
import FixedHeightTemplate from "./FixedHeightTemplate";
import { unitTestMockTemplate } from "../test_config";

jest.mock("react-redux", () => {
const originalModule = jest.requireActual("react-redux");
return {
...originalModule,
useDispatch: () => jest.fn(),
useSelector: () => jest.fn(),
};
});

jest.mock("./LargeTemplate", () => ({
__esModule: true,
default: () => <div data-testid="mocked-large-template" />,
}));

const BaseTemplateRender = () => (
<ThemeProvider theme={lightTheme}>
<TemplateLayout
hideForkTemplateButton={false}
template={unitTestMockTemplate}
/>
</ThemeProvider>
);
Comment on lines +27 to +34
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The BaseTemplateRender function is a good utility for rendering the component with default props to avoid repetition in tests. However, it's not wrapped in a Router, which might be necessary for tests that involve navigation.

- const BaseTemplateRender = () => (
+ const BaseTemplateRender = ({ historyMock }) => (
+   <Router history={historyMock || history}>
    <ThemeProvider theme={lightTheme}>
      <TemplateLayout
        hideForkTemplateButton={false}
        template={unitTestMockTemplate}
      />
    </ThemeProvider>
+   </Router>
  );

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
const BaseTemplateRender = () => (
<ThemeProvider theme={lightTheme}>
<TemplateLayout
hideForkTemplateButton={false}
template={unitTestMockTemplate}
/>
</ThemeProvider>
);
const BaseTemplateRender = ({ historyMock }) => (
<Router history={historyMock || history}>
<ThemeProvider theme={lightTheme}>
<TemplateLayout
hideForkTemplateButton={false}
template={unitTestMockTemplate}
/>
</ThemeProvider>
</Router>
);


describe("<TemplateLayout />", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it("renders template details correctly", () => {
render(<BaseTemplateRender />);
expect(screen.getByText(unitTestMockTemplate.title)).toBeInTheDocument();
expect(
screen.getByText(unitTestMockTemplate.description),
).toBeInTheDocument();
expect(screen.getByAltText("Template Thumbnail")).toBeInTheDocument();
});

it("navigates to the template URL when clicked", () => {
render(<Router history={history}>{BaseTemplateRender()}</Router>);
const pushMock = jest.spyOn(history, "push");
fireEvent.click(screen.getByText(unitTestMockTemplate.title));
expect(pushMock).toHaveBeenCalledWith(
templateIdUrl({ id: unitTestMockTemplate.id }),
);
Comment on lines +50 to +56
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The test case "navigates to the template URL when clicked" correctly mocks the history.push function and asserts that it is called with the correct URL. However, the BaseTemplateRender function should be called with a mock history object to isolate the test.

- render(<Router history={history}>{BaseTemplateRender()}</Router>);
+ const historyMock = { push: jest.fn(), listen: jest.fn(), location: {} };
+ render(BaseTemplateRender({ historyMock }));
- const pushMock = jest.spyOn(history, "push");
+ const pushMock = historyMock.push;

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
it("navigates to the template URL when clicked", () => {
render(<Router history={history}>{BaseTemplateRender()}</Router>);
const pushMock = jest.spyOn(history, "push");
fireEvent.click(screen.getByText(unitTestMockTemplate.title));
expect(pushMock).toHaveBeenCalledWith(
templateIdUrl({ id: unitTestMockTemplate.id }),
);
it("navigates to the template URL when clicked", () => {
const historyMock = { push: jest.fn(), listen: jest.fn(), location: {} };
render(BaseTemplateRender({ historyMock }));
const pushMock = historyMock.push;
fireEvent.click(screen.getByText(unitTestMockTemplate.title));
expect(pushMock).toHaveBeenCalledWith(
templateIdUrl({ id: unitTestMockTemplate.id }),
);

});

it("does not trigger onForkTemplateClick when the button is hidden", () => {
const onForkTemplateClick = jest.fn();
render(
<ThemeProvider theme={lightTheme}>
<TemplateLayout
hideForkTemplateButton
onForkTemplateClick={onForkTemplateClick}
template={unitTestMockTemplate}
/>
</ThemeProvider>,
);
fireEvent.click(screen.getByText(unitTestMockTemplate.title));
expect(onForkTemplateClick).not.toHaveBeenCalled();
});

it("renders fixed height template styling correctly", () => {
render(
<ThemeProvider theme={lightTheme}>
<FixedHeightTemplate
hideForkTemplateButton={false}
template={unitTestMockTemplate}
/>
,
</ThemeProvider>,
);

const titleElement = screen.getByText(unitTestMockTemplate.title);
expect(titleElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");

const categoriesElement = screen.getByText(
"Operations • Communications • All",
);
expect(categoriesElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");

const descriptionElement = screen.getByText(
unitTestMockTemplate.description,
);
expect(descriptionElement).toHaveStyle("height: 85px");
expect(descriptionElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");

const imageElement = screen.getByAltText("Template Thumbnail");
expect(imageElement).toHaveStyle("height: 180px");
});
Comment on lines +74 to +104
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The test case "renders fixed height template styling correctly" checks for specific styles applied to elements. However, there are repeated checks for the display: -webkit-box style on the titleElement which seems to be a copy-paste error and should be applied to the correct elements.

- expect(titleElement).toHaveStyle("display: -webkit-box");
+ expect(categoriesElement).toHaveStyle("display: -webkit-box");
- expect(titleElement).toHaveStyle("display: -webkit-box");
+ expect(descriptionElement).toHaveStyle("display: -webkit-box");

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
it("renders fixed height template styling correctly", () => {
render(
<ThemeProvider theme={lightTheme}>
<FixedHeightTemplate
hideForkTemplateButton={false}
template={unitTestMockTemplate}
/>
,
</ThemeProvider>,
);
const titleElement = screen.getByText(unitTestMockTemplate.title);
expect(titleElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");
const categoriesElement = screen.getByText(
"Operations • Communications • All",
);
expect(categoriesElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");
const descriptionElement = screen.getByText(
unitTestMockTemplate.description,
);
expect(descriptionElement).toHaveStyle("height: 85px");
expect(descriptionElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");
const imageElement = screen.getByAltText("Template Thumbnail");
expect(imageElement).toHaveStyle("height: 180px");
});
it("renders fixed height template styling correctly", () => {
render(
<ThemeProvider theme={lightTheme}>
<FixedHeightTemplate
hideForkTemplateButton={false}
template={unitTestMockTemplate}
/>
,
</ThemeProvider>,
);
const titleElement = screen.getByText(unitTestMockTemplate.title);
expect(titleElement).toHaveStyle("overflow: hidden");
expect(titleElement).toHaveStyle("display: -webkit-box");
const categoriesElement = screen.getByText(
"Operations • Communications • All",
);
expect(categoriesElement).toHaveStyle("overflow: hidden");
expect(categoriesElement).toHaveStyle("display: -webkit-box");
const descriptionElement = screen.getByText(
unitTestMockTemplate.description,
);
expect(descriptionElement).toHaveStyle("height: 85px");
expect(descriptionElement).toHaveStyle("overflow: hidden");
expect(descriptionElement).toHaveStyle("display: -webkit-box");
const imageElement = screen.getByAltText("Template Thumbnail");
expect(imageElement).toHaveStyle("height: 180px");
});

});
5 changes: 3 additions & 2 deletions app/client/src/pages/Templates/Template/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function TemplateLayout(props: TemplateLayoutProps) {
onClick={onClick}
>
<ImageWrapper className="image-wrapper">
<StyledImage src={screenshotUrls[0]} />
<StyledImage alt="Template Thumbnail" src={screenshotUrls[0]} />
</ImageWrapper>
<TemplateContent className="template-content">
<Text className="title" kind="heading-m" renderAs="h1">
Expand Down Expand Up @@ -176,7 +176,8 @@ export function TemplateLayout(props: TemplateLayoutProps) {
>
<Button
className="t--fork-template fork-button"
isDisabled={isImportingTemplateToApp}
data-testid="t--fork-template-button"
isDisabled={isImportingTemplateToApp ? true : false}
isIconButton
isLoading={
props.onForkTemplateClick && loadingTemplateId === id
Expand Down