Limit and configure how many jobs the Jobs panels show
This commit is contained in:
+66
-3
@@ -15,6 +15,7 @@ let api, main, details, cleanups;
|
||||
const config = {
|
||||
metadata_fields: { title: 'Title', authors: 'Authors', comments: 'Description', series: 'Series', pubdate: 'Published', tags: 'Tags', languages: 'Language' },
|
||||
mode_labels: { new: 'New chapters' }, library_available: true, update_interval: 2,
|
||||
job_list_max_hours: 720, job_list_max_count: 500,
|
||||
};
|
||||
const rule = { pattern: 'before', replacement: 'after', flags: 'i', note: '', enabled: true };
|
||||
const emptyRules = { rules: [], paragraphs: null, global_paragraphs: true };
|
||||
@@ -49,7 +50,7 @@ const writes = () => api.requests.filter((r) => r.method !== 'GET');
|
||||
|
||||
for (const value of ['7', '']) {
|
||||
test(`settings save converts ${JSON.stringify(value)} to a count`, async () => {
|
||||
settingsPage(main);
|
||||
settingsPage(main, {}, config);
|
||||
await settle();
|
||||
api.on('PUT', 'settings', {});
|
||||
field(main, 'recent-chapters').value = value;
|
||||
@@ -60,7 +61,7 @@ for (const value of ['7', '']) {
|
||||
}
|
||||
|
||||
test('personal.ini save reports warnings and clears them after a clean save', async () => {
|
||||
settingsPage(main);
|
||||
settingsPage(main, {}, config);
|
||||
await settle();
|
||||
const card = section(main, 'FanFicFare settings (personal.ini)');
|
||||
field(main, 'personal.ini').value = '[defaults]\nis_adult: true';
|
||||
@@ -74,7 +75,7 @@ test('personal.ini save reports warnings and clears them after a clean save', as
|
||||
});
|
||||
|
||||
test('failed settings saves retain edits and re-enable the action', async () => {
|
||||
settingsPage(main);
|
||||
settingsPage(main, {}, config);
|
||||
await settle();
|
||||
const card = section(main, 'FanFicFare settings (personal.ini)');
|
||||
field(main, 'personal.ini').value = 'invalid ini';
|
||||
@@ -85,6 +86,28 @@ test('failed settings saves retain edits and re-enable the action', async () =>
|
||||
assert.match(ui.toasts.textContent, /Invalid settings/);
|
||||
});
|
||||
|
||||
test('the jobs list settings load and save all four fields', async () => {
|
||||
api.on('GET', 'settings', {
|
||||
recent_chapters: 0, personal_ini: '',
|
||||
story_jobs_hours: 36, story_jobs_count: 10, main_jobs_hours: 6, main_jobs_count: 25,
|
||||
});
|
||||
settingsPage(main, {}, config);
|
||||
await settle();
|
||||
const card = section(main, 'Jobs list');
|
||||
assert.equal(field(main, 'story-jobs-hours').value, 36);
|
||||
assert.equal(field(main, 'main-jobs-count').value, 25);
|
||||
field(main, 'story-jobs-hours').value = '48';
|
||||
field(main, 'story-jobs-count').value = '20';
|
||||
field(main, 'main-jobs-hours').value = '12';
|
||||
field(main, 'main-jobs-count').value = '50';
|
||||
api.on('PUT', 'settings', {});
|
||||
await click(card, 'Save');
|
||||
assert.deepEqual(api.sent('PUT', 'settings')[0].body, {
|
||||
story_jobs_hours: '48', story_jobs_count: '20', main_jobs_hours: '12', main_jobs_count: '50',
|
||||
});
|
||||
assert.match(ui.toasts.textContent, /Saved/);
|
||||
});
|
||||
|
||||
test('adding stories keeps input on rejection and clears it after a mixed result', async () => {
|
||||
await mountStories({ ...config, library_available: false });
|
||||
const urls = nodes(main).find((el) => el.tagName === 'textarea');
|
||||
@@ -491,6 +514,46 @@ test('chapter comparisons and revision changes send the chosen revision numbers'
|
||||
assert.equal(api.sent('GET', 'chapters/2/diff?source=1').length, 1);
|
||||
});
|
||||
|
||||
test('a job panel shows a queued job however old, but limits others by age', () => {
|
||||
const { el, render } = jobPanel({ hours: 1, count: 10 });
|
||||
const now = Date.now();
|
||||
const old = new Date(now - 2 * 3600000).toISOString();
|
||||
const recent = new Date(now - 30 * 60000).toISOString();
|
||||
render([
|
||||
{ id: 'a', status: 'queued', title: 'Old queued', updated: old, created: old },
|
||||
{ id: 'b', status: 'done', title: 'Old done', updated: old, created: old },
|
||||
{ id: 'c', status: 'done', title: 'Recent done', updated: recent, created: recent },
|
||||
]);
|
||||
assert.match(el.textContent, /Old queued/);
|
||||
assert.doesNotMatch(el.textContent, /Old done/);
|
||||
assert.match(el.textContent, /Recent done/);
|
||||
});
|
||||
|
||||
test('a job panel caps jobs other than queued by count, newest first', () => {
|
||||
const { el, render } = jobPanel({ hours: 24, count: 2 });
|
||||
const now = Date.now();
|
||||
const at = (minsAgo) => new Date(now - minsAgo * 60000).toISOString();
|
||||
render([
|
||||
{ id: 'a', status: 'done', title: 'Oldest', updated: at(30), created: at(30) },
|
||||
{ id: 'b', status: 'done', title: 'Middle', updated: at(20), created: at(20) },
|
||||
{ id: 'c', status: 'done', title: 'Newest', updated: at(10), created: at(10) },
|
||||
]);
|
||||
assert.match(el.textContent, /Newest/);
|
||||
assert.match(el.textContent, /Middle/);
|
||||
assert.doesNotMatch(el.textContent, /Oldest/);
|
||||
});
|
||||
|
||||
test('a job panel shows a running job however old, like a queued job', () => {
|
||||
const { el, render } = jobPanel({ hours: 1, count: 10 });
|
||||
const old = new Date(Date.now() - 2 * 3600000).toISOString();
|
||||
render([
|
||||
{ id: 'a', status: 'running', title: 'Old running', updated: old, created: old },
|
||||
{ id: 'b', status: 'done', title: 'Old done', updated: old, created: old },
|
||||
]);
|
||||
assert.match(el.textContent, /Old running/);
|
||||
assert.doesNotMatch(el.textContent, /Old done/);
|
||||
});
|
||||
|
||||
test('job cancellation posts the job ID and refreshes polling', async () => {
|
||||
startPolling();
|
||||
await settle();
|
||||
|
||||
Reference in New Issue
Block a user