storebound/tests/matrix-bugs.test.ts

54 lines
3.6 KiB
TypeScript

// Bugs the release acceptance matrix (tools/acceptance.ts) found, each pinned: a missing app info on App Store Connect
// is a clear error (it was "undefined is not an object (evaluating 'info.id')"), and asset uploads and review draft
// names take the base name of Windows paths (split('/') left the whole C:\\... path as the file name).
import { afterEach, describe, expect, test } from 'bun:test';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { run as appleAppinfo } from '../cli/apple/appinfo';
import { run as appleListing } from '../cli/apple/listing';
import { CRASH } from '../tools/acceptance';
import { ascEnv, BASE, capture, mockFetch, project, restore } from './helpers/store-mock';
const ROOT = join(import.meta.dir, '..');
afterEach(restore);
describe('bugs the matrix found', () => {
test('no app info on App Store Connect: a clear error, not "undefined is not an object"', async () => {
ascEnv();
const cfg = { ...BASE, apple: { ...BASE.apple!, info: { free: true } } };
for (const [name, runIt, argv] of [['appinfo', appleAppinfo, ['--dry']], ['listing', appleListing, ['--version', '1.0.0', '--dry']]] as const) {
const p = project(cfg, { 'store/appstore.md': readFileSync(join(ROOT, 'templates/appstore.md'), 'utf8') });
mockFetch([
{ match: /^\/v1\/apps\/6400000101\/appInfos/, answer: { data: [] } },
{ match: /^\/v1\/apps\/6400000101\/appStoreVersions/, answer: { data: [{ type: 'appStoreVersions', id: 'v1', attributes: { versionString: '1.0.0', platform: 'IOS', appVersionState: 'PREPARE_FOR_SUBMISSION' } }] } },
{ match: /./, answer: { data: [] } },
]);
let msg = '';
try { await capture(() => runIt(p.ctx([...argv]))); } catch (e) { msg = (e as Error).message; }
expect(msg, name).toMatch(/App Store Connect returned no app info for app 6400000101/);
expect(msg, name).not.toMatch(CRASH);
}
});
test('asset uploads and review draft names take the base name of Windows paths too', () => {
const asc = readFileSync(join(ROOT, 'cli/apple/asc.ts'), 'utf8');
expect(asc).toMatch(/const name = basename\(file\);/);
for (const f of ['cli/reviews.ts', 'cli/apple/previews.ts']) expect(readFileSync(join(ROOT, f), 'utf8'), f).not.toMatch(/\.split\('\/'\)\.pop\(\)/);
});
});
// live sweep (2026-10-14): a listing file with a tr-TR section the config's languages[] does not have stopped
// `play images --dry` with "tr-TR: no entry in languages[] has this Play code" while `play listing` pushes that text
describe('live sweep', () => {
test('play images skips a listing language that is not in languages[] (with the fix) instead of failing', async () => {
const { run: playImages } = await import('../cli/play/images');
const listing = (lang: string) => `## ${lang}\n<!-- play: ${lang} -->\n\n### Play short description\n\`\`\`\nNotes.\n\`\`\`\n\n### Play full description\n\`\`\`\nNotes for everyone.\n\`\`\`\n`;
const cfg = { ...BASE, languages: [{ id: 'en', apple: 'en-US', play: 'en-US' }], play: { ...BASE.play!, listing: 'store/listing.md' } };
const p = project(cfg, { 'store/listing.md': `# Play\n\n${listing('en-US')}\n${listing('tr-TR')}` });
let msg = '';
const r = await capture(() => playImages(p.ctx(['--dry']))).catch(e => { msg = (e as Error).message; return null; });
expect(msg).not.toContain('no entry in languages[] has this Play code');
if (r) expect(r.out + r.err).toContain("skipped tr-TR: in the listing file but no entry in languages[] has play: 'tr-TR'");
else expect(msg).toMatch(/en-US/); // en-US has no renders in the temp project: that error, not the tr-TR one
});
});