navbar样式debug #52
Merged
hnu202326010204
merged 7 commits from yangyixuan_branch into develop 6 days ago
@ -1,267 +0,0 @@
|
||||
/**
|
||||
* Property-Based Tests for Subpage Style Consistency
|
||||
*
|
||||
* Feature: ui-consistency-fix
|
||||
* Requirements: 5.1-5.7
|
||||
*
|
||||
* Tests that subpages use Kinetic Typography (--kt-*) variables
|
||||
* instead of hand-drawn style (--hd-*) variables.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import * as fc from 'fast-check'
|
||||
import {
|
||||
KT_VARIABLE_PREFIX,
|
||||
HD_VARIABLE_PREFIX,
|
||||
REQUIRED_KT_VARIABLES,
|
||||
BILINGUAL_TITLE_STRUCTURE,
|
||||
isKTVariable,
|
||||
isHDVariable,
|
||||
extractCSSVariables,
|
||||
validateCSSVariables,
|
||||
isValidBilingualTitle,
|
||||
validateSubpageStyle
|
||||
} from './subpageStyles'
|
||||
|
||||
describe('Subpage Style Consistency Tests', () => {
|
||||
/**
|
||||
* Requirements: 5.1 - Subpages should use --kt-* variables
|
||||
*/
|
||||
describe('CSS Variable Prefix Detection', () => {
|
||||
it('isKTVariable should return true for --kt-* prefixed variables', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.string({ minLength: 1, maxLength: 20 }).filter(s => /^[a-zA-Z0-9-]+$/.test(s)),
|
||||
(suffix) => {
|
||||
const variable = `${KT_VARIABLE_PREFIX}${suffix}`
|
||||
expect(isKTVariable(variable)).toBe(true)
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
|
||||
it('isKTVariable should return false for non-kt variables', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.string().filter(s => !s.startsWith(KT_VARIABLE_PREFIX)),
|
||||
(variable) => {
|
||||
expect(isKTVariable(variable)).toBe(false)
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
it('isHDVariable should return true for --hd-* prefixed variables', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.string({ minLength: 1, maxLength: 20 }).filter(s => /^[a-zA-Z0-9-]+$/.test(s)),
|
||||
(suffix) => {
|
||||
const variable = `${HD_VARIABLE_PREFIX}${suffix}`
|
||||
expect(isHDVariable(variable)).toBe(true)
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
|
||||
it('isHDVariable should return false for non-hd variables', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.string().filter(s => !s.startsWith(HD_VARIABLE_PREFIX)),
|
||||
(variable) => {
|
||||
expect(isHDVariable(variable)).toBe(false)
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
|
||||
it('KT and HD variables should be mutually exclusive', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.string(),
|
||||
(variable) => {
|
||||
// A variable cannot be both KT and HD
|
||||
const isKT = isKTVariable(variable)
|
||||
const isHD = isHDVariable(variable)
|
||||
expect(isKT && isHD).toBe(false)
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Requirements: 5.1 - CSS variable extraction and validation
|
||||
*/
|
||||
describe('CSS Variable Extraction', () => {
|
||||
it('should extract all var() references from CSS', () => {
|
||||
const css = 'color: var(--kt-fg); background: var(--kt-bg);'
|
||||
const variables = extractCSSVariables(css)
|
||||
expect(variables).toContain('--kt-fg')
|
||||
expect(variables).toContain('--kt-bg')
|
||||
expect(variables.length).toBe(2)
|
||||
})
|
||||
|
||||
it('should return empty array for CSS without variables', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.string().filter(s => !s.includes('var(--')),
|
||||
(css) => {
|
||||
const variables = extractCSSVariables(css)
|
||||
expect(variables).toEqual([])
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
|
||||
it('should handle non-string input gracefully', () => {
|
||||
expect(extractCSSVariables(null)).toEqual([])
|
||||
expect(extractCSSVariables(undefined)).toEqual([])
|
||||
expect(extractCSSVariables(123)).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Requirements: 5.1 - Validate CSS uses only KT variables
|
||||
*/
|
||||
describe('CSS Variable Validation', () => {
|
||||
it('should mark CSS with only KT variables as valid', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.array(
|
||||
fc.string({ minLength: 1, maxLength: 10 }).filter(s => /^[a-zA-Z0-9-]+$/.test(s)),
|
||||
{ minLength: 1, maxLength: 5 }
|
||||
),
|
||||
(suffixes) => {
|
||||
const css = suffixes.map(s => `prop: var(--kt-${s});`).join(' ')
|
||||
const result = validateCSSVariables(css)
|
||||
expect(result.valid).toBe(true)
|
||||
expect(result.hdVariables).toEqual([])
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
|
||||
it('should mark CSS with HD variables as invalid', () => {
|
||||
const css = 'color: var(--hd-text); background: var(--kt-bg);'
|
||||
const result = validateCSSVariables(css)
|
||||
expect(result.valid).toBe(false)
|
||||
expect(result.hdVariables).toContain('--hd-text')
|
||||
})
|
||||
|
||||
it('should detect all HD variables in mixed CSS', () => {
|
||||
fc.assert(
|
||||
fc.property(
|
||||
fc.array(
|
||||
fc.string({ minLength: 1, maxLength: 10 }).filter(s => /^[a-zA-Z0-9-]+$/.test(s)),
|
||||
{ minLength: 1, maxLength: 3 }
|
||||
),
|
||||
(hdSuffixes) => {
|
||||
const css = hdSuffixes.map(s => `prop: var(--hd-${s});`).join(' ')
|
||||
const result = validateCSSVariables(css)
|
||||
expect(result.valid).toBe(false)
|
||||
expect(result.hdVariables.length).toBe(hdSuffixes.length)
|
||||
}
|
||||
),
|
||||
{ numRuns: 50 }
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Requirements: 5.2 - Bilingual title structure validation
|
||||
*/
|
||||
describe('Bilingual Title Structure', () => {
|
||||
it('should validate complete bilingual title structure', () => {
|
||||
const validStructure = { hasPrimaryTitle: true, hasSubtitle: true }
|
||||
expect(isValidBilingualTitle(validStructure)).toBe(true)
|
||||
})
|
||||
|
||||
it('should reject incomplete bilingual title structure', () => {
|
||||
expect(isValidBilingualTitle({ hasPrimaryTitle: true, hasSubtitle: false })).toBe(false)
|
||||
expect(isValidBilingualTitle({ hasPrimaryTitle: false, hasSubtitle: true })).toBe(false)
|
||||
expect(isValidBilingualTitle({ hasPrimaryTitle: false, hasSubtitle: false })).toBe(false)
|
||||
})
|
||||
|
||||
it('should handle invalid input gracefully', () => {
|
||||
expect(isValidBilingualTitle(null)).toBe(false)
|
||||
expect(isValidBilingualTitle(undefined)).toBe(false)
|
||||
expect(isValidBilingualTitle('string')).toBe(false)
|
||||
expect(isValidBilingualTitle(123)).toBe(false)
|
||||
})
|
||||
|
||||
it('BILINGUAL_TITLE_STRUCTURE should have required classes', () => {
|
||||
expect(BILINGUAL_TITLE_STRUCTURE.primaryClass).toBe('kt-subpage__title')
|
||||
expect(BILINGUAL_TITLE_STRUCTURE.subtitleClass).toBe('kt-subpage__title-en')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Requirements: 5.1-5.7 - Full subpage style validation
|
||||
*/
|
||||
describe('Subpage Style Validation', () => {
|
||||
it('should validate subpage with KT variables and bilingual title', () => {
|
||||
const subpage = {
|
||||
cssContent: 'color: var(--kt-fg); background: var(--kt-bg);',
|
||||
hasBilingualTitle: true
|
||||
}
|
||||
const result = validateSubpageStyle(subpage)
|
||||
expect(result.valid).toBe(true)
|
||||
expect(result.errors).toEqual([])
|
||||
})
|
||||
|
||||
it('should reject subpage with HD variables', () => {
|
||||
const subpage = {
|
||||
cssContent: 'color: var(--hd-text);',
|
||||
hasBilingualTitle: true
|
||||
}
|
||||
const result = validateSubpageStyle(subpage)
|
||||
expect(result.valid).toBe(false)
|
||||
expect(result.errors.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('should reject subpage without bilingual title', () => {
|
||||
const subpage = {
|
||||
cssContent: 'color: var(--kt-fg);',
|
||||
hasBilingualTitle: false
|
||||
}
|
||||
const result = validateSubpageStyle(subpage)
|
||||
expect(result.valid).toBe(false)
|
||||
expect(result.errors).toContain('Missing bilingual title structure')
|
||||
})
|
||||
|
||||
it('should handle invalid subpage object', () => {
|
||||
expect(validateSubpageStyle(null).valid).toBe(false)
|
||||
expect(validateSubpageStyle(undefined).valid).toBe(false)
|
||||
expect(validateSubpageStyle('string').valid).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Requirements: 5.1, 5.3 - Required KT variables
|
||||
*/
|
||||
describe('Required KT Variables', () => {
|
||||
it('REQUIRED_KT_VARIABLES should contain essential styling variables', () => {
|
||||
expect(REQUIRED_KT_VARIABLES).toContain('--kt-bg')
|
||||
expect(REQUIRED_KT_VARIABLES).toContain('--kt-fg')
|
||||
expect(REQUIRED_KT_VARIABLES).toContain('--kt-border')
|
||||
expect(REQUIRED_KT_VARIABLES).toContain('--kt-accent')
|
||||
expect(REQUIRED_KT_VARIABLES).toContain('--kt-font')
|
||||
expect(REQUIRED_KT_VARIABLES).toContain('--kt-radius')
|
||||
})
|
||||
|
||||
it('all required variables should use KT prefix', () => {
|
||||
for (const variable of REQUIRED_KT_VARIABLES) {
|
||||
expect(isKTVariable(variable)).toBe(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue