From 3c87f5cac93738fa15fcae9afffee55bf13a2347 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sun, 2 Mar 2025 18:34:02 +0100 Subject: [PATCH 1/4] chore: adding components for release --- app/client/src/git/ce/constants/messages.tsx | 18 +++++ .../LatestCommitInfo/LatestCommitInfoView.tsx | 41 ++++++++++++ .../git/components/LatestCommitInfo/index.tsx | 15 +++++ .../git/components/OpsModal/OpsModalView.tsx | 10 +++ .../git/components/OpsModal/TabRelease.tsx | 60 +++++++++++++++++ .../components/ReleaseNotesInput/index.tsx | 31 +++++++++ .../ReleaseVersionRadioGroupView.tsx | 67 +++++++++++++++++++ .../ReleaseVersionRadioGroup/index.tsx | 24 +++++++ app/client/src/git/constants/enums.ts | 1 + app/client/src/git/ee/constants/messages.tsx | 1 + 10 files changed, 268 insertions(+) create mode 100644 app/client/src/git/ce/constants/messages.tsx create mode 100644 app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx create mode 100644 app/client/src/git/components/LatestCommitInfo/index.tsx create mode 100644 app/client/src/git/components/OpsModal/TabRelease.tsx create mode 100644 app/client/src/git/components/ReleaseNotesInput/index.tsx create mode 100644 app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx create mode 100644 app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx create mode 100644 app/client/src/git/ee/constants/messages.tsx diff --git a/app/client/src/git/ce/constants/messages.tsx b/app/client/src/git/ce/constants/messages.tsx new file mode 100644 index 000000000000..0978898423ff --- /dev/null +++ b/app/client/src/git/ce/constants/messages.tsx @@ -0,0 +1,18 @@ +export const OPS_MODAL = { + TAB_RELEASE: "RELEASE", +}; + +export const TAB_RELEASE = { + TITLE: "Release version", + RELEASE_BTN: "Release", +}; + +export const RELEASE_VERSION_RADIO_GROUP = { + TITLE: "Version", + LAST_RELEASED: "Last released", +}; + +export const RELEASE_NOTES_INPUT = { + TITLE: "Release notes", + PLACEHOLDER: "Your release notes here", +}; diff --git a/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx b/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx new file mode 100644 index 000000000000..b2544173eb67 --- /dev/null +++ b/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx @@ -0,0 +1,41 @@ +import { Flex, Icon, Text } from "@appsmith/ads"; +import React from "react"; +import styled from "styled-components"; + +const Container = styled(Flex)` + border-radius: 4px; + background-color: var(--ads-v2-color-gray-0); +`; + +interface LatestCommitInfoViewProps { + authorName: string | null; + committedAt: string | null; + hash: string | null; + message: string | null; +} + +function LatestCommitInfoView({ + authorName = null, + committedAt = null, + hash = null, + message = null, +}: LatestCommitInfoViewProps) { + return ( + + + {message} + + {authorName} committed {committedAt} + + + + + + {hash} + + + + ); +} + +export default LatestCommitInfoView; diff --git a/app/client/src/git/components/LatestCommitInfo/index.tsx b/app/client/src/git/components/LatestCommitInfo/index.tsx new file mode 100644 index 000000000000..b5d4c9f6e68d --- /dev/null +++ b/app/client/src/git/components/LatestCommitInfo/index.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import LatestCommitInfoView from "./LatestCommitInfoView"; + +function LatestCommitInfo() { + return ( + + ); +} + +export default LatestCommitInfo; diff --git a/app/client/src/git/components/OpsModal/OpsModalView.tsx b/app/client/src/git/components/OpsModal/OpsModalView.tsx index a0f696a747f4..4841c5519613 100644 --- a/app/client/src/git/components/OpsModal/OpsModalView.tsx +++ b/app/client/src/git/components/OpsModal/OpsModalView.tsx @@ -15,6 +15,8 @@ import styled from "styled-components"; // import ReconnectSSHError from "../components/ReconnectSSHError"; import { GitOpsTab } from "git/constants/enums"; import noop from "lodash/noop"; +import TabRelease from "./TabRelease"; +import { OPS_MODAL } from "git/ee/constants/messages"; const StyledModalContent = styled(ModalContent)` &&& { @@ -91,10 +93,18 @@ function OpsModalView({ > {createMessage(MERGE)} + + {OPS_MODAL.TAB_RELEASE} + {opsModalTab === GitOpsTab.Deploy && } {opsModalTab === GitOpsTab.Merge && } + {opsModalTab === GitOpsTab.Release && } {/* */} diff --git a/app/client/src/git/components/OpsModal/TabRelease.tsx b/app/client/src/git/components/OpsModal/TabRelease.tsx new file mode 100644 index 000000000000..b1ce504ac26e --- /dev/null +++ b/app/client/src/git/components/OpsModal/TabRelease.tsx @@ -0,0 +1,60 @@ +import { Button, ModalBody, ModalFooter, Text } from "@appsmith/ads"; +import LatestCommitInfo from "git/components/LatestCommitInfo"; +import ReleaseNotesInput from "git/components/ReleaseNotesInput"; +import ReleaseVersionRadioGroup from "git/components/ReleaseVersionRadioGroup"; +import { TAB_RELEASE } from "git/ee/constants/messages"; +import React, { useCallback, useState } from "react"; +import styled from "styled-components"; + +const Container = styled.div` + min-height: 360px; + overflow: unset; + padding-bottom: 4px; +`; + +const TabTitle = styled(Text)` + margin-bottom: 12px; + color: var(--ads-v2-color-fg-emphasis); +`; + +const StyledModalFooter = styled(ModalFooter)` + min-height: 52px; +`; + +function TabRelease() { + const [releaseVersion, setReleaseVersion] = useState(null); + const [releaseNotes, setReleaseNotes] = useState(null); + + const isReleaseDisabled = !releaseVersion || !releaseNotes; + + const handleClickOnRelease = useCallback(() => {}, []); + + return ( + <> + + + + {TAB_RELEASE.TITLE} + + + + + + + + + + + ); +} + +export default TabRelease; diff --git a/app/client/src/git/components/ReleaseNotesInput/index.tsx b/app/client/src/git/components/ReleaseNotesInput/index.tsx new file mode 100644 index 000000000000..4936efe69347 --- /dev/null +++ b/app/client/src/git/components/ReleaseNotesInput/index.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import { Flex, Input } from "@appsmith/ads"; +import { RELEASE_NOTES_INPUT } from "git/ee/constants/messages"; +import { noop } from "lodash"; + +interface ReleaseNotesInputProps { + onTextChange: (text: string | null) => void; + text: string | null; +} + +function ReleaseNotesInput({ + onTextChange = noop, + text = null, +}: ReleaseNotesInputProps) { + return ( + + + + ); +} + +export default ReleaseNotesInput; diff --git a/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx b/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx new file mode 100644 index 000000000000..5d9e9486cdf6 --- /dev/null +++ b/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx @@ -0,0 +1,67 @@ +import React, { useCallback, useEffect, useMemo, useState } from "react"; +import { Flex, Radio, RadioGroup, Tag, Text } from "@appsmith/ads"; +import { RELEASE_VERSION_RADIO_GROUP } from "git/ee/constants/messages"; +import { inc } from "semver"; +import noop from "lodash/noop"; + +type ReleaseType = "major" | "minor" | "patch" | null; + +interface ReleaseVersionRadioGroupViewProps { + currentVersion: string | null; + onVersionChange: (value: string | null) => void; + releasedAt: string | null; +} + +function ReleaseVersionRadioGroupView({ + currentVersion = null, + onVersionChange = noop, + releasedAt = null, +}: ReleaseVersionRadioGroupViewProps) { + const [releaseType, setReleaseType] = useState("patch"); + + const nextVersion = useMemo(() => { + if (!currentVersion || !releaseType) return null; + + return inc(currentVersion, releaseType); + }, [currentVersion, releaseType]); + + useEffect( + function releaseVersionChangeEffect() { + onVersionChange(nextVersion); + }, + [nextVersion, onVersionChange], + ); + + const handleRadioChange = useCallback((value: string) => { + setReleaseType(value as ReleaseType); + }, []); + + return ( + + {RELEASE_VERSION_RADIO_GROUP.TITLE} + + + + {nextVersion ?? "-"} + + + + Major + Minor + Patch + + + + {RELEASE_VERSION_RADIO_GROUP.LAST_RELEASED}: {currentVersion ?? "-"} ( + {releasedAt ?? "-"}) + + + ); +} + +export default ReleaseVersionRadioGroupView; diff --git a/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx b/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx new file mode 100644 index 000000000000..15e72b1b9a86 --- /dev/null +++ b/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import ReleaseVersionRadioGroupView from "./ReleaseVersionRadioGroupView"; +import noop from "lodash/noop"; + +interface ReleaseVersionRadioGroupProps { + onVersionChange: (version: string | null) => void; +} + +function ReleaseVersionRadioGroup({ + onVersionChange = noop, +}: ReleaseVersionRadioGroupProps) { + const currentVersion = "4.1.2"; + const releasedAt = "2 weeks ago"; + + return ( + + ); +} + +export default ReleaseVersionRadioGroup; diff --git a/app/client/src/git/constants/enums.ts b/app/client/src/git/constants/enums.ts index af2fb31513a6..b979b66645ed 100644 --- a/app/client/src/git/constants/enums.ts +++ b/app/client/src/git/constants/enums.ts @@ -7,6 +7,7 @@ export enum GitArtifactType { export enum GitOpsTab { Deploy = "Deploy", Merge = "Merge", + Release = "Release", } export enum GitSettingsTab { diff --git a/app/client/src/git/ee/constants/messages.tsx b/app/client/src/git/ee/constants/messages.tsx new file mode 100644 index 000000000000..ca3e37386344 --- /dev/null +++ b/app/client/src/git/ee/constants/messages.tsx @@ -0,0 +1 @@ +export * from "../../ce/constants/messages"; From 8b8226bc3a003c9c99aae2f94b3e3daeb9046a87 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sun, 2 Mar 2025 20:11:03 +0100 Subject: [PATCH 2/4] chore: adding store for latest commit actions --- .../LatestCommitInfo/LatestCommitInfoView.tsx | 4 +- .../git/components/LatestCommitInfo/index.tsx | 11 ++++-- .../git/components/OpsModal/OpsModalView.tsx | 10 ----- app/client/src/git/hooks/useLatestCommit.ts | 29 ++++++++++++++ .../git/requests/fetchLatestCommitRequest.ts | 15 ++++++++ .../fetchLatestCommitRequest.types.ts | 11 ++++++ .../store/actions/fetchLatestCommitActions.ts | 38 +++++++++++++++++++ app/client/src/git/store/gitArtifactSlice.ts | 8 ++++ .../src/git/store/helpers/initialState.ts | 5 +++ .../store/selectors/gitArtifactSelectors.ts | 5 +++ app/client/src/git/store/types.ts | 2 + 11 files changed, 122 insertions(+), 16 deletions(-) create mode 100644 app/client/src/git/hooks/useLatestCommit.ts create mode 100644 app/client/src/git/requests/fetchLatestCommitRequest.ts create mode 100644 app/client/src/git/requests/fetchLatestCommitRequest.types.ts create mode 100644 app/client/src/git/store/actions/fetchLatestCommitActions.ts diff --git a/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx b/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx index b2544173eb67..fc6fb1ce671f 100644 --- a/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx +++ b/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.tsx @@ -25,13 +25,13 @@ function LatestCommitInfoView({ {message} - {authorName} committed {committedAt} + {authorName ?? "-"} committed {committedAt ?? "-"} - {hash} + {hash ?? "-"} diff --git a/app/client/src/git/components/LatestCommitInfo/index.tsx b/app/client/src/git/components/LatestCommitInfo/index.tsx index b5d4c9f6e68d..ce04d0695e36 100644 --- a/app/client/src/git/components/LatestCommitInfo/index.tsx +++ b/app/client/src/git/components/LatestCommitInfo/index.tsx @@ -1,13 +1,16 @@ import React from "react"; import LatestCommitInfoView from "./LatestCommitInfoView"; +import useLatestCommit from "git/hooks/useLatestCommit"; function LatestCommitInfo() { + const { latestCommit } = useLatestCommit(); + return ( ); } diff --git a/app/client/src/git/components/OpsModal/OpsModalView.tsx b/app/client/src/git/components/OpsModal/OpsModalView.tsx index 4841c5519613..a0f696a747f4 100644 --- a/app/client/src/git/components/OpsModal/OpsModalView.tsx +++ b/app/client/src/git/components/OpsModal/OpsModalView.tsx @@ -15,8 +15,6 @@ import styled from "styled-components"; // import ReconnectSSHError from "../components/ReconnectSSHError"; import { GitOpsTab } from "git/constants/enums"; import noop from "lodash/noop"; -import TabRelease from "./TabRelease"; -import { OPS_MODAL } from "git/ee/constants/messages"; const StyledModalContent = styled(ModalContent)` &&& { @@ -93,18 +91,10 @@ function OpsModalView({ > {createMessage(MERGE)} - - {OPS_MODAL.TAB_RELEASE} - {opsModalTab === GitOpsTab.Deploy && } {opsModalTab === GitOpsTab.Merge && } - {opsModalTab === GitOpsTab.Release && } {/* */} diff --git a/app/client/src/git/hooks/useLatestCommit.ts b/app/client/src/git/hooks/useLatestCommit.ts new file mode 100644 index 000000000000..2d96ece707de --- /dev/null +++ b/app/client/src/git/hooks/useLatestCommit.ts @@ -0,0 +1,29 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import useArtifactSelector from "./useArtifactSelector"; +import { selectLatestCommitState } from "git/store/selectors/gitArtifactSelectors"; +import { useDispatch } from "react-redux"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { useCallback } from "react"; + +export default function useLatestCommit() { + const dispatch = useDispatch(); + const { artifact, artifactDef } = useGitContext(); + const artifactId = artifact?.id; + + const latestCommitState = useArtifactSelector(selectLatestCommitState); + + const fetchLatestCommit = useCallback(() => { + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.fetchLatestCommitInit({ artifactDef, artifactId }), + ); + } + }, [artifactDef, artifactId, dispatch]); + + return { + latestCommit: latestCommitState?.value ?? null, + isLatestCommitLoading: latestCommitState?.loading ?? false, + latestCommitError: latestCommitState?.error ?? null, + fetchLatestCommit, + }; +} diff --git a/app/client/src/git/requests/fetchLatestCommitRequest.ts b/app/client/src/git/requests/fetchLatestCommitRequest.ts new file mode 100644 index 000000000000..e1c2fb150650 --- /dev/null +++ b/app/client/src/git/requests/fetchLatestCommitRequest.ts @@ -0,0 +1,15 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import type { AxiosPromise } from "axios"; +import type { GitArtifactType } from "git/constants/enums"; +import type { FetchLatestCommitResponse } from "./fetchLatestCommitRequest.types"; +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; + +export default async function fetchLatestCommitRequest( + artifactType: GitArtifactType, + branchedArtifactId: string, +): AxiosPromise { + return Api.get( + `${GIT_BASE_URL}/${artifactType}/${branchedArtifactId}/commit/latest`, + ); +} diff --git a/app/client/src/git/requests/fetchLatestCommitRequest.types.ts b/app/client/src/git/requests/fetchLatestCommitRequest.types.ts new file mode 100644 index 000000000000..c48e8c3ae071 --- /dev/null +++ b/app/client/src/git/requests/fetchLatestCommitRequest.types.ts @@ -0,0 +1,11 @@ +import type { ApiResponse } from "api/types"; + +export interface FetchLatestCommitResponseData { + authorName: string; + committedAt: string; + hash: string; + message: string; +} + +export type FetchLatestCommitResponse = + ApiResponse; diff --git a/app/client/src/git/store/actions/fetchLatestCommitActions.ts b/app/client/src/git/store/actions/fetchLatestCommitActions.ts new file mode 100644 index 000000000000..dfb842d657de --- /dev/null +++ b/app/client/src/git/store/actions/fetchLatestCommitActions.ts @@ -0,0 +1,38 @@ +import type { + GitArtifactErrorPayloadAction, + GitAsyncSuccessPayload, +} from "../types"; +import { createArtifactAction } from "../helpers/createArtifactAction"; +import type { FetchLatestCommitResponseData } from "git/requests/fetchLatestCommitRequest.types"; + +export interface FetchLatestCommitInitPayload { + artifactId: string; +} + +export const fetchLatestCommitInitAction = + createArtifactAction((state) => { + state.apiResponses.latestCommit.loading = true; + state.apiResponses.latestCommit.error = null; + + return state; + }); + +export const fetchLatestCommitSuccessAction = createArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.latestCommit.loading = false; + state.apiResponses.latestCommit.value = action.payload.responseData; + + return state; +}); + +export const fetchLatestCommitErrorAction = createArtifactAction( + (state, action: GitArtifactErrorPayloadAction) => { + const { error } = action.payload; + + state.apiResponses.latestCommit.loading = false; + state.apiResponses.latestCommit.error = error; + + return state; + }, +); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 25e295366c05..f5bdcac8801f 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -141,6 +141,11 @@ import { resetCurrentBranchAction, updateCurrentBranchAction, } from "./actions/currentBranchActions"; +import { + fetchLatestCommitErrorAction, + fetchLatestCommitInitAction, + fetchLatestCommitSuccessAction, +} from "./actions/fetchLatestCommitActions"; const initialState: GitArtifactRootReduxState = {}; @@ -205,6 +210,9 @@ export const gitArtifactSlice = createSlice({ pullError: pullErrorAction, toggleOpsModal: toggleOpsModalAction, toggleConflictErrorModal: toggleConflictErrorModalAction, + fetchLatestCommitInit: fetchLatestCommitInitAction, + fetchLatestCommitSuccess: fetchLatestCommitSuccessAction, + fetchLatestCommitError: fetchLatestCommitErrorAction, // branches fetchBranchesInit: fetchBranchesInitAction, diff --git a/app/client/src/git/store/helpers/initialState.ts b/app/client/src/git/store/helpers/initialState.ts index 0528d5945cc6..1781a28342f7 100644 --- a/app/client/src/git/store/helpers/initialState.ts +++ b/app/client/src/git/store/helpers/initialState.ts @@ -52,6 +52,11 @@ const gitArtifactInitialAPIResponses: GitArtifactAPIResponsesReduxState = { loading: false, error: null, }, + latestCommit: { + value: null, + loading: false, + error: null, + }, pull: { loading: false, error: null, diff --git a/app/client/src/git/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/store/selectors/gitArtifactSelectors.ts index eb8f7aab0c49..6df75a63b210 100644 --- a/app/client/src/git/store/selectors/gitArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitArtifactSelectors.ts @@ -88,6 +88,11 @@ export const selectCommitState = ( artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.commit; +export const selectLatestCommitState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses?.latestCommit; + export const selectDiscardState = ( state: GitRootState, artifactDef: GitArtifactDef, diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index e6d1231679fd..e62b7ec47990 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -19,6 +19,7 @@ import type { import type { FetchGlobalSSHKeyResponseData } from "git/requests/fetchGlobalSSHKeyRequest.types"; import type { FetchRefsResponseData } from "git/requests/fetchRefsRequest.types"; import type { GitArtifactDef } from "git/types"; +import type { FetchLatestCommitResponseData } from "git/requests/fetchLatestCommitRequest.types"; export interface GitApiError extends ApiResponseError { errorType?: string; @@ -41,6 +42,7 @@ export interface GitArtifactAPIResponsesReduxState connect: GitAsyncStateWithoutValue; status: GitAsyncState; commit: GitAsyncStateWithoutValue; + latestCommit: GitAsyncState; pull: GitAsyncStateWithoutValue; discard: GitAsyncStateWithoutValue; mergeStatus: GitAsyncState; From 89b8c96b41776f56bab9f460c5f4076bb63233f5 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sun, 2 Mar 2025 20:14:20 +0100 Subject: [PATCH 3/4] chore: removing hardcoded values --- .../src/git/components/ReleaseVersionRadioGroup/index.tsx | 8 ++++---- .../src/git/requests/fetchLatestCommitRequest.types.ts | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx b/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx index 15e72b1b9a86..a117dea1dc34 100644 --- a/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx +++ b/app/client/src/git/components/ReleaseVersionRadioGroup/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import ReleaseVersionRadioGroupView from "./ReleaseVersionRadioGroupView"; import noop from "lodash/noop"; +import useLatestCommit from "git/hooks/useLatestCommit"; interface ReleaseVersionRadioGroupProps { onVersionChange: (version: string | null) => void; @@ -9,14 +10,13 @@ interface ReleaseVersionRadioGroupProps { function ReleaseVersionRadioGroup({ onVersionChange = noop, }: ReleaseVersionRadioGroupProps) { - const currentVersion = "4.1.2"; - const releasedAt = "2 weeks ago"; + const { latestCommit } = useLatestCommit(); return ( ); } diff --git a/app/client/src/git/requests/fetchLatestCommitRequest.types.ts b/app/client/src/git/requests/fetchLatestCommitRequest.types.ts index c48e8c3ae071..3a21cc31edcc 100644 --- a/app/client/src/git/requests/fetchLatestCommitRequest.types.ts +++ b/app/client/src/git/requests/fetchLatestCommitRequest.types.ts @@ -5,6 +5,8 @@ export interface FetchLatestCommitResponseData { committedAt: string; hash: string; message: string; + releaseTagName: string; + releasedAt: string; } export type FetchLatestCommitResponse = From e7ee3853fa50a1dde5c572f924cf86cf3b81126b Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sun, 2 Mar 2025 20:59:55 +0100 Subject: [PATCH 4/4] chore: adding unit tests --- .../LatestCommitInfoView.test.tsx | 94 +++++++++++++++++++ .../components/ReleaseNotesInput/index.tsx | 1 + .../ReleaseVersionRadioGroupView.test.tsx | 72 ++++++++++++++ .../ReleaseVersionRadioGroupView.tsx | 12 ++- 4 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.test.tsx create mode 100644 app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.test.tsx diff --git a/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.test.tsx b/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.test.tsx new file mode 100644 index 000000000000..f5cfcf517c65 --- /dev/null +++ b/app/client/src/git/components/LatestCommitInfo/LatestCommitInfoView.test.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { render } from "@testing-library/react"; +import LatestCommitInfoView from "./LatestCommitInfoView"; +import "@testing-library/jest-dom"; + +describe("LatestCommitInfoView", () => { + it("renders correctly with all props", () => { + const { getByText } = render( + , + ); + + expect(getByText("Initial commit")).toBeInTheDocument(); + expect(getByText("John Doe committed 2025-03-01")).toBeInTheDocument(); + expect(getByText("abc123")).toBeInTheDocument(); + }); + + it("renders correctly with null authorName", () => { + const { getByText } = render( + , + ); + + expect(getByText("Initial commit")).toBeInTheDocument(); + expect(getByText("- committed 2025-03-01")).toBeInTheDocument(); + expect(getByText("abc123")).toBeInTheDocument(); + }); + + it("renders correctly with null committedAt", () => { + const { getByText } = render( + , + ); + + expect(getByText("Initial commit")).toBeInTheDocument(); + expect(getByText("John Doe committed -")).toBeInTheDocument(); + expect(getByText("abc123")).toBeInTheDocument(); + }); + + it("renders correctly with null hash", () => { + const { getByText } = render( + , + ); + + expect(getByText("Initial commit")).toBeInTheDocument(); + expect(getByText("John Doe committed 2025-03-01")).toBeInTheDocument(); + expect(getByText("-")).toBeInTheDocument(); + }); + + it("renders correctly with null message", () => { + const { getByText } = render( + , + ); + + expect(getByText("John Doe committed 2025-03-01")).toBeInTheDocument(); + expect(getByText("abc123")).toBeInTheDocument(); + }); + + it("renders correctly with all null props", () => { + const { getByText } = render( + , + ); + + expect(getByText("- committed -")).toBeInTheDocument(); + expect(getByText("-")).toBeInTheDocument(); + }); +}); diff --git a/app/client/src/git/components/ReleaseNotesInput/index.tsx b/app/client/src/git/components/ReleaseNotesInput/index.tsx index 4936efe69347..8b12fc931f63 100644 --- a/app/client/src/git/components/ReleaseNotesInput/index.tsx +++ b/app/client/src/git/components/ReleaseNotesInput/index.tsx @@ -16,6 +16,7 @@ function ReleaseNotesInput({ { + const mockOnVersionChange = jest.fn(); + + const renderComponent = (props = {}) => { + return render( + , + ); + }; + + beforeEach(() => { + mockOnVersionChange.mockClear(); + }); + + it("should render correctly with initial props", () => { + const { getByRole, getByTestId } = renderComponent(); + + expect(getByTestId("t--git-release-version-title").textContent).toBe( + "Version", + ); + expect(getByTestId("t--git-release-next-version").textContent).toBe( + "1.0.1", + ); + expect(getByTestId("t--git-release-released-at").textContent).toBe( + "Last released: 1.0.0 (2023-01-01)", + ); + expect(getByRole("radio", { name: /patch/i })).toBeChecked(); + }); + + it("should change version when a different radio button is selected", () => { + const { getByRole, getByTestId } = renderComponent(); + + fireEvent.click(getByRole("radio", { name: /minor/i })); + expect(getByTestId("t--git-release-next-version").textContent).toBe( + "1.1.0", + ); + fireEvent.click(getByRole("radio", { name: /major/i })); + expect(getByTestId("t--git-release-next-version").textContent).toBe( + "2.0.0", + ); + }); + + it("should call onVersionChange with the correct version", () => { + const { getByRole } = renderComponent(); + + expect(mockOnVersionChange).toHaveBeenCalledWith("1.0.1"); // initial call with patch version + fireEvent.click(getByRole("radio", { name: /minor/i })); + expect(mockOnVersionChange).toHaveBeenCalledWith("1.1.0"); + fireEvent.click(getByRole("radio", { name: /major/i })); + expect(mockOnVersionChange).toHaveBeenCalledWith("2.0.0"); + }); + + it("should handle null values for currentVersion and releasedAt", () => { + const { getByTestId } = renderComponent({ + currentVersion: null, + releasedAt: null, + }); + + expect(getByTestId("t--git-release-released-at").textContent).toBe( + "Last released: - (-)", + ); + }); +}); diff --git a/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx b/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx index 5d9e9486cdf6..3f05c811e19d 100644 --- a/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx +++ b/app/client/src/git/components/ReleaseVersionRadioGroup/ReleaseVersionRadioGroupView.tsx @@ -38,10 +38,16 @@ function ReleaseVersionRadioGroupView({ return ( - {RELEASE_VERSION_RADIO_GROUP.TITLE} + + {RELEASE_VERSION_RADIO_GROUP.TITLE} + - + {nextVersion ?? "-"} @@ -56,7 +62,7 @@ function ReleaseVersionRadioGroupView({ Patch - + {RELEASE_VERSION_RADIO_GROUP.LAST_RELEASED}: {currentVersion ?? "-"} ( {releasedAt ?? "-"})