Skip to content

Commit

Permalink
Merge pull request #11 from chromaui/tom/ap-3340-set-sidebar-status-f…
Browse files Browse the repository at this point in the history
…rom-build

Set sidebar status from build result
  • Loading branch information
tmeasday authored Jul 25, 2023
2 parents aec33c0 + bd86cca commit 6952cc7
Show file tree
Hide file tree
Showing 14 changed files with 1,620 additions and 551 deletions.
10 changes: 5 additions & 5 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module.exports = {
root: true,
extends: ["@storybook/eslint-config-storybook"],
extends: ["@storybook/eslint-config-storybook", "plugin:storybook/recommended"],
rules: {
"@typescript-eslint/explicit-module-boundary-types": "off",
"eslint-comments/disable-enable-pair": "off",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"simple-import-sort/exports": "error"
},
parser: "@typescript-eslint/parser",
parserOptions: {
project: ["./tsconfig.json"],
project: ["./tsconfig.json"]
},
plugins: ["simple-import-sort"],
};
plugins: ["simple-import-sort"]
};
5 changes: 2 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ jobs:
- name: Lint
run: yarn lint

# Currently we don't have any tests written, this is here for when we do
# - name: Test
# run: yarn test
- name: Test
run: yarn test
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
43 changes: 24 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@
"release": "yarn run build && auto shipit",
"start": "run-p build:watch 'storybook --quiet'",
"prerelease": "zx scripts/prepublish-checks.mjs",
"storybook": "CHROMATIC_ADDON_NAME='../dist/index.js' storybook dev -p 6006"
"storybook": "CHROMATIC_ADDON_NAME='../dist/index.js' storybook dev -p 6006",
"test": "jest"
},
"dependencies": {
"@storybook/csf-tools": "^7.1.0-alpha.34",
"@storybook/csf-tools": "^7.2.0-alpha.0",
"@storybook/design-system": "^7.15.11",
"chromatic": "^6.19.8",
"date-fns": "^2.30.0",
Expand All @@ -66,16 +67,18 @@
"@graphql-codegen/cli": "^4.0.1",
"@graphql-codegen/client-preset": "^4.0.1",
"@graphql-typed-document-node/core": "^3.2.0",
"@storybook/addon-actions": "^7.1.0-alpha.34",
"@storybook/addon-essentials": "^7.1.0-alpha.34",
"@storybook/addon-interactions": "^7.1.0-alpha.34",
"@storybook/channels": "^7.1.0-alpha.34",
"@storybook/addon-actions": "^7.2.0-alpha.0",
"@storybook/addon-essentials": "^7.2.0-alpha.0",
"@storybook/addon-interactions": "^7.2.0-alpha.0",
"@storybook/addon-mdx-gfm": "^7.2.0-alpha.0",
"@storybook/channels": "^7.2.0-alpha.0",
"@storybook/eslint-config-storybook": "^3.1.2",
"@storybook/manager-api": "^7.1.0-alpha.34",
"@storybook/react": "^7.1.0-alpha.34",
"@storybook/react-vite": "^7.1.0-alpha.34",
"@storybook/testing-library": "^0.0.14-next.1",
"@storybook/theming": "^7.1.0-alpha.34",
"@storybook/manager-api": "^7.2.0-alpha.0",
"@storybook/react": "^7.2.0-alpha.0",
"@storybook/react-vite": "^7.2.0-alpha.0",
"@storybook/testing-library": "^0.2.1-next.0",
"@storybook/theming": "^7.2.0-alpha.0",
"@types/jest": "^29.5.3",
"@types/node": "^18.15.0",
"@types/pluralize": "^0.0.29",
"@types/react": "^18.0.34",
Expand All @@ -88,6 +91,7 @@
"eslint": "^8.42.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-storybook": "^0.6.13",
"graphql": "^16.6.0",
"jest": "^29.5.0",
"msw": "^1.2.1",
Expand All @@ -99,22 +103,23 @@
"react": "^18.0.0",
"react-dom": "^18.0.0",
"rimraf": "^3.0.2",
"storybook": "^7.1.0-alpha.34",
"storybook": "^7.2.0-alpha.0",
"storybook-addon-designs": "^7.0.0-beta.2",
"ts-jest": "^29.1.1",
"tsup": "^6.6.3",
"typescript": "^4.9.5",
"vite": "^4.1.4",
"vite-plugin-environment": "^1.1.3",
"zx": "^1.14.1"
},
"peerDependencies": {
"@storybook/blocks": "^7.1.0-alpha.32",
"@storybook/components": "^7.1.0-alpha.32",
"@storybook/core-events": "^7.1.0-alpha.32",
"@storybook/manager-api": "^7.1.0-alpha.32",
"@storybook/preview-api": "^7.1.0-alpha.32",
"@storybook/theming": "^7.1.0-alpha.32",
"@storybook/types": "^7.1.0-alpha.32",
"@storybook/blocks": "^7.2.0-alpha.0",
"@storybook/components": "^7.2.0-alpha.0",
"@storybook/core-events": "^7.2.0-alpha.0",
"@storybook/manager-api": "^7.2.0-alpha.0",
"@storybook/preview-api": "^7.2.0-alpha.0",
"@storybook/theming": "^7.2.0-alpha.0",
"@storybook/types": "^7.2.0-alpha.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
Expand Down
18 changes: 16 additions & 2 deletions src/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useAddonState, useChannel, useStorybookState } from "@storybook/manager-api";
import {
useAddonState,
useChannel,
useStorybookApi,
useStorybookState,
} from "@storybook/manager-api";
import React, { useCallback } from "react";

import { ADDON_ID, PANEL_ID, START_BUILD } from "./constants";
Expand All @@ -8,6 +13,7 @@ import { LinkProject } from "./screens/LinkProject/LinkProject";
import { VisualTests } from "./screens/VisualTests/VisualTests";
import { AddonState } from "./types";
import { client, Provider, useAccessToken } from "./utils/graphQLClient";
import { StatusUpdate } from "./utils/testsToStatusUpdate";
import { useProjectId } from "./utils/useProjectId";

interface PanelProps {
Expand All @@ -17,9 +23,10 @@ interface PanelProps {
const { GIT_BRANCH, GIT_SLUG } = process.env;

export const Panel = ({ active }: PanelProps) => {
const api = useStorybookApi();
const [accessToken, setAccessToken] = useAccessToken();

const [state, setAddonState] = useAddonState<AddonState>(ADDON_ID, { isOutdated: true });
const [state, setAddonState] = useAddonState<AddonState>(ADDON_ID, { isOutdated: false });
const { storyId } = useStorybookState();

const setIsOutdated = useCallback(
Expand All @@ -39,6 +46,12 @@ export const Panel = ({ active }: PanelProps) => {
emit(START_BUILD);
}, [emit, state, setAddonState]);

const updateBuildStatus = useCallback(
(update: StatusUpdate) => {
api.experimental_updateStatus(ADDON_ID, update);
},
[api]
);
const [projectId, updateProject, projectIdChanged, clearProjectIdChanged] = useProjectId();

// Render a hidden element when the addon panel is not active.
Expand Down Expand Up @@ -75,6 +88,7 @@ export const Panel = ({ active }: PanelProps) => {
setAccessToken={setAccessToken}
setIsOutdated={setIsOutdated}
setIsRunning={setIsRunning}
updateBuildStatus={updateBuildStatus}
storyId={storyId}
/>
</Provider>
Expand Down
2 changes: 1 addition & 1 deletion src/Tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const storedBuildId = localStorage.getItem(DEV_BUILD_ID_KEY);

export const Tool = () => {
const [state, setAddonState] = useAddonState<AddonState>(ADDON_ID, {
isOutdated: true,
isOutdated: false,
lastBuildId: storedBuildId,
});

Expand Down
1 change: 1 addition & 0 deletions src/gql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ export type ProjectLastBuildArgs = {
branches?: InputMaybe<Array<Scalars['String']['input']>>;
defaultBranch?: InputMaybe<Scalars['Boolean']['input']>;
results?: InputMaybe<Array<BuildResult>>;
slug?: InputMaybe<Scalars['String']['input']>;
statuses?: InputMaybe<Array<BuildStatus>>;
};

Expand Down
3 changes: 3 additions & 0 deletions src/screens/VisualTests/VisualTests.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { action } from "@storybook/addon-actions";
import type { Meta, StoryObj } from "@storybook/react";
import { findByRole, fireEvent } from "@storybook/testing-library";
import { graphql } from "msw";
Expand Down Expand Up @@ -258,6 +259,7 @@ const meta = {
args: {
storyId: "button--primary",
projectId: "Project:id123",
updateBuildStatus: action("updateBuildStatus"),
},
} satisfies Meta<typeof VisualTests>;

Expand Down Expand Up @@ -309,6 +311,7 @@ export const OutdatedRunning: Story = {
...Outdated.args,
isRunning: true,
},
argTypes: { updateBuildStatus: { action: "updateBuildStatus" } },
parameters: {
...Outdated.parameters,
},
Expand Down
32 changes: 25 additions & 7 deletions src/screens/VisualTests/VisualTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
TestStatus,
} from "../../gql/graphql";
import { aggregateResult } from "../../utils/aggregateResult";
import { useProjectId } from "../../utils/useProjectId";
import { StatusUpdate, testsToStatusUpdate } from "../../utils/testsToStatusUpdate";
import { BuildInfo } from "./BuildInfo";
import { RenderSettings } from "./RenderSettings";
import { SnapshotComparison } from "./SnapshotComparison";
Expand Down Expand Up @@ -157,17 +157,19 @@ interface VisualTestsProps {
setAccessToken: (accessToken: string | null) => void;
setIsOutdated: (isOutdated: boolean) => void;
setIsRunning: (isRunning: boolean) => void;
updateBuildStatus: (update: StatusUpdate) => void;
storyId: string;
}

let last: any;
export const VisualTests = ({
isOutdated,
isRunning,
lastDevBuildId,
runDevBuild,
setAccessToken,
setIsOutdated,
setIsRunning,
updateBuildStatus,
projectId,
branch,
slug,
Expand All @@ -193,14 +195,31 @@ export const VisualTests = ({
[reviewTest]
);

const build = getFragment(FragmentBuildFields, data?.build || data?.project?.lastBuild);

const buildComplete = build && "result" in build;
const buildStatusUpdate =
build &&
"tests" in build &&
testsToStatusUpdate(getFragment(FragmentTestFields, build.tests.nodes));

useEffect(() => {
if (isRunning && data?.build && "result" in data.build) {
setIsOutdated(false);
if (buildComplete && isRunning) {
setIsRunning(false);
}
}, [isRunning, setIsOutdated, setIsRunning, data]);
}, [buildComplete, isRunning, setIsRunning]);

const build = getFragment(FragmentBuildFields, data?.build || data?.project?.lastBuild);
useEffect(() => {
last = {
buildStatusUpdate,
string: JSON.stringify(buildStatusUpdate),
};
if (buildStatusUpdate) {
updateBuildStatus(buildStatusUpdate);
}
// We use the stringified version of buildStatusUpdate to do a deep diff
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(buildStatusUpdate), updateBuildStatus]);

useEffect(() => {
let interval: any;
Expand Down Expand Up @@ -271,7 +290,6 @@ export const VisualTests = ({

const allTests = getFragment(FragmentTestFields, "tests" in build ? build.tests.nodes : []);
const tests = allTests.filter((test) => test.story?.storyId === storyId);

const { changeCount, brokenCount, resultsByBrowser, resultsByViewport, viewportInfoById } =
tests.reduce(
(acc, test) => {
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export type AnnouncedBuild = Extract<BuildFieldsFragment, { __typename: "Announc
export type PublishedBuild = Extract<BuildFieldsFragment, { __typename: "PublishedBuild" }>;
export type StartedBuild = Extract<BuildFieldsFragment, { __typename: "StartedBuild" }>;
export type CompletedBuild = Extract<BuildFieldsFragment, { __typename: "CompletedBuild" }>;

export type BuildWithTests = StartedBuild | CompletedBuild;
109 changes: 109 additions & 0 deletions src/utils/testsToStatusUpdate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { TestStatus } from "../gql/graphql";
import { testsToStatusUpdate } from "./testsToStatusUpdate";

it("handles single test", () => {
expect(
testsToStatusUpdate([
{
status: TestStatus.Passed,
story: {
storyId: "story--id",
},
},
])
).toMatchInlineSnapshot(`
{
"story--id": {
"description": "Chromatic Visual Tests",
"status": null,
"title": "Visual Tests",
},
}
`);
});

it("handles multiple tests", () => {
expect(
testsToStatusUpdate([
{
status: TestStatus.Pending,
story: {
storyId: "story--id",
},
},
{
status: TestStatus.Denied,
story: {
storyId: "story2--id",
},
},
])
).toMatchInlineSnapshot(`
{
"story--id": {
"description": "Chromatic Visual Tests",
"status": "warn",
"title": "Visual Tests",
},
"story2--id": {
"description": "Chromatic Visual Tests",
"status": "error",
"title": "Visual Tests",
},
}
`);
});

it("handles multiple viewports", () => {
expect(
testsToStatusUpdate([
{
status: TestStatus.Broken,
story: {
storyId: "story--id",
},
},
{
status: TestStatus.Pending,
story: {
storyId: "story--id",
},
},
])
).toMatchInlineSnapshot(`
{
"story--id": {
"description": "Chromatic Visual Tests",
"status": "error",
"title": "Visual Tests",
},
}
`);
});

it("handles multiple viewports, reverse order", () => {
expect(
testsToStatusUpdate([
{
status: TestStatus.Pending,
story: {
storyId: "story--id",
},
},
{
status: TestStatus.Broken,
story: {
storyId: "story--id",
},
},
])
).toMatchInlineSnapshot(`
{
"story--id": {
"description": "Chromatic Visual Tests",
"status": "error",
"title": "Visual Tests",
},
}
`);
});
Loading

0 comments on commit 6952cc7

Please sign in to comment.