From 6443a5c44211acd891f41f4b3c9a4515b2474cc8 Mon Sep 17 00:00:00 2001 From: CRT Date: Fri, 16 Oct 2026 06:14:02 +0800 Subject: [PATCH] neutral names in docs, tests and comments (no real app or project names) --- apps/desktop/src-tauri/tests/d5.rs | 6 +++--- apps/desktop/src-tauri/tests/machine.rs | 14 +++++++------- docs/desktop-release.md | 2 +- tests/desktop-dist.test.ts | 6 +++--- tests/machine.test.ts | 24 ++++++++++++------------ tests/onboard.test.ts | 2 +- tests/template-answers.test.ts | 2 +- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/apps/desktop/src-tauri/tests/d5.rs b/apps/desktop/src-tauri/tests/d5.rs index 7d20dce..27fd060 100644 --- a/apps/desktop/src-tauri/tests/d5.rs +++ b/apps/desktop/src-tauri/tests/d5.rs @@ -55,12 +55,12 @@ fn updater_has_a_real_minisign_key_and_only_storebound_dev() { #[test] fn open_deep_link_takes_one_plain_absolute_path() { let p = |s: &str| deep_link_open_path(&Url::parse(s).unwrap()); - let abs = if cfg!(windows) { "C:%5Cgames%5CDemo App" } else { "%2FUsers%2Fyou%2Fgames%2FDemo App" }; - let want = if cfg!(windows) { "C:\\games\\Demo App" } else { "/Users/you/games/Demo App" }; + let abs = if cfg!(windows) { "C:%5Cgames%5Cdemo-app" } else { "%2FUsers%2Fyou%2Fgames%2Fdemo-app" }; + let want = if cfg!(windows) { "C:\\games\\demo-app" } else { "/Users/you/games/demo-app" }; assert_eq!(p(&format!("storebound://open?path={abs}")), Some(PathBuf::from(want))); assert_eq!(p(&format!("storebound://open/?path={abs}")), Some(PathBuf::from(want))); for bad in [ - "storebound://open?path=games%2FDemo App".to_string(), + "storebound://open?path=games%2Fdemo-app".to_string(), "storebound://open?path=".to_string(), "storebound://open".to_string(), format!("storebound://open?path={abs}&path={abs}"), diff --git a/apps/desktop/src-tauri/tests/machine.rs b/apps/desktop/src-tauri/tests/machine.rs index 78d76ad..3dde508 100644 --- a/apps/desktop/src-tauri/tests/machine.rs +++ b/apps/desktop/src-tauri/tests/machine.rs @@ -46,7 +46,7 @@ fn ids_match_the_cli() { // cli/lib/workspace.ts accountId and cli/lib/registry.ts folderId give the same values assert_eq!(profiles::account_id(AccountKind::Apple, "acme"), "747351dbf2569d17"); assert_eq!(profiles::account_id(AccountKind::Play, "default"), "82a8c2561d950999"); - assert_eq!(registry::folder_id("/w/Star Dash"), "f4994b9746e7eb18"); + assert_eq!(registry::folder_id("/w/star-dash"), "c27311c5023dc3ba"); assert!(profiles::valid_name("default") && profiles::valid_name("acme-games.2") && !profiles::valid_name("../x") && !profiles::valid_name("-a")); assert_eq!(profiles::slug("Acme Games: Play!"), "acme-games-play"); assert_eq!(profiles::slug("???"), "account"); @@ -133,19 +133,19 @@ fn project(id: &str, path: &str, play: Option<&str>) -> Project { fn the_folder_list_is_the_machines() { let dir = tempfile::tempdir().unwrap(); let file = dir.path().join("projects.json"); - let mut st = State { projects: vec![project("aaaaaaaaaaaaaaaa", "/w/Star Dash", Some("acc"))], ..State::default() }; + let mut st = State { projects: vec![project("aaaaaaaaaaaaaaaa", "/w/star-dash", Some("acc"))], ..State::default() }; // first start: the app's list becomes the shared one assert!(!registry::sync(&mut st, &file).unwrap()); assert_eq!(registry::read(&file).unwrap()[0].id, "aaaaaaaaaaaaaaaa"); // the CLI adds a folder (storebound desktop / apps add): the app shows it, the first keeps its accounts let mut list = registry::read(&file).unwrap(); - list.push(Entry { id: registry::folder_id("/w/a game"), path: "/w/a game".into(), name: "a game".into(), added: "t".into() }); + list.push(Entry { id: registry::folder_id("/w/demo-game"), path: "/w/demo-game".into(), name: "demo-game".into(), added: "t".into() }); registry::write(&file, &list).unwrap(); assert!(registry::sync(&mut st, &file).unwrap()); - assert_eq!(st.projects.iter().map(|p| p.path.as_str()).collect::>(), vec!["/w/Star Dash", "/w/a game"]); + assert_eq!(st.projects.iter().map(|p| p.path.as_str()).collect::>(), vec!["/w/star-dash", "/w/demo-game"]); assert_eq!(st.projects[0].play_account.as_deref(), Some("acc")); // the CLI removes one (apps remove): it leaves the app with its overrides - st.overrides.ignored.push(format!("project:{}", registry::folder_id("/w/a game"))); + st.overrides.ignored.push(format!("project:{}", registry::folder_id("/w/demo-game"))); registry::write(&file, &list[..1]).unwrap(); assert!(registry::sync(&mut st, &file).unwrap()); assert_eq!(st.projects.len(), 1); @@ -155,7 +155,7 @@ fn the_folder_list_is_the_machines() { registry::write(&file, &[list[0].clone(), Entry { id: registry::folder_id("/w/cli"), path: "/w/cli".into(), name: "cli".into(), added: String::new() }]).unwrap(); registry::publish(&st, &file, &[]).unwrap(); let paths: Vec = registry::read(&file).unwrap().into_iter().map(|e| e.path).collect(); - assert_eq!(paths, vec!["/w/Star Dash", "/w/third", "/w/cli"]); + assert_eq!(paths, vec!["/w/star-dash", "/w/third", "/w/cli"]); // bad entries are dropped, not the whole file assert_eq!(registry::parse(r#"{"projects":[{"path":"rel"},{"path":"/a","id":"XYZ"},{"path":"/a"}]}"#).iter().map(|e| e.id.clone()).collect::>(), vec![registry::folder_id("/a")]); } @@ -173,7 +173,7 @@ fn store_only_apps_join_their_profiles_account_and_survive_folder_writes() { assert_eq!(apps.iter().map(|a| a.app_id.as_str()).collect::>(), vec!["6400000999", "com.example.legacy"]); assert_eq!(apps[1].bundle_id.as_deref(), Some("com.example.legacy")); // the app writes its folder list: the store-only entries stay - let mut st = State { projects: vec![project("aaaaaaaaaaaaaaaa", "/w/Star Dash", None)], ..State::default() }; + let mut st = State { projects: vec![project("aaaaaaaaaaaaaaaa", "/w/star-dash", None)], ..State::default() }; registry::publish(&st, &file, &[]).unwrap(); assert_eq!(registry::read_store_apps(&file).len(), 2); assert!(registry::sync(&mut st, &file).is_ok()); diff --git a/docs/desktop-release.md b/docs/desktop-release.md index 81eccac..05a2222 100644 --- a/docs/desktop-release.md +++ b/docs/desktop-release.md @@ -316,7 +316,7 @@ candidate on a tag (Jenkins still publishes site/, and `publish` storebound.dev/ 3. **Windows runner on the VDS (done).** Windows Server 2022 Standard (evaluation) in a KVM virtual machine, in Docker (`dockurr/windows:6.05`), `/srv/windows-runner/`. Forgejo runner 13.2.0 (`vds-windows`, label `windows:host`, capacity 1, job timeout 3 h), registered at the **CRT user level**: every CRT repository can use - it (storebound, Demo App, ...). + it (storebound, demo-app, ...). - **Resources:** 8 vCPUs, 12 GB RAM, a 150 GB disk (`storage/data.img`, sparse). `restart: unless-stopped`. - **Network:** nothing public. The web viewer (8006), RDP (3389) and the VM's OpenSSH (22, as host port 2223) are bound to 127.0.0.1 on the VDS; use an SSH tunnel (`ssh -L 8006:127.0.0.1:8006 root@`, then diff --git a/tests/desktop-dist.test.ts b/tests/desktop-dist.test.ts index ba1fb10..ff2771d 100644 --- a/tests/desktop-dist.test.ts +++ b/tests/desktop-dist.test.ts @@ -126,9 +126,9 @@ describe('the installed app', () => { expect(findInstalled('linux', {}, at([]), '/home/you', () => ['storeboundish.AppImage'])).toBeNull(); }); test('opened with the folder as a deep link, never through a shell', () => { - const link = openFolderLink('/Users/you/games/Demo App & co'); - expect(link).toBe('storebound://open?path=%2FUsers%2Fyou%2Fgames%2FDemo App%20%26%20co'); - expect(new URL(link).searchParams.get('path')).toBe('/Users/you/games/Demo App & co'); + const link = openFolderLink('/Users/you/games/demo-app & co'); + expect(link).toBe('storebound://open?path=%2FUsers%2Fyou%2Fgames%2Fdemo-app%20%26%20co'); + expect(new URL(link).searchParams.get('path')).toBe('/Users/you/games/demo-app & co'); expect(openCommand('darwin', { path: '/Applications/storebound.app', how: 'bundle' }, link)).toEqual(['open', '-b', 'dev.storebound.desktop', link]); expect(openCommand('darwin', { path: '/Applications/storebound.app', how: 'bundle' }, null)).toEqual(['open', '-b', 'dev.storebound.desktop']); expect(openCommand('win32', { path: 'C:\\x\\storebound-desktop.exe', how: 'exe' }, link)).toEqual(['C:\\x\\storebound-desktop.exe', link]); diff --git a/tests/machine.test.ts b/tests/machine.test.ts index e3da940..2d12675 100644 --- a/tests/machine.test.ts +++ b/tests/machine.test.ts @@ -66,7 +66,7 @@ describe('credentials: one machine, many projects', () => { writeFileSync(join(creds, 'default.json'), JSON.stringify({ ASC_KEY_ID: 'DEFAULT000', ASC_ISSUER_ID: 'iss', ASC_P8: PEM('x') })); expect(defaultProfile()).toBe('teamB'); // the project's own keys beat the pointer; a profile the project names beats both; env beats all - const a = project(base, 'Star Dash'); + const a = project(base, 'star-dash'); expect(ascKey(a).keyId).toBe('ABCDE12345'); const file = join(a, '.storebound', 'credentials.json'); writeFileSync(file, JSON.stringify({ ...JSON.parse(readFileSync(file, 'utf8')), account: 'teamA' })); @@ -84,7 +84,7 @@ describe('credentials: one machine, many projects', () => { })); test('project-only values from the project, store keys from the profile, env over everything', () => machine(({ creds, base }) => { - const a = project(base, 'Star Dash'); + const a = project(base, 'star-dash'); // the project's own keys work without any profile expect(ascKey(a).keyId).toBe('ABCDE12345'); mkdirSync(creds, { recursive: true }); @@ -113,7 +113,7 @@ describe('credentials: one machine, many projects', () => { })); test('accounts import: two projects with the same Apple key and Play account -> one profile, 0600 files, projects stay valid', () => machine(({ creds, base }) => { - const a = project(base, 'Star Dash'), b = project(base, 'a game'); + const a = project(base, 'star-dash'), b = project(base, 'demo-game'); const dry = planImport(a); expect(dry.profile).toBe('default'); expect(dry.reuse).toBe(false); @@ -136,7 +136,7 @@ describe('credentials: one machine, many projects', () => { const projA = JSON.parse(readFileSync(join(a, '.storebound', 'credentials.json'), 'utf8')); expect(projA.account).toBe('default'); expect(projA.ASC_KEY_ID).toBeUndefined(); - expect(projA.ANDROID_KEYSTORE).toBe('Star Dash.jks'); + expect(projA.ANDROID_KEYSTORE).toBe('star-dash.jks'); expect(ascKey(a).pem).toContain('apple-secret-sentinel'); expect(playServiceAccount(a).client_email).toBe('release@example.com'); // the second project with the same account: the same profile, its files unchanged @@ -145,7 +145,7 @@ describe('credentials: one machine, many projects', () => { expect(second.reuse).toBe(true); expect(second.writes.filter(w => w.path.startsWith(creds)).map(w => w.action)).toEqual(['same']); applyImport(second); - expect(JSON.parse(readFileSync(join(b, '.storebound', 'credentials.json'), 'utf8')).ANDROID_KEYSTORE_PASSWORD).toBe('a game-pw'); + expect(JSON.parse(readFileSync(join(b, '.storebound', 'credentials.json'), 'utf8')).ANDROID_KEYSTORE_PASSWORD).toBe('demo-game-pw'); expect(ascKey(b).keyId).toBe('ABCDE12345'); // running it again changes nothing expect(planImport(b).writes.every(w => w.action === 'same')).toBe(true); @@ -157,13 +157,13 @@ describe('credentials: one machine, many projects', () => { expect(third.profile).toBe('other-studio'); applyImport(third); expect(ascKey(c).keyId).toBe('ZZZZZ99999'); - expect(ascKey(a).keyId).toBe('ABCDE12345'); // "account": "default" still points Star Dash at its own + expect(ascKey(a).keyId).toBe('ABCDE12345'); // "account": "default" still points star-dash at its own expect(useProfile(c, 'default')).toContain('credentials.json'); expect(() => useProfile(c, 'missing')).toThrow(/no profile/); })); test('the import command prints paths and names, never key values', () => machine(({ base }) => { - const a = project(base, 'Star Dash'); + const a = project(base, 'star-dash'); const r = Bun.spawnSync(['bun', join(ROOT, 'cli', 'index.ts'), 'accounts', 'import', '--dry', '--dir', a], { env: { ...process.env, STOREBOUND_NO_NETWORK: '1' } }); const out = r.stdout.toString() + r.stderr.toString(); expect(r.exitCode).toBe(0); @@ -179,14 +179,14 @@ describe('credentials: one machine, many projects', () => { describe('the machine\'s app folder list', () => { test('add, re-add, remove; ids are the desktop export ids; bad entries are dropped', () => machine(({ base }) => { const r0 = { version: 1 as const, projects: [] }; - const { registry, added } = withFolder(r0, '/w/Star Dash', 'Star Dash', 't'); + const { registry, added } = withFolder(r0, '/w/star-dash', 'Star Dash', 't'); expect(added).toBe(true); - expect(registry.projects[0]!.id).toBe(desktopProjectId('/w/Star Dash')); - expect(withFolder(registry, '/w/Star Dash/', undefined, 't').added).toBe(false); - expect(withoutFolder(registry, folderId('/w/Star Dash')).removed?.name).toBe('Star Dash'); + expect(registry.projects[0]!.id).toBe(desktopProjectId('/w/star-dash')); + expect(withFolder(registry, '/w/star-dash/', undefined, 't').added).toBe(false); + expect(withoutFolder(registry, folderId('/w/star-dash')).removed?.name).toBe('Star Dash'); expect(parseRegistry('{"projects":[{"path":"relative"},{"path":"/a","id":"zz"},{"path":"/a"}]}').projects.map(p => [p.path, p.id])).toEqual([['/a', folderId('/a')]]); expect(parseRegistry('not json').projects).toEqual([]); - const dir = project(base, 'a game'); + const dir = project(base, 'demo-game'); expect(addFolder(dir).added).toBe(true); expect(addFolder(dir).added).toBe(false); expect(readRegistry().projects.map(p => p.path)).toEqual([dir]); diff --git a/tests/onboard.test.ts b/tests/onboard.test.ts index 5273bd3..a0263eb 100644 --- a/tests/onboard.test.ts +++ b/tests/onboard.test.ts @@ -317,7 +317,7 @@ describe('store-only apps in the machine list', () => { expect(reg.storeApps).toEqual([{ id: storeAppId('apple', '6400000999'), store: 'apple', appId: '6400000999', account: 'teamA', name: 'Demo App', bundleId: null, added: reg.storeApps![0]!.added }]); expect(reg.projects).toEqual([]); // a folder added later keeps the store-only entry - const f = withFolder(reg, '/w/Star Dash', undefined, 't').registry; + const f = withFolder(reg, '/w/star-dash', undefined, 't').registry; expect(f.storeApps).toHaveLength(1); expect(parseRegistry(JSON.stringify(f)).storeApps).toHaveLength(1); const again = await capture(() => apps(parseArgs(['add', '--store', 'apple', '--app-id', '6400000999', '--account', 'teamA', '--name', 'Demo App'], []))); diff --git a/tests/template-answers.test.ts b/tests/template-answers.test.ts index 01eac32..92f2d61 100644 --- a/tests/template-answers.test.ts +++ b/tests/template-answers.test.ts @@ -51,7 +51,7 @@ describe('template answers', () => { }); test('a config from before `unanswered` is recognised by the template values; [] means answered', () => { - const legacy = { app: { name: 'Demo Blast', copyright: '2026 Example Studio' }, apple: { bundleId: 'x', info: { reviewNotes: 'mine', ageRating: { advertising: true } } }, + const legacy = { app: { name: 'DEMO BLAST', copyright: '2026 Example Studio' }, apple: { bundleId: 'x', info: { reviewNotes: 'mine', ageRating: { advertising: true } } }, dataSafety: { collectsData: true, encryptedInTransit: true, accountCreation: ['PSL_ACM_NONE'], data: { PSL_APPROX_LOCATION: { shared: true, collect: ['analytics', 'advertising', 'fraud'], share: ['analytics', 'advertising', 'fraud'] }, PSL_USER_INTERACTION: { shared: true, collect: ['analytics', 'advertising'], share: ['analytics', 'advertising'] },