mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-03-25 13:01:31 +01:00
Add integration tests for server-side completions cancellation with Escape
This commit is contained in:
parent
96d32d863d
commit
57781a1aa0
4 changed files with 95 additions and 55 deletions
|
@ -6,7 +6,7 @@ import { fireEvent } from '@testing-library/dom';
|
||||||
import { assertNotNull } from '../../utils/assert';
|
import { assertNotNull } from '../../utils/assert';
|
||||||
import { TextInputElement } from '../input';
|
import { TextInputElement } from '../input';
|
||||||
import store from '../../utils/store';
|
import store from '../../utils/store';
|
||||||
import { GetTagSuggestionsResponse } from 'autocomplete/client';
|
import { GetTagSuggestionsResponse, TagSuggestion } from 'autocomplete/client';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reusable test environment for autocompletion tests. Note that it does no
|
* A reusable test environment for autocompletion tests. Note that it does no
|
||||||
|
@ -44,27 +44,30 @@ export class TestContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
if (url.searchParams.get('term')?.toLowerCase() !== 'mar') {
|
const term = url.searchParams.get('term');
|
||||||
const suggestions: GetTagSuggestionsResponse = { suggestions: [] };
|
|
||||||
return JSON.stringify(suggestions);
|
const termLower = assertNotNull(term).toLowerCase();
|
||||||
}
|
|
||||||
|
const fakeSuggestions: TagSuggestion[] = [
|
||||||
|
{
|
||||||
|
alias: 'marvelous',
|
||||||
|
canonical: 'beautiful',
|
||||||
|
images: 30,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
canonical: 'mare',
|
||||||
|
images: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
canonical: 'market',
|
||||||
|
images: 10,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const suggestions: GetTagSuggestionsResponse = {
|
const suggestions: GetTagSuggestionsResponse = {
|
||||||
suggestions: [
|
suggestions: fakeSuggestions.filter(suggestion =>
|
||||||
{
|
(suggestion.alias || suggestion.canonical).startsWith(termLower),
|
||||||
alias: 'marvelous',
|
),
|
||||||
canonical: 'beautiful',
|
|
||||||
images: 30,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
canonical: 'mare',
|
|
||||||
images: 20,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
canonical: 'market',
|
|
||||||
images: 10,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return JSON.stringify(suggestions);
|
return JSON.stringify(suggestions);
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import { init } from './context';
|
|
||||||
|
|
||||||
it('ignores the autocompletion results if Escape was pressed', async () => {
|
|
||||||
const ctx = await init();
|
|
||||||
|
|
||||||
await Promise.all([ctx.setInput('mar'), ctx.keyDown('Escape')]);
|
|
||||||
|
|
||||||
// The input must be empty because the user typed `mar` and pressed `Escape` right after that
|
|
||||||
ctx.expectUi().toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"input": "mar<>",
|
|
||||||
"suggestions": [],
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
// First request for the local autocomplete index.
|
|
||||||
expect(fetch).toHaveBeenCalledTimes(1);
|
|
||||||
|
|
||||||
await ctx.setInput('mar');
|
|
||||||
|
|
||||||
ctx.expectUi().toMatchInlineSnapshot(`
|
|
||||||
{
|
|
||||||
"input": "mar<>",
|
|
||||||
"suggestions": [
|
|
||||||
"marvelous → beautiful 30",
|
|
||||||
"mare 20",
|
|
||||||
"market 10",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Second request for the server-side suggestions.
|
|
||||||
expect(fetch).toHaveBeenCalledTimes(2);
|
|
||||||
});
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { init } from '../context';
|
||||||
|
|
||||||
|
it('ignores the autocompletion results if Escape was pressed', async () => {
|
||||||
|
const ctx = await init();
|
||||||
|
|
||||||
|
// First request for the local autocomplete index was done
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await Promise.all([ctx.setInput('mar'), ctx.keyDown('Escape')]);
|
||||||
|
|
||||||
|
// The input must be empty because the user typed `mar` and pressed `Escape` right after that
|
||||||
|
ctx.expectUi().toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"input": "mar<>",
|
||||||
|
"suggestions": [],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
// No new requests must've been sent because the input was debounced early
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await ctx.setInput('mar');
|
||||||
|
|
||||||
|
ctx.expectUi().toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"input": "mar<>",
|
||||||
|
"suggestions": [
|
||||||
|
"marvelous → beautiful 30",
|
||||||
|
"mare 20",
|
||||||
|
"market 10",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Second request for the server-side suggestions.
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
ctx.setInput('mare');
|
||||||
|
|
||||||
|
// After 300 milliseconds the debounce threshold is over, and the server-side
|
||||||
|
// completions request is issued.
|
||||||
|
vi.advanceTimersByTime(300);
|
||||||
|
|
||||||
|
await ctx.keyDown('Escape');
|
||||||
|
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
|
ctx.expectUi().toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"input": "mare<>",
|
||||||
|
"suggestions": [],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
ctx.setInput('mare');
|
||||||
|
|
||||||
|
// Make sure that the user gets the results immediately without any debouncing (0 ms)
|
||||||
|
await vi.advanceTimersByTimeAsync(0);
|
||||||
|
|
||||||
|
ctx.expectUi().toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"input": "mare<>",
|
||||||
|
"suggestions": [
|
||||||
|
"mare 20",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
// The results must come from the cache, so no new fetch calls must have been made
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(3);
|
||||||
|
});
|
|
@ -1,4 +1,4 @@
|
||||||
import { init } from './context';
|
import { init } from '../context';
|
||||||
|
|
||||||
it('requests server-side autocomplete if local autocomplete returns no results', async () => {
|
it('requests server-side autocomplete if local autocomplete returns no results', async () => {
|
||||||
const ctx = await init();
|
const ctx = await init();
|
Loading…
Add table
Reference in a new issue