@uipath/test-manager-tool 1.203.0-preview.233 → 1.203.0-preview.237

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/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  Command,
4
4
  metadata,
5
5
  registerCommands
6
- } from "./tool-0nx90twz.js";
6
+ } from "./tool-a78ywp6r.js";
7
7
  import"./tool-1de529jm.js";
8
8
 
9
9
  // src/index.ts
@@ -11180,7 +11180,7 @@ var package_default = {
11180
11180
  name: "@uipath/test-manager-tool",
11181
11181
  author: "UiPath",
11182
11182
  license: "SEE LICENSE IN LICENSE.txt",
11183
- version: "1.203.0-preview.233",
11183
+ version: "1.203.0-preview.237",
11184
11184
  description: "Manage test cases, test sets, executions, and results.",
11185
11185
  private: false,
11186
11186
  repository: {
@@ -13579,6 +13579,7 @@ class SuccessOutput {
13579
13579
  Data;
13580
13580
  Pagination;
13581
13581
  Instructions;
13582
+ Warning;
13582
13583
  Log;
13583
13584
  constructor(code, data) {
13584
13585
  this.Code = code;
@@ -14163,7 +14164,165 @@ class FilterImplicitLimitError extends Error {
14163
14164
  this.instructions = "Pass --limit <n> to choose how many records the filter applies to. " + "To filter over all records, pass the command's maximum accepted --limit (see the option's description in --help).";
14164
14165
  }
14165
14166
  }
14166
- function applyFilter(data, filter) {
14167
+ function countRecords(data) {
14168
+ if (Array.isArray(data))
14169
+ return data.length;
14170
+ return data == null ? 0 : 1;
14171
+ }
14172
+ function availableFields(data) {
14173
+ const records = Array.isArray(data) ? data : [data];
14174
+ const keys = new Set;
14175
+ for (const record of records) {
14176
+ if (record && typeof record === "object" && !Array.isArray(record)) {
14177
+ for (const key of Object.keys(record))
14178
+ keys.add(key);
14179
+ }
14180
+ }
14181
+ return [...keys];
14182
+ }
14183
+ function decodeQuotedIdentifier(whole, inner) {
14184
+ const [error, decoded] = catchError(() => JSON.parse(whole));
14185
+ if (!error && typeof decoded === "string")
14186
+ return decoded;
14187
+ return inner.replace(/\\(.)/g, "$1");
14188
+ }
14189
+ function referencedFields(filter) {
14190
+ const top = new Set;
14191
+ const nested = new Set;
14192
+ const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
14193
+ const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
14194
+ const quoted = [];
14195
+ const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
14196
+ const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
14197
+ if (!isAlias) {
14198
+ quoted.push({
14199
+ name: decodeQuotedIdentifier(whole, name),
14200
+ index,
14201
+ tail: isPathTail(withoutValueLiterals, index)
14202
+ });
14203
+ }
14204
+ return `"${" ".repeat(whole.length - 2)}"`;
14205
+ });
14206
+ const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
14207
+ const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
14208
+ const place = (name, index, tail) => {
14209
+ if (tail || index >= rootEnd)
14210
+ nested.add(name);
14211
+ else
14212
+ top.add(name);
14213
+ };
14214
+ for (const entry of quoted)
14215
+ place(entry.name, entry.index, entry.tail);
14216
+ const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
14217
+ const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
14218
+ for (const match of identifiers) {
14219
+ const [, name, trailing] = match;
14220
+ if (trailing || reserved.has(name))
14221
+ continue;
14222
+ place(name, match.index, isPathTail(withoutLiterals, match.index));
14223
+ }
14224
+ return {
14225
+ top: [...top],
14226
+ nested: [...nested].filter((name) => !top.has(name)),
14227
+ hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
14228
+ };
14229
+ }
14230
+ function appearsBelowTopLevel(data, name) {
14231
+ let budget = 2000;
14232
+ const visit = (value, depth) => {
14233
+ if (budget-- <= 0 || depth > 4)
14234
+ return false;
14235
+ if (value === null || typeof value !== "object")
14236
+ return false;
14237
+ if (Array.isArray(value))
14238
+ return value.some((entry) => visit(entry, depth));
14239
+ const record = value;
14240
+ if (depth > 0 && Object.hasOwn(record, name))
14241
+ return true;
14242
+ return Object.values(record).some((entry) => visit(entry, depth + 1));
14243
+ };
14244
+ return visit(data, 0);
14245
+ }
14246
+ function alwaysNullKeys(records) {
14247
+ const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
14248
+ if (objects.length === 0 || objects.length !== records.length)
14249
+ return [];
14250
+ const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
14251
+ if (keys.length === 0)
14252
+ return [];
14253
+ const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
14254
+ return nullKeys.length === keys.length ? nullKeys : [];
14255
+ }
14256
+ function carriesOnlyNulls(value) {
14257
+ if (value === null)
14258
+ return true;
14259
+ if (Array.isArray(value)) {
14260
+ return value.length > 0 && value.every(carriesOnlyNulls);
14261
+ }
14262
+ if (typeof value === "object" && value !== undefined) {
14263
+ const values = Object.values(value);
14264
+ return values.length > 0 && values.every(carriesOnlyNulls);
14265
+ }
14266
+ return false;
14267
+ }
14268
+ function nameList(names, cap2 = 12) {
14269
+ const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
14270
+ const rest = names.length - shown.length;
14271
+ return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
14272
+ }
14273
+ function buildFilterWarning(filter, data, outcome) {
14274
+ const present = availableFields(data);
14275
+ const refs = referencedFields(filter);
14276
+ const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
14277
+ const unchecked = refs.nested.filter((name) => !present.includes(name));
14278
+ const count = countRecords(data);
14279
+ const scope = `${count} record(s)`;
14280
+ const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
14281
+ const soundness = unchecked.length > 0 ? `${nameList(unchecked)} ${unchecked.length === 1 ? "reads" : "read"} below the top level, so ${unchecked.length === 1 ? "it was" : "they were"} not checked against the record keys` : refs.top.length > 0 ? "every field it names exists" : "";
14282
+ const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
14283
+ let detail;
14284
+ let lede;
14285
+ if (outcome.kind === "null-elements") {
14286
+ lede = "returned only null values";
14287
+ const projected = `all ${outcome.count} of the elements it projected are null`;
14288
+ if (unknown.length > 0) {
14289
+ detail = `${projected}, because ${isNotAField(unknown)}`;
14290
+ } else if (unchecked.length > 0) {
14291
+ detail = withSoundness(projected);
14292
+ } else {
14293
+ detail = `${projected}, and every field it names exists — a multi-select list ` + `(\`[A, B]\`) reads each entry against \`Data\` itself, so on a list ` + `result use \`[].[A, B]\` or \`[].{a: A, b: B}\` to read the records`;
14294
+ }
14295
+ } else if (outcome.kind === "null-rows") {
14296
+ lede = "returned only null values";
14297
+ const projected = `every value it projected is null on all ${outcome.count} row(s)`;
14298
+ detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
14299
+ } else if (outcome.kind === "null-values") {
14300
+ lede = "returned only null values";
14301
+ const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
14302
+ const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
14303
+ if (sameSet) {
14304
+ detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
14305
+ } else if (unknown.length > 0) {
14306
+ detail = `${projected}, because ${isNotAField(unknown)}`;
14307
+ } else {
14308
+ detail = withSoundness(`${projected} on all ${scope}`);
14309
+ }
14310
+ } else {
14311
+ lede = "returned nothing";
14312
+ if (unknown.length > 0) {
14313
+ detail = isNotAField(unknown);
14314
+ } else {
14315
+ const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
14316
+ detail = withSoundness(`${selection} — it read ${scope}`);
14317
+ }
14318
+ }
14319
+ const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
14320
+ return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
14321
+ }
14322
+ function appendWarning(existing, note) {
14323
+ return existing ? `${existing} ${note}` : note;
14324
+ }
14325
+ function applyFilter(data, filter, onWarning) {
14167
14326
  const codec = requireJmespath();
14168
14327
  let result;
14169
14328
  try {
@@ -14171,9 +14330,34 @@ function applyFilter(data, filter) {
14171
14330
  } catch (err) {
14172
14331
  throw new FilterEvaluationError(filter, err);
14173
14332
  }
14174
- if (result == null)
14333
+ const inputCount = countRecords(data);
14334
+ const warn = (outcome) => {
14335
+ if (inputCount === 0)
14336
+ return;
14337
+ const note = buildFilterWarning(filter, data, outcome);
14338
+ getOutputSink().writeErr(`[WARN] ${note}
14339
+ `);
14340
+ onWarning?.(note);
14341
+ };
14342
+ const warnIfAllNull = (records) => {
14343
+ const keys = alwaysNullKeys(records);
14344
+ if (keys.length > 0)
14345
+ warn({ kind: "null-values", keys });
14346
+ };
14347
+ if (result == null) {
14348
+ warn({ kind: "empty" });
14175
14349
  return [];
14350
+ }
14176
14351
  if (Array.isArray(result)) {
14352
+ if (result.length === 0) {
14353
+ warn({ kind: "empty" });
14354
+ } else if (result.every((entry) => entry === null)) {
14355
+ warn({ kind: "null-elements", count: result.length });
14356
+ } else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
14357
+ warn({ kind: "null-rows", count: result.length });
14358
+ } else {
14359
+ warnIfAllNull(result);
14360
+ }
14177
14361
  if (result.length > 0 && typeof result[0] !== "object") {
14178
14362
  const fieldMatch = filter.match(/\.(\w+)$/);
14179
14363
  const key = fieldMatch ? fieldMatch[1] : "Value";
@@ -14181,10 +14365,30 @@ function applyFilter(data, filter) {
14181
14365
  }
14182
14366
  return result;
14183
14367
  }
14184
- if (typeof result === "object")
14368
+ if (typeof result === "object") {
14369
+ warnIfAllNull([result]);
14185
14370
  return result;
14371
+ }
14186
14372
  return { Value: result };
14187
14373
  }
14374
+ function filterFailureData(envelope) {
14375
+ const filter = getOutputFilter();
14376
+ const data = envelope.Data;
14377
+ if (!filter || data == null)
14378
+ return;
14379
+ let note;
14380
+ const [filterError, filtered] = catchError(() => applyFilter(data, filter, (n) => {
14381
+ note = n;
14382
+ }));
14383
+ if (filterError) {
14384
+ envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
14385
+ return;
14386
+ }
14387
+ envelope.Data = filtered;
14388
+ if (note) {
14389
+ envelope.Warning = appendWarning(envelope.Warning, note);
14390
+ }
14391
+ }
14188
14392
  function defaultErrorCodeForResult(result) {
14189
14393
  switch (result) {
14190
14394
  case RESULTS.AuthenticationError:
@@ -14267,8 +14471,14 @@ var OutputFormatter;
14267
14471
  }
14268
14472
  const filter = getOutputFilter();
14269
14473
  if (filter) {
14270
- const filtered = applyFilter(data.Data, filter);
14474
+ let note;
14475
+ const filtered = applyFilter(data.Data, filter, (n) => {
14476
+ note = n;
14477
+ });
14271
14478
  data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
14479
+ if (note) {
14480
+ data.Warning = appendWarning(data.Warning, note);
14481
+ }
14272
14482
  }
14273
14483
  logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
14274
14484
  }
@@ -14296,6 +14506,7 @@ var OutputFormatter;
14296
14506
  delete envelope.TelemetryErrorClass;
14297
14507
  delete envelope.TelemetryTerminalOutcome;
14298
14508
  delete envelope.TelemetryTerminalSignal;
14509
+ filterFailureData(envelope);
14299
14510
  if (!suppressTelemetry) {
14300
14511
  telemetry.trackEvent(CommonTelemetryEvents.Error, {
14301
14512
  result: data.Result,
@@ -14344,13 +14555,20 @@ var OutputFormatter;
14344
14555
  OutputFormatter.log = log;
14345
14556
  function formatToString(data) {
14346
14557
  const filter = getOutputFilter();
14558
+ const envelope = data;
14347
14559
  if ("Data" in data && data.Data != null) {
14348
14560
  data.Data = normalizeDataKeys(data.Data);
14349
14561
  if (filter) {
14350
- data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
14562
+ let note;
14563
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
14564
+ note = n;
14565
+ }));
14566
+ if (note) {
14567
+ envelope.Warning = appendWarning(envelope.Warning, note);
14568
+ }
14351
14569
  }
14352
14570
  }
14353
- const output = normalizeOutputKeys(data);
14571
+ const output = normalizeOutputKeys(envelope);
14354
14572
  const lines = [];
14355
14573
  const sink = getOutputSink();
14356
14574
  printOutput(output, getOutputFormat(), (msg) => {
@@ -39650,4 +39868,4 @@ var registerCommands = async (program2) => {
39650
39868
 
39651
39869
  export { Command, metadata, registerCommands };
39652
39870
 
39653
- //# debugId=E8376B84BB0F228064756E2164756E21
39871
+ //# debugId=857CE73A7D674FC564756E2164756E21
package/dist/tool.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  metadata,
3
3
  registerCommands
4
- } from "./tool-0nx90twz.js";
4
+ } from "./tool-a78ywp6r.js";
5
5
  import"./tool-1de529jm.js";
6
6
  export {
7
7
  metadata,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@uipath/test-manager-tool",
3
3
  "author": "UiPath",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
- "version": "1.203.0-preview.233",
5
+ "version": "1.203.0-preview.237",
6
6
  "description": "Manage test cases, test sets, executions, and results.",
7
7
  "private": false,
8
8
  "repository": {
@@ -27,5 +27,5 @@
27
27
  "files": [
28
28
  "dist"
29
29
  ],
30
- "gitHead": "641614a6f9817662baaf51dabdebbfa2a9334b1b"
30
+ "gitHead": "4ad3e17a66f2c7fb7fe1f0e3e04a5b6175a0a9a3"
31
31
  }