Address review feedback and regenerate API reports
- Handle quoted arguments in createScriptOptionsParser using a proper shell-like splitter instead of naive whitespace splitting - Pass CommandContext directly in bump tests instead of using a helper - Regenerate cli-report.md Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -15,6 +15,40 @@
|
||||
*/
|
||||
import { parseArgs, type ParseArgsConfig } from 'node:util';
|
||||
|
||||
// Splits a shell-like argument string, respecting single and double quotes
|
||||
function splitShellArgs(str: string): string[] {
|
||||
const args: string[] = [];
|
||||
let current = '';
|
||||
let quote: string | undefined;
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const ch = str[i];
|
||||
|
||||
if (quote) {
|
||||
if (ch === quote) {
|
||||
quote = undefined;
|
||||
} else {
|
||||
current += ch;
|
||||
}
|
||||
} else if (ch === '"' || ch === "'") {
|
||||
quote = ch;
|
||||
} else if (/\s/.test(ch)) {
|
||||
if (current) {
|
||||
args.push(current);
|
||||
current = '';
|
||||
}
|
||||
} else {
|
||||
current += ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (current) {
|
||||
args.push(current);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export function createScriptOptionsParser(
|
||||
commandPath: string[],
|
||||
options: ParseArgsConfig['options'],
|
||||
@@ -27,7 +61,7 @@ export function createScriptOptionsParser(
|
||||
}
|
||||
|
||||
const argsStr = scriptStr.slice(expectedScript.length).trim();
|
||||
const args = argsStr ? argsStr.split(/\s+/) : [];
|
||||
const args = argsStr ? splitShellArgs(argsStr) : [];
|
||||
|
||||
const { values } = parseArgs({ args, strict: false, options });
|
||||
return values;
|
||||
|
||||
@@ -15,6 +15,40 @@
|
||||
*/
|
||||
import { parseArgs, type ParseArgsConfig } from 'node:util';
|
||||
|
||||
// Splits a shell-like argument string, respecting single and double quotes
|
||||
function splitShellArgs(str: string): string[] {
|
||||
const args: string[] = [];
|
||||
let current = '';
|
||||
let quote: string | undefined;
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const ch = str[i];
|
||||
|
||||
if (quote) {
|
||||
if (ch === quote) {
|
||||
quote = undefined;
|
||||
} else {
|
||||
current += ch;
|
||||
}
|
||||
} else if (ch === '"' || ch === "'") {
|
||||
quote = ch;
|
||||
} else if (/\s/.test(ch)) {
|
||||
if (current) {
|
||||
args.push(current);
|
||||
current = '';
|
||||
}
|
||||
} else {
|
||||
current += ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (current) {
|
||||
args.push(current);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export function createScriptOptionsParser(
|
||||
commandPath: string[],
|
||||
options: ParseArgsConfig['options'],
|
||||
@@ -27,7 +61,7 @@ export function createScriptOptionsParser(
|
||||
}
|
||||
|
||||
const argsStr = scriptStr.slice(expectedScript.length).trim();
|
||||
const args = argsStr ? argsStr.split(/\s+/) : [];
|
||||
const args = argsStr ? splitShellArgs(argsStr) : [];
|
||||
|
||||
const { values } = parseArgs({ args, strict: false, options });
|
||||
return values;
|
||||
|
||||
@@ -17,7 +17,6 @@ import fs from 'fs-extra';
|
||||
import * as runObj from '@backstage/cli-common';
|
||||
import { overrideTargetPaths } from '@backstage/cli-common/testUtils';
|
||||
import bump, { bumpBackstageJsonVersion, createVersionFinder } from './bump';
|
||||
import type { CommandContext } from '../../../../wiring/types';
|
||||
import { registerMswTestHooks, withLogCollector } from '@backstage/test-utils';
|
||||
import { YarnInfoInspectData } from '../../lib/versioning/packages';
|
||||
import { setupServer } from 'msw/node';
|
||||
@@ -126,27 +125,7 @@ const expectLogsToMatch = (
|
||||
expect(receivedLogs.filter(Boolean).sort()).toEqual(expected.sort());
|
||||
};
|
||||
|
||||
function callBump(flags: Record<string, string | boolean | null>) {
|
||||
const args: string[] = [];
|
||||
for (const [key, value] of Object.entries(flags)) {
|
||||
if (value === null || value === undefined) {
|
||||
continue;
|
||||
}
|
||||
const flag = `--${key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`)}`;
|
||||
if (typeof value === 'boolean') {
|
||||
if (value) {
|
||||
args.push(flag);
|
||||
}
|
||||
} else {
|
||||
args.push(flag, value);
|
||||
}
|
||||
}
|
||||
const context: CommandContext = {
|
||||
args,
|
||||
info: { usage: 'backstage-cli versions:bump', description: 'test' },
|
||||
};
|
||||
return bump(context);
|
||||
}
|
||||
const info = { usage: 'backstage-cli versions:bump', description: '' };
|
||||
|
||||
describe('bump', () => {
|
||||
const mockDir = createMockDirectory();
|
||||
@@ -212,7 +191,7 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -305,7 +284,7 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main', skipInstall: true });
|
||||
await bump({ args: ['--release', 'main', '--skip-install'], info });
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -407,7 +386,7 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -511,7 +490,7 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -606,9 +585,9 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await expect(callBump({ release: '999.0.1' })).rejects.toThrow(
|
||||
'No release found for 999.0.1 version',
|
||||
);
|
||||
await expect(
|
||||
bump({ args: ['--release', '999.0.1'], info }),
|
||||
).rejects.toThrow('No release found for 999.0.1 version');
|
||||
});
|
||||
expect(logs.filter(Boolean)).toEqual([
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -712,7 +691,7 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'next' });
|
||||
await bump({ args: ['--release', 'next'], info });
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -791,9 +770,14 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({
|
||||
pattern: '@{backstage,backstage-extra}/*',
|
||||
release: 'main',
|
||||
await bump({
|
||||
args: [
|
||||
'--pattern',
|
||||
'@{backstage,backstage-extra}/*',
|
||||
'--release',
|
||||
'main',
|
||||
],
|
||||
info,
|
||||
});
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
@@ -900,7 +884,7 @@ describe('bump', () => {
|
||||
),
|
||||
);
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
expectLogsToMatch(logs, [
|
||||
'Using default pattern glob @backstage/*',
|
||||
@@ -1139,7 +1123,7 @@ describe('environment variables', () => {
|
||||
);
|
||||
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
|
||||
expectLogsToMatch(logs, [
|
||||
@@ -1213,7 +1197,7 @@ describe('environment variables', () => {
|
||||
} as any);
|
||||
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
|
||||
expectLogsToMatch(logs, [
|
||||
@@ -1298,7 +1282,7 @@ describe('environment variables', () => {
|
||||
);
|
||||
|
||||
const { log: logs } = await withLogCollector(['log', 'warn'], async () => {
|
||||
await callBump({ release: 'main' });
|
||||
await bump({ args: ['--release', 'main'], info });
|
||||
});
|
||||
|
||||
expectLogsToMatch(logs, [
|
||||
@@ -1347,7 +1331,7 @@ describe('environment variables', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await expect(callBump({ release: 'main' })).rejects.toThrow();
|
||||
await expect(bump({ args: ['--release', 'main'], info })).rejects.toThrow();
|
||||
});
|
||||
|
||||
it('should handle network errors when using custom base URL', async () => {
|
||||
@@ -1375,6 +1359,6 @@ describe('environment variables', () => {
|
||||
),
|
||||
);
|
||||
|
||||
await expect(callBump({ release: 'main' })).rejects.toThrow();
|
||||
await expect(bump({ args: ['--release', 'main'], info })).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user