/* eslint-env jest */
import type {
ISeoBulkFields,
ISeoBulkRow,
} from '../../../service/seo/seo.interface';
import {
DRAFT_CREDITS,
changeOf,
draftCost,
draftRequest,
mergeDraft,
ranToday,
renderRow,
rowState,
} from '../bulk-editor';
const LIST = {
separator: '|',
variables: { '%sitename%': 'Kettle Shop', '%page%': '' },
};
const content =
'
A cast iron kettle keeps tea warm for hours and lasts for decades when it is dried after use.
How do you care for a cast iron kettle?
Dry it after every use.
';
const row = (overrides: Partial = {}): ISeoBulkRow => ({
id: 12,
type: 'post',
status: 'publish',
title: 'Kettles',
post_title: 'Kettles',
excerpt: '',
link: 'https://shop.example/kettles/',
edit_link: 'https://shop.example/wp-admin/post.php?post=12&action=edit',
editable: true,
fields: { title: '', description: '', keywords: 'cast iron kettle' },
templates: { title: '%title% %sep% %sitename%', description: '%excerpt%' },
variables: {
'%title%': 'Kettles',
'%excerpt%': 'A cast iron kettle keeps tea warm.',
},
score: 40,
stale: false,
ran_today: [],
input: {
title: 'Kettles | Kettle Shop',
description: 'A cast iron kettle keeps tea warm.',
slug: 'kettles',
content,
keyword: 'cast iron kettle',
keywords: ['cast iron kettle'],
hasFeaturedImage: false,
imageAlts: [],
postType: 'post',
language: 'en',
siteLanguage: 'en_US',
keywordUsedElsewhere: null,
},
...overrides,
});
const fields = (overrides: Partial = {}): ISeoBulkFields => ({
...row().fields,
...overrides,
});
describe('the bulk editor rows', () => {
it('prices the drafts as the agent bills the snippet', () => {
expect(DRAFT_CREDITS).toBe(10);
expect(draftCost(7)).toBe(70);
});
it('prints what the server printed until a field changes', () => {
expect(renderRow(row(), fields(), LIST)).toEqual({
title: 'Kettles | Kettle Shop',
description: 'A cast iron kettle keeps tea warm.',
});
expect(
renderRow(
row(),
fields({ title: '%focuskw%: how to choose one %sep% %sitename%' }),
LIST
).title
).toBe('cast iron kettle: how to choose one | Kettle Shop');
// An empty field prints its template.
expect(
renderRow(row(), fields({ description: '', keywords: 'kettle' }), LIST)
.description
).toBe('A cast iron kettle keeps tea warm.');
expect(renderRow(row(), fields({ keywords: 'kettle' }), LIST).title).toBe(
'Kettles | Kettle Shop'
);
});
it('scores with the editor analysis, and keeps no score without a keyword', () => {
const state = rowState(row(), fields(), LIST, 'shop.example');
expect(state.score).toBe(state.analysis.score);
expect(state.tests.fixIds).toContain('keywordInTitle');
const better = rowState(
row(),
fields({ title: 'Cast iron kettle: how to choose and care for one' }),
LIST,
'shop.example'
);
expect(better.tests.fixIds).not.toContain('keywordInTitle');
expect(better.score).toBeGreaterThan(state.score ?? 0);
expect(
rowState(row(), fields({ keywords: '' }), LIST, 'shop.example').score
).toBeNull();
});
it('saves only what changed, with the score it makes', () => {
expect(changeOf(row(), fields(), 40)).toBeNull();
expect(changeOf(row(), fields({ title: 'New title' }), 55)).toEqual({
id: 12,
title: 'New title',
score: 55,
});
expect(changeOf(row(), fields({ keywords: '' }), null)).toEqual({
id: 12,
keywords: '',
});
});
it('puts a draft in the way Fix with AI applies it in the editor', () => {
expect(
mergeDraft(fields({ keywords: 'kettle, teapot, cast iron' }), {
title: 'Cast iron kettle: how to choose one',
description: 'How to choose a cast iron kettle by size and enamel.',
keyword: 'cast iron kettle',
})
).toEqual({
title: 'Cast iron kettle: how to choose one',
description: 'How to choose a cast iron kettle by size and enamel.',
keywords: 'cast iron kettle, teapot, cast iron',
});
// What the draft left empty stays.
expect(
mergeDraft(fields({ title: 'Mine' }), {
title: ' ',
description: '',
keyword: '',
})
).toEqual(fields({ title: 'Mine' }));
});
it('asks Fix with AI for the snippet alone, with the tests as edited', () => {
const state = rowState(row(), fields(), LIST, 'shop.example');
const request = draftRequest(
row(),
fields({ keywords: 'kettle care, kettle' }),
state.tests
);
expect(request).toMatchObject({
post_id: 12,
title: 'Kettles',
keyword: 'kettle care',
slug: 'kettles',
snippet: true,
rewrite: false,
keyword_used_elsewhere: false,
});
expect(request.content).toBe(content);
expect(request.test_ids).toEqual(state.tests.fixIds);
expect(request.tests).toHaveLength(state.tests.fixIds.length);
});
it('tells a row Fix with AI already ran on today', () => {
expect(ranToday(row())).toBe(false);
expect(ranToday(row({ ran_today: ['fix'] }))).toBe(true);
expect(ranToday(row({ ran_today: ['faq'] }))).toBe(false);
});
});