refactor: turn Profile page into a component
This way it is easier to inspect the design implementation. Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
parent
34be485a49
commit
20a44974d5
13 changed files with 714 additions and 213 deletions
|
@ -1,3 +1,12 @@
|
|||
<button type="button" class="underline">block</button>
|
||||
or
|
||||
<button type="button" class="underline">report</button>
|
||||
<script lang="ts">
|
||||
import { _ } from 'svelte-i18n';
|
||||
</script>
|
||||
|
||||
{@html $_('page.profile.activities.block_or_report', {
|
||||
values: {
|
||||
blockElementOpen: '<button type="button" class="underline">',
|
||||
blockElementClose: '</button>',
|
||||
reportElementOpen: '<button type="button" class="underline">',
|
||||
reportElementClose: '</button>'
|
||||
}
|
||||
})}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { _ } from 'svelte-i18n';
|
||||
|
||||
/**
|
||||
* Under which name shall the person be known?
|
||||
*/
|
||||
|
@ -11,7 +13,8 @@
|
|||
</script>
|
||||
|
||||
<h1 class="h1 font-semibold text-4xl leading-tight">
|
||||
<span class="sr-only">Profile for </span>
|
||||
<!-- FIXME: Include placeholder in i18n -->
|
||||
<span class="sr-only">{$_('page.profile.heading')}</span>
|
||||
{@html displayName}
|
||||
</h1>
|
||||
<p class="leading-normal my-1">({@html pronoun})</p>
|
||||
|
|
10
src/lib/components/pages/Profile.svelte
Normal file
10
src/lib/components/pages/Profile.svelte
Normal file
|
@ -0,0 +1,10 @@
|
|||
<script lang="ts">
|
||||
import ProfileTemplate from '../templates/Profile.svelte';
|
||||
|
||||
/**
|
||||
* Data populated by SvelteKit
|
||||
*/
|
||||
export let data: unknown = null;
|
||||
</script>
|
||||
|
||||
<ProfileTemplate {data} />
|
5
src/lib/components/templates/Profile.d.ts
vendored
Normal file
5
src/lib/components/templates/Profile.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
export type ProfileData = {
|
||||
user: {
|
||||
display_name: string;
|
||||
};
|
||||
};
|
105
src/lib/components/templates/Profile.svelte
Normal file
105
src/lib/components/templates/Profile.svelte
Normal file
|
@ -0,0 +1,105 @@
|
|||
<script lang="ts">
|
||||
import { _, date } from 'svelte-i18n';
|
||||
import { NorthStar24, Star16 } from 'svelte-octicons';
|
||||
|
||||
import Avatar from '../atoms/Avatar.svelte';
|
||||
import BlockOrReport from '../atoms/BlockOrReport.svelte';
|
||||
import Created from '../atoms/Created.svelte';
|
||||
import DisplayName from '../atoms/DisplayName.svelte';
|
||||
|
||||
import type { ProfileData } from './Profile.d.ts';
|
||||
|
||||
/**
|
||||
* Required context for populating the template.
|
||||
*/
|
||||
export let data: ProfileData = null;
|
||||
</script>
|
||||
|
||||
<section class="w-full mx-auto flex px-8 pt-8">
|
||||
<!-- Profile header -->
|
||||
<div>
|
||||
<Avatar avatar={data.user.avatar} displayName={data.user.display_name} />
|
||||
</div>
|
||||
<!-- Board -->
|
||||
<div class="flex flex-1 flex-col pl-8">
|
||||
<div class="self-end">
|
||||
<Created
|
||||
created_at={data.user.created_at}
|
||||
created_at_formatted={data.user.created_at_formatted}
|
||||
/>
|
||||
<BlockOrReport />
|
||||
</div>
|
||||
<!-- Top Row -->
|
||||
<div class="flex mt-2">
|
||||
<!-- Board -->
|
||||
<div class="flex flex-col flex-1 gap-2">
|
||||
<div class="flex items-end">
|
||||
<DisplayName displayName={data.user.display_name} pronoun={data.user.pronoun} />
|
||||
</div>
|
||||
<span class="leading-tight">
|
||||
{data.user.username}@{data.user.instance}
|
||||
</span>
|
||||
</div>
|
||||
<!-- Interaction Links -->
|
||||
<button type="button" class="btn-icon border rounded-none self-start">
|
||||
<Star16 fill="currentColor" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="w-full h-full mx-auto flex mt-8 px-8">
|
||||
<!-- Board -->
|
||||
<div class="flex flex-1 flex-col px-4">
|
||||
<div class="space-y-6">
|
||||
<h2 class="h2 font-semibold leading-tight text-base px-4">
|
||||
{$_('page.profile.projects.heading')}
|
||||
</h2>
|
||||
<p class="px-4">
|
||||
{$_('page.profile.projects.empty')}
|
||||
{@html $_('page.profile.projects.add_or_import', {
|
||||
values: {
|
||||
addElementOpen: '<a class="anchor" href="#">',
|
||||
addElementClose: '</a>',
|
||||
importElementOpen: '<a class="anchor" href="/projects/import/">',
|
||||
importElementClose: '</a>'
|
||||
}
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- History -->
|
||||
<div class="flex flex-1 flex-col px-4">
|
||||
<div class="space-y-6">
|
||||
<h2 class="h2 font-semibold leading-tight text-base">
|
||||
{$_('page.profile.history.heading')}
|
||||
</h2>
|
||||
<ul>
|
||||
<li class="flex flex-col border-l-2 ml-2">
|
||||
<!-- Commit day -->
|
||||
<span class="relative">
|
||||
<span class="absolute -left-3">
|
||||
<NorthStar24 fill="currentColor" />
|
||||
</span>
|
||||
<span class="ml-4">
|
||||
{$date(new Date('2023-04-23'))} - {$_(
|
||||
'page.profile.history.activities.setup.summary'
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
<!-- Commits -->
|
||||
<span class="ml-6 mt-8">
|
||||
<span class="border box-decoration-clone px-4 py-2 leading-10">
|
||||
{$_('page.profile.history.activities.setup.description', {
|
||||
values: {
|
||||
created_with: data.user.created_with,
|
||||
instance: data.user.instance,
|
||||
username: data.user.username
|
||||
}
|
||||
})}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
|
@ -34,6 +34,27 @@
|
|||
"heading": "Create project",
|
||||
"intro": "Add a new F2 project to Anvil."
|
||||
},
|
||||
"profile": {
|
||||
"activities": {
|
||||
"block_or_report": "{blockElementOpen}block{blockElementClose} or {reportElementOpen}report{reportElementClose}",
|
||||
"like": ""
|
||||
},
|
||||
"heading": "Profile for",
|
||||
"history": {
|
||||
"activities": {
|
||||
"setup": {
|
||||
"description": "The F2 account @{username}@{instance} was successfully set up within {created_with}",
|
||||
"summary": "account set up"
|
||||
}
|
||||
},
|
||||
"heading": "Activities"
|
||||
},
|
||||
"projects": {
|
||||
"add_or_import": "{addElementOpen}Add a project{addElementClose} or {importElementOpen}import a project{importElementClose}.",
|
||||
"empty": "No projects added yet.",
|
||||
"heading": "Projects"
|
||||
}
|
||||
},
|
||||
"welcome": "Welcome to Anvil!"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,77 +1,8 @@
|
|||
<script>
|
||||
import Avatar from '$lib/components/atoms/Avatar.svelte';
|
||||
import BlockOrReport from '$lib/components/atoms/BlockOrReport.svelte';
|
||||
import Created from '$lib/components/atoms/Created.svelte';
|
||||
import DisplayName from '$lib/components/atoms/DisplayName.svelte';
|
||||
import Profile from '$lib/components/pages/Profile.svelte';
|
||||
|
||||
/** @type {import('./$types').PageData} */
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<section class="w-full mx-auto flex px-8 pt-8">
|
||||
<!-- Profile header -->
|
||||
<div>
|
||||
<Avatar avatar={data.user.avatar} displayName={data.user.display_name} />
|
||||
</div>
|
||||
<!-- Board -->
|
||||
<div class="flex flex-1 flex-col pl-8">
|
||||
<div class="self-end">
|
||||
<Created
|
||||
created_at={data.user.created_at}
|
||||
created_at_formatted={data.user.created_at_formatted}
|
||||
/>
|
||||
<BlockOrReport />
|
||||
</div>
|
||||
<!-- Top Row -->
|
||||
<div class="flex mt-2">
|
||||
<!-- Board -->
|
||||
<div class="flex flex-col flex-1 gap-2">
|
||||
<div class="flex items-end">
|
||||
<DisplayName displayName={data.user.display_name} pronoun={data.user.pronoun} />
|
||||
</div>
|
||||
<span class="leading-tight">
|
||||
{@html data.user.username}@{@html data.user.instance}
|
||||
</span>
|
||||
</div>
|
||||
<!-- Interaction Links -->
|
||||
<button type="button" class="btn-icon border rounded-none self-start">⭐</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="w-full h-full mx-auto flex mt-8 px-8">
|
||||
<!-- Board -->
|
||||
<div class="flex flex-1 flex-col px-4">
|
||||
<div class="space-y-6">
|
||||
<h2 class="h2 font-semibold leading-tight text-base px-4">Projects</h2>
|
||||
<p class="px-4">
|
||||
No projects added yet.
|
||||
<a class="anchor" href="#">Add a project</a>
|
||||
or
|
||||
<a class="anchor" href="/projects/import/">import a project</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- History -->
|
||||
<div class="flex flex-1 flex-col px-4">
|
||||
<div class="space-y-6">
|
||||
<h2 class="h2 font-semibold leading-tight text-base">Activities</h2>
|
||||
<ul>
|
||||
<li class="flex flex-col border-l-2 ml-2">
|
||||
<!-- Commit day -->
|
||||
<span>
|
||||
<!-- North Star in surface-900 -->
|
||||
<span class="-ml-2 bg-[#0f161f]">✴️</span>
|
||||
<span class="ml-4">Apr 23, 2023 - account set up</span>
|
||||
</span>
|
||||
<!-- Commits -->
|
||||
<span class="ml-6 mt-8">
|
||||
<span class="border box-decoration-clone px-4 py-2 leading-10">
|
||||
The F2 account @{@html data.user.username}@{@html data.user.instance} was successfully
|
||||
set up within {@html data.user.created_with}
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<Profile {data} />
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { init, locale, register } from 'svelte-i18n';
|
||||
|
||||
import BlockOrReport from '../../../src/lib/components/atoms/BlockOrReport.svelte';
|
||||
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||
|
||||
describe('BlockOrReport.svelte', () => {
|
||||
beforeEach(() => {
|
||||
register('en', () => import('../../../src/lib/i18n/locales/en.json'));
|
||||
init({ fallbackLocale: 'en', initialLocale: 'en' });
|
||||
locale.set('en');
|
||||
});
|
||||
|
||||
it('should mount', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
|
@ -23,7 +31,7 @@ describe('BlockOrReport.svelte', () => {
|
|||
render(BlockOrReport);
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('block')).toBeDefined();
|
||||
expect(screen.getByRole('button', { name: 'block' })).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow for report', () => {
|
||||
|
@ -34,6 +42,6 @@ describe('BlockOrReport.svelte', () => {
|
|||
render(BlockOrReport);
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('report')).toBeDefined();
|
||||
expect(screen.getByRole('button', { name: 'report' })).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { init, locale, register } from 'svelte-i18n';
|
||||
|
||||
import DisplayName from '../../../src/lib/components/atoms/DisplayName.svelte';
|
||||
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||
|
||||
describe('DisplayName.svelte', () => {
|
||||
beforeEach(() => {
|
||||
register('en', () => import('../../../src/lib/i18n/locales/en.json'));
|
||||
init({ fallbackLocale: 'en', initialLocale: 'en' });
|
||||
locale.set('en');
|
||||
});
|
||||
|
||||
it('should mount', () => {
|
||||
// Arrange
|
||||
const displayName = 'Jane Doe';
|
||||
|
@ -13,6 +21,7 @@ describe('DisplayName.svelte', () => {
|
|||
render(DisplayName, { displayName, pronoun });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByRole('heading', { level: 1 })).toBeInTheDocument();
|
||||
expect(screen.getByText(displayName)).toBeInTheDocument();
|
||||
// Turn into regular expression to respect round brackets
|
||||
expect(screen.getByText(new RegExp(pronoun))).toBeInTheDocument();
|
||||
|
|
|
@ -2,7 +2,7 @@ import '@testing-library/jest-dom';
|
|||
import { render, screen } from '@testing-library/svelte';
|
||||
import { init, locale, register } from 'svelte-i18n';
|
||||
|
||||
import ImportProject from '../../../src/lib/components/templates/ImportProject.svelte';
|
||||
import ImportProject from '../../../src/lib/components/pages/ImportProject.svelte';
|
||||
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||
|
||||
describe('ImportProject.svelte', () => {
|
||||
|
@ -14,10 +14,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should mount', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
const { container } = render(ImportProject);
|
||||
const { container } = render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(container).toBeTruthy();
|
||||
|
@ -25,10 +25,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a form', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByRole('form')).toBeInTheDocument();
|
||||
|
@ -36,10 +36,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a h2', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
const h2 = screen.getByRole('heading', { level: 2 });
|
||||
|
||||
// Assert
|
||||
|
@ -49,10 +49,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have an intro text', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText(enMessages.page.import_project.intro)).toBeInTheDocument();
|
||||
|
@ -61,10 +61,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('name', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the asterisk
|
||||
const name = screen.getByLabelText(
|
||||
|
@ -77,10 +77,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a text input', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const name = screen.getByPlaceholderText(
|
||||
enMessages.page.import_project.form.fields.name.placeholder
|
||||
|
@ -94,10 +94,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('when empty', () => {
|
||||
it('should display an error', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(
|
||||
|
@ -110,10 +110,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe.skip('when filled', () => {
|
||||
it('should hide the error', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(
|
||||
|
@ -123,10 +123,11 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should show a live updating hint', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
const value = 'Vervis';
|
||||
|
||||
// Act
|
||||
render(ImportProject, { value });
|
||||
render(ImportProject, { data, value });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText(`domain.example/projects/${value}`)).toBeInTheDocument();
|
||||
|
@ -137,10 +138,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('description', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const description = screen.getByLabelText(
|
||||
enMessages.page.import_project.form.fields.description.label
|
||||
|
@ -152,10 +153,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a textarea', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const description = screen.getByPlaceholderText(
|
||||
enMessages.page.import_project.form.fields.description.placeholder
|
||||
|
@ -169,44 +170,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('avatar', () => {
|
||||
it('should have a heading', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
|
||||
const avatar = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
name: enMessages.page.import_project.form.avatar
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have an upload button', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const avatar = screen.getByLabelText(
|
||||
new RegExp(enMessages.page.import_project.form.fields.avatar.label)
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('components', () => {
|
||||
it('should have a heading', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const components = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
|
@ -220,10 +187,62 @@ describe('ImportProject.svelte', () => {
|
|||
describe('repository', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const avatar = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
name: enMessages.page.import_project.form.avatar
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have an upload button', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const avatar = screen.getByLabelText(
|
||||
new RegExp(enMessages.page.import_project.form.fields.avatar.label)
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('components', () => {
|
||||
it('should have a heading', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject, { data });
|
||||
|
||||
const components = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
name: enMessages.page.import_project.form.components
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(components).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('repository', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const repository = screen.getByLabelText(
|
||||
|
@ -236,10 +255,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have an URL input', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const repository = screen.getByPlaceholderText(
|
||||
|
@ -252,10 +271,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a hint', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const repository = screen.getByText(
|
||||
|
@ -270,10 +289,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('issues', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const issues = screen.getByLabelText(
|
||||
|
@ -288,10 +307,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('pull requests', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const issues = screen.getByLabelText(enMessages.page.import_project.form.fields.pr.label);
|
||||
|
|
181
tests/components/pages/Profile.test.ts
Normal file
181
tests/components/pages/Profile.test.ts
Normal file
|
@ -0,0 +1,181 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { init, locale, register } from 'svelte-i18n';
|
||||
|
||||
import Profile from '../../../src/lib/components/pages/Profile.svelte';
|
||||
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||
|
||||
describe('Profile.svelte', () => {
|
||||
beforeEach(() => {
|
||||
register('en', () => import('../../../src/lib/i18n/locales/en.json'));
|
||||
init({ fallbackLocale: 'en', initialLocale: 'en' });
|
||||
locale.set('en');
|
||||
});
|
||||
|
||||
it('should mount', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
const { container } = render(Profile, { data });
|
||||
|
||||
// Assert
|
||||
expect(container).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have a h1', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const h1 = screen.getByRole('heading', { level: 1 });
|
||||
|
||||
// Assert
|
||||
expect(h1).toBeInTheDocument();
|
||||
expect(h1).toHaveTextContent(enMessages.page.profile.heading);
|
||||
});
|
||||
|
||||
it('should have a block button', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const button = screen.getByRole('button', { name: 'block' });
|
||||
|
||||
// Assert
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have a report button', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const button = screen.getByRole('button', { name: 'report' });
|
||||
|
||||
// Assert
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// FIXME: Reenable once emoji was replaced with svelte-octicon
|
||||
it.skip('should have a like button', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const button = screen.getByRole('button', { name: enMessages.page.profile.activities.like });
|
||||
|
||||
// Assert
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('projects', () => {
|
||||
it('should have a h2', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const h2 = screen.getByRole('heading', {
|
||||
level: 2,
|
||||
name: enMessages.page.profile.projects.heading
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(h2).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should add a project', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const a = screen.getByRole('link', { name: 'Add a project' });
|
||||
|
||||
// Assert
|
||||
expect(a).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should import a project', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const a = screen.getByRole('link', { name: 'import a project' });
|
||||
|
||||
// Assert
|
||||
expect(a).toBeInTheDocument();
|
||||
expect(a).toHaveAttribute('href', '/projects/import/');
|
||||
});
|
||||
});
|
||||
|
||||
describe('history', () => {
|
||||
it('should have a h2', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const h2 = screen.getByRole('heading', {
|
||||
level: 2,
|
||||
name: enMessages.page.profile.history.heading
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(h2).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have an entry for created account', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {
|
||||
created_with: 'Anvil',
|
||||
instance: 'domain.example',
|
||||
username: 'jane_doe'
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const li = screen.getByRole('listitem');
|
||||
|
||||
// Assert
|
||||
expect(li).toBeInTheDocument();
|
||||
expect(li).toHaveTextContent(
|
||||
new RegExp(enMessages.page.profile.history.activities.setup.summary)
|
||||
);
|
||||
expect(li).toHaveTextContent(
|
||||
new RegExp(
|
||||
enMessages.page.profile.history.activities.setup.description
|
||||
.replace('{username}', data.user.username)
|
||||
.replace('{instance}', data.user.instance)
|
||||
.replace('{created_with}', data.user.created_with)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,7 +2,7 @@ import '@testing-library/jest-dom';
|
|||
import { render, screen } from '@testing-library/svelte';
|
||||
import { init, locale, register } from 'svelte-i18n';
|
||||
|
||||
import ImportProject from '../../../src/lib/components/pages/ImportProject.svelte';
|
||||
import ImportProject from '../../../src/lib/components/templates/ImportProject.svelte';
|
||||
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||
|
||||
describe('ImportProject.svelte', () => {
|
||||
|
@ -14,10 +14,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should mount', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
const { container } = render(ImportProject);
|
||||
const { container } = render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(container).toBeTruthy();
|
||||
|
@ -25,10 +25,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a form', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByRole('form')).toBeInTheDocument();
|
||||
|
@ -36,10 +36,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a h2', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
const h2 = screen.getByRole('heading', { level: 2 });
|
||||
|
||||
// Assert
|
||||
|
@ -49,10 +49,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have an intro text', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText(enMessages.page.import_project.intro)).toBeInTheDocument();
|
||||
|
@ -61,10 +61,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('name', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the asterisk
|
||||
const name = screen.getByLabelText(
|
||||
|
@ -77,10 +77,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a text input', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const name = screen.getByPlaceholderText(
|
||||
enMessages.page.import_project.form.fields.name.placeholder
|
||||
|
@ -94,10 +94,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('when empty', () => {
|
||||
it('should display an error', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(
|
||||
|
@ -110,10 +110,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe.skip('when filled', () => {
|
||||
it('should hide the error', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Assert
|
||||
expect(
|
||||
|
@ -123,10 +123,11 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should show a live updating hint', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
const value = 'Vervis';
|
||||
|
||||
// Act
|
||||
render(ImportProject, { value });
|
||||
render(ImportProject, { data, value });
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText(`domain.example/projects/${value}`)).toBeInTheDocument();
|
||||
|
@ -137,10 +138,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('description', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const description = screen.getByLabelText(
|
||||
enMessages.page.import_project.form.fields.description.label
|
||||
|
@ -152,10 +153,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a textarea', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const description = screen.getByPlaceholderText(
|
||||
enMessages.page.import_project.form.fields.description.placeholder
|
||||
|
@ -169,44 +170,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('avatar', () => {
|
||||
it('should have a heading', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
|
||||
const avatar = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
name: enMessages.page.import_project.form.avatar
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have an upload button', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const avatar = screen.getByLabelText(
|
||||
new RegExp(enMessages.page.import_project.form.fields.avatar.label)
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('components', () => {
|
||||
it('should have a heading', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const components = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
|
@ -220,10 +187,62 @@ describe('ImportProject.svelte', () => {
|
|||
describe('repository', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
const avatar = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
name: enMessages.page.import_project.form.avatar
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have an upload button', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const avatar = screen.getByLabelText(
|
||||
new RegExp(enMessages.page.import_project.form.fields.avatar.label)
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(avatar).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('components', () => {
|
||||
it('should have a heading', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject, { data });
|
||||
|
||||
const components = screen.getByRole('heading', {
|
||||
level: 3,
|
||||
name: enMessages.page.import_project.form.components
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(components).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('repository', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const repository = screen.getByLabelText(
|
||||
|
@ -236,10 +255,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have an URL input', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const repository = screen.getByPlaceholderText(
|
||||
|
@ -252,10 +271,10 @@ describe('ImportProject.svelte', () => {
|
|||
|
||||
it('should have a hint', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const repository = screen.getByText(
|
||||
|
@ -270,10 +289,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('issues', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const issues = screen.getByLabelText(
|
||||
|
@ -288,10 +307,10 @@ describe('ImportProject.svelte', () => {
|
|||
describe('pull requests', () => {
|
||||
it('should have a label', () => {
|
||||
// Arrange
|
||||
// Nothing to prepare
|
||||
const data = {};
|
||||
|
||||
// Act
|
||||
render(ImportProject);
|
||||
render(ImportProject, { data });
|
||||
|
||||
// Turn into regular expression to account for the icon
|
||||
const issues = screen.getByLabelText(enMessages.page.import_project.form.fields.pr.label);
|
||||
|
|
181
tests/components/templates/Profile.test.ts
Normal file
181
tests/components/templates/Profile.test.ts
Normal file
|
@ -0,0 +1,181 @@
|
|||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { init, locale, register } from 'svelte-i18n';
|
||||
|
||||
import Profile from '../../../src/lib/components/templates/Profile.svelte';
|
||||
import enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||
|
||||
describe('Profile.svelte', () => {
|
||||
beforeEach(() => {
|
||||
register('en', () => import('../../../src/lib/i18n/locales/en.json'));
|
||||
init({ fallbackLocale: 'en', initialLocale: 'en' });
|
||||
locale.set('en');
|
||||
});
|
||||
|
||||
it('should mount', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
const { container } = render(Profile, { data });
|
||||
|
||||
// Assert
|
||||
expect(container).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have a h1', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const h1 = screen.getByRole('heading', { level: 1 });
|
||||
|
||||
// Assert
|
||||
expect(h1).toBeInTheDocument();
|
||||
expect(h1).toHaveTextContent(enMessages.page.profile.heading);
|
||||
});
|
||||
|
||||
it('should have a block button', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const button = screen.getByRole('button', { name: 'block' });
|
||||
|
||||
// Assert
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have a report button', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const button = screen.getByRole('button', { name: 'report' });
|
||||
|
||||
// Assert
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// FIXME: Reenable once emoji was replaced with svelte-octicon
|
||||
it.skip('should have a like button', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const button = screen.getByRole('button', { name: enMessages.page.profile.activities.like });
|
||||
|
||||
// Assert
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('projects', () => {
|
||||
it('should have a h2', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const h2 = screen.getByRole('heading', {
|
||||
level: 2,
|
||||
name: enMessages.page.profile.projects.heading
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(h2).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should add a project', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const a = screen.getByRole('link', { name: 'Add a project' });
|
||||
|
||||
// Assert
|
||||
expect(a).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should import a project', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const a = screen.getByRole('link', { name: 'import a project' });
|
||||
|
||||
// Assert
|
||||
expect(a).toBeInTheDocument();
|
||||
expect(a).toHaveAttribute('href', '/projects/import/');
|
||||
});
|
||||
});
|
||||
|
||||
describe('history', () => {
|
||||
it('should have a h2', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const h2 = screen.getByRole('heading', {
|
||||
level: 2,
|
||||
name: enMessages.page.profile.history.heading
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(h2).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should have an entry for created account', () => {
|
||||
// Arrange
|
||||
const data = {
|
||||
user: {
|
||||
created_with: 'Anvil',
|
||||
instance: 'domain.example',
|
||||
username: 'jane_doe'
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
render(Profile, { data });
|
||||
const li = screen.getByRole('listitem');
|
||||
|
||||
// Assert
|
||||
expect(li).toBeInTheDocument();
|
||||
expect(li).toHaveTextContent(
|
||||
new RegExp(enMessages.page.profile.history.activities.setup.summary)
|
||||
);
|
||||
expect(li).toHaveTextContent(
|
||||
new RegExp(
|
||||
enMessages.page.profile.history.activities.setup.description
|
||||
.replace('{username}', data.user.username)
|
||||
.replace('{instance}', data.user.instance)
|
||||
.replace('{created_with}', data.user.created_with)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue