Skip to content

Commit

Permalink
Add tests (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
timomeh committed Mar 24, 2024
1 parent d531385 commit a6c29bb
Show file tree
Hide file tree
Showing 12 changed files with 403 additions and 1 deletion.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'daily'
groups:
lint:
patterns:
- 'prettier*'
- 'eslint*'
36 changes: 36 additions & 0 deletions .github/workflows/playwright.yml
@@ -0,0 +1,36 @@
name: Playwright Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: pnpm
- run: pnpm install
- run: pnpm exec playwright install --with-deps
- run: pnpm exec playwright test
env:
GITHUB_ACCESS_TOKEN: ${{ secrets.BLOG_GH_ACCESS_TOKEN }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-screenshots
path: playwright-screenshots/
retention-days: 30
5 changes: 5 additions & 0 deletions .gitignore
Expand Up @@ -34,3 +34,8 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
/test-results/
/playwright-report/
/playwright-screenshots/
/blob-report/
/playwright/.cache/
5 changes: 4 additions & 1 deletion package.json
Expand Up @@ -6,7 +6,9 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"test": "playwright test",
"test:ui": "playwright test --ui"
},
"dependencies": {
"@octokit/graphql": "8.0.1",
Expand Down Expand Up @@ -41,6 +43,7 @@
"shiki": "1.1.7"
},
"devDependencies": {
"@playwright/test": "1.42.1",
"@tailwindcss/typography": "0.5.10",
"@types/ellipsize": "0.1.3",
"@types/lodash": "4.14.202",
Expand Down
43 changes: 43 additions & 0 deletions playwright.config.ts
@@ -0,0 +1,43 @@
import { defineConfig, devices } from '@playwright/test'

const PORT = process.env.PORT || 3000
const baseURL = `http://localhost:${PORT}`

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* 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: process.env.CI ? 'github' : 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL,

/* 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'] },
},
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm dev',
url: baseURL,
reuseExistingServer: !process.env.CI,
},
})
35 changes: 35 additions & 0 deletions pnpm-lock.yaml

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

1 change: 1 addition & 0 deletions src/comps/fade-in-image.tsx
Expand Up @@ -11,6 +11,7 @@ export function FadeInImage(props: ImageProps) {
<Image
quality={90}
fill
data-fade-in
data-loaded={loaded}
className="absolute inset-0 object-cover opacity-0 transition-opacity duration-1000
data-[loaded=true]:opacity-100"
Expand Down
25 changes: 25 additions & 0 deletions src/lib/blog.ts
Expand Up @@ -21,6 +21,10 @@ export const listTags = cache(async () => {
})

export const getTag = cache(async (slug: string) => {
if (slug === '__test') {
return { slug: 'test', name: 'Test', color: 'red' }
}

const labels = await fetchSortedLabels()
if (!labels.some((label) => labelNameToSlug(label.name) === slug)) {
return null
Expand Down Expand Up @@ -57,6 +61,27 @@ export const listPosts = cache(async (filter: ListPostsFilter = {}) => {
})

export const listPostsByYear = cache(async (filter: ListPostsFilter = {}) => {
if (filter.tag === '__test') {
return [
{
year: 2022,
posts: [
'how-to-build-a-blog',
'how-i-built-this-blog',
'what-belongs-into-gitignore',
],
},
{
year: 2023,
posts: [
'updating-to-next-13-app-dir',
'offtopic-thoughts',
'kid-francescoli-arte-concerts',
],
},
]
}

const discussions = await fetchSortedDiscussions({
label: filter.tag ? `tag:${filter.tag}` : undefined,
})
Expand Down
45 changes: 45 additions & 0 deletions tests/home.spec.ts
@@ -0,0 +1,45 @@
import { expect, test } from '@playwright/test'

test('has the correct title', async ({ page }) => {
await page.goto('/')
await expect(page).toHaveTitle('timomeh.de')
})

test('shows years', async ({ page }) => {
await page.goto('/')

await expect(
page.getByRole('heading', { name: '2024', exact: true }),
).toBeVisible()
await expect(
page.getByRole('heading', { name: '2023', exact: true }),
).toBeVisible()
await expect(
page.getByRole('heading', { name: '2022', exact: true }),
).toBeVisible()
})

test('lists articles', async ({ page }) => {
await page.goto('/')
await expect(page.getByRole('article')).not.toHaveCount(0)
expect(
page.getByRole('article', { name: /How to Build a Blog/ }),
).toBeDefined()
})

test('lists all tags', async ({ page }) => {
await page.goto('/')
await expect(page.getByRole('navigation').getByRole('link')).not.toHaveCount(
0,
)
})

test('has an active everything tag by default', async ({ page }) => {
await page.goto('/')
await expect(
page.getByRole('navigation').getByRole('link').first(),
).toHaveText('Everything')
await expect(
page.getByRole('navigation').getByRole('link').first(),
).toHaveAttribute('data-current', 'true')
})
51 changes: 51 additions & 0 deletions tests/page.spec.ts
@@ -0,0 +1,51 @@
import { expect, test } from '@playwright/test'

test('navigates from home to about', async ({ page }) => {
await page.goto('/')

await page.click('text=Timo Mämecke')
await expect(page).toHaveTitle('Hi, I’m Timo 👋 | timomeh.de')
expect(
page.getByRole('heading', { level: 1, name: 'Hi, I’m Timo 👋' }),
).toBeDefined()

expect(page.url()).toMatch(/\/about$/)
})

test('navigates from a post back', async ({ page }) => {
await page.goto('/about')

await page.getByRole('link', { name: /Back$/ }).click()
await expect(page).toHaveTitle('timomeh.de')
expect(new URL(page.url()).pathname).toBe('/')
})

test('renders the about page', async ({ page }) => {
await page.goto('/about')
await page.waitForLoadState('networkidle')
await page.screenshot({
fullPage: true,
path: 'playwright-screenshots/about.png',
timeout: 60_000,
})
})

test('renders the feeds page', async ({ page }) => {
await page.goto('/feeds')
await page.waitForLoadState('networkidle')
await page.screenshot({
fullPage: true,
path: 'playwright-screenshots/feeds.png',
timeout: 60_000,
})
})

test('renders the imprint page', async ({ page }) => {
await page.goto('/impressum')
await page.waitForLoadState('networkidle')
await page.screenshot({
fullPage: true,
path: 'playwright-screenshots/impressum.png',
timeout: 60_000,
})
})

0 comments on commit a6c29bb

Please sign in to comment.