tauri-test-cli 0.4.1 → 0.6.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/cli.js CHANGED
@@ -11320,7 +11320,7 @@ var require_async = __commonJS((exports, module) => {
11320
11320
  return awaitable;
11321
11321
  }
11322
11322
  function applyEach$1(eachfn) {
11323
- return function applyEach(fns, ...callArgs) {
11323
+ return function applyEach2(fns, ...callArgs) {
11324
11324
  const go = awaitify(function(callback) {
11325
11325
  var that = this;
11326
11326
  return eachfn(fns, (fn, cb) => {
@@ -13720,9 +13720,9 @@ GFS4: `);
13720
13720
  function readdir(path, options, cb) {
13721
13721
  if (typeof options === "function")
13722
13722
  cb = options, options = null;
13723
- var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir(path2, options2, cb2, startTime) {
13723
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path2, options2, cb2, startTime) {
13724
13724
  return fs$readdir(path2, fs$readdirCallback(path2, options2, cb2, startTime));
13725
- } : function go$readdir(path2, options2, cb2, startTime) {
13725
+ } : function go$readdir2(path2, options2, cb2, startTime) {
13726
13726
  return fs$readdir(path2, options2, fs$readdirCallback(path2, options2, cb2, startTime));
13727
13727
  };
13728
13728
  return go$readdir(path, options, cb);
@@ -17462,9 +17462,9 @@ var require_util3 = __commonJS((exports, module) => {
17462
17462
  var AbortController2 = globalThis.AbortController || require_abort_controller().AbortController;
17463
17463
  var AsyncFunction = Object.getPrototypeOf(async function() {}).constructor;
17464
17464
  var Blob2 = globalThis.Blob || bufferModule.Blob;
17465
- var isBlob = typeof Blob2 !== "undefined" ? function isBlob(b) {
17465
+ var isBlob = typeof Blob2 !== "undefined" ? function isBlob2(b) {
17466
17466
  return b instanceof Blob2;
17467
- } : function isBlob(b) {
17467
+ } : function isBlob2(b) {
17468
17468
  return false;
17469
17469
  };
17470
17470
  var validateAbortSignal = (signal, name) => {
@@ -20945,9 +20945,9 @@ var require_duplexify = __commonJS((exports, module) => {
20945
20945
  var { createDeferredPromise } = require_util3();
20946
20946
  var from = require_from();
20947
20947
  var Blob2 = globalThis.Blob || bufferModule.Blob;
20948
- var isBlob = typeof Blob2 !== "undefined" ? function isBlob(b) {
20948
+ var isBlob = typeof Blob2 !== "undefined" ? function isBlob2(b) {
20949
20949
  return b instanceof Blob2;
20950
- } : function isBlob(b) {
20950
+ } : function isBlob2(b) {
20951
20951
  return false;
20952
20952
  };
20953
20953
  var AbortController2 = globalThis.AbortController || require_abort_controller().AbortController;
@@ -22123,7 +22123,7 @@ var require_operators = __commonJS((exports, module) => {
22123
22123
  validateInteger(concurrency, "options.concurrency", 1);
22124
22124
  validateInteger(highWaterMark, "options.highWaterMark", 0);
22125
22125
  highWaterMark += concurrency;
22126
- return async function* map() {
22126
+ return async function* map2() {
22127
22127
  const signal = require_util3().AbortSignalAny([options === null || options === undefined ? undefined : options.signal].filter(Boolean2));
22128
22128
  const stream = this;
22129
22129
  const queue = [];
@@ -22229,7 +22229,7 @@ var require_operators = __commonJS((exports, module) => {
22229
22229
  if ((options === null || options === undefined ? undefined : options.signal) != null) {
22230
22230
  validateAbortSignal(options.signal, "options.signal");
22231
22231
  }
22232
- return async function* asIndexedPairs() {
22232
+ return async function* asIndexedPairs2() {
22233
22233
  let index = 0;
22234
22234
  for await (const val of this) {
22235
22235
  var _options$signal;
@@ -22368,7 +22368,7 @@ var require_operators = __commonJS((exports, module) => {
22368
22368
  }
22369
22369
  function flatMap(fn, options) {
22370
22370
  const values = map.call(this, fn, options);
22371
- return async function* flatMap() {
22371
+ return async function* flatMap2() {
22372
22372
  for await (const val of values) {
22373
22373
  yield* val;
22374
22374
  }
@@ -22392,7 +22392,7 @@ var require_operators = __commonJS((exports, module) => {
22392
22392
  validateAbortSignal(options.signal, "options.signal");
22393
22393
  }
22394
22394
  number = toIntegerOrInfinity(number);
22395
- return async function* drop() {
22395
+ return async function* drop2() {
22396
22396
  var _options$signal5;
22397
22397
  if (options !== null && options !== undefined && (_options$signal5 = options.signal) !== null && _options$signal5 !== undefined && _options$signal5.aborted) {
22398
22398
  throw new AbortError;
@@ -22416,7 +22416,7 @@ var require_operators = __commonJS((exports, module) => {
22416
22416
  validateAbortSignal(options.signal, "options.signal");
22417
22417
  }
22418
22418
  number = toIntegerOrInfinity(number);
22419
- return async function* take() {
22419
+ return async function* take2() {
22420
22420
  var _options$signal7;
22421
22421
  if (options !== null && options !== undefined && (_options$signal7 = options.signal) !== null && _options$signal7 !== undefined && _options$signal7.aborted) {
22422
22422
  throw new AbortError;
@@ -40369,7 +40369,7 @@ var require_util7 = __commonJS((exports, module) => {
40369
40369
  writable: true,
40370
40370
  enumerable: true,
40371
40371
  configurable: true,
40372
- value: function forEach(callbackfn, thisArg = globalThis) {
40372
+ value: function forEach2(callbackfn, thisArg = globalThis) {
40373
40373
  webidl.brandCheck(this, object);
40374
40374
  webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`);
40375
40375
  if (typeof callbackfn !== "function") {
@@ -55307,7 +55307,7 @@ var require_css_value = __commonJS((exports, module) => {
55307
55307
 
55308
55308
  // node_modules/rgb2hex/index.js
55309
55309
  var require_rgb2hex = __commonJS((exports, module) => {
55310
- var rgb2hex = module.exports = function rgb2hex(color) {
55310
+ var rgb2hex = module.exports = function rgb2hex2(color) {
55311
55311
  if (typeof color !== "string") {
55312
55312
  throw new Error("color has to be type of `string`");
55313
55313
  } else if (color.substr(0, 1) === "#") {
@@ -55882,7 +55882,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
55882
55882
  entries: function entries() {
55883
55883
  return properties;
55884
55884
  },
55885
- forEach: function forEach(fn) {
55885
+ forEach: function forEach2(fn) {
55886
55886
  var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
55887
55887
  for (var _i = 0, _properties = properties;_i < _properties.length; _i++) {
55888
55888
  var _properties$_i = _slicedToArray(_properties[_i], 2), key = _properties$_i[0], values = _properties$_i[1];
@@ -55906,8 +55906,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
55906
55906
  },
55907
55907
  values: function values() {
55908
55908
  return properties.map(function(_ref3) {
55909
- var _ref4 = _slicedToArray(_ref3, 2), values = _ref4[1];
55910
- return values;
55909
+ var _ref4 = _slicedToArray(_ref3, 2), values2 = _ref4[1];
55910
+ return values2;
55911
55911
  });
55912
55912
  }
55913
55913
  };
@@ -56238,7 +56238,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
56238
56238
  entries: function entries() {
56239
56239
  return dom;
56240
56240
  },
56241
- forEach: function forEach(fn) {
56241
+ forEach: function forEach2(fn) {
56242
56242
  var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
56243
56243
  for (var _i = 0, _dom = dom;_i < _dom.length; _i++) {
56244
56244
  var _dom$_i = _slicedToArray(_dom[_i], 2), key = _dom$_i[0], values = _dom$_i[1];
@@ -56262,8 +56262,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
56262
56262
  },
56263
56263
  values: function values() {
56264
56264
  return dom.map(function(_ref3) {
56265
- var _ref4 = _slicedToArray(_ref3, 2), values = _ref4[1];
56266
- return values;
56265
+ var _ref4 = _slicedToArray(_ref3, 2), values2 = _ref4[1];
56266
+ return values2;
56267
56267
  });
56268
56268
  }
56269
56269
  };
@@ -61489,10 +61489,10 @@ var require_rolesMap = __commonJS((exports) => {
61489
61489
  if (!t) {
61490
61490
  if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && typeof r.length == "number") {
61491
61491
  t && (r = t);
61492
- var _n = 0, F2 = function F() {};
61492
+ var _n = 0, F2 = function F3() {};
61493
61493
  return { s: F2, n: function n() {
61494
61494
  return _n >= r.length ? { done: true } : { done: false, value: r[_n++] };
61495
- }, e: function e(r2) {
61495
+ }, e: function e2(r2) {
61496
61496
  throw r2;
61497
61497
  }, f: F2 };
61498
61498
  }
@@ -61505,7 +61505,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61505
61505
  }, n: function n() {
61506
61506
  var r2 = t.next();
61507
61507
  return a2 = r2.done, r2;
61508
- }, e: function e(r2) {
61508
+ }, e: function e2(r2) {
61509
61509
  u = true, o = r2;
61510
61510
  }, f: function f() {
61511
61511
  try {
@@ -61576,7 +61576,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61576
61576
  var superClassIter = _step.value;
61577
61577
  var _iterator2 = _createForOfIteratorHelper(superClassIter), _step2;
61578
61578
  try {
61579
- var _loop = function _loop() {
61579
+ var _loop = function _loop2() {
61580
61580
  var superClassName = _step2.value;
61581
61581
  var superClassRoleTuple = roles.filter(function(_ref3) {
61582
61582
  var _ref4 = _slicedToArray(_ref3, 1), name = _ref4[0];
@@ -61611,7 +61611,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61611
61611
  entries: function entries() {
61612
61612
  return roles;
61613
61613
  },
61614
- forEach: function forEach(fn) {
61614
+ forEach: function forEach2(fn) {
61615
61615
  var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
61616
61616
  var _iterator3 = _createForOfIteratorHelper(roles), _step3;
61617
61617
  try {
@@ -61642,8 +61642,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61642
61642
  },
61643
61643
  values: function values() {
61644
61644
  return roles.map(function(_ref7) {
61645
- var _ref8 = _slicedToArray(_ref7, 2), values = _ref8[1];
61646
- return values;
61645
+ var _ref8 = _slicedToArray(_ref7, 2), values2 = _ref8[1];
61646
+ return values2;
61647
61647
  });
61648
61648
  }
61649
61649
  };
@@ -61719,7 +61719,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61719
61719
  role = _rolesMap.default.get(key);
61720
61720
  if (role) {
61721
61721
  concepts = [].concat(role.baseConcepts, role.relatedConcepts);
61722
- _loop = function _loop() {
61722
+ _loop = function _loop2() {
61723
61723
  var relation = concepts[k];
61724
61724
  if (relation.module === "HTML") {
61725
61725
  var concept = relation.concept;
@@ -61764,7 +61764,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61764
61764
  entries: function entries() {
61765
61765
  return elementRoles;
61766
61766
  },
61767
- forEach: function forEach(fn) {
61767
+ forEach: function forEach2(fn) {
61768
61768
  var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
61769
61769
  for (var _i2 = 0, _elementRoles = elementRoles;_i2 < _elementRoles.length; _i2++) {
61770
61770
  var _elementRoles$_i = _slicedToArray(_elementRoles[_i2], 2), _key = _elementRoles$_i[0], values = _elementRoles$_i[1];
@@ -61780,7 +61780,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61780
61780
  has: function has(key2) {
61781
61781
  return !!elementRoleMap.get(key2);
61782
61782
  },
61783
- keys: function keys() {
61783
+ keys: function keys2() {
61784
61784
  return elementRoles.map(function(_ref) {
61785
61785
  var _ref2 = _slicedToArray(_ref, 1), key2 = _ref2[0];
61786
61786
  return key2;
@@ -61788,8 +61788,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61788
61788
  },
61789
61789
  values: function values() {
61790
61790
  return elementRoles.map(function(_ref3) {
61791
- var _ref4 = _slicedToArray(_ref3, 2), values = _ref4[1];
61792
- return values;
61791
+ var _ref4 = _slicedToArray(_ref3, 2), values2 = _ref4[1];
61792
+ return values2;
61793
61793
  });
61794
61794
  }
61795
61795
  };
@@ -61949,7 +61949,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61949
61949
  entries: function entries() {
61950
61950
  return roleElement;
61951
61951
  },
61952
- forEach: function forEach(fn) {
61952
+ forEach: function forEach2(fn) {
61953
61953
  var thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
61954
61954
  for (var _i = 0, _roleElement = roleElement;_i < _roleElement.length; _i++) {
61955
61955
  var _roleElement$_i = _slicedToArray(_roleElement[_i], 2), _key = _roleElement$_i[0], values = _roleElement$_i[1];
@@ -61965,7 +61965,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61965
61965
  has: function has(key2) {
61966
61966
  return !!roleElementMap.get(key2);
61967
61967
  },
61968
- keys: function keys() {
61968
+ keys: function keys2() {
61969
61969
  return roleElement.map(function(_ref) {
61970
61970
  var _ref2 = _slicedToArray(_ref, 1), key2 = _ref2[0];
61971
61971
  return key2;
@@ -61973,8 +61973,8 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
61973
61973
  },
61974
61974
  values: function values() {
61975
61975
  return roleElement.map(function(_ref3) {
61976
- var _ref4 = _slicedToArray(_ref3, 2), values = _ref4[1];
61977
- return values;
61976
+ var _ref4 = _slicedToArray(_ref3, 2), values2 = _ref4[1];
61977
+ return values2;
61978
61978
  });
61979
61979
  }
61980
61980
  };
@@ -66247,7 +66247,7 @@ var init_filters = __esm(() => {
66247
66247
  import_boolbase3 = __toESM(require_boolbase(), 1);
66248
66248
  filters = {
66249
66249
  contains(next, text2, { adapter }) {
66250
- return function contains(elem) {
66250
+ return function contains2(elem) {
66251
66251
  return next(elem) && adapter.getText(elem).includes(text2);
66252
66252
  };
66253
66253
  },
@@ -67381,7 +67381,7 @@ var init_traversing = __esm(() => {
67381
67381
 
67382
67382
  // node_modules/cheerio/dist/esm/parse.js
67383
67383
  function getParse(parser) {
67384
- return function parse(content, options, isDocument2, context) {
67384
+ return function parse5(content, options, isDocument2, context) {
67385
67385
  if (typeof Buffer !== "undefined" && Buffer.isBuffer(content)) {
67386
67386
  content = content.toString();
67387
67387
  }
@@ -75540,7 +75540,7 @@ var init_parser = __esm(() => {
75540
75540
 
75541
75541
  // node_modules/parse5/node_modules/entities/dist/esm/escape.js
75542
75542
  function getEscaper2(regex2, map3) {
75543
- return function escape(data2) {
75543
+ return function escape2(data2) {
75544
75544
  let match;
75545
75545
  let lastIndex = 0;
75546
75546
  let result = "";
@@ -85512,7 +85512,7 @@ var require_util15 = __commonJS((exports, module) => {
85512
85512
  writable: true,
85513
85513
  enumerable: true,
85514
85514
  configurable: true,
85515
- value: function forEach(callbackfn, thisArg = globalThis) {
85515
+ value: function forEach2(callbackfn, thisArg = globalThis) {
85516
85516
  webidl.brandCheck(this, object);
85517
85517
  webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`);
85518
85518
  if (typeof callbackfn !== "function") {
@@ -99816,7 +99816,7 @@ var require_frame2 = __commonJS((exports, module) => {
99816
99816
  var BUFFER_SIZE = 8 * 1024;
99817
99817
  var buffer = null;
99818
99818
  var bufIdx = BUFFER_SIZE;
99819
- var randomFillSync = runtimeFeatures.has("crypto") ? __require("node:crypto").randomFillSync : function randomFillSync(buffer2, _offset, _size) {
99819
+ var randomFillSync = runtimeFeatures.has("crypto") ? __require("node:crypto").randomFillSync : function randomFillSync2(buffer2, _offset, _size) {
99820
99820
  for (let i = 0;i < buffer2.length; ++i) {
99821
99821
  buffer2[i] = Math.random() * 255 | 0;
99822
99822
  }
@@ -102311,8 +102311,11 @@ var init_esm11 = __esm(() => {
102311
102311
  };
102312
102312
  });
102313
102313
 
102314
+ // src/cli.ts
102315
+ import { resolve } from "path";
102316
+
102314
102317
  // src/driver.ts
102315
- import { spawn } from "child_process";
102318
+ import { spawn, execSync } from "child_process";
102316
102319
 
102317
102320
  // node_modules/webdriverio/build/node.js
102318
102321
  var import_jszip = __toESM(require_lib3(), 1);
@@ -120571,17 +120574,78 @@ import { homedir } from "os";
120571
120574
  import { join } from "path";
120572
120575
  var driverProcess = null;
120573
120576
  var browser = null;
120577
+ var exitHandlerRegistered = false;
120574
120578
  var DRIVER_PORT = 4444;
120575
120579
  var DRIVER_HOST = "127.0.0.1";
120580
+ function getDescendantPids(pid) {
120581
+ try {
120582
+ const children2 = execSync(`pgrep -P ${pid} 2>/dev/null`, { encoding: "utf8" }).trim().split(`
120583
+ `).filter(Boolean).map(Number);
120584
+ const descendants = [];
120585
+ for (const child of children2) {
120586
+ descendants.push(child, ...getDescendantPids(child));
120587
+ }
120588
+ return descendants;
120589
+ } catch {
120590
+ return [];
120591
+ }
120592
+ }
120593
+ function killProcessTree(pid, signal = "SIGKILL") {
120594
+ const descendants = getDescendantPids(pid);
120595
+ for (const child of descendants.reverse()) {
120596
+ try {
120597
+ process.kill(child, signal);
120598
+ } catch {}
120599
+ }
120600
+ try {
120601
+ process.kill(pid, signal);
120602
+ } catch {}
120603
+ }
120604
+ function forceKillDriver() {
120605
+ if (driverProcess?.pid) {
120606
+ killProcessTree(driverProcess.pid);
120607
+ driverProcess = null;
120608
+ }
120609
+ }
120610
+ function killStaleDriver() {
120611
+ let killed = false;
120612
+ for (const port of [DRIVER_PORT, DRIVER_PORT + 1]) {
120613
+ try {
120614
+ const pids = execSync(`lsof -ti:${port} 2>/dev/null`, { encoding: "utf8" }).trim();
120615
+ if (pids) {
120616
+ for (const pidStr of pids.split(`
120617
+ `)) {
120618
+ const pid = parseInt(pidStr);
120619
+ if (pid) {
120620
+ killProcessTree(pid);
120621
+ killed = true;
120622
+ }
120623
+ }
120624
+ }
120625
+ } catch {}
120626
+ }
120627
+ if (killed) {
120628
+ execSync("sleep 0.5");
120629
+ }
120630
+ }
120576
120631
  async function startDriver() {
120577
120632
  if (driverProcess) {
120578
120633
  return;
120579
120634
  }
120635
+ killStaleDriver();
120580
120636
  const tauriDriverPath = join(homedir(), ".cargo", "bin", "tauri-driver");
120581
120637
  return new Promise((resolve, reject) => {
120582
- driverProcess = spawn(tauriDriverPath, [], {
120583
- stdio: ["ignore", "pipe", "pipe"]
120638
+ driverProcess = spawn("setsid", [
120639
+ "sh",
120640
+ "-c",
120641
+ `"${tauriDriverPath}" & PID=$!; trap "kill 0 2>/dev/null" EXIT; read; exit`
120642
+ ], {
120643
+ stdio: ["pipe", "pipe", "pipe"]
120584
120644
  });
120645
+ if (!exitHandlerRegistered) {
120646
+ exitHandlerRegistered = true;
120647
+ process.on("exit", forceKillDriver);
120648
+ }
120585
120649
  driverProcess.on("error", (err) => {
120586
120650
  reject(new Error(`Failed to start tauri-driver: ${err.message}`));
120587
120651
  });
@@ -120602,8 +120666,8 @@ async function startDriver() {
120602
120666
  });
120603
120667
  }
120604
120668
  function stopDriver() {
120605
- if (driverProcess) {
120606
- driverProcess.kill();
120669
+ if (driverProcess?.pid) {
120670
+ killProcessTree(driverProcess.pid);
120607
120671
  driverProcess = null;
120608
120672
  }
120609
120673
  }
@@ -120653,22 +120717,83 @@ async function disconnect() {
120653
120717
  import { writeFile } from "fs/promises";
120654
120718
 
120655
120719
  // src/driver.ts
120656
- import { spawn as spawn2 } from "child_process";
120720
+ import { spawn as spawn2, execSync as execSync2 } from "child_process";
120657
120721
  import { homedir as homedir2 } from "os";
120658
120722
  import { join as join2 } from "path";
120659
120723
  var driverProcess2 = null;
120660
120724
  var browser2 = null;
120725
+ var exitHandlerRegistered2 = false;
120661
120726
  var DRIVER_PORT2 = 4444;
120662
120727
  var DRIVER_HOST2 = "127.0.0.1";
120728
+ function getDescendantPids2(pid) {
120729
+ try {
120730
+ const children2 = execSync2(`pgrep -P ${pid} 2>/dev/null`, { encoding: "utf8" }).trim().split(`
120731
+ `).filter(Boolean).map(Number);
120732
+ const descendants = [];
120733
+ for (const child of children2) {
120734
+ descendants.push(child, ...getDescendantPids2(child));
120735
+ }
120736
+ return descendants;
120737
+ } catch {
120738
+ return [];
120739
+ }
120740
+ }
120741
+ function killProcessTree2(pid, signal = "SIGKILL") {
120742
+ const descendants = getDescendantPids2(pid);
120743
+ for (const child of descendants.reverse()) {
120744
+ try {
120745
+ process.kill(child, signal);
120746
+ } catch {}
120747
+ }
120748
+ try {
120749
+ process.kill(pid, signal);
120750
+ } catch {}
120751
+ }
120752
+ function forceKillDriver2() {
120753
+ if (driverProcess2?.pid) {
120754
+ killProcessTree2(driverProcess2.pid);
120755
+ driverProcess2 = null;
120756
+ }
120757
+ }
120758
+ function killStaleDriver2() {
120759
+ let killed = false;
120760
+ for (const port of [DRIVER_PORT2, DRIVER_PORT2 + 1]) {
120761
+ try {
120762
+ const pids = execSync2(`lsof -ti:${port} 2>/dev/null`, { encoding: "utf8" }).trim();
120763
+ if (pids) {
120764
+ for (const pidStr of pids.split(`
120765
+ `)) {
120766
+ const pid = parseInt(pidStr);
120767
+ if (pid) {
120768
+ killProcessTree2(pid);
120769
+ killed = true;
120770
+ }
120771
+ }
120772
+ }
120773
+ } catch {}
120774
+ }
120775
+ if (killed) {
120776
+ execSync2("sleep 0.5");
120777
+ }
120778
+ }
120663
120779
  async function startDriver2() {
120664
120780
  if (driverProcess2) {
120665
120781
  return;
120666
120782
  }
120783
+ killStaleDriver2();
120667
120784
  const tauriDriverPath = join2(homedir2(), ".cargo", "bin", "tauri-driver");
120668
120785
  return new Promise((resolve, reject) => {
120669
- driverProcess2 = spawn2(tauriDriverPath, [], {
120670
- stdio: ["ignore", "pipe", "pipe"]
120786
+ driverProcess2 = spawn2("setsid", [
120787
+ "sh",
120788
+ "-c",
120789
+ `"${tauriDriverPath}" & PID=$!; trap "kill 0 2>/dev/null" EXIT; read; exit`
120790
+ ], {
120791
+ stdio: ["pipe", "pipe", "pipe"]
120671
120792
  });
120793
+ if (!exitHandlerRegistered2) {
120794
+ exitHandlerRegistered2 = true;
120795
+ process.on("exit", forceKillDriver2);
120796
+ }
120672
120797
  driverProcess2.on("error", (err) => {
120673
120798
  reject(new Error(`Failed to start tauri-driver: ${err.message}`));
120674
120799
  });
@@ -120688,12 +120813,6 @@ async function startDriver2() {
120688
120813
  setTimeout(() => resolve(), 1000);
120689
120814
  });
120690
120815
  }
120691
- function stopDriver2() {
120692
- if (driverProcess2) {
120693
- driverProcess2.kill();
120694
- driverProcess2 = null;
120695
- }
120696
- }
120697
120816
  async function waitForPageLoad2(browser3, timeout = 1e4) {
120698
120817
  const start = Date.now();
120699
120818
  while (Date.now() - start < timeout) {
@@ -120731,13 +120850,6 @@ async function connect2(options) {
120731
120850
  function getBrowser() {
120732
120851
  return browser2;
120733
120852
  }
120734
- async function disconnect2() {
120735
- if (browser2) {
120736
- await browser2.deleteSession();
120737
- browser2 = null;
120738
- }
120739
- stopDriver2();
120740
- }
120741
120853
  function requireBrowser() {
120742
120854
  if (!browser2) {
120743
120855
  throw new Error("Not connected. Run 'tauri-test-cli connect' first.");
@@ -121158,6 +121270,7 @@ async function evaluate(script) {
121158
121270
 
121159
121271
  // src/server.ts
121160
121272
  import { createServer } from "http";
121273
+ import { readFileSync } from "fs";
121161
121274
 
121162
121275
  // src/commands/screenshot.ts
121163
121276
  import { writeFile as writeFile3 } from "fs/promises";
@@ -121675,12 +121788,10 @@ async function shutdown() {
121675
121788
  return;
121676
121789
  isShuttingDown = true;
121677
121790
  console.error("Shutting down...");
121791
+ forceKillDriver2();
121678
121792
  if (serverInstance) {
121679
121793
  serverInstance.close();
121680
121794
  }
121681
- try {
121682
- await disconnect2();
121683
- } catch {}
121684
121795
  process.exit(0);
121685
121796
  }
121686
121797
  async function injectKeepAlive() {
@@ -121714,6 +121825,36 @@ async function startServer(options) {
121714
121825
  const { port, appPath, waitTimeout, autoWait } = options;
121715
121826
  process.on("SIGINT", shutdown);
121716
121827
  process.on("SIGTERM", shutdown);
121828
+ const getAncestorPids = () => {
121829
+ const pids = [];
121830
+ let pid = process.pid;
121831
+ while (pid > 1) {
121832
+ try {
121833
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
121834
+ const ppid = parseInt(stat.split(") ")[1].split(" ")[1]);
121835
+ if (ppid <= 1)
121836
+ break;
121837
+ pids.push(ppid);
121838
+ pid = ppid;
121839
+ } catch {
121840
+ break;
121841
+ }
121842
+ }
121843
+ return pids;
121844
+ };
121845
+ const ancestorPids = getAncestorPids();
121846
+ if (ancestorPids.length > 0) {
121847
+ setInterval(() => {
121848
+ for (const pid of ancestorPids) {
121849
+ try {
121850
+ process.kill(pid, 0);
121851
+ } catch {
121852
+ shutdown();
121853
+ return;
121854
+ }
121855
+ }
121856
+ }, 500);
121857
+ }
121717
121858
  console.error(`Launching app and waiting for load (timeout: ${waitTimeout}ms)...`);
121718
121859
  await connect2({ appPath, waitTimeout });
121719
121860
  console.error("App loaded successfully.");
@@ -121740,7 +121881,7 @@ async function startServer(options) {
121740
121881
  }
121741
121882
 
121742
121883
  // src/checks.ts
121743
- import { execSync } from "child_process";
121884
+ import { execSync as execSync3 } from "child_process";
121744
121885
  import os4 from "os";
121745
121886
  var reset = "\x1B[0m";
121746
121887
  var bold = "\x1B[1m";
@@ -121751,7 +121892,7 @@ var dim = "\x1B[2m";
121751
121892
  function commandExists(cmd) {
121752
121893
  try {
121753
121894
  const checkCmd = os4.platform() === "win32" ? `where ${cmd} 2>nul` : `which ${cmd} 2>/dev/null`;
121754
- execSync(checkCmd, { stdio: "ignore" });
121895
+ execSync3(checkCmd, { stdio: "ignore" });
121755
121896
  return true;
121756
121897
  } catch {
121757
121898
  return false;
@@ -121759,7 +121900,7 @@ function commandExists(cmd) {
121759
121900
  }
121760
121901
  function pkgConfigExists(pkg) {
121761
121902
  try {
121762
- execSync(`pkg-config --modversion ${pkg}`, { stdio: "ignore" });
121903
+ execSync3(`pkg-config --modversion ${pkg}`, { stdio: "ignore" });
121763
121904
  return true;
121764
121905
  } catch {
121765
121906
  return false;
@@ -121848,7 +121989,7 @@ function printDependencyStatus() {
121848
121989
  }
121849
121990
 
121850
121991
  // src/commands/utils.ts
121851
- import { execSync as execSync2, spawn as spawn3 } from "child_process";
121992
+ import { execSync as execSync4, spawn as spawn3 } from "child_process";
121852
121993
  import os5 from "os";
121853
121994
  var reset2 = "\x1B[0m";
121854
121995
  var bold2 = "\x1B[1m";
@@ -121862,7 +122003,7 @@ async function setup() {
121862
122003
  console.log();
121863
122004
  try {
121864
122005
  try {
121865
- execSync2("cargo --version", { stdio: "ignore" });
122006
+ execSync4("cargo --version", { stdio: "ignore" });
121866
122007
  } catch {
121867
122008
  return {
121868
122009
  success: false,
@@ -121925,7 +122066,7 @@ async function cleanup() {
121925
122066
  if (platform === "win32") {
121926
122067
  for (const pattern of processPatterns) {
121927
122068
  try {
121928
- execSync2(`taskkill /F /IM ${pattern}.exe 2>nul`, { stdio: "ignore" });
122069
+ execSync4(`taskkill /F /IM ${pattern}.exe 2>nul`, { stdio: "ignore" });
121929
122070
  killed.push(pattern);
121930
122071
  console.log(` ${green2}✓${reset2} Killed ${pattern}`);
121931
122072
  } catch {
@@ -121935,7 +122076,7 @@ async function cleanup() {
121935
122076
  } else {
121936
122077
  for (const pattern of processPatterns) {
121937
122078
  try {
121938
- execSync2(`pkill -f "${pattern}"`, { stdio: "ignore" });
122079
+ execSync4(`pkill -f "${pattern}"`, { stdio: "ignore" });
121939
122080
  killed.push(pattern);
121940
122081
  console.log(` ${green2}✓${reset2} Killed ${pattern}`);
121941
122082
  } catch {
@@ -121956,7 +122097,7 @@ function checkXvfb() {
121956
122097
  return false;
121957
122098
  }
121958
122099
  try {
121959
- execSync2("which Xvfb", { stdio: "ignore" });
122100
+ execSync4("which Xvfb", { stdio: "ignore" });
121960
122101
  return true;
121961
122102
  } catch {
121962
122103
  return false;
@@ -121967,7 +122108,7 @@ function findAvailableDisplay() {
121967
122108
  const lockFile = `/tmp/.X${display}-lock`;
121968
122109
  const socketFile = `/tmp/.X11-unix/X${display}`;
121969
122110
  try {
121970
- execSync2(`test -e ${lockFile} || test -e ${socketFile}`, { stdio: "ignore" });
122111
+ execSync4(`test -e ${lockFile} || test -e ${socketFile}`, { stdio: "ignore" });
121971
122112
  } catch {
121972
122113
  return display;
121973
122114
  }
@@ -121980,7 +122121,7 @@ async function waitForDisplay(display, timeoutMs = 1e4) {
121980
122121
  const pollInterval = 100;
121981
122122
  while (Date.now() - startTime < timeoutMs) {
121982
122123
  try {
121983
- execSync2(`DISPLAY=${displayStr} xdpyinfo`, { stdio: "ignore", timeout: 1000 });
122124
+ execSync4(`DISPLAY=${displayStr} xdpyinfo`, { stdio: "ignore", timeout: 1000 });
121984
122125
  return true;
121985
122126
  } catch {
121986
122127
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
@@ -122021,6 +122162,8 @@ async function startXvfb() {
122021
122162
  console.error(`Xvfb ready on display ${displayStr}`);
122022
122163
  xvfbDisplay = display;
122023
122164
  process.env.DISPLAY = displayStr;
122165
+ delete process.env.WAYLAND_DISPLAY;
122166
+ process.env.GDK_BACKEND = "x11";
122024
122167
  return display;
122025
122168
  }
122026
122169
  function stopXvfb() {
@@ -122268,7 +122411,7 @@ async function executeCommand2(cmd, globalAutoWait) {
122268
122411
  }
122269
122412
  return await evaluate(cmd.script);
122270
122413
  case "sleep":
122271
- await new Promise((resolve) => setTimeout(resolve, cmd.ms ?? 1000));
122414
+ await new Promise((resolve2) => setTimeout(resolve2, cmd.ms ?? 1000));
122272
122415
  return { slept: cmd.ms ?? 1000 };
122273
122416
  default:
122274
122417
  throw new Error(`Unknown command: ${cmd.cmd}`);
@@ -122340,7 +122483,7 @@ async function main() {
122340
122483
  process.exit(1);
122341
122484
  }
122342
122485
  }
122343
- const appPath = options.app;
122486
+ const appPath = options.app ? resolve(options.app) : undefined;
122344
122487
  const jsonOutput = !!options.json;
122345
122488
  const port = options.port ? parseInt(options.port) : 9222;
122346
122489
  const clientModeCommands = ["screenshot", "snapshot", "click", "type", "wait", "eval"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tauri-test-cli",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "CLI for testing Tauri applications with screenshot capture, DOM inspection, and user interaction simulation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -81,29 +81,34 @@ MINOR_VERSION="${major}.$((minor + 1)).0"
81
81
  MAJOR_VERSION="$((major + 1)).0.0"
82
82
 
83
83
  echo -e "${CYAN}Select version bump type:${NC}"
84
- echo " 1) patch (${CURRENT_VERSION} -> ${PATCH_VERSION})"
85
- echo " 2) minor (${CURRENT_VERSION} -> ${MINOR_VERSION})"
86
- echo " 3) major (${CURRENT_VERSION} -> ${MAJOR_VERSION})"
87
- echo " 4) cancel"
84
+ echo " 1) none (keep ${CURRENT_VERSION})"
85
+ echo " 2) patch (${CURRENT_VERSION} -> ${PATCH_VERSION})"
86
+ echo " 3) minor (${CURRENT_VERSION} -> ${MINOR_VERSION})"
87
+ echo " 4) major (${CURRENT_VERSION} -> ${MAJOR_VERSION})"
88
+ echo " 5) cancel"
88
89
  echo ""
89
90
 
90
- read -p "Enter choice [1-4]: " -n 1 -r CHOICE
91
+ read -p "Enter choice [1-5]: " -n 1 -r CHOICE
91
92
  echo ""
92
93
 
93
94
  case $CHOICE in
94
95
  1)
96
+ BUMP_TYPE=""
97
+ NEW_VERSION="$CURRENT_VERSION"
98
+ ;;
99
+ 2)
95
100
  BUMP_TYPE="patch"
96
101
  NEW_VERSION="$PATCH_VERSION"
97
102
  ;;
98
- 2)
103
+ 3)
99
104
  BUMP_TYPE="minor"
100
105
  NEW_VERSION="$MINOR_VERSION"
101
106
  ;;
102
- 3)
107
+ 4)
103
108
  BUMP_TYPE="major"
104
109
  NEW_VERSION="$MAJOR_VERSION"
105
110
  ;;
106
- 4|*)
111
+ 5|*)
107
112
  echo -e "${YELLOW}Publish cancelled.${NC}"
108
113
  exit 0
109
114
  ;;
@@ -115,33 +120,39 @@ echo ""
115
120
  # STEP 3: Bump version
116
121
  # ============================================================================
117
122
 
118
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
119
- echo -e "${GREEN}▶ Step 3: Bumping version to ${NEW_VERSION}...${NC}"
120
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
121
- echo ""
123
+ if [[ -n "$BUMP_TYPE" ]]; then
124
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
125
+ echo -e "${GREEN}▶ Step 3: Bumping version to ${NEW_VERSION}...${NC}"
126
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
127
+ echo ""
122
128
 
123
- ./scripts/bump-version.sh "$BUMP_TYPE"
129
+ ./scripts/bump-version.sh "$BUMP_TYPE"
124
130
 
125
- # ============================================================================
126
- # STEP 4: Commit, tag, and push to GitHub
127
- # ============================================================================
131
+ # ============================================================================
132
+ # STEP 4: Commit, tag, and push to GitHub
133
+ # ============================================================================
128
134
 
129
- echo ""
130
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
131
- echo -e "${GREEN}▶ Step 4: Pushing to GitHub...${NC}"
132
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
133
- echo ""
135
+ echo ""
136
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
137
+ echo -e "${GREEN}▶ Step 4: Pushing to GitHub...${NC}"
138
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
139
+ echo ""
134
140
 
135
- echo -e "${BLUE}Committing changes...${NC}"
136
- git add pixi.toml package.json .claude-plugin/plugin.json
137
- git commit -m "Bump version to $NEW_VERSION"
141
+ echo -e "${BLUE}Committing changes...${NC}"
142
+ git add pixi.toml package.json .claude-plugin/plugin.json
143
+ git commit -m "Bump version to $NEW_VERSION"
138
144
 
139
- echo -e "${BLUE}Creating git tag v${NEW_VERSION}...${NC}"
140
- git tag "v${NEW_VERSION}"
145
+ echo -e "${BLUE}Creating git tag v${NEW_VERSION}...${NC}"
146
+ git tag "v${NEW_VERSION}"
141
147
 
142
- echo -e "${BLUE}Pushing to remote...${NC}"
143
- git push
144
- git push --tags
148
+ echo -e "${BLUE}Pushing to remote...${NC}"
149
+ git push
150
+ git push --tags
151
+ else
152
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
153
+ echo -e "${GREEN}▶ Skipping version bump, keeping ${CURRENT_VERSION}${NC}"
154
+ echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
155
+ fi
145
156
 
146
157
  echo -e "${GREEN}✓ Pushed to GitHub${NC}"
147
158