UNPKG

creevey

Version:

Cross-browser screenshot testing tool for Storybook with fancy UI Runner

196 lines 10.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.CreeveyApp = CreeveyApp; const react_1 = __importStar(require("react")); const use_immer_1 = require("use-immer"); const theming_1 = require("storybook/theming"); const types_js_1 = require("../../types.js"); const helpers_js_1 = require("../shared/helpers.js"); const CreeveyContext_js_1 = require("./CreeveyContext.js"); const KeyboardEventsContext_js_1 = require("./KeyboardEventsContext.js"); const index_js_1 = require("./CreeveyView/SideBar/index.js"); const ResultsPage_js_1 = require("../shared/components/ResultsPage.js"); const Toggle_js_1 = require("./CreeveyView/SideBar/Toggle.js"); const themes_js_1 = require("./themes.js"); const FlexContainer = (0, theming_1.withTheme)(theming_1.styled.div(({ theme }) => ({ height: '100vh', display: 'flex', background: theme.background.content, color: theme.color.defaultText, }))); const ToggleContainer = theming_1.styled.div({ zIndex: 1, position: 'absolute', right: 10, top: 10, }); function CreeveyApp({ api, initialState }) { const [tests, updateTests] = (0, use_immer_1.useImmer)(initialState.tests); const [isRunning, setIsRunning] = (0, react_1.useState)(initialState.isRunning); const [openedTestPath, openTest] = (0, react_1.useState)([]); const [filter, setFilter] = (0, react_1.useState)({ status: null, subStrings: [] }); const [theme, setTheme] = (0, themes_js_1.useTheme)(); const openedTest = (0, helpers_js_1.getTestByPath)(tests, openedTestPath); const failedTests = (0, react_1.useMemo)(() => (0, helpers_js_1.getFailedTests)(tests), [tests]); const [retry, setRetry] = (0, react_1.useState)(openedTest?.results?.length ?? 0); const result = (0, react_1.useMemo)(() => openedTest?.results?.[retry - 1], [openedTest, retry]); const [imageName, setImageName] = (0, react_1.useState)(Object.keys(result?.images ?? {})[0] ?? ''); const [sidebarFocusedItem, setSidebarFocusedItem] = (0, react_1.useState)([]); const canApprove = (0, react_1.useMemo)(() => Boolean(openedTest?.results?.[retry - 1]?.images && openedTest.approved?.[imageName] != retry - 1 && openedTest.results[retry - 1].status != 'success'), [imageName, openedTest, retry]); if (openedTestPath.length > 0 && !(0, types_js_1.isDefined)(openedTest)) openTest([]); const handleSuiteOpen = (0, react_1.useCallback)((path, opened) => { updateTests((draft) => { (0, helpers_js_1.openSuite)(draft, path, opened); }); }, [updateTests]); const handleSuiteToggle = (0, react_1.useCallback)((path, checked) => { updateTests((draft) => { (0, helpers_js_1.checkSuite)(draft, path, checked); }); }, [updateTests]); const handleOpenTest = (0, react_1.useCallback)((test) => { const testPath = (0, helpers_js_1.getTestPath)(test); (0, helpers_js_1.setSearchParams)(testPath); setSidebarFocusedItem(testPath); updateTests((draft) => { (0, helpers_js_1.openSuite)(draft, testPath, true); openTest(testPath); }); }, [updateTests]); const handleGoToNextFailedTest = (0, react_1.useCallback)(() => { if (failedTests.length == 0) return; const currentTest = failedTests.findIndex((t) => t.id === openedTest?.id); const failedImages = Object.entries(result?.images ?? {}) .filter(([name, image]) => // TODO Move to helpers, it duplicates in a few places Boolean(image?.error != null && openedTest?.approved?.[name] != retry - 1 && result?.status != 'success')) .map(([name]) => name); if (failedImages.length > 1 && (failedTests.length == 1 || failedImages.indexOf(imageName) < failedImages.length - 1)) { setImageName((name) => failedImages[failedImages.indexOf(name) + 1] ?? failedImages[0]); } else { const nextFailedTest = failedTests[currentTest + 1] ?? failedTests[0]; handleOpenTest(nextFailedTest); } }, [failedTests, handleOpenTest, openedTest, retry, result, imageName]); const handleImageApproveNew = (0, react_1.useCallback)(() => { const id = openedTest?.id; if (!id) return; api?.approve(id, retry - 1, imageName); }, [api, imageName, openedTest?.id, retry]); const handleImageApproveAndGoNext = (0, react_1.useCallback)(() => { handleImageApproveNew(); handleGoToNextFailedTest(); }, [handleImageApproveNew, handleGoToNextFailedTest]); const handleApproveAll = (0, react_1.useCallback)(() => { // TODO Update handled incorrectly api?.approveAll(); }, [api]); const handleStart = (0, react_1.useCallback)((tests) => api?.start((0, helpers_js_1.getCheckedTests)(tests).map((test) => test.id)), [api]); const handleStop = (0, react_1.useCallback)(() => api?.stop(), [api]); const handleThemeChange = (0, react_1.useCallback)((isDark) => { setTheme(isDark ? 'dark' : 'light'); }, [setTheme]); (0, react_1.useEffect)(() => { const retry = openedTest?.results?.length ?? 0; const result = openedTest?.results?.[retry - 1] ?? { images: {} }; setImageName(Object.keys(result.images ?? {})[0] ?? ''); setRetry(retry); }, [openedTest?.results]); (0, react_1.useEffect)(() => { window.addEventListener('popstate', (event) => { updateTests((draft) => { const state = event.state; if (state && typeof state == 'object' && 'testPath' in state) { const { testPath } = state; if (Array.isArray(testPath)) { // TODO Add validations (0, helpers_js_1.openSuite)(draft, testPath, true); openTest(testPath); } } }); }); updateTests((draft) => { const testPath = (0, helpers_js_1.getTestPathFromSearch)(); (0, helpers_js_1.openSuite)(draft, testPath, true); openTest(testPath); }); }, [updateTests]); // TODO unsubscribe (0, react_1.useEffect)(() => api?.onUpdate(({ isRunning, tests, removedTests = [] }) => { if ((0, types_js_1.isDefined)(isRunning)) setIsRunning(isRunning); if ((0, types_js_1.isDefined)(tests)) updateTests((draft) => { Object.values(tests).forEach((test) => { if (test) (0, helpers_js_1.updateTestStatus)(draft, (0, helpers_js_1.getTestPath)(test), test); }); removedTests.forEach((test) => { (0, helpers_js_1.removeTests)(draft, (0, helpers_js_1.getTestPath)(test)); }); }); }), [api, updateTests]); return (react_1.default.createElement(CreeveyContext_js_1.CreeveyContext.Provider, { value: { isReport: initialState.isReport, isRunning, onImageNext: canApprove ? handleGoToNextFailedTest : undefined, onImageApprove: canApprove ? handleImageApproveAndGoNext : undefined, onApproveAll: handleApproveAll, onStart: handleStart, onStop: handleStop, onSuiteOpen: handleSuiteOpen, onSuiteToggle: handleSuiteToggle, sidebarFocusedItem, setSidebarFocusedItem, isUpdateMode: initialState.isUpdateMode, } }, react_1.default.createElement(theming_1.ThemeProvider, { theme: (0, theming_1.ensure)(theming_1.themes[theme]) }, react_1.default.createElement(KeyboardEventsContext_js_1.KeyboardEvents, { rootSuite: tests, filter: filter }, react_1.default.createElement(FlexContainer, null, react_1.default.createElement(index_js_1.SideBar, { rootSuite: tests, testId: openedTest?.id, onOpenTest: handleOpenTest, filter: filter, setFilter: setFilter }), openedTest && (react_1.default.createElement(ResultsPage_js_1.ResultsPage, { key: `${openedTest.id}_${openedTest.results?.length ?? 0}`, path: openedTestPath, results: openedTest.results, approved: openedTest.approved, retry: retry, imageName: imageName, onImageChange: setImageName, onRetryChange: setRetry })), react_1.default.createElement(ToggleContainer, null, react_1.default.createElement(Toggle_js_1.Toggle, { value: theme == 'dark', onChange: handleThemeChange }))))))); } //# sourceMappingURL=CreeveyApp.js.map