Browse Source

Complete tests.

Stefano Cossu 1 year ago
parent
commit
dcefce0716

+ 4 - 4
TODO.md

@@ -29,10 +29,10 @@ discussion, etc.); *X* = not implementing.
 - *D* Config file documentation
 - *D* Hooks documentation
 - *D* Rebranding (ScriptShifter)
-- *W* Tests
-  - *W* Config parsing
-  - *W* Transliteration
-  - *P* REST API
+- *D* Tests
+  - *D* Config parsing
+  - *D* Transliteration
+  - *D* REST API
 - *W* Complete conversion of existing tables to YAML
   - *P* Arabic
   - *P* Armenian

+ 4 - 1
scriptshifter/hooks/test.py

@@ -3,7 +3,10 @@ import logging
 from scriptshifter.exceptions import CONT
 
 
-__doc__ = """ Test hook functions. """
+__doc__ = """ Test hook functions.
+
+Do not remove. Used in unit tests.
+"""
 
 
 logger = logging.getLogger(__name__)

+ 8 - 2
scriptshifter/rest_api.py

@@ -1,5 +1,8 @@
+import logging
+
+from base64 import b64encode
 from copy import deepcopy
-from os import environ
+from os import environ, urandom
 
 from flask import Flask, Response, jsonify, render_template, request
 
@@ -7,12 +10,15 @@ from scriptshifter.tables import list_tables, load_table
 from scriptshifter.trans import transliterate
 
 
+logger = logging.getLogger(__name__)
+
+
 def create_app():
     flask_env = environ.get("TXL_APP_MODE", "production")
     app = Flask(__name__)
     app.config.update({
         "ENV": flask_env,
-        "SECRET_KEY": environ["TXL_FLASK_SECRET"],
+        "SECRET_KEY": environ.get("TXL_FLASK_SECRET", b64encode(urandom(64))),
         # Prod requires the application to be behind a web server, or static
         # files won't be served directly by Flask using this option.
         "USE_X_SENDFILE": flask_env == "production",

+ 1 - 1
scriptshifter/trans.py

@@ -194,6 +194,7 @@ def transliterate(src, lang, r2s=False, capitalize=False):
                     or
                     (capitalize == "all" and ctx.cur_flags & CUR_BOW)
                 ):
+                    logger.info("Capitalizing token.")
                     tk = tk.capitalize()
                 ctx.dest_ls.append(tk)
                 ctx.cur += step
@@ -218,7 +219,6 @@ def transliterate(src, lang, r2s=False, capitalize=False):
         delattr(ctx, "cur_flags")
 
     delattr(ctx, "cur")
-    delattr(ctx, "word_boundary")
 
     # This hook may take care of the assembly and cause the function to return
     # its own return value.

+ 13 - 0
tests/__init__.py

@@ -1,4 +1,17 @@
+from importlib import reload
 from os import path
 
+import scriptshifter.tables
+
+
 TEST_DIR = path.dirname(path.realpath(__file__))
 TEST_DATA_DIR = path.join(TEST_DIR, "data")
+
+
+def reload_tables():
+    reload(scriptshifter.tables)  # Reload new config dir.
+    from scriptshifter import tables
+    tables.list_tables.cache_clear()
+    tables.load_table.cache_clear()
+
+    return tables

+ 0 - 0
tests/data/_test_base1.yml → tests/data/_base1.yml


+ 1 - 1
tests/data/_test_base2.yml → tests/data/_base2.yml

@@ -3,7 +3,7 @@
 general:
   name: Test inheritance base 2
   parents:
-    - _test_base1
+    - _base1
 
 roman_to_script:
   ignore:

+ 0 - 0
tests/data/_test_base3.yml → tests/data/_base3.yml


+ 6 - 0
tests/data/index.yml

@@ -0,0 +1,6 @@
+inherited:
+  name: Test inherited table
+ordering:
+  name: Test ordering
+rot3:
+  name: Test ROT3 hooks

+ 2 - 2
tests/data/test_inherited.yml → tests/data/inherited.yml

@@ -3,8 +3,8 @@
 general:
   name: Test inheritance leaf file
   parents:
-    - _test_base2
-    - _test_base3
+    - _base2
+    - _base3
 
 roman_to_script:
   ignore:

+ 105 - 10
tests/test01_cfg.py

@@ -1,23 +1,118 @@
 from unittest import TestCase
 
-from importlib import reload
 from os import environ
 
-from tests import TEST_DATA_DIR
-import scriptshifter.tables
+import scriptshifter
+
+from tests import TEST_DATA_DIR, reload_tables
 
 
 class TestConfig(TestCase):
     """ Test configuration parsing. """
+    def setUp(self):
+        environ["TXL_CONFIG_TABLE_DIR"] = TEST_DATA_DIR
+        self.tables = reload_tables()
 
     def test_ordering(self):
+        tbl = self.tables.load_table("ordering")
+        exp_order = ["ABCD", "AB", "A", "BCDE", "BCD", "BEFGH", "B"]
+
+        self.assertEqual(
+                [s[0] for s in tbl["roman_to_script"]["map"]], exp_order)
+
+
+class TestOverride(TestCase):
+    """ Test configuration overrides. """
+    def setUp(self):
         environ["TXL_CONFIG_TABLE_DIR"] = TEST_DATA_DIR
-        reload(scriptshifter.tables)  # Reload new config dir.
-        from scriptshifter import tables
-        tables.list_tables.cache_clear()
-        tables.load_table.cache_clear()
+        self.tables = reload_tables()
 
-        tbl = tables.load_table("ordering")
-        exp_order = ["ABCD", "AB", "A", "BCDE", "BCD", "BEFGH", "B"]
+    def test_override_map(self):
+        tbl = self.tables.load_table("inherited")
+
+        self.assertEqual(tbl["general"]["name"], "Test inheritance leaf file")
+
+        # Entries are additive.
+        self.assertEqual(
+                tbl["roman_to_script"]["ignore"],
+                ["Fritter my wig", "Hi", "Ho", "Thing-um-a-jig"])
+        self.assertEqual(
+                tbl["roman_to_script"]["map"],
+                (
+                    ("A", "a"),
+                    ("B", "b"),
+                    ("C", "c"),
+                    ("D", "d"),
+                    ("E", "e"),
+                    ("F", "f"),
+                    ("G", "g"),
+                    ("H", "h"),
+                    ("I", "i"),
+                    ("J", "j"),
+                    ("K", "k"),
+                    ("L", "l"),
+                    ("M", "m"),
+                    ("N", "n"),
+                    ("O", "o"),
+                    ("P", "p"),
+                    ("Q", "q"),
+                    ("R", "r"),
+                    ("S", "s"),
+                    ("T", "t"),
+                    ("U", "u"),
+                    ("V", "v"),
+                    ("W", "w"),
+                    ("X", "x"),
+                    ("Y", "y"),
+                    ("Z", "z"),
+                ))
+
+        # First 4 entries are overridden multiple times.
+        self.assertEqual(
+                tbl["script_to_roman"]["map"],
+                (
+                    ("a", "9"),
+                    ("b", "0"),
+                    ("c", "7"),
+                    ("d", "8"),
+                    ("e", "E"),
+                    ("f", "F"),
+                    ("g", "G"),
+                    ("h", "H"),
+                    ("i", "I"),
+                    ("j", "J"),
+                    ("k", "K"),
+                    ("l", "L"),
+                    ("m", "M"),
+                    ("n", "N"),
+                    ("o", "O"),
+                    ("p", "P"),
+                    ("q", "Q"),
+                    ("r", "R"),
+                    ("s", "S"),
+                    ("t", "T"),
+                    ("u", "U"),
+                    ("v", "V"),
+                    ("w", "W"),
+                    ("x", "X"),
+                    ("y", "Y"),
+                    ("z", "Z"),
+                ))
+
+
+class TestHooks(TestCase):
+    """ Test parsing of hook functions. """
+    def setUp(self):
+        environ["TXL_CONFIG_TABLE_DIR"] = TEST_DATA_DIR
+        self.tables = reload_tables()
+
+    def test_rot3(self):
+        tbl = self.tables.load_table("rot3")
 
-        assert [s[0] for s in tbl["roman_to_script"]["map"]] == exp_order
+        self.assertEqual(
+                tbl["script_to_roman"]["hooks"],
+                {
+                    "begin_input_token": [
+                        (scriptshifter.hooks.test.rotate, {"n": -3})
+                    ]
+                })

+ 13 - 11
tests/test02_transliteration.py

@@ -3,10 +3,9 @@ import logging
 from unittest import TestCase, TestSuite, TextTestRunner
 from csv import reader
 
-from importlib import reload
 from os import environ, path
 
-from tests import TEST_DATA_DIR
+from tests import TEST_DATA_DIR, reload_tables
 from scriptshifter.trans import transliterate
 import scriptshifter.tables
 
@@ -18,12 +17,11 @@ class TestTrans(TestCase):
     """
     Test S2R transliteration.
 
+    Modified test case class to run independent tests for each CSV row.
+
     TODO use a comprehensive sample table and report errors for unsupported
     languages.
     """
-    """
-    Modified test case class to run independent tests for each CSV row.
-    """
 
     def sample_s2r(self):
         """
@@ -35,7 +33,9 @@ class TestTrans(TestCase):
         config = scriptshifter.tables.load_table(self.tbl)
         if "script_to_roman" in config:
             txl = transliterate(self.script, self.tbl)
-            self.assertEqual(txl, self.roman)
+            self.assertEqual(
+                    txl, self.roman,
+                    f"S2R transliteration error for {self.tbl}!")
 
     def sample_r2s(self):
         """
@@ -47,13 +47,19 @@ class TestTrans(TestCase):
         config = scriptshifter.tables.load_table(self.tbl)
         if "roman_to_script" in config:
             txl = transliterate(self.roman, self.tbl, r2s=True)
-            self.assertEqual(txl, self.script)
+            self.assertEqual(
+                    txl, self.script,
+                    f"R2S transliteration error for {self.tbl}!")
 
 
 def make_suite():
     """
     Build parametrized test cases.
     """
+    if "TXL_CONFIG_TABLE_DIR" in environ:
+        del environ["TXL_CONFIG_TABLE_DIR"]
+    reload_tables()
+
     suite = TestSuite()
     with open(
             path.join(TEST_DATA_DIR, "sample_strings.csv"),
@@ -74,8 +80,4 @@ def make_suite():
     return suite
 
 
-if "TXL_CONFIG_TABLE_DIR" in environ:
-    del environ["TXL_CONFIG_TABLE_DIR"]
-    reload(scriptshifter.tables)
-
 TextTestRunner().run(make_suite())

+ 96 - 0
tests/test03_rest_api.py

@@ -0,0 +1,96 @@
+import json
+
+from os import environ
+from unittest import TestCase
+
+from scriptshifter.rest_api import app
+from tests import TEST_DATA_DIR, reload_tables
+
+
+EP = "http://localhost:8000"
+
+
+class TestRestAPI(TestCase):
+    """ Test REST API interaction. """
+    def setUp(self):
+        environ["TXL_CONFIG_TABLE_DIR"] = TEST_DATA_DIR
+        # if "TXL_CONFIG_TABLE_DIR" in environ:
+        #     del environ["TXL_CONFIG_TABLE_DIR"]
+        reload_tables()
+
+        # Start webapp.
+        app.testing = True
+
+    def test_health(self):
+        with app.test_client() as c:
+            rsp = c.get("/health")
+
+        self.assertEqual(rsp.status_code, 200)
+
+    def test_language_list(self):
+        with app.test_client() as c:
+            rsp = c.get("/languages")
+
+        self.assertEqual(rsp.status_code, 200)
+
+        data = json.loads(rsp.get_data(as_text=True))
+        self.assertIn("inherited", data)
+        self.assertIn("name", data["inherited"])
+        self.assertNotIn("_base1", data)
+        self.assertNotIn("_base2", data)
+        self.assertNotIn("_base3", data)
+
+    def test_lang_table(self):
+        with app.test_client() as c:
+            rsp = c.get("/table/ordering")
+
+        self.assertEqual(rsp.status_code, 200)
+        data = json.loads(rsp.get_data(as_text=True))
+
+        self.assertIn("general", data)
+        self.assertIn("roman_to_script", data)
+        self.assertIn("map", data["roman_to_script"])
+        self.assertEqual(data["roman_to_script"]["map"][0], ["ABCD", ""])
+
+    def test_trans_api_s2r(self):
+        with app.test_client() as c:
+            rsp = c.post("/trans/rot3", data={"text": "defg"})
+
+        self.assertEqual(rsp.status_code, 200)
+        data = rsp.get_data(as_text=True)
+
+        self.assertEqual(data, "abcd")
+
+    def test_trans_api_r2s(self):
+        with app.test_client() as c:
+            rsp = c.post("/trans/rot3/r2s", data={"text": "abcd"})
+
+        self.assertEqual(rsp.status_code, 200)
+        data = rsp.get_data(as_text=True)
+
+        self.assertEqual(data, "defg")
+
+    def test_trans_api_capitalize(self):
+        with app.test_client() as c:
+            rsp = c.post(
+                    "/trans/rot3/r2s",
+                    data={"capitalize": "first", "text": "bcde"})
+
+        self.assertEqual(rsp.status_code, 200)
+        data = rsp.get_data(as_text=True)
+
+        self.assertEqual(data, "Efgh")
+
+    def test_trans_form(self):
+        with app.test_client() as c:
+            rsp = c.post(
+                    "/transliterate", data={
+                        "text": "abcd",
+                        "r2s": "true",
+                        "lang": "rot3",
+                    })
+
+        self.assertEqual(rsp.status_code, 200)
+        data = rsp.get_data(as_text=True)
+
+        self.assertEqual(data, "defg")