store-only apps edit their listing on the store (storebound listing live / set: old -> new per field with the checks, a PATCH of only the edited fields; serve listing.set is the one store-only write, its token bound to the store ids; policy.rs STORE_ONLY_WRITES, write_with_confirm for store targets); screenshot captions per language and scene edited as a text edit of the shots copy JSON (JSON files keep their layout); Play content rating, target audience and App content answers in App info; docs/console-parity.md after the editors (73 rows: 55 complete, 18 with the reason) and tests/console-parity.test.ts keeping it honest
This commit is contained in:
parent
3cea2af4e1
commit
7ac028421a
33 changed files with 852 additions and 157 deletions
|
|
@ -80,6 +80,8 @@ describe('config-path: one value set by path, the rest of the file byte for byte
|
|||
expect(out).toContain("apple: { bundleId: 'com.example.app', info: { reviewNotes: 'Line one\\nIt\\'s line two' } },");
|
||||
const app = setByPath(CFG, 'storebound.config.ts', 'app.marketingUrl', 'https://example.com/m');
|
||||
expect(app).toContain(" contactEmail: 'support@example.com',\n marketingUrl: 'https://example.com/m',\n },");
|
||||
// after a last member without a trailing comma (and its comment)
|
||||
expect(setByPath('export default {\n a: 1 // one\n};\n', 'c.ts', 'b', 2)).toBe('export default {\n a: 1, // one\n b: 2,\n};\n');
|
||||
});
|
||||
test('removes a key; the edited file still loads to the same object otherwise', async () => {
|
||||
const out = setByPath(CFG, 'storebound.config.ts', 'app.website', undefined);
|
||||
|
|
@ -301,3 +303,30 @@ describe('CLI: storebound edit on a copy of the demo app', () => {
|
|||
expect(statSync(f).mode & 0o777).toBe(0o600);
|
||||
});
|
||||
});
|
||||
|
||||
describe('JSON files edited as text (the shots copy file keeps one scene per line)', () => {
|
||||
test('a caption line changes, the other lines and the layout stay', async () => {
|
||||
const dir = mkdtempSync(join(tmpdir(), 'sb-copy-'));
|
||||
cpSync(join(ROOT, 'examples', 'demo-app'), dir, { recursive: true });
|
||||
const file = join(dir, 'store', 'shots', 'copy.json');
|
||||
const before = readFileSync(file, 'utf8');
|
||||
const ops = JSON.stringify([{ kind: 'shotsCopy', lang: 'en', scene: 'lists', field: 'title', line: 1, value: 'in one tidy place' }, { kind: 'shotsCopy', lang: 'tr', scene: 'share', field: 'sub', value: 'Birlikte düzenleyin.' }]);
|
||||
const r = await Bun.$`bun ${CLI} edit --ops ${ops}`.cwd(dir).quiet().nothrow();
|
||||
expect(r.exitCode).toBe(0);
|
||||
const after = readFileSync(file, 'utf8');
|
||||
const changed = after.split('\n').filter((l, i) => l !== before.split('\n')[i]);
|
||||
expect(changed).toHaveLength(2);
|
||||
expect(changed[0]).toContain('"title": ["Every list,","in one tidy place"]');
|
||||
expect(JSON.parse(after).tr.share.sub).toBe('Birlikte düzenleyin.');
|
||||
expect(after.split('\n').length).toBe(before.split('\n').length);
|
||||
});
|
||||
test('setByPath on JSON: insert and remove without trailing commas', () => {
|
||||
const j = '{\n "a": { "x": 1 },\n "b": 2\n}\n';
|
||||
const ins = setByPath(j, 'f.json', 'c', 'new');
|
||||
expect(JSON.parse(ins)).toEqual({ a: { x: 1 }, b: 2, c: 'new' });
|
||||
expect(ins).toContain(' "b": 2,\n "c": "new"\n}');
|
||||
const rem = setByPath(j, 'f.json', 'b', undefined);
|
||||
expect(JSON.parse(rem)).toEqual({ a: { x: 1 } });
|
||||
expect(JSON.parse(setByPath(j, 'f.json', 'a.y', [1, 2]))).toEqual({ a: { x: 1, y: [1, 2] }, b: 2 });
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue