From a013bb51feacd4823feb8956a5b1a93935acd436 Mon Sep 17 00:00:00 2001
From: David Beniamine <david.beniamine@tetras-libre.fr>
Date: Wed, 15 Feb 2023 23:44:40 +0100
Subject: [PATCH] Working test with fixtures

---
 Mirador_backend/app.py                        |  8 ++++--
 Mirador_backend/models.py                     | 15 +++++++---
 .../tests/test_mirador_resource.py            | 12 ++++++--
 Mirador_backend/tests/tester.py               | 14 ++++++++--
 Mirador_backend/utils/app.py                  |  9 ++++++
 Mirador_backend/utils/config.py               | 12 +++-----
 Mirador_backend/utils/database.py             | 28 +++++++++----------
 cli                                           |  2 +-
 8 files changed, 65 insertions(+), 35 deletions(-)
 create mode 100644 Mirador_backend/utils/app.py

diff --git a/Mirador_backend/app.py b/Mirador_backend/app.py
index 5c652c5..9ac4c93 100644
--- a/Mirador_backend/app.py
+++ b/Mirador_backend/app.py
@@ -6,20 +6,22 @@ from flask_apispec.extension import FlaskApiSpec
 from Mirador_backend.routes import v1
 from Mirador_backend.utils.config import ConfigFactory
 from Mirador_backend.utils.database import db
+from Mirador_backend.utils.app import setApp
 
 app = Flask(__name__)
+setApp(app)
 api = Api(app)
 docs = FlaskApiSpec(app)
 
-app.config.from_object(ConfigFactory.getConfig())
-app.db = db
+app.config.from_object(ConfigFactory())
+app.db = db(app.config['DB'], app.config['DEBUG'])
 
 v1.register_routes(api, docs)
 
 
 @app.teardown_appcontext
 def shutdown_session(exception=None):
-    db.close()
+    app.db.close()
 
 
 if __name__ == '__main__':
diff --git a/Mirador_backend/models.py b/Mirador_backend/models.py
index 5847f07..c35529c 100644
--- a/Mirador_backend/models.py
+++ b/Mirador_backend/models.py
@@ -5,7 +5,7 @@ from sqlalchemy import Integer, JSON
 from sqlalchemy import select
 from sqlalchemy.exc import NoResultFound
 import json
-from Mirador_backend.utils.database import db
+from Mirador_backend.utils.app import getApp
 
 
 class NotFound(NoResultFound):
@@ -16,7 +16,10 @@ class BaseModel(DeclarativeBase):
     """A generic model class
     """
 
-    session = db.db_session
+    session = getApp().db.session
+    """Access the db session"""
+
+    engine = getApp().db.engine
     """Access the db session"""
 
     fillable = []
@@ -30,9 +33,13 @@ class BaseModel(DeclarativeBase):
               }
     """Actual data fields"""
 
-    def create_tables():
+    def create_all():
         """Creates all tables for all models"""
-        BaseModel.metadata.create_all(db.engine)
+        BaseModel.metadata.create_all(getApp().db.engine)
+
+    def drop_all():
+        """drop all tables for all models"""
+        BaseModel.metadata.drop_all(getApp().db.engine)
 
     @classmethod
     def query(cls, stmt):
diff --git a/Mirador_backend/tests/test_mirador_resource.py b/Mirador_backend/tests/test_mirador_resource.py
index 37da0e2..a0a0558 100644
--- a/Mirador_backend/tests/test_mirador_resource.py
+++ b/Mirador_backend/tests/test_mirador_resource.py
@@ -4,15 +4,21 @@ from Mirador_backend.tests.tester import TestCase
 
 
 class MiradorResourceTest(TestCase):
+    def getData(self):
+        return self.getFixtureRecordsByModel(self.fixtures[0], 'Mirador_backend.models.MiradorResource')
+
     def testGetOne(self):
+        id = 1
         payload = json.dumps({})
-        response = self.client.get(self.base + '/1', headers={"Content-Type": "application/json"}, data=payload)
+        response = self.client.get(f'{self.base}/{id}', headers={"Content-Type": "application/json"}, data=payload)
 
         self.assertEqual(200, response.status_code)
-        self.assertEqual(None, response.json)
+
+        expected = next(x for x in self.getData() if x['id'] == id)
+        self.assertEqual(expected, response.json)
 
     def testGetAll(self):
         payload = json.dumps({})
         response = self.client.get(self.base, headers={"Content-Type": "application/json"}, data=payload)
         self.assertEqual(200, response.status_code)
-        self.assertEqual([], response.json)
+        self.assertEqual({str(x['id']): x for x in self.getData()}, response.json)
diff --git a/Mirador_backend/tests/tester.py b/Mirador_backend/tests/tester.py
index b1aae8b..57a9bff 100644
--- a/Mirador_backend/tests/tester.py
+++ b/Mirador_backend/tests/tester.py
@@ -1,18 +1,28 @@
 import unittest
+import json
+from os.path import dirname, abspath
+from flask_fixtures import FixturesMixin
 
 from Mirador_backend.app import app
-from flask_fixtures import FixturesMixin
+from Mirador_backend.models import BaseModel
 
 
 class TestCase(unittest.TestCase, FixturesMixin):
     fixtures = ['test.json']
     app = app
-    db = app.db
+    db = BaseModel
 
     def setUp(self):
         self.base = 'v1/mirador_resource'
         self.client = app.test_client()
 
+    def getFixture(self, name):
+        with open(f'{dirname(abspath(__file__))}/fixtures/{name}') as f:
+            return json.load(f)
+
+    def getFixtureRecordsByModel(self, name, model):
+        return next(x['records'] for x in self.getFixture(name) if x['model'] == model)
+
     def tearDown(self):
         # TODO
         pass
diff --git a/Mirador_backend/utils/app.py b/Mirador_backend/utils/app.py
new file mode 100644
index 0000000..71f6b56
--- /dev/null
+++ b/Mirador_backend/utils/app.py
@@ -0,0 +1,9 @@
+def getApp():
+    return getApp.app
+
+
+getApp.app = None
+
+
+def setApp(app):
+    getApp.app = app
diff --git a/Mirador_backend/utils/config.py b/Mirador_backend/utils/config.py
index a7f9976..002af56 100644
--- a/Mirador_backend/utils/config.py
+++ b/Mirador_backend/utils/config.py
@@ -14,7 +14,7 @@ class Config(object):
     APISPEC_SWAGGER_UI_URL = '/swagger-ui/'  # URI to access UI of API Doc
     ENV = getenv('ENV', 'dev')
     TESTING = False
-    DEBUG = False
+    DEBUG = getenv('ENV', 'dev') != 'prod'
     DB = {
         'TYPE': getenv('DB_TYPE', 'mariadb+mariadbconnector'),
         'USER': getenv('MYSQL_USER', 'user'),
@@ -26,14 +26,10 @@ class Config(object):
 
 class TestingConfig(Config):
     TESTING = True
+    DEBUG = True
     DB = None
     FIXTURES_DIRS = ['tests/fixtures']
 
 
-class ConfigFactory():
-    config = None
-
-    def getConfig():
-        if ConfigFactory.config is None:
-            ConfigFactory.config = TestingConfig() if getenv('ENV', 'dev') == 'test' else Config()
-        return ConfigFactory.config
+def ConfigFactory():
+    return TestingConfig if getenv('ENV', 'dev') == 'test' else Config
diff --git a/Mirador_backend/utils/database.py b/Mirador_backend/utils/database.py
index 20bbc19..8d35a0d 100644
--- a/Mirador_backend/utils/database.py
+++ b/Mirador_backend/utils/database.py
@@ -1,20 +1,20 @@
 from sqlalchemy import create_engine
 from sqlalchemy.orm import scoped_session, sessionmaker
-from Mirador_backend.utils.config import ConfigFactory
-
-
-def getDBUri():
-    params = ConfigFactory.getConfig().DB
-    if params is None:
-        return 'sqlite://'
-    return f'{params["TYPE"]}://{params["USER"]}:{params["PASSWORD"]}@{params["HOST"]}/{params["BASE"]}'
 
 
 class db():
-    engine = create_engine(getDBUri(), echo=ConfigFactory.getConfig().DEBUG)
-    db_session = scoped_session(sessionmaker(autocommit=False,
-                                             autoflush=False,
-                                             bind=engine))
+    def __getDBUri(self):
+        params = self.config
+        if params is None:
+            return 'sqlite://'
+        return f'{params["TYPE"]}://{params["USER"]}:{params["PASSWORD"]}@{params["HOST"]}/{params["BASE"]}'
+
+    def __init__(self, config, debug):
+        self.config = config
+        self.engine = create_engine(self.__getDBUri(), echo=debug)
+        self.session = scoped_session(sessionmaker(autocommit=False,
+                                                   autoflush=False,
+                                                   bind=self.engine))
 
-    def close():
-        db.db_session.remove()
+    def close(self):
+        self.session.remove()
diff --git a/cli b/cli
index 60329d4..d40535c 100755
--- a/cli
+++ b/cli
@@ -69,7 +69,7 @@ case $action in
         set +x
         ;;
     "mysql_init")
-        $cmd python -c 'from Mirador_backend.models import BaseModel; BaseModel.create_tables()'
+        $cmd python -c 'from Mirador_backend.models import BaseModel; BaseModel.create_all()'
         ;;
     "shell")
         $cmd ipython
-- 
GitLab