Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,16 @@ jobs:
run: |
rm -rf .rustfmt.toml
cargo fmt
- name: Build Landing
run: |
bun run --filter @devup-ui/components build-storybook
mv ./packages/components/storybook-static ./apps/landing/public/storybook
bun run --filter landing build
- name: Upload artifact
- name: Build Landing
run: |
bun run --filter @devup-ui/components build-storybook
mv ./packages/components/storybook-static ./apps/landing/public/storybook
bun run --filter landing build
- name: Install Playwright Browsers
run: bunx playwright install chromium --with-deps
- name: Run E2E Tests
run: bun run test:e2e
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./apps/landing/out
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ tarpaulin-report.json
storybook-static
.claude
.sisyphus
test-results
playwright-report
13 changes: 11 additions & 2 deletions bun.lock

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

1 change: 1 addition & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[test]
root = "packages"
preload = ["./packages/bun-plugin/src/index.ts", "./bun.setup.ts", "bun-test-env-dom"]
coverage = true
coverageReporter = ["text", "lcov"]
Expand Down
269 changes: 269 additions & 0 deletions e2e/components-pages.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
import { expect, test } from '@playwright/test'

test.describe('Components Pages', () => {
test.describe('Components link availability', () => {
test('header has Components link pointing to /components/overview', async ({
browser,
}) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const link = page.locator('a[href="/components/overview"]').first()
await expect(link).toBeVisible()
await expect(link).toHaveAttribute('href', '/components/overview')
await context.close()
})

test('Components link text is correct', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const link = page
.locator('a[href="/components/overview"]')
.filter({ hasText: 'Components' })
await expect(link).toBeVisible()
await context.close()
})

test('Components link is hidden on mobile', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 375, height: 812 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const link = page
.locator('a[href="/components/overview"]')
.filter({ hasText: 'Components' })
const isVisible = await link.isVisible().catch(() => false)
expect(isVisible).toBeFalsy()
await context.close()
})

test('Components link is visible on desktop', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const link = page
.locator('a[href="/components/overview"]')
.filter({ hasText: 'Components' })
await expect(link).toBeVisible()
await context.close()
})
})

test.describe('Storybook link', () => {
test('header has Storybook link', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const link = page.locator('a[href="/storybook/index.html"]').first()
await expect(link).toBeVisible()
await context.close()
})

test('Storybook link is hidden on mobile', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 375, height: 812 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const link = page
.locator('a[href="/storybook/index.html"]')
.filter({ hasText: 'Storybook' })
const isVisible = await link.isVisible().catch(() => false)
expect(isVisible).toBeFalsy()
await context.close()
})
})

test.describe('Benchmark section (component showcase on home page)', () => {
test('has Comparison Benchmarks section', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

await expect(page.getByText('Comparison Bechmarks').first()).toBeVisible()
await context.close()
})

test('shows Devup UI benchmark card', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const benchSection = page.getByText('Comparison Bechmarks').first()
await benchSection.scrollIntoViewIfNeeded()

// The Devup UI card is inside a client-side animation wrapper that keeps
// it visually hidden (opacity/transform) when JS is disabled. Verify the
// element exists in the DOM instead.
await expect(
page.locator('.typo-h5', { hasText: 'Devup UI' }).first(),
).toBeAttached()
await context.close()
})

test('shows competitor benchmarks', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const benchSection = page.getByText('Comparison Bechmarks').first()
await benchSection.scrollIntoViewIfNeeded()
await page.waitForTimeout(500)

// Check that several competitor names are visible
await expect(page.getByText('Chakra UI').first()).toBeVisible()
await expect(page.getByText('Tailwindcss').first()).toBeVisible()
await context.close()
})

test('desktop benchmark section screenshot', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const benchSection = page.getByText('Comparison Bechmarks').first()
await benchSection.scrollIntoViewIfNeeded()
await page.waitForTimeout(500)

await expect(page).toHaveScreenshot(
'components-benchmark-section-desktop.png',
{ fullPage: false },
)
await context.close()
})

test('mobile benchmark section screenshot', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 375, height: 812 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const benchSection = page.getByText('Comparison Bechmarks').first()
await benchSection.scrollIntoViewIfNeeded()
await page.waitForTimeout(500)

await expect(page).toHaveScreenshot(
'components-benchmark-section-mobile.png',
{ fullPage: false },
)
await context.close()
})

test('dark mode benchmark section screenshot', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
colorScheme: 'dark',
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const benchSection = page.getByText('Comparison Bechmarks').first()
await benchSection.scrollIntoViewIfNeeded()
await page.waitForTimeout(500)

await expect(page).toHaveScreenshot(
'dark-components-benchmark-section-desktop.png',
{ fullPage: false },
)
await context.close()
})
})

test.describe('Community section', () => {
test('has Join our community section', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const community = page.getByText('Join our community').first()
await community.scrollIntoViewIfNeeded()
await expect(community).toBeVisible()
await context.close()
})

test('has Discord link', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const discordLink = page
.locator('a[href="https://discord.gg/8zjcGc7cWh"]')
.first()
await expect(discordLink).toBeVisible()
await context.close()
})

test('has KakaoTalk link', async ({ browser }) => {
const context = await browser.newContext({
javaScriptEnabled: false,
viewport: { width: 1440, height: 900 },
})
const page = await context.newPage()
await page.goto('/')
await page.waitForTimeout(500)

const kakaoLink = page
.locator('a[href="https://open.kakao.com/o/giONwVAh"]')
.first()
await expect(kakaoLink).toBeVisible()
await context.close()
})
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading