Source code for tests.test_parser

import pytest
import uuid
from unittest.mock import Mock, patch

from steps.api.utils.parser import (
    find, to_float, to_int, parse_string, parse_nested_value,
    get_true_keys, try_read_from_variable, try_save_value_to_variable, check_expected_values_in_response,
    RANDOM_UUID_KEY
)


[docs] def test_find(): # Test with a simple dictionary test_dict = { "components": { "schemas": { "User": { "properties": { "id": {"type": "integer"} } } } } } # Test finding a nested path result = find("components/schemas/User", test_dict) assert result == test_dict["components"]["schemas"]["User"] # Test finding a path with multiple levels result = find("components/schemas/User/properties/id", test_dict) assert result == {"type": "integer"} # Test with a path that doesn't exist with pytest.raises(KeyError): find("components/schemas/NonExistent", test_dict)
[docs] def test_to_float(): # Test with valid float string assert to_float("3.14") == 3.14 # Test with valid integer string assert to_float("42") == 42.0 # Test with invalid string assert to_float("not_a_float") is None # Test with empty string assert to_float("") is None
[docs] def test_to_int(): # Test with valid integer string assert to_int("42") == 42 # Test with float string (should fail) assert to_int("3.14") is None # Test with invalid string assert to_int("not_an_int") is None # Test with empty string assert to_int("") is None
[docs] def test_parse_string(): # Test with None value assert parse_string("None") is None # Test with boolean values assert parse_string("true") is True assert parse_string("false") is False # Test with JSON object json_obj = parse_string('{"key": "value"}') assert isinstance(json_obj, dict) assert json_obj["key"] == "value" # Test with JSON array json_arr = parse_string('[1, 2, 3]') assert isinstance(json_arr, list) assert json_arr == [1, 2, 3] # Test with integer assert parse_string("42") == 42 # Test with float assert parse_string("3.14") == 3.14 # Test with string that can't be parsed as anything else assert parse_string("just a string") == "just a string"
@patch("steps.api.utils.parser.try_read_from_variable")
[docs] def test_parse_nested_value_string(mock_try_read): # Mock the try_read_from_variable function mock_try_read.return_value = "parsed_value" # Test with a string context = Mock() result = parse_nested_value("test_string", context) assert result == "parsed_value" mock_try_read.assert_called_once_with("test_string", context)
[docs] def test_parse_nested_value_dict(): # Test with a dictionary containing strings context = Mock() # Set up nested dictionary test_dict = { "key1": "value1", "key2": { "nested_key": "nested_value" }, "key3": [ "list_item_1", {"list_nested_key": "list_nested_value"} ] } # Mock the try_read_from_variable function with patch("steps.api.utils.parser.try_read_from_variable", side_effect=lambda value, ctx: f"parsed_{value}" if isinstance(value, str) else value): result = parse_nested_value(test_dict, context) # Check that all strings were parsed assert result["key1"] == "parsed_value1" assert result["key2"]["nested_key"] == "parsed_nested_value" assert result["key3"][0] == "parsed_list_item_1" assert result["key3"][1]["list_nested_key"] == "parsed_list_nested_value" # Check that it's a copy, not the original assert result is not test_dict
[docs] def test_get_true_keys_dict(): # Test with a dictionary test_dict = { "key1": { "key2": [ {"key3": "value"} ] } } # Test getting keys for the first level keys = get_true_keys(["key1"], test_dict) assert keys == ["key1"] # Test getting keys for nested levels keys = get_true_keys(["key1", "key2", "0", "key3"], test_dict) assert keys == ["key1", "key2", 0, "key3"] # Test with invalid keys with pytest.raises(KeyError): get_true_keys(["nonexistent"], test_dict)
[docs] def test_get_true_keys_list(): # Test with a list test_list = [ {"key1": "value1"}, {"key2": "value2"} ] # Test getting keys for the first level keys = get_true_keys(["0"], test_list) assert keys == [0] # Test getting keys for nested levels keys = get_true_keys(["0", "key1"], test_list) assert keys == [0, "key1"] # Test with invalid keys with pytest.raises(IndexError): get_true_keys(["2"], test_list) # Index out of range
[docs] def test_get_true_keys_unsupported_type(): # Test with an unsupported type (not dict or list) with pytest.raises(NotImplementedError): get_true_keys(["key"], "not_a_dict_or_list")
[docs] def test_try_read_from_variable_random_uuid(): # Test reading a random UUID with patch("uuid.uuid4", return_value=uuid.UUID("12345678-1234-5678-1234-567812345678")): result = try_read_from_variable(RANDOM_UUID_KEY, None) assert result == "12345678-1234-5678-1234-567812345678"
[docs] def test_try_read_from_variable_temporary(): # Test reading a temporary variable context = Mock() context.cloud.temp = {"test_key": "test_value"} # Use the VARIABLE_METHOD_PATTERN to match "temporary variable "test_key"" result = try_read_from_variable('temporary variable "test_key"', context) assert result == "test_value"
[docs] def test_try_read_from_variable_user(): # Test reading a user variable context = Mock() context.cloud.users = [ {"first_name": "John", "last_name": "Doe"}, {"first_name": "Jane", "last_name": "Smith"} ] # Use the USER_VARIABLE_METHOD_PATTERN to match 'variable "first_name" of user 0' result = try_read_from_variable('variable "first_name" of user 0', context) assert result == "John" # Test with another user index result = try_read_from_variable('variable "last_name" of user 1', context) assert result == "Smith"
[docs] def test_try_read_from_variable_admin(): # Test reading an admin variable context = Mock() context.cloud.admin = {"email": "admin@example.com", "role": "admin"} # Use the ADMIN_VARIABLE_METHOD_PATTERN to match 'variable "email" of admin' result = try_read_from_variable('variable "email" of admin', context) assert result == "admin@example.com"
[docs] def test_try_read_from_variable_platform(): # Test reading a platform variable context = Mock() context.cloud.default_platform = {"name": "test_platform", "version": "1.0"} # Use the PLATFORM_VARIABLE_METHOD_PATTERN to match 'variable "name" of default platform' result = try_read_from_variable('variable "name" of default platform', context) assert result == "test_platform"
[docs] def test_try_read_from_variable_environment(): # Test reading an environment variable context = Mock() context.cloud.environnement = {"TEST_VAR": "test_value"} # Use the ENV_VARIABLE_METHOD_PATTERN to match 'environnement variable "TEST_VAR"' result = try_read_from_variable('environnement variable "TEST_VAR"', context) assert result == "test_value"
[docs] def test_try_read_from_variable_type_conversion(): # Test string type conversion result = try_read_from_variable('string "test"', None) assert result == "test" # Test int type conversion result = try_read_from_variable('int 42', None) assert result == 42 # Test float type conversion result = try_read_from_variable('float 3.14', None) assert result == 3.14
[docs] def test_try_read_from_variable_fallback(): # Test fallback to returning the original string when no pattern matches result = try_read_from_variable("unmatched string", None) assert result == "unmatched string"
[docs] def test_try_save_value_to_variable_temporary(): # Test saving to a temporary variable context = Mock() context.cloud.temp = {} try_save_value_to_variable(context, "test_value", 'temporary variable "test_key"') assert context.cloud.temp["test_key"] == "test_value"
[docs] def test_try_save_value_to_variable_user(): # Test saving to a user variable context = Mock() context.cloud.users = [{}] try_save_value_to_variable(context, "John", 'variable "first_name" of user 0') assert context.cloud.users[0]["first_name"] == "John"
[docs] def test_try_save_value_to_variable_nonexistent_pattern(): # Test with a pattern that doesn't match any variable type context = Mock() with pytest.raises(RuntimeWarning): try_save_value_to_variable(context, "value", "invalid pattern")
[docs] def test_check_expected_values_in_response_simple_key(): # Test a simple key match context = Mock() context.request = Mock() context.request.response.json.return_value = {"status": "success", "message": "Operation completed"} # Test with matching value result, expected, response = check_expected_values_in_response(context, "status", "success") assert result is True assert expected == "success" assert response == "success" # Test with non-matching value result, expected, response = check_expected_values_in_response(context, "status", "failure") assert result is False assert expected == "failure" assert response == "success" # Test with non-existent key with pytest.raises(AssertionError): check_expected_values_in_response(context, "nonexistent", "value")
[docs] def test_check_expected_values_in_response_nested_key(): # Test with a nested key using bracket notation context = Mock() context.request = Mock() context.request.response.json.return_value = { "data": { "user": { "name": "John", "id": 123 } } } # Test with matching value result, expected, response = check_expected_values_in_response(context, "data[\"user\"][\"name\"]", "John") assert result is True assert expected == "John" assert response == "John" # Test with non-matching value result, expected, response = check_expected_values_in_response(context, "data[\"user\"][\"id\"]", "456") assert result is False assert expected == 456 assert response == 123
[docs] def test_check_expected_values_in_response_eval_methods(): # Test with eval methods (any, all, none) context = Mock() context.request = Mock() context.request.response.json.return_value = { "items": [ {"id": 1, "status": "active"}, {"id": 2, "status": "inactive"}, {"id": 3, "status": "active"} ] } # Test with 'any' method matching result, expected, response = check_expected_values_in_response( context, "any([item[\"status\"] for item in response[\"items\"]])", "active") assert result is True assert expected == "active" assert response == ["active", "inactive", "active"] # Test with 'all' method not matching result, expected, response = check_expected_values_in_response( context, "all([item[\"status\"] for item in response[\"items\"]])", "active") assert result is False assert expected == "active" assert response == ["active", "inactive", "active"] # Test with 'none' method not matching result, expected, response = check_expected_values_in_response( context, "none([item[\"status\"] for item in response[\"items\"]])", "active") assert result is False assert expected == "active" assert response == ["active", "inactive", "active"] # Test with 'none' method matching result, expected, response = check_expected_values_in_response( context, "none([item[\"status\"] for item in response[\"items\"]])", "pending") assert result is True assert expected == "pending" assert response == ["active", "inactive", "active"]
[docs] def test_check_expected_values_in_response_with_variable(): # Test with a value from a variable context = Mock() context.request = Mock() context.request.response.json.return_value = {"user_id": 123} # Mock try_read_from_variable to return a specific value with patch("steps.api.utils.parser.try_read_from_variable", return_value=123): result, expected, response = check_expected_values_in_response( context, "user_id", 'variable "id" of user 0') assert result is True assert expected == 123 assert response == 123