Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/playground/cli/src/is-valid-wordpress-slug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* The Regex is based on the releases on https://wordpress.org/download/releases/#betas
* The version string can be one of the following formats:
* - "latest"
* - "beta"
* - "trunk"
* - "nightly"
* - "x.y" (x and y are integers) e.g. "6.2"
Expand All @@ -16,6 +17,6 @@
*/
export function isValidWordPressSlug(version: string): boolean {
const versionPattern =
/^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/;
/^latest$|^beta$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/;
return versionPattern.test(version);
}
2 changes: 1 addition & 1 deletion packages/playground/cli/src/run-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export async function parseOptionsAndRunCLI() {
new URL(args.wp);
} catch {
throw new Error(
'Unrecognized WordPress version. Please use "latest", a URL, or a numeric version such as "6.2", "6.0.1", "6.2-beta1", or "6.2-RC1"'
'Unrecognized WordPress version. Please use "latest", "beta", "trunk", "nightly", a URL, or a numeric version such as "6.2", "6.0.1", "6.2-beta1", or "6.2-RC1"'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamziel I think the point is here, the conditional check if the version is valid, if not skip it and doesn't do anything. I think we should throw a message if the value is not valid

if (args.wp !== undefined && !isValidWordPressSlug(args.wp)) {
					try {
						// Check if is valid URL
						new URL(args.wp);
					} catch {
						throw new Error(
							'Unrecognized WordPress version. Please use "latest", "beta", "trunk", "nightly", a URL, or a numeric version such as "6.2", "6.0.1", "6.2-beta1", or "6.2-RC1"'
						);
					}
				}
				```

);
}
}
Expand Down
60 changes: 60 additions & 0 deletions packages/playground/cli/tests/is-valid-wordpress-slug.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { describe, it, expect } from 'vitest';
import { isValidWordPressSlug } from '../src/is-valid-wordpress-slug';

describe('isValidWordPressSlug', () => {
it('should accept "latest"', () => {
expect(isValidWordPressSlug('latest')).toBe(true);
});

it('should accept "beta"', () => {
expect(isValidWordPressSlug('beta')).toBe(true);
});

it('should accept "trunk"', () => {
expect(isValidWordPressSlug('trunk')).toBe(true);
});

it('should accept "nightly"', () => {
expect(isValidWordPressSlug('nightly')).toBe(true);
});

it('should accept version with major and minor (e.g., "6.2")', () => {
expect(isValidWordPressSlug('6.2')).toBe(true);
expect(isValidWordPressSlug('5.9')).toBe(true);
});

it('should accept version with major, minor, and patch (e.g., "6.2.1")', () => {
expect(isValidWordPressSlug('6.2.1')).toBe(true);
expect(isValidWordPressSlug('5.9.3')).toBe(true);
});

it('should accept version with beta suffix (e.g., "6.2-beta1")', () => {
expect(isValidWordPressSlug('6.2-beta1')).toBe(true);
expect(isValidWordPressSlug('6.2.1-beta1')).toBe(true);
expect(isValidWordPressSlug('6.2-beta')).toBe(true);
});

it('should accept version with RC suffix (e.g., "6.2-RC1")', () => {
expect(isValidWordPressSlug('6.2-RC1')).toBe(true);
expect(isValidWordPressSlug('6.2.1-RC1')).toBe(true);
expect(isValidWordPressSlug('6.2-RC')).toBe(true);
});

it('should reject invalid version strings', () => {
expect(isValidWordPressSlug('brazil')).toBe(false);
expect(isValidWordPressSlug('invalid')).toBe(false);
expect(isValidWordPressSlug('beta1')).toBe(false);
expect(isValidWordPressSlug('RC1')).toBe(false);
expect(isValidWordPressSlug('6')).toBe(false);
expect(isValidWordPressSlug('6.x')).toBe(false);
expect(isValidWordPressSlug('6.2.x')).toBe(false);
expect(isValidWordPressSlug('')).toBe(false);
});

it('should reject version with invalid format', () => {
expect(isValidWordPressSlug('6.2.1.2')).toBe(false);
expect(isValidWordPressSlug('v6.2')).toBe(false);
expect(isValidWordPressSlug('6.2-alpha')).toBe(false);
expect(isValidWordPressSlug('6.2-beta-1')).toBe(false);
});
});
76 changes: 76 additions & 0 deletions packages/playground/cli/tests/run-cli-validation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { parseOptionsAndRunCLI } from '../src/run-cli';

describe('parseOptionsAndRunCLI WordPress version validation', () => {
let originalArgv: string[];
let exitSpy: ReturnType<typeof vi.spyOn>;
let consoleErrorSpy: ReturnType<typeof vi.spyOn>;

beforeEach(() => {
originalArgv = process.argv;
exitSpy = vi.spyOn(process, 'exit').mockImplementation((() => {
throw new Error('process.exit called');
}) as any);
consoleErrorSpy = vi
.spyOn(console, 'error')
.mockImplementation(() => {});
});

afterEach(() => {
process.argv = originalArgv;
exitSpy.mockRestore();
consoleErrorSpy.mockRestore();
});

it('should reject invalid WordPress version "brazil"', async () => {
process.argv = ['node', 'cli.js', 'server', '--wp=brazil'];

await expect(parseOptionsAndRunCLI()).rejects.toThrow(
'process.exit called'
);

expect(consoleErrorSpy).toHaveBeenCalled();
const errorMessage = consoleErrorSpy.mock.calls[0][0];
expect(errorMessage).toContain('Unrecognized WordPress version');
});

it('should reject invalid WordPress version "invalid-version"', async () => {
process.argv = ['node', 'cli.js', 'server', '--wp=invalid-version'];

await expect(parseOptionsAndRunCLI()).rejects.toThrow(
'process.exit called'
);

expect(consoleErrorSpy).toHaveBeenCalled();
const errorMessage = consoleErrorSpy.mock.calls[0][0];
expect(errorMessage).toContain('Unrecognized WordPress version');
});

it('should accept valid WordPress version "beta"', async () => {
process.argv = [
'node',
'cli.js',
'server',
'--wp=beta',
'--skip-wordpress-setup',
];

// This test would actually start the server, so we skip it in unit tests
// The important part is that it doesn't throw a validation error
// We'll rely on integration tests to verify the full flow
});

it('should accept valid WordPress version "latest"', async () => {
process.argv = [
'node',
'cli.js',
'server',
'--wp=latest',
'--skip-wordpress-setup',
];

// This test would actually start the server, so we skip it in unit tests
// The important part is that it doesn't throw a validation error
// We'll rely on integration tests to verify the full flow
});
});
38 changes: 38 additions & 0 deletions packages/playground/cli/tests/run-cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,4 +690,42 @@ describe('other run-cli behaviors', () => {
expect(response.status).toBe(500);
});
});

describe('WordPress version validation', () => {
test('should accept "latest" as a valid WordPress version', async () => {
cliServer = await runCLI({
...suiteCliArgs,
command: 'server',
wp: 'latest',
});
expect(cliServer).toBeDefined();
});

test('should accept "beta" as a valid WordPress version', async () => {
cliServer = await runCLI({
...suiteCliArgs,
command: 'server',
wp: 'beta',
});
expect(cliServer).toBeDefined();
});

test('should accept numeric version as valid WordPress version', async () => {
cliServer = await runCLI({
...suiteCliArgs,
command: 'server',
wp: '6.2',
});
expect(cliServer).toBeDefined();
});

test('should accept valid URL as WordPress version', async () => {
cliServer = await runCLI({
...suiteCliArgs,
command: 'server',
wp: 'https://downloads.wordpress.org/release/wordpress-6.2.zip',
});
expect(cliServer).toBeDefined();
});
});
});