Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LO100 validator for dynamic layout sections #4792

Merged
merged 18 commits into from
Feb 5, 2025
Merged
4 changes: 4 additions & 0 deletions .changelog/4792.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
changes:
- description: Added LO100 new validation. The validation verify of script names when used in the dynamic section of the layout.
type: feature
pr_number: 4792
4 changes: 3 additions & 1 deletion demisto_sdk/commands/validate/sdk_validation_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ select = [
"IN162",
"IN163",
"LO107",
"LO100",
"PB100",
"PB101",
"PB103",
Expand Down Expand Up @@ -515,6 +516,7 @@ select = [
"RN114",
"RN115",
"RN116",
"TR100"
"TR100",
"LO100"
]
warning = []
309 changes: 309 additions & 0 deletions demisto_sdk/commands/validate/test_files/invalid_layoutscontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
{
"detailsV2": {
"tabs": [
{
"id": "summary",
"name": "Legacy Summary",
"type": "summary"
},
{
"hidden": false,
"id": "zmjvpqxkcs",
"name": "XDR Device Control Violations",
"sections": [
{
"displayType": "ROW",
"h": 2,
"hideName": false,
"i": "zmjvpqxkcs-1vduzkpmlh-fce71720-98b0-11e9-97d7-ed26ef9e46c8",
"isVisible": true,
"items": [
{
"dropEffect": "move",
"endCol": 2,
"fieldId": "type",
"height": 22,
"id": "1cc0c4a0-9bd7-11e9-ba23-8723b1f1df6b",
"index": 0,
"listId": "fce71720-98b0-11e9-97d7-ed26ef9e46c8",
"sectionItemType": "field",
"startCol": 0
},
{
"endCol": 2,
"fieldId": "dbotsource",
"height": 22,
"id": "87e18ad0-9bd7-11e9-ba23-8723b1f1df6b",
"index": 1,
"sectionItemType": "field",
"startCol": 0
},
{
"endCol": 2,
"fieldId": "sourceinstance",
"height": 22,
"id": "43cfe2d0-9bee-11e9-9a3f-8b4b2158e260",
"index": 2,
"sectionItemType": "field",
"startCol": 0
},
{
"dropEffect": "move",
"endCol": 2,
"fieldId": "severity",
"height": 22,
"id": "20430d90-9bd7-11e9-ba23-8723b1f1df6b",
"index": 3,
"listId": "fce71720-98b0-11e9-97d7-ed26ef9e46c8",
"sectionItemType": "field",
"startCol": 0
},
{
"endCol": 2,
"fieldId": "playbookid",
"height": 22,
"id": "930bb7a0-a866-11e9-aeb8-c3448b5d692d",
"index": 4,
"sectionItemType": "field",
"startCol": 0
},
{
"dropEffect": "move",
"endCol": 2,
"fieldId": "sourcebrand",
"height": 22,
"id": "42f03130-9bee-11e9-9a3f-8b4b2158e260",
"index": 5,
"listId": "fce71720-98b0-11e9-97d7-ed26ef9e46c8",
"sectionItemType": "field",
"startCol": 0
},
{
"dropEffect": "move",
"endCol": 2,
"fieldId": "owner",
"height": 22,
"id": "4fd2b640-a7d6-11e9-8433-9f52f2917950",
"index": 7,
"listId": "fce71720-98b0-11e9-97d7-ed26ef9e46c8",
"sectionItemType": "field",
"startCol": 0
}
],
"maxH": null,
"maxW": 1,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Case Details",
"static": false,
"w": 1,
"x": 0,
"y": 0
},
{
"displayType": "ROW",
"h": 2,
"hideName": false,
"i": "zmjvpqxkcs-1vduzkpmlh-61263cc0-98b1-11e9-97d7-ed26ef9e46c8",
"isVisible": true,
"items": [

],
"maxH": null,
"maxW": 1,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Notes",
"readOnly": true,
"static": false,
"type": "notes",
"w": 1,
"x": 0,
"y": 2
},
{
"columns": [
{
"displayed": true,
"isDefault": false,
"key": "id",
"width": 110
},
{
"displayed": true,
"isDefault": true,
"key": "name",
"width": 300
},
{
"displayed": true,
"isDefault": false,
"key": "owner",
"width": 160
},
{
"displayed": true,
"isDefault": true,
"key": "type",
"width": 200
},
{
"displayed": true,
"isDefault": true,
"key": "status",
"width": 80
},
{
"displayed": true,
"isDefault": true,
"key": "closeNotes",
"width": 300
}
],
"displayType": "ROW",
"h": 1,
"hideName": false,
"i": "zmjvpqxkcs-1vduzkpmlh-770ec200-98b1-11e9-97d7-ed26ef9e46c8",
"isVisible": true,
"items": [

],
"maxH": null,
"maxW": 1,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Linked Incidents",
"readOnly": true,
"static": false,
"type": "linkedIncidents",
"w": 1,
"x": 1,
"y": 4
},
{
"displayType": "ROW",
"h": 1,
"hideName": false,
"i": "zmjvpqxkcs-1vduzkpmlh-842632c0-98b1-11e9-97d7-ed26ef9e46c8",
"isVisible": true,
"items": [

],
"maxH": null,
"maxW": 1,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Child Incidents",
"readOnly": true,
"static": false,
"query": "TestScript",
"type": "childInv",
"w": 1,
"x": 0,
"y": 4
},
{
"h": 2,
"hideName": false,
"i": "zmjvpqxkcs-1vduzkpmlh-5cc7f260-ad4f-11e9-a2d3-c520aeb407da",
"items": [

],
"maxH": null,
"maxW": 1,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Affected Hosts Count",
"query": "TestScript2",
"queryType": "script",
"static": false,
"type": "dynamic",
"w": 1,
"x": 2,
"y": 2
},
{
"h": 2,
"hideName": false,
"i": "zmjvpqxkcs-1vduzkpmlh-11cd1fd0-ad52-11e9-a2d3-c520aeb407da",
"items": [

],
"maxH": null,
"maxW": 1,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Affected Users Count",
"query": "612ad420-04a9-11eb-ba3b-5h42d710bdf4",
"queryType": "script",
"static": false,
"type": "dynamic",
"w": 1,
"x": 2,
"y": 0
},
{
"displayType": "ROW",
"h": 4,
"hideName": false,
"i": "zmjvpqxkcs-3f818d20-49e7-11eb-ba3b-2d79d330bdf4",
"items": [
{
"endCol": 2,
"fieldId": "xdrdevicecontrolviolations",
"height": 106,
"id": "475ad420-49e7-11eb-ba3b-2d79d330bdf4",
"index": 0,
"sectionItemType": "field",
"startCol": 0
}
],
"maxW": 3,
"minH": 1,
"minW": 1,
"moved": false,
"name": "Device Control Violations",
"static": false,
"w": 1,
"x": 1,
"y": 0
}
],
"type": "custom"
},
{
"id": "warRoom",
"name": "War Room",
"type": "warRoom"
},
{
"id": "workPlan",
"name": "Work Plan",
"type": "workPlan"
},
{
"id": "evidenceBoard",
"name": "Evidence Board",
"type": "evidenceBoard"
},
{
"id": "relatedIncidents",
"name": "Related Incidents",
"type": "relatedIncidents"
}
]
},
"group": "incident",
"id": "Cortex XDR Device Control Violations",
"name": "Cortex XDR Device Control Violations",
"system": false,
"version": -1,
"fromVersion": "6.0.0",
"description": ""
}
52 changes: 51 additions & 1 deletion demisto_sdk/commands/validate/tests/LO_validators_test.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
from typing import List
from pathlib import Path
from typing import List, cast

import pytest

from demisto_sdk.commands.common.constants import MarketplaceVersions
from demisto_sdk.commands.common.legacy_git_tools import git_path
from demisto_sdk.commands.content_graph.objects.base_content import BaseContent
from demisto_sdk.commands.content_graph.objects.layout import Layout
from demisto_sdk.commands.content_graph.tests.test_tools import load_json
from demisto_sdk.commands.validate.tests.test_tools import create_layout_object
from demisto_sdk.commands.validate.validators.base_validator import BaseValidator
from demisto_sdk.commands.validate.validators.LO_validators.LO100_validate_dynamic_section import (
IsValidDynamicSectionValidator,
)
from demisto_sdk.commands.validate.validators.LO_validators.LO107_is_valid_type import (
IsValidTypeValidator,
)
from TestSuite.repo import Repo


@pytest.mark.parametrize(
Expand Down Expand Up @@ -112,3 +122,43 @@ def test_IsValidTypeValidator_returns_no_failures_after_removal_of_MarketplaceV2
assert not IsValidTypeValidator().obtain_invalid_content_items(
[layout_object]
), "Expected validation to pass after removal of MarketplaceV2"


@pytest.fixture
def repo_for_test_layout(graph_repo):
pack_1 = graph_repo.create_pack("Pack1")
invalid_layout_object = f"{git_path()}/demisto_sdk/commands/validate/test_files/invalid_layoutscontainer.json"
json_content = load_json(invalid_layout_object)
pack_1.create_layout(name="layout", content=json_content)
pack_1.create_script("TestScript")

return graph_repo


def test_IsValidDynamicSectionValidator_script_not_found(
repo_for_test_layout: Repo,
):
"""
Given
Invalid layout object with 2 invalid sections - one contains query with UUID and the other contains query with unknown script name.
When
the IsValidDynamicSectionValidator's obtain_invalid_content_items method is called with the layout object,
Then
the obtain_invalid_content_items method should return 2 failures, one for invalid query with UUID and the other for unknown script name.
"""
graph_interface = repo_for_test_layout.create_graph()
BaseValidator.graph_interface = graph_interface
layout_object = cast(
Layout,
BaseContent.from_path(Path(repo_for_test_layout.packs[0].layouts[0].path)),
)
results = IsValidDynamicSectionValidator().obtain_invalid_content_items(
content_items=[layout_object]
)
assert (
results[0].message
== "The tab XDR Device Control Violations contains the following script that not exists in the repo: TestScript2."
)
results[
1
].message == "The tab XDR Device Control Violations contains UUID value: 612ad420-04a9-11eb-ba3b-5h42d710bdf4 in the query field, please change it to valid script name."
Loading
Loading