- storybook/react-webpack5: ^9.1.10
- jest: ^30.2.0
- react: ^18.3.1
- react-dom: ^18.3.1
- typescript: ^5.9.3
npm i react typescript @types/react tslib --save-dev
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
peerDependencies
: The dependencies provided by the user of the librarydevDependencies
: The dependencies you need for development and testdependencies
: The dependencies provided by the developer of the library
npx tsc -init
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
Button.tests.tsx
: Verify the Button component works as expected in different scenarios.Button.tsx
: Define the Button component’s structure, behavior, and appearance.Button.types
.tsx: Define TypeScript interfaces or types for the Button component.Index.ts
: Provide a single entry point for importing the Button component and its types.Button.stories.tsx
: Provide visual examples of the Button for development and documentation.
npm install rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-typescript rollup-plugin-peer-deps-external @rollup/plugin-terser rollup-plugin-dts --save-dev
export default [
{
input: "src/Index.ts",
output: [
//creating separate files specified by the main and module entries in the package.json
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
terser(),
],
external: ["react", "react-dom"],
},
{
input: "src/Index.ts",
output: [{ file: "dist/types.d.ts", format: "es" }],
//generates a type declaration file (types.d.ts) using the dts plugin
plugins: [dts.default()],
},
];
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"scripts": {
"rollup": "rollup -c --bundleConfigAsCjs",
}
main
: "dist/cjs/index.js": Specifies the CommonJS entry pointmodule
: "dist/esm/index.js": Indicates the ECMAScript Module entry pointtypes
: "dist/index.d.ts": Points to the TypeScript type declaration filescripts
: {"rollup": "rollup -c --bundleConfigAsCjs", ...}: Defines a script command
npm install rollup-plugin-postcss --save-dev
npm run rollup
npm install react@18.3.1 react-dom@18.3.1
npm install styled-components
npm install @testing-library/react jest @types/jest jest-environment-jsdom --save-dev
Install Babel and related plugins to handle JSX transformations for Jest
npm install @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript babel-jest --save-dev
Install identity-obj-proxy to allow Jest to treat all types of imports (CSS, LESS, and SCSS) as generic objects
npm install identity-obj-proxy -save-dev
// runs before every test
beforeEach(() => {
console.log("Setting up test environment")
jest.clearAllMocks();
});
// runs after each test
afterEach(() => {
console.log("Cleaning up after each test")
cleanup();
jest.clearAllMocks();
});
// runs once before all tests
beforeAll(() => {
console.log("Initialize test environment before all tests");
});
// runs once after all tests
afterAll(() => {
console.log("Cleaning up after all tests");
});
module.exports = {
testEnvironment: "jsdom",
testMatch: [
"**/__tests__/**/*.+(ts|tsx|js)",
// Add files ending with .tests.tsx|ts|js
"**/?(*.)+(spec|tests|test).+(ts|tsx|js)"
],
moduleNameMapper: {
".(css|less|scss)$": "identity-obj-proxy",
},
setupFilesAfterEnv: ["./src/setupTests.ts"],
};
module.exports = {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
};
"scripts": {
"test": "jest",
}
-
Run all tests
npm run test
-
Run only tests for the
Button component
npm test -- Button
-
Run only changed files since
last commit
npx jest --onlyChanged
- Run only the specific test file
npx jest src/components/Button/Button.tests.tsx
- Run only tests with name containing
"disabled"
npx jest -t "disabled"
- Watch the test changes and run all tests
npx jest --watch
- Run all tests and create coverage reports.
npx jest --coverage
This creates a /coverage folder with a full HTML report:
• Statements – how many lines of code are executed
• Branches – how many if/else paths are tested
• Functions – how many functions are called
• Lines – total code lines covered
npx sb init --builder webpack5
Static the StoryBook
npm run build-storybook
storybook dev -p 6006
npm run storybook
# Stage 1 - Build the StoryBook
FROM node:20-alpine AS building
# Set up the workdir
WORKDIR /feng_li_ui_garden
# Copy the package.json to install all necessary dependencies
COPY package.json ./
# Install all dependencies
RUN npm install
# Copy all source code to prepare for building artifact
COPY . .
# Execute build command
RUN npm run build-storybook
# Stage 2 - Deploy the StoryBook
FROM nginx:alpine AS production
WORKDIR /feng_li_ui_garden
# Clean up all files under the html direcotry
RUN rm -rf /usr/share/nginx/html/*
# Copy the built Storybook static files
COPY --from=building /feng_li_ui_garden/storybook-static /usr/share/nginx/html
# Expose the default port of Nginx for the Container
EXPOSE 80
# Let Nginx run in foreground mode and keep the container alive
CMD ["nginx", "-g", "daemon off;"]
docker rm feng_li_coding_assignment12
docker image rm feng_li_coding_assignment12
docker build -t feng_li_coding_assignment12 .
docker run -d -p 8083:80 --name feng_li_coding_assignment12 feng_li_coding_assignment12
docker stop feng_li_coding_assignment12
docker start feng_li_coding_assignment12