@tapflowio/ios-agent 0.13.0 → 0.14.0
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/IOSAgent.d.ts +6 -1
- package/dist/IOSAgent.d.ts.map +1 -1
- package/dist/IOSAgent.js +114 -3
- package/dist/IOSAgent.js.map +1 -1
- package/dist/SimctlWrapper.d.ts +2 -0
- package/dist/SimctlWrapper.d.ts.map +1 -1
- package/dist/SimctlWrapper.js +34 -1
- package/dist/SimctlWrapper.js.map +1 -1
- package/dist/XCUITreeReader.d.ts +26 -0
- package/dist/XCUITreeReader.d.ts.map +1 -0
- package/dist/XCUITreeReader.js +194 -0
- package/dist/XCUITreeReader.js.map +1 -0
- package/dist/xcuiTree.d.ts +3 -0
- package/dist/xcuiTree.d.ts.map +1 -0
- package/dist/xcuiTree.js +129 -0
- package/dist/xcuiTree.js.map +1 -0
- package/package.json +8 -4
- package/xctest-runner/TapflowTreeRunner.xcodeproj/project.pbxproj +388 -0
- package/xctest-runner/TapflowTreeRunner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/xctest-runner/TapflowTreeRunner.xcodeproj/xcshareddata/xcschemes/TreeRunner.xcscheme +116 -0
- package/xctest-runner/TreeHost/TreeHostApp.swift +13 -0
- package/xctest-runner/TreeRunner/TreeServer.swift +107 -0
- package/xctest-runner/TreeRunner/TreeServerTest.swift +19 -0
- package/xctest-runner/project.yml +37 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
// !$*UTF8*$!
|
|
2
|
+
{
|
|
3
|
+
archiveVersion = 1;
|
|
4
|
+
classes = {
|
|
5
|
+
};
|
|
6
|
+
objectVersion = 77;
|
|
7
|
+
objects = {
|
|
8
|
+
|
|
9
|
+
/* Begin PBXBuildFile section */
|
|
10
|
+
26EAE68A8AEF6711E909FBF8 /* TreeHostApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88601611A041AD1AA457AC2 /* TreeHostApp.swift */; };
|
|
11
|
+
86A27D15B777D3EFB8F5C73A /* TreeServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D3C253530C16617C1AEC98B /* TreeServer.swift */; };
|
|
12
|
+
874197138AF312F10FE87D92 /* TreeServerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83974A83B526E4945DF35FAD /* TreeServerTest.swift */; };
|
|
13
|
+
/* End PBXBuildFile section */
|
|
14
|
+
|
|
15
|
+
/* Begin PBXContainerItemProxy section */
|
|
16
|
+
2631044DFA3ECF19849A6BD3 /* PBXContainerItemProxy */ = {
|
|
17
|
+
isa = PBXContainerItemProxy;
|
|
18
|
+
containerPortal = E86248EBE591AA453974543F /* Project object */;
|
|
19
|
+
proxyType = 1;
|
|
20
|
+
remoteGlobalIDString = AB37E7C89C6AC8FE774DE79B;
|
|
21
|
+
remoteInfo = TreeHost;
|
|
22
|
+
};
|
|
23
|
+
/* End PBXContainerItemProxy section */
|
|
24
|
+
|
|
25
|
+
/* Begin PBXFileReference section */
|
|
26
|
+
408EEDD6371DF9A7F37A7948 /* TreeHost.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = TreeHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
27
|
+
6D3C253530C16617C1AEC98B /* TreeServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeServer.swift; sourceTree = "<group>"; };
|
|
28
|
+
83974A83B526E4945DF35FAD /* TreeServerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeServerTest.swift; sourceTree = "<group>"; };
|
|
29
|
+
A95BDC906708455856C9D8E4 /* TreeRunner.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = TreeRunner.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
30
|
+
E88601611A041AD1AA457AC2 /* TreeHostApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeHostApp.swift; sourceTree = "<group>"; };
|
|
31
|
+
/* End PBXFileReference section */
|
|
32
|
+
|
|
33
|
+
/* Begin PBXGroup section */
|
|
34
|
+
0F650F3B42CC15EC2EF9AECD = {
|
|
35
|
+
isa = PBXGroup;
|
|
36
|
+
children = (
|
|
37
|
+
C00C055751602D6FC0D7FD1E /* TreeHost */,
|
|
38
|
+
C373148BBCFFDEF3DF602664 /* TreeRunner */,
|
|
39
|
+
630548875BA0FE74BCFB2E15 /* Products */,
|
|
40
|
+
);
|
|
41
|
+
sourceTree = "<group>";
|
|
42
|
+
};
|
|
43
|
+
630548875BA0FE74BCFB2E15 /* Products */ = {
|
|
44
|
+
isa = PBXGroup;
|
|
45
|
+
children = (
|
|
46
|
+
408EEDD6371DF9A7F37A7948 /* TreeHost.app */,
|
|
47
|
+
A95BDC906708455856C9D8E4 /* TreeRunner.xctest */,
|
|
48
|
+
);
|
|
49
|
+
name = Products;
|
|
50
|
+
sourceTree = "<group>";
|
|
51
|
+
};
|
|
52
|
+
C00C055751602D6FC0D7FD1E /* TreeHost */ = {
|
|
53
|
+
isa = PBXGroup;
|
|
54
|
+
children = (
|
|
55
|
+
E88601611A041AD1AA457AC2 /* TreeHostApp.swift */,
|
|
56
|
+
);
|
|
57
|
+
path = TreeHost;
|
|
58
|
+
sourceTree = "<group>";
|
|
59
|
+
};
|
|
60
|
+
C373148BBCFFDEF3DF602664 /* TreeRunner */ = {
|
|
61
|
+
isa = PBXGroup;
|
|
62
|
+
children = (
|
|
63
|
+
6D3C253530C16617C1AEC98B /* TreeServer.swift */,
|
|
64
|
+
83974A83B526E4945DF35FAD /* TreeServerTest.swift */,
|
|
65
|
+
);
|
|
66
|
+
path = TreeRunner;
|
|
67
|
+
sourceTree = "<group>";
|
|
68
|
+
};
|
|
69
|
+
/* End PBXGroup section */
|
|
70
|
+
|
|
71
|
+
/* Begin PBXNativeTarget section */
|
|
72
|
+
AB37E7C89C6AC8FE774DE79B /* TreeHost */ = {
|
|
73
|
+
isa = PBXNativeTarget;
|
|
74
|
+
buildConfigurationList = 32CF64B25AC119299FC98D21 /* Build configuration list for PBXNativeTarget "TreeHost" */;
|
|
75
|
+
buildPhases = (
|
|
76
|
+
CE9026862C5143296E746C9F /* Sources */,
|
|
77
|
+
);
|
|
78
|
+
buildRules = (
|
|
79
|
+
);
|
|
80
|
+
dependencies = (
|
|
81
|
+
);
|
|
82
|
+
name = TreeHost;
|
|
83
|
+
packageProductDependencies = (
|
|
84
|
+
);
|
|
85
|
+
productName = TreeHost;
|
|
86
|
+
productReference = 408EEDD6371DF9A7F37A7948 /* TreeHost.app */;
|
|
87
|
+
productType = "com.apple.product-type.application";
|
|
88
|
+
};
|
|
89
|
+
E94851893DB2D30285F8858D /* TreeRunner */ = {
|
|
90
|
+
isa = PBXNativeTarget;
|
|
91
|
+
buildConfigurationList = E0368676E0E41217C91B678B /* Build configuration list for PBXNativeTarget "TreeRunner" */;
|
|
92
|
+
buildPhases = (
|
|
93
|
+
768AC7F04FCA5A1BF7C7D0EC /* Sources */,
|
|
94
|
+
);
|
|
95
|
+
buildRules = (
|
|
96
|
+
);
|
|
97
|
+
dependencies = (
|
|
98
|
+
A306F004A9003D98B87FDFED /* PBXTargetDependency */,
|
|
99
|
+
);
|
|
100
|
+
name = TreeRunner;
|
|
101
|
+
packageProductDependencies = (
|
|
102
|
+
);
|
|
103
|
+
productName = TreeRunner;
|
|
104
|
+
productReference = A95BDC906708455856C9D8E4 /* TreeRunner.xctest */;
|
|
105
|
+
productType = "com.apple.product-type.bundle.ui-testing";
|
|
106
|
+
};
|
|
107
|
+
/* End PBXNativeTarget section */
|
|
108
|
+
|
|
109
|
+
/* Begin PBXProject section */
|
|
110
|
+
E86248EBE591AA453974543F /* Project object */ = {
|
|
111
|
+
isa = PBXProject;
|
|
112
|
+
attributes = {
|
|
113
|
+
BuildIndependentTargetsInParallel = YES;
|
|
114
|
+
LastUpgradeCheck = 1430;
|
|
115
|
+
TargetAttributes = {
|
|
116
|
+
E94851893DB2D30285F8858D = {
|
|
117
|
+
TestTargetID = AB37E7C89C6AC8FE774DE79B;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
buildConfigurationList = B268324BC08517F6C2141849 /* Build configuration list for PBXProject "TapflowTreeRunner" */;
|
|
122
|
+
developmentRegion = en;
|
|
123
|
+
hasScannedForEncodings = 0;
|
|
124
|
+
knownRegions = (
|
|
125
|
+
Base,
|
|
126
|
+
en,
|
|
127
|
+
);
|
|
128
|
+
mainGroup = 0F650F3B42CC15EC2EF9AECD;
|
|
129
|
+
minimizedProjectReferenceProxies = 1;
|
|
130
|
+
preferredProjectObjectVersion = 77;
|
|
131
|
+
productRefGroup = 630548875BA0FE74BCFB2E15 /* Products */;
|
|
132
|
+
projectDirPath = "";
|
|
133
|
+
projectRoot = "";
|
|
134
|
+
targets = (
|
|
135
|
+
AB37E7C89C6AC8FE774DE79B /* TreeHost */,
|
|
136
|
+
E94851893DB2D30285F8858D /* TreeRunner */,
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
/* End PBXProject section */
|
|
140
|
+
|
|
141
|
+
/* Begin PBXSourcesBuildPhase section */
|
|
142
|
+
768AC7F04FCA5A1BF7C7D0EC /* Sources */ = {
|
|
143
|
+
isa = PBXSourcesBuildPhase;
|
|
144
|
+
buildActionMask = 2147483647;
|
|
145
|
+
files = (
|
|
146
|
+
86A27D15B777D3EFB8F5C73A /* TreeServer.swift in Sources */,
|
|
147
|
+
874197138AF312F10FE87D92 /* TreeServerTest.swift in Sources */,
|
|
148
|
+
);
|
|
149
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
150
|
+
};
|
|
151
|
+
CE9026862C5143296E746C9F /* Sources */ = {
|
|
152
|
+
isa = PBXSourcesBuildPhase;
|
|
153
|
+
buildActionMask = 2147483647;
|
|
154
|
+
files = (
|
|
155
|
+
26EAE68A8AEF6711E909FBF8 /* TreeHostApp.swift in Sources */,
|
|
156
|
+
);
|
|
157
|
+
runOnlyForDeploymentPostprocessing = 0;
|
|
158
|
+
};
|
|
159
|
+
/* End PBXSourcesBuildPhase section */
|
|
160
|
+
|
|
161
|
+
/* Begin PBXTargetDependency section */
|
|
162
|
+
A306F004A9003D98B87FDFED /* PBXTargetDependency */ = {
|
|
163
|
+
isa = PBXTargetDependency;
|
|
164
|
+
target = AB37E7C89C6AC8FE774DE79B /* TreeHost */;
|
|
165
|
+
targetProxy = 2631044DFA3ECF19849A6BD3 /* PBXContainerItemProxy */;
|
|
166
|
+
};
|
|
167
|
+
/* End PBXTargetDependency section */
|
|
168
|
+
|
|
169
|
+
/* Begin XCBuildConfiguration section */
|
|
170
|
+
04475AB2325A10E71BB05CF7 /* Release */ = {
|
|
171
|
+
isa = XCBuildConfiguration;
|
|
172
|
+
buildSettings = {
|
|
173
|
+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
174
|
+
CODE_SIGN_IDENTITY = "iPhone Developer";
|
|
175
|
+
GENERATE_INFOPLIST_FILE = YES;
|
|
176
|
+
LD_RUNPATH_SEARCH_PATHS = (
|
|
177
|
+
"$(inherited)",
|
|
178
|
+
"@executable_path/Frameworks",
|
|
179
|
+
);
|
|
180
|
+
PRODUCT_BUNDLE_IDENTIFIER = dev.tapflow.treerunner.host;
|
|
181
|
+
SDKROOT = iphoneos;
|
|
182
|
+
TARGETED_DEVICE_FAMILY = "1,2";
|
|
183
|
+
};
|
|
184
|
+
name = Release;
|
|
185
|
+
};
|
|
186
|
+
0F84FBE32B45B64354676D78 /* Release */ = {
|
|
187
|
+
isa = XCBuildConfiguration;
|
|
188
|
+
buildSettings = {
|
|
189
|
+
BUNDLE_LOADER = "$(TEST_HOST)";
|
|
190
|
+
GENERATE_INFOPLIST_FILE = YES;
|
|
191
|
+
LD_RUNPATH_SEARCH_PATHS = (
|
|
192
|
+
"$(inherited)",
|
|
193
|
+
"@executable_path/Frameworks",
|
|
194
|
+
"@loader_path/Frameworks",
|
|
195
|
+
);
|
|
196
|
+
PRODUCT_BUNDLE_IDENTIFIER = dev.tapflow.treerunner.uitests;
|
|
197
|
+
SDKROOT = iphoneos;
|
|
198
|
+
TARGETED_DEVICE_FAMILY = "1,2";
|
|
199
|
+
TEST_TARGET_NAME = TreeHost;
|
|
200
|
+
};
|
|
201
|
+
name = Release;
|
|
202
|
+
};
|
|
203
|
+
17661D1CEC0BCB16F2CF8810 /* Release */ = {
|
|
204
|
+
isa = XCBuildConfiguration;
|
|
205
|
+
buildSettings = {
|
|
206
|
+
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
207
|
+
CLANG_ANALYZER_NONNULL = YES;
|
|
208
|
+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
|
209
|
+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
|
210
|
+
CLANG_CXX_LIBRARY = "libc++";
|
|
211
|
+
CLANG_ENABLE_MODULES = YES;
|
|
212
|
+
CLANG_ENABLE_OBJC_ARC = YES;
|
|
213
|
+
CLANG_ENABLE_OBJC_WEAK = YES;
|
|
214
|
+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
215
|
+
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
216
|
+
CLANG_WARN_COMMA = YES;
|
|
217
|
+
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
218
|
+
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
219
|
+
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
220
|
+
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
|
221
|
+
CLANG_WARN_EMPTY_BODY = YES;
|
|
222
|
+
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
223
|
+
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
224
|
+
CLANG_WARN_INT_CONVERSION = YES;
|
|
225
|
+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
226
|
+
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
227
|
+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
228
|
+
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
229
|
+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
230
|
+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
231
|
+
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
232
|
+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
233
|
+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
|
234
|
+
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
235
|
+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
236
|
+
COPY_PHASE_STRIP = NO;
|
|
237
|
+
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
238
|
+
ENABLE_NS_ASSERTIONS = NO;
|
|
239
|
+
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
240
|
+
GCC_C_LANGUAGE_STANDARD = gnu11;
|
|
241
|
+
GCC_NO_COMMON_BLOCKS = YES;
|
|
242
|
+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
243
|
+
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
244
|
+
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
245
|
+
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
246
|
+
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
247
|
+
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
248
|
+
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
|
249
|
+
MTL_ENABLE_DEBUG_INFO = NO;
|
|
250
|
+
MTL_FAST_MATH = YES;
|
|
251
|
+
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
252
|
+
SDKROOT = iphoneos;
|
|
253
|
+
SWIFT_COMPILATION_MODE = wholemodule;
|
|
254
|
+
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
|
255
|
+
SWIFT_VERSION = 5.0;
|
|
256
|
+
};
|
|
257
|
+
name = Release;
|
|
258
|
+
};
|
|
259
|
+
665CEF305E01AD84204FE1AA /* Debug */ = {
|
|
260
|
+
isa = XCBuildConfiguration;
|
|
261
|
+
buildSettings = {
|
|
262
|
+
BUNDLE_LOADER = "$(TEST_HOST)";
|
|
263
|
+
GENERATE_INFOPLIST_FILE = YES;
|
|
264
|
+
LD_RUNPATH_SEARCH_PATHS = (
|
|
265
|
+
"$(inherited)",
|
|
266
|
+
"@executable_path/Frameworks",
|
|
267
|
+
"@loader_path/Frameworks",
|
|
268
|
+
);
|
|
269
|
+
PRODUCT_BUNDLE_IDENTIFIER = dev.tapflow.treerunner.uitests;
|
|
270
|
+
SDKROOT = iphoneos;
|
|
271
|
+
TARGETED_DEVICE_FAMILY = "1,2";
|
|
272
|
+
TEST_TARGET_NAME = TreeHost;
|
|
273
|
+
};
|
|
274
|
+
name = Debug;
|
|
275
|
+
};
|
|
276
|
+
8D273ED725602839488F78BC /* Debug */ = {
|
|
277
|
+
isa = XCBuildConfiguration;
|
|
278
|
+
buildSettings = {
|
|
279
|
+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
280
|
+
CODE_SIGN_IDENTITY = "iPhone Developer";
|
|
281
|
+
GENERATE_INFOPLIST_FILE = YES;
|
|
282
|
+
LD_RUNPATH_SEARCH_PATHS = (
|
|
283
|
+
"$(inherited)",
|
|
284
|
+
"@executable_path/Frameworks",
|
|
285
|
+
);
|
|
286
|
+
PRODUCT_BUNDLE_IDENTIFIER = dev.tapflow.treerunner.host;
|
|
287
|
+
SDKROOT = iphoneos;
|
|
288
|
+
TARGETED_DEVICE_FAMILY = "1,2";
|
|
289
|
+
};
|
|
290
|
+
name = Debug;
|
|
291
|
+
};
|
|
292
|
+
C6EA51ACA32945E2449085D0 /* Debug */ = {
|
|
293
|
+
isa = XCBuildConfiguration;
|
|
294
|
+
buildSettings = {
|
|
295
|
+
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
296
|
+
CLANG_ANALYZER_NONNULL = YES;
|
|
297
|
+
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
|
298
|
+
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
|
299
|
+
CLANG_CXX_LIBRARY = "libc++";
|
|
300
|
+
CLANG_ENABLE_MODULES = YES;
|
|
301
|
+
CLANG_ENABLE_OBJC_ARC = YES;
|
|
302
|
+
CLANG_ENABLE_OBJC_WEAK = YES;
|
|
303
|
+
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
|
304
|
+
CLANG_WARN_BOOL_CONVERSION = YES;
|
|
305
|
+
CLANG_WARN_COMMA = YES;
|
|
306
|
+
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
|
307
|
+
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
|
308
|
+
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
|
309
|
+
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
|
310
|
+
CLANG_WARN_EMPTY_BODY = YES;
|
|
311
|
+
CLANG_WARN_ENUM_CONVERSION = YES;
|
|
312
|
+
CLANG_WARN_INFINITE_RECURSION = YES;
|
|
313
|
+
CLANG_WARN_INT_CONVERSION = YES;
|
|
314
|
+
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
|
315
|
+
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
|
316
|
+
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
|
317
|
+
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
|
318
|
+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
|
319
|
+
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
|
320
|
+
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
|
321
|
+
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
|
322
|
+
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
|
323
|
+
CLANG_WARN_UNREACHABLE_CODE = YES;
|
|
324
|
+
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
|
325
|
+
COPY_PHASE_STRIP = NO;
|
|
326
|
+
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
327
|
+
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
|
328
|
+
ENABLE_TESTABILITY = YES;
|
|
329
|
+
GCC_C_LANGUAGE_STANDARD = gnu11;
|
|
330
|
+
GCC_DYNAMIC_NO_PIC = NO;
|
|
331
|
+
GCC_NO_COMMON_BLOCKS = YES;
|
|
332
|
+
GCC_OPTIMIZATION_LEVEL = 0;
|
|
333
|
+
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
334
|
+
"$(inherited)",
|
|
335
|
+
"DEBUG=1",
|
|
336
|
+
);
|
|
337
|
+
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
338
|
+
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
|
339
|
+
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
|
340
|
+
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
|
341
|
+
GCC_WARN_UNUSED_FUNCTION = YES;
|
|
342
|
+
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
343
|
+
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
|
344
|
+
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
|
345
|
+
MTL_FAST_MATH = YES;
|
|
346
|
+
ONLY_ACTIVE_ARCH = YES;
|
|
347
|
+
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
348
|
+
SDKROOT = iphoneos;
|
|
349
|
+
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
|
350
|
+
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
|
351
|
+
SWIFT_VERSION = 5.0;
|
|
352
|
+
};
|
|
353
|
+
name = Debug;
|
|
354
|
+
};
|
|
355
|
+
/* End XCBuildConfiguration section */
|
|
356
|
+
|
|
357
|
+
/* Begin XCConfigurationList section */
|
|
358
|
+
32CF64B25AC119299FC98D21 /* Build configuration list for PBXNativeTarget "TreeHost" */ = {
|
|
359
|
+
isa = XCConfigurationList;
|
|
360
|
+
buildConfigurations = (
|
|
361
|
+
8D273ED725602839488F78BC /* Debug */,
|
|
362
|
+
04475AB2325A10E71BB05CF7 /* Release */,
|
|
363
|
+
);
|
|
364
|
+
defaultConfigurationIsVisible = 0;
|
|
365
|
+
defaultConfigurationName = Debug;
|
|
366
|
+
};
|
|
367
|
+
B268324BC08517F6C2141849 /* Build configuration list for PBXProject "TapflowTreeRunner" */ = {
|
|
368
|
+
isa = XCConfigurationList;
|
|
369
|
+
buildConfigurations = (
|
|
370
|
+
C6EA51ACA32945E2449085D0 /* Debug */,
|
|
371
|
+
17661D1CEC0BCB16F2CF8810 /* Release */,
|
|
372
|
+
);
|
|
373
|
+
defaultConfigurationIsVisible = 0;
|
|
374
|
+
defaultConfigurationName = Debug;
|
|
375
|
+
};
|
|
376
|
+
E0368676E0E41217C91B678B /* Build configuration list for PBXNativeTarget "TreeRunner" */ = {
|
|
377
|
+
isa = XCConfigurationList;
|
|
378
|
+
buildConfigurations = (
|
|
379
|
+
665CEF305E01AD84204FE1AA /* Debug */,
|
|
380
|
+
0F84FBE32B45B64354676D78 /* Release */,
|
|
381
|
+
);
|
|
382
|
+
defaultConfigurationIsVisible = 0;
|
|
383
|
+
defaultConfigurationName = Debug;
|
|
384
|
+
};
|
|
385
|
+
/* End XCConfigurationList section */
|
|
386
|
+
};
|
|
387
|
+
rootObject = E86248EBE591AA453974543F /* Project object */;
|
|
388
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<Scheme
|
|
3
|
+
LastUpgradeVersion = "1430"
|
|
4
|
+
version = "1.7">
|
|
5
|
+
<BuildAction
|
|
6
|
+
parallelizeBuildables = "YES"
|
|
7
|
+
buildImplicitDependencies = "YES"
|
|
8
|
+
runPostActionsOnFailure = "NO">
|
|
9
|
+
<BuildActionEntries>
|
|
10
|
+
<BuildActionEntry
|
|
11
|
+
buildForTesting = "YES"
|
|
12
|
+
buildForRunning = "YES"
|
|
13
|
+
buildForProfiling = "YES"
|
|
14
|
+
buildForArchiving = "YES"
|
|
15
|
+
buildForAnalyzing = "YES">
|
|
16
|
+
<BuildableReference
|
|
17
|
+
BuildableIdentifier = "primary"
|
|
18
|
+
BlueprintIdentifier = "AB37E7C89C6AC8FE774DE79B"
|
|
19
|
+
BuildableName = "TreeHost.app"
|
|
20
|
+
BlueprintName = "TreeHost"
|
|
21
|
+
ReferencedContainer = "container:TapflowTreeRunner.xcodeproj">
|
|
22
|
+
</BuildableReference>
|
|
23
|
+
</BuildActionEntry>
|
|
24
|
+
<BuildActionEntry
|
|
25
|
+
buildForTesting = "YES"
|
|
26
|
+
buildForRunning = "NO"
|
|
27
|
+
buildForProfiling = "NO"
|
|
28
|
+
buildForArchiving = "NO"
|
|
29
|
+
buildForAnalyzing = "NO">
|
|
30
|
+
<BuildableReference
|
|
31
|
+
BuildableIdentifier = "primary"
|
|
32
|
+
BlueprintIdentifier = "E94851893DB2D30285F8858D"
|
|
33
|
+
BuildableName = "TreeRunner.xctest"
|
|
34
|
+
BlueprintName = "TreeRunner"
|
|
35
|
+
ReferencedContainer = "container:TapflowTreeRunner.xcodeproj">
|
|
36
|
+
</BuildableReference>
|
|
37
|
+
</BuildActionEntry>
|
|
38
|
+
</BuildActionEntries>
|
|
39
|
+
</BuildAction>
|
|
40
|
+
<TestAction
|
|
41
|
+
buildConfiguration = "Debug"
|
|
42
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
43
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
44
|
+
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
45
|
+
onlyGenerateCoverageForSpecifiedTargets = "NO">
|
|
46
|
+
<MacroExpansion>
|
|
47
|
+
<BuildableReference
|
|
48
|
+
BuildableIdentifier = "primary"
|
|
49
|
+
BlueprintIdentifier = "AB37E7C89C6AC8FE774DE79B"
|
|
50
|
+
BuildableName = "TreeHost.app"
|
|
51
|
+
BlueprintName = "TreeHost"
|
|
52
|
+
ReferencedContainer = "container:TapflowTreeRunner.xcodeproj">
|
|
53
|
+
</BuildableReference>
|
|
54
|
+
</MacroExpansion>
|
|
55
|
+
<Testables>
|
|
56
|
+
<TestableReference
|
|
57
|
+
skipped = "NO"
|
|
58
|
+
parallelizable = "NO">
|
|
59
|
+
<BuildableReference
|
|
60
|
+
BuildableIdentifier = "primary"
|
|
61
|
+
BlueprintIdentifier = "E94851893DB2D30285F8858D"
|
|
62
|
+
BuildableName = "TreeRunner.xctest"
|
|
63
|
+
BlueprintName = "TreeRunner"
|
|
64
|
+
ReferencedContainer = "container:TapflowTreeRunner.xcodeproj">
|
|
65
|
+
</BuildableReference>
|
|
66
|
+
</TestableReference>
|
|
67
|
+
</Testables>
|
|
68
|
+
<CommandLineArguments>
|
|
69
|
+
</CommandLineArguments>
|
|
70
|
+
</TestAction>
|
|
71
|
+
<LaunchAction
|
|
72
|
+
buildConfiguration = "Debug"
|
|
73
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
74
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
75
|
+
launchStyle = "0"
|
|
76
|
+
useCustomWorkingDirectory = "NO"
|
|
77
|
+
ignoresPersistentStateOnLaunch = "NO"
|
|
78
|
+
debugDocumentVersioning = "YES"
|
|
79
|
+
debugServiceExtension = "internal"
|
|
80
|
+
allowLocationSimulation = "YES">
|
|
81
|
+
<BuildableProductRunnable
|
|
82
|
+
runnableDebuggingMode = "0">
|
|
83
|
+
<BuildableReference
|
|
84
|
+
BuildableIdentifier = "primary"
|
|
85
|
+
BlueprintIdentifier = "AB37E7C89C6AC8FE774DE79B"
|
|
86
|
+
BuildableName = "TreeHost.app"
|
|
87
|
+
BlueprintName = "TreeHost"
|
|
88
|
+
ReferencedContainer = "container:TapflowTreeRunner.xcodeproj">
|
|
89
|
+
</BuildableReference>
|
|
90
|
+
</BuildableProductRunnable>
|
|
91
|
+
</LaunchAction>
|
|
92
|
+
<ProfileAction
|
|
93
|
+
buildConfiguration = "Release"
|
|
94
|
+
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
95
|
+
savedToolIdentifier = ""
|
|
96
|
+
useCustomWorkingDirectory = "NO"
|
|
97
|
+
debugDocumentVersioning = "YES">
|
|
98
|
+
<BuildableProductRunnable
|
|
99
|
+
runnableDebuggingMode = "0">
|
|
100
|
+
<BuildableReference
|
|
101
|
+
BuildableIdentifier = "primary"
|
|
102
|
+
BlueprintIdentifier = "AB37E7C89C6AC8FE774DE79B"
|
|
103
|
+
BuildableName = "TreeHost.app"
|
|
104
|
+
BlueprintName = "TreeHost"
|
|
105
|
+
ReferencedContainer = "container:TapflowTreeRunner.xcodeproj">
|
|
106
|
+
</BuildableReference>
|
|
107
|
+
</BuildableProductRunnable>
|
|
108
|
+
</ProfileAction>
|
|
109
|
+
<AnalyzeAction
|
|
110
|
+
buildConfiguration = "Debug">
|
|
111
|
+
</AnalyzeAction>
|
|
112
|
+
<ArchiveAction
|
|
113
|
+
buildConfiguration = "Release"
|
|
114
|
+
revealArchiveInOrganizer = "YES">
|
|
115
|
+
</ArchiveAction>
|
|
116
|
+
</Scheme>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
// Minimal host app required by the UI-test target. The runner drives a SEPARATE
|
|
4
|
+
// app (the app under test) via XCUIApplication(bundleIdentifier:), so this host
|
|
5
|
+
// stays empty.
|
|
6
|
+
@main
|
|
7
|
+
struct TreeHostApp: App {
|
|
8
|
+
var body: some Scene {
|
|
9
|
+
WindowGroup {
|
|
10
|
+
Text("tapflow tree runner host")
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Network
|
|
3
|
+
import XCTest
|
|
4
|
+
|
|
5
|
+
// Minimal HTTP server that serves a target app's accessibility tree.
|
|
6
|
+
// Runs inside the resident UI-test process, so tree reads are window-agnostic
|
|
7
|
+
// (no Simulator.app window required — the tapflow headless path).
|
|
8
|
+
//
|
|
9
|
+
// Routes:
|
|
10
|
+
// GET /health → "ok" (readiness probe)
|
|
11
|
+
// GET /tree?bundleId=<id> → the app's XCUIApplication.debugDescription (text)
|
|
12
|
+
final class TreeServer {
|
|
13
|
+
private let listener: NWListener
|
|
14
|
+
private let queue = DispatchQueue(label: "dev.tapflow.treeserver")
|
|
15
|
+
|
|
16
|
+
init(port: UInt16) throws {
|
|
17
|
+
let params = NWParameters.tcp
|
|
18
|
+
params.allowLocalEndpointReuse = true
|
|
19
|
+
guard let nwPort = NWEndpoint.Port(rawValue: port) else {
|
|
20
|
+
throw NSError(domain: "TreeServer", code: 1, userInfo: [NSLocalizedDescriptionKey: "invalid port \(port)"])
|
|
21
|
+
}
|
|
22
|
+
// Bind loopback ONLY. The simulator shares the host's network stack, so a
|
|
23
|
+
// default all-interfaces bind would expose the app's UI tree to the LAN with
|
|
24
|
+
// no auth — tapflow keeps app data inside the machine. requiredLocalEndpoint
|
|
25
|
+
// forces the listen socket onto 127.0.0.1 (requiredInterfaceType alone does not).
|
|
26
|
+
params.requiredLocalEndpoint = NWEndpoint.hostPort(host: NWEndpoint.Host("127.0.0.1"), port: nwPort)
|
|
27
|
+
listener = try NWListener(using: params)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func start() {
|
|
31
|
+
listener.newConnectionHandler = { [weak self] conn in
|
|
32
|
+
guard let self else { return }
|
|
33
|
+
conn.start(queue: self.queue)
|
|
34
|
+
self.receive(conn, buffer: Data())
|
|
35
|
+
}
|
|
36
|
+
// Surface a bind failure (e.g. port held by a stale runner) immediately by
|
|
37
|
+
// exiting — otherwise the process stays alive looking "ready" and the host
|
|
38
|
+
// only fails after the full 90s /health poll.
|
|
39
|
+
listener.stateUpdateHandler = { state in
|
|
40
|
+
if case .failed(let error) = state {
|
|
41
|
+
FileHandle.standardError.write(Data("tree server failed to bind: \(error)\n".utf8))
|
|
42
|
+
exit(1)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
listener.start(queue: queue)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Accumulate bytes until the full request head arrives (GET has no body).
|
|
49
|
+
private func receive(_ conn: NWConnection, buffer: Data) {
|
|
50
|
+
conn.receive(minimumIncompleteLength: 1, maximumLength: 65536) { [weak self] data, _, isComplete, error in
|
|
51
|
+
guard let self else { return }
|
|
52
|
+
var buf = buffer
|
|
53
|
+
if let data { buf.append(data) }
|
|
54
|
+
if let head = String(data: buf, encoding: .utf8), head.contains("\r\n\r\n") {
|
|
55
|
+
self.handleRequest(conn, head: head)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
if isComplete || error != nil { conn.cancel(); return }
|
|
59
|
+
self.receive(conn, buffer: buf)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private func handleRequest(_ conn: NWConnection, head: String) {
|
|
64
|
+
let requestLine = head.split(separator: "\r\n", maxSplits: 1, omittingEmptySubsequences: false).first.map(String.init) ?? ""
|
|
65
|
+
let parts = requestLine.split(separator: " ")
|
|
66
|
+
let path = parts.count >= 2 ? String(parts[1]) : "/"
|
|
67
|
+
// XCUITest snapshot access must run on the main thread.
|
|
68
|
+
DispatchQueue.main.async {
|
|
69
|
+
let (status, body) = Self.route(path)
|
|
70
|
+
self.respond(conn, status: status, body: body)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private static func route(_ path: String) -> (String, String) {
|
|
75
|
+
if path.hasPrefix("/health") {
|
|
76
|
+
return ("200 OK", "ok")
|
|
77
|
+
}
|
|
78
|
+
if path.hasPrefix("/tree") {
|
|
79
|
+
guard let bundleId = query(path, "bundleId"), !bundleId.isEmpty else {
|
|
80
|
+
return ("400 Bad Request", "missing bundleId")
|
|
81
|
+
}
|
|
82
|
+
let app = XCUIApplication(bundleIdentifier: bundleId)
|
|
83
|
+
return ("200 OK", app.debugDescription)
|
|
84
|
+
}
|
|
85
|
+
return ("404 Not Found", "unknown route")
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private static func query(_ path: String, _ key: String) -> String? {
|
|
89
|
+
guard let q = path.split(separator: "?").dropFirst().first else { return nil }
|
|
90
|
+
for pair in q.split(separator: "&") {
|
|
91
|
+
let kv = pair.split(separator: "=", maxSplits: 1)
|
|
92
|
+
if kv.count == 2 && kv[0] == key {
|
|
93
|
+
let raw = String(kv[1])
|
|
94
|
+
return raw.removingPercentEncoding ?? raw
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return nil
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private func respond(_ conn: NWConnection, status: String, body: String) {
|
|
101
|
+
let bytes = Array(body.utf8)
|
|
102
|
+
let header = "HTTP/1.1 \(status)\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: \(bytes.count)\r\nConnection: close\r\n\r\n"
|
|
103
|
+
var out = Data(header.utf8)
|
|
104
|
+
out.append(contentsOf: bytes)
|
|
105
|
+
conn.send(content: out, completion: .contentProcessed { _ in conn.cancel() })
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
|
|
3
|
+
// Resident runner: starts the HTTP tree server, then blocks so the process stays
|
|
4
|
+
// alive serving queries until the host terminates it (session end / shutdown).
|
|
5
|
+
// The host detects readiness by polling GET /health on the chosen port.
|
|
6
|
+
final class TreeServerTest: XCTestCase {
|
|
7
|
+
func testServeTree() throws {
|
|
8
|
+
let portStr = ProcessInfo.processInfo.environment["TAPFLOW_TREE_PORT"] ?? "22087"
|
|
9
|
+
guard let port = UInt16(portStr) else {
|
|
10
|
+
XCTFail("invalid TAPFLOW_TREE_PORT: \(portStr)")
|
|
11
|
+
return
|
|
12
|
+
}
|
|
13
|
+
let server = try TreeServer(port: port)
|
|
14
|
+
server.start()
|
|
15
|
+
print("TAPFLOW_TREE_READY port=\(port)")
|
|
16
|
+
// Block forever — the host kills the process to stop the runner.
|
|
17
|
+
RunLoop.current.run()
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: TapflowTreeRunner
|
|
2
|
+
options:
|
|
3
|
+
bundleIdPrefix: dev.tapflow
|
|
4
|
+
deploymentTarget:
|
|
5
|
+
iOS: "16.0"
|
|
6
|
+
targets:
|
|
7
|
+
# Minimal host app the UI-test target attaches to. It never drives itself —
|
|
8
|
+
# the runner queries a SEPARATE target app via XCUIApplication(bundleIdentifier:).
|
|
9
|
+
TreeHost:
|
|
10
|
+
type: application
|
|
11
|
+
platform: iOS
|
|
12
|
+
sources: [TreeHost]
|
|
13
|
+
settings:
|
|
14
|
+
base:
|
|
15
|
+
GENERATE_INFOPLIST_FILE: true
|
|
16
|
+
PRODUCT_BUNDLE_IDENTIFIER: dev.tapflow.treerunner.host
|
|
17
|
+
# Resident UI-test target: launches, opens an HTTP server, and serves the
|
|
18
|
+
# accessibility tree of any bundleId on demand. Window-agnostic (runs inside
|
|
19
|
+
# the simulator) so it works with no Simulator.app window (tapflow headless path).
|
|
20
|
+
TreeRunner:
|
|
21
|
+
type: bundle.ui-testing
|
|
22
|
+
platform: iOS
|
|
23
|
+
sources: [TreeRunner]
|
|
24
|
+
dependencies:
|
|
25
|
+
- target: TreeHost
|
|
26
|
+
settings:
|
|
27
|
+
base:
|
|
28
|
+
GENERATE_INFOPLIST_FILE: true
|
|
29
|
+
PRODUCT_BUNDLE_IDENTIFIER: dev.tapflow.treerunner.uitests
|
|
30
|
+
schemes:
|
|
31
|
+
TreeRunner:
|
|
32
|
+
build:
|
|
33
|
+
targets:
|
|
34
|
+
TreeHost: all
|
|
35
|
+
TreeRunner: [test]
|
|
36
|
+
test:
|
|
37
|
+
targets: [TreeRunner]
|