From 7a0fbaaf3e6b3581037cbbe92e13d5ccbc104116 Mon Sep 17 00:00:00 2001 From: Krsiak Daniel Date: Fri, 8 Mar 2024 23:05:44 +0100 Subject: [PATCH] =?UTF-8?q?docs:=20=F0=9F=93=9D=20split=20readme=20into=20?= =?UTF-8?q?smaller=20ones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-continuous-integration-deployment.md | 115 +++++++++ README-development.md | 43 ++++ README-testing.md | 99 ++++++++ README.md | 258 +++----------------- screenshots/technologies.png | Bin 0 -> 13912 bytes 5 files changed, 294 insertions(+), 221 deletions(-) create mode 100644 README-continuous-integration-deployment.md create mode 100644 README-development.md create mode 100644 README-testing.md create mode 100644 screenshots/technologies.png diff --git a/README-continuous-integration-deployment.md b/README-continuous-integration-deployment.md new file mode 100644 index 00000000..36273147 --- /dev/null +++ b/README-continuous-integration-deployment.md @@ -0,0 +1,115 @@ +# 🚀 CI/CD - Continuous Integration / Deployment + +This project uses GitHub Actions for CI and Netlify for CD. + +**Table of Contents:** + +- [🚀 CI/CD - Continuous Integration / Deployment](#-cicd---continuous-integration--deployment) + - [🛠️ CI - Continuous Integration](#️-ci---continuous-integration) + - [Status](#status) + - [GitHub Actions](#github-actions) + - [Workflow for Jest 🃏](#workflow-for-jest-) + - [Workflow for Playwright 🎭](#workflow-for-playwright--) + - [✅ CD - Continuous Deployment](#-cd---continuous-deployment) + - [Status](#status-1) + - [Netlify](#netlify) + +--- + +## 🛠️ CI - Continuous Integration + +This app uses GitHub Actions for CI. + +### Status + +[![Jest Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml) [![Playwright Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) + +### GitHub Actions + +Workflows are defined in `.github/workflows` directory. + +#### Workflow for Jest 🃏 + +- Workflow file: [jest.yml](.github/workflows/jest.yml) +- View the results on GitHub: [actions/workflows/jest.yml](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml) + +
+Click to read workflow description 👀 + +--- + +This workflow is triggered in 2 scenarios: + +1. When a push is made to the `master` branch. +2. When a pull request is opened against the `master` branch. + +The workflow consists of a single job named `build`, which is executed on the latest version of Ubuntu. + +The `build` job follows these steps: + +1. Checkout the repository using the `actions/checkout@v3` action. +2. Setup Node.js environment using the `actions/setup-node@v3` action with Node.js version 18. +3. It installs the dependencies of your project using `npm ci`. This command is similar to `npm install`, but it's designed to be used in automated environments such as this one. +4. Run JEST tests using `npm test`. +5. Upload the test report as an artifact: + - Using the `actions/upload-artifact@v3` action. + - This step is always executed regardless of the success or failure of previous steps. + - The artifact is named `jest-report` + - It is located at path `jest-report/` + - It is retained for 7 days. + +
+ +#### Workflow for Playwright 🎭 + +- Workflow file: [playwright.yml](.github/workflows/playwright.yml) +- View the results on GitHub: [actions/workflows/playwright.yml](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) + +
+Click to read workflow description 👀 + +--- + +This workflow is triggered in 2 scenarios: + +1. When a push is made to the `master` branch. +2. When a pull request is opened against `master` branch. + +The workflow consists of a single job named `test`, which is executed on the latest version of Ubuntu. + +The `test` job follows these steps: + +1. Checkout the repository using the `actions/checkout@v3` action. +2. Setup Node.js environment using the `actions/setup-node@v3` action with Node.js version 18. +3. It installs the dependencies of your project using `npm ci`. This command is similar to `npm install`, but it's designed to be used in automated environments such as this one. +4. Install Playwright browsers using `npx playwright install --with-deps`. +5. Run Playwright tests using `npx playwright test`. +6. Upload the test report as an artifact: + - Using the `actions/upload-artifact@v3` action. + - This step is always executed regardless of the success or failure of previous steps. + - The artifact is named `playwright-report` + - It is located at path `playwright-report/` + - It is retained for 7 days. + +
+ +## ✅ CD - Continuous Deployment + +This app is deployed on Netlify. + +### Status + +[![Netlify Status](https://api.netlify.com/api/v1/badges/eb322254-0169-4941-9416-3806b0bd5be6/deploy-status)](https://app.netlify.com/sites/portfolio-website-krsiak-cz/deploys) + +### Netlify + +Build starts when a new commit is pushed to the `master` branch. + +Using build plugin: + +- [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview) to automatically run audit on website after every build. + +Deploys: + +- Netlify page [portfolio-website-krsiak-cz/deploys](https://app.netlify.com/sites/portfolio-website-krsiak-cz/deploys) +- You can click on the last 2 deploys to see the details. diff --git a/README-development.md b/README-development.md new file mode 100644 index 00000000..1a260011 --- /dev/null +++ b/README-development.md @@ -0,0 +1,43 @@ +# Development + +Development environment for the project. + +**Table of Contents:** + +- [Development](#development) + - [💻 Commands](#-commands) + - [💅 Prettier](#-prettier) + +--- + +## 💻 Commands + +Install dependencies. + +```bash +npm i +``` + +Runs the app in the development mode. + +```bash +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) to view it in your browser. + +## 💅 Prettier + +This project uses Prettier for code formatting. + +Check if the code is formatted correctly. + +```bash +npm run prettier:check +``` + +Format the code via Prettier. + +```bash +npm run prettier:fix +``` diff --git a/README-testing.md b/README-testing.md new file mode 100644 index 00000000..a37b9c66 --- /dev/null +++ b/README-testing.md @@ -0,0 +1,99 @@ +# 🐛 Testing + +This project uses the following tools. + +**Table of Contents:** + +- [🐛 Testing](#-testing) + - [🃏 JEST](#-jest) + - [Test Coverage for Jest](#test-coverage-for-jest) + - [🎭 Playwright](#-playwright) + - [Test Coverage for Playwright](#test-coverage-for-playwright) + - [Other Commands](#other-commands) + +--- + +## 🃏 JEST + +Jest is JavaScript Testing Framework. + +- Test are located folder in `__tests__/jest` +- Naming is `file.test.ts` + +Runs the unit tests. + +```bash +npm run test +``` + +### Test Coverage for Jest + +Jest will generate a code coverage report. + +- The report will be output to the console. +- It will also be saved to a `/coverage` directory in project root as HTML file. + +```bash +npm run test:coverage +``` + +## 🎭 Playwright + +Playwright is library for browser automation E2E testing. + +- Test are located folder in `__tests__/playwright` +- Naming is `file.spec.ts` + +Runs the E2E tests. + +```bash +npx playwright test +``` + +Runs the E2E tests using alias for `npx playwright test` + +```bash +npm run test:e2e +``` + +### Test Coverage for Playwright + +Playwright will generate a code coverage report. + +- It serves HTML report on new localhost port. + +```bash + npx playwright show-report +``` + +### Other Commands + +Starts the interactive UI mode. + +```bash +npx playwright test --ui +``` + +Runs the tests only on Desktop Chrome. + +```bash +npx playwright test --project=chromium +``` + +Runs the tests in a specific file. + +```bash +npx playwright test file.spec.ts +``` + +Runs the tests in debug mode. + +```bash +npx playwright test --debug +``` + +Auto generate tests with Codegen. + +```bash +npx playwright codegen +``` diff --git a/README.md b/README.md index 4dda8fa5..3fddbb9b 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,34 @@ -# React Developer - Portfolio Website | krsiak.cz - -[![Jest Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml) [![Playwright Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) [![Netlify Status](https://api.netlify.com/api/v1/badges/eb322254-0169-4941-9416-3806b0bd5be6/deploy-status)](https://app.netlify.com/sites/portfolio-website-krsiak-cz/deploys) +# Portfolio Website - krsiak.cz React Developer portfolio website 👨‍💻 +**Table of Contents:** + +- [Portfolio Website - krsiak.cz](#portfolio-website---krsiakcz) + - [⚡ Project Website](#-project-website) + - [🚦 Project Status](#-project-status) + - [🛠️ Tech Stack](#️-tech-stack) + - [📝 Features](#-features) + - [💻 Development](#-development) + - [🐛 Testing](#-testing) + - [🚀 CI/CD - Continuous Integration / Deployment](#-cicd---continuous-integration--deployment) + - [🖼️ Screenshots](#️-screenshots) + +--- + ## ⚡ Project Website - +Website: + +## 🚦 Project Status + +[![Jest Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml) [![Playwright Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) [![Netlify Status](https://api.netlify.com/api/v1/badges/eb322254-0169-4941-9416-3806b0bd5be6/deploy-status)](https://app.netlify.com/sites/portfolio-website-krsiak-cz/deploys) ## 🛠️ Tech Stack -Using the following technologies. +![Tech Stack](/screenshots/technologies.png) -![My Skills](https://skillicons.dev/icons?i=js,ts,react,next,tailwind,jest,githubactions,netlify) +Using the following technologies: - [JavaScript](https://developer.mozilla.org/en-US/docs/Web/javascript) - [TypeScript](https://www.typescriptlang.org/) @@ -28,232 +44,32 @@ Using the following technologies. The website contains the following sections and pages. -**Links:** - -- 👉 LinkedIn, GitHub, Resume - **Sections:** -- 👉 skills -- 👉 about -- 👉 work projects -- 👉 personal projects +- 👉 Intro +- 👉 Links: LinkedIn, GitHub, Resume +- 👉 Skills +- 👉 About +- 👉 Work projects +- 👉 Personal projects **Project pages:** -- 👉 page for each project -- 👉 project image gallery - -## 💻 Commands - -Install dependencies. - -```bash -npm i -``` - -Runs the app in the development mode. - -```bash -npm run dev -``` - -Open [http://localhost:3000](http://localhost:3000) to view it in your browser. - -## 💅 Prettier - -This project uses Prettier for code formatting. - -Check if the code is formatted correctly. - -```bash -npm run prettier:check -``` - -Format the code via Prettier. - -```bash -npm run prettier:fix -``` - -## 🐛 Testing - 🃏 JEST - -Jest is JavaScript Testing Framework. - -- Test are located folder in `__tests__/jest` -- Naming is `file.test.ts` - -Runs the unit tests. - -```bash -npm run test -``` - -### Test coverage - -Jest will generate a code coverage report. - -- The report will be output to the console. -- It will also be saved to a `/coverage` directory in project root as HTML file. - -```bash -npm run test:coverage -``` - -## 🐛 Testing - 🎭 Playwright - -Playwright is library for browser automation E2E testing. - -- Test are located folder in `__tests__/playwright` -- Naming is `file.spec.ts` - -Runs the E2E tests. - -```bash -npx playwright test -``` - -Runs the E2E tests using alias for `npx playwright test` - -```bash -npm run test:e2e -``` - -### Test coverage - -Playwright will generate a code coverage report. - -- It serves HTML report on new localhost port. - -```bash - npx playwright show-report -``` - -### Other commands - -Starts the interactive UI mode. - -```bash -npx playwright test --ui -``` - -Runs the tests only on Desktop Chrome. - -```bash -npx playwright test --project=chromium -``` - -Runs the tests in a specific file. - -```bash -npx playwright test file.spec.ts -``` - -Runs the tests in debug mode. - -```bash -npx playwright test --debug -``` - -Auto generate tests with Codegen. - -```bash -npx playwright codegen -``` - -## 🚀 🛠️ CI - Continuous Integration - -This app uses GitHub Actions for CI. - -### GitHub Actions - Workflow "Jest" - -[![Jest Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/jest.yml) - -- Workflow file: [jest.yml](.github/workflows/jest.yml) -- View the results on GitHub: [actions/workflows/playwright.yml](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) - -
-Click to read workflow description 👀 - ---- - -This GitHub Actions workflow is named **"Jest"**. - -It is triggered in 2 scenarios: - -1. When a push is made to the `master` branch. -2. When a pull request is opened against the `master` branch. - -The workflow consists of a single job named `build`, which is executed on the latest version of Ubuntu. - -The `build` job follows these steps: - -1. Checkout the repository using the `actions/checkout@v3` action. -2. Setup Node.js environment using the `actions/setup-node@v3` action with Node.js version 18. -3. It installs the dependencies of your project using `npm ci`. This command is similar to `npm install`, but it's designed to be used in automated environments such as this one. -4. Run JEST tests using `npm test`. -5. Upload the test report as an artifact: - - Using the `actions/upload-artifact@v3` action. - - This step is always executed regardless of the success or failure of previous steps. - - The artifact is named `jest-report` - - It is located at path `jest-report/` - - It is retained for 7 days. - -
- -### GitHub Actions - Workflow "Playwright" - -[![Playwright Tests](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml/badge.svg)](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) - -- Workflow files in project root: [playwright.yml](.github/workflows/playwright.yml) -- View the results on GitHub: [actions/workflows/playwright.yml](https://github.com/krsiakdaniel/portfolio-website-krsiak-cz/actions/workflows/playwright.yml) - -
-Click to read workflow description 👀 - ---- - -It is triggered in 2 scenarios: - -1. When a push is made to the `master` branch. -2. When a pull request is opened against `master` branch. - -The workflow consists of a single job named `test`, which is executed on the latest version of Ubuntu. - -The `test` job follows these steps: - -1. Checkout the repository using the `actions/checkout@v3` action. -2. Setup Node.js environment using the `actions/setup-node@v3` action with Node.js version 18. -3. It installs the dependencies of your project using `npm ci`. This command is similar to `npm install`, but it's designed to be used in automated environments such as this one. -4. Install Playwright browsers using `npx playwright install --with-deps`. -5. Run Playwright tests using `npx playwright test`. -6. Upload the test report as an artifact: - - Using the `actions/upload-artifact@v3` action. - - This step is always executed regardless of the success or failure of previous steps. - - The artifact is named `playwright-report` - - It is located at path `playwright-report/` - - It is retained for 7 days. - -
- -## 🚀 ✅ CD - Continuous Deployment - -This app is deployed on Netlify. - -### Netlify +- 👉 Project information +- 👉 Job description +- 👉 Project screenshots -[![Netlify Status](https://api.netlify.com/api/v1/badges/eb322254-0169-4941-9416-3806b0bd5be6/deploy-status)](https://app.netlify.com/sites/portfolio-website-krsiak-cz/deploys) +## 💻 Development -Build starts when a new commit is pushed to the `master` branch. +Development: [README-development.md](README-development.md) -Using build plugin: +## 🐛 Testing -- [Lighthouse](https://developer.chrome.com/docs/lighthouse/overview) to automatically run audit on website after every build. +Testing: [README-testing.md](README-testing.md) -Deploys: +## 🚀 CI/CD - Continuous Integration / Deployment -- Netlify page [portfolio-website-krsiak-cz/deploys](https://app.netlify.com/sites/portfolio-website-krsiak-cz/deploys) -- You can click on the last 2 deploys to see the details. +CI/CD: [README-continuous-integration-deployment.md](README-continuous-integration-deployment.md) ## 🖼️ Screenshots diff --git a/screenshots/technologies.png b/screenshots/technologies.png new file mode 100644 index 0000000000000000000000000000000000000000..4ddc5ee677874f6a7b4ed605c64cffe59d9d8ae1 GIT binary patch literal 13912 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