feat: embeddable CompanyGame with loader, poster, no-WebGL fallback and SEO
- CompanyGame bundles the store, a branded loader with start-up progress, an optional light poster (Enter the game) and a company-info fallback when WebGL is missing. - startMode prop and ?mode= start straight in a mode; ?poster shows the poster first. - Pixel ratio capped at 1.5 on touch devices and 1.75 on desktop (constants/graphics.js). - Build writes the title, description, Organization JSON-LD and a hidden Persian summary into index.html from the company config. - README explains iframe and component embedding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { COMPANY } from '../src/config/company.js';
|
||||
import { seoHead, seoStructuredData, seoSummary } from '../src/utils/seoSummary.js';
|
||||
|
||||
test('The page head carries the company title and description', () => {
|
||||
const head = seoHead();
|
||||
assert.ok(head.includes(`<title>${COMPANY.name}`));
|
||||
assert.match(head, /<meta name="description" content="[^"]+"/);
|
||||
});
|
||||
|
||||
test('The hidden summary lists the company, every product and the contact details', () => {
|
||||
const summary = seoSummary();
|
||||
assert.ok(summary.startsWith('<section class="sr-only"'));
|
||||
for (const product of COMPANY.products) assert.ok(summary.includes(product.name));
|
||||
assert.ok(summary.includes(COMPANY.contact.email));
|
||||
});
|
||||
|
||||
test('Structured data is valid JSON-LD for the organization', () => {
|
||||
const json = seoStructuredData().replace(/^<script[^>]*>|<\/script>$/g, '');
|
||||
const data = JSON.parse(json);
|
||||
assert.equal(data['@type'], 'Organization');
|
||||
assert.equal(data.name, COMPANY.name);
|
||||
assert.equal(data.address.addressLocality, COMPANY.contact.city);
|
||||
});
|
||||
Reference in New Issue
Block a user