# -*- coding: utf-8 -*- # Copyright 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License") # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import testing_config from unittest import mock from unittest import skip from internals.link_helpers import ( Link, LINK_TYPE_CHROMIUM_BUG, LINK_TYPE_GITHUB_ISSUE, LINK_TYPE_GITHUB_MARKDOWN, LINK_TYPE_WEB, LINK_TYPE_MDN_DOCS, LINK_TYPE_GOOGLE_DOCS, LINK_TYPE_MOZILLA_BUG, LINK_TYPE_SPECS, valid_url ) class LinkHelperTest(testing_config.CustomTestCase): def test_specs_url(self): urls = [ "https://w3c.github.io/presentation-api/", "https://www.w3.org/TR/css-pseudo-4/#highlight-pseudos", "https://dev.w3.org/html5/spec-LC/the-button-element.html", "https://drafts.csswg.org/css-conditional-4/#support-definition-ext", "https://drafts.csswg.org/css-values-3/#position", "https://dom.spec.whatwg.org/#validate", "https://html.spec.whatwg.org/multipage/webappapis.html", "https://wicg.github.io/keyboard-map/#layoutchange-event", ] for url in urls: with self.subTest(url=url): link = Link(url) self.assertEqual(link.type, LINK_TYPE_SPECS) self.assertEqual(link.url, url) def test_mozilla_bug(self): link = Link("https://bugzilla.mozilla.org/show_bug.cgi?id=1314686") link.parse() self.assertEqual(link.type, LINK_TYPE_MOZILLA_BUG) self.assertTrue(link.is_parsed) self.assertFalse(link.is_error) self.assertIsNotNone(link.information.get('title')) self.assertIsNotNone(link.information.get('description')) def test_google_docs_url(self): link = Link("https://docs.google.com/document/d/1-M_o-il38aW64Gyk4R23Yaxy1p2Uy7D0i6J5qTWzypU") link.parse() self.assertEqual(link.type, LINK_TYPE_GOOGLE_DOCS) self.assertTrue(link.is_parsed) self.assertFalse(link.is_error) self.assertIsNotNone(link.information.get('title')) def test_mdn_docs_url(self): link = Link("https://developer.mozilla.org/en-US/docs/Web/HTML") link.parse() self.assertEqual(link.type, LINK_TYPE_MDN_DOCS) self.assertEqual(link.url, "https://developer.mozilla.org/en-US/docs/Web/HTML") self.assertTrue(link.is_parsed) self.assertFalse(link.is_error) self.assertIsNotNone(link.information.get('title')) self.assertIsNotNone(link.information.get('description')) def test_valid_url(self): invalid_urls = [ 'http://', 'http://.', 'https://invalid', ] valid_urls = [ 'http://www.google.com/', 'https://www.google.com/', 'http://www.google.com', 'https://www.google.com', ] for url in invalid_urls: with self.subTest(url=url): self.assertFalse(valid_url(url)) for url in valid_urls: with self.subTest(url=url): self.assertTrue(valid_url(url)) @mock.patch('requests.get') def test_mock_not_found_url(self, mock_requests_get): mock_requests_get.return_value = testing_config.Blank( status_code=404, content='') link = Link("https://www.google.com/") link.parse() self.assertEqual(link.type, LINK_TYPE_WEB) self.assertEqual(link.is_error, True) self.assertEqual(link.http_error_code, 404) def test_extract_urls_from_value(self): field_value = "https://www.chromestatus.com/feature/1234" urls = Link.extract_urls_from_value(field_value) self.assertEqual(urls, [field_value]) field_value = "https://w3c.github.io/presentation-api/" urls = Link.extract_urls_from_value(field_value) self.assertEqual(urls, [field_value]) field_value = "leadinghttps:https://www.chromestatus.com/feature/1234');, https://www.chromestatus.com/feature/5678 is valid" urls = Link.extract_urls_from_value(field_value) self.assertEqual(urls, ["https://www.chromestatus.com/feature/1234", "https://www.chromestatus.com/feature/5678"]) field_value = ["https://www.chromestatus.com/feature/1234", "not a valid urlhttps://www.chromestatus.com/feature/", None] urls = Link.extract_urls_from_value(field_value) self.assertEqual(urls, ["https://www.chromestatus.com/feature/1234"]) def test_link_github_markdown(self): urls_to_test = [ "https://github.com/w3c/reporting/blob/master/EXPLAINER.md#crashes", "https://github.com/tc39/proposal-logical-assignment/blob/master/README.md", "https://github.com/w3c/reporting/blob/7984341ce9554473fc9487001b169703e9871811/EXPLAINER.md" ] for url in urls_to_test: link = Link(url) self.assertEqual(link.type, LINK_TYPE_GITHUB_MARKDOWN) def test_link_parse_github_markdown_with_renamed_branch(self): # master branch is renamed to main link = Link( "https://github.com/w3c/reporting/blob/master/EXPLAINER.md") link.parse() if link.is_error and "rate limit" in str(link.error): return info = link.information self.assertEqual(link.type, LINK_TYPE_GITHUB_MARKDOWN) self.assertEqual(link.is_parsed, True) self.assertEqual(info["_parsed_title"], "Reporting API") print(info) def test_link_parse_github_markdown_with_hash(self): link = Link( "https://github.com/vmpstr/web-proposals/blob/b146b4447b3746669000f1abbb5a19d32f508540/explainers/cv-auto-event.md") link.parse() if link.is_error and "rate limit" in str(link.error): return info = link.information self.assertEqual(link.type, LINK_TYPE_GITHUB_MARKDOWN) self.assertEqual(link.is_parsed, True) self.assertEqual(info["_parsed_title"], "CSS `content-visibility` state change event") def test_link_github_issue(self): urls_to_test = [ "https://github.com/GoogleChrome/chromium-dashboard/issues/999", "https://www.github.com/GoogleChrome/chromium-dashboard/issues/999", "https://www.github.com/GoogleChrome/chromium-dashboard/issues/999?params=1#issuecomment-688970447", ] for url in urls_to_test: link = Link(url) self.assertEqual(link.type, LINK_TYPE_GITHUB_ISSUE) def test_link_non_github_issue(self): urls_to_test = [ "https://fakegithub.com/GoogleChrome/chromium-dashboard/issues/999", "https://www.github.com/GoogleChrome/chromium-dashboard/issues/", ] for url in urls_to_test: link = Link(url) self.assertNotEqual(link, LINK_TYPE_GITHUB_ISSUE) def test_parse_github_issue(self): link = Link( "https://www.github.com/GoogleChrome/chromium-dashboard/issues/999?params=1#issuecomment-688970447" ) link.parse() if link.is_error and "rate limit" in str(link.error): return info = link.information self.assertEqual(link.type, LINK_TYPE_GITHUB_ISSUE) self.assertEqual(link.is_parsed, True) self.assertEqual(info["title"], "Comments field is incorrectly escaped") self.assertEqual(info["state"], "closed") self.assertEqual(info["state_reason"], "completed") self.assertEqual(info["created_at"], "2020-09-03T18:29:42Z") self.assertEqual(info["closed_at"], "2020-12-01T21:50:57Z") self.assertEqual(info["labels"], ["bug"]) @mock.patch("logging.error") def test_parse_github_issue_fail_wrong_id_or_no_permission(self, mock_error): link = Link( "https://www.github.com/GoogleChrome/chromium-dashboard/issues/100000000000000" ) link.parse() self.assertEqual(link.type, LINK_TYPE_GITHUB_ISSUE) self.assertEqual(link.is_parsed, True) self.assertEqual(link.is_error, True) self.assertEqual(link.http_error_code, 404) def test_link_code_google(self): link = Link("https://code.google.com/p/chromium/issues/detail?id=515786") self.assertEqual(link.type, LINK_TYPE_CHROMIUM_BUG) def test_link_crbug(self): link = Link("https://crbug.com/1352598") self.assertEqual(link.type, LINK_TYPE_CHROMIUM_BUG) def test_link_chromium(self): link = Link("https://bugs.chromium.org/p/chromium/issues/detail?id=100000") self.assertEqual(link.type, LINK_TYPE_CHROMIUM_BUG) def test_link_non_chromium(self): link = Link("https://bugs0chromium.org/p/chromium/issues/detail?id=100000") self.assertNotEqual(link.type, LINK_TYPE_CHROMIUM_BUG) @skip('Until issues.chromium.org has an API') def test_parse_chromium_tracker(self): link = Link("https://bugs.chromium.org/p/chromium/issues/detail?id=100000") link.parse() info = link.information self.assertEqual(link.type, LINK_TYPE_CHROMIUM_BUG) self.assertEqual(link.is_parsed, True) self.assertEqual(info["summary"], "Repeated zooms leave tearing artifact") self.assertEqual(info["statusRef"]["status"], "Fixed") self.assertEqual(info["ownerRef"]["displayName"], "backer@chromium.org") @skip('Until issues.chromium.org has an API') @mock.patch("logging.error") def test_parse_chromium_tracker_fail_wrong_id(self, mock_error): link = Link( "https://bugs.chromium.org/p/chromium/issues/detail?id=100000000000000" ) link.parse() self.assertEqual(link.type, LINK_TYPE_CHROMIUM_BUG) self.assertEqual(link.is_parsed, True) self.assertEqual(link.is_error, True) self.assertEqual(link.information, None) @skip('Until issues.chromium.org has an API') @mock.patch("logging.error") def test_parse_chromium_tracker_fail_no_permission(self, mock_error): link = Link("https://bugs.chromium.org/p/chromium/issues/detail?id=1") link.parse() self.assertEqual(link.type, LINK_TYPE_CHROMIUM_BUG) self.assertEqual(link.is_parsed, True) self.assertEqual(link.is_error, True) self.assertEqual(link.information, None) def test_extract_invalid_url(self): urls = Link.extract_urls_from_value('Some kind of https://... link.') self.assertEqual(len(urls), 0)