@realfavicongenerator/check-favicon 0.4.7 → 0.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const google_1 = require("./google");
13
+ const helper_1 = require("./helper");
14
+ const test_helper_1 = require("./test-helper");
15
+ const types_1 = require("./types");
16
+ test('getRobotsFileUrl', () => {
17
+ expect((0, google_1.getRobotsFileUrl)('https://example.com')).toEqual('https://example.com/robots.txt');
18
+ expect((0, google_1.getRobotsFileUrl)('https://example.com/some-path')).toEqual('https://example.com/robots.txt');
19
+ });
20
+ const runRobotsTest = (urls, robotsFile, messages) => __awaiter(void 0, void 0, void 0, function* () {
21
+ const report = yield (0, google_1.checkRobotsFile)('https://example.com', urls, (0, test_helper_1.testFetcher)(robotsFile ? {
22
+ 'https://example.com/robots.txt': {
23
+ status: 200,
24
+ contentType: 'text/plain',
25
+ readableStream: yield (0, helper_1.stringToReadableStream)(robotsFile)
26
+ }
27
+ } : {}));
28
+ const filteredMessages = report.map(m => ({ status: m.status, id: m.id }));
29
+ expect(filteredMessages).toEqual(messages);
30
+ });
31
+ test('checkRobotsFile - No robots file', () => __awaiter(void 0, void 0, void 0, function* () {
32
+ yield runRobotsTest(['https://example.com/favicon.png'], null, [
33
+ {
34
+ status: types_1.CheckerStatus.Ok,
35
+ id: types_1.MessageId.googleNoRobotsFile
36
+ }
37
+ ]);
38
+ }));
39
+ test('checkRobotsFile - PNG favicon is accessible', () => __awaiter(void 0, void 0, void 0, function* () {
40
+ yield runRobotsTest(['https://example.com/favicon.png'], `
41
+ User-agent: *
42
+ Allow: /`, [
43
+ {
44
+ status: types_1.CheckerStatus.Ok,
45
+ id: types_1.MessageId.googleRobotsFileFound
46
+ },
47
+ {
48
+ status: types_1.CheckerStatus.Ok,
49
+ id: types_1.MessageId.googlePngIconAllowedByRobots
50
+ }
51
+ ]);
52
+ }));
53
+ test('checkRobotsFile - PNG favicon is *not* accessible', () => __awaiter(void 0, void 0, void 0, function* () {
54
+ yield runRobotsTest(['https://example.com/favicon.png'], `
55
+ # *
56
+ User-agent: *
57
+ Allow: /
58
+
59
+ User-agent: Googlebot-Image
60
+ Disallow: /*.png
61
+ `, [
62
+ {
63
+ status: types_1.CheckerStatus.Ok,
64
+ id: types_1.MessageId.googleRobotsFileFound
65
+ },
66
+ {
67
+ status: types_1.CheckerStatus.Error,
68
+ id: types_1.MessageId.googlePngIconBlockedByRobots
69
+ }
70
+ ]);
71
+ }));
package/dist/helper.d.ts CHANGED
@@ -16,8 +16,15 @@ export type CheckIconProcessor = {
16
16
  wrongSize: (widthHeight: number) => void;
17
17
  };
18
18
  export declare const pathToMimeType: (path: string) => string;
19
- export declare const checkIcon: (iconUrl: string | undefined, processor: CheckIconProcessor, fetcher: Fetcher, mimeType: string | undefined, expectedWidthHeight?: number) => Promise<string | null>;
19
+ export type CheckIconOutput = {
20
+ content: string | null;
21
+ url: string | null;
22
+ width: number | null;
23
+ height: number | null;
24
+ };
25
+ export declare const checkIcon: (iconUrl: string | undefined, processor: CheckIconProcessor, fetcher: Fetcher, mimeType: string | undefined, expectedWidthHeight?: number) => Promise<CheckIconOutput | null>;
20
26
  export declare const mergeUrlAndPath: (baseUrl: string, absoluteOrRelativePath: string) => string;
21
27
  export declare const parseSizesAttribute: (sizes: string | undefined | null) => number | null;
22
28
  export declare const bufferToDataUrl: (buffer: Buffer, mimeType: string) => string;
29
+ export declare const filePathToDataUrl: (filePath: string) => Promise<string>;
23
30
  export declare const fetchFetcher: Fetcher;
package/dist/helper.js CHANGED
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.fetchFetcher = exports.bufferToDataUrl = exports.parseSizesAttribute = exports.mergeUrlAndPath = exports.checkIcon = exports.pathToMimeType = exports.readableStreamToBuffer = exports.readableStreamToString = exports.stringToReadableStream = exports.filePathToString = exports.filePathToReadableStream = void 0;
15
+ exports.fetchFetcher = exports.filePathToDataUrl = exports.bufferToDataUrl = exports.parseSizesAttribute = exports.mergeUrlAndPath = exports.checkIcon = exports.pathToMimeType = exports.readableStreamToBuffer = exports.readableStreamToString = exports.stringToReadableStream = exports.filePathToString = exports.filePathToReadableStream = void 0;
16
16
  const promises_1 = __importDefault(require("fs/promises"));
17
17
  const sharp_1 = __importDefault(require("sharp"));
18
18
  const filePathToReadableStream = (path) => __awaiter(void 0, void 0, void 0, function* () {
@@ -35,9 +35,11 @@ const filePathToString = (path) => __awaiter(void 0, void 0, void 0, function* (
35
35
  });
36
36
  exports.filePathToString = filePathToString;
37
37
  const stringToReadableStream = (str) => {
38
+ const encoder = new TextEncoder();
39
+ const uint8Array = encoder.encode(str);
38
40
  return new ReadableStream({
39
41
  start(controller) {
40
- controller.enqueue(str);
42
+ controller.enqueue(uint8Array);
41
43
  controller.close();
42
44
  }
43
45
  });
@@ -114,13 +116,13 @@ const checkIcon = (iconUrl, processor, fetcher, mimeType, expectedWidthHeight) =
114
116
  }
115
117
  else if (res.readableStream) {
116
118
  processor.downloadable();
117
- const content = yield (0, exports.readableStreamToBuffer)(res.readableStream);
118
- const meta = yield (0, sharp_1.default)(content).metadata();
119
+ const rawContent = yield (0, exports.readableStreamToBuffer)(res.readableStream);
120
+ const meta = yield (0, sharp_1.default)(rawContent).metadata();
119
121
  const contentType = res.contentType || (0, exports.pathToMimeType)(iconUrl);
122
+ const content = yield (0, exports.bufferToDataUrl)(rawContent, contentType);
120
123
  if (meta.width && meta.height) {
121
124
  if (meta.width !== meta.height) {
122
125
  processor.notSquare(meta.width, meta.height);
123
- return null;
124
126
  }
125
127
  else {
126
128
  processor.square(meta.width);
@@ -134,9 +136,19 @@ const checkIcon = (iconUrl, processor, fetcher, mimeType, expectedWidthHeight) =
134
136
  }
135
137
  }
136
138
  }
137
- return (0, exports.bufferToDataUrl)(content, contentType);
139
+ return {
140
+ content,
141
+ url: iconUrl,
142
+ width: meta.width || null,
143
+ height: meta.height || null
144
+ };
138
145
  }
139
- return null;
146
+ return {
147
+ content: null,
148
+ url: iconUrl,
149
+ width: null,
150
+ height: null
151
+ };
140
152
  });
141
153
  exports.checkIcon = checkIcon;
142
154
  const mergeUrlAndPath = (baseUrl, absoluteOrRelativePath) => {
@@ -177,6 +189,13 @@ const bufferToDataUrl = (buffer, mimeType) => {
177
189
  return `data:${mimeType};base64,${buffer.toString('base64')}`;
178
190
  };
179
191
  exports.bufferToDataUrl = bufferToDataUrl;
192
+ const filePathToDataUrl = (filePath) => __awaiter(void 0, void 0, void 0, function* () {
193
+ const readStream = yield (0, exports.filePathToReadableStream)(filePath);
194
+ const rawContent = yield (0, exports.readableStreamToBuffer)(readStream);
195
+ const contentType = (0, exports.pathToMimeType)(filePath);
196
+ return (0, exports.bufferToDataUrl)(rawContent, contentType);
197
+ });
198
+ exports.filePathToDataUrl = filePathToDataUrl;
180
199
  const fetchFetcher = (url, contentType) => __awaiter(void 0, void 0, void 0, function* () {
181
200
  const res = yield fetch(url, {
182
201
  headers: {
@@ -34,7 +34,12 @@ test('checkIcon - noHref', () => __awaiter(void 0, void 0, void 0, function* ()
34
34
  }));
35
35
  test('checkIcon - icon404', () => __awaiter(void 0, void 0, void 0, function* () {
36
36
  const processor = getTestProcessor();
37
- expect(yield (0, helper_1.checkIcon)('/does-not-exist.png', processor.processor, (0, test_helper_1.testFetcher)({}), 'image/png')).toBeNull();
37
+ expect(yield (0, helper_1.checkIcon)('/does-not-exist.png', processor.processor, (0, test_helper_1.testFetcher)({}), 'image/png')).toEqual({
38
+ content: null,
39
+ url: '/does-not-exist.png',
40
+ width: null,
41
+ height: null
42
+ });
38
43
  expect(processor.messages).toEqual(['icon404']);
39
44
  }));
40
45
  test('checkIcon - icon404', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -44,7 +49,12 @@ test('checkIcon - icon404', () => __awaiter(void 0, void 0, void 0, function* ()
44
49
  contentType: 'image/png',
45
50
  status: 500
46
51
  }
47
- }), 'image/png')).toBeNull();
52
+ }), 'image/png')).toEqual({
53
+ content: null,
54
+ url: '/bad-icon.png',
55
+ width: null,
56
+ height: null
57
+ });
48
58
  expect(processor.messages).toEqual(['cannotGet 500']);
49
59
  }));
50
60
  test('checkIcon - downloadable & square', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -99,7 +109,12 @@ test('checkIcon - downloadable & notSquare', () => __awaiter(void 0, void 0, voi
99
109
  contentType: 'image/png',
100
110
  readableStream: yield (0, helper_1.filePathToReadableStream)(nonSquareIcon)
101
111
  }
102
- }), 'image/png', 500)).toBeNull();
112
+ }), 'image/png', 500)).toEqual({
113
+ content: yield (0, helper_1.filePathToDataUrl)(nonSquareIcon),
114
+ url: '/non-square-icon.png',
115
+ width: 240,
116
+ height: 180
117
+ });
103
118
  expect(processor.messages).toEqual([
104
119
  'downloadable',
105
120
  'notSquare 240x180'
@@ -159,7 +159,7 @@ const checkTouchIconIcon = (baseUrl_2, head_2, ...args_2) => __awaiter(void 0, [
159
159
  }
160
160
  };
161
161
  touchIcon = yield (0, helper_1.checkIcon)(touchIconUrl, processor, fetcher, undefined);
162
- return { messages, touchIcon };
162
+ return { messages, touchIcon: touchIcon ? touchIcon.content : null };
163
163
  });
164
164
  exports.checkTouchIconIcon = checkTouchIconIcon;
165
165
  const getDuplicatedSizes = (sizes) => {
package/dist/types.d.ts CHANGED
@@ -72,7 +72,15 @@ export declare enum MessageId {
72
72
  manifestIconNotSquare = 65,
73
73
  manifestIconRightSize = 66,
74
74
  manifestIconSquare = 67,
75
- manifestIconWrongSize = 68
75
+ manifestIconWrongSize = 68,
76
+ googleNoRobotsFile = 69,
77
+ googleRobotsFileFound = 70,
78
+ googleIcoBlockedByRobots = 71,
79
+ googleIcoAllowedByRobots = 72,
80
+ googleSvgIconBlockedByRobots = 73,
81
+ googleSvgIconAllowedByRobots = 74,
82
+ googlePngIconBlockedByRobots = 75,
83
+ googlePngIconAllowedByRobots = 76
76
84
  }
77
85
  export type CheckerMessage = {
78
86
  status: CheckerStatus;
@@ -85,9 +93,24 @@ export type FetchResponse = {
85
93
  readableStream?: ReadableStream | null;
86
94
  };
87
95
  export type Fetcher = (url: string, contentType?: string) => Promise<FetchResponse>;
96
+ export type CheckedIcon = {
97
+ content: string | null;
98
+ url: string | null;
99
+ width: number | null;
100
+ height: number | null;
101
+ };
102
+ export type DesktopSingleReport = {
103
+ messages: CheckerMessage[];
104
+ icon: CheckedIcon | null;
105
+ };
88
106
  export type DesktopFaviconReport = {
89
107
  messages: CheckerMessage[];
90
108
  icon: string | null;
109
+ icons: {
110
+ png: CheckedIcon | null;
111
+ ico: CheckedIcon | null;
112
+ svg: CheckedIcon | null;
113
+ };
91
114
  };
92
115
  export type TouchIconTitleReport = {
93
116
  messages: CheckerMessage[];
@@ -111,3 +134,8 @@ export type FaviconReport = {
111
134
  webAppManifest: WebAppManifestReport;
112
135
  };
113
136
  export type TouchIconReport = TouchIconIconReport & TouchIconTitleReport;
137
+ export type GoogleReport = {
138
+ messages: CheckerMessage[];
139
+ icon: string | null;
140
+ icons: CheckedIcon[];
141
+ };
package/dist/types.js CHANGED
@@ -78,4 +78,12 @@ var MessageId;
78
78
  MessageId[MessageId["manifestIconRightSize"] = 66] = "manifestIconRightSize";
79
79
  MessageId[MessageId["manifestIconSquare"] = 67] = "manifestIconSquare";
80
80
  MessageId[MessageId["manifestIconWrongSize"] = 68] = "manifestIconWrongSize";
81
+ MessageId[MessageId["googleNoRobotsFile"] = 69] = "googleNoRobotsFile";
82
+ MessageId[MessageId["googleRobotsFileFound"] = 70] = "googleRobotsFileFound";
83
+ MessageId[MessageId["googleIcoBlockedByRobots"] = 71] = "googleIcoBlockedByRobots";
84
+ MessageId[MessageId["googleIcoAllowedByRobots"] = 72] = "googleIcoAllowedByRobots";
85
+ MessageId[MessageId["googleSvgIconBlockedByRobots"] = 73] = "googleSvgIconBlockedByRobots";
86
+ MessageId[MessageId["googleSvgIconAllowedByRobots"] = 74] = "googleSvgIconAllowedByRobots";
87
+ MessageId[MessageId["googlePngIconBlockedByRobots"] = 75] = "googlePngIconBlockedByRobots";
88
+ MessageId[MessageId["googlePngIconAllowedByRobots"] = 76] = "googlePngIconAllowedByRobots";
81
89
  })(MessageId || (exports.MessageId = MessageId = {}));
@@ -257,6 +257,6 @@ const checkWebAppManifestFile = (manifest, baseUrl, fetcher) => __awaiter(void 0
257
257
  }
258
258
  finally { if (e_1) throw e_1.error; }
259
259
  }
260
- return { messages, name, shortName, backgroundColor, themeColor, icon };
260
+ return { messages, name, shortName, backgroundColor, themeColor, icon: icon ? icon.content : null };
261
261
  });
262
262
  exports.checkWebAppManifestFile = checkWebAppManifestFile;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@realfavicongenerator/check-favicon",
3
- "version": "0.4.7",
3
+ "version": "0.4.17",
4
4
  "description": "Check the favicon of a website",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
- "test": "jest",
9
- "test:watch": "jest --watch",
8
+ "test": "jest src",
9
+ "test:watch": "jest src --watch",
10
10
  "build": "tsc",
11
11
  "prepublishOnly": "npm run build"
12
12
  },
@@ -37,6 +37,8 @@
37
37
  "dependencies": {
38
38
  "decode-ico": "^0.4.1",
39
39
  "node-html-parser": "^6.1.13",
40
+ "robots-parser": "^3.0.1",
40
41
  "sharp": "^0.32.6"
41
- }
42
+ },
43
+ "gitHead": "d1b623a15751d0df89d38fc5fd4915adc2e03646"
42
44
  }
@@ -1,10 +1,13 @@
1
1
  import { parse } from 'node-html-parser'
2
2
  import { checkPngFavicon, checkSvgFavicon } from "./desktop";
3
- import { CheckerMessage, CheckerStatus, FetchResponse, MessageId } from '../types';
4
- import { filePathToReadableStream, filePathToString, stringToReadableStream } from '../helper';
3
+ import { CheckerMessage, CheckerStatus, DesktopFaviconReport, FetchResponse, MessageId } from '../types';
4
+ import { filePathToDataUrl, filePathToReadableStream, filePathToString, stringToReadableStream } from '../helper';
5
5
  import { testFetcher } from '../test-helper';
6
6
 
7
- type TestOutput = Pick<CheckerMessage, 'id' | 'status'>[];
7
+ type TestOutput = {
8
+ messages: Pick<CheckerMessage, 'id' | 'status'>[];
9
+ icons: DesktopFaviconReport['icons'];
10
+ }
8
11
 
9
12
  const runSvgTest = async (
10
13
  headFragment: string | null,
@@ -13,62 +16,113 @@ const runSvgTest = async (
13
16
  ) => {
14
17
  const root = headFragment ? parse(headFragment) : null;
15
18
  const result = await checkSvgFavicon('https://example.com/', root, testFetcher(fetchDatabase));
16
- const filteredMessages = result.map(m => ({ status: m.status, id: m.id }));
17
- expect(filteredMessages).toEqual(output);
19
+ const filteredMessages = result.messages.map(m => ({ status: m.status, id: m.id }));
20
+ expect(filteredMessages).toEqual(output.messages);
18
21
  }
19
22
 
20
23
  test('checkSvgFavicon - noHead', async () => {
21
- await runSvgTest(null, [{
22
- status: CheckerStatus.Error,
23
- id: MessageId.noHead,
24
- }]);
24
+ await runSvgTest(null, {
25
+ messages: [{
26
+ status: CheckerStatus.Error,
27
+ id: MessageId.noHead,
28
+ }],
29
+ icons: {
30
+ png: null,
31
+ ico: null,
32
+ svg: null,
33
+ }
34
+ });
25
35
  })
26
36
 
27
37
  test('checkSvgFavicon - noSvgFavicon', async () => {
28
- await runSvgTest(`<title>SOme text</title>`, [{
29
- status: CheckerStatus.Error,
30
- id: MessageId.noSvgFavicon,
31
- }]);
38
+ await runSvgTest(`<title>Some text</title>`, {
39
+ messages: [{
40
+ status: CheckerStatus.Error,
41
+ id: MessageId.noSvgFavicon,
42
+ }],
43
+ icons: {
44
+ png: null,
45
+ ico: null,
46
+ svg: null,
47
+ }
48
+ });
32
49
  })
33
50
 
34
51
  test('checkSvgFavicon - multipleSvgFavicons', async () => {
35
52
  await runSvgTest(`
36
53
  <link rel="icon" type="image/svg+xml" href="/the-icon.svg" />
37
54
  <link rel="icon" type="image/svg+xml" href="/another-icon.svg" />
38
- `, [{
39
- status: CheckerStatus.Error,
40
- id: MessageId.multipleSvgFavicons,
41
- }]);
55
+ `, {
56
+ messages: [{
57
+ status: CheckerStatus.Error,
58
+ id: MessageId.multipleSvgFavicons,
59
+ }], icons: {
60
+ png: null,
61
+ ico: null,
62
+ svg: null,
63
+ }
64
+ });
42
65
  })
43
66
 
44
67
  test('checkSvgFavicon - svgFaviconDeclared & noSvgFaviconHref', async () => {
45
- await runSvgTest(`<link rel="icon" type="image/svg+xml" />`, [{
46
- status: CheckerStatus.Ok,
47
- id: MessageId.svgFaviconDeclared,
48
- }, {
49
- status: CheckerStatus.Error,
50
- id: MessageId.noSvgFaviconHref,
51
- }]);
68
+ await runSvgTest(`<link rel="icon" type="image/svg+xml" />`, {
69
+ messages: [{
70
+ status: CheckerStatus.Ok,
71
+ id: MessageId.svgFaviconDeclared,
72
+ }, {
73
+ status: CheckerStatus.Error,
74
+ id: MessageId.noSvgFaviconHref,
75
+ }],
76
+ icons: {
77
+ png: null,
78
+ ico: null,
79
+ svg: null,
80
+ }
81
+ });
52
82
  })
53
83
 
54
84
  test('checkSvgFavicon - svgFaviconDeclared & svgFavicon404', async () => {
55
- await runSvgTest(`<link rel="icon" type="image/svg+xml" href="/the-icon.svg" />`, [{
56
- status: CheckerStatus.Ok,
57
- id: MessageId.svgFaviconDeclared,
58
- }, {
59
- status: CheckerStatus.Error,
60
- id: MessageId.svgFavicon404,
61
- }]);
85
+ await runSvgTest(`<link rel="icon" type="image/svg+xml" href="/the-icon.svg" />`, {
86
+ messages: [{
87
+ status: CheckerStatus.Ok,
88
+ id: MessageId.svgFaviconDeclared,
89
+ }, {
90
+ status: CheckerStatus.Error,
91
+ id: MessageId.svgFavicon404,
92
+ }],
93
+ icons: {
94
+ png: null,
95
+ ico: null,
96
+ svg: {
97
+ content: null,
98
+ url: 'https://example.com/the-icon.svg',
99
+ width: null,
100
+ height: null,
101
+ },
102
+ }
103
+ });
62
104
  })
63
105
 
64
106
  test('checkSvgFavicon - svgFaviconDeclared & svgFaviconCannotGet', async () => {
65
- await runSvgTest(`<link rel="icon" type="image/svg+xml" href="/the-icon.svg" />`, [{
66
- status: CheckerStatus.Ok,
67
- id: MessageId.svgFaviconDeclared,
107
+ await runSvgTest(`<link rel="icon" type="image/svg+xml" href="/the-icon.svg" />`, {
108
+ messages: [{
109
+ status: CheckerStatus.Ok,
110
+ id: MessageId.svgFaviconDeclared,
111
+ }, {
112
+ status: CheckerStatus.Error,
113
+ id: MessageId.svgFaviconCannotGet,
114
+ }],
115
+ icons: {
116
+ png: null,
117
+ ico: null,
118
+ svg: {
119
+ content: null,
120
+ url: 'https://example.com/the-icon.svg',
121
+ width: null,
122
+ height: null,
123
+ },
124
+ }
68
125
  }, {
69
- status: CheckerStatus.Error,
70
- id: MessageId.svgFaviconCannotGet,
71
- }], {
72
126
  'https://example.com/the-icon.svg': {
73
127
  status: 403,
74
128
  contentType: 'image/svg+xml'
@@ -78,13 +132,24 @@ test('checkSvgFavicon - svgFaviconDeclared & svgFaviconCannotGet', async () => {
78
132
 
79
133
  // For https://github.com/RealFaviconGenerator/core/issues/2
80
134
  test('checkSvgFavicon - Protocol-relative URL', async () => {
81
- await runSvgTest(`<link rel="icon" type="image/svg+xml" href="//example.com/the-icon.svg" />`, [{
82
- status: CheckerStatus.Ok,
83
- id: MessageId.svgFaviconDeclared,
135
+ await runSvgTest(`<link rel="icon" type="image/svg+xml" href="//example.com/the-icon.svg" />`, {
136
+ messages: [{
137
+ status: CheckerStatus.Ok,
138
+ id: MessageId.svgFaviconDeclared,
139
+ }, {
140
+ status: CheckerStatus.Error,
141
+ id: MessageId.svgFaviconCannotGet,
142
+ }], icons: {
143
+ png: null,
144
+ ico: null,
145
+ svg: {
146
+ content: null,
147
+ url: 'https://example.com/the-icon.svg',
148
+ width: null,
149
+ height: null,
150
+ },
151
+ }
84
152
  }, {
85
- status: CheckerStatus.Error,
86
- id: MessageId.svgFaviconCannotGet,
87
- }], {
88
153
  'https://example.com/the-icon.svg': {
89
154
  status: 403,
90
155
  contentType: 'image/svg+xml'
@@ -97,17 +162,29 @@ test('checkSvgFavicon - svgFaviconDeclared & svgFaviconDownloadable & svgFavicon
97
162
 
98
163
  const serpIcon = await filePathToString(testIconPath);
99
164
 
100
- await runSvgTest(`<link rel="icon" type="image/svg+xml" href="/the-icon.svg" />`, [
101
- {
102
- status: CheckerStatus.Ok,
103
- id: MessageId.svgFaviconDeclared,
104
- }, {
105
- status: CheckerStatus.Ok,
106
- id: MessageId.svgFaviconDownloadable,
165
+ await runSvgTest(`<link rel="icon" type="image/svg+xml" href="/the-icon.svg" />`, {
166
+ messages: [
167
+ {
168
+ status: CheckerStatus.Ok,
169
+ id: MessageId.svgFaviconDeclared,
170
+ }, {
171
+ status: CheckerStatus.Ok,
172
+ id: MessageId.svgFaviconDownloadable,
173
+ }, {
174
+ status: CheckerStatus.Ok,
175
+ id: MessageId.svgFaviconSquare,
176
+ }],
177
+ icons: {
178
+ png: null,
179
+ ico: null,
180
+ svg: {
181
+ content: await filePathToDataUrl(testIconPath),
182
+ url: 'https://example.com/the-icon.svg',
183
+ width: 36,
184
+ height: 36,
185
+ },
186
+ }
107
187
  }, {
108
- status: CheckerStatus.Ok,
109
- id: MessageId.svgFaviconSquare,
110
- }], {
111
188
  'https://example.com/the-icon.svg': {
112
189
  status: 200,
113
190
  contentType: 'image/svg+xml',
@@ -124,7 +201,7 @@ const runPngTest = async (
124
201
  const root = headFragment ? parse(headFragment) : null;
125
202
  const result = await checkPngFavicon('https://example.com/', root, testFetcher(fetchDatabase));
126
203
  const filteredMessages = result.messages.map(m => ({ status: m.status, id: m.id }));
127
- expect(filteredMessages).toEqual(output);
204
+ expect(filteredMessages).toEqual(output.messages);
128
205
  }
129
206
 
130
207
  const testIcon16 = './fixtures/16x16.png';
@@ -138,16 +215,27 @@ test('checkSvgFavicon - Three PNG icons with different sizes', async () => {
138
215
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
139
216
  <link rel="icon" type="image/png" sizes="48x48" href="/favicon/favicon-48x48.png">
140
217
  <link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
141
- `, [{
142
- status: CheckerStatus.Ok,
143
- id: MessageId.desktopPngFaviconDeclared,
144
- }, {
145
- status: CheckerStatus.Ok,
146
- id: MessageId.desktopPngFaviconDownloadable,
147
- }, {
148
- status: CheckerStatus.Ok,
149
- id: MessageId.desktopPngFaviconRightSize,
150
- }],
218
+ `, { messages: [{
219
+ status: CheckerStatus.Ok,
220
+ id: MessageId.desktopPngFaviconDeclared,
221
+ }, {
222
+ status: CheckerStatus.Ok,
223
+ id: MessageId.desktopPngFaviconDownloadable,
224
+ }, {
225
+ status: CheckerStatus.Ok,
226
+ id: MessageId.desktopPngFaviconRightSize,
227
+ }],
228
+ icons: {
229
+ png: {
230
+ content: await filePathToDataUrl(testIcon96),
231
+ url: 'https://example.com/favicon/favicon-96x96.png',
232
+ width: 96,
233
+ height: 96,
234
+ },
235
+ ico: null,
236
+ svg: null,
237
+ }
238
+ },
151
239
  {
152
240
  'https://example.com/favicon/favicon-16x16.png': {
153
241
  status: 200,