396 lines
12 KiB
Python
396 lines
12 KiB
Python
"""Tests for CLI commands."""
|
|
|
|
import pytest
|
|
import json
|
|
import tempfile
|
|
from pathlib import Path
|
|
from click.testing import CliRunner
|
|
|
|
from src.cli.commands import cli
|
|
|
|
|
|
@pytest.fixture
|
|
def runner():
|
|
"""Create a Click CLI runner."""
|
|
return CliRunner()
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_openapi_yaml():
|
|
"""Sample OpenAPI specification in YAML format."""
|
|
return """
|
|
openapi: \"3.0.0\"
|
|
info:
|
|
title: Sample API
|
|
version: \"1.0.0\"
|
|
paths:
|
|
/users:
|
|
get:
|
|
summary: Get all users
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Successful response
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
email:
|
|
type: string
|
|
format: email
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
/users/{userId}:
|
|
get:
|
|
summary: Get user by ID
|
|
parameters:
|
|
- name: userId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Successful response
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
email:
|
|
type: string
|
|
format: email
|
|
'404':
|
|
description: User not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
message:
|
|
type: string
|
|
put:
|
|
summary: Update user
|
|
parameters:
|
|
- name: userId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
email:
|
|
type: string
|
|
format: email
|
|
required:
|
|
- name
|
|
responses:
|
|
'200':
|
|
description: User updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
/posts:
|
|
post:
|
|
summary: Create a post
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
content:
|
|
type: string
|
|
authorId:
|
|
type: integer
|
|
responses:
|
|
'201':
|
|
description: Post created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
title:
|
|
type: string
|
|
content:
|
|
type: string
|
|
authorId:
|
|
type: integer
|
|
publishedAt:
|
|
type: string
|
|
format: date-time
|
|
components:
|
|
schemas:
|
|
User:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
email:
|
|
type: string
|
|
format: email
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
Post:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
title:
|
|
type: string
|
|
content:
|
|
type: string
|
|
authorId:
|
|
type: integer
|
|
publishedAt:
|
|
type: string
|
|
format: date-time
|
|
Error:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
message:
|
|
type: string
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_spec_file(sample_openapi_yaml, tmp_path):
|
|
"""Create a temporary OpenAPI spec file."""
|
|
spec_file = tmp_path / "openapi.yaml"
|
|
spec_file.write_text(sample_openapi_yaml)
|
|
return str(spec_file)
|
|
|
|
|
|
class TestCLIServe:
|
|
"""Tests for serve command."""
|
|
|
|
def test_serve_validate_only(self, temp_spec_file, runner):
|
|
"""Test serve command with validate-only option."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "serve", "--validate-only"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "valid" in result.output.lower() or "success" in result.output.lower()
|
|
|
|
def test_serve_missing_spec_file(self, tmp_path, runner):
|
|
"""Test serve command with missing spec file."""
|
|
result = runner.invoke(cli, ["--spec-file", str(tmp_path / "nonexistent.yaml"), "serve", "--validate-only"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "not found" in result.output.lower()
|
|
|
|
def test_serve_with_port(self, temp_spec_file, runner):
|
|
"""Test serve command with custom port."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "serve", "--validate-only", "--port", "3000"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_serve_with_delay(self, temp_spec_file, runner):
|
|
"""Test serve command with delay."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "serve", "--validate-only", "--delay", "100"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
|
|
class TestCLIGenerate:
|
|
"""Tests for generate command."""
|
|
|
|
def test_generate_lists_endpoints(self, temp_spec_file, runner):
|
|
"""Test generate command without path lists endpoints."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "generate"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "/users" in result.output
|
|
|
|
def test_generate_specific_endpoint(self, temp_spec_file, runner):
|
|
"""Test generate command for specific endpoint."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "generate", "/users", "get"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "status_code" in result.output or "200" in result.output
|
|
|
|
def test_generate_with_format_json(self, temp_spec_file, runner):
|
|
"""Test generate command with JSON output format."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "generate", "/users", "get", "--format", "json"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "{" in result.output
|
|
|
|
def test_generate_with_format_yaml(self, temp_spec_file, runner):
|
|
"""Test generate command with YAML output format."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "generate", "/users", "get", "--format", "yaml"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_generate_path_not_found(self, temp_spec_file, runner):
|
|
"""Test generate command with invalid path."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "generate", "/nonexistent", "get"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "not found" in result.output.lower()
|
|
|
|
|
|
class TestCLIValidate:
|
|
"""Tests for validate command."""
|
|
|
|
def test_validate_spec(self, temp_spec_file, runner):
|
|
"""Test validate command for valid spec."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "validate"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "valid" in result.output.lower()
|
|
|
|
def test_validate_missing_file(self, tmp_path, runner):
|
|
"""Test validate command with missing file."""
|
|
result = runner.invoke(cli, ["--spec-file", str(tmp_path / "nonexistent.yaml"), "validate"])
|
|
|
|
assert result.exit_code != 0
|
|
|
|
|
|
class TestCLIRoutes:
|
|
"""Tests for routes command."""
|
|
|
|
def test_routes_lists_all(self, temp_spec_file, runner):
|
|
"""Test routes command lists all routes."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "routes"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "/users" in result.output
|
|
assert "/posts" in result.output
|
|
|
|
|
|
class TestCLIInfo:
|
|
"""Tests for info command."""
|
|
|
|
def test_info_displays_spec_info(self, temp_spec_file, runner):
|
|
"""Test info command displays spec information."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "info"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "Sample API" in result.output
|
|
assert "1.0.0" in result.output
|
|
assert "Paths" in result.output
|
|
|
|
|
|
class TestCLITest:
|
|
"""Tests for test command."""
|
|
|
|
def test_test_endpoint(self, temp_spec_file, runner):
|
|
"""Test test command for specific endpoint."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "test", "/users", "--method", "get"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "Status" in result.output or "200" in result.output
|
|
|
|
def test_test_with_query_params(self, temp_spec_file, runner):
|
|
"""Test test command with query parameters."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "test", "/users", "--method", "get", "--query", "page=1"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_test_with_body(self, temp_spec_file, runner):
|
|
"""Test test command with request body."""
|
|
body = json.dumps({"title": "Test Post", "content": "Content"})
|
|
result = runner.invoke(cli, [
|
|
"--spec-file", temp_spec_file, "test", "/posts", "--method", "post",
|
|
"--body", body
|
|
])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_test_missing_path(self, temp_spec_file, runner):
|
|
"""Test test command without path."""
|
|
result = runner.invoke(cli, ["--spec-file", temp_spec_file, "test"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "path" in result.output.lower()
|
|
|
|
|
|
class TestCLIDocker:
|
|
"""Tests for docker command."""
|
|
|
|
def test_docker_builds_image(self, runner):
|
|
"""Test docker command builds image."""
|
|
result = runner.invoke(cli, ["docker", "--no-build"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "docker run" in result.output
|
|
|
|
def test_docker_with_custom_image_name(self, runner):
|
|
"""Test docker command with custom image name."""
|
|
result = runner.invoke(cli, ["docker", "--no-build", "--image-name", "my-mock-server"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "my-mock-server" in result.output
|
|
|
|
|
|
class TestCLIVersion:
|
|
"""Tests for version option."""
|
|
|
|
def test_version_flag(self, runner):
|
|
"""Test --version flag displays version."""
|
|
result = runner.invoke(cli, ["--version"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "0.1.0" in result.output or "openapi-mock-generator" in result.output
|
|
|
|
|
|
class TestCLIHelp:
|
|
"""Tests for help option."""
|
|
|
|
def test_help_displays_commands(self, runner):
|
|
"""Test --help displays available commands."""
|
|
result = runner.invoke(cli, ["--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "serve" in result.output
|
|
assert "generate" in result.output
|
|
assert "validate" in result.output
|
|
assert "routes" in result.output
|
|
assert "info" in result.output
|