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:
parent
9bb86e84b1
commit
9c4c8f04f4
11 changed files with 2020 additions and 225 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,5 +6,6 @@ node_modules
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
|
coverage
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
|
2074
package-lock.json
generated
2074
package-lock.json
generated
File diff suppressed because it is too large
Load diff
41
package.json
41
package.json
|
@ -10,36 +10,41 @@
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"test:unit": "vitest",
|
"test:unit": "vitest",
|
||||||
|
"test:unit:coverage": "vitest --coverage",
|
||||||
"lint": "prettier --check . && eslint .",
|
"lint": "prettier --check . && eslint .",
|
||||||
"format": "prettier --write ."
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "1.40.1",
|
"@playwright/test": "1.41.2",
|
||||||
"@skeletonlabs/skeleton": "2.6.1",
|
"@skeletonlabs/skeleton": "2.8.0",
|
||||||
"@skeletonlabs/tw-plugin": "0.3.0",
|
"@skeletonlabs/tw-plugin": "0.3.1",
|
||||||
"@sveltejs/adapter-auto": "3.0.1",
|
"@sveltejs/adapter-auto": "3.1.1",
|
||||||
"@sveltejs/kit": "2.0.4",
|
"@sveltejs/kit": "2.5.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "3.0.1",
|
"@sveltejs/vite-plugin-svelte": "3.0.2",
|
||||||
"@tailwindcss/forms": "0.5.7",
|
"@tailwindcss/forms": "0.5.7",
|
||||||
"@tailwindcss/typography": "0.5.10",
|
"@tailwindcss/typography": "0.5.10",
|
||||||
"@types/node": "20.10.5",
|
"@testing-library/jest-dom": "6.4.2",
|
||||||
"@typescript-eslint/eslint-plugin": "6.15.0",
|
"@testing-library/svelte": "4.1.0",
|
||||||
"@typescript-eslint/parser": "6.15.0",
|
"@types/node": "20.11.17",
|
||||||
"autoprefixer": "10.4.16",
|
"@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": "8.56.0",
|
||||||
"eslint-config-prettier": "9.1.0",
|
"eslint-config-prettier": "9.1.0",
|
||||||
"eslint-plugin-svelte": "2.35.1",
|
"eslint-plugin-svelte": "2.35.1",
|
||||||
"postcss": "8.4.32",
|
"jsdom": "24.0.0",
|
||||||
"prettier": "3.1.1",
|
"postcss": "8.4.35",
|
||||||
|
"prettier": "3.2.5",
|
||||||
"prettier-plugin-svelte": "3.1.2",
|
"prettier-plugin-svelte": "3.1.2",
|
||||||
"svelte": "4.2.8",
|
"svelte": "4.2.10",
|
||||||
"svelte-check": "3.6.2",
|
"svelte-check": "3.6.4",
|
||||||
"svelte-octicons": "18.6.0",
|
"svelte-octicons": "18.7.1",
|
||||||
"tailwindcss": "3.4.0",
|
"tailwindcss": "3.4.1",
|
||||||
"tslib": "2.6.2",
|
"tslib": "2.6.2",
|
||||||
"typescript": "5.3.3",
|
"typescript": "5.3.3",
|
||||||
"vite": "5.0.10",
|
"vite": "5.1.1",
|
||||||
"vitest": "1.1.0"
|
"vitest": "1.2.2"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
21
src/lib/components/atoms/Avatar.svelte
Normal file
21
src/lib/components/atoms/Avatar.svelte
Normal 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}
|
||||||
|
/>
|
|
@ -19,8 +19,8 @@ export const actions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: Consumre response?
|
// TODO: Consume response?
|
||||||
await requests.post('/login', { account, passphrase });
|
await requests.post('/login', { account, passphrase, server });
|
||||||
} catch (exc) {
|
} catch (exc) {
|
||||||
console.error(exc);
|
console.error(exc);
|
||||||
return fail(400, { account, incorrect: true });
|
return fail(400, { account, incorrect: true });
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { Avatar } from '@skeletonlabs/skeleton';
|
import Avatar from '$lib/components/atoms/Avatar.svelte';
|
||||||
|
|
||||||
/** @type {import('./$types').PageData} */
|
/** @type {import('./$types').PageData} */
|
||||||
export let data;
|
export let data;
|
||||||
|
@ -9,10 +9,8 @@
|
||||||
<!-- Profile header -->
|
<!-- Profile header -->
|
||||||
<div>
|
<div>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={data.user.avatar}
|
avatar={data.user.avatar}
|
||||||
width="w-32"
|
displayName={data.user.display_name}
|
||||||
rounded="rounded-full"
|
|
||||||
initials={data.user.display_name}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Board -->
|
<!-- Board -->
|
||||||
|
|
60
tests/components/atoms/Avatar.test.ts
Normal file
60
tests/components/atoms/Avatar.test.ts
Normal 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()
|
||||||
|
})
|
||||||
|
})
|
|
@ -8,10 +8,7 @@
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": 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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,5 @@ import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()],
|
plugins: [sveltekit()]
|
||||||
test: {
|
|
||||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
17
vitest.config.ts
Normal file
17
vitest.config.ts
Normal 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
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in a new issue