Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/redirect/test/__init__.py b/redirect/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/redirect/test/__init__.py
diff --git a/redirect/test/redirect_custom_value_test.py b/redirect/test/redirect_custom_value_test.py
new file mode 100644
index 0000000..d3d70ed
--- /dev/null
+++ b/redirect/test/redirect_custom_value_test.py
@@ -0,0 +1,62 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from google.appengine.ext import ndb
+from google.appengine.ext import testbed
+from redirect import redirect_custom_value
+
+
+class TestRedirectCustomValue(unittest.TestCase):
+
+  def setUp(self):
+    self.testbed = testbed.Testbed()
+    self.testbed.activate()
+    self.testbed.init_datastore_v3_stub()
+    self.testbed.init_memcache_stub()
+    ndb.get_context().clear_cache()
+
+  def tearDown(self):
+    self.testbed.deactivate()
+
+  def testGetRedirectCustomValue(self):
+    redirectCustomValue = redirect_custom_value.RedirectCustomValue
+    redirectCustomValue(
+        ProjectName='a',
+        MonorailType='test',
+        MonorailValue='a',
+        RedirectType='t',
+        RedirectValue='v').put()
+
+    (t, v) = redirectCustomValue.Get('a', 'test', 'a')
+    self.assertEqual(t, 't')
+    self.assertEqual(v, 'v')
+
+  def testGetRedirectCustomValueWithoutValue(self):
+    redirectCustomValue = redirect_custom_value.RedirectCustomValue
+
+    (t, v) = redirectCustomValue.Get('a', 'test', 'a')
+    self.assertEqual(t, None)
+    self.assertEqual(v, None)
+
+  def testGetRedirectCustomValueOnlyReturnTheFirstMatch(self):
+    # There should be only one match in db.
+    # This may change if we decided to support mutiple value mapping.
+    redirectCustomValue = redirect_custom_value.RedirectCustomValue
+    redirectCustomValue(
+        ProjectName='a',
+        MonorailType='test',
+        MonorailValue='a',
+        RedirectType='t1',
+        RedirectValue='v1').put()
+    redirectCustomValue(
+        ProjectName='a',
+        MonorailType='test',
+        MonorailValue='a',
+        RedirectType='t2',
+        RedirectValue='v2').put()
+    (t, v) = redirectCustomValue.Get('a', 'test', 'a')
+    self.assertEqual(t, 't1')
+    self.assertEqual(v, 'v1')
diff --git a/redirect/test/redirect_project_template_test.py b/redirect/test/redirect_project_template_test.py
new file mode 100644
index 0000000..13995c7
--- /dev/null
+++ b/redirect/test/redirect_project_template_test.py
@@ -0,0 +1,42 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from google.appengine.ext import ndb
+from google.appengine.ext import testbed
+from redirect import redirect_project_template
+
+
+class TestRedirectCustomValue(unittest.TestCase):
+
+  def setUp(self):
+    self.testbed = testbed.Testbed()
+    self.testbed.activate()
+    self.testbed.init_datastore_v3_stub()
+    self.testbed.init_memcache_stub()
+    ndb.get_context().clear_cache()
+
+  def tearDown(self):
+    self.testbed.deactivate()
+
+  def testGetRedirectProjectTemplate(self):
+    redirectProjectTemplate = redirect_project_template.RedirectProjectTemplate
+    redirectProjectTemplate(
+        ProjectName='a',
+        MonorailTemplateName='default template',
+        RedirectComponentID='123',
+        RedirectTemplateID='456',
+        id='a:default template').put()
+
+    (t, v) = redirectProjectTemplate.Get('a', 'default template')
+    self.assertEqual(t, '123')
+    self.assertEqual(v, '456')
+
+  def testGetRedirectProjectTemplateWithoutValue(self):
+    redirectProjectTemplate = redirect_project_template.RedirectProjectTemplate
+
+    (t, v) = redirectProjectTemplate.Get('a', 'default template')
+    self.assertEqual(t, None)
+    self.assertEqual(v, None)
diff --git a/redirect/test/redirect_test.py b/redirect/test/redirect_test.py
new file mode 100644
index 0000000..d4af8e8
--- /dev/null
+++ b/redirect/test/redirect_test.py
@@ -0,0 +1,57 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+from redirect import redirect
+from mock import patch
+class TestRedirectApp(unittest.TestCase):
+
+  def setUp(self):
+    self.app = redirect.GenerateRedirectApp()
+    self.app.config['TESTING'] = True
+
+  def testNoRedirectIssueList(self):
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/list')
+    self.assertEqual(response.status_code, 404)
+
+  @patch("redirect.redirect_utils.GetRedirectURL")
+  @patch("redirect.redirect_utils.GetSearchQuery")
+  def testRedirectIssueList(self, fake_get_url, fake_get_search_query):
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/list')
+    self.assertEqual(response.status_code, 302)
+
+  def testNoRedirectCreateIssue(self):
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/entry')
+    self.assertEqual(response.status_code, 404)
+
+  @patch("redirect.redirect_utils.GetRedirectURL")
+  def testRedirectCreateIssue(self, fake_get_url):
+    fake_get_url.return_value = "test"
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/entry')
+    self.assertEqual(response.status_code, 302)
+
+  def testNoRedirectIssueDetail(self):
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/detail?id=1')
+    self.assertEqual(response.status_code, 404)
+
+  @patch("redirect.redirect_utils.GetRedirectURL")
+  @patch("redirect.redirectissue.RedirectIssue.Get")
+  def testRedirectIssueDetail(self, fake_get_url, fake_redirectIssue):
+    fake_get_url.return_value = "test"
+    fake_redirectIssue.return_value = "1"
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/detail?id=1')
+    self.assertEqual(response.status_code, 200)
+
+  @patch("redirect.redirect_utils.GetRedirectURL")
+  def testRedirectIssueDetail(self, fake_get_url):
+    fake_get_url.return_value = "test"
+    client = self.app.test_client()
+    response = client.get('/p/project1/issues/detail?id=10000001')
+    self.assertEqual(response.status_code, 200)
diff --git a/redirect/test/redirect_utils_test.py b/redirect/test/redirect_utils_test.py
new file mode 100644
index 0000000..2ea65ce
--- /dev/null
+++ b/redirect/test/redirect_utils_test.py
@@ -0,0 +1,67 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+import werkzeug
+
+from mock import patch
+
+from redirect import redirect_utils
+from mock import patch
+
+
+class TestRedirectUtils(unittest.TestCase):
+
+  @patch("redirect.redirect_project_template.RedirectProjectTemplate.Get")
+  def testNewIssueParams(self, fake_redirectProjectTemplate):
+    fake_redirectProjectTemplate.return_value = None, None
+    params = werkzeug.datastructures.MultiDict(
+        [
+            ('summary', 'this is a summary'),
+            ('owner', 'test@google.com'),
+            ('description', 'task'),
+            ('cc', 'c1@google.com,c2@google.com'),
+        ])
+    expected = ('title=this+is+a+summary&description=task&'
+                'cc=c1%40google.com%2Cc2%40google.com&assignee=test')
+
+    get = redirect_utils.GetNewIssueParams(params, 'project')
+    self.assertEqual(expected, get)
+
+  @patch("redirect.redirect_project_template.RedirectProjectTemplate.Get")
+  def testNewIssueParamsWithComponent(self, fake_redirectProjectTemplate):
+    fake_redirectProjectTemplate.return_value = '1', '2'
+    params = werkzeug.datastructures.MultiDict(
+        [('summary', 'this is a summary'), ('owner', 'test@google.com')])
+    expected = 'component=1&template=2&title=this+is+a+summary&assignee=test'
+
+    get = redirect_utils.GetNewIssueParams(params, 'project')
+    self.assertEqual(expected, get)
+
+  @patch("redirect.redirect_project_template.RedirectProjectTemplate.Get")
+  def testNewIssueParamsWithNoValidValue(self, fake_redirectProjectTemplate):
+    fake_redirectProjectTemplate.return_value = None, None
+    params = werkzeug.datastructures.MultiDict([('test', 'this is a test')])
+    expected = ''
+    get = redirect_utils.GetNewIssueParams(params, 'project')
+    self.assertEqual(expected, get)
+
+  @patch("redirect.redirect_custom_value.RedirectCustomValue.Get")
+  def testGetSearchQuery(self, fake_redirectcustomevalue):
+    fake_redirectcustomevalue.return_value = None, None
+    params = werkzeug.datastructures.MultiDict(
+        [('q', 'owner%3Ame%20has%3ARollout-Type')])
+    expected = 'q=is%3Aopen+assignee%3A%28me%29'
+
+    get = redirect_utils.GetSearchQuery('project', params)
+    self.assertEqual(expected, get)
+
+  @patch("redirect.redirect_custom_value.RedirectCustomValue.Get")
+  def testGetSearchQueryWithCanValue(self, fake_redirectcustomevalue):
+    fake_redirectcustomevalue.return_value = None, None
+    params = werkzeug.datastructures.MultiDict([('can', 4)])
+    expected = 'q=is%3Aopen+reporter%3A%28me%29'
+
+    get = redirect_utils.GetSearchQuery('project', params)
+    self.assertEqual(expected, get)