@craft-native/ios 0.0.237 → 0.0.241
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/cli.js +2 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +17 -1
- package/dist/testing.d.ts +16 -2
- package/package.json +1 -1
- package/templates/CraftApp.swift +418 -93
- package/templates/CraftHeartRate.swift +141 -44
- package/templates/CraftNativeActions.swift +46 -48
- package/templates/CraftNativeScreen.swift +82 -17
- package/templates/CraftPersistentStorage.swift +99 -0
- package/templates/CraftRecordingArchive.swift +85 -0
- package/templates/testing/DriverTests.swift.template +45 -1
package/dist/cli.js
CHANGED
|
@@ -958,6 +958,8 @@ function writeShell(output, config) {
|
|
|
958
958
|
cpSync(join3(TEMPLATES_DIR, "CraftMusic.swift"), join3(output, "Sources", "CraftMusic.swift"));
|
|
959
959
|
cpSync(join3(TEMPLATES_DIR, "CraftBluetooth.swift"), join3(output, "Sources", "CraftBluetooth.swift"));
|
|
960
960
|
cpSync(join3(TEMPLATES_DIR, "CraftHeartRate.swift"), join3(output, "Sources", "CraftHeartRate.swift"));
|
|
961
|
+
cpSync(join3(TEMPLATES_DIR, "CraftRecordingArchive.swift"), join3(output, "Sources", "CraftRecordingArchive.swift"));
|
|
962
|
+
cpSync(join3(TEMPLATES_DIR, "CraftPersistentStorage.swift"), join3(output, "Sources", "CraftPersistentStorage.swift"));
|
|
961
963
|
cpSync(join3(TEMPLATES_DIR, "CraftScheduledWorkouts.swift"), join3(output, "Sources", "CraftScheduledWorkouts.swift"));
|
|
962
964
|
cpSync(join3(TEMPLATES_DIR, "CraftNativeMutation.swift"), join3(output, "Sources", "CraftNativeMutation.swift"));
|
|
963
965
|
cpSync(join3(TEMPLATES_DIR, "CraftNativeUI.swift"), join3(output, "Sources", "CraftNativeUI.swift"));
|
package/dist/index.d.ts
CHANGED
|
@@ -274,6 +274,11 @@ export interface CraftTab {
|
|
|
274
274
|
title: string;
|
|
275
275
|
/** An SF Symbol name. */
|
|
276
276
|
symbol?: string;
|
|
277
|
+
/** Native selected-tab icon overrides; retained pushed screens keep their owning tab's policy. */
|
|
278
|
+
selectedSymbol?: string;
|
|
279
|
+
selectedIconTint?: string;
|
|
280
|
+
/** False suppresses the legacy pulse while selected; omission uses the legacy policy. */
|
|
281
|
+
selectedIconPulse?: boolean;
|
|
277
282
|
}
|
|
278
283
|
/** `/a//b/?q#h` → `/a/b`, the way the shell and the page compare paths. Null for a relative path. */
|
|
279
284
|
export declare function normalizeNativePath(raw: string): string | null;
|
package/dist/index.js
CHANGED
|
@@ -133,13 +133,19 @@ function initSimulatorDriver(options) {
|
|
|
133
133
|
throw new Error("The simulator driver requires iOS 17.0 or newer");
|
|
134
134
|
if (!["http:", "https:"].includes(new URL(control).protocol))
|
|
135
135
|
throw new Error("controlUrl must use HTTP or HTTPS");
|
|
136
|
+
const tabIdentifiers = Object.entries(options.tabIdentifiers ?? {});
|
|
137
|
+
for (const [name2, identifier] of tabIdentifiers) {
|
|
138
|
+
if (!name2.trim() || !identifier.trim())
|
|
139
|
+
throw new Error("Tab names and native identifiers must be nonempty");
|
|
140
|
+
}
|
|
136
141
|
const replacements = {
|
|
137
142
|
PROJECT_NAME: name,
|
|
138
143
|
BUNDLE_PREFIX: prefix,
|
|
139
144
|
IOS_VERSION: version,
|
|
140
145
|
BUNDLE_ID: swiftString(bundleId),
|
|
141
146
|
CONTROL_URL: swiftString(control),
|
|
142
|
-
TABS: `[${(options.tabs ?? []).map(swiftString).join(", ")}]
|
|
147
|
+
TABS: `[${(options.tabs ?? []).map(swiftString).join(", ")}]`,
|
|
148
|
+
TAB_IDENTIFIERS: tabIdentifiers.length ? `[${tabIdentifiers.map(([name2, identifier]) => `${swiftString(name2)}: ${swiftString(identifier)}`).join(", ")}]` : "[:]"
|
|
143
149
|
};
|
|
144
150
|
for (const [source, destination] of [
|
|
145
151
|
["HostApp.swift", "Host/HostApp.swift"],
|
|
@@ -222,10 +228,18 @@ function serializeSimulatorSteps(steps) {
|
|
|
222
228
|
if (!Number.isInteger(number(step.index)))
|
|
223
229
|
throw new Error("field index must be an integer");
|
|
224
230
|
arg = `${step.index} ${step.text}`;
|
|
231
|
+
} else if ("position" in step) {
|
|
232
|
+
if (number(step.position) > 1)
|
|
233
|
+
throw new Error("Slider position must be between 0 and 1");
|
|
234
|
+
arg = `${token(step.id)} ${step.position}`;
|
|
225
235
|
} else if ("id" in step)
|
|
226
236
|
arg = `${token(step.id)} ${step.text}`;
|
|
227
237
|
else if ("text" in step) {
|
|
228
238
|
arg = step.text;
|
|
239
|
+
if (step.command === "longpressid")
|
|
240
|
+
token(arg);
|
|
241
|
+
if (step.command === "expectapp" && !/^[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+$/.test(arg))
|
|
242
|
+
throw new Error("Expected an application bundle identifier");
|
|
229
243
|
if ("seconds" in step && step.seconds !== undefined) {
|
|
230
244
|
if (arg.includes("|"))
|
|
231
245
|
throw new Error("A timed expectation cannot contain |");
|
|
@@ -1141,6 +1155,8 @@ function writeShell(output, config) {
|
|
|
1141
1155
|
cpSync(join3(TEMPLATES_DIR, "CraftMusic.swift"), join3(output, "Sources", "CraftMusic.swift"));
|
|
1142
1156
|
cpSync(join3(TEMPLATES_DIR, "CraftBluetooth.swift"), join3(output, "Sources", "CraftBluetooth.swift"));
|
|
1143
1157
|
cpSync(join3(TEMPLATES_DIR, "CraftHeartRate.swift"), join3(output, "Sources", "CraftHeartRate.swift"));
|
|
1158
|
+
cpSync(join3(TEMPLATES_DIR, "CraftRecordingArchive.swift"), join3(output, "Sources", "CraftRecordingArchive.swift"));
|
|
1159
|
+
cpSync(join3(TEMPLATES_DIR, "CraftPersistentStorage.swift"), join3(output, "Sources", "CraftPersistentStorage.swift"));
|
|
1144
1160
|
cpSync(join3(TEMPLATES_DIR, "CraftScheduledWorkouts.swift"), join3(output, "Sources", "CraftScheduledWorkouts.swift"));
|
|
1145
1161
|
cpSync(join3(TEMPLATES_DIR, "CraftNativeMutation.swift"), join3(output, "Sources", "CraftNativeMutation.swift"));
|
|
1146
1162
|
cpSync(join3(TEMPLATES_DIR, "CraftNativeUI.swift"), join3(output, "Sources", "CraftNativeUI.swift"));
|
package/dist/testing.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface SimulatorDriverOptions {
|
|
|
7
7
|
deploymentTarget?: string;
|
|
8
8
|
controlUrl?: string;
|
|
9
9
|
tabs?: readonly string[];
|
|
10
|
+
/** Stable native accessibility identifiers for tabs whose labels can change. */
|
|
11
|
+
tabIdentifiers?: Readonly<Record<string, string>>;
|
|
10
12
|
/** Bundle a wire-protocol journey and save native XCTest attachments. No control server is needed on physical devices. */
|
|
11
13
|
script?: string;
|
|
12
14
|
}
|
|
@@ -64,15 +66,27 @@ export type SimulatorStep = {
|
|
|
64
66
|
index: number;
|
|
65
67
|
text: string;
|
|
66
68
|
} | {
|
|
67
|
-
command: 'typeid' | 'labelid';
|
|
69
|
+
command: 'typeid' | 'labelid' | 'valueid';
|
|
68
70
|
id: string;
|
|
69
71
|
text: string;
|
|
72
|
+
}
|
|
73
|
+
/** Adjust an actual native UISlider by identifier, using its normalized range. */
|
|
74
|
+
| {
|
|
75
|
+
command: 'sliderid';
|
|
76
|
+
id: string;
|
|
77
|
+
position: number;
|
|
78
|
+
}
|
|
79
|
+
/** Assert a handoff reached the foreground application without launching it. */
|
|
80
|
+
| {
|
|
81
|
+
command: 'expectapp';
|
|
82
|
+
text: string;
|
|
83
|
+
seconds?: number;
|
|
70
84
|
} | {
|
|
71
85
|
command: 'expect' | 'expectexact' | 'expectid' | 'systemexpect';
|
|
72
86
|
text: string;
|
|
73
87
|
seconds?: number;
|
|
74
88
|
} | {
|
|
75
|
-
command: 'tap' | 'tapif' | 'tapid' | 'tapexact' | 'type' | 'absent' | 'absentid' | 'selected' | 'tab' | 'scrollto' | 'dismiss' | 'log' | 'systemtap' | 'systemabsent';
|
|
89
|
+
command: 'tap' | 'tapif' | 'tapid' | 'longpressid' | 'tapexact' | 'type' | 'absent' | 'absentid' | 'selected' | 'tab' | 'scrollto' | 'dismiss' | 'log' | 'systemtap' | 'systemabsent';
|
|
76
90
|
text: string;
|
|
77
91
|
} | {
|
|
78
92
|
command: 'shot' | 'tree' | 'audit' | 'exec' | 'systemtree';
|