Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bf32dd076 | ||
|
|
e2b0c62628 |
@@ -44,6 +44,7 @@ npm run test:coverage # lefedettség riport
|
|||||||
npm run test:browser # browser integration
|
npm run test:browser # browser integration
|
||||||
npm run test:integration # Docker integration (Docker kell!)
|
npm run test:integration # Docker integration (Docker kell!)
|
||||||
npm run test:e2e # E2E tesztek (Docker kell!)
|
npm run test:e2e # E2E tesztek (Docker kell!)
|
||||||
|
npm run test:payload # Payload Local API integráció (élő MongoDB + migrált tartalom kell!)
|
||||||
npm run test:all # teljes proto suite
|
npm run test:all # teljes proto suite
|
||||||
npm run test:smoke:staging # Playwright smoke a staging ellen
|
npm run test:smoke:staging # Playwright smoke a staging ellen
|
||||||
```
|
```
|
||||||
@@ -84,5 +85,23 @@ Plane-sync unit tesztek. Bármelyik hibája megszakítja a kiadást.
|
|||||||
> serializer, optimista zárolás, verziók panel, logó feltöltés, login/logout,
|
> serializer, optimista zárolás, verziók panel, logó feltöltés, login/logout,
|
||||||
> guide, publish) a Payload CMS-re állás után (MITHOME-93) eltávolítottuk —
|
> guide, publish) a Payload CMS-re állás után (MITHOME-93) eltávolítottuk —
|
||||||
> a Payload admin felület a saját upstream tesztelésével fedett, ezt itt nem
|
> a Payload admin felület a saját upstream tesztelésével fedett, ezt itt nem
|
||||||
> duplikáljuk. Payload collection/global konfigurációk saját tesztlefedettsége
|
> duplikáljuk.
|
||||||
> külön feladat (MITHOME-96), még nincs implementálva.
|
>
|
||||||
|
> **MITHOME-96**: Payload collection/global config tesztek —
|
||||||
|
> `src/payload-config.test.ts` (a `npm test`/pre-deploy suite része, nincs
|
||||||
|
> hozzá élő DB, csak a Collection/Global config objektumokat vizsgálja —
|
||||||
|
> köztük két, MITHOME-121-ben talált éles hibára regresszió-őrt: a Media
|
||||||
|
> publikus olvashatósága, a Partners.logo opcionalitása). A Local API elleni,
|
||||||
|
> élő MongoDB-t igénylő tesztek külön scriptben vannak
|
||||||
|
> (`scripts/test-payload-local-api.ts`, `npm run test:payload`) — WHY nem
|
||||||
|
> Jest: a `payload` csomag ESM-only dist-et ad ki, amit a next/jest
|
||||||
|
> transzform alapból nem fordít le (a teljes függőségi fa
|
||||||
|
> `transformIgnorePatterns`-be vétele törékeny lenne), ezért ugyanazt a
|
||||||
|
> bevált `node --import tsx` mintát követi, mint `migrate-content-to-payload.ts`.
|
||||||
|
> Nincs a `pre-deploy-tests.sh`-ban (élő, migrált tartalmú MongoDB kell hozzá,
|
||||||
|
> mint a régi, eltávolított CMS-teszteknek is), de a `npm run test:payload`
|
||||||
|
> paranccsal bármikor lefuttatható egy futó dev MongoDB ellen. A régi,
|
||||||
|
> Docker-stack-hez kötött `integration.test.ts`/`e2e-docker.test.ts` is
|
||||||
|
> frissítve lett a locale-prefixes útvonalakra és a Payload collection-nevekre
|
||||||
|
> (korábban a pre-Payload, unprefixelt útvonalakra és `site_config`/
|
||||||
|
> `contact_submissions` nyers Mongo collection-ökre hivatkoztak).
|
||||||
|
|||||||
+2
-1
@@ -28,7 +28,8 @@
|
|||||||
"docker:dev:logs": "cd .. && docker-compose -f docker-compose.dev.yml logs -f app",
|
"docker:dev:logs": "cd .. && docker-compose -f docker-compose.dev.yml logs -f app",
|
||||||
"docker:build": "docker build -t mozdit-app .",
|
"docker:build": "docker build -t mozdit-app .",
|
||||||
"docker:run": "docker run -p 3000:3000 --env-file .env.local mozdit-app",
|
"docker:run": "docker run -p 3000:3000 --env-file .env.local mozdit-app",
|
||||||
"migrate:content": "node --env-file=.env.local --import tsx scripts/migrate-content-to-payload.ts"
|
"migrate:content": "node --env-file=.env.local --import tsx scripts/migrate-content-to-payload.ts",
|
||||||
|
"test:payload": "node --env-file=.env.local --import tsx scripts/test-payload-local-api.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@payloadcms/db-mongodb": "^3.88.0",
|
"@payloadcms/db-mongodb": "^3.88.0",
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* MITHOME-96 — Payload Local API integrációs teszt.
|
||||||
|
*
|
||||||
|
* Ez a "Local API integrációs tesztek" rész a ticketből: valódi, futó
|
||||||
|
* MongoDB-vel ellenőrzi, hogy a src/lib/payload-content.ts adapter-réteg
|
||||||
|
* ténylegesen jó alakú adatot ad vissza a Globals/Collections-ökből — nem
|
||||||
|
* mock-olt Payload-dal, hanem éles Local API hívásokkal.
|
||||||
|
*
|
||||||
|
* WHY sima node script és nem Jest teszt: a Payload csomag (és több
|
||||||
|
* függősége, pl. @payloadcms/richtext-lexical) ESM-only dist-et ad ki —
|
||||||
|
* Jest (a next/jest SWC transformjával is) alapból nem transzformálja a
|
||||||
|
* node_modules-t, így `import { getPayload } from 'payload'` egy Jest
|
||||||
|
* tesztben `SyntaxError: Cannot use import statement outside a module`-lel
|
||||||
|
* bukik (kipróbálva). A `transformIgnorePatterns` kiterjesztése a teljes
|
||||||
|
* Payload-függőségi fára törékeny és karbantartás-igényes lenne — ehelyett
|
||||||
|
* ugyanazt a bevált mintát követjük, mint a migrate-content-to-payload.ts /
|
||||||
|
* export-content-snapshot.ts scriptek: `node --import tsx`, valódi Node
|
||||||
|
* ESM-mel, semmilyen Jest-transzform nem kell.
|
||||||
|
*
|
||||||
|
* Futtatás (proto/ mappából, futó MongoDB-vel, migrált tartalommal):
|
||||||
|
* MONGODB_URI="mongodb://admin:password123@localhost:27018/mozdit?authSource=admin" \
|
||||||
|
* npm run test:payload
|
||||||
|
*/
|
||||||
|
import assert from 'assert/strict'
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
import config from '../src/payload.config'
|
||||||
|
import {
|
||||||
|
getCommonContent,
|
||||||
|
getHomeContent,
|
||||||
|
getAboutContent,
|
||||||
|
getServicesContent,
|
||||||
|
getContactContent,
|
||||||
|
getLegalPage,
|
||||||
|
getPartners,
|
||||||
|
} from '../src/lib/payload-content'
|
||||||
|
|
||||||
|
let passed = 0
|
||||||
|
|
||||||
|
async function test(name: string, fn: () => Promise<void>) {
|
||||||
|
try {
|
||||||
|
await fn()
|
||||||
|
passed++
|
||||||
|
console.log(`✅ ${name}`)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ ${name}`)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
|
await test('getCommonContent visszaad hu és en tartalmat', async () => {
|
||||||
|
const hu = await getCommonContent('hu')
|
||||||
|
const en = await getCommonContent('en')
|
||||||
|
assert.ok(hu.buttons.webmail, 'hiányzó hu webmail gomb szöveg')
|
||||||
|
assert.ok(en.buttons.webmail, 'hiányzó en webmail gomb szöveg')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('getHomeContent unwrap-eli a trustBullets és services.items.features tömböket', async () => {
|
||||||
|
const home = await getHomeContent('hu')
|
||||||
|
assert.ok(Array.isArray(home.hero.trustBullets))
|
||||||
|
assert.ok(home.hero.trustBullets.every((v) => typeof v === 'string'))
|
||||||
|
for (const item of home.services.items) {
|
||||||
|
assert.ok(Array.isArray(item.features))
|
||||||
|
assert.ok(item.features.every((v) => typeof v === 'string'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('getAboutContent unwrap-eli a story és team paragraphs tömböket', async () => {
|
||||||
|
const about = await getAboutContent('hu')
|
||||||
|
assert.ok(Array.isArray(about.story.paragraphs))
|
||||||
|
assert.ok(Array.isArray(about.team.paragraphs))
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('getServicesContent unwrap-eli a specs.items tömböket', async () => {
|
||||||
|
const services = await getServicesContent('hu')
|
||||||
|
for (const service of services.details.services) {
|
||||||
|
assert.ok(Array.isArray(service.specs.items))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('getContactContent visszaadja a form mezőket', async () => {
|
||||||
|
const contact = await getContactContent('hu')
|
||||||
|
assert.ok(contact.form.fields.email.label)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('getLegalPage megtalálja mindkét jogi oldalt', async () => {
|
||||||
|
const privacy = await getLegalPage('adatvedelem', 'hu')
|
||||||
|
const terms = await getLegalPage('hasznalati-feltetelek', 'hu')
|
||||||
|
assert.equal(privacy?.slug, 'adatvedelem')
|
||||||
|
assert.equal(terms?.slug, 'hasznalati-feltetelek')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('getPartners csak logóval rendelkező partnereket ad vissza', async () => {
|
||||||
|
const partners = await getPartners()
|
||||||
|
for (const partner of partners) {
|
||||||
|
assert.ok(partner.logo.url)
|
||||||
|
assert.ok(partner.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await test('create/findByID/delete ciklus működik (contact-submissions)', async () => {
|
||||||
|
const created = await payload.create({
|
||||||
|
collection: 'contact-submissions',
|
||||||
|
data: {
|
||||||
|
name: 'Local API Test',
|
||||||
|
email: 'local-api-test@example.com',
|
||||||
|
subject: 'MITHOME-96 Local API teszt',
|
||||||
|
message: 'Ez a rekord a test-payload-local-api.ts futása során jön létre és törlődik.',
|
||||||
|
gdprConsent: true,
|
||||||
|
status: 'new',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.ok(created.id)
|
||||||
|
|
||||||
|
const found = await payload.findByID({ collection: 'contact-submissions', id: created.id })
|
||||||
|
assert.equal(found.email, 'local-api-test@example.com')
|
||||||
|
|
||||||
|
await payload.delete({ collection: 'contact-submissions', id: created.id })
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
payload.findByID({ collection: 'contact-submissions', id: created.id })
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(`\n${passed}/${passed} Payload Local API teszt zöld.`)
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((error) => {
|
||||||
|
console.error('\nPayload Local API teszt sikertelen:', error)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* End-to-End tests for the Docker environment
|
* End-to-End tests for the Docker environment
|
||||||
* These tests verify the full application flow in the Docker stack
|
* These tests verify the full application flow in the Docker stack
|
||||||
|
*
|
||||||
|
* MITHOME-96: routes are locale-prefixed (/hu/..., /en/...) since the
|
||||||
|
* Payload CMS migration (MITHOME-91/114) — updated from the old unprefixed
|
||||||
|
* paths.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
describe('Docker E2E Tests', () => {
|
describe('Docker E2E Tests', () => {
|
||||||
@@ -27,24 +31,24 @@ describe('Docker E2E Tests', () => {
|
|||||||
expect(html).toContain('mozdIT Bt.')
|
expect(html).toContain('mozdIT Bt.')
|
||||||
|
|
||||||
// Test navigation links exist in homepage
|
// Test navigation links exist in homepage
|
||||||
expect(html).toContain('href="/rolunk"')
|
expect(html).toContain('href="/hu/rolunk"')
|
||||||
expect(html).toContain('href="/szolgaltatasok"')
|
expect(html).toContain('href="/hu/szolgaltatasok"')
|
||||||
expect(html).toContain('href="/kapcsolat"')
|
expect(html).toContain('href="/hu/kapcsolat"')
|
||||||
|
|
||||||
// Test about page
|
// Test about page
|
||||||
response = await fetch(`${APP_URL}/rolunk`)
|
response = await fetch(`${APP_URL}/hu/rolunk`)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
html = await response.text()
|
html = await response.text()
|
||||||
expect(html).toContain('Rólunk')
|
expect(html).toContain('Rólunk')
|
||||||
|
|
||||||
// Test services page
|
// Test services page
|
||||||
response = await fetch(`${APP_URL}/szolgaltatasok`)
|
response = await fetch(`${APP_URL}/hu/szolgaltatasok`)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
html = await response.text()
|
html = await response.text()
|
||||||
expect(html).toContain('Szolgáltatásaink')
|
expect(html).toContain('Szolgáltatásaink')
|
||||||
|
|
||||||
// Test contact page
|
// Test contact page
|
||||||
response = await fetch(`${APP_URL}/kapcsolat`)
|
response = await fetch(`${APP_URL}/hu/kapcsolat`)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
html = await response.text()
|
html = await response.text()
|
||||||
expect(html).toContain('Kapcsolat')
|
expect(html).toContain('Kapcsolat')
|
||||||
@@ -210,9 +214,9 @@ describe('Docker E2E Tests', () => {
|
|||||||
|
|
||||||
const pages = [
|
const pages = [
|
||||||
{ url: '', title: 'mozdIT Bt.' },
|
{ url: '', title: 'mozdIT Bt.' },
|
||||||
{ url: '/rolunk', title: 'Rólunk' },
|
{ url: '/hu/rolunk', title: 'Rólunk' },
|
||||||
{ url: '/szolgaltatasok', title: 'Szolgáltatásaink' },
|
{ url: '/hu/szolgaltatasok', title: 'Szolgáltatásaink' },
|
||||||
{ url: '/kapcsolat', title: 'Kapcsolatfelvétel' }
|
{ url: '/hu/kapcsolat', title: 'Kapcsolat' }
|
||||||
]
|
]
|
||||||
|
|
||||||
for (const page of pages) {
|
for (const page of pages) {
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Integration tests for the Docker development environment
|
* Integration tests for the Docker development environment
|
||||||
* These tests run against the real services in the Docker stack
|
* These tests run against the real services in the Docker stack
|
||||||
|
*
|
||||||
|
* MITHOME-96: updated for the Payload CMS migration (MITHOME-85 epic) —
|
||||||
|
* routes are now locale-prefixed (/hu/..., /en/...) and content lives in
|
||||||
|
* Payload collections/globals (`globals`, `legal-pages`, `partners`,
|
||||||
|
* `contact-submissions`), not the old raw `site_config`/`contact_submissions`
|
||||||
|
* Mongoose collections. Assumes the Docker dev DB already has content
|
||||||
|
* migrated (`npm run migrate:content`) — see docs/backups for a snapshot if
|
||||||
|
* you need to reseed a throwaway environment.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MongoClient, ObjectId } from 'mongodb'
|
import { MongoClient, ObjectId } from 'mongodb'
|
||||||
@@ -74,12 +82,16 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
const collections = await mozditDb.listCollections().toArray()
|
const collections = await mozditDb.listCollections().toArray()
|
||||||
|
|
||||||
const collectionNames = collections.map(c => c.name)
|
const collectionNames = collections.map(c => c.name)
|
||||||
expect(collectionNames).toContain('site_config')
|
// Payload Globals (Home/About/Services/Contact/Common) live in a
|
||||||
expect(collectionNames).toContain('contact_submissions')
|
// single `globals` collection, one document per global.
|
||||||
|
expect(collectionNames).toContain('globals')
|
||||||
|
expect(collectionNames).toContain('legal-pages')
|
||||||
|
expect(collectionNames).toContain('partners')
|
||||||
|
expect(collectionNames).toContain('contact-submissions')
|
||||||
expect(collectionNames).toContain('users')
|
expect(collectionNames).toContain('users')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should verify site config data exists', async () => {
|
it('should verify the Home global exists and is published', async () => {
|
||||||
if (process.env.NODE_ENV === 'test' && !process.env.INTEGRATION_TESTS) {
|
if (process.env.NODE_ENV === 'test' && !process.env.INTEGRATION_TESTS) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -90,15 +102,12 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mozditDb = mongoClient.db('mozdit')
|
const mozditDb = mongoClient.db('mozdit')
|
||||||
const siteConfig = await mozditDb.collection('site_config').findOne()
|
const home = await mozditDb.collection('globals').findOne({ globalType: 'home' })
|
||||||
|
|
||||||
if (!siteConfig) throw new Error('site_config document not found')
|
if (!home) throw new Error('Home global document not found')
|
||||||
expect(siteConfig).toBeTruthy()
|
expect(home).toHaveProperty('_status', 'published')
|
||||||
expect(siteConfig).toHaveProperty('type', 'site_config')
|
expect(home).toHaveProperty('hero')
|
||||||
expect(siteConfig).toHaveProperty('environment', 'development')
|
expect(home.hero).toHaveProperty('title')
|
||||||
expect(siteConfig).toHaveProperty('data')
|
|
||||||
expect(siteConfig.data).toHaveProperty('general')
|
|
||||||
expect(siteConfig.data.general).toHaveProperty('name', 'mozdIT Bt.')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should access Mongo Express UI', async () => {
|
it('should access Mongo Express UI', async () => {
|
||||||
@@ -179,7 +188,7 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
}
|
}
|
||||||
const savedSubmission = await mongoClient
|
const savedSubmission = await mongoClient
|
||||||
.db('mozdit')
|
.db('mozdit')
|
||||||
.collection('contact_submissions')
|
.collection('contact-submissions')
|
||||||
.findOne({ _id: new ObjectId(result.submissionId) })
|
.findOne({ _id: new ObjectId(result.submissionId) })
|
||||||
expect(savedSubmission).toEqual(expect.objectContaining({
|
expect(savedSubmission).toEqual(expect.objectContaining({
|
||||||
name: contactData.name,
|
name: contactData.name,
|
||||||
@@ -256,7 +265,7 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
|
|
||||||
const result = await response.json()
|
const result = await response.json()
|
||||||
if (response.status === 400) {
|
if (response.status === 400) {
|
||||||
expect(result).toHaveProperty('error', 'Spam gyanús tartalom észlelve')
|
expect(result).toHaveProperty('error', 'Az üzenet spam gyanús tartalmat tartalmaz.')
|
||||||
} else if (response.status === 429) {
|
} else if (response.status === 429) {
|
||||||
expect(result).toHaveProperty('error')
|
expect(result).toHaveProperty('error')
|
||||||
expect(result.error).toContain('Túl sok')
|
expect(result.error).toContain('Túl sok')
|
||||||
@@ -270,13 +279,14 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MITHOME-91/114: bare "/" 307-redirects to "/hu" — fetch follows
|
||||||
|
// redirects by default, so this still lands on the real homepage.
|
||||||
const response = await fetch(DOCKER_SERVICES.app)
|
const response = await fetch(DOCKER_SERVICES.app)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
|
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
expect(html).toContain('mozdIT Bt.')
|
expect(html).toContain('mozdIT Bt.')
|
||||||
expect(html).toContain('Megbízható web‑ és email‑szolgáltatás')
|
expect(html).toContain('Megbízható web- és email szolgáltatás')
|
||||||
expect(html).toContain('Webmail Ugrás')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should load about page', async () => {
|
it('should load about page', async () => {
|
||||||
@@ -284,7 +294,7 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(`${DOCKER_SERVICES.app}/rolunk`)
|
const response = await fetch(`${DOCKER_SERVICES.app}/hu/rolunk`)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
|
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
@@ -297,14 +307,14 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(`${DOCKER_SERVICES.app}/szolgaltatasok`)
|
const response = await fetch(`${DOCKER_SERVICES.app}/hu/szolgaltatasok`)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
|
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
expect(html).toContain('Szolgáltatásaink')
|
expect(html).toContain('Szolgáltatásaink')
|
||||||
expect(html).toContain('Web Hosting')
|
expect(html).toContain('Webtárhely')
|
||||||
expect(html).toContain('Email Szolgáltatás')
|
expect(html).toContain('E-mail szolgáltatás')
|
||||||
expect(html).toContain('DNS Adminisztráció')
|
expect(html).toContain('DNS adminisztráció')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should load contact page', async () => {
|
it('should load contact page', async () => {
|
||||||
@@ -312,7 +322,7 @@ describe('Docker Environment Integration Tests', () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(`${DOCKER_SERVICES.app}/kapcsolat`)
|
const response = await fetch(`${DOCKER_SERVICES.app}/hu/kapcsolat`)
|
||||||
expect(response.status).toBe(200)
|
expect(response.status).toBe(200)
|
||||||
|
|
||||||
const html = await response.text()
|
const html = await response.text()
|
||||||
|
|||||||
@@ -237,7 +237,13 @@ export default function HomeView({ content: pageContent, partners, locale }: Hom
|
|||||||
<p className="text-center mb-10" style={{ color: 'var(--color-foreground-muted)' }}>
|
<p className="text-center mb-10" style={{ color: 'var(--color-foreground-muted)' }}>
|
||||||
{partnersCopy.subtitle}
|
{partnersCopy.subtitle}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-wrap justify-center items-center gap-10">
|
{/* WHY grid + w-fit + mx-auto: a felhasználó kérésére valódi
|
||||||
|
mátrix (max 3 oszlop), nem folyó flex-wrap. `w-fit` zsugorítja
|
||||||
|
a rácsot a tényleges (legfeljebb 3 oszlopnyi) tartalom
|
||||||
|
szélességére, a `mx-auto` pedig ettől tudja középre venni —
|
||||||
|
sima `inline-grid`-en az auto margó nem középre igazítana,
|
||||||
|
mert az egy inline-szintű doboz. */}
|
||||||
|
<div className="grid w-fit grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-10 justify-items-center mx-auto">
|
||||||
{partners.map((partner) => (
|
{partners.map((partner) => (
|
||||||
<a
|
<a
|
||||||
key={partner.name}
|
key={partner.name}
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/**
|
||||||
|
* MITHOME-96 — Payload collection/global config tesztek.
|
||||||
|
*
|
||||||
|
* WHY nem a teljes payload.config.ts-t importáljuk: az a valódi `payload` és
|
||||||
|
* `@payloadcms/db-mongodb` csomagokat importálja értékként (nem csak
|
||||||
|
* típusként), amik ESM-only, natív node_modules-forrást futtatnak — Jest
|
||||||
|
* (a next/jest transzformmal is) nem tudja lefordítani őket anélkül, hogy a
|
||||||
|
* teljes payload-függőségi fát is a transformIgnorePatterns kivételévé
|
||||||
|
* tennénk (próbáltuk: `SyntaxError: Cannot use import statement outside a
|
||||||
|
* module` a payload csomag saját forrásából). Az egyes Collection/Global
|
||||||
|
* fájlok viszont csak `import type` formában hivatkoznak a `payload`
|
||||||
|
* csomagra — ez típus-only import, a build kitörli, így ezek a fájlok
|
||||||
|
* önmagukban, gyors unit tesztként importálhatók, élő MongoDB/PAYLOAD_SECRET
|
||||||
|
* nélkül. Ez fedi le a ticket "Payload config tesztek" részét; a Local API
|
||||||
|
* ellen futó, élő adatbázist igénylő tesztek külön (integrációs) fájlban
|
||||||
|
* vannak — lásd src/__tests__/payload-local-api.test.ts.
|
||||||
|
*
|
||||||
|
* Ezek a tesztek szándékosan regresszió-őrök is: mindkettő egy-egy valódi,
|
||||||
|
* élesben megtalált hibát rögzít (MITHOME-121: Media publikus olvasása,
|
||||||
|
* Partners.logo opcionalitása), hogy soha többé ne térjenek vissza észrevétlenül.
|
||||||
|
*/
|
||||||
|
import { Users } from './collections/Users'
|
||||||
|
import { LegalPages } from './collections/LegalPages'
|
||||||
|
import { Media } from './collections/Media'
|
||||||
|
import { Partners } from './collections/Partners'
|
||||||
|
import { ContactSubmissions } from './collections/ContactSubmissions'
|
||||||
|
import { Home } from './globals/Home'
|
||||||
|
import { About } from './globals/About'
|
||||||
|
import { Services } from './globals/Services'
|
||||||
|
import { Contact } from './globals/Contact'
|
||||||
|
import { Common } from './globals/Common'
|
||||||
|
|
||||||
|
type FieldLike = { name?: string; required?: boolean; type?: string }
|
||||||
|
|
||||||
|
function findField(fields: unknown[], name: string): FieldLike | undefined {
|
||||||
|
return (fields as FieldLike[]).find((f) => f.name === name)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Payload collections', () => {
|
||||||
|
it('all collection slugs are present and unique', () => {
|
||||||
|
const slugs = [Users, LegalPages, Media, Partners, ContactSubmissions].map((c) => c.slug)
|
||||||
|
expect(slugs).toEqual(['users', 'legal-pages', 'media', 'partners', 'contact-submissions'])
|
||||||
|
expect(new Set(slugs).size).toBe(slugs.length)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Media', () => {
|
||||||
|
// Regresszió-őr — MITHOME-121: a Media collection read access-e sokáig
|
||||||
|
// (MITHOME-89 óta) alapértelmezetten csak bejelentkezett usernek volt
|
||||||
|
// engedélyezett, emiatt a partner logók sosem töltődtek be a publikus
|
||||||
|
// oldalon (403 -> a Next.js image-optimizer "nem érvényes kép" hibája).
|
||||||
|
it('allows public (unauthenticated) read access', () => {
|
||||||
|
expect(Media.access?.read).toBeDefined()
|
||||||
|
const result = Media.access!.read!({ req: { user: null } } as never)
|
||||||
|
expect(result).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('only accepts image uploads', () => {
|
||||||
|
expect(Media.upload).toEqual(expect.objectContaining({ mimeTypes: ['image/*'] }))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Partners', () => {
|
||||||
|
it('requires name and url', () => {
|
||||||
|
expect(findField(Partners.fields, 'name')?.required).toBe(true)
|
||||||
|
expect(findField(Partners.fields, 'url')?.required).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Regresszió-őr — MITHOME-121: a felhasználó kérésére a logo mező
|
||||||
|
// opcionálissá vált, hogy egy partner logó nélkül is menthető legyen.
|
||||||
|
it('does not require a logo', () => {
|
||||||
|
const logo = findField(Partners.fields, 'logo')
|
||||||
|
expect(logo).toBeDefined()
|
||||||
|
expect(logo?.required).not.toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('ContactSubmissions', () => {
|
||||||
|
// WHY nincs egyedi access blokk itt tesztelve mint "hiányzik": a Payload
|
||||||
|
// defaultAccess (csak bejelentkezett user) itt a kívánt viselkedés —
|
||||||
|
// lásd a collection saját WHY-kommentjét. Nincs mit tesztelni rajta
|
||||||
|
// (nincs felülírás), de a mezőszerkezetet igen.
|
||||||
|
it('requires the core submission fields', () => {
|
||||||
|
for (const name of ['name', 'email', 'subject', 'message', 'gdprConsent']) {
|
||||||
|
expect(findField(ContactSubmissions.fields, name)?.required).toBe(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('defaults status to "new"', () => {
|
||||||
|
const status = findField(ContactSubmissions.fields, 'status') as FieldLike & {
|
||||||
|
defaultValue?: string
|
||||||
|
options?: { value: string }[]
|
||||||
|
}
|
||||||
|
expect(status?.defaultValue).toBe('new')
|
||||||
|
expect(status?.options?.map((o) => o.value)).toEqual(['new', 'read', 'replied', 'archived'])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('LegalPages', () => {
|
||||||
|
it('has a required, unique slug field', () => {
|
||||||
|
const slug = findField(LegalPages.fields, 'slug') as FieldLike & { unique?: boolean }
|
||||||
|
expect(slug?.required).toBe(true)
|
||||||
|
expect(slug?.unique).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Users', () => {
|
||||||
|
it('locks accounts after 5 failed attempts for 10 minutes', () => {
|
||||||
|
expect(Users.auth).toEqual(
|
||||||
|
expect.objectContaining({ maxLoginAttempts: 5, lockTime: 10 * 60 * 1000 })
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('requires an authenticated user for every access-controlled operation', () => {
|
||||||
|
const access = Users.access!
|
||||||
|
for (const op of ['create', 'read', 'update', 'delete', 'unlock'] as const) {
|
||||||
|
expect(access[op]!({ req: { user: null } } as never)).toBe(false)
|
||||||
|
expect(access[op]!({ req: { user: {} } } as never)).toBe(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Payload globals', () => {
|
||||||
|
it('all global slugs are present and unique', () => {
|
||||||
|
const slugs = [Home, About, Services, Contact, Common].map((g) => g.slug)
|
||||||
|
expect(slugs).toEqual(['home', 'about', 'services', 'contact', 'common'])
|
||||||
|
expect(new Set(slugs).size).toBe(slugs.length)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Home does not duplicate the Partners collection', () => {
|
||||||
|
// MITHOME-89 döntés: a partnerek önálló collection-ök, a Home global
|
||||||
|
// szándékosan nem tartalmaz "partners" mezőt.
|
||||||
|
expect(findField(Home.fields, 'partners')).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Common.buttons.* fields are localized (MITHOME-110 bizonyíték)', () => {
|
||||||
|
const buttonsGroup = findField(Common.fields, 'buttons') as FieldLike & {
|
||||||
|
fields?: (FieldLike & { localized?: boolean })[]
|
||||||
|
}
|
||||||
|
expect(buttonsGroup?.fields?.length).toBeGreaterThan(0)
|
||||||
|
for (const field of buttonsGroup!.fields!) {
|
||||||
|
expect(field.localized).toBe(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user