@uipath/test-manager-tool 1.202.1-preview.220 → 1.202.1-preview.239

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-gy4x3aqe.js";
6
+ } from "./tool-jtbgb7nj.js";
7
7
  import"./tool-1de529jm.js";
8
8
 
9
9
  // src/index.ts
@@ -11179,7 +11179,7 @@ var require_lib3 = __commonJS(function(exports, module) {
11179
11179
  var package_default = {
11180
11180
  name: "@uipath/test-manager-tool",
11181
11181
  license: "SEE LICENSE IN LICENSE.txt",
11182
- version: "1.202.1-preview.220",
11182
+ version: "1.202.1-preview.239",
11183
11183
  description: "Manage test cases, test sets, executions, and results.",
11184
11184
  private: false,
11185
11185
  repository: {
@@ -13557,6 +13557,7 @@ class SuccessOutput {
13557
13557
  Data;
13558
13558
  Pagination;
13559
13559
  Instructions;
13560
+ Warning;
13560
13561
  Log;
13561
13562
  constructor(code, data) {
13562
13563
  this.Code = code;
@@ -13916,7 +13917,165 @@ class FilterImplicitLimitError extends Error {
13916
13917
  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).";
13917
13918
  }
13918
13919
  }
13919
- function applyFilter(data, filter) {
13920
+ function countRecords(data) {
13921
+ if (Array.isArray(data))
13922
+ return data.length;
13923
+ return data == null ? 0 : 1;
13924
+ }
13925
+ function availableFields(data) {
13926
+ const records = Array.isArray(data) ? data : [data];
13927
+ const keys = new Set;
13928
+ for (const record of records) {
13929
+ if (record && typeof record === "object" && !Array.isArray(record)) {
13930
+ for (const key of Object.keys(record))
13931
+ keys.add(key);
13932
+ }
13933
+ }
13934
+ return [...keys];
13935
+ }
13936
+ function decodeQuotedIdentifier(whole, inner) {
13937
+ const [error, decoded] = catchError(() => JSON.parse(whole));
13938
+ if (!error && typeof decoded === "string")
13939
+ return decoded;
13940
+ return inner.replace(/\\(.)/g, "$1");
13941
+ }
13942
+ function referencedFields(filter) {
13943
+ const top = new Set;
13944
+ const nested = new Set;
13945
+ const withoutValueLiterals = filter.replace(/'(?:\\.|[^'\\])*'/g, " ").replace(/`(?:\\.|[^`\\])*`/g, " ");
13946
+ const isPathTail = (text, index) => text[index - 1] === "." && /[A-Za-z0-9_"]/.test(text[index - 2] ?? "");
13947
+ const quoted = [];
13948
+ const withoutLiterals = withoutValueLiterals.replace(/"((?:\\.|[^"\\])*)"/g, (whole, name, index) => {
13949
+ const isAlias = /^\s*:/.test(withoutValueLiterals.slice(index + whole.length));
13950
+ if (!isAlias) {
13951
+ quoted.push({
13952
+ name: decodeQuotedIdentifier(whole, name),
13953
+ index,
13954
+ tail: isPathTail(withoutValueLiterals, index)
13955
+ });
13956
+ }
13957
+ return `"${" ".repeat(whole.length - 2)}"`;
13958
+ });
13959
+ const descent = /[A-Za-z0-9_"]\s*[.[]/.exec(withoutLiterals);
13960
+ const rootEnd = descent ? descent.index + 1 : Number.POSITIVE_INFINITY;
13961
+ const place = (name, index, tail) => {
13962
+ if (tail || index >= rootEnd)
13963
+ nested.add(name);
13964
+ else
13965
+ top.add(name);
13966
+ };
13967
+ for (const entry of quoted)
13968
+ place(entry.name, entry.index, entry.tail);
13969
+ const identifiers = withoutLiterals.matchAll(/([A-Za-z_][A-Za-z0-9_]*)(\s*[:(])?/g);
13970
+ const reserved = new Set(["true", "false", "null", "and", "or", "not"]);
13971
+ for (const match of identifiers) {
13972
+ const [, name, trailing] = match;
13973
+ if (trailing || reserved.has(name))
13974
+ continue;
13975
+ place(name, match.index, isPathTail(withoutLiterals, match.index));
13976
+ }
13977
+ return {
13978
+ top: [...top],
13979
+ nested: [...nested].filter((name) => !top.has(name)),
13980
+ hasPredicate: /\[\s*\?/.test(withoutValueLiterals)
13981
+ };
13982
+ }
13983
+ function appearsBelowTopLevel(data, name) {
13984
+ let budget = 2000;
13985
+ const visit = (value, depth) => {
13986
+ if (budget-- <= 0 || depth > 4)
13987
+ return false;
13988
+ if (value === null || typeof value !== "object")
13989
+ return false;
13990
+ if (Array.isArray(value))
13991
+ return value.some((entry) => visit(entry, depth));
13992
+ const record = value;
13993
+ if (depth > 0 && Object.hasOwn(record, name))
13994
+ return true;
13995
+ return Object.values(record).some((entry) => visit(entry, depth + 1));
13996
+ };
13997
+ return visit(data, 0);
13998
+ }
13999
+ function alwaysNullKeys(records) {
14000
+ const objects = records.filter((r) => r != null && typeof r === "object" && !Array.isArray(r));
14001
+ if (objects.length === 0 || objects.length !== records.length)
14002
+ return [];
14003
+ const keys = [...new Set(objects.flatMap((o) => Object.keys(o)))];
14004
+ if (keys.length === 0)
14005
+ return [];
14006
+ const nullKeys = keys.filter((key) => objects.every((record) => record[key] === null));
14007
+ return nullKeys.length === keys.length ? nullKeys : [];
14008
+ }
14009
+ function carriesOnlyNulls(value) {
14010
+ if (value === null)
14011
+ return true;
14012
+ if (Array.isArray(value)) {
14013
+ return value.length > 0 && value.every(carriesOnlyNulls);
14014
+ }
14015
+ if (typeof value === "object" && value !== undefined) {
14016
+ const values = Object.values(value);
14017
+ return values.length > 0 && values.every(carriesOnlyNulls);
14018
+ }
14019
+ return false;
14020
+ }
14021
+ function nameList(names, cap2 = 12) {
14022
+ const shown = names.slice(0, cap2).map((n) => `\`${n}\``);
14023
+ const rest = names.length - shown.length;
14024
+ return shown.join(", ") + (rest > 0 ? `, and ${rest} more` : "");
14025
+ }
14026
+ function buildFilterWarning(filter, data, outcome) {
14027
+ const present = availableFields(data);
14028
+ const refs = referencedFields(filter);
14029
+ const unknown = refs.top.filter((name) => !present.includes(name) && !appearsBelowTopLevel(data, name));
14030
+ const unchecked = refs.nested.filter((name) => !present.includes(name));
14031
+ const count = countRecords(data);
14032
+ const scope = `${count} record(s)`;
14033
+ const isNotAField = (names) => `${nameList(names)} ${names.length === 1 ? "is not a field" : "are not fields"} on the ${scope} it read`;
14034
+ 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" : "";
14035
+ const withSoundness = (base) => soundness ? `${base}, and ${soundness}` : base;
14036
+ let detail;
14037
+ let lede;
14038
+ if (outcome.kind === "null-elements") {
14039
+ lede = "returned only null values";
14040
+ const projected = `all ${outcome.count} of the elements it projected are null`;
14041
+ if (unknown.length > 0) {
14042
+ detail = `${projected}, because ${isNotAField(unknown)}`;
14043
+ } else if (unchecked.length > 0) {
14044
+ detail = withSoundness(projected);
14045
+ } else {
14046
+ 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`;
14047
+ }
14048
+ } else if (outcome.kind === "null-rows") {
14049
+ lede = "returned only null values";
14050
+ const projected = `every value it projected is null on all ${outcome.count} row(s)`;
14051
+ detail = unknown.length > 0 ? `${projected}, because ${isNotAField(unknown)}` : withSoundness(projected);
14052
+ } else if (outcome.kind === "null-values") {
14053
+ lede = "returned only null values";
14054
+ const projected = `every key it projected (${nameList(outcome.keys)}) is null`;
14055
+ const sameSet = unknown.length === outcome.keys.length && outcome.keys.every((k) => unknown.includes(k));
14056
+ if (sameSet) {
14057
+ detail = `${isNotAField(outcome.keys)}, so every key it projected is null`;
14058
+ } else if (unknown.length > 0) {
14059
+ detail = `${projected}, because ${isNotAField(unknown)}`;
14060
+ } else {
14061
+ detail = withSoundness(`${projected} on all ${scope}`);
14062
+ }
14063
+ } else {
14064
+ lede = "returned nothing";
14065
+ if (unknown.length > 0) {
14066
+ detail = isNotAField(unknown);
14067
+ } else {
14068
+ const selection = refs.hasPredicate ? "no record matched" : "the expression resolved to no value";
14069
+ detail = withSoundness(`${selection} — it read ${scope}`);
14070
+ }
14071
+ }
14072
+ const fields = present.length > 0 ? ` Available fields: ${nameList(present)}.` : "";
14073
+ return `--output-filter ${JSON.stringify(filter)} ${lede}: ${detail}.${fields}`;
14074
+ }
14075
+ function appendWarning(existing, note) {
14076
+ return existing ? `${existing} ${note}` : note;
14077
+ }
14078
+ function applyFilter(data, filter, onWarning) {
13920
14079
  const codec = requireJmespath();
13921
14080
  let result;
13922
14081
  try {
@@ -13924,9 +14083,34 @@ function applyFilter(data, filter) {
13924
14083
  } catch (err) {
13925
14084
  throw new FilterEvaluationError(filter, err);
13926
14085
  }
13927
- if (result == null)
14086
+ const inputCount = countRecords(data);
14087
+ const warn = (outcome) => {
14088
+ if (inputCount === 0)
14089
+ return;
14090
+ const note = buildFilterWarning(filter, data, outcome);
14091
+ getOutputSink().writeErr(`[WARN] ${note}
14092
+ `);
14093
+ onWarning?.(note);
14094
+ };
14095
+ const warnIfAllNull = (records) => {
14096
+ const keys = alwaysNullKeys(records);
14097
+ if (keys.length > 0)
14098
+ warn({ kind: "null-values", keys });
14099
+ };
14100
+ if (result == null) {
14101
+ warn({ kind: "empty" });
13928
14102
  return [];
14103
+ }
13929
14104
  if (Array.isArray(result)) {
14105
+ if (result.length === 0) {
14106
+ warn({ kind: "empty" });
14107
+ } else if (result.every((entry) => entry === null)) {
14108
+ warn({ kind: "null-elements", count: result.length });
14109
+ } else if (result.every((entry) => Array.isArray(entry)) && carriesOnlyNulls(result)) {
14110
+ warn({ kind: "null-rows", count: result.length });
14111
+ } else {
14112
+ warnIfAllNull(result);
14113
+ }
13930
14114
  if (result.length > 0 && typeof result[0] !== "object") {
13931
14115
  const fieldMatch = filter.match(/\.(\w+)$/);
13932
14116
  const key = fieldMatch ? fieldMatch[1] : "Value";
@@ -13934,10 +14118,30 @@ function applyFilter(data, filter) {
13934
14118
  }
13935
14119
  return result;
13936
14120
  }
13937
- if (typeof result === "object")
14121
+ if (typeof result === "object") {
14122
+ warnIfAllNull([result]);
13938
14123
  return result;
14124
+ }
13939
14125
  return { Value: result };
13940
14126
  }
14127
+ function filterFailureData(envelope) {
14128
+ const filter = getOutputFilter();
14129
+ const data = envelope.Data;
14130
+ if (!filter || data == null)
14131
+ return;
14132
+ let note;
14133
+ const [filterError, filtered] = catchError(() => applyFilter(data, filter, (n) => {
14134
+ note = n;
14135
+ }));
14136
+ if (filterError) {
14137
+ envelope.Warning = appendWarning(envelope.Warning, `--output-filter was not applied, so Data is shown in full: ${filterError.message}`);
14138
+ return;
14139
+ }
14140
+ envelope.Data = filtered;
14141
+ if (note) {
14142
+ envelope.Warning = appendWarning(envelope.Warning, note);
14143
+ }
14144
+ }
13941
14145
  function defaultErrorCodeForResult(result) {
13942
14146
  switch (result) {
13943
14147
  case RESULTS.AuthenticationError:
@@ -14020,8 +14224,14 @@ var OutputFormatter;
14020
14224
  }
14021
14225
  const filter = getOutputFilter();
14022
14226
  if (filter) {
14023
- const filtered = applyFilter(data.Data, filter);
14227
+ let note;
14228
+ const filtered = applyFilter(data.Data, filter, (n) => {
14229
+ note = n;
14230
+ });
14024
14231
  data.Data = normalize ? normalizeDataKeys(filtered, verbatim, subtrees && { refs: subtrees.refs, mode: "skip" }) : filtered;
14232
+ if (note) {
14233
+ data.Warning = appendWarning(data.Warning, note);
14234
+ }
14025
14235
  }
14026
14236
  logOutput(normalizeOutputKeys(data), getOutputFormat(), options?.tableRowStyle);
14027
14237
  }
@@ -14049,6 +14259,7 @@ var OutputFormatter;
14049
14259
  delete envelope.TelemetryErrorClass;
14050
14260
  delete envelope.TelemetryTerminalOutcome;
14051
14261
  delete envelope.TelemetryTerminalSignal;
14262
+ filterFailureData(envelope);
14052
14263
  if (!suppressTelemetry) {
14053
14264
  telemetry.trackEvent(CommonTelemetryEvents.Error, {
14054
14265
  result: data.Result,
@@ -14097,13 +14308,20 @@ var OutputFormatter;
14097
14308
  OutputFormatter.log = log;
14098
14309
  function formatToString(data) {
14099
14310
  const filter = getOutputFilter();
14311
+ const envelope = data;
14100
14312
  if ("Data" in data && data.Data != null) {
14101
14313
  data.Data = normalizeDataKeys(data.Data);
14102
14314
  if (filter) {
14103
- data.Data = normalizeDataKeys(applyFilter(data.Data, filter));
14315
+ let note;
14316
+ data.Data = normalizeDataKeys(applyFilter(data.Data, filter, (n) => {
14317
+ note = n;
14318
+ }));
14319
+ if (note) {
14320
+ envelope.Warning = appendWarning(envelope.Warning, note);
14321
+ }
14104
14322
  }
14105
14323
  }
14106
- const output = normalizeOutputKeys(data);
14324
+ const output = normalizeOutputKeys(envelope);
14107
14325
  const lines = [];
14108
14326
  const sink = getOutputSink();
14109
14327
  printOutput(output, getOutputFormat(), (msg) => {
@@ -39287,4 +39505,4 @@ var registerCommands = async (program2) => {
39287
39505
 
39288
39506
  export { Command, metadata, registerCommands };
39289
39507
 
39290
- //# debugId=B230C530A4C2C2D264756E2164756E21
39508
+ //# debugId=75B699B5AA26167164756E2164756E21
package/dist/tool.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  metadata,
3
3
  registerCommands
4
- } from "./tool-gy4x3aqe.js";
4
+ } from "./tool-jtbgb7nj.js";
5
5
  import"./tool-1de529jm.js";
6
6
  export {
7
7
  metadata,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uipath/test-manager-tool",
3
3
  "license": "SEE LICENSE IN LICENSE.txt",
4
- "version": "1.202.1-preview.220",
4
+ "version": "1.202.1-preview.239",
5
5
  "description": "Manage test cases, test sets, executions, and results.",
6
6
  "private": false,
7
7
  "repository": {
@@ -26,5 +26,5 @@
26
26
  "files": [
27
27
  "dist"
28
28
  ],
29
- "gitHead": "a09041733b628c3f6b658a1f58349ea0f40bb492"
29
+ "gitHead": "97545a7857bdff7e6db62bbe13c6097607cf38f1"
30
30
  }