* An app named like one of its bundle's own entries builds, its executable suffixed " App" The executable is named after the app and sits at an iOS bundle's root, beside Info.plist, Frameworks, PlugIns, assets and the rest: an app called "Assets" or "Frameworks" failed at the end of packaging with an unrelated error, and the build service refuses such names up front (expo/exact-build#89). executableName now adds " App" when the name would match one of those entries, case-insensitively, so the app builds; its display name is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]> * executableName's reserved list fits app.mjs's line cap Co-Authored-By: Claude Opus 5.5 <[email protected]> * Only an iOS or tvOS executable takes the " App" suffix; a Mac or Windows one keeps the app's name Fable and Astra: the suffix was in executableName, which every platform shares, so a Mac app named "Plans" or "Watch" would have become "Plans App.app", installed beside its old bundle, missed by uninstall and the DMG; Windows likewise. The collision exists only at a flat bundle's root. executableName is as before; appleExecutableName(app, true) adds the suffix, and only the iOS/tvOS paths ask for it: appleArtifacts for a non-Mac destination, the iOS Info.plist, install, agent-ios and the App Clip. The reserved set also takes PrivacyInfo.xcprivacy and ExactResources, which iosExecutableRefusal would otherwise still refuse, and the test ties it to APPLE_STATIC_TREES. Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
19 lines
1.3 KiB
JavaScript
19 lines
1.3 KiB
JavaScript
import { expect, test } from 'bun:test';
|
|
import { APPLE_STATIC_TREES } from '../host/apple/assets.mjs';
|
|
import { appleExecutableName, executableName } from './app.mjs';
|
|
|
|
// An iOS app named like one of its bundle root's own entries builds, under an executable that does not collide
|
|
// with it; a Mac or Windows executable, which shares no folder with them, keeps the app's name (expo/exact-build#89).
|
|
test("only a flat bundle's executable that would name one of the root's entries gets an App suffix", () => {
|
|
const app = (displayName) => ({ displayName, id: 'com.example.x' });
|
|
expect(appleExecutableName(app('Notes'), true)).toBe('Notes');
|
|
for (const name of ['Assets', 'assets', 'Frameworks', 'PlugIns', 'Info.plist', 'PrivacyInfo.xcprivacy', 'ExactResources', 'Watch', 'en.lproj', '[email protected]']) {
|
|
expect(appleExecutableName(app(name), true)).toBe(`${name} App`);
|
|
expect(appleExecutableName(app(name))).toBe(name);
|
|
expect(executableName(app(name))).toBe(name);
|
|
}
|
|
// Every tree the build copies to the bundle root is reserved, whatever its case.
|
|
for (const tree of APPLE_STATIC_TREES) expect(appleExecutableName(app(tree.toUpperCase()), true)).toBe(`${tree.toUpperCase()} App`);
|
|
expect(appleExecutableName(app('Café'), true)).toBe('Café'.normalize('NFD'));
|
|
});
|