diff --git a/src/e2e/__snapshots__/index.test.ts.snap b/src/e2e/__snapshots__/index.test.ts.snap new file mode 100644 index 0000000..0d62df5 --- /dev/null +++ b/src/e2e/__snapshots__/index.test.ts.snap @@ -0,0 +1,49 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`/ > should return a LinkCard object for http://example.com/ 1`] = ` +{ + "faviconUrl": "http://example.com/favicon.ico", + "title": "Example Domain", + "url": "http://example.com/", +} +`; + +exports[`/ > should return a LinkCard object for http://example.invalid/ 1`] = ` +{ + "url": "http://example.invalid/", +} +`; + +exports[`/ > should return a LinkCard object for https://ogp.me/ 1`] = ` +{ + "description": "The Open Graph protocol enables any web page to become a rich object in a social graph.", + "faviconUrl": "https://ogp.me/favicon.ico", + "ogImageUrl": "https://ogp.me/logo.png", + "title": "Open Graph protocol", + "url": "https://ogp.me/", +} +`; + +exports[`/ > should return a LinkCard object for https://ogp.me/foobarbaz 1`] = ` +{ + "faviconUrl": "https://ogp.me/favicon.ico", + "url": "https://ogp.me/foobarbaz", +} +`; + +exports[`/ > should return a LinkCard object for https://ogp.me/logo.png 1`] = ` +{ + "faviconUrl": "https://ogp.me/favicon.ico", + "url": "https://ogp.me/logo.png", +} +`; + +exports[`/ > should return a LinkCard object for https://www.w3.org/ 1`] = ` +{ + "description": "The World Wide Web Consortium (W3C) develops standards and guidelines to help everyone build a web based on the principles of accessibility, internationalization, privacy and security.", + "faviconUrl": "https://www.w3.org/favicon.ico", + "ogImageUrl": "https://www.w3.org/assets/website-2021/images/w3c-opengraph-image.png", + "title": "W3C", + "url": "https://www.w3.org/", +} +`; diff --git a/src/e2e/index.test.ts b/src/e2e/index.test.ts index 77b9fce..f21caf3 100644 --- a/src/e2e/index.test.ts +++ b/src/e2e/index.test.ts @@ -1,6 +1,5 @@ -import { describe, expect, it } from 'vitest'; +import { describe, it } from 'vitest'; import ky from 'ky'; -import { type LinkCard } from '@/types/LinkCard'; describe.concurrent( '/', @@ -10,72 +9,33 @@ describe.concurrent( } const baseUrl = new URL(process.env.LINK_CARD_TEST_URL); - const makeReq = async (urlParam: string): Promise => { - const url = new URL(baseUrl); - url.searchParams.set('url', urlParam); - return await ky(url).json(); - }; - - it('should return a LinkCard object for http://example.com/', async () => { - expect(await makeReq('http://example.com/')).toStrictEqual({ - url: 'http://example.com/', - title: 'Example Domain', - faviconUrl: 'http://example.com/favicon.ico', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://ogp.me/', async () => { - expect(await makeReq('https://ogp.me/')).toStrictEqual({ - url: 'https://ogp.me/', - title: 'Open Graph protocol', - description: - 'The Open Graph protocol enables any web page to become a rich object in a social graph.', - faviconUrl: 'https://ogp.me/favicon.ico', - ogImageUrl: 'https://ogp.me/logo.png', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://www.w3.org/', async () => { - expect(await makeReq('https://www.w3.org/')).toStrictEqual({ - url: 'https://www.w3.org/', - title: 'W3C', - description: - 'The World Wide Web Consortium (W3C) develops standards and guidelines to help everyone build a web based on the principles of accessibility, internationalization, privacy and security.', - faviconUrl: 'https://www.w3.org/favicon.ico', - ogImageUrl: - 'https://www.w3.org/assets/website-2021/images/w3c-opengraph-image.png', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://ogp.me/foobarbaz', async () => { - // Not Found - expect(await makeReq('https://ogp.me/foobarbaz')).toStrictEqual({ - url: 'https://ogp.me/foobarbaz', - faviconUrl: 'https://ogp.me/favicon.ico', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://ogp.me/logo.png', async () => { - // Not HTML - expect(await makeReq('https://ogp.me/logo.png')).toStrictEqual({ - url: 'https://ogp.me/logo.png', - faviconUrl: 'https://ogp.me/favicon.ico', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for http://example.invalid/', async () => { - // Network Error - expect(await makeReq('http://example.invalid/')).toStrictEqual({ - url: 'http://example.invalid/', - } satisfies LinkCard); - }); + const cases = [ + 'http://example.com/', + 'https://ogp.me/', + 'https://www.w3.org/', + 'https://ogp.me/foobarbaz', + 'https://ogp.me/logo.png', + 'http://example.invalid/', + ] as const satisfies readonly string[]; + + for (const url of cases) { + it(`should return a LinkCard object for ${url}`, async ({ expect }) => { + const endpointUrl = new URL(baseUrl); + endpointUrl.searchParams.set('url', url); + expect(await ky(endpointUrl).json()).toMatchSnapshot(); + }); + } - it('should return 400 for requests with no url parameter', async () => { + it('should return 400 for requests with no url parameter', async ({ + expect, + }) => { const resp = await ky(baseUrl, { throwHttpErrors: false }); expect(resp.status).toBe(400); }); - it('should return 400 for requests with an invalid url parameter', async () => { + it('should return 400 for requests with an invalid url parameter', async ({ + expect, + }) => { const url = new URL(baseUrl); url.searchParams.set('url', 'invalid'); diff --git a/src/utils/__tests__/__snapshots__/createLinkCard.test.ts.snap b/src/utils/__tests__/__snapshots__/createLinkCard.test.ts.snap new file mode 100644 index 0000000..de1305c --- /dev/null +++ b/src/utils/__tests__/__snapshots__/createLinkCard.test.ts.snap @@ -0,0 +1,87 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`createLinkCardFromHtml() > should return a LinkCard object #{1} 1`] = ` +{ + "description": undefined, + "faviconUrl": "https://link-card.example/favicon.ico", + "ogImageUrl": undefined, + "title": undefined, + "url": "https://link-card.example/article/cat", +} +`; + +exports[`createLinkCardFromHtml() > should return a LinkCard object #{2} 1`] = ` +{ + "description": "私はその人を常に先生と呼んでいた。", + "faviconUrl": "https://link-card.example/static/favicon.png", + "ogImageUrl": undefined, + "title": "こころ - 夏目漱石", + "url": "https://link-card.example/article/kokoro", +} +`; + +exports[`createLinkCardFromHtml() > should return a LinkCard object #{3} 1`] = ` +{ + "description": "私はその人を常に先生と呼んでいた。だからここでもただ先生と書くだけで本名は打ち明けない。", + "faviconUrl": "https://link-card.example/article/images/favicon.png", + "ogImageUrl": "https://link-card.example/static/og.png", + "title": "こころ", + "url": "https://link-card.example/article/kokoro/detail.html", +} +`; + +exports[`createLinkCardFromUrl() > should return a LinkCard object for http://example.com/ 1`] = ` +{ + "description": undefined, + "faviconUrl": "http://example.com/favicon.ico", + "ogImageUrl": undefined, + "title": "Example Domain", + "url": "http://example.com/", +} +`; + +exports[`createLinkCardFromUrl() > should return a LinkCard object for http://example.invalid/ 1`] = ` +{ + "url": "http://example.invalid/", +} +`; + +exports[`createLinkCardFromUrl() > should return a LinkCard object for https://ogp.me/ 1`] = ` +{ + "description": "The Open Graph protocol enables any web page to become a rich object in a social graph.", + "faviconUrl": "https://ogp.me/favicon.ico", + "ogImageUrl": "https://ogp.me/logo.png", + "title": "Open Graph protocol", + "url": "https://ogp.me/", +} +`; + +exports[`createLinkCardFromUrl() > should return a LinkCard object for https://ogp.me/foobarbaz 1`] = ` +{ + "description": undefined, + "faviconUrl": "https://ogp.me/favicon.ico", + "ogImageUrl": undefined, + "title": undefined, + "url": "https://ogp.me/foobarbaz", +} +`; + +exports[`createLinkCardFromUrl() > should return a LinkCard object for https://ogp.me/logo.png 1`] = ` +{ + "description": undefined, + "faviconUrl": "https://ogp.me/favicon.ico", + "ogImageUrl": undefined, + "title": undefined, + "url": "https://ogp.me/logo.png", +} +`; + +exports[`createLinkCardFromUrl() > should return a LinkCard object for https://www.w3.org/ 1`] = ` +{ + "description": "The World Wide Web Consortium (W3C) develops standards and guidelines to help everyone build a web based on the principles of accessibility, internationalization, privacy and security.", + "faviconUrl": "https://www.w3.org/favicon.ico", + "ogImageUrl": "https://www.w3.org/assets/website-2021/images/w3c-opengraph-image.png", + "title": "W3C", + "url": "https://www.w3.org/", +} +`; diff --git a/src/utils/__tests__/createLinkCard.test.ts b/src/utils/__tests__/createLinkCard.test.ts index 7cf1fb6..91ebdab 100644 --- a/src/utils/__tests__/createLinkCard.test.ts +++ b/src/utils/__tests__/createLinkCard.test.ts @@ -1,5 +1,4 @@ -import { describe, expect, it } from 'vitest'; -import { type LinkCard } from '@/types/LinkCard'; +import { describe, it } from 'vitest'; import { createLinkCardFromHtml, createLinkCardFromUrl, @@ -8,79 +7,20 @@ import { describe.concurrent( 'createLinkCardFromUrl()', () => { - it('should return a LinkCard object for http://example.com/', async () => { - expect( - await createLinkCardFromUrl(new URL('http://example.com/')), - ).toStrictEqual({ - url: 'http://example.com/', - title: 'Example Domain', - description: undefined, - faviconUrl: 'http://example.com/favicon.ico', - ogImageUrl: undefined, - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://ogp.me/', async () => { - expect( - await createLinkCardFromUrl(new URL('https://ogp.me/')), - ).toStrictEqual({ - url: 'https://ogp.me/', - title: 'Open Graph protocol', - description: - 'The Open Graph protocol enables any web page to become a rich object in a social graph.', - faviconUrl: 'https://ogp.me/favicon.ico', - ogImageUrl: 'https://ogp.me/logo.png', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://www.w3.org/', async () => { - expect( - await createLinkCardFromUrl(new URL('https://www.w3.org/')), - ).toStrictEqual({ - url: 'https://www.w3.org/', - title: 'W3C', - description: - 'The World Wide Web Consortium (W3C) develops standards and guidelines to help everyone build a web based on the principles of accessibility, internationalization, privacy and security.', - faviconUrl: 'https://www.w3.org/favicon.ico', - ogImageUrl: - 'https://www.w3.org/assets/website-2021/images/w3c-opengraph-image.png', - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://ogp.me/foobarbaz', async () => { - // Not Found - expect( - await createLinkCardFromUrl(new URL('https://ogp.me/foobarbaz')), - ).toStrictEqual({ - url: 'https://ogp.me/foobarbaz', - title: undefined, - description: undefined, - faviconUrl: 'https://ogp.me/favicon.ico', - ogImageUrl: undefined, - } satisfies LinkCard); - }); - - it('should return a LinkCard object for https://ogp.me/logo.png', async () => { - // Not HTML - expect( - await createLinkCardFromUrl(new URL('https://ogp.me/logo.png')), - ).toStrictEqual({ - url: 'https://ogp.me/logo.png', - title: undefined, - description: undefined, - faviconUrl: 'https://ogp.me/favicon.ico', - ogImageUrl: undefined, - } satisfies LinkCard); - }); + const cases = [ + 'http://example.com/', + 'https://ogp.me/', + 'https://www.w3.org/', + 'https://ogp.me/foobarbaz', + 'https://ogp.me/logo.png', + 'http://example.invalid/', + ] as const satisfies readonly string[]; - it('should return a LinkCard object for http://example.invalid/', async () => { - // Network Error - expect( - await createLinkCardFromUrl(new URL('http://example.invalid/')), - ).toStrictEqual({ - url: 'http://example.invalid/', - } satisfies LinkCard); - }); + for (const url of cases) { + it(`should return a LinkCard object for ${url}`, async ({ expect }) => { + expect(await createLinkCardFromUrl(new URL(url))).toMatchSnapshot(); + }); + } }, { timeout: 10000, @@ -89,67 +29,43 @@ describe.concurrent( ); describe('createLinkCardFromHtml()', () => { - it('should return a LinkCard object', () => { - expect( - createLinkCardFromHtml( - '', - new URL('https://link-card.example/article/cat'), - ), - ).toStrictEqual({ - url: 'https://link-card.example/article/cat', - title: undefined, - description: undefined, - faviconUrl: 'https://link-card.example/favicon.ico', - ogImageUrl: undefined, - } satisfies LinkCard); - - expect( - createLinkCardFromHtml( - ` - - - - - - こころ - 夏目漱石 - - - `, - new URL('https://link-card.example/article/kokoro'), - ), - ).toStrictEqual({ - url: 'https://link-card.example/article/kokoro', - title: 'こころ - 夏目漱石', - description: '私はその人を常に先生と呼んでいた。', - faviconUrl: 'https://link-card.example/static/favicon.png', - ogImageUrl: undefined, - } satisfies LinkCard); + const cases = [ + ['', 'https://link-card.example/article/cat'], + [ + ` + + + + + + こころ - 夏目漱石 + + + `, + 'https://link-card.example/article/kokoro', + ], + [ + ` + + + + + + + こころ - 夏目漱石 + + + + + + `, + 'https://link-card.example/article/kokoro/detail.html', + ], + ] as const satisfies ReadonlyArray; - expect( - createLinkCardFromHtml( - ` - - - - - - - こころ - 夏目漱石 - - - - - - `, - new URL('https://link-card.example/article/kokoro/detail.html'), - ), - ).toStrictEqual({ - url: 'https://link-card.example/article/kokoro/detail.html', - title: 'こころ', - description: - '私はその人を常に先生と呼んでいた。だからここでもただ先生と書くだけで本名は打ち明けない。', - faviconUrl: 'https://link-card.example/article/images/favicon.png', - ogImageUrl: 'https://link-card.example/static/og.png', - } satisfies LinkCard); - }); + for (const [i, [html, url]] of cases.entries()) { + it(`should return a LinkCard object #{${i + 1}}`, ({ expect }) => { + expect(createLinkCardFromHtml(html, new URL(url))).toMatchSnapshot(); + }); + } });