Compare commits

...

1 Commits

Author SHA1 Message Date
coderabbitai[bot]
81965d4c5f CodeRabbit Generated Unit Tests: Add unit tests for PR changes 2026-05-07 18:19:20 +00:00
3 changed files with 236 additions and 7 deletions

View File

@@ -0,0 +1,85 @@
import { describe, it, expect } from 'vitest'
import { t, hasKey, translationKeys } from './translations'
describe('translations', () => {
describe('pricing.plan.creator keys', () => {
it('feature1 key exists with correct English text', () => {
expect(hasKey('pricing.plan.creator.feature1')).toBe(true)
expect(t('pricing.plan.creator.feature1')).toBe('Import your own LoRAs')
})
it('feature1 key returns correct zh-CN translation', () => {
expect(t('pricing.plan.creator.feature1', 'zh-CN')).toBe(
'导入你自己的 LoRA'
)
})
it('feature2 key does not exist (removed concurrent API jobs entry)', () => {
expect(hasKey('pricing.plan.creator.feature2')).toBe(false)
})
it('translationKeys array does not include removed creator feature2', () => {
expect(translationKeys).not.toContain('pricing.plan.creator.feature2')
})
})
describe('pricing.plan.pro keys', () => {
it('feature1 key exists with correct English text', () => {
expect(hasKey('pricing.plan.pro.feature1')).toBe(true)
expect(t('pricing.plan.pro.feature1')).toBe(
'Longer workflow runtime (up to 1 hour)'
)
})
it('feature1 key returns correct zh-CN translation', () => {
expect(t('pricing.plan.pro.feature1', 'zh-CN')).toBe(
'更长工作流运行时长(最长 1 小时)'
)
})
it('feature2 key does not exist (removed concurrent API jobs entry)', () => {
expect(hasKey('pricing.plan.pro.feature2')).toBe(false)
})
it('translationKeys array does not include removed pro feature2', () => {
expect(translationKeys).not.toContain('pricing.plan.pro.feature2')
})
})
describe('t() function defaults', () => {
it('defaults locale to en when not provided', () => {
expect(t('pricing.plan.creator.feature1')).toBe(
t('pricing.plan.creator.feature1', 'en')
)
})
it('falls back to en when locale translation is missing', () => {
// All keys in this file have both en and zh-CN, but the fallback
// behaviour is part of the contract: t() should return en if the
// locale value is nullish.
const englishValue = t('pricing.plan.pro.feature1', 'en')
expect(englishValue).toBe('Longer workflow runtime (up to 1 hour)')
})
})
describe('hasKey()', () => {
it('returns true for known keys', () => {
expect(hasKey('hero.title')).toBe(true)
expect(hasKey('pricing.plan.creator.feature1')).toBe(true)
expect(hasKey('pricing.plan.pro.feature1')).toBe(true)
})
it('returns false for completely unknown keys', () => {
expect(hasKey('nonexistent.key')).toBe(false)
expect(hasKey('')).toBe(false)
})
it('returns false for the two removed concurrent-API-jobs keys', () => {
// Regression guard: these keys carried "3 concurrent API jobs" and
// "5 concurrent API jobs" copy that was intentionally removed.
expect(hasKey('pricing.plan.creator.feature2')).toBe(false)
expect(hasKey('pricing.plan.pro.feature2')).toBe(false)
})
})
})

View File

@@ -133,27 +133,48 @@ test.describe('AssetHelper', () => {
expect(data.assets[0].id).toBe(STABLE_CHECKPOINT.id)
})
test('GET /assets filters by exclude_tags', async ({
test('GET /assets does not filter by exclude_tags (parameter removed)', async ({
comfyPage,
assetApi
}) => {
// Regression guard: exclude_tags filtering was removed from handleListAssets
// and getFilteredAssets. Passing exclude_tags must NOT exclude any assets —
// all assets matching include_tags (or all assets when include_tags is
// absent) should be returned regardless of the exclude_tags param.
assetApi.configure(
withAsset(STABLE_INPUT_IMAGE),
withAsset({
...STABLE_INPUT_IMAGE,
id: 'missing-input',
tags: ['input', 'missing']
id: 'tagged-input',
tags: ['input', 'extra-tag']
})
)
await assetApi.mock()
const { body } = await assetApi.fetch(
`${comfyPage.url}/api/assets?include_tags=input,&exclude_tags= missing,`
`${comfyPage.url}/api/assets?include_tags=input&exclude_tags=extra-tag`
)
const data = body as { assets: Array<{ id: string }> }
expect(data.assets.map((asset) => asset.id)).toEqual([
STABLE_INPUT_IMAGE.id
])
// Both assets share the 'input' include_tag. With exclude_tags removed,
// neither should be hidden — the response must contain both.
expect(data.assets).toHaveLength(2)
})
test('GET /assets with empty include_tags returns all assets', async ({
comfyPage,
assetApi
}) => {
// When include_tags is absent or empty the helper returns the full store.
assetApi.configure(
withAsset(STABLE_CHECKPOINT),
withAsset(STABLE_LORA),
withAsset(STABLE_INPUT_IMAGE)
)
await assetApi.mock()
const { body } = await assetApi.fetch(`${comfyPage.url}/api/assets`)
const data = body as { assets: Array<{ id: string }> }
expect(data.assets).toHaveLength(3)
})
test('GET /assets/:id returns single asset or 404', async ({

View File

@@ -0,0 +1,123 @@
import { test, expect } from '@playwright/test'
import { getMimeType } from '@e2e/fixtures/utils/mimeTypeUtil'
// These tests verify the current state of getMimeType after audio MIME types
// (mp3, flac, ogg, opus) were removed in favour of 'application/octet-stream'.
test.describe('getMimeType', { tag: '@unit' }, () => {
test.describe('image formats (still supported)', () => {
test('returns image/png for .png files', () => {
expect(getMimeType('photo.png')).toBe('image/png')
})
test('returns image/jpeg for .jpg files', () => {
expect(getMimeType('photo.jpg')).toBe('image/jpeg')
})
test('returns image/jpeg for .jpeg files', () => {
expect(getMimeType('photo.jpeg')).toBe('image/jpeg')
})
test('returns image/webp for .webp files', () => {
expect(getMimeType('image.webp')).toBe('image/webp')
})
test('returns image/svg+xml for .svg files', () => {
expect(getMimeType('icon.svg')).toBe('image/svg+xml')
})
test('returns image/avif for .avif files', () => {
expect(getMimeType('image.avif')).toBe('image/avif')
})
})
test.describe('video formats (still supported)', () => {
test('returns video/webm for .webm files', () => {
expect(getMimeType('video.webm')).toBe('video/webm')
})
test('returns video/mp4 for .mp4 files', () => {
expect(getMimeType('video.mp4')).toBe('video/mp4')
})
})
test.describe('other formats (still supported)', () => {
test('returns application/json for .json files', () => {
expect(getMimeType('data.json')).toBe('application/json')
})
test('returns model/gltf-binary for .glb files', () => {
expect(getMimeType('model.glb')).toBe('model/gltf-binary')
})
})
test.describe('audio formats (no longer supported — regression guard)', () => {
// These formats were explicitly removed from getMimeType. They must now
// fall through to the generic octet-stream default, not return audio/*
// MIME types.
test('returns application/octet-stream for .mp3 files', () => {
expect(getMimeType('audio.mp3')).toBe('application/octet-stream')
})
test('returns application/octet-stream for .flac files', () => {
expect(getMimeType('audio.flac')).toBe('application/octet-stream')
})
test('returns application/octet-stream for .ogg files', () => {
expect(getMimeType('audio.ogg')).toBe('application/octet-stream')
})
test('returns application/octet-stream for .opus files', () => {
expect(getMimeType('audio.opus')).toBe('application/octet-stream')
})
})
test.describe('unknown / fallback extensions', () => {
test('returns application/octet-stream for unknown extensions', () => {
expect(getMimeType('file.xyz')).toBe('application/octet-stream')
})
test('returns application/octet-stream for files with no extension', () => {
expect(getMimeType('README')).toBe('application/octet-stream')
})
test('returns application/octet-stream for empty string', () => {
expect(getMimeType('')).toBe('application/octet-stream')
})
})
test.describe('case insensitivity', () => {
test('handles uppercase .PNG extension', () => {
expect(getMimeType('IMAGE.PNG')).toBe('image/png')
})
test('handles uppercase .JPG extension', () => {
expect(getMimeType('PHOTO.JPG')).toBe('image/jpeg')
})
test('handles uppercase .MP4 extension', () => {
expect(getMimeType('VIDEO.MP4')).toBe('video/mp4')
})
test('handles uppercase .WEBM extension', () => {
expect(getMimeType('VIDEO.WEBM')).toBe('video/webm')
})
// Boundary case: confirm audio formats are not supported regardless of case
test('returns application/octet-stream for uppercase .MP3 extension', () => {
expect(getMimeType('AUDIO.MP3')).toBe('application/octet-stream')
})
})
test.describe('filenames with multiple dots', () => {
test('resolves extension from last segment', () => {
expect(getMimeType('my.file.name.png')).toBe('image/png')
})
test('returns octet-stream when final segment is not a known extension', () => {
expect(getMimeType('archive.tar.gz')).toBe('application/octet-stream')
})
})
})