launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #29012
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