MCPcopy Create free account
hub / github.com/TestSprite/testsprite-cli / runUpdate

Function runUpdate

src/commands/test.ts:1206–1266  ·  view source on GitHub ↗
(
  opts: UpdateOptions,
  deps: TestDeps = {},
)

Source from the content-addressed store, hash-verified

1204 * matches piece-2's pattern.
1205 */
1206export async function runUpdate(
1207 opts: UpdateOptions,
1208 deps: TestDeps = {},
1209): Promise<CliUpdateTestResponse> {
1210 assertIdempotencyKey(opts.idempotencyKey);
1211 requireNonEmpty('test-id', opts.testId);
1212 // P1-3: client-side length checks matching server limits.
1213 if (opts.name !== undefined && opts.name.length > 200) {
1214 throw localValidationError('name', 'must be at most 200 characters');
1215 }
1216 if (opts.description !== undefined && opts.description.length > 2000) {
1217 throw localValidationError('description', 'must be at most 2000 characters');
1218 }
1219 if (opts.priority !== undefined && !CLI_CREATE_PRIORITIES.includes(opts.priority)) {
1220 throw localValidationError('priority', `must be one of: ${CLI_CREATE_PRIORITIES.join(', ')}`, [
1221 ...CLI_CREATE_PRIORITIES,
1222 ]);
1223 }
1224
1225 // No-op rejection: requires at least one of the three patchable
1226 // fields. Caught before fetching credentials or building the
1227 // request so the user gets the cheapest possible error.
1228 const hasName = opts.name !== undefined;
1229 const hasDescription = opts.description !== undefined;
1230 const hasPriority = opts.priority !== undefined;
1231 if (!hasName && !hasDescription && !hasPriority) {
1232 throw localValidationError(
1233 'fields',
1234 'at least one of --name / --description / --priority must be set',
1235 ['name', 'description', 'priority'],
1236 );
1237 }
1238
1239 const idempotencyKey = opts.idempotencyKey ?? `cli-update-${randomUUID()}`;
1240 if (opts.idempotencyKey === undefined && (opts.output === 'json' || opts.verbose || opts.debug)) {
1241 const stderr = deps.stderr ?? ((line: string) => process.stderr.write(`${line}\n`));
1242 stderr(`idempotency-key: ${idempotencyKey}`);
1243 }
1244
1245 // Body carries only the fields the caller passed. Sending
1246 // `{ name: undefined }` would JSON-serialize to omit the key, which
1247 // is the intended wire shape — but we build the body deliberately
1248 // so the contract is auditable rather than dependent on
1249 // JSON.stringify undefined-skipping.
1250 const body: Record<string, string> = {};
1251 if (hasName) body.name = opts.name!;
1252 if (hasDescription) body.description = opts.description!;
1253 if (hasPriority) body.priority = opts.priority!;
1254
1255 const client = makeClient(opts, deps);
1256 const out = makeOutput(opts.output, deps);
1257 const response = await client.put<CliUpdateTestResponse>(
1258 `/tests/${encodeURIComponent(opts.testId)}`,
1259 {
1260 body,
1261 headers: { 'idempotency-key': idempotencyKey },
1262 },
1263 );

Callers 3

test.test.tsFile · 0.70
createTestCommandFunction · 0.70
project.test.tsFile · 0.70

Calls 8

assertIdempotencyKeyFunction · 0.85
requireNonEmptyFunction · 0.85
stderrFunction · 0.85
printMethod · 0.80
localValidationErrorFunction · 0.70
makeClientFunction · 0.70
makeOutputFunction · 0.70
renderUpdateTextFunction · 0.70

Tested by

no test coverage detected