← Back to team overview

launchpad-reviewers team mailing list archive

Re: [Merge] ~lgp171188/launchpad:vulnerability-ui into launchpad:master

 

The screenshots illustrating this UI change are:

1. Vulnerability with a linked CVE and an associated bug.

https://people.canonical.com/~guruprasad/vulnerability_with_cve_and_bugs.png

The page title for this is something like "Bugs : Vulnerability CVE-1234-5678 : <distribution name>".

2. Vulnerability without a linked CVE and any associated bugs.

https://people.canonical.com/~guruprasad/vulnerability_without_any_links.png

The page title for this is something like "Bugs : Vulnerability #<vulnerability.id> : <distribution name>".

Diff comments:

> diff --git a/lib/lp/bugs/browser/tests/test_cve.py b/lib/lp/bugs/browser/tests/test_cvereport.py
> similarity index 100%
> rename from lib/lp/bugs/browser/tests/test_cve.py
> rename to lib/lp/bugs/browser/tests/test_cvereport.py
> diff --git a/lib/lp/bugs/browser/tests/test_vulnerability.py b/lib/lp/bugs/browser/tests/test_vulnerability.py
> new file mode 100644
> index 0000000..eac7e06
> --- /dev/null
> +++ b/lib/lp/bugs/browser/tests/test_vulnerability.py
> @@ -0,0 +1,246 @@
> +# Copyright 2022 Canonical Ltd.  This software is licensed under the
> +# GNU Affero General Public License version 3 (see the file LICENSE).
> +
> +"""Vulnerability browser tests"""
> +from datetime import datetime, timezone
> +
> +from soupmatchers import HTMLContains, Tag, Within
> +from testtools.matchers import MatchesAll, Not
> +
> +from lp.services.webapp import canonical_url
> +from lp.testing import ANONYMOUS, BrowserTestCase, login, person_logged_in
> +from lp.testing.layers import DatabaseFunctionalLayer
> +
> +
> +class TestVulnerabilityPage(BrowserTestCase):
> +    """Tests for the vulnerability browser page."""
> +
> +    layer = DatabaseFunctionalLayer
> +
> +    def get_vulnerability_field_tag(self, name, text, element="span"):
> +        return Tag(
> +            name,
> +            element,
> +            attrs={"id": "-".join(name.lower().split())},
> +            text=text,
> +        )
> +
> +    def test_page_title_vulnerability_without_linked_cve(self):
> +        vulnerability = self.factory.makeVulnerability()
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        login(ANONYMOUS)
> +        self.assertThat(
> +            browser.contents,
> +            HTMLContains(
> +                Tag(
> +                    "page title",
> +                    "title",
> +                    text="Bugs : Vulnerability #{} : {}".format(
> +                        vulnerability.id,
> +                        vulnerability.distribution.displayname,
> +                    ),
> +                )
> +            ),
> +        )
> +
> +    def test_page_title_vulnerability_with_linked_cve(self):
> +        cve = self.factory.makeCVE(sequence="2022-1234")
> +        vulnerability = self.factory.makeVulnerability(cve=cve)
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        login(ANONYMOUS)
> +        self.assertThat(
> +            browser.contents,
> +            HTMLContains(
> +                Tag(
> +                    "page title",
> +                    "title",
> +                    text="Bugs : Vulnerability CVE-2022-1234 : {}".format(
> +                        vulnerability.distribution.displayname
> +                    ),
> +                )
> +            ),
> +        )
> +
> +    def test_vulnerability_page_contains_all_expected_fields(self):
> +        vulnerability = self.factory.makeVulnerability()
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        fields = (
> +            "Date created",
> +            "Date made public",
> +            "CVE",
> +            "Information type",
> +            "Status",
> +            "Importance",
> +            "Importance explanation",
> +            "Creator",
> +            "Notes",
> +            "Mitigation",
> +        )
> +        matchers = []
> +        for field in fields:
> +            matchers.append(
> +                HTMLContains(Tag(field, "b", text="{}:".format(field)))
> +            )
> +        self.assertThat(browser.contents, MatchesAll(*matchers))
> +
> +    def test_vulnerability_page_default_values(self):
> +        vulnerability = self.factory.makeVulnerability()
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        login(ANONYMOUS)
> +        self.assertThat(
> +            browser.contents,
> +            MatchesAll(
> +                HTMLContains(
> +                    self.get_vulnerability_field_tag(
> +                        "Date created",
> +                        vulnerability.date_created.strftime("%Y-%m-%d"),
> +                    ),
> +                    self.get_vulnerability_field_tag(
> +                        "Date made public", "None"
> +                    ),
> +                    self.get_vulnerability_field_tag("CVE", "None"),
> +                    self.get_vulnerability_field_tag(
> +                        "Information type",
> +                        vulnerability.information_type.title,
> +                    ),
> +                    self.get_vulnerability_field_tag(
> +                        "Status", vulnerability.status.title
> +                    ),
> +                    self.get_vulnerability_field_tag(
> +                        "Importance", vulnerability.importance.title
> +                    ),
> +                    self.get_vulnerability_field_tag(
> +                        # importance_explanation defaults to `None` but the
> +                        # factory
> +                        # method auto-generates a value for it.
> +                        "Importance explanation",
> +                        vulnerability.importance_explanation,
> +                    ),
> +                    Within(
> +                        Tag("Creator", "span", attrs={"id": "creator"}),
> +                        Tag(
> +                            "Creator link",
> +                            "a",
> +                            attrs={
> +                                "href": canonical_url(vulnerability.creator),
> +                                "class": "sprite person",
> +                            },
> +                            text=vulnerability.creator.displayname,
> +                        ),
> +                    ),
> +                    self.get_vulnerability_field_tag("Notes", "None"),
> +                    self.get_vulnerability_field_tag("Mitigation", "None"),
> +                ),
> +                Not(
> +                    HTMLContains(
> +                        Tag(
> +                            "Related bugs", "div", attrs={"id": "related-bugs"}
> +                        )
> +                    )
> +                ),
> +            ),
> +        )
> +
> +    def test_vulnerability_cve_linked(self):
> +        cve = self.factory.makeCVE(sequence="2022-1234")
> +        vulnerability = self.factory.makeVulnerability(cve=cve)
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        login(ANONYMOUS)
> +        self.assertThat(
> +            browser.contents,
> +            HTMLContains(
> +                Within(
> +                    Tag(
> +                        "CVE",
> +                        "span",
> +                        attrs={"id": "cve"},
> +                    ),
> +                    Tag(
> +                        "CVE link",
> +                        "a",
> +                        attrs={
> +                            "href": canonical_url(cve, force_local_path=True)
> +                        },
> +                    ),
> +                )
> +            ),
> +        )
> +
> +    def test_vulnerability_optional_parameters_set(self):
> +        vulnerability = self.factory.makeVulnerability(
> +            date_made_public=datetime(1970, 1, 1, tzinfo=timezone.utc),
> +            notes="These are some notes",
> +            mitigation="Here is a mitigation",
> +        )
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        login(ANONYMOUS)
> +        self.assertThat(
> +            browser.contents,
> +            HTMLContains(
> +                self.get_vulnerability_field_tag(
> +                    "Date made public",
> +                    vulnerability.date_made_public.strftime("%Y-%m-%d"),
> +                ),
> +                self.get_vulnerability_field_tag(
> +                    "Notes", "These are some notes"
> +                ),
> +                self.get_vulnerability_field_tag(
> +                    "Mitigation", "Here is a mitigation"
> +                ),
> +            ),
> +        )
> +
> +    def test_vulnerability_related_bugs_present(self):
> +        vulnerability = self.factory.makeVulnerability()
> +        bug1 = self.factory.makeBug()
> +        bug2 = self.factory.makeBug()
> +        with person_logged_in(vulnerability.distribution.owner):
> +            vulnerability.linkBug(bug1)
> +            vulnerability.linkBug(bug2)
> +        browser = self.getUserBrowser(
> +            canonical_url(vulnerability),
> +            user=self.factory.makePerson(),
> +        )
> +        login(ANONYMOUS)
> +        self.assertThat(
> +            browser.contents,
> +            HTMLContains(

This doesn't test the table rows corresponding to the bugtasks in each of the bugs because doing that felt a bit too much in the context of this page since it is just reusing an existing renderer from somewhere else. So let me know if I should still add checks for those.

> +                Tag("Related bugs", "div", attrs={"id": "related-bugs"}),
> +                Tag(
> +                    "Bug #{}".format(bug1.id),
> +                    "a",
> +                    attrs={
> +                        "class": "sprite bug",
> +                        "href": canonical_url(bug1, force_local_path=True),
> +                    },
> +                    text="Bug #{}: {}".format(bug1.id, bug1.title),
> +                ),
> +                Tag(
> +                    "Bug #{}".format(bug2.id),
> +                    "a",
> +                    attrs={
> +                        "class": "sprite bug",
> +                        "href": canonical_url(bug2, force_local_path=True),
> +                    },
> +                    text="Bug #{}: {}".format(bug2.id, bug2.title),
> +                ),
> +            ),
> +        )


-- 
https://code.launchpad.net/~lgp171188/launchpad/+git/launchpad/+merge/428481
Your team Launchpad code reviewers is requested to review the proposed merge of ~lgp171188/launchpad:vulnerability-ui into launchpad:master.



References