zeno-mobile-runner 0.2.0 → 0.2.2
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/CHANGELOG.md +52 -0
- package/FEATURES.md +1 -1
- package/README.md +9 -1
- package/build.zig.zon +2 -2
- package/clients/kotlin/README.md +1 -1
- package/clients/kotlin/build.gradle.kts +1 -1
- package/clients/python/pyproject.toml +1 -1
- package/clients/rust/Cargo.lock +1 -1
- package/clients/rust/Cargo.toml +1 -1
- package/clients/typescript/package.json +1 -1
- package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
- package/docs/protocol.md +10 -10
- package/examples/ios-dev-client-open-link.json +24 -13
- package/examples/ios-dev-client-route-snapshot.json +33 -8
- package/npm/scenarios.mjs +15 -8
- package/npm/wizard.mjs +1 -1
- package/package.json +3 -1
- package/prebuilds/darwin-arm64/zmr +0 -0
- package/prebuilds/darwin-x64/zmr +0 -0
- package/prebuilds/linux-arm64/zmr +0 -0
- package/prebuilds/linux-x64/zmr +0 -0
- package/scripts/create-react-native-expo-demo-app.sh +11 -13
- package/shims/ios/ZMRShim.swift +40 -12
- package/shims/ios/ZMRShimUITestCase.swift +142 -16
- package/src/android.zig +10 -9
- package/src/android_emulator.zig +22 -11
- package/src/android_screen_recording.zig +11 -7
- package/src/bundle.zig +10 -9
- package/src/bundle_redaction.zig +29 -28
- package/src/bundle_tar.zig +15 -12
- package/src/cli_devices.zig +7 -3
- package/src/cli_discover.zig +7 -3
- package/src/cli_doctor.zig +7 -3
- package/src/cli_draft.zig +51 -47
- package/src/cli_explore.zig +7 -3
- package/src/cli_import.zig +8 -4
- package/src/cli_info.zig +13 -6
- package/src/cli_init.zig +9 -5
- package/src/cli_inspect.zig +8 -4
- package/src/cli_run.zig +22 -16
- package/src/cli_serve.zig +3 -3
- package/src/cli_trace.zig +25 -12
- package/src/cli_validate.zig +8 -4
- package/src/command.zig +81 -99
- package/src/config.zig +2 -1
- package/src/config_diagnostics.zig +2 -1
- package/src/config_paths.zig +2 -1
- package/src/doctor.zig +8 -7
- package/src/doctor_hints.zig +1 -1
- package/src/errors.zig +5 -5
- package/src/importer.zig +8 -7
- package/src/ios.zig +26 -29
- package/src/ios_devices.zig +6 -5
- package/src/ios_lifecycle.zig +4 -4
- package/src/json_rpc.zig +39 -40
- package/src/json_rpc_methods.zig +8 -8
- package/src/json_rpc_observation.zig +9 -8
- package/src/json_rpc_params.zig +1 -1
- package/src/json_rpc_trace.zig +22 -21
- package/src/main.zig +22 -10
- package/src/mcp.zig +28 -19
- package/src/mcp_trace.zig +30 -29
- package/src/report.zig +39 -36
- package/src/report_html.zig +5 -4
- package/src/runner.zig +2 -1
- package/src/runner_actions.zig +20 -17
- package/src/runner_diagnostics.zig +4 -4
- package/src/runner_events.zig +55 -51
- package/src/runner_native.zig +21 -19
- package/src/runner_waits.zig +46 -41
- package/src/scaffold.zig +25 -24
- package/src/scenario.zig +4 -3
- package/src/stdio.zig +129 -0
- package/src/trace.zig +34 -26
- package/src/trace_summary.zig +3 -2
- package/src/trace_summary_diagnostic.zig +15 -13
- package/src/validation.zig +5 -4
- package/src/version.zig +1 -1
package/src/bundle_tar.zig
CHANGED
|
@@ -1,42 +1,45 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
pub fn writeFile(
|
|
4
5
|
allocator: std.mem.Allocator,
|
|
5
6
|
trace_dir: []const u8,
|
|
6
7
|
archive_path: []const u8,
|
|
7
|
-
out_file: *std.
|
|
8
|
+
out_file: *std.Io.File,
|
|
8
9
|
) !void {
|
|
9
10
|
if (isUnsafeArchivePath(archive_path)) return error.UnsafeArchivePath;
|
|
10
11
|
const fs_path = try std.fs.path.join(allocator, &.{ trace_dir, archive_path });
|
|
11
12
|
defer allocator.free(fs_path);
|
|
12
13
|
|
|
13
|
-
var in_file = try std.
|
|
14
|
-
defer in_file.close();
|
|
15
|
-
const stat = try in_file.stat();
|
|
14
|
+
var in_file = try std.Io.Dir.cwd().openFile(stdio.io(), fs_path, .{});
|
|
15
|
+
defer in_file.close(stdio.io());
|
|
16
|
+
const stat = try in_file.stat(stdio.io());
|
|
16
17
|
|
|
17
18
|
var header = [_]u8{0} ** 512;
|
|
18
19
|
try writeHeader(&header, archive_path, stat.size);
|
|
19
20
|
|
|
20
|
-
try out_file.
|
|
21
|
+
try std.Io.File.writeStreamingAll(out_file.*, stdio.io(), &header);
|
|
22
|
+
var reader_buffer: [16 * 1024]u8 = undefined;
|
|
23
|
+
var reader = in_file.readerStreaming(stdio.io(), &reader_buffer);
|
|
21
24
|
var buffer: [16 * 1024]u8 = undefined;
|
|
22
25
|
var remaining = stat.size;
|
|
23
26
|
while (remaining > 0) {
|
|
24
27
|
const read_len = @min(buffer.len, remaining);
|
|
25
|
-
const n = try
|
|
28
|
+
const n = try reader.interface.readSliceShort(buffer[0..read_len]);
|
|
26
29
|
if (n == 0) return error.UnexpectedEndOfStream;
|
|
27
|
-
try out_file.
|
|
30
|
+
try std.Io.File.writeStreamingAll(out_file.*, stdio.io(), buffer[0..n]);
|
|
28
31
|
remaining -= n;
|
|
29
32
|
}
|
|
30
33
|
try writePadding(out_file, stat.size);
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
pub fn writeBytes(archive_path: []const u8, bytes: []const u8, out_file: *std.
|
|
36
|
+
pub fn writeBytes(archive_path: []const u8, bytes: []const u8, out_file: *std.Io.File) !void {
|
|
34
37
|
if (isUnsafeArchivePath(archive_path)) return error.UnsafeArchivePath;
|
|
35
38
|
var header = [_]u8{0} ** 512;
|
|
36
39
|
try writeHeader(&header, archive_path, bytes.len);
|
|
37
40
|
|
|
38
|
-
try out_file.
|
|
39
|
-
try out_file.
|
|
41
|
+
try std.Io.File.writeStreamingAll(out_file.*, stdio.io(), &header);
|
|
42
|
+
try std.Io.File.writeStreamingAll(out_file.*, stdio.io(), bytes);
|
|
40
43
|
try writePadding(out_file, bytes.len);
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -57,9 +60,9 @@ fn writeHeader(header: *[512]u8, archive_path: []const u8, size: u64) !void {
|
|
|
57
60
|
writeChecksum(header[148..156], checksum);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
fn writePadding(out_file: *std.
|
|
63
|
+
fn writePadding(out_file: *std.Io.File, size: u64) !void {
|
|
61
64
|
const padding = (512 - (size % 512)) % 512;
|
|
62
|
-
if (padding > 0) try out_file.
|
|
65
|
+
if (padding > 0) try std.Io.File.writeStreamingAll(out_file.*, stdio.io(), (&([_]u8{0} ** 512))[0..padding]);
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
fn isUnsafeArchivePath(archive_path: []const u8) bool {
|
package/src/cli_devices.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
const android = @import("android.zig");
|
|
3
4
|
const device_registry = @import("device_registry.zig");
|
|
4
5
|
const ios = @import("ios.zig");
|
|
@@ -11,7 +12,7 @@ pub const IosDevicesScope = enum {
|
|
|
11
12
|
all,
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
15
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
15
16
|
var platform: run_options.Platform = .android;
|
|
16
17
|
var ios_devices_scope: IosDevicesScope = .simulator;
|
|
17
18
|
var adb_path: []const u8 = "adb";
|
|
@@ -30,7 +31,7 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
30
31
|
} else if (std.mem.eql(u8, arg, "--json")) {
|
|
31
32
|
json = true;
|
|
32
33
|
} else {
|
|
33
|
-
return error.
|
|
34
|
+
return error.unknownFlag;
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -43,7 +44,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
43
44
|
allocator.free(devices);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
var stdout_io: stdio.Output = .{};
|
|
48
|
+
stdout_io.init(.stdout());
|
|
49
|
+
defer stdout_io.deinit();
|
|
50
|
+
const stdout = stdout_io.writer();
|
|
47
51
|
if (json) return try device_registry.writeJson(stdout, registryPlatform(platform), devices);
|
|
48
52
|
if (devices.len == 0) return try stdout.print("No {s} devices found.\n", .{@tagName(platform)});
|
|
49
53
|
for (devices) |device| {
|
package/src/cli_discover.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const cli_draft = @import("cli_draft.zig");
|
|
4
5
|
const cli_output = @import("cli_output.zig");
|
|
@@ -68,7 +69,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
68
69
|
} else if (std.mem.eql(u8, arg, "--json")) {
|
|
69
70
|
parsed.json = true;
|
|
70
71
|
} else {
|
|
71
|
-
return error.
|
|
72
|
+
return error.unknownFlag;
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
@@ -77,7 +78,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
77
78
|
return parsed;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
81
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
81
82
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
82
83
|
defer raw_args.deinit(allocator);
|
|
83
84
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
@@ -86,7 +87,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
86
87
|
var discovered = try discoverFromTrace(allocator, parsed);
|
|
87
88
|
defer discovered.deinit(allocator);
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
var stdout_io: stdio.Output = .{};
|
|
91
|
+
stdout_io.init(.stdout());
|
|
92
|
+
defer stdout_io.deinit();
|
|
93
|
+
const stdout = stdout_io.writer();
|
|
90
94
|
if (parsed.json) {
|
|
91
95
|
try writeJson(stdout, discovered.summary, discovered.validation);
|
|
92
96
|
} else {
|
package/src/cli_doctor.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const cli_output = @import("cli_output.zig");
|
|
4
5
|
const config = @import("config.zig");
|
|
@@ -42,13 +43,13 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
42
43
|
parsed.config_path = if (index < args.len) args[index] else return error.MissingConfigPath;
|
|
43
44
|
parsed.explicit_config = true;
|
|
44
45
|
} else {
|
|
45
|
-
return error.
|
|
46
|
+
return error.unknownFlag;
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
return parsed;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
52
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
52
53
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
53
54
|
defer raw_args.deinit(allocator);
|
|
54
55
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
@@ -104,7 +105,10 @@ fn runParsed(allocator: std.mem.Allocator, parsed: ParsedArgs) !void {
|
|
|
104
105
|
allocator.free(checks);
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
var stdout_io: stdio.Output = .{};
|
|
109
|
+
stdout_io.init(.stdout());
|
|
110
|
+
defer stdout_io.deinit();
|
|
111
|
+
const stdout = stdout_io.writer();
|
|
108
112
|
if (parsed.json) {
|
|
109
113
|
try cli_output.writeDoctorJson(stdout, config_check, checks);
|
|
110
114
|
} else {
|
package/src/cli_draft.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const cli_output = @import("cli_output.zig");
|
|
4
5
|
const trace = @import("trace.zig");
|
|
@@ -100,7 +101,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
100
101
|
} else if (std.mem.eql(u8, arg, "--json")) {
|
|
101
102
|
parsed.json = true;
|
|
102
103
|
} else {
|
|
103
|
-
return error.
|
|
104
|
+
return error.unknownFlag;
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
|
|
@@ -109,7 +110,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
109
110
|
return parsed;
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
113
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
113
114
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
114
115
|
defer raw_args.deinit(allocator);
|
|
115
116
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
@@ -118,7 +119,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
118
119
|
var draft = try draftFromTrace(allocator, parsed);
|
|
119
120
|
defer draft.deinit(allocator);
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
var stdout_io: stdio.Output = .{};
|
|
123
|
+
stdout_io.init(.stdout());
|
|
124
|
+
defer stdout_io.deinit();
|
|
125
|
+
const stdout = stdout_io.writer();
|
|
122
126
|
if (parsed.json) {
|
|
123
127
|
try writeJson(stdout, draft.summary);
|
|
124
128
|
return;
|
|
@@ -150,7 +154,7 @@ pub fn draftFromTrace(allocator: std.mem.Allocator, parsed: ParsedArgs) !OwnedDr
|
|
|
150
154
|
|
|
151
155
|
const manifest_path = try std.fs.path.join(allocator, &.{ from_trace, "trace.json" });
|
|
152
156
|
defer allocator.free(manifest_path);
|
|
153
|
-
const manifest_content = try
|
|
157
|
+
const manifest_content = try stdio.readFileAlloc(allocator, manifest_path, 1024 * 1024);
|
|
154
158
|
defer allocator.free(manifest_content);
|
|
155
159
|
|
|
156
160
|
var parsed_manifest = try std.json.parseFromSlice(std.json.Value, allocator, manifest_content, .{});
|
|
@@ -219,7 +223,7 @@ fn parseReplaySteps(
|
|
|
219
223
|
) !ReplayDraft {
|
|
220
224
|
const events_path = try std.fs.path.join(allocator, &.{ trace_dir, metadata.events_path });
|
|
221
225
|
defer allocator.free(events_path);
|
|
222
|
-
const content =
|
|
226
|
+
const content = stdio.readFileAlloc(allocator, events_path, 64 * 1024 * 1024) catch |err| switch (err) {
|
|
223
227
|
error.FileNotFound => {
|
|
224
228
|
try appendWarning(allocator, owned, "trace events were not found; action replay was skipped");
|
|
225
229
|
return .{
|
|
@@ -393,14 +397,14 @@ fn latestSnapshotPath(
|
|
|
393
397
|
|
|
394
398
|
const artifacts_path = try std.fs.path.join(allocator, &.{ trace_dir, metadata.artifacts_dir });
|
|
395
399
|
defer allocator.free(artifacts_path);
|
|
396
|
-
var dir = try std.
|
|
397
|
-
defer dir.close();
|
|
400
|
+
var dir = try std.Io.Dir.cwd().openDir(stdio.io(), artifacts_path, .{ .iterate = true });
|
|
401
|
+
defer dir.close(stdio.io());
|
|
398
402
|
|
|
399
403
|
var iterator = dir.iterate();
|
|
400
404
|
var best_number: usize = 0;
|
|
401
405
|
var best_name: ?[]u8 = null;
|
|
402
406
|
defer if (best_name) |value| allocator.free(value);
|
|
403
|
-
while (try iterator.next()) |entry| {
|
|
407
|
+
while (try iterator.next(stdio.io())) |entry| {
|
|
404
408
|
if (entry.kind != .file) continue;
|
|
405
409
|
const number = snapshotNumber(entry.name) orelse continue;
|
|
406
410
|
if (best_name == null or number > best_number) {
|
|
@@ -422,7 +426,7 @@ fn parseSemanticSelectors(
|
|
|
422
426
|
path: []const u8,
|
|
423
427
|
owned: *OwnedDraft,
|
|
424
428
|
) ![]DraftSelector {
|
|
425
|
-
const content = try
|
|
429
|
+
const content = try stdio.readFileAlloc(allocator, path, 8 * 1024 * 1024);
|
|
426
430
|
defer allocator.free(content);
|
|
427
431
|
|
|
428
432
|
var parsed = try std.json.parseFromSlice(std.json.Value, allocator, content, .{});
|
|
@@ -505,16 +509,16 @@ fn writeScenarioFile(
|
|
|
505
509
|
force: bool,
|
|
506
510
|
) !void {
|
|
507
511
|
if (std.fs.path.dirname(out_path)) |dir| {
|
|
508
|
-
if (dir.len > 0) try std.
|
|
512
|
+
if (dir.len > 0) try std.Io.Dir.cwd().createDirPath(stdio.io(), dir);
|
|
509
513
|
}
|
|
510
514
|
var file = if (force)
|
|
511
|
-
try std.
|
|
515
|
+
try std.Io.Dir.cwd().createFile(stdio.io(), out_path, .{ .truncate = true })
|
|
512
516
|
else
|
|
513
|
-
try std.
|
|
514
|
-
defer file.close();
|
|
517
|
+
try std.Io.Dir.cwd().createFile(stdio.io(), out_path, .{ .exclusive = true });
|
|
518
|
+
defer file.close(stdio.io());
|
|
515
519
|
|
|
516
520
|
var write_buffer: [8192]u8 = undefined;
|
|
517
|
-
var file_writer = file.
|
|
521
|
+
var file_writer = file.writerStreaming(stdio.io(), &write_buffer);
|
|
518
522
|
try writeScenarioJson(&file_writer.interface, name, app_id, action_steps, selectors);
|
|
519
523
|
try file_writer.interface.flush();
|
|
520
524
|
}
|
|
@@ -609,9 +613,9 @@ fn actionWithStringField(
|
|
|
609
613
|
key: []const u8,
|
|
610
614
|
value: []const u8,
|
|
611
615
|
) ![]const u8 {
|
|
612
|
-
var buffer =
|
|
613
|
-
defer buffer.deinit(
|
|
614
|
-
const writer = buffer.writer
|
|
616
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
617
|
+
defer buffer.deinit();
|
|
618
|
+
const writer = &buffer.writer;
|
|
615
619
|
try writer.writeAll("{\"action\":");
|
|
616
620
|
try trace.writeJsonString(writer, action);
|
|
617
621
|
try writer.writeAll(",");
|
|
@@ -619,7 +623,7 @@ fn actionWithStringField(
|
|
|
619
623
|
try writer.writeAll(":");
|
|
620
624
|
try trace.writeJsonString(writer, value);
|
|
621
625
|
try writer.writeAll("}");
|
|
622
|
-
return try ownBytes(allocator, owned, buffer.
|
|
626
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
623
627
|
}
|
|
624
628
|
|
|
625
629
|
fn actionWithIntField(
|
|
@@ -629,15 +633,15 @@ fn actionWithIntField(
|
|
|
629
633
|
key: []const u8,
|
|
630
634
|
value: usize,
|
|
631
635
|
) ![]const u8 {
|
|
632
|
-
var buffer =
|
|
633
|
-
defer buffer.deinit(
|
|
634
|
-
const writer = buffer.writer
|
|
636
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
637
|
+
defer buffer.deinit();
|
|
638
|
+
const writer = &buffer.writer;
|
|
635
639
|
try writer.writeAll("{\"action\":");
|
|
636
640
|
try trace.writeJsonString(writer, action);
|
|
637
641
|
try writer.writeAll(",");
|
|
638
642
|
try trace.writeJsonString(writer, key);
|
|
639
643
|
try writer.print(":{d}}}", .{value});
|
|
640
|
-
return try ownBytes(allocator, owned, buffer.
|
|
644
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
641
645
|
}
|
|
642
646
|
|
|
643
647
|
fn actionWithSelector(
|
|
@@ -646,15 +650,15 @@ fn actionWithSelector(
|
|
|
646
650
|
action: []const u8,
|
|
647
651
|
selector_value: std.json.Value,
|
|
648
652
|
) ![]const u8 {
|
|
649
|
-
var buffer =
|
|
650
|
-
defer buffer.deinit(
|
|
651
|
-
const writer = buffer.writer
|
|
653
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
654
|
+
defer buffer.deinit();
|
|
655
|
+
const writer = &buffer.writer;
|
|
652
656
|
try writer.writeAll("{\"action\":");
|
|
653
657
|
try trace.writeJsonString(writer, action);
|
|
654
658
|
try writer.writeAll(",\"selector\":");
|
|
655
659
|
try writeJsonValue(writer, selector_value);
|
|
656
660
|
try writer.writeAll("}");
|
|
657
|
-
return try ownBytes(allocator, owned, buffer.
|
|
661
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
658
662
|
}
|
|
659
663
|
|
|
660
664
|
fn actionWithSelectorAndString(
|
|
@@ -665,9 +669,9 @@ fn actionWithSelectorAndString(
|
|
|
665
669
|
key: []const u8,
|
|
666
670
|
value: []const u8,
|
|
667
671
|
) ![]const u8 {
|
|
668
|
-
var buffer =
|
|
669
|
-
defer buffer.deinit(
|
|
670
|
-
const writer = buffer.writer
|
|
672
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
673
|
+
defer buffer.deinit();
|
|
674
|
+
const writer = &buffer.writer;
|
|
671
675
|
try writer.writeAll("{\"action\":");
|
|
672
676
|
try trace.writeJsonString(writer, action);
|
|
673
677
|
try writer.writeAll(",\"selector\":");
|
|
@@ -677,7 +681,7 @@ fn actionWithSelectorAndString(
|
|
|
677
681
|
try writer.writeAll(":");
|
|
678
682
|
try trace.writeJsonString(writer, value);
|
|
679
683
|
try writer.writeAll("}");
|
|
680
|
-
return try ownBytes(allocator, owned, buffer.
|
|
684
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
681
685
|
}
|
|
682
686
|
|
|
683
687
|
fn actionWithSelectorAndInt(
|
|
@@ -688,9 +692,9 @@ fn actionWithSelectorAndInt(
|
|
|
688
692
|
key: []const u8,
|
|
689
693
|
value: usize,
|
|
690
694
|
) ![]const u8 {
|
|
691
|
-
var buffer =
|
|
692
|
-
defer buffer.deinit(
|
|
693
|
-
const writer = buffer.writer
|
|
695
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
696
|
+
defer buffer.deinit();
|
|
697
|
+
const writer = &buffer.writer;
|
|
694
698
|
try writer.writeAll("{\"action\":");
|
|
695
699
|
try trace.writeJsonString(writer, action);
|
|
696
700
|
try writer.writeAll(",\"selector\":");
|
|
@@ -698,7 +702,7 @@ fn actionWithSelectorAndInt(
|
|
|
698
702
|
try writer.writeAll(",");
|
|
699
703
|
try trace.writeJsonString(writer, key);
|
|
700
704
|
try writer.print(":{d}}}", .{value});
|
|
701
|
-
return try ownBytes(allocator, owned, buffer.
|
|
705
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
702
706
|
}
|
|
703
707
|
|
|
704
708
|
fn actionWithSelectors(
|
|
@@ -708,16 +712,16 @@ fn actionWithSelectors(
|
|
|
708
712
|
selectors_value: std.json.Value,
|
|
709
713
|
timeout_ms: ?usize,
|
|
710
714
|
) ![]const u8 {
|
|
711
|
-
var buffer =
|
|
712
|
-
defer buffer.deinit(
|
|
713
|
-
const writer = buffer.writer
|
|
715
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
716
|
+
defer buffer.deinit();
|
|
717
|
+
const writer = &buffer.writer;
|
|
714
718
|
try writer.writeAll("{\"action\":");
|
|
715
719
|
try trace.writeJsonString(writer, action);
|
|
716
720
|
try writer.writeAll(",\"selectors\":");
|
|
717
721
|
try writeJsonValue(writer, selectors_value);
|
|
718
722
|
if (timeout_ms) |actual| try writer.print(",\"timeoutMs\":{d}", .{actual});
|
|
719
723
|
try writer.writeAll("}");
|
|
720
|
-
return try ownBytes(allocator, owned, buffer.
|
|
724
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
721
725
|
}
|
|
722
726
|
|
|
723
727
|
fn actionWithSwipe(
|
|
@@ -729,13 +733,13 @@ fn actionWithSwipe(
|
|
|
729
733
|
y2: i32,
|
|
730
734
|
duration_ms: ?usize,
|
|
731
735
|
) ![]const u8 {
|
|
732
|
-
var buffer =
|
|
733
|
-
defer buffer.deinit(
|
|
734
|
-
const writer = buffer.writer
|
|
736
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
737
|
+
defer buffer.deinit();
|
|
738
|
+
const writer = &buffer.writer;
|
|
735
739
|
try writer.print("{{\"action\":\"swipe\",\"x1\":{d},\"y1\":{d},\"x2\":{d},\"y2\":{d}", .{ x1, y1, x2, y2 });
|
|
736
740
|
if (duration_ms) |actual| try writer.print(",\"durationMs\":{d}", .{actual});
|
|
737
741
|
try writer.writeAll("}");
|
|
738
|
-
return try ownBytes(allocator, owned, buffer.
|
|
742
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
739
743
|
}
|
|
740
744
|
|
|
741
745
|
fn actionWithScrollUntilVisible(
|
|
@@ -745,9 +749,9 @@ fn actionWithScrollUntilVisible(
|
|
|
745
749
|
direction: ?[]const u8,
|
|
746
750
|
timeout_ms: ?usize,
|
|
747
751
|
) ![]const u8 {
|
|
748
|
-
var buffer =
|
|
749
|
-
defer buffer.deinit(
|
|
750
|
-
const writer = buffer.writer
|
|
752
|
+
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
|
753
|
+
defer buffer.deinit();
|
|
754
|
+
const writer = &buffer.writer;
|
|
751
755
|
try writer.writeAll("{\"action\":\"scrollUntilVisible\",\"selector\":");
|
|
752
756
|
try writeJsonValue(writer, selector_value);
|
|
753
757
|
if (direction) |actual| {
|
|
@@ -756,7 +760,7 @@ fn actionWithScrollUntilVisible(
|
|
|
756
760
|
}
|
|
757
761
|
if (timeout_ms) |actual| try writer.print(",\"timeoutMs\":{d}", .{actual});
|
|
758
762
|
try writer.writeAll("}");
|
|
759
|
-
return try ownBytes(allocator, owned, buffer.
|
|
763
|
+
return try ownBytes(allocator, owned, buffer.writer.buffered());
|
|
760
764
|
}
|
|
761
765
|
|
|
762
766
|
fn warnMissingReplayField(
|
|
@@ -919,6 +923,6 @@ fn snapshotNumber(name: []const u8) ?usize {
|
|
|
919
923
|
}
|
|
920
924
|
|
|
921
925
|
fn pathExists(path: []const u8) bool {
|
|
922
|
-
|
|
926
|
+
stdio.access(path) catch return false;
|
|
923
927
|
return true;
|
|
924
928
|
}
|
package/src/cli_explore.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const cli_discover = @import("cli_discover.zig");
|
|
4
5
|
const cli_output = @import("cli_output.zig");
|
|
@@ -66,7 +67,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
66
67
|
} else if (std.mem.eql(u8, arg, "--json")) {
|
|
67
68
|
parsed.json = true;
|
|
68
69
|
} else {
|
|
69
|
-
return error.
|
|
70
|
+
return error.unknownFlag;
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -75,7 +76,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
75
76
|
return parsed;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
79
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
79
80
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
80
81
|
defer raw_args.deinit(allocator);
|
|
81
82
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
@@ -84,7 +85,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
84
85
|
var explored = try exploreFromTrace(allocator, parsed);
|
|
85
86
|
defer explored.deinit(allocator);
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
var stdout_io: stdio.Output = .{};
|
|
89
|
+
stdout_io.init(.stdout());
|
|
90
|
+
defer stdout_io.deinit();
|
|
91
|
+
const stdout = stdout_io.writer();
|
|
88
92
|
if (parsed.json) {
|
|
89
93
|
try writeJson(stdout, explored.summary, explored.discovered.summary, explored.discovered.validation);
|
|
90
94
|
} else {
|
package/src/cli_import.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const cli_output = @import("cli_output.zig");
|
|
4
5
|
const importer = @import("importer.zig");
|
|
@@ -39,13 +40,13 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
39
40
|
} else if (std.mem.eql(u8, arg, "--json")) {
|
|
40
41
|
json = true;
|
|
41
42
|
} else if (std.mem.startsWith(u8, arg, "--")) {
|
|
42
|
-
return error.
|
|
43
|
+
return error.unknownFlag;
|
|
43
44
|
} else if (format == null) {
|
|
44
45
|
format = arg;
|
|
45
46
|
} else if (source_path == null) {
|
|
46
47
|
source_path = arg;
|
|
47
48
|
} else {
|
|
48
|
-
return error.
|
|
49
|
+
return error.unknownFlag;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
if (format == null) return error.MissingImportFormat;
|
|
@@ -62,7 +63,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
66
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
66
67
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
67
68
|
defer raw_args.deinit(allocator);
|
|
68
69
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
@@ -77,7 +78,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
77
78
|
});
|
|
78
79
|
defer result.deinit(allocator);
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
var stdout_io: stdio.Output = .{};
|
|
82
|
+
stdout_io.init(.stdout());
|
|
83
|
+
defer stdout_io.deinit();
|
|
84
|
+
const stdout = stdout_io.writer();
|
|
81
85
|
if (parsed.json) return try cli_output.writeImportJson(stdout, parsed.format, parsed.source_path, result);
|
|
82
86
|
try stdout.print("wrote {s}\n", .{result.out_path});
|
|
83
87
|
try stdout.writeAll("next: zmr validate ");
|
package/src/cli_info.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const schema_registry = @import("schema_registry.zig");
|
|
4
5
|
const version = @import("version.zig");
|
|
@@ -9,29 +10,35 @@ pub fn parseJsonFlag(args: []const []const u8) !bool {
|
|
|
9
10
|
if (std.mem.eql(u8, arg, "--json")) {
|
|
10
11
|
json = true;
|
|
11
12
|
} else {
|
|
12
|
-
return error.
|
|
13
|
+
return error.unknownFlag;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
return json;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
pub fn runVersion(allocator: std.mem.Allocator, args: *std.process.
|
|
19
|
+
pub fn runVersion(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
19
20
|
const json = try parseArgIterator(allocator, args);
|
|
20
|
-
|
|
21
|
+
var stdout_io: stdio.Output = .{};
|
|
22
|
+
stdout_io.init(.stdout());
|
|
23
|
+
defer stdout_io.deinit();
|
|
24
|
+
const stdout = stdout_io.writer();
|
|
21
25
|
if (json) return try version.writeJson(stdout);
|
|
22
26
|
try version.writePlain(stdout);
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
pub fn runSchemas(allocator: std.mem.Allocator, args: *std.process.
|
|
29
|
+
pub fn runSchemas(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
26
30
|
const json = try parseArgIterator(allocator, args);
|
|
27
|
-
|
|
31
|
+
var stdout_io: stdio.Output = .{};
|
|
32
|
+
stdout_io.init(.stdout());
|
|
33
|
+
defer stdout_io.deinit();
|
|
34
|
+
const stdout = stdout_io.writer();
|
|
28
35
|
if (json) return try schema_registry.writeJson(stdout);
|
|
29
36
|
for (schema_registry.all()) |schema_info| {
|
|
30
37
|
try stdout.print("{s}\t{s}\n", .{ schema_info.name, schema_info.path });
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
fn parseArgIterator(allocator: std.mem.Allocator, args: *std.process.
|
|
41
|
+
fn parseArgIterator(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !bool {
|
|
35
42
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
36
43
|
defer raw_args.deinit(allocator);
|
|
37
44
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
package/src/cli_init.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const cli_output = @import("cli_output.zig");
|
|
4
5
|
const scaffold = @import("scaffold.zig");
|
|
@@ -31,26 +32,29 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
31
32
|
} else if (std.mem.eql(u8, arg, "--json")) {
|
|
32
33
|
parsed.json = true;
|
|
33
34
|
} else if (std.mem.startsWith(u8, arg, "--")) {
|
|
34
|
-
return error.
|
|
35
|
+
return error.unknownFlag;
|
|
35
36
|
} else if (parsed.app_scaffold) {
|
|
36
|
-
return error.
|
|
37
|
+
return error.unknownFlag;
|
|
37
38
|
} else if (!path_set) {
|
|
38
39
|
parsed.path = arg;
|
|
39
40
|
path_set = true;
|
|
40
41
|
} else {
|
|
41
|
-
return error.
|
|
42
|
+
return error.unknownFlag;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
return parsed;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
48
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
48
49
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
49
50
|
defer raw_args.deinit(allocator);
|
|
50
51
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
51
52
|
|
|
52
53
|
const parsed = try parseArgs(raw_args.items);
|
|
53
|
-
|
|
54
|
+
var stdout_io: stdio.Output = .{};
|
|
55
|
+
stdout_io.init(.stdout());
|
|
56
|
+
defer stdout_io.deinit();
|
|
57
|
+
const stdout = stdout_io.writer();
|
|
54
58
|
if (parsed.app_scaffold) {
|
|
55
59
|
try scaffold.writeAppScaffold(allocator, parsed.dir, parsed.app_id, parsed.force);
|
|
56
60
|
if (parsed.json) return try cli_output.writeInitAppJson(stdout, parsed.dir, parsed.app_id);
|
package/src/cli_inspect.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const std = @import("std");
|
|
2
|
+
const stdio = @import("stdio.zig");
|
|
2
3
|
|
|
3
4
|
const config = @import("config.zig");
|
|
4
5
|
const scaffold = @import("scaffold.zig");
|
|
@@ -59,13 +60,13 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
|
|
|
59
60
|
index += 1;
|
|
60
61
|
parsed.config_path = if (index < args.len) args[index] else return error.MissingParam;
|
|
61
62
|
} else {
|
|
62
|
-
return error.
|
|
63
|
+
return error.unknownFlag;
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
return parsed;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
pub fn run(allocator: std.mem.Allocator, args: *std.process.
|
|
69
|
+
pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
|
|
69
70
|
var raw_args = std.ArrayList([]const u8).empty;
|
|
70
71
|
defer raw_args.deinit(allocator);
|
|
71
72
|
while (args.next()) |arg| try raw_args.append(allocator, arg);
|
|
@@ -74,7 +75,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
|
|
|
74
75
|
var owned = try inspect(allocator, parsed);
|
|
75
76
|
defer owned.deinit(allocator);
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
var stdout_io: stdio.Output = .{};
|
|
79
|
+
stdout_io.init(.stdout());
|
|
80
|
+
defer stdout_io.deinit();
|
|
81
|
+
const stdout = stdout_io.writer();
|
|
78
82
|
if (parsed.json) {
|
|
79
83
|
try writeJson(stdout, owned.inspection);
|
|
80
84
|
} else {
|
|
@@ -140,7 +144,7 @@ fn appendPlatform(
|
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
fn pathExists(path: []const u8) bool {
|
|
143
|
-
|
|
147
|
+
stdio.access(path) catch return false;
|
|
144
148
|
return true;
|
|
145
149
|
}
|
|
146
150
|
|