Skip to content

Commit

Permalink
Merge pull request #126 from chromaui/matt/ap-3618-git-is-required-fo…
Browse files Browse the repository at this point in the history
…r-visual-test-addon-via-chromatic-cli

git is required for visual test addon via chromatic cli
  • Loading branch information
weeksling committed Oct 4, 2023
2 parents 1b98506 + 8f69032 commit 7385106
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 12 deletions.
13 changes: 13 additions & 0 deletions src/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import { Sections } from "./components/layout";
import {
ADDON_ID,
GIT_INFO,
GIT_INFO_ERROR,
IS_OUTDATED,
LOCAL_BUILD_PROGRESS,
PANEL_ID,
START_BUILD,
} from "./constants";
import { Project } from "./gql/graphql";
import { Authentication } from "./screens/Authentication/Authentication";
import { GitNotFound } from "./screens/GitNotFound/GitNotFound";
import { LinkedProject } from "./screens/LinkProject/LinkedProject";
import { LinkingProjectFailed } from "./screens/LinkProject/LinkingProjectFailed";
import { LinkProject } from "./screens/LinkProject/LinkProject";
Expand All @@ -33,6 +35,7 @@ export const Panel = ({ active, api }: PanelProps) => {
const { storyId } = useStorybookState();

const [gitInfo] = useAddonState<GitInfoPayload>(GIT_INFO);
const [gitInfoError] = useAddonState<Error>(GIT_INFO_ERROR);
const [localBuildProgress] = useAddonState<LocalBuildProgress>(LOCAL_BUILD_PROGRESS);
const [, setOutdated] = useAddonState<boolean>(IS_OUTDATED);
const emit = useChannel({});
Expand All @@ -55,6 +58,16 @@ export const Panel = ({ active, api }: PanelProps) => {
// If the user creates a project in a dialog (either during login or later, it get set here)
const [createdProjectId, setCreatedProjectId] = useState<Project["id"]>();

if (gitInfoError) {
return (
<Provider key={PANEL_ID} value={client}>
<Sections hidden={!active}>
<GitNotFound gitInfoError={gitInfoError} />
</Sections>
</Provider>
);
}

// Render the Authentication flow if the user is not signed in.
if (!accessToken) {
return (
Expand Down
12 changes: 10 additions & 2 deletions src/SidebarTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import pluralize from "pluralize";
import React, { useEffect, useRef } from "react";

import { SidebarTopButton } from "./components/SidebarTopButton";
import { ADDON_ID, IS_OUTDATED, LOCAL_BUILD_PROGRESS, START_BUILD } from "./constants";
import {
ADDON_ID,
GIT_INFO_ERROR,
IS_OUTDATED,
LOCAL_BUILD_PROGRESS,
START_BUILD,
} from "./constants";
import { LocalBuildProgress } from "./types";
import { useAddonState } from "./useAddonState/manager";
import { useAccessToken } from "./utils/graphQLClient";
Expand All @@ -25,6 +31,8 @@ export const SidebarTop = ({ api }: SidebarTopProps) => {
const [localBuildProgress] = useAddonState<LocalBuildProgress>(LOCAL_BUILD_PROGRESS);
const isRunning = !!localBuildProgress && localBuildProgress.currentStep !== "complete";

const [gitInfoError] = useAddonState<Error>(GIT_INFO_ERROR);

const lastStep = useRef(localBuildProgress?.currentStep);
useEffect(() => {
if (localBuildProgress?.currentStep === lastStep.current) return;
Expand Down Expand Up @@ -95,7 +103,7 @@ export const SidebarTop = ({ api }: SidebarTopProps) => {
const emit = useChannel({});
const startBuild = () => emit(START_BUILD);

if (!projectId || isLoggedIn === false) {
if (!projectId || isLoggedIn === false || gitInfoError) {
return null;
}

Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const ACCESS_TOKEN_KEY = `${ADDON_ID}/access-token/${CHROMATIC_BASE_URL}`
export const DEV_BUILD_ID_KEY = `${ADDON_ID}/dev-build-id`;

export const GIT_INFO = `${ADDON_ID}/gitInfo`;
export const GIT_INFO_ERROR = `${ADDON_ID}/gitInfoError`;
export const PROJECT_INFO = `${ADDON_ID}/projectInfo`;
export const IS_OUTDATED = `${ADDON_ID}/isOutdated`;
export const START_BUILD = `${ADDON_ID}/startBuild`;
Expand Down
45 changes: 35 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getConfiguration, getGitInfo, GitInfo } from "chromatic/node";
import {
CHROMATIC_BASE_URL,
GIT_INFO,
GIT_INFO_ERROR,
LOCAL_BUILD_PROGRESS,
PROJECT_INFO,
START_BUILD,
Expand All @@ -26,17 +27,30 @@ function managerEntries(entry: string[] = []) {
// Uses a recursive setTimeout instead of setInterval to avoid overlapping async calls.
const observeGitInfo = async (
interval: number,
callback: (info: GitInfo, prevInfo: GitInfo) => void
callback: (info: GitInfo, prevInfo?: GitInfo) => void,
errorCallback: (e: Error) => void
) => {
let prev: GitInfo;
let prev: GitInfo | undefined;
let prevError: Error | undefined;
let timer: NodeJS.Timeout | undefined;
const act = async () => {
const gitInfo = await getGitInfo();
if (Object.entries(gitInfo).some(([key, value]) => prev?.[key as keyof GitInfo] !== value)) {
callback(gitInfo, prev);
try {
const gitInfo = await getGitInfo();
if (Object.entries(gitInfo).some(([key, value]) => prev?.[key as keyof GitInfo] !== value)) {
callback(gitInfo, prev);
}
prev = gitInfo;
prevError = undefined;
timer = setTimeout(act, interval);
} catch (e: any) {
if (prevError?.message !== e.message) {
console.error(`Failed to fetch git info, with error:\n${e}`);
errorCallback(e);
}
prev = undefined;
prevError = e;
timer = setTimeout(act, interval);
}
prev = gitInfo;
timer = setTimeout(act, interval);
};
act();

Expand Down Expand Up @@ -99,9 +113,20 @@ async function serverChannel(

// eslint-disable-next-line react-hooks/rules-of-hooks
const gitInfoState = useAddonState<GitInfoPayload>(channel, GIT_INFO);
observeGitInfo(5000, (info) => {
gitInfoState.value = info;
});

// eslint-disable-next-line react-hooks/rules-of-hooks
const gitInfoError = useAddonState<Error>(channel, GIT_INFO_ERROR);

observeGitInfo(
5000,
(info) => {
gitInfoError.value = undefined;
gitInfoState.value = info;
},
(error: Error) => {
gitInfoError.value = error;
}
);

return channel;
}
Expand Down
17 changes: 17 additions & 0 deletions src/screens/GitNotFound/GitNotFound.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";

import { storyWrapper } from "../../utils/graphQLClient";
import { GitNotFound } from "./GitNotFound";

const meta = {
component: GitNotFound,
decorators: [storyWrapper],
args: {
gitInfoError: new Error("Git info not found"),
},
} satisfies Meta<typeof GitNotFound>;

export const Default = {} satisfies StoryObj<typeof meta>;

export default meta;
58 changes: 58 additions & 0 deletions src/screens/GitNotFound/GitNotFound.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Icon, Link } from "@storybook/design-system";
import { styled } from "@storybook/theming";
import React from "react";

import { Container } from "../../components/Container";
import { Heading } from "../../components/Heading";
import { VisualTestsIcon } from "../../components/icons/VisualTestsIcon";
import { Section } from "../../components/layout";
import { Stack } from "../../components/Stack";
import { Text } from "../../components/Text";

interface GitNotFoundProps {
gitInfoError: Error;
}

const InfoSection = styled(Section)(({ theme }) => ({
display: "flex",
flexDirection: "row",
alignItems: "center",
borderRadius: theme.appBorderRadius,
background: theme.color.lightest,
padding: 15,
flex: 1,
boxShadow: `0px 1px 3px 0px rgba(0, 0, 0, 0.10), 0px 2px 5px 0px rgba(0, 0, 0, 0.05)`,
}));

const InfoSectionText = styled(Text)(({ theme }) => ({
marginLeft: 14,
flex: 1,
textAlign: "left",
color: theme.color.darker,
}));

export const GitNotFound = ({ gitInfoError }: GitNotFoundProps) => (
<Container>
<Stack>
<div>
<VisualTestsIcon />
<Heading>Visual tests</Heading>
<Text>
Catch bugs in UI appearance automatically. Compare image snapshots to detect visual
changes.
</Text>
</div>
<InfoSection>
<Icon icon="lock" />
<InfoSectionText>
<b>Git not detected</b>
<br />
This addon requires Git to associate test results with commits and branches.
</InfoSectionText>
</InfoSection>
<Link target="_new" href="https://www.chromatic.com/docs/cli/" withArrow>
Visual tests requirements
</Link>
</Stack>
</Container>
);

0 comments on commit 7385106

Please sign in to comment.