fix(web): hygiene — OG image/metadataBase, Header a11y text + nav flag, dead code
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions

- siteConfig.ogImage pointed to an existing asset; metadataBase added so
  relative OG/Twitter URLs resolve against the real origin instead of localhost
- Header sr-only menu label moved to common.json (a11y.openMenu/closeMenu);
  navigation primary styling driven by a NavigationItem.primary flag instead
  of brittle 'Kapcsolat' string comparisons
- remove dead code: lib/site-config.ts (unused hybrid config) and the
  unused, schema-divergent siteConfig.contact.form
- ContactConfig type cleaned up (address/form removed)

Closes MITHOME-77
This commit is contained in:
Do Siki
2026-08-22 12:12:48 +02:00
parent 4c2913e131
commit 9f1fb349c2
10 changed files with 31 additions and 524 deletions
-382
View File
@@ -1,382 +0,0 @@
import { getSiteConfig, saveSiteConfig, initializeDefaultConfig } from './site-config'
import { getCollection } from './mongodb'
import { siteConfig as staticConfig } from '@/config/site'
import { SiteConfig } from '@/types/site'
import logger from './logger'
// Mock dependencies
jest.mock('./mongodb')
jest.mock('./logger', () => ({
__esModule: true,
default: {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn()
}
}))
jest.mock('@/config/site', () => ({
siteConfig: {
general: {
name: 'Test Site',
description: 'Test Description',
url: 'https://test.com',
ogImage: 'https://test.com/og.jpg',
locale: 'en'
},
navigation: {
main: [
{ label: 'Home', href: '/' },
{ label: 'About', href: '/about' }
],
footer: [
{ label: 'Privacy', href: '/privacy' },
{ label: 'Terms', href: '/terms' }
]
},
hero: {
title: 'Welcome',
subtitle: 'Test Subtitle',
description: 'Test description',
cta: {
primary: {
text: 'Get Started',
href: '/get-started'
}
}
},
services: {
title: 'Our Services',
subtitle: 'What we offer',
services: []
},
about: {
title: 'About Us',
description: ['Test about section'],
usps: []
},
footer: {
copyright: '© 2024 Test Site',
links: []
},
contact: {
email: 'test@test.com',
address: 'Test Address',
form: {
title: 'Contact Us',
description: 'Get in touch',
submitText: 'Send Message',
fields: {
name: { label: 'Name', placeholder: 'Your name', required: true },
email: { label: 'Email', placeholder: 'your@email.com', required: true },
message: { label: 'Message', placeholder: 'Your message', required: true },
consent: { label: 'I agree', required: true }
}
}
}
}
}))
const mockCollection = {
findOne: jest.fn(),
replaceOne: jest.fn()
}
describe('Site Config', () => {
beforeEach(() => {
jest.clearAllMocks()
;(getCollection as jest.Mock).mockResolvedValue(mockCollection)
})
describe('getSiteConfig', () => {
it('should return MongoDB config when available', async () => {
const mockConfig: SiteConfig = {
general: {
name: 'MongoDB Site',
description: 'MongoDB Description',
url: 'https://mongodb.com',
ogImage: 'https://mongodb.com/og.jpg',
locale: 'en'
},
navigation: {
main: [{ label: 'Home', href: '/' }],
footer: [{ label: 'Privacy', href: '/privacy' }]
},
hero: {
title: 'MongoDB Hero',
subtitle: 'MongoDB Subtitle',
description: 'MongoDB Description',
cta: {
primary: {
text: 'Get Started',
href: '/get-started'
}
}
},
services: {
title: 'Services',
subtitle: 'Our services',
services: []
},
about: {
title: 'About',
description: ['About us'],
usps: []
},
footer: {
copyright: '© 2024 MongoDB',
links: []
},
contact: {
email: 'mongodb@test.com',
address: 'MongoDB Address',
form: {
title: 'Contact',
description: 'Get in touch',
submitText: 'Send',
fields: {
name: { label: 'Name', placeholder: 'Name', required: true },
email: { label: 'Email', placeholder: 'Email', required: true },
message: { label: 'Message', placeholder: 'Message', required: true },
consent: { label: 'Consent', required: true }
}
}
}
}
mockCollection.findOne.mockResolvedValue({
_id: 'mock-id',
data: mockConfig
})
const config = await getSiteConfig()
expect(config).toEqual(mockConfig)
expect(mockCollection.findOne).toHaveBeenCalledWith({
type: 'site_config',
environment: 'development'
})
expect(logger.info).toHaveBeenCalledWith(
'Loaded site config from MongoDB',
{ configId: 'mock-id' }
)
})
it('should return static config when MongoDB config not found', async () => {
mockCollection.findOne.mockResolvedValue(null)
const config = await getSiteConfig()
expect(config).toEqual(staticConfig)
expect(logger.info).toHaveBeenCalledWith(
'MongoDB config not found, using static fallback'
)
})
it('should return static config when MongoDB is unavailable', async () => {
mockCollection.findOne.mockRejectedValue(new Error('Connection failed'))
const config = await getSiteConfig()
expect(config).toEqual(staticConfig)
expect(logger.warn).toHaveBeenCalledWith(
'MongoDB unavailable, using static config',
{ error: 'Connection failed' }
)
})
})
describe('saveSiteConfig', () => {
it('should save config to MongoDB successfully', async () => {
const newConfig: SiteConfig = {
general: {
name: 'New Site',
description: 'New Description',
url: 'https://new.com',
ogImage: 'https://new.com/og.jpg',
locale: 'en'
},
navigation: {
main: [{ label: 'Home', href: '/' }],
footer: [{ label: 'Privacy', href: '/privacy' }]
},
hero: {
title: 'New Hero',
subtitle: 'New Subtitle',
description: 'New Description',
cta: {
primary: {
text: 'Get Started',
href: '/get-started'
}
}
},
services: {
title: 'Services',
subtitle: 'Our services',
services: []
},
about: {
title: 'About',
description: ['About us'],
usps: []
},
footer: {
copyright: '© 2024 New',
links: []
},
contact: {
email: 'new@test.com',
address: 'New Address',
form: {
title: 'Contact',
description: 'Get in touch',
submitText: 'Send',
fields: {
name: { label: 'Name', placeholder: 'Name', required: true },
email: { label: 'Email', placeholder: 'Email', required: true },
message: { label: 'Message', placeholder: 'Message', required: true },
consent: { label: 'Consent', required: true }
}
}
}
}
mockCollection.replaceOne.mockResolvedValue({ acknowledged: true })
const result = await saveSiteConfig(newConfig)
expect(result).toBe(true)
expect(mockCollection.replaceOne).toHaveBeenCalledWith(
{ type: 'site_config', environment: 'development' },
{
type: 'site_config',
environment: 'development',
data: newConfig,
lastModified: expect.any(Date)
},
{ upsert: true }
)
expect(logger.info).toHaveBeenCalledWith('Saved site config to MongoDB')
})
it('should return false when save fails', async () => {
const newConfig: SiteConfig = {
general: {
name: 'New Site',
description: 'New Description',
url: 'https://new.com',
ogImage: 'https://new.com/og.jpg',
locale: 'en'
},
navigation: {
main: [{ label: 'Home', href: '/' }],
footer: [{ label: 'Privacy', href: '/privacy' }]
},
hero: {
title: 'New Hero',
subtitle: 'New Subtitle',
description: 'New Description',
cta: {
primary: {
text: 'Get Started',
href: '/get-started'
}
}
},
services: {
title: 'Services',
subtitle: 'Our services',
services: []
},
about: {
title: 'About',
description: ['About us'],
usps: []
},
footer: {
copyright: '© 2024 New',
links: []
},
contact: {
email: 'new@test.com',
address: 'New Address',
form: {
title: 'Contact',
description: 'Get in touch',
submitText: 'Send',
fields: {
name: { label: 'Name', placeholder: 'Name', required: true },
email: { label: 'Email', placeholder: 'Email', required: true },
message: { label: 'Message', placeholder: 'Message', required: true },
consent: { label: 'Consent', required: true }
}
}
}
}
mockCollection.replaceOne.mockRejectedValue(new Error('Save failed'))
const result = await saveSiteConfig(newConfig)
expect(result).toBe(false)
expect(logger.error).toHaveBeenCalledWith(
'Failed to save config to MongoDB',
{ error: 'Save failed' }
)
})
})
describe('initializeDefaultConfig', () => {
it('should initialize default config when none exists', async () => {
mockCollection.findOne.mockResolvedValue(null)
mockCollection.replaceOne.mockResolvedValue({ acknowledged: true })
await initializeDefaultConfig()
expect(mockCollection.findOne).toHaveBeenCalledWith({
type: 'site_config',
environment: 'development'
})
expect(mockCollection.replaceOne).toHaveBeenCalledWith(
{ type: 'site_config', environment: 'development' },
{
type: 'site_config',
environment: 'development',
data: staticConfig,
lastModified: expect.any(Date)
},
{ upsert: true }
)
expect(logger.info).toHaveBeenCalledWith(
'Initialized default site config in MongoDB'
)
})
it('should not initialize when config already exists', async () => {
mockCollection.findOne.mockResolvedValue({
_id: 'existing-id',
data: staticConfig
})
await initializeDefaultConfig()
expect(mockCollection.replaceOne).not.toHaveBeenCalled()
expect(logger.info).toHaveBeenCalledWith(
'Site config already exists in MongoDB'
)
})
it('should handle initialization errors gracefully', async () => {
mockCollection.findOne.mockRejectedValue(new Error('Connection failed'))
await initializeDefaultConfig()
expect(logger.error).toHaveBeenCalledWith(
'Failed to initialize site config',
{ error: 'Connection failed' }
)
})
})
})
-74
View File
@@ -1,74 +0,0 @@
// Hybrid approach: File-based fallback + MongoDB integration for future
import { siteConfig as staticConfig } from '@/config/site'
import { SiteConfig } from '@/types/site'
import { getCollection } from './mongodb'
import logger from './logger'
/**
* Get site configuration with hybrid approach
* 1. Try MongoDB first (production-ready)
* 2. Fall back to static file (development/development safe)
*/
export async function getSiteConfig(): Promise<SiteConfig> {
try {
const collection = await getCollection('site_config')
const doc = await collection.findOne({ type: 'site_config', environment: 'development' })
if (doc && doc.data) {
logger.info('Loaded site config from MongoDB', { configId: doc._id })
return doc.data as SiteConfig
} else {
logger.info('MongoDB config not found, using static fallback')
return staticConfig
}
} catch (error) {
logger.warn('MongoDB unavailable, using static config', { error: (error as Error).message })
return staticConfig
}
}
/**
* Save site configuration to MongoDB
* For future admin panel integration
*/
export async function saveSiteConfig(config: SiteConfig): Promise<boolean> {
try {
const collection = await getCollection('site_config')
await collection.replaceOne(
{ type: 'site_config', environment: 'development' },
{
type: 'site_config',
environment: 'development',
data: config,
lastModified: new Date()
},
{ upsert: true }
)
logger.info('Saved site config to MongoDB')
return true
} catch (error) {
logger.error('Failed to save config to MongoDB', { error: (error as Error).message })
return false
}
}
/**
* Initialize default config in MongoDB (one-time setup)
*/
export async function initializeDefaultConfig(): Promise<void> {
try {
const collection = await getCollection('site_config')
const existingConfig = await collection.findOne({ type: 'site_config', environment: 'development' })
if (!existingConfig) {
await saveSiteConfig(staticConfig)
logger.info('Initialized default site config in MongoDB')
} else {
logger.info('Site config already exists in MongoDB')
}
} catch (error) {
logger.error('Failed to initialize site config', { error: (error as Error).message })
}
}