@@ -15446,15 +15446,15 @@ def test_finding_groups_status_pass_when_no_fail(
1544615446 # iam_password_policy has only PASS findings
1544715447 assert data[0]["attributes"]["status"] == "PASS"
1544815448
15449- def test_finding_groups_fully_muted_group_reflects_underlying_status (
15449+ def test_finding_groups_fully_muted_group_is_pass (
1545015450 self, authenticated_client, finding_groups_fixture
1545115451 ):
15452- """A fully-muted group still surfaces its underlying status (no MUTED) .
15452+ """A fully-muted group reports status=PASS and muted=True .
1545315453
15454- rds_encryption has 2 muted FAIL findings, so the group must report
15455- status=FAIL (the orthogonal `muted` boolean signals it isn't actionable).
15456- The status× muted breakdown lets clients answer 'how many failing
15457- findings are muted in this group' .
15454+ rds_encryption has 2 muted FAIL findings. Muted findings are treated
15455+ as resolved/accepted, so the group is no longer actionable and its
15456+ status must be PASS. The ` muted` flag is True because every finding
15457+ in the group is muted .
1545815458 """
1545915459 response = authenticated_client.get(
1546015460 reverse("finding-group-list"),
@@ -15464,7 +15464,7 @@ def test_finding_groups_fully_muted_group_reflects_underlying_status(
1546415464 data = response.json()["data"]
1546515465 assert len(data) == 1
1546615466 attrs = data[0]["attributes"]
15467- assert attrs["status"] == "FAIL "
15467+ assert attrs["status"] == "PASS "
1546815468 assert attrs["muted"] is True
1546915469 assert attrs["fail_count"] == 0
1547015470 assert attrs["fail_muted_count"] == 2
@@ -15479,6 +15479,83 @@ def test_finding_groups_fully_muted_group_reflects_underlying_status(
1547915479 == attrs["muted_count"]
1548015480 )
1548115481
15482+ def test_finding_groups_status_ignores_muted_failures(
15483+ self,
15484+ authenticated_client,
15485+ tenants_fixture,
15486+ scans_fixture,
15487+ resources_fixture,
15488+ ):
15489+ """Muted FAIL findings must not drive the aggregated status.
15490+
15491+ When a group mixes one non-muted PASS with one muted FAIL, the
15492+ actionable outcome is PASS: there are no unmuted failures left. The
15493+ aggregated `status` must reflect that (not FAIL), while `muted`
15494+ stays False because the group still has a non-muted finding.
15495+ """
15496+ tenant = tenants_fixture[0]
15497+ scan1, *_ = scans_fixture
15498+ resource1, *_ = resources_fixture
15499+
15500+ pass_finding = Finding.objects.create(
15501+ tenant_id=tenant.id,
15502+ uid="fg_mixed_muted_pass",
15503+ scan=scan1,
15504+ delta=None,
15505+ status=Status.PASS,
15506+ severity=Severity.low,
15507+ impact=Severity.low,
15508+ check_id="mixed_muted_check",
15509+ check_metadata={
15510+ "CheckId": "mixed_muted_check",
15511+ "checktitle": "Mixed muted check",
15512+ "Description": "Fixture for muted status aggregation.",
15513+ },
15514+ first_seen_at="2024-01-11T00:00:00Z",
15515+ muted=False,
15516+ )
15517+ pass_finding.add_resources([resource1])
15518+
15519+ fail_muted_finding = Finding.objects.create(
15520+ tenant_id=tenant.id,
15521+ uid="fg_mixed_muted_fail",
15522+ scan=scan1,
15523+ delta=None,
15524+ status=Status.FAIL,
15525+ severity=Severity.high,
15526+ impact=Severity.high,
15527+ check_id="mixed_muted_check",
15528+ check_metadata={
15529+ "CheckId": "mixed_muted_check",
15530+ "checktitle": "Mixed muted check",
15531+ "Description": "Fixture for muted status aggregation.",
15532+ },
15533+ first_seen_at="2024-01-12T00:00:00Z",
15534+ muted=True,
15535+ )
15536+ fail_muted_finding.add_resources([resource1])
15537+
15538+ # filter[region] forces finding-level aggregation so we exercise the
15539+ # raw-findings path without touching the daily summary fixture.
15540+ response = authenticated_client.get(
15541+ reverse("finding-group-list"),
15542+ {
15543+ "filter[inserted_at]": TODAY,
15544+ "filter[check_id]": "mixed_muted_check",
15545+ "filter[region]": "us-east-1",
15546+ },
15547+ )
15548+ assert response.status_code == status.HTTP_200_OK
15549+ data = response.json()["data"]
15550+ assert len(data) == 1
15551+ attrs = data[0]["attributes"]
15552+ assert attrs["status"] == "PASS"
15553+ assert attrs["muted"] is False
15554+ assert attrs["pass_count"] == 1
15555+ assert attrs["fail_count"] == 0
15556+ assert attrs["fail_muted_count"] == 1
15557+ assert attrs["muted_count"] == 1
15558+
1548215559 def test_finding_groups_status_filter(
1548315560 self, authenticated_client, finding_groups_fixture
1548415561 ):
0 commit comments