Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test/add cypress #283

Merged
merged 88 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
d8422e9
test: add template cypress test and CI
Feb 14, 2024
31175c4
test: debug
Feb 14, 2024
57485ed
Revert "test: debug"
Feb 14, 2024
dc8ccc4
chore: prettier code format
Feb 14, 2024
3c459b8
ci: run E2E on multiple browsers
Feb 14, 2024
18f5863
ci: fix job name
Feb 14, 2024
cf0ca5d
ci: install webkit deps
Feb 14, 2024
76a4c13
ci: conditionally install webkit deps
Feb 14, 2024
65866ce
ci: e2e condition
Feb 14, 2024
5f9e796
ci: check if ref exists
Feb 14, 2024
5394fd3
test: add incomplete navigation tests
Feb 14, 2024
1596877
ci(e2e): remove debug messages
Feb 14, 2024
77af5ac
test: Cypress uses dedicated TS config
Feb 14, 2024
ca155e4
feat: add cypress to tech stack
Feb 14, 2024
3d220e0
test: run E2E in headed browsers
Feb 14, 2024
4eb9f19
Revert "test: run E2E in headed browsers"
Feb 14, 2024
7e175aa
test: ignore `ValiError`
Feb 14, 2024
c298409
test: fix ignoring ValiError handling
Feb 14, 2024
5e24c8f
chore: Package update
Feb 15, 2024
a9bd849
test: refactor navigation test
Feb 15, 2024
29a6fb4
test: incomplete nav tests with invalid RSS test
Feb 15, 2024
3f4a3d6
test: use another way to test platform profile links, since WebKit ca…
Feb 15, 2024
2bfaa17
ci(unlighthouse): add unlighthouse benchmark
Feb 15, 2024
6b45b53
ci(unlighthouse): workflow name
Feb 15, 2024
57e2b61
ci(unlighthouse): reduce sample to 2 to workaround the error
Feb 15, 2024
ad78b8e
ci(unlighthouse): remove samples for now due to known issue
Feb 15, 2024
502fcdb
test(unlighthouse): upload result as artifact
Feb 15, 2024
975f0d1
ci(unlighthouse): always upload result
Feb 15, 2024
19f9119
test(unlighthouse): use expanded report
Feb 15, 2024
3ef5315
ci(unlighthouse): reduce budget to 80
mwskwong Feb 15, 2024
9ff60d2
ci(unlighthouse): use config file
mwskwong Feb 15, 2024
efa20ad
feat: update base URL in non-prod
mwskwong Feb 15, 2024
8f37b8e
chore: format code
mwskwong Feb 15, 2024
4519d87
test: tsconfig extends vercel base config
mwskwong Feb 15, 2024
1c99ae8
ci(unlighthouse): adjust budget
mwskwong Feb 15, 2024
93f80db
ci(unlighthouse): update config
Feb 16, 2024
9b980e2
chore: Package update
Feb 16, 2024
9425c3e
ci(e2e): use headed browser
Feb 16, 2024
6b07d60
test: remove `cy.request` to social media site, since some of them ar…
Feb 16, 2024
415ad7e
ci(unlighthouse): update throttle method
Feb 16, 2024
66d0904
Revert "ci(unlighthouse): update throttle method"
Feb 16, 2024
d421d6c
chore: Package update
mwskwong Feb 17, 2024
5547dbb
test: add color mode test
mwskwong Feb 17, 2024
8d3819f
chore: format code
mwskwong Feb 17, 2024
c21c423
ci(e2e): use headless browser
mwskwong Feb 17, 2024
b49aeec
feat: remove redundant tooltip
mwskwong Feb 17, 2024
b8771db
ci(unlighthouse): remove budget for now since it is unreliable
mwskwong Feb 17, 2024
00d734b
feat: optimize SVG
mwskwong Feb 17, 2024
fdee50b
chore: Package update
mwskwong Feb 18, 2024
c7173f0
ci(e2e): assign vercel env to env var
mwskwong Feb 18, 2024
7239898
test: add download CV test
mwskwong Feb 18, 2024
d5004ff
chore: format code
mwskwong Feb 18, 2024
af2efa4
ci(e2e): fix env access
mwskwong Feb 18, 2024
e2d97fb
ci(unlighthouse): some how loops forever
mwskwong Feb 18, 2024
f186fb6
Revert "ci(unlighthouse): some how loops forever"
mwskwong Feb 18, 2024
3ed63cc
ci(e2e): debug if `environment` is causing actions to spawn endlessly
mwskwong Feb 18, 2024
616e826
Revert "ci(e2e): debug if `environment` is causing actions to spawn e…
mwskwong Feb 18, 2024
7357cc2
ci(e2e): prevent triggering redeploy
mwskwong Feb 18, 2024
9042086
ci(e2e): avoid infinite loop
mwskwong Feb 18, 2024
ed0b961
ci(e2e): minor formatting
mwskwong Feb 18, 2024
52ef327
chore: Package update
Feb 19, 2024
659dde5
ci(e2e): disable npm cache, since it doesn't work in `deployment_status`
Feb 19, 2024
08b0406
ci(e2e): ensure other tests continue to run even if it fails on one o…
Feb 19, 2024
c1117de
test(download-cy): refactor
mwskwong Feb 19, 2024
8001a18
test(download-cv): validate the CV actually downloads
mwskwong Feb 19, 2024
95e870f
test(download-cv): refactoring
mwskwong Feb 19, 2024
67ff37f
feat: add `suppressHydrationWarning` to `html`
mwskwong Feb 19, 2024
5e9470b
ci(e2e): runs on mac to omit installing webkit deps
Feb 20, 2024
c75e5c7
chore: Package update
Feb 20, 2024
0c1431a
feat: ensure the entire site is blocking bots
Feb 20, 2024
7fcd875
ci: cache Cypress binary and minor changes
Feb 20, 2024
689d9ae
ci(e2e): simplify workflow
Feb 20, 2024
3aea788
Revert "ci(e2e): simplify workflow"
Feb 20, 2024
985ede7
Revert "ci(e2e): runs on mac to omit installing webkit deps"
Feb 20, 2024
369524b
ci(e2e): remove Cypress binary cache since it is not supported in dep…
Feb 20, 2024
5251aff
Merge branch 'develop' into test/add-cypress
mwskwong Feb 20, 2024
b5ba85f
test: use nav constant
mwskwong Feb 20, 2024
adaa46d
test: add linkedin
mwskwong Feb 20, 2024
31858b8
test: add incomplete skill set test
mwskwong Feb 20, 2024
b1c1b42
chore: Package update
Feb 21, 2024
2fe3090
test: refactor tests
Feb 21, 2024
f05ccc9
test: refactor ctx type definition
Feb 21, 2024
9075eca
test: extract queries to dedicated file and refactored skill set test
Feb 21, 2024
47fcbec
test: add WIP slider dragging interaction
Feb 21, 2024
68eadad
test: put helper func in test suite
Feb 21, 2024
7d4bac3
test: complete skill set test suite
Feb 21, 2024
691f4b5
test: fix expected CV URL
Feb 21, 2024
0c80ffb
test: make skill set test or reliable
Feb 21, 2024
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
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ module.exports = {
// Must use default export
{
files: [
'cypress.config.mjs',
'next.config.mjs',
'prettier.config.mjs',
'unlighthouse.config.ts',
'app/**/page.tsx',
'app/**/layout.tsx',
'app/**/not-found.tsx',
Expand All @@ -112,5 +114,9 @@ module.exports = {
files: ['**/*.d.ts'],
rules: { 'import/no-default-export': 'off' },
},
{
files: ['cypress/**'],
extends: ['plugin:cypress/recommended'],
},
],
};
31 changes: 31 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: E2E
on: deployment_status

jobs:
e2e:
if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success'
runs-on: ubuntu-latest
strategy:
matrix:
browser: [chrome, edge, firefox, webkit]
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
# cache: 'npm' # currently npm cache doesn't work in deployment_status
- run: npm ci
- run: npx playwright install-deps webkit
if: matrix.browser == 'webkit'
- uses: cypress-io/github-action@v6
with:
install: false
browser: ${{ matrix.browser }}
env:
CYPRESS_BASE_URL: ${{ github.event.deployment_status.environment_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CYPRESS_CONTENTFUL_SPACE_ID: ${{ secrets.CONTENTFUL_SPACE_ID }}
CYPRESS_CONTENTFUL_ACCESS_TOKEN: ${{ github.event.deployment_status.environment == 'Production' && secrets.CONTENTFUL_ACCESS_TOKEN_PROD || secrets.CONTENTFUL_ACCESS_TOKEN_DEVELOP }}
CYPRESS_ENVIRONMENT: ${{ github.event.deployment_status.environment }}
7 changes: 4 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
name: Lint Code
on: [pull_request, push]
on: push

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 20
cache: 'npm'
- run: npm ci
- run: npx next lint
7 changes: 4 additions & 3 deletions .github/workflows/prettify.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
name: Prettify Code
on: [pull_request, push]
on: push

jobs:
prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 20
cache: 'npm'
- run: npm ci
- run: npx prettier . --check
20 changes: 20 additions & 0 deletions .github/workflows/unlighthouse.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Unlighthouse
on: deployment_status

jobs:
unlighthouse:
if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g @unlighthouse/cli puppeteer
# FIXME: --samples is currently bugged, set it to 3 when unlighthouse is using lighthouse v10+
# FIXME: --throttle is not recognized when specified in config file, specifying it with CLI option instead
- run: |
unlighthouse-ci \
--site ${{ github.event.deployment_status.environment_url }} \
--throttle
- uses: actions/upload-artifact@v4
if: always()
with:
path: ./.unlighthouse
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# cypress
cypress/downloads/
cypress/screenshots/
cypress/videos/
cypress.env.json
39 changes: 17 additions & 22 deletions app/(main)/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Grid,
IconButton,
Stack,
Tooltip,
Typography,
} from '@mui/joy';
import { Metadata } from 'next';
Expand Down Expand Up @@ -157,31 +156,27 @@ const Blog: FC<BlogProps> = async ({ params: { slug } }) => {
{platformProfiles.map(
({ platform, url }) =>
platform && (
<Tooltip
<IconButton
aria-label={`${platform.name} profile`}
component="a"
href={url}
key={platform.id}
title={`${platform.name} profile`}
size="sm"
target="_blank"
>
<IconButton
component="a"
href={url}
size="sm"
target="_blank"
>
<Icon contentfulId={platform.id} />
</IconButton>
</Tooltip>
<Icon contentfulId={platform.id} />
</IconButton>
),
)}
<Tooltip title="RSS Feed">
<IconButton
component="a"
href={blogRssFeed.pathname}
size="sm"
target="_blank"
>
<SiRss viewBox="-2 -2 28 28" />
</IconButton>
</Tooltip>
<IconButton
aria-label="RSS Feed"
component="a"
href={blogRssFeed.pathname}
size="sm"
target="_blank"
>
<SiRss viewBox="-2 -2 28 28" />
</IconButton>
</Stack>
</Stack>
<Stack
Expand Down
3 changes: 2 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import { baseUrl } from '@/constants/site-config';
import { Providers } from './providers';

const RootLayout: FC<PropsWithChildren> = ({ children }) => (
<html lang="en">
// data-joy-color-scheme is dynamically injected, suppressing the hydration warning in this case
<html lang="en" suppressHydrationWarning>
<body>
<Providers>{children}</Providers>
<Analytics />
Expand Down
2 changes: 1 addition & 1 deletion app/robots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const robots = () =>
({
rules: {
userAgent: '*',
allow: '/',
disallow: process.env.VERCEL_ENV === 'production' ? undefined : '/',
},
sitemap: `${baseUrl}/sitemap.xml`,
}) satisfies MetadataRoute.Robots;
Expand Down
37 changes: 13 additions & 24 deletions components/blog/copy-url-button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { IconButton, IconButtonProps, Tooltip } from '@mui/joy';
import { IconButton, IconButtonProps } from '@mui/joy';
import { Check, Copy } from 'lucide-react';
import { usePathname } from 'next/navigation';
import { FC, useEffect, useRef, useState } from 'react';
Expand All @@ -24,28 +24,17 @@ export const CopyUrlButton: FC<Omit<IconButtonProps, 'children'>> = (props) => {
useEffect(() => () => clearTimeout(timeout.current), []);

return (
<Tooltip title="Copy blog url">
<IconButton
aria-pressed={copied}
color={copied ? 'success' : undefined}
onClick={async () => {
await navigator.clipboard.writeText(url);
setCopied(true);
timeout.current = setTimeout(() => setCopied(false), 1000);
}}
sx={{
'&[aria-pressed="true"]:not(:active)': {
bgcolor: 'transparent',
'&:hover': {
bgcolor: (theme) =>
theme.vars.palette[copied ? 'success' : 'neutral'].plainHoverBg,
},
},
}}
{...props}
>
{copied ? <Check /> : <Copy />}
</IconButton>
</Tooltip>
<IconButton
aria-label="Copy blog url"
color={copied ? 'success' : undefined}
onClick={async () => {
await navigator.clipboard.writeText(url);
setCopied(true);
timeout.current = setTimeout(() => setCopied(false), 1000);
}}
{...props}
>
{copied ? <Check /> : <Copy />}
</IconButton>
);
};
12 changes: 6 additions & 6 deletions components/blog/share-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
Menu,
MenuButton,
MenuItem,
Tooltip,
} from '@mui/joy';
import { Share2 } from 'lucide-react';
import { usePathname } from 'next/navigation';
Expand Down Expand Up @@ -66,11 +65,12 @@ export const ShareDropdown: FC<ShareDropdownProps> = ({ blog, ...props }) => {

return (
<Dropdown {...props}>
<Tooltip title="Share this blog">
<MenuButton slots={{ root: IconButton }}>
<Share2 />
</MenuButton>
</Tooltip>
<MenuButton
slotProps={{ root: { 'aria-label': 'Share this blog' } }}
slots={{ root: IconButton }}
>
<Share2 />
</MenuButton>
<Menu>
{socialMediaOptions.map(({ Icon, name, url }) => (
<MenuItem component="a" href={url} key={name} target="_blank">
Expand Down
2 changes: 2 additions & 0 deletions components/contentful.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { LiteralUnion } from 'type-fest';

import * as contentfulIds from '@/constants/contentful-ids';
import ContentfulLight from '@/logos/contentful-light.svg';
import CypressLight from '@/logos/cypress-light.svg';
import EmailJs from '@/logos/emailjs.svg';
import ImprovMx from '@/logos/improvmx.svg';
import Mui from '@/logos/mui.svg';
Expand Down Expand Up @@ -112,6 +113,7 @@ const Logos = {
light: PrismaLight,
dark: PrismaDark,
},
[contentfulIds.cypress]: { light: CypressLight, dark: undefined },
};

export interface LogoProps extends SVGProps<SVGSVGElement> {
Expand Down
40 changes: 19 additions & 21 deletions components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
ListItem,
ListItemButton,
Stack,
Tooltip,
Typography,
} from '@mui/joy';
import NextLink from 'next/link';
Expand All @@ -35,28 +34,27 @@ export const Footer: FC<FooterProps> = async (props) => {
{platformProfiles.map(
({ platform, url }) =>
platform && (
<Tooltip key={platform.id} title={`${platform.name} profile`}>
<IconButton
component="a"
href={url}
size="sm"
target="_blank"
>
<Icon contentfulId={platform.id} />
</IconButton>
</Tooltip>
<IconButton
aria-label={`${platform.name} profile`}
component="a"
href={url}
key={platform.id}
size="sm"
target="_blank"
>
<Icon contentfulId={platform.id} />
</IconButton>
),
)}
<Tooltip title="RSS Feed">
<IconButton
component="a"
href={blogRssFeed.pathname}
size="sm"
target="_blank"
>
<SiRss viewBox="-2 -2 28 28" />
</IconButton>
</Tooltip>
<IconButton
aria-label="RSS Feed"
component="a"
href={blogRssFeed.pathname}
size="sm"
target="_blank"
>
<SiRss viewBox="-2 -2 28 28" />
</IconButton>
</Stack>

<Typography level="body-sm" mt={2}>
Expand Down
25 changes: 13 additions & 12 deletions components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
ListItem,
ListItemButton,
Stack,
Tooltip,
} from '@mui/joy';
import NextLink from 'next/link';
import { FC } from 'react';
Expand Down Expand Up @@ -52,11 +51,13 @@ export const Header: FC<HeaderProps> = async (props) => {
<Link
aria-label="Go to home page"
component={NextLink}
data-cy="logo"
href={{ pathname: home.pathname, hash: home.id }}
>
<Logo width={30} />
</Link>
<List
data-cy="nav-list-md"
orientation="horizontal"
sx={{
'--List-radius': 'var(--joy-radius-sm)',
Expand All @@ -83,17 +84,17 @@ export const Header: FC<HeaderProps> = async (props) => {
{platformProfiles.map(
({ platform, url }) =>
platform && (
<Tooltip key={platform.id} title={`${platform.name} profile`}>
<IconButton
component="a"
href={url}
size="sm"
target="_blank"
variant="outlined"
>
<Icon contentfulId={platform.id} />
</IconButton>
</Tooltip>
<IconButton
aria-label={`${platform.name} profile`}
component="a"
href={url}
key={platform.id}
size="sm"
target="_blank"
variant="outlined"
>
<Icon contentfulId={platform.id} />
</IconButton>
),
)}
<ModeToggleButton size="sm" variant="outlined" />
Expand Down
Loading
Loading