refactor: break out routes into components

For now I'm following the Atomic Design philosophy with respect to
organising the components. I started with Avatar which wraps the
SvelteKit library with some defaults. I test it using vitest which is
now configured accordingly. All dependencies were updated to their
latest version.

Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
André Jaenisch 2024-02-09 11:19:08 +01:00
parent 9bb86e84b1
commit 9c4c8f04f4
No known key found for this signature in database
GPG key ID: 5A668E771F1ED854
11 changed files with 2020 additions and 225 deletions

1
.gitignore vendored
View file

@ -6,5 +6,6 @@ node_modules
.env
.env.*
!.env.example
coverage
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

2074
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -10,36 +10,41 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test:unit": "vitest",
"test:unit:coverage": "vitest --coverage",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@playwright/test": "1.40.1",
"@skeletonlabs/skeleton": "2.6.1",
"@skeletonlabs/tw-plugin": "0.3.0",
"@sveltejs/adapter-auto": "3.0.1",
"@sveltejs/kit": "2.0.4",
"@sveltejs/vite-plugin-svelte": "3.0.1",
"@playwright/test": "1.41.2",
"@skeletonlabs/skeleton": "2.8.0",
"@skeletonlabs/tw-plugin": "0.3.1",
"@sveltejs/adapter-auto": "3.1.1",
"@sveltejs/kit": "2.5.0",
"@sveltejs/vite-plugin-svelte": "3.0.2",
"@tailwindcss/forms": "0.5.7",
"@tailwindcss/typography": "0.5.10",
"@types/node": "20.10.5",
"@typescript-eslint/eslint-plugin": "6.15.0",
"@typescript-eslint/parser": "6.15.0",
"autoprefixer": "10.4.16",
"@testing-library/jest-dom": "6.4.2",
"@testing-library/svelte": "4.1.0",
"@types/node": "20.11.17",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"@vitest/coverage-v8": "1.2.2",
"autoprefixer": "10.4.17",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-svelte": "2.35.1",
"postcss": "8.4.32",
"prettier": "3.1.1",
"jsdom": "24.0.0",
"postcss": "8.4.35",
"prettier": "3.2.5",
"prettier-plugin-svelte": "3.1.2",
"svelte": "4.2.8",
"svelte-check": "3.6.2",
"svelte-octicons": "18.6.0",
"tailwindcss": "3.4.0",
"svelte": "4.2.10",
"svelte-check": "3.6.4",
"svelte-octicons": "18.7.1",
"tailwindcss": "3.4.1",
"tslib": "2.6.2",
"typescript": "5.3.3",
"vite": "5.0.10",
"vitest": "1.1.0"
"vite": "5.1.1",
"vitest": "1.2.2"
},
"type": "module"
}

View file

@ -1,7 +0,0 @@
import { describe, it, expect } from 'vitest';
describe('sum test', () => {
it('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
});

View file

@ -0,0 +1,21 @@
<script lang="ts">
import { Avatar } from '@skeletonlabs/skeleton';
/**
* URL to Avatar image.
*/
export let avatar: string | undefined = '';
/**
* Name to derive initials from if no avatar is given.
*/
export let displayName: string | undefined = '';
</script>
<Avatar
src={avatar}
alt={displayName}
width="w-32"
rounded="rounded-full"
initials={displayName}
/>

View file

@ -19,8 +19,8 @@ export const actions = {
}
try {
// TODO: Consumre response?
await requests.post('/login', { account, passphrase });
// TODO: Consume response?
await requests.post('/login', { account, passphrase, server });
} catch (exc) {
console.error(exc);
return fail(400, { account, incorrect: true });

View file

@ -1,5 +1,5 @@
<script>
import { Avatar } from '@skeletonlabs/skeleton';
import Avatar from '$lib/components/atoms/Avatar.svelte';
/** @type {import('./$types').PageData} */
export let data;
@ -9,10 +9,8 @@
<!-- Profile header -->
<div>
<Avatar
src={data.user.avatar}
width="w-32"
rounded="rounded-full"
initials={data.user.display_name}
avatar={data.user.avatar}
displayName={data.user.display_name}
/>
</div>
<!-- Board -->

View file

@ -0,0 +1,60 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/svelte'
import Avatar from '../../../src/lib/components/atoms/Avatar.svelte'
describe('Avatar.svelte', () => {
it('should mount', () => {
// Arrange
// Nothing to prepare
// Act
const { container } = render(Avatar);
// Assert
expect(container).toBeTruthy()
})
it('should pick up the passed image', () => {
// Arrange
const avatar = 'https://example.com/avatar.png'
// Act
render(Avatar, { avatar })
const figure = screen.getByTestId('avatar')
const image = figure.querySelector('img')
// Assert
expect(figure).toBeInTheDocument()
expect(image).not.toBeNull()
expect(image).toHaveAttribute('src', avatar)
})
it('should use an image with alt text', () => {
// Arrange
const avatar = 'https://example.com/avatar.png'
const displayName = 'Jane Doe'
// Act
render(Avatar, { avatar, displayName })
const figure = screen.getByTestId('avatar')
// Assert
expect(figure).toBeInTheDocument()
expect(screen.getByAltText(displayName)).toBeDefined()
})
it('should use the initials as text', () => {
// Arrange
const displayName = 'Jane Doe'
const initials = displayName.substring(0, 2).toUpperCase()
// Act
render(Avatar, { displayName })
const figure = screen.getByTestId('avatar')
// Assert
expect(figure).toBeInTheDocument()
expect(screen.getByText(initials)).toBeDefined()
})
})

View file

@ -8,10 +8,7 @@
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
"strict": true,
"types": ["vitest/globals"]
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}

View file

@ -2,8 +2,5 @@ import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [sveltekit()],
test: {
include: ['src/**/*.{test,spec}.{js,ts}']
}
plugins: [sveltekit()]
});

17
vitest.config.ts Normal file
View file

@ -0,0 +1,17 @@
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [svelte({ hot: !process.env.VITEST })],
test: {
coverage: {
include: [
'src/**/*.svelte'
]
},
include: ['tests/**/*.test.ts'],
environment: 'jsdom',
globals: true
}
});