Skip to content

Commit

Permalink
Merge pull request #31 from mayank1513/refactor
Browse files Browse the repository at this point in the history
Refactor
  • Loading branch information
mayank1513 authored Jan 5, 2024
2 parents b73be75 + baed6fb commit 93861d7
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 44 deletions.
82 changes: 70 additions & 12 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { act, cleanup, fireEvent, render, screen } from "@testing-library/react";
import App from "App";
import { afterEach, beforeEach, describe, test } from "vitest";
import { afterEach, beforeEach, describe, test, vi } from "vitest";
import boardStyles from "./components/board.module.scss";
import taskStyles from "./components/task/task.module.scss";
import columnListStyles from "./components/column-list/column-list.module.scss";
import Drawer from "components/drawer";
import { scrollIntoViewMock } from "../vitest.setup";
import { handleDragEnd } from "utils/drag";
import { defaultBoard, taskId } from "utils/data";
import { DropReason } from "react-beautiful-dnd";

describe("Test Board", () => {
afterEach(cleanup);
Expand All @@ -13,7 +17,6 @@ describe("Test Board", () => {
});
test("Board Header", ({ expect }) => {
const header = screen.getByTestId("board-header");
console.log(header.textContent);
expect(header.textContent).toContain("Trello Kanban Board");
expect(header.className).toBe(boardStyles.header);
});
Expand Down Expand Up @@ -55,25 +58,80 @@ describe("Test Board", () => {
expect(screen.queryByTestId("column-3")).not.toBeInTheDocument();
});

test("Create a new task", ({ expect }) => {
test("Create a new task", async ({ expect }) => {
const columnEl = screen.getByTestId("column-0");
act(() => fireEvent.click(columnEl.getElementsByTagName("button")[0]));
await new Promise((resolve) => setTimeout(resolve, 400));
expect(columnEl.getElementsByClassName(taskStyles.task).length).toBe(2);
expect(scrollIntoViewMock).toBeCalled();
});

/** Todo: drop on another column or position */
test("Move task", async ({ expect }) => {
const columnEl = screen.getByTestId("column-0");
const taskEl = columnEl.getElementsByClassName(taskStyles.task)[0];
// simulate dragging
act(() => fireEvent.mouseDown(taskEl, { clientX: 0, clientY: 0 }));
for (let i = 0; i < 20; i++) {
act(() => fireEvent.mouseMove(taskEl, { clientX: (i * 350) / 20, clientY: (i * 510) / 20 }));
}
act(() => fireEvent.mouseUp(taskEl));
// simulate dragging -- not very effective
act(() => fireEvent.mouseDown(taskEl, { clientX: 100, clientY: 150 }));
act(() => fireEvent.mouseMove(taskEl, { clientX: 450, clientY: 500 }));
act(() => fireEvent.mouseMove(taskEl, { clientX: 650, clientY: 300 }));
act(() => fireEvent.mouseUp(taskEl, { clientX: 650, clientY: 300 }));
expect(columnEl.getElementsByClassName(taskStyles.task).length).toBe(2);
});

test("handleDragEnd - move task", async ({ expect }) => {
const setStateFn = vi.fn();
handleDragEnd(
{
source: { droppableId: "column-todo", index: 0 },
destination: { droppableId: "column-doing", index: 0 },
draggableId: taskId,
reason: "DROP" as DropReason,
type: "DEFAULT",
mode: "FLUID",
combine: null,
},
JSON.parse(JSON.stringify(defaultBoard)),
setStateFn
);
expect(setStateFn).toBeCalled();
});

test("handleDragEnd - move task out of range", async ({ expect }) => {
const setStateFn = vi.fn();
handleDragEnd(
{
source: { droppableId: "column-todo", index: 0 },
destination: { droppableId: "columns", index: 5 },
draggableId: taskId,
reason: "DROP" as DropReason,
type: "DEFAULT",
mode: "FLUID",
combine: null,
},
JSON.parse(JSON.stringify(defaultBoard)),
setStateFn
);
expect(setStateFn).toBeCalled();
});

test("handleDragEnd - move column", async ({ expect }) => {
const setStateFn = vi.fn();
handleDragEnd(
{
source: { droppableId: "columns", index: 0 },
destination: { droppableId: "columns", index: 1 },
draggableId: "column-todo",
reason: "DROP" as DropReason,
type: "DEFAULT",
mode: "FLUID",
combine: null,
},
JSON.parse(JSON.stringify(defaultBoard)),
setStateFn
);
expect(setStateFn).toBeCalled();
});

test("Remove task", async ({ expect }) => {
const columnEl = screen.getByTestId("column-0");
const taskEl = columnEl.getElementsByClassName(taskStyles.task)[0];
Expand All @@ -92,19 +150,19 @@ describe("Test Board", () => {
});

test("Drawer", ({ expect }) => {
render(<Drawer open scope="Global" />);
act(() => render(<Drawer open scope="Global" />));
act(() => fireEvent.click(screen.getByText("⚙")));
expect(screen.getByText("Settings")).toBeDefined();
});
test("Drawer -> Global", ({ expect }) => {
render(<Drawer open scope="Global" />);
act(() => render(<Drawer open scope="Global" />));
const el = screen.getByText("📋 Open TKB (Workspace)");
expect(el).toBeDefined();
act(() => fireEvent.click(el));
});

test("Drawer -> Workspace", ({ expect }) => {
render(<Drawer open scope="Workspace" />);
act(() => render(<Drawer open scope="Workspace" />));
const el = screen.getByText("📋 Open TKB (Global)");
expect(el).toBeDefined();
act(() => fireEvent.click(el));
Expand Down
32 changes: 1 addition & 31 deletions src/components/board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import ColumnList from "./column-list";
import { DragDropContext, DropResult } from "react-beautiful-dnd";
import { ForkMe } from "@mayank1513/fork-me/server";
import "@mayank1513/fork-me/server/index.css";
import { BoardType } from "@/interface";
import DrawerToggle from "./drawer-toggle";
import { useState } from "react";
import Drawer from "./drawer";
import { handleDragEnd } from "utils/drag";

export default function Board() {
const { state, setState } = useGlobalState();
Expand All @@ -32,36 +32,6 @@ export default function Board() {
);
}

function handleDragEnd(result: DropResult, state: BoardType, setState: (state: BoardType) => void) {
const { source, destination, draggableId } = result;
if (!destination) return;

if (destination.droppableId === source.droppableId && destination.index === source.index) return;

/** column id always starts with "column-" */
const columns = [...state.columns];
if (draggableId.startsWith("column-")) {
const column = columns.splice(source.index, 1)[0];
columns.splice(destination.index, 0, column);
setState({ ...state, columns: columns });
} else {
const sourceCol = columns.find((c) => c.id === source.droppableId);
let destinationCol;
if (destination.droppableId === "columns") {
destinationCol = columns[Math.min(destination.index, columns.length - 1)];
} else {
destinationCol = columns.find((c) => c.id === destination.droppableId);
}
const taskId = sourceCol?.tasksIds.splice(source.index, 1)[0];
const tasks = { ...state.tasks };
if (taskId) {
tasks[taskId].columnId = destination.droppableId;
destinationCol?.tasksIds.splice(destination.index, 0, taskId);
setState({ ...state, columns });
}
}
}

function BrowserOnlyUI() {
return (
<>
Expand Down
2 changes: 1 addition & 1 deletion src/utils/data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BoardType } from "@/interface";
import { nanoid } from "nanoid";

const taskId = "task-" + nanoid();
export const taskId = "task-" + nanoid();
export const defaultBoard: BoardType = {
scope: "",
tasks: {
Expand Down
32 changes: 32 additions & 0 deletions src/utils/drag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { BoardType } from "@/interface";
import { DropResult } from "react-beautiful-dnd";

export function handleDragEnd(result: DropResult, state: BoardType, setState: (state: BoardType) => void) {
const { source, destination, draggableId } = result;
if (!destination) return;

if (destination.droppableId === source.droppableId && destination.index === source.index) return;

/** column id always starts with "column-" */
const columns = [...state.columns];
if (draggableId.startsWith("column-")) {
const column = columns.splice(source.index, 1)[0];
columns.splice(destination.index, 0, column);
setState({ ...state, columns: columns });
} else {
const sourceCol = columns.find((c) => c.id === source.droppableId);
let destinationCol;
if (destination.droppableId === "columns") {
destinationCol = columns[Math.min(destination.index, columns.length - 1)];
} else {
destinationCol = columns.find((c) => c.id === destination.droppableId);
}
const taskId = sourceCol?.tasksIds.splice(source.index, 1)[0];
const tasks = { ...state.tasks };
if (taskId) {
tasks[taskId].columnId = destination.droppableId;
destinationCol?.tasksIds.splice(destination.index, 0, taskId);
setState({ ...state, columns });
}
}
}
5 changes: 5 additions & 0 deletions vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
import "@testing-library/jest-dom";
import { vi } from "vitest";

export const scrollIntoViewMock = vi.fn();

window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;

0 comments on commit 93861d7

Please sign in to comment.