feat: enhance README and TODO documentation, implement mobile menu functionality in Header component
- Updated README.md with project details, quick start instructions, and tech stack. - Expanded TODO.md to reflect current project status and backlog items, including Linear ticket synchronization. - Added mobile menu toggle functionality in Header component with corresponding tests for user interactions. - Configured Next.js for Docker deployment and optimized build settings.
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
* End-to-End tests for the Docker environment
|
||||
* These tests verify the full application flow in the Docker stack
|
||||
*/
|
||||
|
||||
describe('Docker E2E Tests', () => {
|
||||
const APP_URL = 'http://localhost:3000'
|
||||
|
||||
beforeAll(() => {
|
||||
// Skip E2E tests if not in Docker environment
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
console.log('Skipping E2E tests - use E2E_TESTS=1 to enable')
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
describe('Navigation Flow', () => {
|
||||
it('should navigate through all main pages', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
// Test homepage
|
||||
let response = await fetch(APP_URL)
|
||||
expect(response.status).toBe(200)
|
||||
let html = await response.text()
|
||||
expect(html).toContain('mozdIT Bt.')
|
||||
|
||||
// Test navigation links exist in homepage
|
||||
expect(html).toContain('href="/rolunk"')
|
||||
expect(html).toContain('href="/szolgaltatasok"')
|
||||
expect(html).toContain('href="/kapcsolat"')
|
||||
|
||||
// Test about page
|
||||
response = await fetch(`${APP_URL}/rolunk`)
|
||||
expect(response.status).toBe(200)
|
||||
html = await response.text()
|
||||
expect(html).toContain('Rólunk')
|
||||
|
||||
// Test services page
|
||||
response = await fetch(`${APP_URL}/szolgaltatasok`)
|
||||
expect(response.status).toBe(200)
|
||||
html = await response.text()
|
||||
expect(html).toContain('Szolgáltatásaink')
|
||||
|
||||
// Test contact page
|
||||
response = await fetch(`${APP_URL}/kapcsolat`)
|
||||
expect(response.status).toBe(200)
|
||||
html = await response.text()
|
||||
expect(html).toContain('Kapcsolat')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Contact Form Flow', () => {
|
||||
it('should handle complete contact form submission flow', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
// Valid submission
|
||||
const validData = {
|
||||
name: 'E2E Test User',
|
||||
email: 'e2e@test.com',
|
||||
subject: 'E2E Test Subject',
|
||||
message: 'This is a comprehensive end-to-end test message',
|
||||
gdprConsent: true
|
||||
}
|
||||
|
||||
const response = await fetch(`${APP_URL}/api/contact`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(validData)
|
||||
})
|
||||
|
||||
// Might be rate limited due to previous tests
|
||||
expect([200, 429]).toContain(response.status)
|
||||
const result = await response.json()
|
||||
if (response.status === 200) {
|
||||
expect(result.message).toBe('Üzenet sikeresen elküldve!')
|
||||
} else {
|
||||
expect(result.error).toContain('Túl sok')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle validation errors properly', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
// Test missing required fields
|
||||
const invalidData = {
|
||||
name: '',
|
||||
email: 'invalid-email',
|
||||
subject: '',
|
||||
message: 'Short',
|
||||
gdprConsent: false
|
||||
}
|
||||
|
||||
const response = await fetch(`${APP_URL}/api/contact`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(invalidData)
|
||||
})
|
||||
|
||||
// Might be rate limited or validation error
|
||||
expect([400, 429]).toContain(response.status)
|
||||
const result = await response.json()
|
||||
if (response.status === 400) {
|
||||
expect(result.error).toContain('validációs hiba')
|
||||
} else {
|
||||
expect(result.error).toContain('Túl sok')
|
||||
}
|
||||
})
|
||||
|
||||
it('should handle rate limiting correctly', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
const testData = {
|
||||
name: 'Rate Limit E2E Test',
|
||||
email: 'ratelimit-e2e@test.com',
|
||||
subject: 'Rate Limit Test',
|
||||
message: 'Testing rate limiting in E2E environment',
|
||||
gdprConsent: true
|
||||
}
|
||||
|
||||
// Send multiple requests to trigger rate limiting
|
||||
const requests = []
|
||||
for (let i = 0; i < 5; i++) {
|
||||
requests.push(
|
||||
fetch(`${APP_URL}/api/contact`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
...testData,
|
||||
message: `${testData.message} - Request ${i + 1}`
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const responses = await Promise.all(requests)
|
||||
const statusCodes = responses.map(r => r.status)
|
||||
|
||||
// Due to previous tests, all might be rate limited
|
||||
// Just check that rate limiting is working
|
||||
expect(statusCodes).toContain(429)
|
||||
|
||||
// If any succeeded, that's also fine
|
||||
const hasSuccess = statusCodes.includes(200)
|
||||
const hasRateLimit = statusCodes.includes(429)
|
||||
expect(hasRateLimit).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('API Health and Monitoring', () => {
|
||||
it('should provide comprehensive health information', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
const response = await fetch(`${APP_URL}/api/health`)
|
||||
expect(response.status).toBe(200)
|
||||
|
||||
const health = await response.json()
|
||||
expect(health).toHaveProperty('status', 'ok')
|
||||
expect(health).toHaveProperty('timestamp')
|
||||
expect(health).toHaveProperty('uptime')
|
||||
expect(health).toHaveProperty('version', '0.1.0')
|
||||
expect(health).toHaveProperty('environment')
|
||||
|
||||
// Uptime should be a positive number
|
||||
expect(typeof health.uptime).toBe('number')
|
||||
expect(health.uptime).toBeGreaterThan(0)
|
||||
|
||||
// Timestamp should be a valid ISO string
|
||||
expect(() => new Date(health.timestamp)).not.toThrow()
|
||||
})
|
||||
|
||||
it('should handle HEAD requests for health checks', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
const response = await fetch(`${APP_URL}/api/health`, {
|
||||
method: 'HEAD'
|
||||
})
|
||||
|
||||
expect(response.status).toBe(200)
|
||||
expect(response.headers.get('cache-control')).toContain('no-cache')
|
||||
|
||||
// HEAD request should have no body
|
||||
const text = await response.text()
|
||||
expect(text).toBe('')
|
||||
})
|
||||
})
|
||||
|
||||
describe('SEO and Meta Tags', () => {
|
||||
it('should have proper meta tags on all pages', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
const pages = [
|
||||
{ url: '', title: 'mozdIT Bt.' },
|
||||
{ url: '/rolunk', title: 'Rólunk' },
|
||||
{ url: '/szolgaltatasok', title: 'Szolgáltatásaink' },
|
||||
{ url: '/kapcsolat', title: 'Kapcsolatfelvétel' }
|
||||
]
|
||||
|
||||
for (const page of pages) {
|
||||
const response = await fetch(`${APP_URL}${page.url}`)
|
||||
expect(response.status).toBe(200)
|
||||
|
||||
const html = await response.text()
|
||||
|
||||
// Check for essential meta tags
|
||||
expect(html).toContain('<meta name="viewport"')
|
||||
expect(html).toContain('<meta name="description"')
|
||||
expect(html).toContain('mozdIT Bt.')
|
||||
|
||||
// Check for Open Graph tags
|
||||
expect(html).toContain('<meta property="og:title"')
|
||||
expect(html).toContain('<meta property="og:description"')
|
||||
|
||||
// Check for proper title
|
||||
expect(html).toContain('<title>')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Performance and Caching', () => {
|
||||
it('should have proper cache headers', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
// Test static assets caching
|
||||
const response = await fetch(APP_URL)
|
||||
expect(response.status).toBe(200)
|
||||
|
||||
// Health endpoint should have no-cache
|
||||
const healthResponse = await fetch(`${APP_URL}/api/health`)
|
||||
expect(healthResponse.headers.get('cache-control')).toContain('no-cache')
|
||||
})
|
||||
|
||||
it('should load pages within reasonable time', async () => {
|
||||
if (process.env.NODE_ENV === 'test' && !process.env.E2E_TESTS) {
|
||||
return
|
||||
}
|
||||
|
||||
const startTime = Date.now()
|
||||
const response = await fetch(APP_URL)
|
||||
const endTime = Date.now()
|
||||
|
||||
expect(response.status).toBe(200)
|
||||
|
||||
const loadTime = endTime - startTime
|
||||
// Should load within 5 seconds (generous for Docker environment)
|
||||
expect(loadTime).toBeLessThan(5000)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user