@absolutejs/absolute 0.20.0-beta.22 → 0.20.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +411 -80
- package/dist/mobile/index.js +210 -16
- package/dist/mobile/index.js.map +4 -4
- package/dist/src/mobile/androidTestReport.d.ts +14 -0
- package/dist/src/mobile/deviceCapabilities.d.ts +7 -1
- package/dist/src/mobile/iosTestReport.d.ts +7 -41
- package/dist/src/mobile/nativeTestReport.d.ts +72 -0
- package/package.json +6 -3
package/dist/cli/index.js
CHANGED
|
@@ -6763,7 +6763,7 @@ var init_syncSchema = __esm(() => {
|
|
|
6763
6763
|
import { readFileSync as readFileSync12 } from "fs";
|
|
6764
6764
|
import { extname as extname5, join as join20, relative as relative11, resolve as resolve16 } from "path";
|
|
6765
6765
|
import ts4 from "typescript";
|
|
6766
|
-
var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/devices-capacitor", SOURCE_GLOB, IGNORED_DIRECTORIES, IDENTIFIER_PATTERN, CAPACITOR_MODULE_PATTERN, CAPACITOR_PACKAGE_PATTERN, ANDROID_PERMISSION_PATTERN, IOS_USAGE_DESCRIPTIONS, object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson = (path) => {
|
|
6766
|
+
var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/devices-capacitor", SOURCE_GLOB, IGNORED_DIRECTORIES, IDENTIFIER_PATTERN, CAPACITOR_MODULE_PATTERN, CAPACITOR_PACKAGE_PATTERN, ANDROID_PERMISSION_PATTERN, IOS_USAGE_DESCRIPTIONS, IOS_PRIVACY_ACCESSED_API_REASONS, IOS_PRIVACY_ACCESSED_APIS, object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson = (path) => {
|
|
6767
6767
|
const value = JSON.parse(readFileSync12(path, "utf8"));
|
|
6768
6768
|
if (!object2(value))
|
|
6769
6769
|
throw new TypeError(`${path} must contain an object.`);
|
|
@@ -6781,15 +6781,37 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6781
6781
|
if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
|
|
6782
6782
|
throw new TypeError(`${field}.permissions must contain Android permission names.`);
|
|
6783
6783
|
return [...permissions];
|
|
6784
|
-
},
|
|
6784
|
+
}, iosPrivacyAccessedApis = (value, field) => {
|
|
6785
6785
|
if (value === undefined)
|
|
6786
6786
|
return;
|
|
6787
6787
|
if (!object2(value))
|
|
6788
6788
|
throw new TypeError(`${field} must be an object.`);
|
|
6789
|
-
const
|
|
6790
|
-
|
|
6789
|
+
const privacy = {};
|
|
6790
|
+
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
6791
|
+
const reasons = value[api];
|
|
6792
|
+
if (reasons === undefined)
|
|
6793
|
+
continue;
|
|
6794
|
+
const supported = IOS_PRIVACY_ACCESSED_API_REASONS[api];
|
|
6795
|
+
if (!Array.isArray(reasons) || reasons.length === 0 || !reasons.every((reason) => typeof reason === "string" && supported.has(reason)))
|
|
6796
|
+
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
6797
|
+
privacy[api] = [...reasons];
|
|
6798
|
+
}
|
|
6799
|
+
if (Object.keys(value).some((api) => !IOS_PRIVACY_ACCESSED_APIS.some((known) => known === api)))
|
|
6800
|
+
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
6801
|
+
return privacy;
|
|
6802
|
+
}, iosNativeRequirements = (value, field) => {
|
|
6803
|
+
if (value === undefined)
|
|
6804
|
+
return;
|
|
6805
|
+
if (!object2(value))
|
|
6806
|
+
throw new TypeError(`${field} must be an object.`);
|
|
6807
|
+
const { privacyAccessedApis, usageDescriptions } = value;
|
|
6808
|
+
if (usageDescriptions !== undefined && (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose))))
|
|
6791
6809
|
throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
|
|
6792
|
-
|
|
6810
|
+
const privacy = iosPrivacyAccessedApis(privacyAccessedApis, `${field}.privacyAccessedApis`);
|
|
6811
|
+
return {
|
|
6812
|
+
...privacy === undefined ? {} : { privacyAccessedApis: privacy },
|
|
6813
|
+
...usageDescriptions === undefined ? {} : { usageDescriptions: [...usageDescriptions] }
|
|
6814
|
+
};
|
|
6793
6815
|
}, parseProvider = (name, value) => {
|
|
6794
6816
|
if (!IDENTIFIER_PATTERN.test(name))
|
|
6795
6817
|
throw new TypeError("Device capability names must be identifiers.");
|
|
@@ -6810,10 +6832,10 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6810
6832
|
throw new TypeError(`${name}.native must be an object.`);
|
|
6811
6833
|
const { android, ios } = nativeMetadata;
|
|
6812
6834
|
const permissions = androidPermissions(android, `${name}.native.android`);
|
|
6813
|
-
const
|
|
6835
|
+
const iosRequirements = iosNativeRequirements(ios, `${name}.native.ios`);
|
|
6814
6836
|
native = {
|
|
6815
6837
|
...permissions === undefined ? {} : { android: { permissions } },
|
|
6816
|
-
...
|
|
6838
|
+
...iosRequirements === undefined ? {} : { ios: iosRequirements }
|
|
6817
6839
|
};
|
|
6818
6840
|
}
|
|
6819
6841
|
return {
|
|
@@ -6822,14 +6844,32 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6822
6844
|
...native === undefined ? {} : { native },
|
|
6823
6845
|
packages: [...value.packages]
|
|
6824
6846
|
};
|
|
6825
|
-
}, absoluteDeviceNativeRequirements = (plan) =>
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6847
|
+
}, absoluteDeviceNativeRequirements = (plan) => {
|
|
6848
|
+
const privacy = plan.capabilities.reduce((requirements, name) => {
|
|
6849
|
+
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
6850
|
+
const reasons = plan.providers[name]?.native?.ios?.privacyAccessedApis?.[api] ?? [];
|
|
6851
|
+
if (reasons.length === 0)
|
|
6852
|
+
continue;
|
|
6853
|
+
const current = requirements[api] ?? new Set;
|
|
6854
|
+
for (const reason of reasons)
|
|
6855
|
+
current.add(reason);
|
|
6856
|
+
requirements[api] = current;
|
|
6857
|
+
}
|
|
6858
|
+
return requirements;
|
|
6859
|
+
}, {});
|
|
6860
|
+
return {
|
|
6861
|
+
androidPermissions: [
|
|
6862
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
|
|
6863
|
+
].sort(),
|
|
6864
|
+
iosPrivacyAccessedApis: IOS_PRIVACY_ACCESSED_APIS.flatMap((api) => {
|
|
6865
|
+
const reasons = privacy[api];
|
|
6866
|
+
return reasons ? [{ api, reasons: [...reasons].sort() }] : [];
|
|
6867
|
+
}),
|
|
6868
|
+
iosUsageDescriptions: [
|
|
6869
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
|
|
6870
|
+
].sort()
|
|
6871
|
+
};
|
|
6872
|
+
}, loadAbsoluteDeviceCapabilityProviders = (projectRoot) => {
|
|
6833
6873
|
const path = join20(resolve16(projectRoot), "node_modules", CAPACITOR_ADAPTER, "package.json");
|
|
6834
6874
|
const manifest = readJson(path);
|
|
6835
6875
|
const { absolutejs } = manifest;
|
|
@@ -6953,6 +6993,12 @@ var init_deviceCapabilities = __esm(() => {
|
|
|
6953
6993
|
"photo-library",
|
|
6954
6994
|
"photo-library-add"
|
|
6955
6995
|
]);
|
|
6996
|
+
IOS_PRIVACY_ACCESSED_API_REASONS = {
|
|
6997
|
+
NSPrivacyAccessedAPICategoryFileTimestamp: new Set(["C617.1"])
|
|
6998
|
+
};
|
|
6999
|
+
IOS_PRIVACY_ACCESSED_APIS = [
|
|
7000
|
+
"NSPrivacyAccessedAPICategoryFileTimestamp"
|
|
7001
|
+
];
|
|
6956
7002
|
});
|
|
6957
7003
|
|
|
6958
7004
|
// src/mobile/buildPipeline.ts
|
|
@@ -16469,7 +16515,7 @@ var init_nativeDeepLinks = () => {};
|
|
|
16469
16515
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
16470
16516
|
import { readFile as readFile12, rename as rename9, writeFile as writeFile10 } from "fs/promises";
|
|
16471
16517
|
import { join as join47 } from "path";
|
|
16472
|
-
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->", NOT_FOUND2 = -1, escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile2 = async (path, source) => {
|
|
16518
|
+
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->", NOT_FOUND2 = -1, IOS_PRIVACY_FILE_REFERENCE = "A85D0C000000000000000001", IOS_PRIVACY_BUILD_FILE = "A85D0C000000000000000002", escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile2 = async (path, source) => {
|
|
16473
16519
|
const current = await readFile12(path, "utf8");
|
|
16474
16520
|
if (current === source)
|
|
16475
16521
|
return false;
|
|
@@ -16477,6 +16523,14 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16477
16523
|
await writeFile10(temporary, source, { flag: "wx" });
|
|
16478
16524
|
await rename9(temporary, path);
|
|
16479
16525
|
return true;
|
|
16526
|
+
}, optionalSource = async (path) => {
|
|
16527
|
+
try {
|
|
16528
|
+
return await readFile12(path, "utf8");
|
|
16529
|
+
} catch (error) {
|
|
16530
|
+
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
16531
|
+
return null;
|
|
16532
|
+
throw error;
|
|
16533
|
+
}
|
|
16480
16534
|
}, managed = (source, region, insertion) => {
|
|
16481
16535
|
const start2 = source.indexOf(START_MARKER2);
|
|
16482
16536
|
const end = source.indexOf(END_MARKER2);
|
|
@@ -16505,6 +16559,129 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16505
16559
|
if (purpose === "location-always")
|
|
16506
16560
|
return `${appName} does not track location in the background; this description supports the foreground location provider required by the native runtime.`;
|
|
16507
16561
|
return `${appName} adds to your photo library only for photo actions you choose.`;
|
|
16562
|
+
}, privacyEntries = (requirements) => requirements.iosPrivacyAccessedApis.map(({ api, reasons }) => ` <dict>
|
|
16563
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
16564
|
+
<string>${escapeXml2(api)}</string>
|
|
16565
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
16566
|
+
<array>
|
|
16567
|
+
${reasons.map((reason) => ` <string>${escapeXml2(reason)}</string>`).join(`
|
|
16568
|
+
`)}
|
|
16569
|
+
</array>
|
|
16570
|
+
</dict>`).join(`
|
|
16571
|
+
`), privacyManifestSource = (source, requirements) => {
|
|
16572
|
+
const entries = privacyEntries(requirements);
|
|
16573
|
+
const wholeRegion = entries ? ` ${START_MARKER2}
|
|
16574
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
16575
|
+
<array>
|
|
16576
|
+
${entries}
|
|
16577
|
+
</array>
|
|
16578
|
+
${END_MARKER2}
|
|
16579
|
+
` : "";
|
|
16580
|
+
if (source === null)
|
|
16581
|
+
return entries ? `<?xml version="1.0" encoding="UTF-8"?>
|
|
16582
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
16583
|
+
<plist version="1.0">
|
|
16584
|
+
<dict>
|
|
16585
|
+
${wholeRegion} <key>NSPrivacyCollectedDataTypes</key>
|
|
16586
|
+
<array/>
|
|
16587
|
+
<key>NSPrivacyTracking</key>
|
|
16588
|
+
<false/>
|
|
16589
|
+
</dict>
|
|
16590
|
+
</plist>
|
|
16591
|
+
` : null;
|
|
16592
|
+
const start2 = source.indexOf(START_MARKER2);
|
|
16593
|
+
if (start2 !== NOT_FOUND2) {
|
|
16594
|
+
const end = source.indexOf(END_MARKER2);
|
|
16595
|
+
if (end === NOT_FOUND2)
|
|
16596
|
+
throw new TypeError("AbsoluteJS device-capability ownership markers are malformed.");
|
|
16597
|
+
const owned = source.slice(start2, end);
|
|
16598
|
+
const ownsWholeKey = owned.includes("NSPrivacyAccessedAPITypes");
|
|
16599
|
+
let region = "";
|
|
16600
|
+
if (ownsWholeKey)
|
|
16601
|
+
region = wholeRegion;
|
|
16602
|
+
else if (entries)
|
|
16603
|
+
region = ` ${START_MARKER2}
|
|
16604
|
+
${entries}
|
|
16605
|
+
${END_MARKER2}
|
|
16606
|
+
`;
|
|
16607
|
+
return managed(source, region, source.lastIndexOf("</dict>"));
|
|
16608
|
+
}
|
|
16609
|
+
const key = source.indexOf("<key>NSPrivacyAccessedAPITypes</key>");
|
|
16610
|
+
if (key === NOT_FOUND2)
|
|
16611
|
+
return managed(source, wholeRegion, source.lastIndexOf("</dict>"));
|
|
16612
|
+
if (!entries)
|
|
16613
|
+
return source;
|
|
16614
|
+
const array = source.indexOf("<array>", key);
|
|
16615
|
+
if (array === NOT_FOUND2)
|
|
16616
|
+
throw new TypeError("iOS PrivacyInfo.xcprivacy has a malformed NSPrivacyAccessedAPITypes value.");
|
|
16617
|
+
const insertion = source.indexOf(`
|
|
16618
|
+
`, array);
|
|
16619
|
+
if (insertion === NOT_FOUND2)
|
|
16620
|
+
throw new TypeError("iOS PrivacyInfo.xcprivacy array is malformed.");
|
|
16621
|
+
return managed(source, ` ${START_MARKER2}
|
|
16622
|
+
${entries}
|
|
16623
|
+
${END_MARKER2}
|
|
16624
|
+
`, insertion + 1);
|
|
16625
|
+
}, writeIosPrivacyManifest = async (path, current, source) => {
|
|
16626
|
+
if (source === null)
|
|
16627
|
+
return false;
|
|
16628
|
+
if (current !== null)
|
|
16629
|
+
return writeChangedFile2(path, source);
|
|
16630
|
+
await writeFile10(path, source, { flag: "wx" });
|
|
16631
|
+
return true;
|
|
16632
|
+
}, configureIosPrivacyProject = async (config, requirements) => {
|
|
16633
|
+
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
16634
|
+
return false;
|
|
16635
|
+
const projectPath = join47(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
16636
|
+
const project = await readFile12(projectPath, "utf8");
|
|
16637
|
+
return writeChangedFile2(projectPath, addIosPrivacyProjectReference(project));
|
|
16638
|
+
}, addIosPrivacyProjectReference = (source) => {
|
|
16639
|
+
const fileMatch = source.match(/([A-F0-9]{24}) \/\* PrivacyInfo\.xcprivacy \*\/ = \{isa = PBXFileReference;/u);
|
|
16640
|
+
const fileReference = fileMatch?.[1] ?? IOS_PRIVACY_FILE_REFERENCE;
|
|
16641
|
+
const buildMatch = source.match(/([A-F0-9]{24}) \/\* PrivacyInfo\.xcprivacy in Resources \*\/ = \{isa = PBXBuildFile;/u);
|
|
16642
|
+
const buildFile = buildMatch?.[1] ?? IOS_PRIVACY_BUILD_FILE;
|
|
16643
|
+
if (!fileMatch && source.includes(fileReference) || !buildMatch && source.includes(buildFile))
|
|
16644
|
+
throw new TypeError("AbsoluteJS iOS privacy-manifest identifiers collide.");
|
|
16645
|
+
let next = source;
|
|
16646
|
+
if (!buildMatch) {
|
|
16647
|
+
const marker = "/* End PBXBuildFile section */";
|
|
16648
|
+
const index = next.indexOf(marker);
|
|
16649
|
+
if (index === NOT_FOUND2)
|
|
16650
|
+
throw new TypeError("Could not find the iOS PBXBuildFile section.");
|
|
16651
|
+
next = `${next.slice(0, index)} ${buildFile} /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = ${fileReference} /* PrivacyInfo.xcprivacy */; };
|
|
16652
|
+
${next.slice(index)}`;
|
|
16653
|
+
}
|
|
16654
|
+
if (!fileMatch) {
|
|
16655
|
+
const marker = "/* End PBXFileReference section */";
|
|
16656
|
+
const index = next.indexOf(marker);
|
|
16657
|
+
if (index === NOT_FOUND2)
|
|
16658
|
+
throw new TypeError("Could not find the iOS PBXFileReference section.");
|
|
16659
|
+
next = `${next.slice(0, index)} ${fileReference} /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
|
16660
|
+
${next.slice(index)}`;
|
|
16661
|
+
}
|
|
16662
|
+
const groupsStart = next.indexOf("/* Begin PBXGroup section */");
|
|
16663
|
+
const groupsEnd = next.indexOf("/* End PBXGroup section */");
|
|
16664
|
+
const groups = next.slice(groupsStart, groupsEnd);
|
|
16665
|
+
if (!groups.includes(`${fileReference} /* PrivacyInfo.xcprivacy */`)) {
|
|
16666
|
+
const appGroup = groups.match(/[A-F0-9]{24} \/\* App \*\/ = \{\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = \(\n/u);
|
|
16667
|
+
if (!appGroup || appGroup.index === undefined)
|
|
16668
|
+
throw new TypeError("Could not find the iOS App PBXGroup.");
|
|
16669
|
+
const index = groupsStart + appGroup.index + appGroup[0].length;
|
|
16670
|
+
next = `${next.slice(0, index)} ${fileReference} /* PrivacyInfo.xcprivacy */,
|
|
16671
|
+
${next.slice(index)}`;
|
|
16672
|
+
}
|
|
16673
|
+
const resourcesStart = next.indexOf("/* Begin PBXResourcesBuildPhase section */");
|
|
16674
|
+
const resourcesEnd = next.indexOf("/* End PBXResourcesBuildPhase section */");
|
|
16675
|
+
const resources = next.slice(resourcesStart, resourcesEnd);
|
|
16676
|
+
if (!resources.includes(`${buildFile} /* PrivacyInfo.xcprivacy in Resources */`)) {
|
|
16677
|
+
const files = resources.match(/isa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = \d+;\n\t\t\tfiles = \(\n/u);
|
|
16678
|
+
if (!files || files.index === undefined)
|
|
16679
|
+
throw new TypeError("Could not find the iOS Resources build phase.");
|
|
16680
|
+
const index = resourcesStart + files.index + files[0].length;
|
|
16681
|
+
next = `${next.slice(0, index)} ${buildFile} /* PrivacyInfo.xcprivacy in Resources */,
|
|
16682
|
+
${next.slice(index)}`;
|
|
16683
|
+
}
|
|
16684
|
+
return next;
|
|
16508
16685
|
}, configureIos2 = async (config, plan) => {
|
|
16509
16686
|
const path = join47(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
16510
16687
|
const source = await readFile12(path, "utf8");
|
|
@@ -16516,7 +16693,15 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16516
16693
|
${content}
|
|
16517
16694
|
${END_MARKER2}
|
|
16518
16695
|
` : "";
|
|
16519
|
-
|
|
16696
|
+
const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
16697
|
+
const privacyPath = join47(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
16698
|
+
const privacyCurrent = await optionalSource(privacyPath);
|
|
16699
|
+
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
16700
|
+
const [privacyChanged, projectChanged] = await Promise.all([
|
|
16701
|
+
writeIosPrivacyManifest(privacyPath, privacyCurrent, privacySource),
|
|
16702
|
+
configureIosPrivacyProject(config, requirements)
|
|
16703
|
+
]);
|
|
16704
|
+
return infoChanged || privacyChanged || projectChanged;
|
|
16520
16705
|
}, configureAndroid2 = async (config, plan) => {
|
|
16521
16706
|
const path = join47(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
16522
16707
|
const source = await readFile12(path, "utf8");
|
|
@@ -17706,24 +17891,25 @@ var init_iosConformance = __esm(() => {
|
|
|
17706
17891
|
HMR_LINE = new RegExp(String.raw`\[hmr:ios\]\s+([^\n]*?)\s+(applied in|falling back to reload after|failed after)\s+(\d+)ms(?:; server\s+(\d+)ms, client\s+(\d+)ms)?`, "u");
|
|
17707
17892
|
});
|
|
17708
17893
|
|
|
17709
|
-
// src/mobile/
|
|
17894
|
+
// src/mobile/nativeTestReport.ts
|
|
17710
17895
|
import { mkdir as mkdir13, readFile as readFile18, writeFile as writeFile15 } from "fs/promises";
|
|
17711
17896
|
import { join as join51 } from "path";
|
|
17712
|
-
var
|
|
17713
|
-
`, "<br>"),
|
|
17714
|
-
const { run
|
|
17715
|
-
const evidence = run.screenshot ? `
|
|
17897
|
+
var secretPattern, bearerPattern, coordinatePattern, sanitizeNativeReportText = (value) => value.replace(bearerPattern, "Bearer [REDACTED]").replace(secretPattern, "$1$2[REDACTED]").replace(coordinatePattern, "$1$2[REDACTED]").replace(/(https?:\/\/[^\s?#]+)[?#][^\s]*/giu, "$1?[REDACTED]"), markdownCell = (value) => sanitizeNativeReportText(value).replaceAll("|", "\\|").replaceAll(`
|
|
17898
|
+
`, "<br>"), createAbsoluteNativeAutomatedChecks = (run) => {
|
|
17899
|
+
const target = `${run.targetKind} ${run.targetId}`;
|
|
17900
|
+
const evidence = run.screenshot ? `Screenshot: ${run.screenshot}` : undefined;
|
|
17716
17901
|
let hmrResult = "NOT_RUN";
|
|
17717
17902
|
if (run.hmr)
|
|
17718
17903
|
hmrResult = run.hmr.outcome === "failed" ? "FAIL" : "PASS";
|
|
17719
|
-
const
|
|
17904
|
+
const routeDetails = run.routes?.length ? ` Routes: ${run.routes.join(", ")}.` : "";
|
|
17905
|
+
return [
|
|
17720
17906
|
{
|
|
17721
|
-
details: `Captured
|
|
17907
|
+
details: `Captured host, toolchain, Bun, and AbsoluteJS metadata for ${target}.`,
|
|
17722
17908
|
id: "AUTO-SETUP-01",
|
|
17723
17909
|
result: "PASS"
|
|
17724
17910
|
},
|
|
17725
17911
|
{
|
|
17726
|
-
details: run.status === "pass" ? `The app
|
|
17912
|
+
details: run.status === "pass" ? `The app launched and connected to native HMR in ${run.durationMs}ms.${routeDetails}` : `The automated native run failed after ${run.durationMs}ms: ${run.error ?? "No error detail was available."}`,
|
|
17727
17913
|
...evidence ? { evidence } : {},
|
|
17728
17914
|
id: "AUTO-DEV-01",
|
|
17729
17915
|
result: run.status === "pass" ? "PASS" : "FAIL"
|
|
@@ -17734,55 +17920,46 @@ var MANUAL_CHECKS, secretPattern, bearerPattern, coordinatePattern, sanitizeIosR
|
|
|
17734
17920
|
result: hmrResult
|
|
17735
17921
|
},
|
|
17736
17922
|
{
|
|
17737
|
-
details: run.screenshot ? "A
|
|
17923
|
+
details: run.screenshot ? "A target screenshot was captured. Visually review it before sharing this directory." : "No target screenshot was captured.",
|
|
17738
17924
|
...evidence ? { evidence } : {},
|
|
17739
17925
|
id: "AUTO-ARTIFACT-01",
|
|
17740
17926
|
result: run.screenshot ? "PASS" : "FAIL"
|
|
17741
17927
|
}
|
|
17742
17928
|
];
|
|
17743
|
-
|
|
17929
|
+
}, createAbsoluteNativeTestReport = (options) => ({
|
|
17930
|
+
automatedChecks: options.automatedChecks ?? createAbsoluteNativeAutomatedChecks(options.run),
|
|
17931
|
+
generatedAt: options.generatedAt ?? new Date().toISOString(),
|
|
17932
|
+
manualChecks: options.manualChecks.map(([id, details]) => ({
|
|
17744
17933
|
details,
|
|
17745
17934
|
id,
|
|
17746
17935
|
result: "NOT_RUN"
|
|
17747
|
-
}))
|
|
17748
|
-
|
|
17749
|
-
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
17754
|
-
bunVersion: options.bunVersion,
|
|
17755
|
-
macosVersion: options.macosVersion,
|
|
17756
|
-
provider: "capacitor",
|
|
17757
|
-
xcodeVersion: options.xcodeVersion
|
|
17758
|
-
},
|
|
17759
|
-
overallResult: run.status === "fail" ? "FAIL" : "INCOMPLETE",
|
|
17760
|
-
platform: "ios",
|
|
17761
|
-
reportVersion: 1,
|
|
17762
|
-
run
|
|
17763
|
-
};
|
|
17764
|
-
}, readPackageVersionForIosReport = async (packageJsonPath) => {
|
|
17936
|
+
})),
|
|
17937
|
+
metadata: options.metadata,
|
|
17938
|
+
overallResult: options.run.status === "fail" ? "FAIL" : "INCOMPLETE",
|
|
17939
|
+
platform: options.run.platform,
|
|
17940
|
+
reportVersion: 1,
|
|
17941
|
+
run: options.run
|
|
17942
|
+
}), readPackageVersionForNativeReport = async (packageJsonPath) => {
|
|
17765
17943
|
const manifest = JSON.parse(await readFile18(packageJsonPath, "utf8"));
|
|
17766
17944
|
if (typeof manifest !== "object" || manifest === null)
|
|
17767
17945
|
return "unknown";
|
|
17768
17946
|
const version2 = Reflect.get(manifest, "version");
|
|
17769
17947
|
return typeof version2 === "string" ? version2 : "unknown";
|
|
17770
|
-
},
|
|
17948
|
+
}, renderAbsoluteNativeTestReport = (report) => {
|
|
17771
17949
|
const table = (checks) => checks.map((check2) => `| ${check2.id} | ${check2.result} | ${markdownCell(check2.details)} | ${markdownCell(check2.evidence ?? "")} |`).join(`
|
|
17772
17950
|
`);
|
|
17773
|
-
|
|
17951
|
+
const metadata = Object.entries(report.metadata).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `- ${key}: ${markdownCell(value)}`).join(`
|
|
17952
|
+
`);
|
|
17953
|
+
return `# AbsoluteJS ${report.platform} test report
|
|
17774
17954
|
|
|
17775
17955
|
- Overall result: ${report.overallResult}
|
|
17776
17956
|
- Generated: ${report.generatedAt}
|
|
17777
|
-
- AbsoluteJS: ${markdownCell(report.metadata.absolutejsVersion)}
|
|
17778
|
-
- macOS: ${markdownCell(report.metadata.macosVersion)}
|
|
17779
|
-
- Xcode: ${markdownCell(report.metadata.xcodeVersion)}
|
|
17780
|
-
- Bun: ${markdownCell(report.metadata.bunVersion)}
|
|
17781
17957
|
- App bundle ID: ${markdownCell(report.run.appId)}
|
|
17782
|
-
-
|
|
17958
|
+
- Target: ${report.run.targetKind} ${markdownCell(report.run.targetId)}
|
|
17783
17959
|
- Automated run: ${report.run.status.toUpperCase()} (${report.run.durationMs}ms)
|
|
17960
|
+
${metadata}
|
|
17784
17961
|
|
|
17785
|
-
|
|
17962
|
+
This report is local and is never uploaded by AbsoluteJS. Before sharing its directory, visually inspect screenshots and logs. Never add passwords, signing material, tokens, cookies, private Sync data, or exact coordinates.
|
|
17786
17963
|
|
|
17787
17964
|
## Automated checks
|
|
17788
17965
|
|
|
@@ -17790,26 +17967,54 @@ var MANUAL_CHECKS, secretPattern, bearerPattern, coordinatePattern, sanitizeIosR
|
|
|
17790
17967
|
| --- | --- | --- | --- |
|
|
17791
17968
|
${table(report.automatedChecks)}
|
|
17792
17969
|
|
|
17793
|
-
##
|
|
17970
|
+
## Manual checklist
|
|
17794
17971
|
|
|
17795
|
-
Replace each \`NOT_RUN\` with \`PASS\`, \`FAIL\`, or \`SKIPPED\` after
|
|
17972
|
+
Replace each \`NOT_RUN\` with \`PASS\`, \`FAIL\`, or \`SKIPPED\` after completing the platform runbook. A failure must name sanitized evidence and state actual versus expected behavior.
|
|
17796
17973
|
|
|
17797
17974
|
| Test ID | Result | Observed result / timing | Evidence or failure details |
|
|
17798
17975
|
| --- | --- | --- | --- |
|
|
17799
17976
|
${table(report.manualChecks)}
|
|
17800
17977
|
`;
|
|
17801
|
-
},
|
|
17978
|
+
}, writeAbsoluteNativeTestReport = async (directory, report) => {
|
|
17802
17979
|
await mkdir13(directory, { recursive: true });
|
|
17803
17980
|
const jsonPath = join51(directory, "report.json");
|
|
17804
17981
|
const markdownPath = join51(directory, "report.md");
|
|
17805
17982
|
await Promise.all([
|
|
17806
17983
|
writeFile15(jsonPath, `${JSON.stringify(report, null, 2)}
|
|
17807
17984
|
`),
|
|
17808
|
-
writeFile15(markdownPath,
|
|
17985
|
+
writeFile15(markdownPath, renderAbsoluteNativeTestReport(report))
|
|
17809
17986
|
]);
|
|
17810
17987
|
return { directory, jsonPath, markdownPath };
|
|
17811
17988
|
};
|
|
17989
|
+
var init_nativeTestReport = __esm(() => {
|
|
17990
|
+
secretPattern = /(authorization|access[_ -]?token|refresh[_ -]?token|socket[_ -]?ticket|password|cookie)(\s*[=:]\s*)([^\s,;]+)/giu;
|
|
17991
|
+
bearerPattern = /bearer\s+[^\s,;]+/giu;
|
|
17992
|
+
coordinatePattern = /\b(latitude|longitude|lat|lng)(\s*[=:]\s*)-?\d+(?:\.\d+)?/giu;
|
|
17993
|
+
});
|
|
17994
|
+
|
|
17995
|
+
// src/mobile/iosTestReport.ts
|
|
17996
|
+
var MANUAL_CHECKS, readPackageVersionForIosReport, sanitizeIosReportText, writeAbsoluteIosPartnerReport, createAbsoluteIosPartnerReport = (options) => {
|
|
17997
|
+
const { udid, ...run } = options.run;
|
|
17998
|
+
return createAbsoluteNativeTestReport({
|
|
17999
|
+
...options.generatedAt ? { generatedAt: options.generatedAt } : {},
|
|
18000
|
+
manualChecks: MANUAL_CHECKS,
|
|
18001
|
+
metadata: {
|
|
18002
|
+
absolutejsVersion: options.absolutejsVersion,
|
|
18003
|
+
bunVersion: options.bunVersion,
|
|
18004
|
+
macosVersion: options.macosVersion,
|
|
18005
|
+
provider: "capacitor",
|
|
18006
|
+
xcodeVersion: options.xcodeVersion
|
|
18007
|
+
},
|
|
18008
|
+
run: {
|
|
18009
|
+
...run,
|
|
18010
|
+
platform: "ios",
|
|
18011
|
+
targetId: udid,
|
|
18012
|
+
targetKind: "simulator"
|
|
18013
|
+
}
|
|
18014
|
+
});
|
|
18015
|
+
};
|
|
17812
18016
|
var init_iosTestReport = __esm(() => {
|
|
18017
|
+
init_nativeTestReport();
|
|
17813
18018
|
MANUAL_CHECKS = [
|
|
17814
18019
|
[
|
|
17815
18020
|
"SETUP-01",
|
|
@@ -17822,6 +18027,14 @@ var init_iosTestReport = __esm(() => {
|
|
|
17822
18027
|
["DEV-01", "Record cold and warm bun dev startup timings."],
|
|
17823
18028
|
["DEV-02", "Complete route traversal, HMR, relaunch, and recovery checks."],
|
|
17824
18029
|
["CAP-01", "Complete automatic device-capability provisioning checks."],
|
|
18030
|
+
...Array.from({ length: 8 }, (_, index) => [
|
|
18031
|
+
`FILES-${String(index + 1).padStart(2, "0")}`,
|
|
18032
|
+
`Complete provider-neutral Documents runbook check FILES-${String(index + 1).padStart(2, "0")}.`
|
|
18033
|
+
]),
|
|
18034
|
+
...Array.from({ length: 8 }, (_, index) => [
|
|
18035
|
+
`NOTIF-${String(index + 1).padStart(2, "0")}`,
|
|
18036
|
+
`Complete provider-neutral Local Notifications runbook check NOTIF-${String(index + 1).padStart(2, "0")}.`
|
|
18037
|
+
]),
|
|
17825
18038
|
...Array.from({ length: 14 }, (_, index) => [
|
|
17826
18039
|
`LOC-${String(index + 1).padStart(2, "0")}`,
|
|
17827
18040
|
`Complete foreground-location runbook check LOC-${String(index + 1).padStart(2, "0")} without recording exact coordinates.`
|
|
@@ -17847,9 +18060,65 @@ var init_iosTestReport = __esm(() => {
|
|
|
17847
18060
|
"Review this directory for sensitive content and complete every row."
|
|
17848
18061
|
]
|
|
17849
18062
|
];
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
18063
|
+
readPackageVersionForIosReport = readPackageVersionForNativeReport;
|
|
18064
|
+
sanitizeIosReportText = sanitizeNativeReportText;
|
|
18065
|
+
writeAbsoluteIosPartnerReport = writeAbsoluteNativeTestReport;
|
|
18066
|
+
});
|
|
18067
|
+
|
|
18068
|
+
// src/mobile/androidTestReport.ts
|
|
18069
|
+
var MANUAL_CHECKS2, createAbsoluteAndroidTestReport = (options) => {
|
|
18070
|
+
const { serial, ...run } = options.run;
|
|
18071
|
+
return createAbsoluteNativeTestReport({
|
|
18072
|
+
...options.generatedAt ? { generatedAt: options.generatedAt } : {},
|
|
18073
|
+
manualChecks: MANUAL_CHECKS2,
|
|
18074
|
+
metadata: {
|
|
18075
|
+
absolutejsVersion: options.absolutejsVersion,
|
|
18076
|
+
adbVersion: options.adbVersion,
|
|
18077
|
+
bunVersion: options.bunVersion,
|
|
18078
|
+
host: options.host,
|
|
18079
|
+
provider: "capacitor"
|
|
18080
|
+
},
|
|
18081
|
+
run: {
|
|
18082
|
+
...run,
|
|
18083
|
+
platform: "android",
|
|
18084
|
+
targetId: serial,
|
|
18085
|
+
targetKind: serial.startsWith("emulator-") ? "emulator" : "device"
|
|
18086
|
+
}
|
|
18087
|
+
});
|
|
18088
|
+
};
|
|
18089
|
+
var init_androidTestReport = __esm(() => {
|
|
18090
|
+
init_nativeTestReport();
|
|
18091
|
+
MANUAL_CHECKS2 = [
|
|
18092
|
+
[
|
|
18093
|
+
"SETUP-01",
|
|
18094
|
+
"Confirm Android SDK, emulator/device, Bun, and package versions."
|
|
18095
|
+
],
|
|
18096
|
+
["DEV-01", "Record cold and warm native startup timings."],
|
|
18097
|
+
["DEV-02", "Complete route traversal, HMR, relaunch, and recovery checks."],
|
|
18098
|
+
["CAP-01", "Complete automatic device-capability provisioning checks."],
|
|
18099
|
+
[
|
|
18100
|
+
"FILES-01",
|
|
18101
|
+
"Complete provider-neutral file pick, export, open, and cleanup checks."
|
|
18102
|
+
],
|
|
18103
|
+
...Array.from({ length: 6 }, (_, index) => [
|
|
18104
|
+
`NOTIF-${String(index + 1).padStart(2, "0")}`,
|
|
18105
|
+
`Complete provider-neutral Local Notifications check NOTIF-${String(index + 1).padStart(2, "0")}.`
|
|
18106
|
+
]),
|
|
18107
|
+
[
|
|
18108
|
+
"AUTH-01",
|
|
18109
|
+
"Complete system-browser sign-in, callback, restore, and sign-out checks."
|
|
18110
|
+
],
|
|
18111
|
+
[
|
|
18112
|
+
"SYNC-01",
|
|
18113
|
+
"Complete online, offline, reconnect, isolation, and conflict checks."
|
|
18114
|
+
],
|
|
18115
|
+
["BGSYNC-01", "Complete WorkManager background Sync acceptance."],
|
|
18116
|
+
["BUILD-01", "Pass release doctor and produce a signed AAB."],
|
|
18117
|
+
[
|
|
18118
|
+
"REPORT-01",
|
|
18119
|
+
"Review this directory for sensitive content and complete every row."
|
|
18120
|
+
]
|
|
18121
|
+
];
|
|
17853
18122
|
});
|
|
17854
18123
|
|
|
17855
18124
|
// src/mobile/releasePublisher.ts
|
|
@@ -18728,7 +18997,8 @@ Emulator setup verification:`);
|
|
|
18728
18997
|
const routes = valuesAfter(args, "--route");
|
|
18729
18998
|
if (routes.length === 0)
|
|
18730
18999
|
routes.push(mobile.entry);
|
|
18731
|
-
const
|
|
19000
|
+
const reportRoot = nativeReportRoot(args, projectRoot, "android");
|
|
19001
|
+
const artifactRoot = reportRoot ?? safeArtifactRoot(projectRoot, valueAfter(args, "--artifacts"));
|
|
18732
19002
|
const startedAt = performance.now();
|
|
18733
19003
|
let session;
|
|
18734
19004
|
try {
|
|
@@ -18767,6 +19037,30 @@ Emulator setup verification:`);
|
|
|
18767
19037
|
console.log(JSON.stringify(report, null, 2));
|
|
18768
19038
|
else
|
|
18769
19039
|
printAndroidTestReport(report);
|
|
19040
|
+
const screenshot = reportRoot ? await session.screenshot(join52(artifactRoot, "android-emulator.png")) : undefined;
|
|
19041
|
+
await writeRequestedAndroidReport({
|
|
19042
|
+
adb,
|
|
19043
|
+
args,
|
|
19044
|
+
projectRoot,
|
|
19045
|
+
run: {
|
|
19046
|
+
appId: mobile.appId,
|
|
19047
|
+
durationMs: report.durationMs,
|
|
19048
|
+
...hmrApply ? {
|
|
19049
|
+
hmr: {
|
|
19050
|
+
clientMs: hmrApply.clientMs,
|
|
19051
|
+
durationMs: hmrApply.duration,
|
|
19052
|
+
outcome: hmrApply.outcome,
|
|
19053
|
+
serverMs: hmrApply.serverMs
|
|
19054
|
+
}
|
|
19055
|
+
} : {},
|
|
19056
|
+
hmrConnected: true,
|
|
19057
|
+
port,
|
|
19058
|
+
routes: checks.map(({ route }) => route),
|
|
19059
|
+
...screenshot ? { screenshot } : {},
|
|
19060
|
+
serial,
|
|
19061
|
+
status: "pass"
|
|
19062
|
+
}
|
|
19063
|
+
});
|
|
18770
19064
|
return report;
|
|
18771
19065
|
} catch (error) {
|
|
18772
19066
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
@@ -18785,6 +19079,22 @@ Emulator setup verification:`);
|
|
|
18785
19079
|
serial,
|
|
18786
19080
|
session
|
|
18787
19081
|
});
|
|
19082
|
+
await writeRequestedAndroidReport({
|
|
19083
|
+
adb,
|
|
19084
|
+
args,
|
|
19085
|
+
projectRoot,
|
|
19086
|
+
run: {
|
|
19087
|
+
appId: mobile.appId,
|
|
19088
|
+
durationMs,
|
|
19089
|
+
error: sanitizeNativeReportText(error instanceof Error ? error.message : String(error)),
|
|
19090
|
+
hmrConnected: false,
|
|
19091
|
+
port,
|
|
19092
|
+
routes,
|
|
19093
|
+
...screenshot ? { screenshot } : {},
|
|
19094
|
+
serial,
|
|
19095
|
+
status: "fail"
|
|
19096
|
+
}
|
|
19097
|
+
});
|
|
18788
19098
|
throw new Error(`${error instanceof Error ? error.message : String(error)} Failure diagnostics: ${diagnosticPath}${screenshot ? `; screenshot: ${screenshot}` : ""}`, { cause: error });
|
|
18789
19099
|
} finally {
|
|
18790
19100
|
await session?.close();
|
|
@@ -18875,7 +19185,7 @@ Emulator setup verification:`);
|
|
|
18875
19185
|
if (!selected)
|
|
18876
19186
|
throw new TypeError("No ready AbsoluteJS iOS simulator was found. Start `bun dev` and wait for the iOS target to become ready.");
|
|
18877
19187
|
return selected;
|
|
18878
|
-
},
|
|
19188
|
+
}, requireCapturedCommand = (command, label) => {
|
|
18879
19189
|
const result = captureCommand4(command);
|
|
18880
19190
|
if (result.exitCode !== 0)
|
|
18881
19191
|
throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
|
|
@@ -18906,37 +19216,56 @@ Emulator setup verification:`);
|
|
|
18906
19216
|
diagnosticPath,
|
|
18907
19217
|
screenshot: screenshotResult.exitCode === 0 ? screenshot : undefined
|
|
18908
19218
|
};
|
|
18909
|
-
},
|
|
19219
|
+
}, nativeReportRoot = (args, projectRoot, platform6) => {
|
|
18910
19220
|
const index = args.indexOf("--report");
|
|
18911
19221
|
if (index === NOT_FOUND3)
|
|
18912
19222
|
return;
|
|
18913
19223
|
const candidate = args[index + 1];
|
|
18914
19224
|
const explicit = candidate?.startsWith("--") ? undefined : candidate;
|
|
18915
19225
|
const timestamp = new Date().toISOString().replaceAll(":", "-");
|
|
18916
|
-
return safeArtifactRoot(projectRoot, explicit ?? `.absolutejs/mobile/test-reports
|
|
18917
|
-
},
|
|
18918
|
-
const xcodebuildPath = requireCapturedIosCommand([xcrun, "--find", "xcodebuild"], "Xcode version inspection").stdout.trim();
|
|
18919
|
-
const xcodeVersion = requireCapturedIosCommand([xcodebuildPath, "-version"], "Xcode version inspection").stdout.trim();
|
|
18920
|
-
const macosVersion = requireCapturedIosCommand(["/usr/bin/sw_vers", "-productVersion"], "macOS version inspection").stdout.trim();
|
|
19226
|
+
return safeArtifactRoot(projectRoot, explicit ?? `.absolutejs/mobile/test-reports/${platform6}-${timestamp}`);
|
|
19227
|
+
}, absolutejsVersionForReport = async () => {
|
|
18921
19228
|
let absolutejsVersion = process.env.ABSOLUTE_VERSION ?? "unknown";
|
|
18922
|
-
|
|
19229
|
+
const versions = await Promise.all([
|
|
18923
19230
|
resolve41(import.meta.dir, "..", "..", "package.json"),
|
|
18924
19231
|
resolve41(import.meta.dir, "..", "..", "..", "package.json")
|
|
18925
|
-
])
|
|
18926
|
-
|
|
19232
|
+
].map((candidate) => readPackageVersionForIosReport(candidate).catch(() => "unknown")));
|
|
19233
|
+
for (const version2 of versions) {
|
|
18927
19234
|
if (version2 === "unknown")
|
|
18928
19235
|
continue;
|
|
18929
19236
|
absolutejsVersion = version2;
|
|
18930
19237
|
break;
|
|
18931
19238
|
}
|
|
19239
|
+
return absolutejsVersion;
|
|
19240
|
+
}, writeRequestedAndroidReport = async (options) => {
|
|
19241
|
+
const reportRoot = nativeReportRoot(options.args, options.projectRoot, "android");
|
|
19242
|
+
if (!reportRoot)
|
|
19243
|
+
return;
|
|
19244
|
+
const adbVersion = requireCapturedCommand([options.adb, "version"], "ADB version inspection").stdout.trim();
|
|
19245
|
+
const report = createAbsoluteAndroidTestReport({
|
|
19246
|
+
absolutejsVersion: await absolutejsVersionForReport(),
|
|
19247
|
+
adbVersion,
|
|
19248
|
+
bunVersion: Bun.version,
|
|
19249
|
+
host: `${process.platform}-${process.arch}`,
|
|
19250
|
+
run: options.run
|
|
19251
|
+
});
|
|
19252
|
+
const paths = await writeAbsoluteNativeTestReport(reportRoot, report);
|
|
19253
|
+
const print = options.args.includes("--json") ? console.error : console.log;
|
|
19254
|
+
print(`Android test report: ${paths.markdownPath}`);
|
|
19255
|
+
print(`Return this report directory: ${paths.directory}`);
|
|
19256
|
+
return paths;
|
|
19257
|
+
}, iosReportMetadata = async (xcrun) => {
|
|
19258
|
+
const xcodebuildPath = requireCapturedCommand([xcrun, "--find", "xcodebuild"], "Xcode version inspection").stdout.trim();
|
|
19259
|
+
const xcodeVersion = requireCapturedCommand([xcodebuildPath, "-version"], "Xcode version inspection").stdout.trim();
|
|
19260
|
+
const macosVersion = requireCapturedCommand(["/usr/bin/sw_vers", "-productVersion"], "macOS version inspection").stdout.trim();
|
|
18932
19261
|
return {
|
|
18933
|
-
absolutejsVersion,
|
|
19262
|
+
absolutejsVersion: await absolutejsVersionForReport(),
|
|
18934
19263
|
bunVersion: Bun.version,
|
|
18935
19264
|
macosVersion,
|
|
18936
19265
|
xcodeVersion
|
|
18937
19266
|
};
|
|
18938
19267
|
}, writeRequestedIosReport = async (options) => {
|
|
18939
|
-
const reportRoot =
|
|
19268
|
+
const reportRoot = nativeReportRoot(options.args, options.projectRoot, "ios");
|
|
18940
19269
|
if (!reportRoot)
|
|
18941
19270
|
return;
|
|
18942
19271
|
const metadata = await iosReportMetadata(options.xcrun);
|
|
@@ -18955,11 +19284,11 @@ Emulator setup verification:`);
|
|
|
18955
19284
|
const timeoutMs = androidTestTimeout(args);
|
|
18956
19285
|
const xcrun = await requireIosXcrun();
|
|
18957
19286
|
const simulator = selectIosSimulator(xcrun, valueAfter(args, "--udid") ?? valueAfter(args, "--serial"));
|
|
18958
|
-
const reportRoot =
|
|
19287
|
+
const reportRoot = nativeReportRoot(args, projectRoot, "ios");
|
|
18959
19288
|
const artifactRoot = reportRoot ?? safeArtifactRoot(projectRoot, valueAfter(args, "--artifacts"));
|
|
18960
19289
|
const startedAt = performance.now();
|
|
18961
19290
|
try {
|
|
18962
|
-
|
|
19291
|
+
requireCapturedCommand([
|
|
18963
19292
|
xcrun,
|
|
18964
19293
|
"simctl",
|
|
18965
19294
|
"get_app_container",
|
|
@@ -18967,7 +19296,7 @@ Emulator setup verification:`);
|
|
|
18967
19296
|
mobile.appId,
|
|
18968
19297
|
"app"
|
|
18969
19298
|
], "iOS installed-app inspection");
|
|
18970
|
-
|
|
19299
|
+
requireCapturedCommand([
|
|
18971
19300
|
xcrun,
|
|
18972
19301
|
"simctl",
|
|
18973
19302
|
"launch",
|
|
@@ -18978,7 +19307,7 @@ Emulator setup verification:`);
|
|
|
18978
19307
|
await waitForIosHmrClient({ https, port, timeoutMs });
|
|
18979
19308
|
await mkdir14(artifactRoot, { recursive: true });
|
|
18980
19309
|
const screenshot = join52(artifactRoot, "ios-simulator.png");
|
|
18981
|
-
|
|
19310
|
+
requireCapturedCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
|
|
18982
19311
|
const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
|
|
18983
19312
|
const report = {
|
|
18984
19313
|
appId: mobile.appId,
|
|
@@ -19111,7 +19440,7 @@ Emulator setup verification:`);
|
|
|
19111
19440
|
await publishIos(args.slice(2));
|
|
19112
19441
|
return;
|
|
19113
19442
|
}
|
|
19114
|
-
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--udid id] [--artifacts dir] [--json]> [--config path]");
|
|
19443
|
+
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--udid id] [--artifacts dir] [--json]> [--config path]");
|
|
19115
19444
|
};
|
|
19116
19445
|
var init_mobile = __esm(() => {
|
|
19117
19446
|
init_dependencies();
|
|
@@ -19134,6 +19463,8 @@ var init_mobile = __esm(() => {
|
|
|
19134
19463
|
init_iosSimulatorController();
|
|
19135
19464
|
init_iosConformance();
|
|
19136
19465
|
init_iosTestReport();
|
|
19466
|
+
init_androidTestReport();
|
|
19467
|
+
init_nativeTestReport();
|
|
19137
19468
|
init_releasePublisher();
|
|
19138
19469
|
init_start();
|
|
19139
19470
|
init_utils();
|
|
@@ -19163,8 +19494,8 @@ var init_mobile = __esm(() => {
|
|
|
19163
19494
|
"@capacitor/cli@8.5.0",
|
|
19164
19495
|
"@capacitor/android@8.5.0",
|
|
19165
19496
|
"@capacitor/ios@8.5.0",
|
|
19166
|
-
"@absolutejs/devices@0.
|
|
19167
|
-
"@absolutejs/devices-capacitor@0.
|
|
19497
|
+
"@absolutejs/devices@0.5.0",
|
|
19498
|
+
"@absolutejs/devices-capacitor@0.6.1"
|
|
19168
19499
|
];
|
|
19169
19500
|
CAPACITOR_SYNC_PACKAGE_SPECS = [
|
|
19170
19501
|
"@absolutejs/sync-capacitor@0.9.1",
|