Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
122 lines
3.6 KiB
TypeScript
122 lines
3.6 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { ORGANIZATION_ID, WEBSITE_ID, eventSchema, faqPage, organizationSchema, webSiteSchema } from '@/lib/seo/JsonLd'
|
|
|
|
const eventSchemaBase = {
|
|
name: 'رویداد نمونه',
|
|
description: null,
|
|
startDate: '2026-08-01T10:00:00Z',
|
|
endDate: '2026-08-01T12:00:00Z',
|
|
url: 'https://ghabilee.ir/e/sample',
|
|
isFree: false,
|
|
price: 250_000,
|
|
}
|
|
|
|
describe('SEO structured data', () => {
|
|
it('converts stored toman prices to rial for IRR offers', () => {
|
|
const schema = eventSchema({
|
|
...eventSchemaBase,
|
|
address: 'خیابان ولیعصر',
|
|
cityName: 'تهران',
|
|
})
|
|
|
|
expect(schema.offers).toMatchObject({ price: 2_500_000, priceCurrency: 'IRR' })
|
|
expect(schema).toMatchObject({ url: eventSchemaBase.url })
|
|
})
|
|
|
|
it('emits PostalAddress for a public street address', () => {
|
|
const schema = eventSchema({
|
|
...eventSchemaBase,
|
|
address: 'خیابان ولیعصر، پلاک ۱۲',
|
|
cityName: 'تهران',
|
|
})
|
|
|
|
expect(schema.location).toEqual({
|
|
'@type': 'Place',
|
|
name: 'تهران',
|
|
address: {
|
|
'@type': 'PostalAddress',
|
|
streetAddress: 'خیابان ولیعصر، پلاک ۱۲',
|
|
addressLocality: 'تهران',
|
|
addressCountry: 'IR',
|
|
},
|
|
})
|
|
})
|
|
|
|
it('uses generalArea when the exact address is hidden from crawlers', () => {
|
|
const schema = eventSchema({
|
|
...eventSchemaBase,
|
|
address: null,
|
|
generalArea: 'خیابان هفتتیر',
|
|
cityName: 'مشهد',
|
|
})
|
|
|
|
expect(schema.location.address).toEqual({
|
|
'@type': 'PostalAddress',
|
|
streetAddress: 'خیابان هفتتیر',
|
|
addressLocality: 'مشهد',
|
|
addressCountry: 'IR',
|
|
})
|
|
expect(JSON.stringify(schema.location)).not.toContain('null')
|
|
})
|
|
|
|
it('still emits addressLocality when only the city is public', () => {
|
|
const schema = eventSchema({
|
|
...eventSchemaBase,
|
|
address: null,
|
|
cityName: 'اصفهان',
|
|
})
|
|
|
|
expect(schema.location.address).toEqual({
|
|
'@type': 'PostalAddress',
|
|
addressLocality: 'اصفهان',
|
|
addressCountry: 'IR',
|
|
})
|
|
})
|
|
|
|
it('treats blank address strings as missing and does not leak them', () => {
|
|
const schema = eventSchema({
|
|
...eventSchemaBase,
|
|
address: ' ',
|
|
generalArea: 'محدوده ونک',
|
|
cityName: 'تهران',
|
|
})
|
|
|
|
expect(schema.location.address.streetAddress).toBe('محدوده ونک')
|
|
})
|
|
|
|
it('emits FAQPage entities for evergreen landing content', () => {
|
|
const schema = faqPage([{ question: 'چطور ثبتنام کنم؟', answer: 'از صفحه رویداد.' }])
|
|
|
|
expect(schema).toMatchObject({
|
|
'@type': 'FAQPage',
|
|
mainEntity: [{ '@type': 'Question', name: 'چطور ثبتنام کنم؟' }],
|
|
})
|
|
})
|
|
|
|
it('uses stable IDs to connect the website and its organization', () => {
|
|
const organization = organizationSchema({
|
|
url: 'https://ghabilee.ir',
|
|
logo: 'https://ghabilee.ir/logo.svg',
|
|
telephone: '+985100000000',
|
|
address: { locality: 'مشهد', streetAddress: 'نمونه' },
|
|
})
|
|
|
|
expect(organization).toMatchObject({
|
|
'@id': ORGANIZATION_ID,
|
|
alternateName: 'Ghabilee',
|
|
sameAs: ['https://www.instagram.com/Ghabilee_support/', 'https://t.me/Ghabilee_support'],
|
|
contactPoint: {
|
|
'@type': 'ContactPoint',
|
|
telephone: '+985100000000',
|
|
contactType: 'customer support',
|
|
areaServed: 'IR',
|
|
},
|
|
})
|
|
expect(webSiteSchema('https://ghabilee.ir')).toMatchObject({
|
|
'@id': WEBSITE_ID,
|
|
publisher: { '@id': ORGANIZATION_ID },
|
|
})
|
|
})
|
|
})
|