Exemple #1
0
def step_generic_modify_request_json(ctx: Context, target_key: str,
                                     value: str) -> None:
    """Modifies the request data in the behave context to have the actual value of the given string representation.

    Args:
        ctx: The behave context
        target_key: The key whose value is to be modified
        value: A string representation of what the new value should be

    """
    LOGGER.debug(
        f"Attempting to modify the JSON request payload at: {target_key} to be: {value}."
    )
    desired_value = CommonBehave.interpolate_context_attributes(ctx, value)
    parsed_key = CommonBehave.interpolate_context_attributes(ctx, target_key)
    if desired_value.lower() in ("none", "null"):
        ctx.request_data = modify_json_value(ctx.request_data, parsed_key,
                                             None)
    elif desired_value.lower() in ("invalid", "empty", "empty string"):
        ctx.request_data = modify_json_value(ctx.request_data, parsed_key, "")
    elif desired_value.lower() in "uuid":
        ctx.request_data = modify_json_value(ctx.request_data, parsed_key,
                                             str(uuid.uuid4()))
    else:
        ctx.request_data = modify_json_value(ctx.request_data, parsed_key,
                                             desired_value)
    LOGGER.debug("Successfully updated JSON request payload.")
Exemple #2
0
def step_debug_pdb(ctx: Context) -> None:
    """Sets a pdb to be used for debugging.

    The gherkin-linter will catch this step to prevent a pdb being pushed.
    Multiple if statements log everything a dev would need to start debugging the issue.

    Args:
        ctx: The behave context object

    """
    LOGGER.debug(
        "Behave PDB step was set. Current context attributes broken down by context layer:"
    )
    CommonBehave.log_context_attributes(ctx)
    pdb.set_trace()
def step_assert_headers(ctx: Context, negate: str) -> None:
    """Checks that the headers have the proper values.

    Args:
        ctx: The behave context
        negate: A string representing whether or not a response should be negated. If it should be negated, it will have
            a value 'not'. Otherwise, it will be None

    """
    for row in ctx.table:
        header = ctx.response.headers.get(row[0])
        header_value = CommonBehave.interpolate_context_attributes(ctx, row[1])
        if negate:
            LOGGER.debug(
                f"Checking that the response header: {row[0]} should not be: {header_value}."
            )
            assert (
                header != header_value
            ), f'Expected response header: "{row[0]}" to not be "{header_value}", but it was "{header}"'
        else:
            LOGGER.debug(
                f"Checking that the response header: {row[0]} should be: {header_value}."
            )
            assert (
                header == header_value
            ), f'Expected response header: "{row[0]}" to be "{header_value}", but it was "{header}"'
        LOGGER.debug("Successfully validated response headers.")
Exemple #4
0
def step_save_response_attribute_to_context(ctx: Context, key: str,
                                            value_name: str) -> None:
    """Sets the JSON response with a given key to a value in the behave context with an attribute name of <value_name>

    Args:
        ctx: The behave context
        key: The key from the JSON response
        value_name: The new name for the new attribute in the behave context

    """
    interpolated_key = CommonBehave.interpolate_context_attributes(
        ctx, f"$.{key}")
    list_of_values = jsonpath(ctx.response.json(), interpolated_key)
    LOGGER.debug(
        f"Attempting to save JSON response at: {interpolated_key} as: {value_name}."
    )
    if list_of_values:
        found_value = list_of_values[0]
        setattr(ctx, value_name, found_value)
        LOGGER.debug(
            f"Successfully saved response attribute: {key} as {value_name}.")
    else:
        raise KeyError(
            f"No key: '{interpolated_key}' found in the JSON response: {ctx.response.json()}"
        )
def step_assert_rest_response_collection_size(ctx: Context, key: str,
                                              negate: str,
                                              collection_size: str) -> None:
    """Checks that the JSON response does or does not have a collection of the given size.

    Args:
        ctx: The behave context
        negate: A string representing whether or not a response should be negated. If it should be negated, it will have
            a value 'not'. Otherwise, it will be None
        key: The key in the JSON response where the collection size should be checked
        collection_size: The expected size of the collection

    """

    if key:
        list_of_values = jsonpath(
            ctx.response.json(),
            CommonBehave.interpolate_context_attributes(ctx, key))
        if list_of_values:
            found_value = list_of_values[0]
            if isinstance(found_value, (dict, list)):
                if negate:
                    LOGGER.debug(
                        f"Checking that the JSON response at key: {key} should not have size: {collection_size}."
                    )
                    assert len(found_value) != int(collection_size), (
                        f"Expected the JSON value at key: {key} to not be a collection with size: {int(collection_size)},"
                        f" but we found: {len(found_value)} in the collection")
                    LOGGER.debug(
                        f"Validated that the JSON response at key: {key} did not have size: {collection_size}."
                    )
                else:
                    LOGGER.debug(
                        f"Checking that the JSON response at key: {key} should have size: {collection_size}."
                    )
                    assert len(found_value) == int(collection_size), (
                        f"Expected the JSON value at key: {key} to be a collection with size: {int(collection_size)},"
                        f" but we found: {len(found_value)} in the collection")
                    LOGGER.debug(
                        f"Validated that the JSON response at key: {key} did have size: {collection_size}."
                    )
            else:
                raise TypeError(
                    f"No dict or list found at key: '{key}'. We found: {type(found_value).__name__}"
                )
        else:
            raise KeyError(
                f"No key: '{key}' found in the JSON response: {ctx.response.json()}"
            )
    else:
        LOGGER.debug(
            f"Checking that the JSON response should have size: {collection_size}."
        )
        found_value = len(ctx.response.json())
        assert found_value == int(collection_size), (
            f"Expected the JSON value to be a collection with size: {int(collection_size)},"
            f" but we found: {found_value} in the collection")
        LOGGER.debug(
            f"Validated that the JSON response did have size: {collection_size}."
        )
def step_assert_rest_response_key(ctx: Context, negate: str, key: str) -> None:
    """Checks that the JSON response contains a given key.

    Args:
        ctx: The behave context
        negate: A string representing whether or not a response should be negated. If it should be negated, it will have
            a value 'not'. Otherwise, it will be None
        key: The key that should be present in the response

    """
    list_of_values = jsonpath(
        ctx.response.json(),
        CommonBehave.interpolate_context_attributes(ctx, f"$.{key}"),
    )
    if negate:
        LOGGER.debug(
            f"Checking that the JSON response should not include key: {key}.")
        assert (
            not list_of_values
        ), f"Expected no key to be found at '{key}', but it was present. Response: {ctx.response.text}"
        LOGGER.debug(
            f"Validated that the JSON response did not include key: {key}.")
    else:
        LOGGER.debug(
            f"Checking that the JSON response should include key: {key}.")
        assert (
            list_of_values
        ), f"Expected key to be found at '{key}', but it was not present. Response: {ctx.response.text}"
        LOGGER.debug(
            f"Validated that the JSON response did include key: {key}.")
def step_assert_rest_response_value(ctx: Context, key: str, negate: str,
                                    value: str) -> None:
    """Generic step definition that will read in a key using json path and traverse the json to find the value.

    Assertions are done based on the negate flag.
    Json path is a language that allows you to find values in json based on an expression.
    Find more info on json path here: https://restfulapi.net/json-jsonpath/.

    Args:
        ctx: behave context
        negate: type of assert. Either should be or should not be. represented by optional gherkin syntax = 'no'
        key: json path key expression
        value: the expected value in the assert

    """
    list_of_values = jsonpath(
        ctx.response.json(),
        CommonBehave.interpolate_context_attributes(ctx, key))
    desired_value = CommonBehave.interpolate_context_attributes(ctx, value)
    if list_of_values:
        found_value = str(list_of_values[0])

        if negate:
            LOGGER.debug(
                f"Checking that the JSON response at key: {key} should not be: {value}."
            )
            assert (
                found_value != desired_value
            ), f"Expected the JSON value at key: {key} to not be: {desired_value}, but we found: {found_value}"
            LOGGER.debug(
                f"Validated that the JSON response at key: {key} was not value: {value}"
            )
        else:
            LOGGER.debug(
                f"Checking that the JSON response at key: {key} should be: {value}."
            )
            assert (
                found_value == desired_value
            ), f"Expected the JSON value at key: {key} to be: {desired_value}, but we found: {found_value}"
            LOGGER.debug(
                f"Validated that the JSON response at key: {key} was value: {value}"
            )
    else:
        raise KeyError(
            f"No key: '{key}' found in the JSON response: {ctx.response.json()}"
        )
Exemple #8
0
def step_save_position_attribute_to_context(ctx: Context,
                                            key: str,
                                            value: str,
                                            json_key: str = None) -> None:
    """
    Attempts to obtain a key from the JSON response and set the value of that key to the behave context

    Args:
        ctx: The behave context
        key: The positional key that is being searched for
        value: The value the positional key should have
        json_key: The json key that indicates where the search for the positional key should occur

    """
    interpolated_key = CommonBehave.interpolate_context_attributes(ctx, key)
    interpolated_value = CommonBehave.interpolate_context_attributes(
        ctx, value)
    # Check if we are at the root of the json. If we are then use the '.' instead of the json key
    if json_key:
        list_of_values = jsonpath(ctx.response.json(), json_key)
    else:
        list_of_values = jsonpath(ctx.response.json(), ".")
    LOGGER.debug(
        f"Attempting to find position where key: {key} is value: {value} at: {list_of_values}."
    )
    if list_of_values:
        json_objects = list_of_values[0]
        for json_object in json_objects:
            if json_object[interpolated_key] == interpolated_value:
                setattr(ctx, "position", str(json_objects.index(json_object)))
                LOGGER.debug(
                    f"Successfully saved position as: {ctx.position} for key: {key} and value {value} at {list_of_values}."
                )
                break
        else:
            raise KeyError(
                f"No key: '{interpolated_key}' found in the dictionary: {json_object}"
            )
    else:
        raise KeyError(
            f"No collection found at '{json_key}' in the JSON response: {ctx.response.json()}"
        )
Exemple #9
0
def step_url_navigation(ctx: Context, endpoint: str) -> None:
    """
    Navigate to a page by it's url

    Args:
        ctx: The behave context
        endpoint: The url of the page without the base host name

    """
    LOGGER.debug(f"Attempting to navigate to {ctx.host}{endpoint}")
    endpoint = CommonBehave.interpolate_context_attributes(ctx, endpoint)
    ctx.driver.get(f"{ctx.host}{endpoint}")
    LOGGER.debug(f"Successfully navigated to {ctx.host}{endpoint}")
def step_assert_rest_response_data_type(ctx: Context, key: str, negate: str,
                                        data_type: str) -> None:
    """Checks that the key in the response is of the given data type.

    Args:
        ctx: The behave context
        key: The key in the response
        negate: A string representing whether or not a response should be negated. If it should be negated, it will have
            a value 'not'. Otherwise, it will be None
        data_type: The data type of the key

    """
    list_of_values = jsonpath(
        ctx.response.json(),
        CommonBehave.interpolate_context_attributes(ctx, f"$.{key}"),
    )
    if list_of_values:
        found_value = list_of_values[0]
        class_name = found_value.__class__.__name__
        if negate:
            LOGGER.debug(
                f"Checking that the JSON response at key: {key} should not have data type: {data_type}."
            )
            assert (
                class_name != data_type
            ), f"Expected the data type at key: '{key}' to not be '{data_type}', but we found: '{class_name}'"
            LOGGER.debug(
                f"Validated that the JSON response at key: {key} did not have data type: {data_type}."
            )
        else:
            LOGGER.debug(
                f"Checking that the JSON response at key: {key} should have data type: {data_type}."
            )
            assert (
                class_name == data_type
            ), f"Expected the data type at key: '{key}' to be '{data_type}', but we found: '{class_name}'"
            LOGGER.debug(
                f"Validated that the JSON response at key: {key} did have data type: {data_type}."
            )
    else:
        raise KeyError(
            f"No key: '{key}' found in the JSON response: {ctx.response.json()}"
        )
Exemple #11
0
def step_generic_json_dictionary(ctx: Context, value_name: str = None) -> None:
    """Sets the given table representing a request payload to an attribute in the behave context as a given name.

    Args:
        ctx: The behave context
        value_name: The name of the attribute in the behave context

    """
    LOGGER.debug(f"Attempting to save payload as: {value_name}.")
    payload: Dict[str, Union[str, int]] = {}
    for row in ctx.table:
        value = CommonBehave.interpolate_context_attributes(ctx, row[1])
        # If value is a digit .. cast to int
        if value.isdigit():
            payload[row[0]] = int(value)
        else:
            payload[row[0]] = value
    # If value_name is specified, set a context attribute with that name equal to the payload.
    # Else set ctx.request_data equal to the payload.
    if value_name:
        setattr(ctx, value_name, payload)
    else:
        ctx.request_data = payload
    LOGGER.debug(f"Successfully saved payload: {payload} as: {value_name}.")
Exemple #12
0
def step_set_request_header(ctx: Context, header: str,
                            header_value: str) -> None:
    """Sets a given type of request header to a given value.

    Args:
        ctx: The behave context
        header: The type of request header
        header_value: The value the request header should have

    """
    ctx.headers = {}
    desired_value = CommonBehave.interpolate_context_attributes(
        ctx, header_value)
    LOGGER.debug(
        f"Attempting to set request header: {header} to: {header_value}.")
    if desired_value.lower() in ("invalid", "empty", "empty string"):
        ctx.headers[header] = ""
    elif desired_value.lower() in ("none", "null"):
        ctx.headers[header] = None
    else:
        ctx.headers[header] = desired_value
    LOGGER.debug(
        f"Successfully set request header: {header} to: {ctx.headers[header]}."
    )