-
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master'
- Loading branch information
Showing
15 changed files
with
500 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { $ } from '../utils/dom'; | ||
import { assertNotNull } from '../utils/assert'; | ||
import { setupSearch } from '../search'; | ||
import { setupTagListener } from '../tagsinput'; | ||
|
||
const formData = `<form class="js-search-form"> | ||
<input type="text" class="js-search-field"> | ||
<a data-search-prepend="-">NOT</a> | ||
<a data-search-add="id.lte:10" data-search-select-last="2" data-search-show-help="numeric">Numeric ID</a> | ||
<a data-search-add="my:faves" data-search-show-help=" ">My favorites</a> | ||
<div class="hidden" data-search-help="boolean"> | ||
<span class="js-search-help-subject"></span> is a Boolean value field | ||
</div> | ||
<div class="hidden" data-search-help="numeric"> | ||
<span class="js-search-help-subject"></span> is a numerical range field | ||
</div> | ||
</form>`; | ||
|
||
describe('Search form help', () => { | ||
beforeAll(() => { | ||
setupSearch(); | ||
setupTagListener(); | ||
}); | ||
|
||
let input: HTMLInputElement; | ||
let prependAnchor: HTMLAnchorElement; | ||
let idAnchor: HTMLAnchorElement; | ||
let favesAnchor: HTMLAnchorElement; | ||
let helpNumeric: HTMLDivElement; | ||
let subjectSpan: HTMLElement; | ||
|
||
beforeEach(() => { | ||
document.body.innerHTML = formData; | ||
|
||
input = assertNotNull($<HTMLInputElement>('input')); | ||
prependAnchor = assertNotNull($<HTMLAnchorElement>('a[data-search-prepend]')); | ||
idAnchor = assertNotNull($<HTMLAnchorElement>('a[data-search-add="id.lte:10"]')); | ||
favesAnchor = assertNotNull($<HTMLAnchorElement>('a[data-search-add="my:faves"]')); | ||
helpNumeric = assertNotNull($<HTMLDivElement>('[data-search-help="numeric"]')); | ||
subjectSpan = assertNotNull($<HTMLSpanElement>('span', helpNumeric)); | ||
}); | ||
|
||
it('should add text to input field', () => { | ||
idAnchor.click(); | ||
expect(input.value).toBe('id.lte:10'); | ||
|
||
favesAnchor.click(); | ||
expect(input.value).toBe('id.lte:10, my:faves'); | ||
}); | ||
|
||
it('should focus and select text in input field when requested', () => { | ||
idAnchor.click(); | ||
expect(input).toHaveFocus(); | ||
expect(input.selectionStart).toBe(7); | ||
expect(input.selectionEnd).toBe(9); | ||
}); | ||
|
||
it('should highlight subject name when requested', () => { | ||
expect(helpNumeric).toHaveClass('hidden'); | ||
idAnchor.click(); | ||
expect(helpNumeric).not.toHaveClass('hidden'); | ||
expect(subjectSpan).toHaveTextContent('Numeric ID'); | ||
}); | ||
|
||
it('should not focus and select text in input field when unavailable', () => { | ||
favesAnchor.click(); | ||
expect(input).not.toHaveFocus(); | ||
expect(input.selectionStart).toBe(8); | ||
expect(input.selectionEnd).toBe(8); | ||
}); | ||
|
||
it('should not highlight subject name when unavailable', () => { | ||
favesAnchor.click(); | ||
expect(helpNumeric).toHaveClass('hidden'); | ||
}); | ||
|
||
it('should prepend to empty input', () => { | ||
prependAnchor.click(); | ||
expect(input.value).toBe('-'); | ||
}); | ||
|
||
it('should prepend to single input', () => { | ||
input.value = 'a'; | ||
prependAnchor.click(); | ||
expect(input.value).toBe('-a'); | ||
}); | ||
|
||
it('should prepend to comma-separated input', () => { | ||
input.value = 'a,b'; | ||
prependAnchor.click(); | ||
expect(input.value).toBe('a,-b'); | ||
}); | ||
|
||
it('should prepend to comma and space-separated input', () => { | ||
input.value = 'a, b'; | ||
prependAnchor.click(); | ||
expect(input.value).toBe('a, -b'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
import { $, $$, hideEl } from '../utils/dom'; | ||
import { assertNotNull } from '../utils/assert'; | ||
import { TermSuggestion } from '../utils/suggestions'; | ||
import { setupTagsInput, addTag, reloadTagsInput } from '../tagsinput'; | ||
|
||
const formData = `<form class="tags-form"> | ||
<div class="js-tag-block fancy-tag-upload"> | ||
<textarea class="js-taginput js-taginput-plain"></textarea> | ||
<div class="js-taginput js-taginput-fancy"> | ||
<input type="text" class="js-taginput-input" placeholder="add a tag"> | ||
</div> | ||
</div> | ||
<button class="js-taginput-show">Fancy Editor</button> | ||
<button class="js-taginput-hide hidden">Plain Editor</button> | ||
<input type="submit" value="Save Tags"> | ||
</form>`; | ||
|
||
describe('Fancy tags input', () => { | ||
let form: HTMLFormElement; | ||
let tagBlock: HTMLDivElement; | ||
let plainInput: HTMLTextAreaElement; | ||
let fancyInput: HTMLDivElement; | ||
let fancyText: HTMLInputElement; | ||
let fancyShowButton: HTMLButtonElement; | ||
let plainShowButton: HTMLButtonElement; | ||
|
||
beforeEach(() => { | ||
window.booru.fancyTagUpload = true; | ||
window.booru.fancyTagEdit = true; | ||
document.body.innerHTML = formData; | ||
|
||
form = assertNotNull($<HTMLFormElement>('.tags-form')); | ||
tagBlock = assertNotNull($<HTMLDivElement>('.js-tag-block')); | ||
plainInput = assertNotNull($<HTMLTextAreaElement>('.js-taginput-plain')); | ||
fancyInput = assertNotNull($<HTMLDivElement>('.js-taginput-fancy')); | ||
fancyText = assertNotNull($<HTMLInputElement>('.js-taginput-input')); | ||
fancyShowButton = assertNotNull($<HTMLButtonElement>('.js-taginput-show')); | ||
plainShowButton = assertNotNull($<HTMLButtonElement>('.js-taginput-hide')); | ||
|
||
// prevent these from submitting the form | ||
fancyShowButton.addEventListener('click', e => e.preventDefault()); | ||
plainShowButton.addEventListener('click', e => e.preventDefault()); | ||
}); | ||
|
||
for (let i = 0; i < 4; i++) { | ||
const type = (i & 2) === 0 ? 'upload' : 'edit'; | ||
const name = (i & 2) === 0 ? 'fancyTagUpload' : 'fancyTagEdit'; | ||
const value = (i & 1) === 0; | ||
|
||
// eslint-disable-next-line no-loop-func | ||
it(`should imply ${name}:${value} <-> ${type}:${value} on setup`, () => { | ||
window.booru.fancyTagEdit = false; | ||
window.booru.fancyTagUpload = false; | ||
window.booru[name] = value; | ||
|
||
plainInput.value = 'a, b'; | ||
tagBlock.classList.remove('fancy-tag-edit', 'fancy-tag-upload'); | ||
tagBlock.classList.add(`fancy-tag-${type}`); | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
|
||
setupTagsInput(tagBlock); | ||
expect($$('span.tag', fancyInput)).toHaveLength(value ? 2 : 0); | ||
}); | ||
} | ||
|
||
it('should move tags from the plain to the fancy editor when the fancy editor is shown', () => { | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
|
||
setupTagsInput(tagBlock); | ||
plainInput.value = 'a, b'; | ||
fancyShowButton.click(); | ||
expect($$('span.tag', fancyInput)).toHaveLength(2); | ||
}); | ||
|
||
it('should move tags from the plain to the fancy editor on reload event', () => { | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
|
||
setupTagsInput(tagBlock); | ||
plainInput.value = 'a, b'; | ||
reloadTagsInput(plainInput); | ||
expect($$('span.tag', fancyInput)).toHaveLength(2); | ||
}); | ||
|
||
it('should respond to addtag events', () => { | ||
setupTagsInput(tagBlock); | ||
addTag(plainInput, 'a'); | ||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
}); | ||
|
||
it('should not respond to addtag events if the container is hidden', () => { | ||
setupTagsInput(tagBlock); | ||
hideEl(fancyInput); | ||
addTag(plainInput, 'a'); | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
}); | ||
|
||
it('should respond to autocomplete events', () => { | ||
setupTagsInput(tagBlock); | ||
fancyText.dispatchEvent(new CustomEvent<TermSuggestion>('autocomplete', { detail: { value: 'a', label: 'a' } })); | ||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
}); | ||
|
||
it('should allow removing previously added tags by clicking them', () => { | ||
setupTagsInput(tagBlock); | ||
addTag(plainInput, 'a'); | ||
assertNotNull($<HTMLAnchorElement>('span.tag a', fancyInput)).click(); | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
}); | ||
|
||
it('should allow removing previously added tags by adding one with a minus sign prepended', () => { | ||
setupTagsInput(tagBlock); | ||
addTag(plainInput, 'a'); | ||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
addTag(plainInput, '-a'); | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
}); | ||
|
||
it('should disallow adding empty tags', () => { | ||
setupTagsInput(tagBlock); | ||
addTag(plainInput, ''); | ||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
}); | ||
|
||
it('should disallow adding existing tags', () => { | ||
setupTagsInput(tagBlock); | ||
addTag(plainInput, 'a'); | ||
addTag(plainInput, 'a'); | ||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
}); | ||
|
||
it('should submit the form on ctrl+enter', () => { | ||
setupTagsInput(tagBlock); | ||
|
||
const ev = new KeyboardEvent('keydown', { keyCode: 13, ctrlKey: true, bubbles: true }); | ||
|
||
return new Promise<void>(resolve => { | ||
form.addEventListener('submit', e => { | ||
e.preventDefault(); | ||
resolve(); | ||
}); | ||
|
||
fancyText.dispatchEvent(ev); | ||
expect(ev.defaultPrevented).toBe(true); | ||
}); | ||
}); | ||
|
||
it('does nothing when backspacing on empty input and there are no tags', () => { | ||
setupTagsInput(tagBlock); | ||
|
||
const ev = new KeyboardEvent('keydown', { keyCode: 8, bubbles: true }); | ||
fancyText.dispatchEvent(ev); | ||
|
||
expect($$('span.tag', fancyInput)).toHaveLength(0); | ||
}); | ||
|
||
it('erases the last added tag when backspacing on empty input', () => { | ||
setupTagsInput(tagBlock); | ||
addTag(plainInput, 'a'); | ||
addTag(plainInput, 'b'); | ||
|
||
const ev = new KeyboardEvent('keydown', { keyCode: 8, bubbles: true }); | ||
fancyText.dispatchEvent(ev); | ||
|
||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
}); | ||
|
||
it('adds new tag when comma is pressed', () => { | ||
setupTagsInput(tagBlock); | ||
|
||
const ev = new KeyboardEvent('keydown', { keyCode: 188, bubbles: true }); | ||
fancyText.value = 'a'; | ||
fancyText.dispatchEvent(ev); | ||
|
||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
expect(fancyText.value).toBe(''); | ||
}); | ||
|
||
it('adds new tag when enter is pressed', () => { | ||
setupTagsInput(tagBlock); | ||
|
||
const ev = new KeyboardEvent('keydown', { keyCode: 13, bubbles: true }); | ||
fancyText.value = 'a'; | ||
fancyText.dispatchEvent(ev); | ||
|
||
expect($$('span.tag', fancyInput)).toHaveLength(1); | ||
expect(fancyText.value).toBe(''); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.