@realfavicongenerator/check-favicon
Version:
Check the favicon of a website
181 lines (163 loc) • 5.9 kB
text/typescript
import { parse } from 'node-html-parser'
import { CheckerMessage, CheckerStatus, FetchResponse, MessageId } from "./types";
import { checkTouchIcon, checkTouchIconIcon, checkTouchIconTitle, getDuplicatedSizes } from "./touch-icon";
import { testFetcher } from './test-helper';
import { bufferToDataUrl, filePathToReadableStream, readableStreamToBuffer } from './helper';
type TestOutput = {
messages: Pick<CheckerMessage, 'id' | 'status'>[],
appTitle?: string,
touchIcon?: string | null
}
const runCheckTouchIconTitleTest = async (
headFragment: string | null,
output: TestOutput,
fetchDatabase: { [url: string]: FetchResponse } = {}
) => {
const root = headFragment ? parse(headFragment) : null;
const result = await checkTouchIconTitle('https://example.com/', root, testFetcher(fetchDatabase));
const filteredMessages = result.messages.map(m => ({ status: m.status, id: m.id }));
expect({
messages: filteredMessages,
appTitle: result.appTitle
}).toEqual(output);
}
test('checkTouchIconTitle - noHead', async () => {
await runCheckTouchIconTitleTest(null, { messages: [{
status: CheckerStatus.Error,
id: MessageId.noHead,
}]});
})
test('checkTouchIconTitle - noTouchWebAppTitle', async () => {
await runCheckTouchIconTitleTest('<title>Some text</title>', { messages: [{
status: CheckerStatus.Warning,
id: MessageId.noTouchWebAppTitle,
}]});
})
test('checkTouchIconTitle - multipleTouchWebAppTitles', async () => {
await runCheckTouchIconTitleTest(`
<meta name="apple-mobile-web-app-title" content="First title">
<meta name="apple-mobile-web-app-title" content="Second title">
`, { messages: [{
status: CheckerStatus.Error,
id: MessageId.multipleTouchWebAppTitles,
}]});
})
test('checkTouchIconTitle - touchWebAppTitleDeclared', async () => {
await runCheckTouchIconTitleTest(`
<meta name="apple-mobile-web-app-title" content="The App Name">
`, { messages: [{
status: CheckerStatus.Ok,
id: MessageId.touchWebAppTitleDeclared,
}], appTitle: 'The App Name' });
})
const runCheckTouchIconTest = async (
headFragment: string | null,
output: TestOutput,
fetchDatabase: { [url: string]: FetchResponse } = {}
) => {
const root = headFragment ? parse(headFragment) : null;
const result = await checkTouchIconIcon('https://example.com/', root, testFetcher(fetchDatabase));
const filteredMessages = result.messages.map(m => ({ status: m.status, id: m.id }));
expect({
messages: filteredMessages,
touchIcon: result.touchIcon
}).toEqual({
...output,
touchIcon: output.touchIcon || null
});
}
test('checkTouchIcon - noHead', async () => {
await runCheckTouchIconTest(null, { messages: [{
status: CheckerStatus.Error,
id: MessageId.noHead,
}]});
})
test('checkTouchIcon - noTouchIcon', async () => {
await runCheckTouchIconTest('<title>Some text</title>', { messages: [{
status: CheckerStatus.Error,
id: MessageId.noTouchIcon,
}]});
})
test('checkTouchIcon - multipleTouchIcon - no size', async () => {
await runCheckTouchIconTest(`
<link rel="apple-touch-icon" href="some-icon.png">
<link rel="apple-touch-icon" href="some-other-icon.png">
`, { messages: [{
status: CheckerStatus.Ok,
id: MessageId.touchIconDeclared,
}, {
status: CheckerStatus.Error,
id: MessageId.duplicatedTouchIconSizes,
}]}, {
'https://example.com/some-icon.png': {
status: 200,
contentType: 'image/png',
readableStream: null
},
'https://example.com/some-other-icon.png': {
status: 200,
contentType: 'image/png',
readableStream: null
}
});
})
test('checkTouchIcon - multipleTouchIcon - specific size', async () => {
await runCheckTouchIconTest(`
<link rel="apple-touch-icon" sizes="180x180" href="some-icon.png">
<link rel="apple-touch-icon" sizes="180x180" href="some-other-icon.png">
`, { messages: [{
status: CheckerStatus.Ok,
id: MessageId.touchIconDeclared,
}, {
status: CheckerStatus.Error,
id: MessageId.duplicatedTouchIconSizes,
}]}, {
'https://example.com/some-icon.png': {
status: 200,
contentType: 'image/png',
readableStream: null
},
'https://example.com/some-other-icon.png': {
status: 200,
contentType: 'image/png',
readableStream: null
}
});
})
const testIcon = './fixtures/180x180.png';
test('checkTouchIcon - Regular case', async () => {
await runCheckTouchIconTest(`
<link rel="apple-touch-icon" href="some-other-icon.png">
`, { messages: [{
status: CheckerStatus.Ok,
id: MessageId.touchIconDeclared,
}, {
status: CheckerStatus.Ok,
id: MessageId.touchIconDownloadable,
},{
status: CheckerStatus.Ok,
id: MessageId.touchIconSquare
}], touchIcon: bufferToDataUrl(await readableStreamToBuffer(await filePathToReadableStream(testIcon)), 'image/png')
}, {
'https://example.com/some-other-icon.png': {
status: 200,
contentType: 'image/png',
readableStream: await filePathToReadableStream(testIcon)
}
});
})
test('getDuplicatedSizes', () => {
// No duplicates
expect(getDuplicatedSizes([])).toEqual([]);
expect(getDuplicatedSizes([ undefined ])).toEqual([]);
expect(getDuplicatedSizes([ '180x180' ])).toEqual([]);
expect(getDuplicatedSizes([ undefined, '180x180' ])).toEqual([]);
// Duplicates
expect(getDuplicatedSizes([ '152x152', '180x180', '180x180' ])).toEqual([ '180x180' ]);
expect(getDuplicatedSizes([ undefined, '180x180', undefined, undefined ])).toEqual([ undefined ]);
expect(getDuplicatedSizes([
'152x152', '180x180', '152x152', undefined, '152x152', undefined
])).toEqual([
'152x152', undefined
]);
})