Skip to content

Commit

Permalink
test: handle additional edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Oct 8, 2024
1 parent cae0e2c commit bef5316
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/css/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function extractFontFaceData(css: string, family?: string): FontFaceData[
const fontFaces: FontFaceData[] = []

for (const node of findAll(parse(css), node => node.type === 'Atrule' && node.name === 'font-face')) {
/* istanbul ignore block */
/* v8 ignore next 3 */
if (node.type !== 'Atrule' || node.name !== 'font-face') {
continue
}
Expand Down
3 changes: 1 addition & 2 deletions src/providers/adobe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ interface ProviderOption {
id: string[] | string
}

const fontAPI = $fetch.create({ baseURL: 'https://typekit.com' })
const fontCSSAPI = $fetch.create({ baseURL: 'https://use.typekit.net' })

async function getAdobeFontMeta(id: string): Promise<AdobeFontKit> {
const { kit } = await fontAPI<{ kit: AdobeFontKit }>(`/api/v1/json/kits/${id}/published`, { responseType: 'json' })
const { kit } = await $fetch<{ kit: AdobeFontKit }>(`https://typekit.com/api/v1/json/kits/${id}/published`, { responseType: 'json' })
return kit
}

Expand Down
39 changes: 37 additions & 2 deletions test/providers/adobe.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, it, vi } from 'vitest'
import { createUnifont, providers } from '../../src'
import { pickUniqueBy, sanitizeFontSource } from '../utils'
import { mockFetchReturn, pickUniqueBy, sanitizeFontSource } from '../utils'

describe('adobe', () => {
it('correctly types options for adobe provider', async () => {
Expand All @@ -11,8 +11,43 @@ describe('adobe', () => {
expect(true).toBe(true)
})

it('handles empty id', async () => {
// @ts-expect-error id is required
await createUnifont([providers.adobe({})])
})

it('handles string id', async () => {
const unifont = await createUnifont([providers.adobe({ id: 'sij5ufr' })])
const { fonts } = await unifont.resolveFont('Aleo')
expect(fonts.length).toBeGreaterThan(0)
})

it('handles invalid JSON from adobe api', async () => {
const error = vi.spyOn(console, 'error').mockImplementation(() => {})

const unifont = await createUnifont([providers.adobe({ id: ['bob'] })])

const restoreFetch = mockFetchReturn(/^https:\/\/typekit.com\/api\//, () => {
return { json: () => Promise.resolve({ kit: '' }) }
})
expect(await unifont.resolveFont('Aleo').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)

expect(error).toHaveBeenCalledWith(
'Could not initialize provider `adobe`. `unifont` will not be able to process fonts provided by this provider.',
expect.objectContaining({}),
)

restoreFetch()
})

it('works', async () => {
const unifont = await createUnifont([providers.adobe({ id: ['sij5ufr', 'grx7wdj'] })])
expect(await unifont.resolveFont('NonExistent Font').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
expect(await unifont.resolveFont('Aleo', {
weights: ['1100'],
// @ts-expect-error invalid style
styles: ['foo'],
}).then(r => r.fonts)).toMatchInlineSnapshot(`[]`)

const { fonts: aleo } = await unifont.resolveFont('Aleo')

Expand Down
2 changes: 2 additions & 0 deletions test/providers/bunny.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { createUnifont, providers } from '../../src'
describe('bunny', () => {
it('works', async () => {
const unifont = await createUnifont([providers.bunny()])
expect(await unifont.resolveFont('NonExistent Font').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
expect(await unifont.resolveFont('Abel', { weights: ['1100'] }).then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
const { fonts } = await unifont.resolveFont('Abel')
expect(fonts).toMatchInlineSnapshot(`
[
Expand Down
8 changes: 7 additions & 1 deletion test/providers/fontshare.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { sanitizeFontSource } from '../utils'
describe('fontshare', () => {
it('works', async () => {
const unifont = await createUnifont([providers.fontshare()])
const { fonts } = await unifont.resolveFont('Satoshi')
expect(await unifont.resolveFont('NonExistent Font').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
expect(await unifont.resolveFont('Satoshi', { weights: ['1100'] }).then(r => r.fonts)).toMatchInlineSnapshot(`[]`)

const { fonts: normal } = await unifont.resolveFont('Panchang')
expect(normal.every(f => f.style === 'normal')).toBe(true)

const { fonts } = await unifont.resolveFont('Satoshi', { styles: ['normal'] })
expect(sanitizeFontSource(fonts)).toMatchInlineSnapshot(`
[
{
Expand Down
179 changes: 178 additions & 1 deletion test/providers/fontsource.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { describe, expect, it } from 'vitest'
import { describe, expect, it, vi } from 'vitest'
import { createUnifont, providers } from '../../src'
import { mockFetchReturn } from '../utils'

describe('fontsource', () => {
it('works', async () => {
const unifont = await createUnifont([providers.fontsource()])
expect(await unifont.resolveFont('NonExistent Font').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
expect(await unifont.resolveFont('Roboto Mono', { weights: ['1100'] }).then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
const { fonts } = await unifont.resolveFont('Roboto Mono')

expect(fonts).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -679,4 +682,178 @@ describe('fontsource', () => {
]
`)
})

it('handles default subsets', async () => {
const unifont = await createUnifont([providers.fontsource()])
const { fonts } = await unifont.resolveFont('Roboto Mono', { subsets: undefined })
expect(fonts).toMatchInlineSnapshot(`
[
{
"src": [
{
"format": "woff2",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono:vf@latest/latin-wght-normal.woff2",
},
],
"style": "normal",
"unicodeRange": [
"U+0000-00FF",
"U+0131",
"U+0152-0153",
"U+02BB-02BC",
"U+02C6",
"U+02DA",
"U+02DC",
"U+0304",
"U+0308",
"U+0329",
"U+2000-206F",
"U+2074",
"U+20AC",
"U+2122",
"U+2191",
"U+2193",
"U+2212",
"U+2215",
"U+FEFF",
"U+FFFD",
],
"weight": [
100,
700,
],
},
{
"src": [
{
"format": "woff2",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono@latest/latin-400-normal.woff2",
},
{
"format": "woff",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono@latest/latin-400-normal.woff",
},
{
"format": "ttf",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono@latest/latin-400-normal.ttf",
},
],
"style": "normal",
"unicodeRange": [
"U+0000-00FF",
"U+0131",
"U+0152-0153",
"U+02BB-02BC",
"U+02C6",
"U+02DA",
"U+02DC",
"U+0304",
"U+0308",
"U+0329",
"U+2000-206F",
"U+2074",
"U+20AC",
"U+2122",
"U+2191",
"U+2193",
"U+2212",
"U+2215",
"U+FEFF",
"U+FFFD",
],
"weight": "400",
},
{
"src": [
{
"format": "woff2",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono:vf@latest/latin-wght-italic.woff2",
},
],
"style": "italic",
"unicodeRange": [
"U+0000-00FF",
"U+0131",
"U+0152-0153",
"U+02BB-02BC",
"U+02C6",
"U+02DA",
"U+02DC",
"U+0304",
"U+0308",
"U+0329",
"U+2000-206F",
"U+2074",
"U+20AC",
"U+2122",
"U+2191",
"U+2193",
"U+2212",
"U+2215",
"U+FEFF",
"U+FFFD",
],
"weight": [
100,
700,
],
},
{
"src": [
{
"format": "woff2",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono@latest/latin-400-italic.woff2",
},
{
"format": "woff",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono@latest/latin-400-italic.woff",
},
{
"format": "ttf",
"url": "https://cdn.jsdelivr.net/fontsource/fonts/roboto-mono@latest/latin-400-italic.ttf",
},
],
"style": "italic",
"unicodeRange": [
"U+0000-00FF",
"U+0131",
"U+0152-0153",
"U+02BB-02BC",
"U+02C6",
"U+02DA",
"U+02DC",
"U+0304",
"U+0308",
"U+0329",
"U+2000-206F",
"U+2074",
"U+20AC",
"U+2122",
"U+2191",
"U+2193",
"U+2212",
"U+2215",
"U+FEFF",
"U+FFFD",
],
"weight": "400",
},
]
`)
})

it('should handle failure to fetch', async () => {
const error = vi.spyOn(console, 'error').mockImplementation(() => {})
const restoreFetch = mockFetchReturn(/variable/, () => {
throw new Error('Failed to fetch')
})

const unifont = await createUnifont([providers.fontsource()])
await unifont.resolveFont('Roboto Mono')

expect(error).toHaveBeenCalledWith('Could not download variable axes metadata for `Roboto Mono` from `fontsource`. `unifont` will not be able to inject variable axes for Roboto Mono.')

error.mockRestore()
restoreFetch()
})
})
1 change: 1 addition & 0 deletions test/providers/google.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe('google', () => {

it('works', async () => {
const unifont = await createUnifont([providers.google()])
expect(await unifont.resolveFont('NonExistent Font').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)

const { fonts } = await unifont.resolveFont('Poppins')

Expand Down
1 change: 1 addition & 0 deletions test/providers/googleicons.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { sanitizeFontSource } from '../utils'
describe('googleicons', () => {
it('works', async () => {
const unifont = await createUnifont([providers.googleicons()])
expect(await unifont.resolveFont('Poppins').then(r => r.fonts)).toMatchInlineSnapshot(`[]`)
const { fonts } = await unifont.resolveFont('Material Symbols Outlined')
const { fonts: legacy } = await unifont.resolveFont('Material Icons Outlined')
expect(sanitizeFontSource(fonts)).toMatchInlineSnapshot(`
Expand Down
15 changes: 15 additions & 0 deletions test/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,18 @@ export function sanitizeFontSource(data: FontFaceData[]) {
})),
}))
}

export function mockFetchReturn(condition: RegExp, value: () => unknown) {
const originalFetch = globalThis.fetch

globalThis.fetch = (...args) => {
if (condition.test(args[0] as string)) {
return value() as any
}
return originalFetch(...args)
}

return () => {
globalThis.fetch = originalFetch
}
}

0 comments on commit bef5316

Please sign in to comment.