Repo restructure.
This commit is contained in:
172
packages/declaform/tests/declaform.test.ts
Normal file
172
packages/declaform/tests/declaform.test.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { Declaform } from '../src';
|
||||
|
||||
const MOVIE_FORM_NO_SRC = `
|
||||
<decla-form id="form">
|
||||
<form slot="form">
|
||||
<div class="input-group">
|
||||
<label for="name">Name</label>
|
||||
<input id="name" name="name" />
|
||||
</div>
|
||||
<select id="genre" name="genre">
|
||||
<option value="comedy">Comedy</option>
|
||||
<option value="horror">Horror</option>
|
||||
</select>
|
||||
<fieldset>
|
||||
<legend>Rating</legend>
|
||||
<div class="input-group">
|
||||
<label for="rating-type-user">Type</label>
|
||||
<input id="rating-type-user" name="rating.type" type="radio" value="user" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="rating-type-critic">Type</label>
|
||||
<input id="rating-type-critic" name="rating.type" type="radio" value="critic" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="rating-score">Score</label>
|
||||
<input id="rating-score" name="rating.score" type="number" />
|
||||
</div>
|
||||
</fieldset>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</decla-form>
|
||||
`;
|
||||
|
||||
const MOVIE_FORM_HTTP = `
|
||||
<decla-form id="form" src="movie/jaws" action="movie/jaws" method="PUT">
|
||||
<form slot="form">
|
||||
<div class="input-group">
|
||||
<label for="name">Name</label>
|
||||
<input id="name" name="name" />
|
||||
</div>
|
||||
<select id="genre" name="genre">
|
||||
<option value="comedy">Comedy</option>
|
||||
<option value="horror">Horror</option>
|
||||
</select>
|
||||
<fieldset>
|
||||
<legend>Rating</legend>
|
||||
<div class="input-group">
|
||||
<label for="rating-type-user">Type</label>
|
||||
<input id="rating-type-user" name="rating.type" type="radio" value="user" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="rating-type-critic">Type</label>
|
||||
<input id="rating-type-critic" name="rating.type" type="radio" value="critic" />
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="rating-score">Score</label>
|
||||
<input id="rating-score" name="rating.score" type="number" />
|
||||
</div>
|
||||
</fieldset>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</decla-form>
|
||||
`;
|
||||
|
||||
describe('Declaform', () => {
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = '';
|
||||
})
|
||||
|
||||
it('Should mount.', () => {
|
||||
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||
expect(document.getElementById('form')).toBeTruthy();
|
||||
})
|
||||
|
||||
it('.toObject() should serialize form into a JS object', () => {
|
||||
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||
const form = document.getElementById('form') as Declaform;
|
||||
setInputValue('name', 'Monty Python');
|
||||
setInputValue('genre', 'comedy');
|
||||
setRadioValue('rating.type', 'user');
|
||||
setInputValue('rating-score', '5');
|
||||
const obj = form.toObject();
|
||||
expect(obj).toMatchObject({
|
||||
name: 'Monty Python',
|
||||
genre: 'comedy',
|
||||
rating: {
|
||||
score: 5,
|
||||
type: 'user',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('.hydrate() should populate input fields from a JS object', () => {
|
||||
document.body.innerHTML = MOVIE_FORM_NO_SRC;
|
||||
const form = document.getElementById('form') as Declaform;
|
||||
form.hydrate({
|
||||
name: 'Jaws',
|
||||
genre: 'horror',
|
||||
rating: {
|
||||
score: 5,
|
||||
type: 'critic',
|
||||
}
|
||||
});
|
||||
expect(getInputValue('name')).toBe('Jaws')
|
||||
expect(getInputValue('genre')).toBe('horror')
|
||||
expect(getInputValue('rating-score')).toBe('5');
|
||||
expect(document.getElementById('rating-type-critic')?.hasAttribute('checked')).toBe(true)
|
||||
});
|
||||
|
||||
it('Supplying "src" attribute should hydrate form with the supplied endpoint.', async () => {
|
||||
globalThis.fetch = jest.fn().mockResolvedValue({
|
||||
status: 200,
|
||||
ok: true,
|
||||
json: () => Promise.resolve({
|
||||
name: 'Jaws',
|
||||
genre: 'horror',
|
||||
rating: {
|
||||
score: 5,
|
||||
type: 'critic',
|
||||
}
|
||||
})
|
||||
})
|
||||
document.body.innerHTML = MOVIE_FORM_HTTP;
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 0))
|
||||
|
||||
expect(getInputValue('name')).toBe('Jaws')
|
||||
expect(getInputValue('genre')).toBe('horror')
|
||||
expect(getInputValue('rating-score')).toBe('5');
|
||||
expect(document.getElementById('rating-type-critic')?.hasAttribute('checked')).toBe(true)
|
||||
});
|
||||
});
|
||||
|
||||
function setInputValue(id: string, value: string) {
|
||||
const input = document.getElementById(id);
|
||||
if (!input) {
|
||||
throw new Error(`No input with id "${id}"!`);
|
||||
}
|
||||
if (!('value' in input)) {
|
||||
throw new Error(`Tag with id "${id}" does not have "value" attribute!`);
|
||||
}
|
||||
input.value = value;
|
||||
}
|
||||
|
||||
function getInputValue(id: string) {
|
||||
const input = document.getElementById(id);
|
||||
if (!input) {
|
||||
throw new Error(`No input with id "${id}"!`);
|
||||
}
|
||||
if (!('value' in input)) {
|
||||
throw new Error(`Tag with id "${id}" does not have "value" attribute!`);
|
||||
}
|
||||
return input.value;
|
||||
}
|
||||
|
||||
function setRadioValue(name: string, value: string) {
|
||||
const radios = document.querySelectorAll(`[name="${name}"]`);
|
||||
if (!radios) {
|
||||
throw new Error(`No radios with name "${name}"!`);
|
||||
}
|
||||
radios.forEach(radio => {
|
||||
if (!('value' in radio)) {
|
||||
throw new Error('Radio option does not have "value" attribute!');
|
||||
}
|
||||
radio.removeAttribute('checked');
|
||||
})
|
||||
const option = ([...radios] as HTMLInputElement[]).find(x => x.value);
|
||||
if (!option) {
|
||||
throw new Error(`No option with value "${value}"`);
|
||||
}
|
||||
option.setAttribute('checked', '');
|
||||
}
|
||||
Reference in New Issue
Block a user