Skip to content

Commit

Permalink
tests: added e2e tests to app
Browse files Browse the repository at this point in the history
  • Loading branch information
Eduardoooxd committed Jun 9, 2024
1 parent 087f805 commit 7fa9e8f
Show file tree
Hide file tree
Showing 17 changed files with 258 additions and 15 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Playwright Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: lts/*

- name: Install dependencies
run: npm install -g pnpm && pnpm install

- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps

- name: Run Playwright tests
run: pnpm e2e:test

- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ yarn-error.log*

# typescript
*.tsbuildinfo
next-env.d.ts
next-env.d.ts
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/tests-examples
66 changes: 66 additions & 0 deletions e2e/landing-page.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { expect, test } from '@playwright/test';

test.describe('Landing Page Tests', () => {
test.beforeEach(async ({ page }) => {
// Navigate to the base URL before each test
await page.goto('/');
});

test('Should have the appropriate page title', async ({ page }) => {
await expect(page).toHaveTitle(/Eduardo Couto/);
});

test('Should check content on hero section', async ({ page }) => {
await expect(page.getByTestId('hero-message')).toContainText(
"Hello, I'm Eduardo. I'm a full-stack developer with 2 years of experience. I enjoy buildingwebsites & applications. My main focus is with Java and React (Next.js).",
);
});

test('Should navigate to the Projects section', async ({ page }) => {
// Click on the Projects link
await page.goto('/#projects');

// Verify the Projects section is displayed by checking for a specific element
const projectsHeading = page.getByTestId('projects-heading');

await expect(projectsHeading).toBeTruthy();
await expect(projectsHeading).toContainText('My projects');
await expect(projectsHeading).toBeVisible();
});

test('Should submit the Contact form successfully', async ({ page }) => {
// Navigate to the Contact section
await page.goto('/#contact');
// Fill the form
await page.fill('input[name="name"]', 'John Doe');
await page.fill('input[name="email"]', 'john.doe@example.com');
await page.fill('textarea[name="message"]', 'Hello, This is a test message.');
// Click the submit button
await page.click('text=Submit');
// Verify submission success message or redirection
await expect(page.getByTestId('toast-container')).toBeVisible();
await expect(page.getByTestId('toast-container')).toContainText('Email sent successfully!');
});

test('Should show the contact form errors', async ({ page }) => {
// Navigate to the Contact section
await page.goto('/#contact');
// Fill the form
await page.fill('input[name="name"]', 'J');
await page.fill('input[name="email"]', 'john.doe@example.com');
await page.fill('textarea[name="message"]', '');
// Click the submit button
await page.click('text=Submit');

// Verify the error messages
await expect(page.getByTestId('invalid-name-warning')).toHaveText(
'Name must be at least 2 characters long',
);

await expect(page.getByTestId('invalid-email-warning')).toBeHidden();

await expect(page.getByTestId('invalid-message-warning')).toHaveText(
'Message must be at least 10 characters long',
);
});
});
32 changes: 32 additions & 0 deletions e2e/not-found-page.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect, test } from '@playwright/test';

test.describe('404 Page Tests', () => {
test.beforeEach(async ({ page }) => {
// Navigate to the base URL before each test
await page.goto('/non-existent-page');
});

test('Should display a 404 message for non-existent routes', async ({ page }) => {
// Navigate to a non-existent route
await page.goto('/non-existent-page');
// Check if the 404 text is present
await expect(page.locator('h1')).toContainText('404');
await expect(page.locator('h2')).toContainText('Page not found - Seems you look lost');

const redirectLink = page.getByTestId('redirect-home-link');
expect(redirectLink).toBeTruthy();
expect(redirectLink).toContainText('Click here to go back home');
expect(redirectLink).toHaveAttribute('href', '/');
});

test('Should redirect to landing page on click', async ({ page }) => {
// Navigate to a non-existent route
await page.goto('/non-existent-page');
// Check if the 404 text is present

const redirectLink = page.getByTestId('redirect-home-link');
await redirectLink.click();

await expect(page).toHaveURL('/');
});
});
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"e2e:test": "playwright test",
"e2e:open": "playwright test --ui",
"e2e:codegen": "playwright codegen"
},
"dependencies": {
"@hookform/resolvers": "^3.4.2",
Expand All @@ -32,6 +35,7 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@playwright/test": "^1.44.1",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
57 changes: 57 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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',
/* Run tests in files in parallel */
fullyParallel: true,
/* 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',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm start',
url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI,
},
});
43 changes: 41 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default function Custom404() {
<div className="min-dh-screen-without-nav flex flex-col items-center justify-center gap-2">
<h1 className="text-5xl font-bold">404</h1>
<h2 className="text-base font-semibold sm:text-2xl">Page not found - Seems you look lost</h2>
<Link href="/" className="underline">
<Link href="/" className="underline" data-testid="redirect-home-link">
Click here to go back home
</Link>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/about-me.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function AboutMe() {
delay: 0.225,
}}
>
<SectionHeading>About me</SectionHeading>
<SectionHeading dataTestId="about-heading">About me</SectionHeading>
<p className="mb-4">
After graduating with a degree in <span className="font-bold">Informatics Engineering</span>
, I decided to pursue my passion for software development. I have gained extensive
Expand Down
6 changes: 3 additions & 3 deletions src/components/contact-section-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function ContactSectionForm() {
<FormControl>
<Input placeholder="Your name" {...field} />
</FormControl>
<FormMessage />
<FormMessage data-testid="invalid-name-warning" />
</FormItem>
)}
/>
Expand All @@ -69,7 +69,7 @@ export default function ContactSectionForm() {
<FormControl>
<Input type="email" placeholder="Your email" {...field} />
</FormControl>
<FormMessage />
<FormMessage data-testid="invalid-email-warning" />
</FormItem>
)}
/>
Expand All @@ -82,7 +82,7 @@ export default function ContactSectionForm() {
<FormControl>
<Textarea placeholder="Your message" {...field} />
</FormControl>
<FormMessage />
<FormMessage data-testid="invalid-message-warning" />
</FormItem>
)}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/contact-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function ContactSection() {
}}
viewport={{ once: true }}
>
<SectionHeading>Contact Me</SectionHeading>
<SectionHeading dataTestId="contact-heading">Contact Me</SectionHeading>
<div className="flex flex-col gap-4">
<p className="sm:text-center">
Contact me at {''}
Expand Down
2 changes: 1 addition & 1 deletion src/components/experience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function Experience() {

return (
<section id="experience" ref={ref} className="scroll-mt-8 sm:scroll-mt-28">
<SectionHeading>My Experience</SectionHeading>
<SectionHeading dataTestId="experience-heading">My Experience</SectionHeading>

<div ref={timelineInViewRef}>
<VerticalTimeline lineColor="">
Expand Down
Loading

0 comments on commit 7fa9e8f

Please sign in to comment.