Skip to content

Commit

Permalink
chore: Git mod - quick action bar control
Browse files Browse the repository at this point in the history
  • Loading branch information
ashit-rath committed Dec 3, 2024
1 parent 2b64e65 commit a1abdc8
Show file tree
Hide file tree
Showing 10 changed files with 1,470 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React from "react";
import { render, screen, act } from "@testing-library/react";
import AutocommitStatusbar from "./AutocommitStatusbar";
import "@testing-library/jest-dom";

// Mock timers using Jest
jest.useFakeTimers();

// Mock the Statusbar component from '@appsmith/ads-old'
jest.mock("@appsmith/ads-old", () => ({
Statusbar: ({ percentage }: { percentage: number }) => (
<div data-testid="statusbar">{percentage}%</div>
),
}));

describe("AutocommitStatusbar Component", () => {
afterEach(() => {
jest.clearAllTimers();
});

it("should render with initial percentage 0 when completed is false", () => {
render(<AutocommitStatusbar completed={false} />);
const statusbar = screen.getByTestId("statusbar");

expect(statusbar).toBeInTheDocument();
expect(statusbar).toHaveTextContent("0%");
});

it("should increment percentage over time when completed is false", () => {
render(<AutocommitStatusbar completed={false} />);
const statusbar = screen.getByTestId("statusbar");

// Initial percentage
expect(statusbar).toHaveTextContent("0%");

// Advance timer by one interval
act(() => {
jest.advanceTimersByTime((4 * 1000) / 9);
});
expect(statusbar).toHaveTextContent("10%");

// Advance timer by another interval
act(() => {
jest.advanceTimersByTime((4 * 1000) / 9);
});
expect(statusbar).toHaveTextContent("20%");

// Continue until percentage reaches 90%
act(() => {
jest.advanceTimersByTime((4 * 1000 * 7) / 9);
});
expect(statusbar).toHaveTextContent("90%");
});

it("should not increment percentage beyond 90 when completed is false", () => {
render(<AutocommitStatusbar completed={false} />);
const statusbar = screen.getByTestId("statusbar");

// Advance time beyond the total interval duration
act(() => {
jest.advanceTimersByTime(5000);
});
expect(statusbar).toHaveTextContent("90%");

// Advance time further to ensure percentage doesn't exceed 90%
act(() => {
jest.advanceTimersByTime(5000);
});
expect(statusbar).toHaveTextContent("90%");
});

it("should set percentage to 100 when completed is true", () => {
render(<AutocommitStatusbar completed />);
const statusbar = screen.getByTestId("statusbar");

expect(statusbar).toHaveTextContent("100%");
});

it("should call onHide after 1 second when completed is true", () => {
const onHide = jest.fn();

render(<AutocommitStatusbar completed onHide={onHide} />);
expect(onHide).not.toHaveBeenCalled();

// Advance timer by 1 second
act(() => {
jest.advanceTimersByTime(1000);
});
expect(onHide).toHaveBeenCalledTimes(1);
});

it("should clean up intervals and timeouts on unmount", () => {
const onHide = jest.fn();

render(<AutocommitStatusbar completed={false} onHide={onHide} />);

// Start the interval
act(() => {
jest.advanceTimersByTime((4 * 1000) / 9);
});

// Unmount the component

// Advance time to see if any timers are still running
act(() => {
jest.advanceTimersByTime(10000);
});
expect(onHide).not.toHaveBeenCalled();
});

it("should handle transition from false to true for completed prop", () => {
const onHide = jest.fn();
const { rerender } = render(
<AutocommitStatusbar completed={false} onHide={onHide} />,
);
const statusbar = screen.getByTestId("statusbar");

// Advance timer to increase percentage
act(() => {
jest.advanceTimersByTime((4 * 1000) / 9);
});
expect(statusbar).toHaveTextContent("10%");

// Update the completed prop to true
rerender(<AutocommitStatusbar completed onHide={onHide} />);
expect(statusbar).toHaveTextContent("100%");

// Ensure onHide is called after 1 second
act(() => {
jest.advanceTimersByTime(1000);
});
expect(onHide).toHaveBeenCalledTimes(1);
});

it("should not reset percentage when completed changes from true to false", () => {
const { rerender } = render(<AutocommitStatusbar completed />);
const statusbar = screen.getByTestId("statusbar");

expect(statusbar).toHaveTextContent("100%");

// Change completed to false
rerender(<AutocommitStatusbar completed={false} />);
expect(statusbar).toHaveTextContent("100%");

// Advance timer to check if percentage increments beyond 100%
act(() => {
jest.advanceTimersByTime((4 * 1000) / 9);
});
expect(statusbar).toHaveTextContent("100%");
});
});
117 changes: 117 additions & 0 deletions app/client/src/git/components/QuickActions/AutocommitStatusbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useEffect, useRef, useState } from "react";
import { Statusbar } from "@appsmith/ads-old";
import styled from "styled-components";
import {
AUTOCOMMIT_IN_PROGRESS_MESSAGE,
createMessage,
} from "ee/constants/messages";

interface AutocommitStatusbarProps {
completed: boolean;
onHide?: () => void;
}

const PROGRESSBAR_WIDTH = 150;
const PROGRESS_INTERVAL = 4 * 1000; // in ms
const MAX_PROGRESS_PERCENTAGE = 90;
const PROGRESS_INCREMENT = 10;
const STEPS = 9;

const StatusbarWrapper = styled.div`
> div {
display: flex;
height: initial;
align-items: center;
}
> div > div {
margin-top: 0px;
width: ${PROGRESSBAR_WIDTH}px;
margin-right: var(--ads-v2-spaces-4);
}
> div > p {
margin-top: 0;
}
`;

export default function AutocommitStatusbar({
completed,
onHide,
}: AutocommitStatusbarProps) {
const intervalRef = useRef<number | null>(null);
const timeoutRef = useRef<number | null>(null);
const [percentage, setPercentage] = useState(0);

// Effect for incrementing percentage when not completed
useEffect(
function incrementPercentage() {
if (!completed) {
intervalRef.current = setInterval(() => {
setPercentage((prevPercentage) => {
if (prevPercentage < MAX_PROGRESS_PERCENTAGE) {
return prevPercentage + PROGRESS_INCREMENT;
} else {
// Clear the interval when percentage reaches 90%
if (intervalRef.current !== null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}

return prevPercentage;
}
});
}, PROGRESS_INTERVAL / STEPS);
}

// Cleanup function to clear the interval
return () => {
if (intervalRef.current !== null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
},
[completed],
); // Removed 'percentage' from dependencies

// Effect for setting percentage to 100% when completed
useEffect(
function finishPercentage() {
if (completed) {
setPercentage(100);
}
},
[completed],
);

// Effect for calling onHide after 1 second when completed
useEffect(
function onCompleteCallback() {
if (completed && onHide) {
timeoutRef.current = setTimeout(() => {
onHide();
}, 1000);
}

return () => {
if (timeoutRef.current !== null) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
};
},
[completed, onHide],
);

return (
<StatusbarWrapper data-testid="t--autocommit-statusbar">
<Statusbar
active={false}
message={createMessage(AUTOCOMMIT_IN_PROGRESS_MESSAGE)}
percentage={percentage}
showOnlyMessage
/>
</StatusbarWrapper>
);
}
Loading

0 comments on commit a1abdc8

Please sign in to comment.