-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/complete list logic and implement tests #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 10 commits
9f2e5be
0b825d3
5292d5f
87e493c
67f1dac
9c6072c
59d7116
218ff0a
38d7b2c
bfb6652
331f4df
b01fa61
c784a2c
44bf551
163dd9f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
module.exports = { | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
}; | ||
testEnvironment: 'jsdom', | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import React, { ReactNode } from "react"; | ||
import { render } from "@testing-library/react"; | ||
import "@testing-library/jest-dom/extend-expect"; | ||
import List, { Props as ListProps } from "./index"; | ||
|
||
interface TestRowProps { | ||
id: number; | ||
label: string; | ||
} | ||
|
||
function TestRow({ id, label }: TestRowProps) { | ||
return ( | ||
<div> | ||
{id} - {label} | ||
</div> | ||
); | ||
} | ||
|
||
interface TestEmptyProps { | ||
className?: string; | ||
message: string; | ||
} | ||
|
||
function TestEmpty({ message }: TestEmptyProps) { | ||
return ( | ||
<> | ||
<span>custom message:</span> {message} | ||
</> | ||
); | ||
} | ||
|
||
const sharedProps: ListProps<TestRowProps, TestRowProps> = { | ||
RowComponent: TestRow, | ||
rows: [ | ||
{ id: 10, label: "A" }, | ||
{ id: 11, label: "B" }, | ||
{ id: 12, label: "C" } | ||
] | ||
}; | ||
|
||
describe("The List component tests", () => { | ||
test("It should render custom EmptyComponent and message", () => { | ||
const { queryByText } = render( | ||
<List<TestRowProps, TestRowProps, TestEmptyProps> | ||
{...sharedProps} | ||
rows={[]} | ||
EmptyComponent={TestEmpty} | ||
EmptyProps={{ message: "No Data" }} | ||
/> | ||
); | ||
expect(queryByText("custom message:")).toBeInTheDocument(); | ||
}); | ||
|
||
test("It should not render EmptyComponent if hasEmpty is false", () => { | ||
const { queryByTestId } = render( | ||
<List {...sharedProps} rows={[]} hasEmpty={false} /> | ||
); | ||
expect(queryByTestId("empty-component")).toBeNull(); | ||
}); | ||
|
||
test("It should render firstChild and lastChild at correct positions", () => { | ||
const firstChild = <span data-testid="first-child" />; | ||
const lastChild = <span data-testid="last-child" />; | ||
const { getByTestId } = render( | ||
<List {...sharedProps} firstChild={firstChild} lastChild={lastChild} /> | ||
); | ||
expect(getByTestId("root").firstChild).toBe(getByTestId("first-child")); | ||
expect(getByTestId("root").lastChild).toBe(getByTestId("last-child")); | ||
}); | ||
|
||
test("It should render custom container", () => { | ||
function CustomContainer({ children }: { children: ReactNode }) { | ||
return ( | ||
<section data-testid="custom-root"> | ||
{children} | ||
</section> | ||
); | ||
} | ||
const { getByTestId } = render( | ||
<List {...sharedProps} Container={CustomContainer} /> | ||
); | ||
|
||
expect(getByTestId("custom-root")).toBeInTheDocument(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,11 @@ | ||
import React, { ComponentType, memo, ReactNode } from "react"; | ||
import React, { ComponentType, memo, ReactNode, ElementType } from "react"; | ||
import ListRows, { Props as ListRowsProps } from "../ListRows"; | ||
import Empty, { Props as EmptyProps } from "../Empty"; | ||
|
||
export interface Props<T, U = T, V extends EmptyProps = EmptyProps> | ||
extends ListRowsProps<T, U> { | ||
className?: string; | ||
Container?: ComponentType<{ className?: string; children: ReactNode }> | ElementType; | ||
|
||
EmptyComponent?: ComponentType<V>; | ||
EmptyProps?: V; | ||
hasEmpty?: boolean; | ||
|
@@ -14,6 +15,7 @@ export interface Props<T, U = T, V extends EmptyProps = EmptyProps> | |
|
||
function BList<T, U = T, V extends EmptyProps = EmptyProps>({ | ||
am1rb marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
className, | ||
Container = 'div', | ||
EmptyComponent = Empty, | ||
EmptyProps, | ||
hasEmpty = true, | ||
|
@@ -23,14 +25,14 @@ function BList<T, U = T, V extends EmptyProps = EmptyProps>({ | |
...other | ||
}: Props<T, U, V>) { | ||
return ( | ||
<div className={className}> | ||
<Container data-testid="root" className={className}> | ||
{firstChild} | ||
<ListRows rows={rows} {...other} /> | ||
{hasEmpty && rows.length === 0 && ( | ||
<EmptyComponent {...(EmptyProps as V)} /> | ||
<EmptyComponent data-testid="empty-component" {...(EmptyProps as V)} /> | ||
)} | ||
{lastChild} | ||
</div> | ||
</Container> | ||
); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React from "react"; | ||
import { render } from "@testing-library/react"; | ||
import "@testing-library/jest-dom/extend-expect"; | ||
import ListRows, { Props as ListRowsProps } from "./index"; | ||
|
||
interface TestRowProps { | ||
person: { code: number }; | ||
name: string; | ||
family: string; | ||
id: unknown; | ||
} | ||
|
||
function TestRow({ person: { code }, name, family }: TestRowProps) { | ||
return ( | ||
<div> | ||
{code} - {name} {family} | ||
</div> | ||
); | ||
} | ||
|
||
const sharedProps: ListRowsProps<TestRowProps> = { | ||
RowComponent: TestRow, | ||
rows: [ | ||
{ person: { code: 11 }, name: "Sara", family: "Doe", id: 11 }, | ||
{ person: { code: 12 }, name: "John", family: "Doe", id: 12 } | ||
], | ||
dataKey: "person.code" | ||
}; | ||
|
||
const originalError = console.error; | ||
afterEach(() => (console.error = originalError)); | ||
|
||
describe("The ListRows component tests", () => { | ||
test("It should throw an Error if the dataKey does not exist", () => { | ||
console.error = jest.fn(); | ||
try { | ||
render(<ListRows {...sharedProps} dataKey="invalid.key" />); | ||
} catch (e) { | ||
expect(e.message).toBe("The `invalid.key` property does not exist"); | ||
} | ||
}); | ||
|
||
test("It should throw an Error if the type of dataKey property is not number or string", () => { | ||
const keys = [ | ||
{ key: 11, error: false }, | ||
{ key: "11", error: false }, | ||
{ key: true, error: true }, | ||
{ key: () => {}, error: true }, | ||
{ key: new Date(), error: true }, | ||
{ key: { test: { a: "b" } }, error: true } | ||
]; | ||
|
||
console.error = jest.fn(); | ||
|
||
keys.forEach(record => { | ||
let hasError = false; | ||
try { | ||
render( | ||
<ListRows | ||
{...sharedProps} | ||
RowProps={row => ({ ...row, id: record.key })} | ||
dataKey="id" | ||
/> | ||
); | ||
} catch (e) { | ||
hasError = | ||
e.message === "The type of `id` property must be string or number"; | ||
} | ||
|
||
expect(hasError).toBe(record.error); | ||
}); | ||
}); | ||
|
||
test("It should render rows correctly", () => { | ||
const { queryByText } = render(<ListRows {...sharedProps} />); | ||
expect(queryByText("11 - Sara Doe")).toBeInTheDocument(); | ||
expect(queryByText("12 - John Doe")).toBeInTheDocument(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "./components/ListRows"; |
Uh oh!
There was an error while loading. Please reload this page.