Onboarding live apps without owner questions for what the stores and the code prove: storebound onboard imports the live products and subscriptions with USD / base prices (catalog diff clean), contact values, the App Review contact and demo account (credentials.json, masked), sign-in for review from Apple's review detail and auth code, and the account deletion page from the app's site; App Store keywords count characters (live fields up to 265 bytes accepted); validate accepts the 6.5-inch iPhone set and Play's default-language graphics fallback; Play Reporting API off gives the project's enable link and apps list falls back to local apps; accounts default <profile>; store-only apps (apps add --store --app-id) shown read-only in the desktop (pitfalls 43-52)

This commit is contained in:
CRTkafa 2026-10-13 07:25:01 +08:00
parent d2ce185441
commit e5f148e534
55 changed files with 1648 additions and 158 deletions

View file

@ -100,7 +100,7 @@ describe('Play account check with the real 403', () => {
const after = new Error(`GET /apps:search?pageSize=1000 -> 403 ${errorBody(SERVICE_DISABLED_BODY, 800)}`);
expect(playCheck('sb@example.com', { error: after }).status).toBe('api-disabled');
});
test('the CLI: check says api-disabled; list fails with the reason and the fix on one line', async () => {
test('the CLI: check says api-disabled with the project\'s link; list does not fail: the finding and the local apps (pitfall 46)', async () => {
playKey();
globalThis.fetch = (async (input: string | URL | Request) => {
const url = String(input instanceof Request ? input.url : input);
@ -110,17 +110,24 @@ describe('Play account check with the real 403', () => {
}) as typeof fetch;
const root = mkdtempSync(join(tmpdir(), 'sb-real-'));
const c = await checkAccount('play', root);
expect(c).toMatchObject({ status: 'api-disabled', principal: 'sb@example.com' });
await expect(listApps('play', root, false)).rejects.toThrow(/-> 403 \{"error":/);
expect(c).toMatchObject({ status: 'api-disabled', principal: 'sb@example.com', docs: 'https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com?project=123456789000' });
const savedReg = process.env.STOREBOUND_REGISTRY;
process.env.STOREBOUND_REGISTRY = join(root, 'projects.json');
const cwd = process.cwd();
process.chdir(root);
try {
let msg = '';
try { await appsRun(parseArgs(['list', '--store', 'play', '--json'], ['json', 'icons'])); } catch (e) { msg = (e as Error).message; }
expect(msg).not.toContain('\n');
expect(msg).toContain('Reporting API is off');
expect(msg).toContain('Fix: Google Cloud console');
} finally { process.chdir(cwd); }
const r = await listApps('play', root, false);
expect(r.apps).toEqual([]);
expect(r.warnings[0]).not.toContain('\n');
expect(r.warnings[0]).toContain('Reporting API is off');
expect(r.warnings[0]).toContain('Fix: Enable "Google Play Developer Reporting API" for that project: https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com?project=123456789000');
let failed = false;
try { await appsRun(parseArgs(['list', '--store', 'play', '--json'], ['json', 'icons'])); } catch { failed = true; }
expect(failed).toBe(false);
} finally {
process.chdir(cwd);
if (savedReg === undefined) delete process.env.STOREBOUND_REGISTRY; else process.env.STOREBOUND_REGISTRY = savedReg;
}
});
});