diff --git a/.dockerignore b/.dockerignore index c2923d8..ebe0776 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,3 +8,5 @@ CONTRIBUTING.md LICENSE README.md SECURITY.md +test-results +playwright-report diff --git a/.gitignore b/.gitignore index ecfdb4f..d504dd4 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ yarn.lock pnpm-lock.yaml *storybook.log +test-results +playwright-report diff --git a/.storybook/main.ts b/.storybook/main.ts index 5d43640..ab1922e 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,21 +1,19 @@ -import type {StorybookConfig} from "@storybook/vue3-vite"; +import type { StorybookConfig } from "@storybook/vue3-vite"; const config: StorybookConfig = { - stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], - addons: [ - "@storybook/addon-onboarding", - "@storybook/addon-links", - "@storybook/addon-essentials", - "@chromatic-com/storybook", - "@storybook/addon-interactions", - ], - framework: { - name: "@storybook/vue3-vite", - options: {}, - }, - docs: { - autodocs: "tag", - }, - staticDirs: ["../public"], + stories: [ "../stories/**/*.stories.ts" ], + addons: [ + "@storybook/addon-onboarding", + "@storybook/addon-links", + "@storybook/addon-essentials", + "@chromatic-com/storybook", + "@storybook/addon-interactions", + ], + framework: { + name: "@storybook/vue3-vite", + options: {}, + }, + docs: {}, + staticDirs: [ "../public" ], }; export default config; diff --git a/.storybook/manager.ts b/.storybook/manager.ts index b51ccfb..3d99cf9 100644 --- a/.storybook/manager.ts +++ b/.storybook/manager.ts @@ -5,7 +5,7 @@ addons.setConfig({ theme: create({ base: "dark", textColor: "white", - appPreviewBg: "#333333", + appPreviewBg: "#0f101d", brandTitle: "NEI Market Analytics", brandUrl: "https://bush1d3v-portfolio.vercel.app/", brandImage: "logo.svg", diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 208f92f..61b3760 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -20,7 +20,7 @@ const preview: Preview = { values: [ { name: "dark", - value: "#333333", + value: "#0f101d", }, { name: "light", @@ -29,8 +29,18 @@ const preview: Preview = { ], }, }, - tags: ["autodocs"], - decorators: [withActions], + tags: ["autodocs", "autodocs"], + decorators: [ + withActions, + (story) => ({ + components: {story}, + template: ` +
+ +
+ `, + }), + ], }; export default preview; diff --git a/Dockerfile b/Dockerfile index edd7213..025ebe7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,9 @@ FROM node:20 RUN apt-get update && apt-get install -y \ xdg-utils \ - git-all + git-all \ + libevent-2.1-7 \ + libgstreamer-plugins-bad1.0-0 WORKDIR /app @@ -14,4 +16,6 @@ EXPOSE 5173 EXPOSE 6006 +EXPOSE 9323 + CMD ["npm", "run", "dev"] diff --git a/README.md b/README.md index acb2a1d..1325fdc 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ O **NEI Market Analytics** é um projeto de código aberto projetado para fornec docker   vitest    storybook-js     - vueuse   + vueuse    + playwright   biomejs   chromatic   @@ -73,7 +74,13 @@ bun build ### Executar testes de unidade com [Vitest](https://vitest.dev/) ```sh -bun tests +bun test:unit +``` + +### Executar testes de ponta a ponta com [Playwright](https://playwright.dev/) + +```sh +bun test:e2e ``` Isso executa os testes de ponta a ponta no servidor de desenvolvimento Vite. @@ -109,7 +116,8 @@ The **NEI Market Analytics** is an open-source project designed to provide compr docker   vitest    storybook-js     - vueuse   + vueuse    + playwright   biomejs   chromatic   @@ -155,5 +163,11 @@ bun build ### Run Unit Tests with [Vitest](https://vitest.dev/) ```sh -bun tests +bun test:unit +``` + +### Run E2E Tests with [Playwright](https://playwright.dev/) + +```sh +bun test:e2e ``` diff --git a/docker-compose.yml b/docker-compose.yml index b9fa9b6..556dd41 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,7 @@ services: volumes: - .:/app working_dir: /app - environment: - - GIT_USER_EMAIL=${GIT_USER_EMAIL} - - GIT_USER_NAME=${GIT_USER_NAME} - command: sh -c "git config --global user.email \"$GIT_USER_EMAIL\" && git config --global user.name \"$GIT_USER_NAME\" && git config --global --add safe.directory /app && npm run dev" + command: npm run dev ports: - "5173:5173" @@ -26,3 +23,14 @@ services: - "6006:6006" depends_on: - vue + + playwright: + image: node:20 + volumes: + - .:/app + working_dir: /app + command: sh -c "npx playwright install-deps && npx playwright install chromium && npx playwright install firefox && apt-get install -y xvfb xauth && xvfb-run -- npx playwright test --ui" + ports: + - "9323:9323" + depends_on: + - vue diff --git a/e2e/about-us.spec.ts b/e2e/about-us.spec.ts new file mode 100644 index 0000000..86d06d5 --- /dev/null +++ b/e2e/about-us.spec.ts @@ -0,0 +1,45 @@ +import { test, expect } from "@playwright/test"; + +test.describe("About Us Page Tests", () => { + test("Visits the about-us page and checks content", async ({ page }) => { + await page.goto("/about-us"); + + const mainContent = page.locator("main.container"); + await expect(mainContent).toBeVisible(); + + const h1 = mainContent.locator("h1"); + await expect(h1).toHaveText("Impulsionando o Futuro Juntos"); + + const h2 = mainContent.locator("h2"); + await expect(h2).toHaveText("Colaborando para um amanhã mais tecnológico."); + + const p = mainContent.locator("p"); + await expect(p).toHaveText("Por Trás dos Códigos"); + + const header = page.locator("header"); + await expect(header).toBeVisible(); + + const footer = page.locator("footer"); + await expect(footer).toBeVisible(); + }); + + test("Checks visibility of Accordion and Badges components", async ({ page }) => { + await page.goto("/about-us"); + + const accordion = page.locator("[data-testid='Accordion']"); + await expect(accordion).toBeVisible(); + + const badges = page.locator("[data-testid='Badges']"); + await expect(badges).toBeVisible(); + }); + + // test("Checks navigation back to home", async ({ page }) => { + // await page.goto("/about-us"); + + // const homeLink = page.locator("a[href='/']"); + // await expect(homeLink).toBeVisible(); + // await homeLink.click(); + + // await expect(page).toHaveURL("/"); + // }); +}); diff --git a/e2e/home.spec.ts b/e2e/home.spec.ts new file mode 100644 index 0000000..b98ad8c --- /dev/null +++ b/e2e/home.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from "@playwright/test"; + +test.describe("Home Page Tests", () => { + test("Visits the app root url and checks main content", async ({ page }) => { + await page.goto("/"); + + const mainContainer = page.locator("main.container"); + await expect(mainContainer).toBeVisible(); + await expect(mainContainer).toHaveText("NEI Market Analytics"); + }); + + test("Checks visibility of header", async ({ page }) => { + await page.goto("/"); + + const header = page.locator("header"); + await expect(header).toBeVisible(); + }); + + test("Checks visibility of footer", async ({ page }) => { + await page.goto("/"); + + const footer = page.locator("footer"); + await expect(footer).toBeVisible(); + }); + + test("Checks clickable text and navigation to about-us", async ({ page }) => { + await page.goto("/"); + + const clickableText = page.locator("main.container >> text=NEI Market Analytics"); + await expect(clickableText).toBeVisible(); + await clickableText.click(); + + await expect(page).toHaveURL("/about-us"); + }); +}); diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json new file mode 100644 index 0000000..dfdb9af --- /dev/null +++ b/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/index.html b/index.html index 85a6462..0a0c6c4 100644 --- a/index.html +++ b/index.html @@ -19,6 +19,11 @@ + + + NEI Market Analytics diff --git a/mocks/components/HoverCard.ts b/mocks/components/HoverCard.ts new file mode 100644 index 0000000..d0adca1 --- /dev/null +++ b/mocks/components/HoverCard.ts @@ -0,0 +1,9 @@ +import type {HoverCardProps} from "@/components/HoverCard.vue"; + +export const HoverCardMock: HoverCardProps = { + title: "John Doe", + description: "Creator of Radix UI and Figma's design system", + startDate: "February 2022", + avatarSrc: "https://avatars.githubusercontent.com/u/11473738?v=4", + avatarFallback: "JD", +}; diff --git a/mocks/components/tags/Image.ts b/mocks/components/tags/Image.ts new file mode 100644 index 0000000..5399308 --- /dev/null +++ b/mocks/components/tags/Image.ts @@ -0,0 +1,9 @@ +import type {ImageProps} from "@/tags/Image.vue"; + +export const ImageMock: ImageProps = { + alt: "image", + height: "80", + width: "80", + src: "https://via.placeholder.com/80", + class: "w-20 h-20 rounded-full", +}; diff --git a/mocks/components/tags/Link.ts b/mocks/components/tags/Link.ts new file mode 100644 index 0000000..82619f2 --- /dev/null +++ b/mocks/components/tags/Link.ts @@ -0,0 +1,7 @@ +import type {LinkProps} from "@/tags/Link.vue"; + +export const LinkMock: LinkProps = { + href: "https://www.google.com", + target: "_blank", + class: "font-bold underline", +}; diff --git a/package.json b/package.json index 6b69c37..70e823b 100644 --- a/package.json +++ b/package.json @@ -6,18 +6,21 @@ "license": "MIT", "scripts": { "dev": "vite", - "build": "run-p type-check \"build-only {@}\" --", + "builds": "run-p type-check \"build-only {@}\" --", "preview": "vite preview", - "tests": "vitest", + "test:unit": "vitest", + "test:e2e": "playwright test", + "test:report": "bunx playwright show-report", + "test:e2e-ui": "bunx playwright test --ui", "storybook": "storybook dev -p 6006", "lint": "npx @biomejs/biome format --write ./", "build-only": "vite build", "type-check": "vue-tsc --build --force", + "build-storybook": "storybook build", "docker-build": "docker-compose build", "docker-run": "docker build -t nei_market_analytics .", "docker-up": "docker-compose up", - "docker-clean": "docker-compose down", - "build-storybook": "storybook build" + "docker-clean": "docker-compose down" }, "dependencies": { "@radix-icons/vue": "^1.0.0", @@ -33,18 +36,19 @@ "vue-router": "^4.3.3" }, "devDependencies": { + "@playwright/test": "^1.44.1", "@biomejs/biome": "^1.8.3", - "@chromatic-com/storybook": "^1.9.0", - "@storybook/addon-essentials": "^8.2.9", - "@storybook/addon-interactions": "^8.2.9", - "@storybook/addon-links": "^8.2.9", - "@storybook/addon-onboarding": "^8.2.9", - "@storybook/blocks": "^8.2.9", - "@storybook/manager-api": "^8.2.9", - "@storybook/test": "^8.2.9", - "@storybook/theming": "^8.2.9", - "@storybook/vue3": "^8.2.9", - "@storybook/vue3-vite": "^8.2.9", + "@chromatic-com/storybook": "^2.0.2", + "@storybook/addon-essentials": "^8.3.0", + "@storybook/addon-interactions": "^8.3.0", + "@storybook/addon-links": "^8.3.0", + "@storybook/addon-onboarding": "^8.3.0", + "@storybook/blocks": "^8.3.0", + "@storybook/manager-api": "^8.3.0", + "@storybook/test": "^8.3.0", + "@storybook/theming": "^8.3.0", + "@storybook/vue3": "^8.3.0", + "@storybook/vue3-vite": "^8.3.0", "@testing-library/vue": "^8.1.0", "@tsconfig/node20": "^20.1.4", "@types/jsdom": "^21.1.7", @@ -56,9 +60,8 @@ "autoprefixer": "^10.4.20", "jsdom": "^25.0.0", "npm-run-all2": "^6.2.0", - "shadcn-nuxt": "^0.10.4", "start-server-and-test": "^2.0.4", - "storybook": "^8.2.9", + "storybook": "^8.3.0", "typescript": "~5.5.4", "vite": "^5.3.1", "vite-plugin-vue-devtools": "^7.3.1", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..29d34c6 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,86 @@ +import process from "node:process"; +import { defineConfig, devices } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: "./e2e", + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [ [ 'html', { outputFolder: 'playwright-report' } ] ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: "http://localhost:5173", + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI, + + /* Take a screenshot on failure */ + screenshot: 'only-on-failure', + video: 'retain-on-failure', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { + ...devices[ "Desktop Chrome" ], + }, + }, + { + name: "firefox", + use: { + ...devices[ "Desktop Firefox" ], + }, + }, + { + name: "Mobile Chrome", + use: { + ...devices[ "Pixel 5" ], + }, + }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? "vite preview --port 5173" : "vite dev", + port: 5173, + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/public/sitemap.xml b/public/sitemap.xml index 2595c3e..6e70dba 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -7,7 +7,7 @@ 1.0 - http://localhost:5173/about + http://localhost:5173/about-us 2023-10-01 monthly 0.8 diff --git a/src/App.vue b/src/App.vue index 6d7b1b5..936445c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,6 +1,7 @@