From 20a44974d5df6805250518c14de6ddeb1b0bb01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Mon, 19 Feb 2024 11:33:41 +0100 Subject: [PATCH] refactor: turn Profile page into a component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way it is easier to inspect the design implementation. Signed-off-by: André Jaenisch --- src/lib/components/atoms/BlockOrReport.svelte | 15 +- src/lib/components/atoms/DisplayName.svelte | 5 +- src/lib/components/pages/Profile.svelte | 10 + src/lib/components/templates/Profile.d.ts | 5 + src/lib/components/templates/Profile.svelte | 105 ++++++++++ src/lib/i18n/locales/en.json | 21 ++ src/routes/profile/+page.svelte | 73 +------ tests/components/atoms/BlockOrReport.test.ts | 12 +- tests/components/atoms/DisplayName.test.ts | 9 + tests/components/pages/ImportProject.test.ts | 155 ++++++++------- tests/components/pages/Profile.test.ts | 181 ++++++++++++++++++ .../templates/ImportProject.test.ts | 155 ++++++++------- tests/components/templates/Profile.test.ts | 181 ++++++++++++++++++ 13 files changed, 714 insertions(+), 213 deletions(-) create mode 100644 src/lib/components/pages/Profile.svelte create mode 100644 src/lib/components/templates/Profile.d.ts create mode 100644 src/lib/components/templates/Profile.svelte create mode 100644 tests/components/pages/Profile.test.ts create mode 100644 tests/components/templates/Profile.test.ts diff --git a/src/lib/components/atoms/BlockOrReport.svelte b/src/lib/components/atoms/BlockOrReport.svelte index ac762c3..957588a 100644 --- a/src/lib/components/atoms/BlockOrReport.svelte +++ b/src/lib/components/atoms/BlockOrReport.svelte @@ -1,3 +1,12 @@ - -or - + + +{@html $_('page.profile.activities.block_or_report', { + values: { + blockElementOpen: '', + reportElementOpen: '' + } +})} diff --git a/src/lib/components/atoms/DisplayName.svelte b/src/lib/components/atoms/DisplayName.svelte index 7f344b4..0ec3627 100644 --- a/src/lib/components/atoms/DisplayName.svelte +++ b/src/lib/components/atoms/DisplayName.svelte @@ -1,4 +1,6 @@

- Profile for + + {$_('page.profile.heading')} {@html displayName}

({@html pronoun})

diff --git a/src/lib/components/pages/Profile.svelte b/src/lib/components/pages/Profile.svelte new file mode 100644 index 0000000..312983e --- /dev/null +++ b/src/lib/components/pages/Profile.svelte @@ -0,0 +1,10 @@ + + + diff --git a/src/lib/components/templates/Profile.d.ts b/src/lib/components/templates/Profile.d.ts new file mode 100644 index 0000000..445e0e2 --- /dev/null +++ b/src/lib/components/templates/Profile.d.ts @@ -0,0 +1,5 @@ +export type ProfileData = { + user: { + display_name: string; + }; +}; diff --git a/src/lib/components/templates/Profile.svelte b/src/lib/components/templates/Profile.svelte new file mode 100644 index 0000000..4cea224 --- /dev/null +++ b/src/lib/components/templates/Profile.svelte @@ -0,0 +1,105 @@ + + +
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ +
+ + {data.user.username}@{data.user.instance} + +
+ + +
+
+
+
+ +
+
+

+ {$_('page.profile.projects.heading')} +

+

+ {$_('page.profile.projects.empty')} + {@html $_('page.profile.projects.add_or_import', { + values: { + addElementOpen: '', + addElementClose: '', + importElementOpen: '', + importElementClose: '' + } + })} +

+
+
+ +
+
+

+ {$_('page.profile.history.heading')} +

+
    +
  • + + + + + + + {$date(new Date('2023-04-23'))} - {$_( + 'page.profile.history.activities.setup.summary' + )} + + + + + + {$_('page.profile.history.activities.setup.description', { + values: { + created_with: data.user.created_with, + instance: data.user.instance, + username: data.user.username + } + })} + + +
  • +
+
+
+
diff --git a/src/lib/i18n/locales/en.json b/src/lib/i18n/locales/en.json index ce2ce79..2a00138 100644 --- a/src/lib/i18n/locales/en.json +++ b/src/lib/i18n/locales/en.json @@ -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!" } } diff --git a/src/routes/profile/+page.svelte b/src/routes/profile/+page.svelte index 8b44570..84be240 100644 --- a/src/routes/profile/+page.svelte +++ b/src/routes/profile/+page.svelte @@ -1,77 +1,8 @@ -
- -
- -
- -
-
- - -
- -
- -
-
- -
- - {@html data.user.username}@{@html data.user.instance} - -
- - -
-
-
-
- -
-
-

Projects

-

- No projects added yet. - Add a project - or - import a project. -

-
-
- -
-
-

Activities

-
    -
  • - - - - ✴️ - Apr 23, 2023 - account set up - - - - - The F2 account @{@html data.user.username}@{@html data.user.instance} was successfully - set up within {@html data.user.created_with} - - -
  • -
-
-
-
+ diff --git a/tests/components/atoms/BlockOrReport.test.ts b/tests/components/atoms/BlockOrReport.test.ts index aa75d21..93a4a82 100644 --- a/tests/components/atoms/BlockOrReport.test.ts +++ b/tests/components/atoms/BlockOrReport.test.ts @@ -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(); }); }); diff --git a/tests/components/atoms/DisplayName.test.ts b/tests/components/atoms/DisplayName.test.ts index 10cf548..a943c5b 100644 --- a/tests/components/atoms/DisplayName.test.ts +++ b/tests/components/atoms/DisplayName.test.ts @@ -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(); diff --git a/tests/components/pages/ImportProject.test.ts b/tests/components/pages/ImportProject.test.ts index e84e678..a61a4f6 100644 --- a/tests/components/pages/ImportProject.test.ts +++ b/tests/components/pages/ImportProject.test.ts @@ -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); diff --git a/tests/components/pages/Profile.test.ts b/tests/components/pages/Profile.test.ts new file mode 100644 index 0000000..c87c932 --- /dev/null +++ b/tests/components/pages/Profile.test.ts @@ -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) + ) + ); + }); + }); +}); diff --git a/tests/components/templates/ImportProject.test.ts b/tests/components/templates/ImportProject.test.ts index 720e9f9..d525b58 100644 --- a/tests/components/templates/ImportProject.test.ts +++ b/tests/components/templates/ImportProject.test.ts @@ -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); diff --git a/tests/components/templates/Profile.test.ts b/tests/components/templates/Profile.test.ts new file mode 100644 index 0000000..4aa32c7 --- /dev/null +++ b/tests/components/templates/Profile.test.ts @@ -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) + ) + ); + }); + }); +});