-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
244 additions
and
331 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,125 +1,102 @@ | ||
import { resolve } from 'path' | ||
import * as fs from 'fs' | ||
import honoSitemapPlugin, { | ||
getFrequency, | ||
getPriority, | ||
getValueForUrl, | ||
isFilePathMatch, | ||
processRoutes, | ||
validateOptions, | ||
} from './sitemap' | ||
|
||
vi.mock('fs', () => ({ | ||
writeFileSync: vi.fn(), | ||
})) | ||
|
||
describe('honoSitemapPlugin', () => { | ||
beforeEach(() => { | ||
vi.resetAllMocks() | ||
import type { SitemapOptions } from './sitemap' | ||
import sitemap from './sitemap' | ||
import { Hono } from 'hono' | ||
|
||
// モックHonoアプリケーションを作成 | ||
const createMockApp = (routes: string[]) => { | ||
const app = new Hono() | ||
routes.forEach((route) => { | ||
app.get(route, () => new Response('OK')) | ||
}) | ||
return app | ||
} | ||
describe('sitemap', () => { | ||
it('sitemap generator creates valid XML', async () => { | ||
const app = createMockApp(['/', '/about', '/contact']) | ||
const options: SitemapOptions = { | ||
app, | ||
hostname: 'https://example.com', | ||
} | ||
|
||
it('should create a plugin with default options', () => { | ||
const plugin = honoSitemapPlugin() | ||
expect(plugin.name).toBe('vite-plugin-hono-sitemap') | ||
expect(plugin.apply).toBe('build') | ||
}) | ||
const result = await sitemap(options) | ||
|
||
it('should transform matching files', () => { | ||
const plugin = honoSitemapPlugin() | ||
// @ts-expect-error transform is private | ||
const result = plugin.transform('', '/app/routes/index.tsx') | ||
expect(result).toEqual({ code: '', map: null }) | ||
expect(result.status).toBe(200) | ||
expect(result.headers['Content-Type']).toBe('application/xml') | ||
expect(result.data).toContain('<?xml version="1.0" encoding="UTF-8"?>') | ||
expect(result.data).toContain('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">') | ||
expect(result.data).toContain('<loc>https://example.com/</loc>') | ||
expect(result.data).toContain('<loc>https://example.com/about/</loc>') | ||
expect(result.data).toContain('<loc>https://example.com/contact/</loc>') | ||
}) | ||
|
||
it('should generate sitemap on buildEnd', () => { | ||
const plugin = honoSitemapPlugin({ hostname: 'https://example.com' }) | ||
// @ts-expect-error transform is private | ||
plugin.transform('', '/app/routes/index.tsx') | ||
// @ts-expect-error transform is private | ||
plugin.transform('', '/app/routes/about.tsx') | ||
// @ts-expect-error buildEnd is private | ||
plugin.buildEnd() | ||
|
||
expect(fs.writeFileSync).toHaveBeenCalledWith( | ||
resolve(process.cwd(), 'dist', 'sitemap.xml'), | ||
expect.stringContaining('<loc>https://example.com/</loc>') | ||
) | ||
expect(fs.writeFileSync).toHaveBeenCalledWith( | ||
resolve(process.cwd(), 'dist', 'sitemap.xml'), | ||
expect.stringContaining('<loc>https://example.com/about/</loc>') | ||
) | ||
}) | ||
}) | ||
it('sitemap generator respects exclude option', async () => { | ||
const app = createMockApp(['/', '/about', '/contact', '/admin']) | ||
const options: SitemapOptions = { | ||
app, | ||
hostname: 'https://example.com', | ||
exclude: ['/admin'], | ||
} | ||
|
||
describe('isFilePathMatch', () => { | ||
it('should match valid file paths', () => { | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/index.tsx', [])).toBe(true) | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/about/index.tsx', [])).toBe(true) | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/.well-known/security.txt.tsx', [])).toBe( | ||
true | ||
) | ||
}) | ||
const result = await sitemap(options) | ||
|
||
it('should not match invalid file paths', () => { | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/$id.tsx', [])).toBe(false) | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/test.spec.tsx', [])).toBe(false) | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/_middleware.tsx', [])).toBe(false) | ||
expect(result.data).not.toContain('<loc>https://example.com/admin/</loc>') | ||
}) | ||
|
||
it('should exclude specified paths', () => { | ||
expect(isFilePathMatch('/Users/abc/repo/app/routes/admin/index.tsx', ['/admin'])).toBe(false) | ||
}) | ||
}) | ||
it('sitemap generator uses custom frequency and priority', async () => { | ||
const app = createMockApp(['/', '/about']) | ||
const options: SitemapOptions = { | ||
app, | ||
hostname: 'https://example.com', | ||
frequency: { | ||
'/': 'daily', | ||
}, | ||
priority: { | ||
'/': '1.0', | ||
}, | ||
} | ||
|
||
describe('validateOptions', () => { | ||
it('should throw error for invalid hostname', () => { | ||
expect(() => validateOptions({ hostname: 'example.com' })).toThrow() | ||
}) | ||
const result = await sitemap(options) | ||
|
||
it('should throw error for invalid priority', () => { | ||
expect(() => validateOptions({ priority: { '/': '1.5' } })).toThrow() | ||
expect(result.data).toContain('<changefreq>daily</changefreq>') | ||
expect(result.data).toContain('<priority>1.0</priority>') | ||
}) | ||
|
||
it('should throw error for invalid frequency', () => { | ||
expect(() => validateOptions({ frequency: { '/': 'biweekly' as any } })).toThrow() | ||
}) | ||
}) | ||
it('sitemap generator throws error for invalid priority', async () => { | ||
const app = createMockApp(['/', '/about']) | ||
const options: SitemapOptions = { | ||
app, | ||
hostname: 'https://example.com', | ||
priority: { | ||
'/': '2.0', // 無効な優先度 | ||
}, | ||
} | ||
|
||
describe('processRoutes', () => { | ||
it('should process routes correctly', () => { | ||
const files = ['/app/routes/index.tsx', '/app/routes/about.tsx'] | ||
const result = processRoutes(files, 'https://example.com', '/app/routes', {}, {}) | ||
expect(result).toHaveLength(2) | ||
expect(result[0].url).toBe('https://example.com') | ||
expect(result[1].url).toBe('https://example.com/about') | ||
await expect(sitemap(options)).rejects.toThrow('Invalid priority value') | ||
}) | ||
}) | ||
|
||
describe('getFrequency', () => { | ||
it('should return correct frequency', () => { | ||
expect(getFrequency('/', { '/': 'daily' })).toBe('daily') | ||
expect(getFrequency('/about', { '/about': 'monthly' })).toBe('monthly') | ||
expect(getFrequency('/unknown', {})).toBe('weekly') | ||
}) | ||
}) | ||
it('sitemap generator throws error for invalid frequency', async () => { | ||
const app = createMockApp(['/', '/about']) | ||
const options: SitemapOptions = { | ||
app, | ||
hostname: 'https://example.com', | ||
frequency: { | ||
'/': 'annually' as any, // 無効な頻度 | ||
}, | ||
} | ||
|
||
describe('getPriority', () => { | ||
it('should return correct priority', () => { | ||
expect(getPriority('/', { '/': '1.0' })).toBe('1.0') | ||
expect(getPriority('/about', { '/about': '0.8' })).toBe('0.8') | ||
expect(getPriority('/unknown', {})).toBe('0.5') | ||
await expect(sitemap(options)).rejects.toThrow('Invalid frequency value') | ||
}) | ||
}) | ||
|
||
describe('getValueForUrl', () => { | ||
it('should return correct value for URL patterns', () => { | ||
const patterns = { | ||
'/': 'home', | ||
'/blog/*': 'blog', | ||
'/about': 'about', | ||
it('sitemap generator uses default values when not provided', async () => { | ||
const app = createMockApp(['/', '/about']) | ||
const options: SitemapOptions = { | ||
app, | ||
} | ||
expect(getValueForUrl('/', patterns, 'default')).toBe('home') | ||
expect(getValueForUrl('/blog/post-1', patterns, 'default')).toBe('blog') | ||
expect(getValueForUrl('/contact', patterns, 'default')).toBe('default') | ||
|
||
const result = await sitemap(options) | ||
|
||
expect(result.data).toContain('<loc>http://localhost:5173/</loc>') | ||
expect(result.data).toContain('<changefreq>weekly</changefreq>') | ||
expect(result.data).toContain('<priority>0.5</priority>') | ||
}) | ||
}) |
Oops, something went wrong.