JiraCreateIssue-example

This script is used to simplify the process of creating a new Issue in Jira. You can specify custom fields using the `customFields` argument.

python · Atlassian Jira

Details

IDJiraCreateIssue-example
Languagepython
From Version5.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Tagsjira example

README

This script is used to simplify the process of creating a new Issue in Jira.
You can specify custom fields using the customFields argument.

Script Data


Name Description
Script Type python3
Tags jira, example
Cortex XSOAR Version 5.0.0

Dependencies


This script uses the following commands and scripts.

  • jira-create-issue

Used In


This script is used in the following playbooks and scripts.

  • Indeni Demo

Inputs


Argument Name Description
summary Summary of the issue, a mandatory field
projectKey Project key to associate the issue
issueTypeName Choose issue type by name - e.g. Problem
issueTypeId Choose issue type by its numeric ID
projectName Project name to associate the issue
description Issue description
labels comma separated list of labels
priority priority name, e.g. High/Medium.
dueDate Due date for the issue, in format YYYY-MM-DD
assignee assignee name
reporter reporter name
parentIssueKey Parent issue key if you create a sub-task
parentIssueId Parent issue ID if you create a sub-task
customFields Comma-separated custom field keys and values to include in the created incident, e.g. `customfield_10101=foo,customfield_10102=bar`

Outputs


Path Description Type
Ticket.Id Id of ticket Unknown
Ticket.Key Key of ticket Unknown
from typing import Any

import pytest
from JiraCreateIssueExample import add_custom_fields, parse_custom_fields, validate_date_field


@pytest.mark.parametrize("due_date", [("2022-01-01"), ("2023-01-31"), ("2024-02-29")])
def test_validate_date_field_data_remains(due_date: str):
    """
    Given:
        - A string representing a date in format '%Y-%m-%d'.

    When:
        - Case A: A valid string is in expected format and passed to `validate_date_field`
        - Case B: A valid string is in expected format and passed to `validate_date_field`
        - Case C: A leap year string is in expected format and passed to `validate_date_field`

    Then:
        - Case A: No exception is thrown.
        - Case B: No exception is thrown.
        - Case C: No exception is thrown.
    """

    validate_date_field(due_date)


@pytest.mark.parametrize("due_date", [("2022-31-31"), ("202-51-XY"), ("ABC")])
def test_validate_date_field_format(due_date: str):
    """
    Given:
        - An invalid string.

    When:
        - Case A: Attempting to validate the string with `validate_date_field` but it has an invalid month (31)
        - Case B: Attempting to validate the string with `validate_date_field` but it has an invalid month (51) and day(XY)
        - Case C: Attempting to validate the string with `validate_date_field` but it has invalid everything
    Then:
        - Case A: A `ValueError` exception is thrown.
        - Case B: A `ValueError` exception is thrown.
        - Case C: A `ValueError` exception is thrown.
    """

    with pytest.raises(ValueError, match=r"time data '(.*)' does not match format '%Y-%m-%d'"):
        raise validate_date_field(due_date)


@pytest.mark.parametrize("due_date", [("2022-12-12T13:00:00"), ("2022-12-12Z12")])
def test_validate_date_field_time_data_doesnt_match(due_date: str):
    """
    Given:
        - An invalid string.

    When:
        - Case A: Attempting to validate the string with `validate_date_field` but it has added time.
        - Case B: Attempting to validate the string with `validate_date_field` but it has added timezone.

    Then:
        - Case A: A `ValueError` exception is thrown.
        - Case B: A `ValueError` exception is thrown.
    """

    with pytest.raises(ValueError, match=r"unconverted data remains: "):
        raise validate_date_field(due_date)


@pytest.mark.parametrize(
    "custom_fields, expected",
    [
        (["customfield_10096=test"], {"customfield_10096": "test"}),
        (["customfield_10096=test", "customfield_10040=100"], {"customfield_10096": "test", "customfield_10040": 100}),
        (["customfield_10096=test", "customfield_10040=0100"], {"customfield_10096": "test", "customfield_10040": "0100"}),
        (["customfield_10096=test", "customfield_10040=A100"], {"customfield_10096": "test", "customfield_10040": "A100"}),
        (["customfield_10096:test", "customfield_10040=A100"], {"customfield_10040": "A100"}),
        (["customfield_10096==test", "customfield_10040=A100"], {"customfield_10040": "A100"}),
        ([], {}),
    ],
)
def test_parse_custom_fields(custom_fields: list[str], expected: dict[str, Any]):
    """
    Given:
        - A list of strings of custom fields.
        - An expected list of dicts of custom fields.

    When:
        - Case A: Passing a list of 1 string with text type custom field to `parse_custom_fields`.
        - Case B: Passing a list of 2 strings, one with text type custom field, one with integer type custom field into
        `parse_custom_fields`.
        - Case C: Passing a list of 2 strings, one with text type custom field, one with integer type custom field with 0
        padding into `parse_custom_fields`.
        - Case D: Passing a list of 2 strings of text type custom fields into `parse_custom_fields`.
        - Case E: Passing a list of 2 strings of 1 text type custom field, 1 custom field with unexpected delimiter (:).
        - Case F: Passing a list of 1 string wit text type custom field, 1 custom field with unexpected delimiter (==).
        - Case G: Passing an empty list.

    Then:
        - Case A: A dictionary with 1 attribute is returned.
        - Case B: A dictionary with 1 attribute field, 1 integer custom field is returned.
        - Case C: A dictionary with 2 attributes fields is returned.
        - Case D: A dictionary with 2 attributes fields is returned.
        - Case E: A dictionary with 1 attribute field is returned.
        - Case F: A dictionary with 1 attribute field is returned.
        - Case G: An empty dictionary is returned.
    """

    actual = parse_custom_fields(custom_fields)
    assert actual == expected


@pytest.mark.parametrize(
    "args, custom_fields, expected",
    [
        (
            {"arg1": "val1", "arg2": 1},
            {"customfield_10096": "test", "customfield_10040": 100},
            {"arg1": "val1", "arg2": 1, "issueJson": {"fields": {"customfield_10096": "test", "customfield_10040": 100}}},
        ),
        (
            {},
            {"customfield_10096": "test", "customfield_10040": 100},
            {"issueJson": {"fields": {"customfield_10096": "test", "customfield_10040": 100}}},
        ),
    ],
)
def test_add_custom_fields(args: dict[str, Any], custom_fields: dict[str, Any], expected):
    """
    Given:
        - A dictionary of arguments.
        - A dictionary representing custom fields.
        - An expected dictionary result.

    When:
        - Case A: Passing a dictionary with 2 attributes and another dictionary with 2 attributes into `add_custom_fields`.
        - Case B: Passing a dictionary with 2 attributes and an empty dictionary into `add_custom_fields`.
        - Case C: Passing a empty dictionary and another one with 2 attributes into `add_custom_fields`.
    Then:
        - Case A: The resulting dictionary will have 4 attributes with `issueJson` root.
        - Case B: The resulting dictionary will be identical to the first one supplied.
        - Case C: The resulting dictionary will have 2 attributes with `issueJson` root.
    """

    actual = add_custom_fields(args, custom_fields)

    assert actual == expected