diff --git a/.github/workflows/web_coverage.yaml b/.github/workflows/web_coverage.yaml index 21b7b91a..24064473 100644 --- a/.github/workflows/web_coverage.yaml +++ b/.github/workflows/web_coverage.yaml @@ -9,6 +9,7 @@ on: env: NODE_VERSION: "18.16.0" PNPM_VERSION: "8.5.0" + COVERAGE: "true" concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true @@ -45,10 +46,14 @@ jobs: build: pnpm run build start: pnpm run start browser: chrome + env: + COVERAGE: "true" - name: Jest run run: | pnpm run test:unit + env: + COVERAGE: "true" - name: Upload coverage to Codecov uses: codecov/codecov-action@v2 diff --git a/package.json b/package.json index 104e66b7..931dd8f6 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "type": "module", "scripts": { "dev": "vite", + "dev:coverage": "cross-env COVERAGE=true vite", "build": "vite build", "lint": "tsc --noEmit --project tsconfig.web.json && eslint --ext .js,.ts,.tsx . --ignore-path .eslintignore.web", "start": "vite preview --port 3000", @@ -14,8 +15,10 @@ "test": "pnpm run test:unit && pnpm run test:components", "test:components": "cypress run --component --browser chrome --headless", "test:unit": "jest --coverage", + "test:unit:coverage": "cross-env COVERAGE=true jest --coverage", + "test:components:coverage": "cross-env COVERAGE=true cypress run --component --browser chrome --headless", "test:cy": "cypress run", - "coverage": "pnpm run test:unit && pnpm run test:components", + "coverage": "cross-env COVERAGE=true pnpm run test:unit && cross-env COVERAGE=true pnpm run test:components", "generate-tokens": "node scripts/system-token/convert-tokens.cjs" }, "dependencies": { diff --git a/src/components/_shared/color-picker/ColorPicker.tsx b/src/components/_shared/color-picker/ColorPicker.tsx index 050b836b..f457c49f 100644 --- a/src/components/_shared/color-picker/ColorPicker.tsx +++ b/src/components/_shared/color-picker/ColorPicker.tsx @@ -5,7 +5,7 @@ import React, { useCallback, useRef, useMemo } from 'react'; import Typography from '@mui/material/Typography'; import { useTranslation } from 'react-i18next'; -import { TitleOutlined } from '@mui/icons-material'; +import TitleOutlined from '@mui/icons-material/TitleOutlined'; export interface ColorPickerProps { onChange?: (format: EditorMarkFormat.FontColor | EditorMarkFormat.BgColor, color: string) => void; diff --git a/src/components/_shared/modal/IndexedDBCleaner.tsx b/src/components/_shared/modal/IndexedDBCleaner.tsx index 9bddafa1..554f3e6f 100644 --- a/src/components/_shared/modal/IndexedDBCleaner.tsx +++ b/src/components/_shared/modal/IndexedDBCleaner.tsx @@ -1,5 +1,8 @@ import { notify } from '@/components/_shared/notify'; -import { TaskAltRounded } from '@mui/icons-material'; + +import TaskAltRounded from '@mui/icons-material/TaskAltRounded'; +import DeleteIcon from '@mui/icons-material/Delete'; + import React, { useState, useEffect } from 'react'; import { Box, @@ -11,7 +14,6 @@ import { ListItemText, Typography, } from '@mui/material'; -import DeleteIcon from '@mui/icons-material/Delete'; const MAX_DELETE = 50; const IndexedDBCleaner = () => { @@ -139,4 +141,4 @@ const IndexedDBCleaner = () => { ); }; -export default IndexedDBCleaner; \ No newline at end of file +export default IndexedDBCleaner; diff --git a/src/components/_shared/more-actions/importer/ImporterDialogContent.tsx b/src/components/_shared/more-actions/importer/ImporterDialogContent.tsx index 37c8f3f8..5b85091e 100644 --- a/src/components/_shared/more-actions/importer/ImporterDialogContent.tsx +++ b/src/components/_shared/more-actions/importer/ImporterDialogContent.tsx @@ -2,6 +2,7 @@ import FileDropzone from '@/components/_shared/file-dropzone/FileDropzone'; import { notify } from '@/components/_shared/notify'; import { TabPanel, ViewTab, ViewTabs } from '@/components/_shared/tabs/ViewTabs'; import { AFConfigContext } from '@/components/main/app.hooks'; + import LinearProgress from '@mui/material/LinearProgress'; import React, { useCallback, useContext } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/src/components/_shared/notify/CustomSnackbar.tsx b/src/components/_shared/notify/CustomSnackbar.tsx index e84ec95b..7818b04b 100644 --- a/src/components/_shared/notify/CustomSnackbar.tsx +++ b/src/components/_shared/notify/CustomSnackbar.tsx @@ -1,10 +1,8 @@ -import { - ErrorOutline, - HighlightOff, - PowerSettingsNew, - TaskAltRounded, -} from '@mui/icons-material'; -import { IconButton } from '@mui/material'; +import ErrorOutline from '@mui/icons-material/ErrorOutline'; +import HighlightOff from '@mui/icons-material/HighlightOff'; +import PowerSettingsNew from '@mui/icons-material/PowerSettingsNew'; +import TaskAltRounded from '@mui/icons-material/TaskAltRounded'; +import IconButton from '@mui/material/IconButton'; import React from 'react'; import { useSnackbar, SnackbarContent, CustomContentProps } from 'notistack'; import { ReactComponent as CloseIcon } from '@/assets/icons/close.svg'; @@ -58,4 +56,4 @@ const CustomSnackbar = React.forwardRef((pro ); }); -export default CustomSnackbar; \ No newline at end of file +export default CustomSnackbar; diff --git a/src/components/app/landing-pages/RequestAccess.tsx b/src/components/app/landing-pages/RequestAccess.tsx index 52d2e225..4f1e142d 100644 --- a/src/components/app/landing-pages/RequestAccess.tsx +++ b/src/components/app/landing-pages/RequestAccess.tsx @@ -2,8 +2,11 @@ import { NormalModal } from '@/components/_shared/modal'; import { notify } from '@/components/_shared/notify'; import { useAppViewId, useCurrentWorkspaceId } from '@/components/app/app.hooks'; import { AFConfigContext, useCurrentUser, useService } from '@/components/main/app.hooks'; -import { TaskAltRounded } from '@mui/icons-material'; -import { Button, Divider, Typography } from '@mui/material'; + +import TaskAltRounded from '@mui/icons-material/TaskAltRounded'; +import Button from '@mui/material/Button'; +import Divider from '@mui/material/Divider'; +import Typography from '@mui/material/Typography'; import React, { useContext } from 'react'; import { useTranslation, Trans } from 'react-i18next'; import { ReactComponent as AppflowyLogo } from '@/assets/icons/appflowy.svg'; diff --git a/src/components/main/withAppWrapper.tsx b/src/components/main/withAppWrapper.tsx index 96aa9737..66ea36ec 100644 --- a/src/components/main/withAppWrapper.tsx +++ b/src/components/main/withAppWrapper.tsx @@ -5,7 +5,8 @@ import AppTheme from '@/components/main/AppTheme'; import AppConfig from '@/components/main/AppConfig'; import { Suspense } from 'react'; import { SnackbarProvider } from 'notistack'; -import { styled } from '@mui/material'; + +import { styled } from '@mui/material/styles'; import { InfoSnackbar } from '../_shared/notify'; const StyledSnackbarProvider = styled(SnackbarProvider)` diff --git a/src/pages/AcceptInvitationPage.tsx b/src/pages/AcceptInvitationPage.tsx index 0629f7ed..106e4667 100644 --- a/src/pages/AcceptInvitationPage.tsx +++ b/src/pages/AcceptInvitationPage.tsx @@ -4,7 +4,7 @@ import ChangeAccount from '@/components/_shared/modal/ChangeAccount'; import { notify } from '@/components/_shared/notify'; import { getAvatar } from '@/components/_shared/view-icon/utils'; import { AFConfigContext, useCurrentUser, useService } from '@/components/main/app.hooks'; -import { EmailOutlined } from '@mui/icons-material'; +import EmailOutlined from '@mui/icons-material/EmailOutlined'; import { Avatar, Button, Divider } from '@mui/material'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index d46d3251..36239579 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -1,5 +1,6 @@ import Import from '@/components/_shared/more-actions/importer/Import'; -import { Typography } from '@mui/material'; + +import Typography from '@mui/material/Typography'; import React from 'react'; import { ReactComponent as AppflowyLogo } from '@/assets/icons/appflowy.svg'; import { useSearchParams } from 'react-router-dom'; diff --git a/vite.config.ts b/vite.config.ts index 518927ff..bb36c046 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,8 +1,7 @@ -import { defineConfig } from 'vite'; +import { defineConfig, Plugin } from 'vite'; import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; import { visualizer } from 'rollup-plugin-visualizer'; -import usePluginImport from 'vite-plugin-importer'; import { totalBundleSize } from 'vite-plugin-total-bundle-size'; import path from 'path'; import istanbul from 'vite-plugin-istanbul'; @@ -12,6 +11,7 @@ import { viteExternalsPlugin } from 'vite-plugin-externals'; const resourcesPath = path.resolve(__dirname, '../resources'); const isDev = process.env.NODE_ENV === 'development'; const isProd = process.env.NODE_ENV === 'production'; +const isTest = process.env.NODE_ENV === 'test' || process.env.COVERAGE === 'true'; // https://vitejs.dev/config/ export default defineConfig({ @@ -34,7 +34,6 @@ export default defineConfig({ isProd ? viteExternalsPlugin({ react: 'React', 'react-dom': 'ReactDOM', - }) : undefined, svgr({ svgrOptions: { @@ -72,7 +71,8 @@ export default defineConfig({ }, }, }), - istanbul({ + // Enable istanbul for code coverage (active if isTest is true) + isTest ? istanbul({ cypress: true, requireEnv: false, include: ['src/**/*'], @@ -81,13 +81,7 @@ export default defineConfig({ 'cypress/**/*', 'node_modules/**/*', ], - }), - usePluginImport({ - libraryName: '@mui/icons-material', - libraryDirectory: '', - camel2DashComponentName: false, - style: false, - }), + }) : undefined, process.env.ANALYZE_MODE ? visualizer({ emitFile: true, @@ -109,15 +103,20 @@ export default defineConfig({ ignored: ['node_modules'], }, cors: false, + sourcemapIgnoreList: false, }, envPrefix: ['AF'], esbuild: { + keepNames: true, + sourcesContent: true, + sourcemap: true, + minifyIdentifiers: false, // Disable identifier minification in development + minifySyntax: false, // Disable syntax minification in development pure: !isDev ? ['console.log', 'console.debug', 'console.info', 'console.trace'] : [], }, build: { target: `esnext`, reportCompressedSize: true, - sourcemap: isDev, rollupOptions: isProd ? {