feat: import projects form
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
parent
fecd15f862
commit
34be485a49
12 changed files with 791 additions and 8 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "anvil",
|
"name": "anvil",
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "anvil",
|
"name": "anvil",
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "1.41.2",
|
"@playwright/test": "1.41.2",
|
||||||
"@skeletonlabs/skeleton": "2.8.0",
|
"@skeletonlabs/skeleton": "2.8.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "anvil",
|
"name": "anvil",
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en" class="dark">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
|
|
10
src/lib/components/pages/ImportProject.svelte
Normal file
10
src/lib/components/pages/ImportProject.svelte
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import ImportProjectTemplate from '../templates/ImportProject.svelte';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data populated by SvelteKit
|
||||||
|
*/
|
||||||
|
export let data: unknown = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ImportProjectTemplate {data} />
|
119
src/lib/components/templates/ImportProject.svelte
Normal file
119
src/lib/components/templates/ImportProject.svelte
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { AlertFill16, Info16, Repo24, Upload16 } from 'svelte-octicons';
|
||||||
|
import { _ } from 'svelte-i18n';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required context for populating the template.
|
||||||
|
*/
|
||||||
|
export const data: unknown = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="w-full">
|
||||||
|
<form
|
||||||
|
class="w-96 flex flex-col gap-6 mx-auto px-8 py-8 bg-surface-100 border border-surface-300"
|
||||||
|
name="import-project"
|
||||||
|
>
|
||||||
|
<h2 class="h2 text-surface-500">{$_('page.import_project.heading')}</h2>
|
||||||
|
<p class="text-surface-500">{$_('page.import_project.intro')}</p>
|
||||||
|
<div class="flex flex-col gap-1">
|
||||||
|
<h3 class="text-surface-500">
|
||||||
|
<label class="label" for="project-name">
|
||||||
|
{$_('page.import_project.form.fields.name.label')}
|
||||||
|
<span class="required">*</span>
|
||||||
|
</label>
|
||||||
|
</h3>
|
||||||
|
<input
|
||||||
|
id="project-name"
|
||||||
|
name="project-name"
|
||||||
|
class="input input-error"
|
||||||
|
type="text"
|
||||||
|
placeholder={$_('page.import_project.form.fields.name.placeholder')}
|
||||||
|
/>
|
||||||
|
<div class="flex gap-2 items-center text-error-500">
|
||||||
|
<AlertFill16 fill="currentColor" />
|
||||||
|
{$_('page.import_project.form.fields.name.error')}
|
||||||
|
</div>
|
||||||
|
<div class="text-surface-400">
|
||||||
|
domain.example/projects/<span class="text-surface-500">NameUpdateRealtime</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 class="text-surface-500">
|
||||||
|
<label class="label" for="project-description">
|
||||||
|
{$_('page.import_project.form.fields.description.label')}
|
||||||
|
</label>
|
||||||
|
</h3>
|
||||||
|
<textarea
|
||||||
|
id="project-description"
|
||||||
|
name="project-description"
|
||||||
|
class="textarea"
|
||||||
|
placeholder={$_('page.import_project.form.fields.description.placeholder')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 class="text-surface-500">{$_('page.import_project.form.avatar')}</h3>
|
||||||
|
<div class="flex">
|
||||||
|
<span class="bg-surface-300 flex justify-center items-center h-12 w-12">
|
||||||
|
<Repo24 class="h-6 w-6" />
|
||||||
|
</span>
|
||||||
|
<label
|
||||||
|
for="project-avatar"
|
||||||
|
class="h-12 flex flex-1 gap-2 items-center justify-center px-4 bg-surface-025 text-surface-400"
|
||||||
|
>
|
||||||
|
<Upload16 fill="currentColor" />
|
||||||
|
{$_('page.import_project.form.fields.avatar.label')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="project-avatar"
|
||||||
|
name="project-avatar"
|
||||||
|
class="opacity-0 w-1"
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<h3 class="text-surface-500">
|
||||||
|
{$_('page.import_project.form.components')}
|
||||||
|
</h3>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
id="project-repository"
|
||||||
|
name="project-repository"
|
||||||
|
class="input h-6 w-6"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<label for="project-repository" class="label inline text-surface-500">
|
||||||
|
{$_('page.import_project.form.fields.repository.label')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="url"
|
||||||
|
class="input ml-8 w-auto"
|
||||||
|
placeholder={$_('page.import_project.form.fields.repository.placeholder')}
|
||||||
|
/>
|
||||||
|
<div class="flex gap-1 items-center ml-8 text-warning-700">
|
||||||
|
<Info16 fill="currentColor" />
|
||||||
|
{$_('page.import_project.form.fields.repository.hint')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input id="project-issues" name="project-issues" class="input h-6 w-6" type="checkbox" />
|
||||||
|
<label for="project-issues" class="label inline text-surface-500">
|
||||||
|
{$_('page.import_project.form.fields.issues.label')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input id="project-pr" name="project-pr" class="input h-6 w-6" type="checkbox" />
|
||||||
|
<label for="project-pr" class="label inline text-surface-500">
|
||||||
|
{$_('page.import_project.form.fields.pr.label')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button bg-success-600 text-white h-12">
|
||||||
|
{$_('page.import_project.form.submit')}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
|
@ -1,5 +1,39 @@
|
||||||
{
|
{
|
||||||
"page": {
|
"page": {
|
||||||
|
"import_project": {
|
||||||
|
"form": {
|
||||||
|
"avatar": "Avatar",
|
||||||
|
"components": "Components",
|
||||||
|
"fields": {
|
||||||
|
"avatar": {
|
||||||
|
"label": "Upload image"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"label": "Description",
|
||||||
|
"placeholder": "Describe the project in less than 100 characters…"
|
||||||
|
},
|
||||||
|
"issues": {
|
||||||
|
"label": "Issues"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"error": "This field is required",
|
||||||
|
"label": "Name",
|
||||||
|
"placeholder": "Name of the project…"
|
||||||
|
},
|
||||||
|
"pr": {
|
||||||
|
"label": "Pull Requests"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"hint": "optional: import from git repo",
|
||||||
|
"label": "Repository",
|
||||||
|
"placeholder": "url of git repository…"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"submit": "Create project"
|
||||||
|
},
|
||||||
|
"heading": "Create project",
|
||||||
|
"intro": "Add a new F2 project to Anvil."
|
||||||
|
},
|
||||||
"welcome": "Welcome to Anvil!"
|
"welcome": "Welcome to Anvil!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
No projects added yet.
|
No projects added yet.
|
||||||
<a class="anchor" href="#">Add a project</a>
|
<a class="anchor" href="#">Add a project</a>
|
||||||
or
|
or
|
||||||
<a class="anchor" href="#">import a project</a>.
|
<a class="anchor" href="/projects/import/">import a project</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
4
src/routes/projects/import/+page.server.js
Normal file
4
src/routes/projects/import/+page.server.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/** @type {import('./$types').PageServerLoad} */
|
||||||
|
export async function load({ params }) {
|
||||||
|
return {};
|
||||||
|
}
|
8
src/routes/projects/import/+page.svelte
Normal file
8
src/routes/projects/import/+page.svelte
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<script>
|
||||||
|
import ImportProject from '$lib/components/pages/ImportProject.svelte';
|
||||||
|
|
||||||
|
/** @type {import('./types').PageData} */
|
||||||
|
export let data;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ImportProject {data} />
|
304
tests/components/pages/ImportProject.test.ts
Normal file
304
tests/components/pages/ImportProject.test.ts
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
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 enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||||
|
|
||||||
|
describe('ImportProject.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
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const { container } = render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(container).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a form', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByRole('form')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a h2', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
const h2 = screen.getByRole('heading', { level: 2 });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(h2).toBeInTheDocument();
|
||||||
|
expect(h2).toHaveTextContent(enMessages.page.import_project.heading);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an intro text', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.page.import_project.intro)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('name', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the asterisk
|
||||||
|
const name = screen.getByLabelText(
|
||||||
|
new RegExp(enMessages.page.import_project.form.fields.name.label)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(name).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a text input', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
const name = screen.getByPlaceholderText(
|
||||||
|
enMessages.page.import_project.form.fields.name.placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(name).toBeInTheDocument();
|
||||||
|
expect(name).toHaveAttribute('type', 'text');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when empty', () => {
|
||||||
|
it('should display an error', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(
|
||||||
|
screen.getByText(enMessages.page.import_project.form.fields.name.error)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// FIXME: Enable once the dev server is running
|
||||||
|
describe.skip('when filled', () => {
|
||||||
|
it('should hide the error', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(
|
||||||
|
screen.getByText(enMessages.page.import_project.form.fields.name.error)
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show a live updating hint', () => {
|
||||||
|
// Arrange
|
||||||
|
const value = 'Vervis';
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject, { value });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(`domain.example/projects/${value}`)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('description', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
const description = screen.getByLabelText(
|
||||||
|
enMessages.page.import_project.form.fields.description.label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(description).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a textarea', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
const description = screen.getByPlaceholderText(
|
||||||
|
enMessages.page.import_project.form.fields.description.placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(description).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('avatar', () => {
|
||||||
|
it('should have a heading', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const repository = screen.getByLabelText(
|
||||||
|
enMessages.page.import_project.form.fields.repository.label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(repository).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an URL input', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const repository = screen.getByPlaceholderText(
|
||||||
|
enMessages.page.import_project.form.fields.repository.placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(repository).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a hint', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const repository = screen.getByText(
|
||||||
|
enMessages.page.import_project.form.fields.repository.hint
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(repository).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('issues', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const issues = screen.getByLabelText(
|
||||||
|
enMessages.page.import_project.form.fields.issues.label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(issues).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('pull requests', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const issues = screen.getByLabelText(enMessages.page.import_project.form.fields.pr.label);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(issues).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
304
tests/components/templates/ImportProject.test.ts
Normal file
304
tests/components/templates/ImportProject.test.ts
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
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 enMessages from '../../../src/lib/i18n/locales/en.json';
|
||||||
|
|
||||||
|
describe('ImportProject.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
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const { container } = render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(container).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a form', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByRole('form')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a h2', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
const h2 = screen.getByRole('heading', { level: 2 });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(h2).toBeInTheDocument();
|
||||||
|
expect(h2).toHaveTextContent(enMessages.page.import_project.heading);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an intro text', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(enMessages.page.import_project.intro)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('name', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the asterisk
|
||||||
|
const name = screen.getByLabelText(
|
||||||
|
new RegExp(enMessages.page.import_project.form.fields.name.label)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(name).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a text input', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
const name = screen.getByPlaceholderText(
|
||||||
|
enMessages.page.import_project.form.fields.name.placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(name).toBeInTheDocument();
|
||||||
|
expect(name).toHaveAttribute('type', 'text');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when empty', () => {
|
||||||
|
it('should display an error', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(
|
||||||
|
screen.getByText(enMessages.page.import_project.form.fields.name.error)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// FIXME: Enable once the dev server is running
|
||||||
|
describe.skip('when filled', () => {
|
||||||
|
it('should hide the error', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(
|
||||||
|
screen.getByText(enMessages.page.import_project.form.fields.name.error)
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show a live updating hint', () => {
|
||||||
|
// Arrange
|
||||||
|
const value = 'Vervis';
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject, { value });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(screen.getByText(`domain.example/projects/${value}`)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('description', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
const description = screen.getByLabelText(
|
||||||
|
enMessages.page.import_project.form.fields.description.label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(description).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a textarea', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
const description = screen.getByPlaceholderText(
|
||||||
|
enMessages.page.import_project.form.fields.description.placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(description).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('avatar', () => {
|
||||||
|
it('should have a heading', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const repository = screen.getByLabelText(
|
||||||
|
enMessages.page.import_project.form.fields.repository.label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(repository).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have an URL input', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const repository = screen.getByPlaceholderText(
|
||||||
|
enMessages.page.import_project.form.fields.repository.placeholder
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(repository).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a hint', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const repository = screen.getByText(
|
||||||
|
enMessages.page.import_project.form.fields.repository.hint
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(repository).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('issues', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const issues = screen.getByLabelText(
|
||||||
|
enMessages.page.import_project.form.fields.issues.label
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(issues).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('pull requests', () => {
|
||||||
|
it('should have a label', () => {
|
||||||
|
// Arrange
|
||||||
|
// Nothing to prepare
|
||||||
|
|
||||||
|
// Act
|
||||||
|
render(ImportProject);
|
||||||
|
|
||||||
|
// Turn into regular expression to account for the icon
|
||||||
|
const issues = screen.getByLabelText(enMessages.page.import_project.form.fields.pr.label);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(issues).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue