mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-27 13:47:58 +01:00
Add tests for clientside image filtering
This commit is contained in:
parent
bbc1879a1e
commit
d0771c7216
2 changed files with 167 additions and 5 deletions
161
assets/js/__tests__/imagesclientside.spec.ts
Normal file
161
assets/js/__tests__/imagesclientside.spec.ts
Normal file
|
@ -0,0 +1,161 @@
|
|||
import { filterNode, initImagesClientside } from '../imagesclientside';
|
||||
import { parseSearch } from '../match_query';
|
||||
import { matchNone } from '../query/boolean';
|
||||
import { assertNotNull } from '../utils/assert';
|
||||
import { $ } from '../utils/dom';
|
||||
|
||||
describe('filterNode', () => {
|
||||
beforeEach(() => {
|
||||
window.booru.hiddenTagList = [];
|
||||
window.booru.spoileredTagList = [];
|
||||
window.booru.ignoredTagList = [];
|
||||
window.booru.imagesWithDownvotingDisabled = [];
|
||||
|
||||
window.booru.hiddenFilter = matchNone();
|
||||
window.booru.spoileredFilter = matchNone();
|
||||
});
|
||||
|
||||
function makeMediaContainer() {
|
||||
const element = document.createElement('div');
|
||||
element.innerHTML = `
|
||||
<div class="image-container" data-image-id="1" data-image-tags="[1]">
|
||||
<div class="js-spoiler-info-overlay"></div>
|
||||
<picture><img src=""/></picture>
|
||||
</div>
|
||||
`;
|
||||
return [ element, assertNotNull($<HTMLDivElement>('.js-spoiler-info-overlay', element)) ];
|
||||
}
|
||||
|
||||
it('should show image media boxes not matching any filter', () => {
|
||||
const [ container, spoilerOverlay ] = makeMediaContainer();
|
||||
|
||||
filterNode(container);
|
||||
expect(spoilerOverlay).not.toContainHTML('(Complex Filter)');
|
||||
expect(spoilerOverlay).not.toContainHTML('(unknown tag)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).not.toContain('1');
|
||||
});
|
||||
|
||||
it('should spoiler media boxes spoilered by a tag filter', () => {
|
||||
const [ container, spoilerOverlay ] = makeMediaContainer();
|
||||
window.booru.spoileredTagList = [1];
|
||||
|
||||
filterNode(container);
|
||||
expect(spoilerOverlay).toContainHTML('(unknown tag)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
it('should spoiler media boxes spoilered by a complex filter', () => {
|
||||
const [ container, spoilerOverlay ] = makeMediaContainer();
|
||||
window.booru.spoileredFilter = parseSearch('id:1');
|
||||
|
||||
filterNode(container);
|
||||
expect(spoilerOverlay).toContainHTML('(Complex Filter)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
it('should hide media boxes hidden by a tag filter', () => {
|
||||
const [ container, spoilerOverlay ] = makeMediaContainer();
|
||||
window.booru.hiddenTagList = [1];
|
||||
|
||||
filterNode(container);
|
||||
expect(spoilerOverlay).toContainHTML('[HIDDEN]');
|
||||
expect(spoilerOverlay).toContainHTML('(unknown tag)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
it('should hide media boxes hidden by a complex filter', () => {
|
||||
const [ container, spoilerOverlay ] = makeMediaContainer();
|
||||
window.booru.hiddenFilter = parseSearch('id:1');
|
||||
|
||||
filterNode(container);
|
||||
expect(spoilerOverlay).toContainHTML('[HIDDEN]');
|
||||
expect(spoilerOverlay).toContainHTML('(Complex Filter)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
function makeImageBlock(): HTMLElement[] {
|
||||
const element = document.createElement('div');
|
||||
element.innerHTML = `
|
||||
<div class="image-show-container" data-image-id="1" data-image-tags="[1]">
|
||||
<div class="image-filtered hidden">
|
||||
<img src=""/>
|
||||
<span class="filter-explanation"></span>
|
||||
</div>
|
||||
<div class="image-show hidden">
|
||||
<picture><img src=""/></picture>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
return [
|
||||
element,
|
||||
assertNotNull($<HTMLDivElement>('.image-filtered', element)),
|
||||
assertNotNull($<HTMLDivElement>('.image-show', element)),
|
||||
assertNotNull($<HTMLSpanElement>('.filter-explanation', element))
|
||||
];
|
||||
}
|
||||
|
||||
it('should show image blocks not matching any filter', () => {
|
||||
const [ container, imageFiltered, imageShow ] = makeImageBlock();
|
||||
|
||||
filterNode(container);
|
||||
expect(imageFiltered).toHaveClass('hidden');
|
||||
expect(imageShow).not.toHaveClass('hidden');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).not.toContain('1');
|
||||
});
|
||||
|
||||
it('should spoiler image blocks spoilered by a tag filter', () => {
|
||||
const [ container, imageFiltered, imageShow, filterExplanation ] = makeImageBlock();
|
||||
window.booru.spoileredTagList = [1];
|
||||
|
||||
filterNode(container);
|
||||
expect(imageFiltered).not.toHaveClass('hidden');
|
||||
expect(imageShow).toHaveClass('hidden');
|
||||
expect(filterExplanation).toContainHTML('spoilered by');
|
||||
expect(filterExplanation).toContainHTML('(unknown tag)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
it('should spoiler image blocks spoilered by a complex filter', () => {
|
||||
const [ container, imageFiltered, imageShow, filterExplanation ] = makeImageBlock();
|
||||
window.booru.spoileredFilter = parseSearch('id:1');
|
||||
|
||||
filterNode(container);
|
||||
expect(imageFiltered).not.toHaveClass('hidden');
|
||||
expect(imageShow).toHaveClass('hidden');
|
||||
expect(filterExplanation).toContainHTML('spoilered by');
|
||||
expect(filterExplanation).toContainHTML('complex tag expression');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
it('should hide image blocks hidden by a tag filter', () => {
|
||||
const [ container, imageFiltered, imageShow, filterExplanation ] = makeImageBlock();
|
||||
window.booru.hiddenTagList = [1];
|
||||
|
||||
filterNode(container);
|
||||
expect(imageFiltered).not.toHaveClass('hidden');
|
||||
expect(imageShow).toHaveClass('hidden');
|
||||
expect(filterExplanation).toContainHTML('hidden by');
|
||||
expect(filterExplanation).toContainHTML('(unknown tag)');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
it('should hide image blocks hidden by a complex filter', () => {
|
||||
const [ container, imageFiltered, imageShow, filterExplanation ] = makeImageBlock();
|
||||
window.booru.hiddenFilter = parseSearch('id:1');
|
||||
|
||||
filterNode(container);
|
||||
expect(imageFiltered).not.toHaveClass('hidden');
|
||||
expect(imageShow).toHaveClass('hidden');
|
||||
expect(filterExplanation).toContainHTML('hidden by');
|
||||
expect(filterExplanation).toContainHTML('complex tag expression');
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toContain('1');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('initImagesClientside', () => {
|
||||
it('should initialize the imagesWithDownvotingDisabled array', () => {
|
||||
initImagesClientside();
|
||||
expect(window.booru.imagesWithDownvotingDisabled).toEqual([]);
|
||||
});
|
||||
});
|
|
@ -2,6 +2,7 @@
|
|||
* Client-side image filtering/spoilering.
|
||||
*/
|
||||
|
||||
import { assertNotUndefined } from './utils/assert';
|
||||
import { $$, escapeHtml } from './utils/dom';
|
||||
import { setupInteractions } from './interactions';
|
||||
import { showThumb, showBlock, spoilerThumb, spoilerBlock, hideThumb } from './utils/image';
|
||||
|
@ -15,20 +16,20 @@ function run(
|
|||
img: HTMLDivElement,
|
||||
tags: TagData[],
|
||||
complex: AstMatcher,
|
||||
callback: RunCallback,
|
||||
runCallback: RunCallback
|
||||
): boolean {
|
||||
const hit = (() => {
|
||||
// Check tags array first to provide more precise filter explanations
|
||||
const hitTags = imageHitsTags(img, tags);
|
||||
if (hitTags.length !== 0) {
|
||||
callback(img, hitTags, 'tags');
|
||||
runCallback(img, hitTags, 'tags');
|
||||
return true;
|
||||
}
|
||||
|
||||
// No tags matched, try complex filter AST
|
||||
const hitComplex = imageHitsComplex(img, complex);
|
||||
if (hitComplex) {
|
||||
callback(img, hitTags, 'complex');
|
||||
runCallback(img, hitTags, 'complex');
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -36,9 +37,9 @@ function run(
|
|||
return false;
|
||||
})();
|
||||
|
||||
if (hit && img.dataset.imageId) {
|
||||
if (hit) {
|
||||
// Disallow negative interaction on image which is not visible
|
||||
window.booru.imagesWithDownvotingDisabled.push(img.dataset.imageId);
|
||||
window.booru.imagesWithDownvotingDisabled.push(assertNotUndefined(img.dataset.imageId));
|
||||
}
|
||||
|
||||
return hit;
|
||||
|
|
Loading…
Reference in a new issue