about summary refs log tree commit diff
path: root/gn2/tests/unit/wqflask/api
diff options
context:
space:
mode:
authorArun Isaac2023-12-29 18:55:37 +0000
committerArun Isaac2023-12-29 19:01:46 +0000
commit204a308be0f741726b9a620d88fbc22b22124c81 (patch)
treeb3cf66906674020b530c844c2bb4982c8a0e2d39 /gn2/tests/unit/wqflask/api
parent83062c75442160427b50420161bfcae2c5c34c84 (diff)
downloadgenenetwork2-204a308be0f741726b9a620d88fbc22b22124c81.tar.gz
Namespace all modules under gn2.
We move all modules under a gn2 directory. This is important for
"correct" packaging and deployment as a Guix service.
Diffstat (limited to 'gn2/tests/unit/wqflask/api')
-rw-r--r--gn2/tests/unit/wqflask/api/__init__.py0
-rw-r--r--gn2/tests/unit/wqflask/api/test_correlation.py175
-rw-r--r--gn2/tests/unit/wqflask/api/test_gen_menu.py423
-rw-r--r--gn2/tests/unit/wqflask/api/test_mapping.py113
-rw-r--r--gn2/tests/unit/wqflask/api/test_markdown_routes.py54
5 files changed, 765 insertions, 0 deletions
diff --git a/gn2/tests/unit/wqflask/api/__init__.py b/gn2/tests/unit/wqflask/api/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/gn2/tests/unit/wqflask/api/__init__.py
diff --git a/gn2/tests/unit/wqflask/api/test_correlation.py b/gn2/tests/unit/wqflask/api/test_correlation.py
new file mode 100644
index 00000000..8835375d
--- /dev/null
+++ b/gn2/tests/unit/wqflask/api/test_correlation.py
@@ -0,0 +1,175 @@
+import unittest
+from unittest import mock
+from gn2.wqflask import app
+from collections import OrderedDict
+from gn2.wqflask.api.correlation import init_corr_params
+from gn2.wqflask.api.correlation import convert_to_mouse_gene_id
+from gn2.wqflask.api.correlation import do_literature_correlation_for_all_traits
+from gn2.wqflask.api.correlation import get_sample_r_and_p_values
+from gn2.wqflask.api.correlation import calculate_results
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for k, v in obj.items():
+            setattr(self, k, v)
+
+
+class MockDataset(AttributeSetter):
+    def get_trait_data(self):
+        return None
+
+    def retrieve_genes(self, id=None):
+        return {"TT-1": "GH-1", "TT-2": "GH-2", "TT-3": "GH-3"}
+
+
+class TestCorrelations(unittest.TestCase):
+    def setUp(self):
+        self.app_context = app.app_context()
+        self.app_context.push()
+
+    def tearDown(self):
+        self.app_context.pop()
+
+    def test_init_corr_params(self):
+        start_vars = {"return_count": "3", "type": "T1", "method": "spearman"}
+
+        corr_params_results = init_corr_params(start_vars=start_vars)
+        expected_results = {"return_count": 3, "type": "T1", "method": "spearman"}
+
+        self.assertEqual(corr_params_results, expected_results)
+
+    @mock.patch("wqflask.api.correlation.database_connection")
+    def test_convert_to_mouse_gene_id(self, mock_db):
+        conn = mock.MagicMock()
+        mock_db.return_value.__enter__.return_value = conn
+        with conn.cursor() as cursor:
+            cursor.fetchone.side_effect = [("MG-1",), ("MG-2",)]
+
+            self.assertEqual(
+                convert_to_mouse_gene_id(species="Other", gene_id=""), None
+            )
+            self.assertEqual(
+                convert_to_mouse_gene_id(species="mouse", gene_id="MG-4"), "MG-4"
+            )
+            self.assertEqual(
+                convert_to_mouse_gene_id(species="rat", gene_id="R1"), "MG-1"
+            )
+            self.assertEqual(
+                convert_to_mouse_gene_id(species="human", gene_id="H1"), "MG-2"
+            )
+
+    @mock.patch("wqflask.api.correlation.database_connection")
+    @mock.patch("wqflask.api.correlation.convert_to_mouse_gene_id")
+    def test_do_literature_correlation_for_all_traits(
+        self, mock_convert_to_mouse_geneid, mock_db
+    ):
+        mock_convert_to_mouse_geneid.side_effect = ["MG-1", "MG-2;", "MG-3", "MG-4"]
+
+        trait_geneid_dict = {"TT-1": "GH-1", "TT-2": "GH-2", "TT-3": "GH-3"}
+        conn = mock.MagicMock()
+        mock_db.return_value.__enter__.return_value = conn
+        with conn.cursor() as cursor:
+            cursor.fetchone.side_effect = [("V1",), ("V2",), ("V3",)]
+            this_trait = AttributeSetter({"geneid": "GH-1"})
+            target_dataset = AttributeSetter(
+                {"group": AttributeSetter({"species": "rat"})}
+            )
+            results = do_literature_correlation_for_all_traits(
+                this_trait=this_trait,
+                target_dataset=target_dataset,
+                trait_geneid_dict=trait_geneid_dict,
+                corr_params={},
+            )
+            expected_results = {
+                "TT-1": ["GH-1", 0],
+                "TT-2": ["GH-2", "V1"],
+                "TT-3": ["GH-3", "V2"],
+            }
+            self.assertEqual(results, expected_results)
+
+    @mock.patch("wqflask.api.correlation.corr_result_helpers.normalize_values")
+    def test_get_sample_r_and_p_values(self, mock_normalize):
+
+        group = AttributeSetter(
+            {"samplelist": ["S1", "S2", "S3", "S4", "S5", "S6", "S7"]}
+        )
+        target_dataset = AttributeSetter({"group": group})
+
+        target_vals = [3.4, 6.2, 4.1, 3.4, 1.2, 5.6]
+        trait_data = {
+            "S1": AttributeSetter({"value": 2.3}),
+            "S2": AttributeSetter({"value": 1.1}),
+            "S3": AttributeSetter({"value": 6.3}),
+            "S4": AttributeSetter({"value": 3.6}),
+            "S5": AttributeSetter({"value": 4.1}),
+            "S6": AttributeSetter({"value": 5.0}),
+        }
+        this_trait = AttributeSetter({"data": trait_data})
+        mock_normalize.return_value = (
+            [2.3, 1.1, 6.3, 3.6, 4.1, 5.0],
+            [3.4, 6.2, 4.1, 3.4, 1.2, 5.6],
+            6,
+        )
+        mock_normalize.side_effect = [
+            ([2.3, 1.1, 6.3, 3.6, 4.1, 5.0], [3.4, 6.2, 4.1, 3.4, 1.2, 5.6], 6),
+            ([2.3, 1.1, 6.3, 3.6, 4.1, 5.0], [3.4, 6.2, 4.1, 3.4, 1.2, 5.6], 6),
+            ([2.3, 1.1, 1.4], [3.4, 6.2, 4.1], 3),
+        ]
+
+        results_pearsonr = get_sample_r_and_p_values(
+            this_trait=this_trait,
+            this_dataset={},
+            target_vals=target_vals,
+            target_dataset=target_dataset,
+            type="pearson",
+        )
+        results_spearmanr = get_sample_r_and_p_values(
+            this_trait=this_trait,
+            this_dataset={},
+            target_vals=target_vals,
+            target_dataset=target_dataset,
+            type="spearman",
+        )
+        results_num_overlap = get_sample_r_and_p_values(
+            this_trait=this_trait,
+            this_dataset={},
+            target_vals=target_vals,
+            target_dataset=target_dataset,
+            type="pearson",
+        )
+        expected_pearsonr = [-0.21618688834430866, 0.680771605997119, 6]
+        expected_spearmanr = [-0.11595420713048969, 0.826848213385815, 6]
+        for i, val in enumerate(expected_pearsonr):
+            self.assertAlmostEqual(val, results_pearsonr[i], 4)
+        for i, val in enumerate(expected_spearmanr):
+            self.assertAlmostEqual(val, results_spearmanr[i], 4)
+        self.assertEqual(results_num_overlap, None)
+
+    @mock.patch("wqflask.api.correlation.do_literature_correlation_for_all_traits")
+    def test_calculate_results(self, literature_correlation):
+
+        literature_correlation.return_value = {
+            "TT-1": ["GH-1", 0],
+            "TT-2": ["GH-2", 3],
+            "TT-3": ["GH-3", 1],
+        }
+
+        this_dataset = MockDataset({"group": AttributeSetter({"species": "rat"})})
+        target_dataset = MockDataset({"group": AttributeSetter({"species": "rat"})})
+        this_trait = AttributeSetter({"geneid": "GH-1"})
+        corr_params = {"type": "literature"}
+        sorted_results = calculate_results(
+            this_trait=this_trait,
+            this_dataset=this_dataset,
+            target_dataset=target_dataset,
+            corr_params=corr_params,
+        )
+        expected_results = {
+            "TT-2": ["GH-2", 3],
+            "TT-3": ["GH-3", 1],
+            "TT-1": ["GH-1", 0],
+        }
+
+        self.assertTrue(isinstance(sorted_results, OrderedDict))
+        self.assertEqual(dict(sorted_results), expected_results)
diff --git a/gn2/tests/unit/wqflask/api/test_gen_menu.py b/gn2/tests/unit/wqflask/api/test_gen_menu.py
new file mode 100644
index 00000000..a6081e99
--- /dev/null
+++ b/gn2/tests/unit/wqflask/api/test_gen_menu.py
@@ -0,0 +1,423 @@
+"""Test cases for wqflask.api.gen_menu"""
+import unittest
+from unittest import mock
+
+from gn2.wqflask.api.gen_menu import gen_dropdown_json
+from gn2.wqflask.api.gen_menu import get_groups
+from gn2.wqflask.api.gen_menu import get_types
+from gn2.wqflask.api.gen_menu import get_datasets
+from gn2.wqflask.api.gen_menu import phenotypes_exist
+from gn2.wqflask.api.gen_menu import genotypes_exist
+from gn2.wqflask.api.gen_menu import build_datasets
+from gn2.wqflask.api.gen_menu import build_types
+
+
+class TestGenMenu(unittest.TestCase):
+    """Tests for the gen_menu module"""
+
+    def setUp(self):
+        self.test_group = {
+            'mouse': [
+                ['H_T1',
+                 'H_T',
+                 'Family:DescriptionA'
+                 ],
+                ['H_T2', "H_T'", 'Family:None']
+            ],
+            'human': [
+                ['BXD', 'BXD', 'Family:None'],
+                ['HLC', 'Liver: Normal Gene Expression with Genotypes (Merck)',
+                 'Family:Test']
+            ]
+        }
+
+        self.test_type = {
+            'mouse': {
+                'H_T2': [('Phenotypes',
+                          'Traits and Cofactors',
+                          'Phenotypes'),
+                         ('Genotypes',
+                          'DNA Markers and SNPs',
+                          'Genotypes'),
+                         ['M', 'M', 'Molecular Trait Datasets']],
+                'H_T1': [('Phenotypes',
+                          'Traits and Cofactors',
+                          'Phenotypes'),
+                         ('Genotypes',
+                          'DNA Markers and SNPs',
+                          'Genotypes'),
+                         ['M', 'M', 'Molecular Trait Datasets']]
+            },
+            'human': {
+                'HLC': [('Phenotypes',
+                         'Traits and Cofactors',
+                         'Phenotypes'),
+                        ('Genotypes',
+                         'DNA Markers and SNPs',
+                         'Genotypes'),
+                        ['M', 'M', 'Molecular Trait Datasets']],
+                'BXD': [('Phenotypes',
+                         'Traits and Cofactors',
+                         'Phenotypes'),
+                        ('Genotypes',
+                         'DNA Markers and SNPs',
+                         'Genotypes'),
+                        ['M', 'M', 'Molecular Trait Datasets']]
+            }
+        }
+
+    def test_get_groups(self):
+        """Test that species groups are grouped correctly"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.side_effect = [
+                # Mouse
+                (('BXD', 'BXD', None),
+                 ('HLC', ('Liver: Normal Gene Expression '
+                          'with Genotypes (Merck)'),
+                  'Test')),
+                # Human
+                (('H_T1', "H_T", "DescriptionA"),
+                 ('H_T2', "H_T'", None))
+            ]
+            self.assertEqual(get_groups([["human", "Human"],
+                                         ["mouse", "Mouse"]],
+                                        db_mock),
+                             self.test_group)
+
+            for name in ["mouse", "human"]:
+                cursor.execute.assert_any_call(
+                    ("SELECT InbredSet.Name, InbredSet.FullName, "
+                     "IFNULL(InbredSet.Family, 'None') "
+                     "FROM InbredSet, Species WHERE Species.Name "
+                     "= '{}' AND InbredSet.SpeciesId = Species.Id GROUP by "
+                     "InbredSet.Name ORDER BY IFNULL(InbredSet.FamilyOrder, "
+                     "InbredSet.FullName) ASC, IFNULL(InbredSet.Family, "
+                     "InbredSet.FullName) ASC, InbredSet.FullName ASC, "
+                     "InbredSet.MenuOrderId ASC").format(name)
+                )
+
+    def test_phenotypes_exist_called_with_correct_query(self):
+        """Test that phenotypes_exist is called with the correct query"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchone.return_value = None
+            phenotypes_exist("test", db_mock)
+            cursor.execute.assert_called_with(
+                "SELECT Name FROM PublishFreeze "
+                "WHERE PublishFreeze.Name = 'testPublish'"
+            )
+
+    def test_phenotypes_exist_with_falsy_values(self):
+        """Test that phenotype check returns correctly when given
+        a None value"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            for x in [None, False, (), [], ""]:
+                cursor.fetchone.return_value = x
+            self.assertFalse(phenotypes_exist("test", db_mock))
+
+    def test_phenotypes_exist_with_truthy_value(self):
+        """Test that phenotype check returns correctly when given Truthy"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as conn:
+            with conn.cursor() as cursor:
+                for x in ["x", ("result"), ["result"], [1]]:
+                    cursor.fetchone.return_value = (x)
+                self.assertTrue(phenotypes_exist("test", db_mock))
+
+    def test_genotypes_exist_called_with_correct_query(self):
+        """Test that genotypes_exist is called with the correct query"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchone.return_value = None
+            genotypes_exist("test", db_mock)
+            cursor.execute.assert_called_with(
+                "SELECT Name FROM GenoFreeze WHERE "
+                "GenoFreeze.Name = 'testGeno'"
+            )
+
+    def test_genotypes_exist_with_falsy_values(self):
+        """Test that genotype check returns correctly when given a None value
+
+        """
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            for x in [None, False, (), [], ""]:
+                cursor.fetchone.return_value = x
+                self.assertFalse(genotypes_exist("test", db_mock))
+
+    def test_genotypes_exist_with_truthy_value(self):
+        """Test that genotype check returns correctly when given Truthy """
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            for x in ["x", ("result"), ["result"], [1]]:
+                cursor.fetchone.return_value = (x)
+                self.assertTrue(phenotypes_exist("test", db_mock))
+
+    def test_build_datasets_with_type_phenotypes(self):
+        """Test that correct dataset is returned for a phenotype type"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = (
+                (602, "BXDPublish", "BXD Published Phenotypes"),
+            )
+            self.assertEqual(build_datasets("Mouse", "BXD",
+                                            "Phenotypes", db_mock),
+                             [['602', "BXDPublish",
+                               "BXD Published Phenotypes"]])
+            cursor.execute.assert_called_with(
+                "SELECT InfoFiles.GN_AccesionId, PublishFreeze.Name, "
+                + "PublishFreeze.FullName FROM InfoFiles, PublishFreeze, "
+                + "InbredSet WHERE InbredSet.Name = 'BXD' AND "
+                + "PublishFreeze.InbredSetId = InbredSet.Id AND "
+                + "InfoFiles.InfoPageName = PublishFreeze.Name "
+                + "ORDER BY PublishFreeze.CreateTime ASC"
+            )
+            self.assertEqual(build_datasets("Mouse", "MDP",
+                                            "Phenotypes", db_mock),
+                             [['602', "BXDPublish",
+                               "Mouse Phenome Database"]])
+
+            cursor.fetchall.return_value = ()
+            cursor.fetchone.return_value = (
+                "BXDPublish", "Mouse Phenome Database"
+            )
+            self.assertEqual(build_datasets("Mouse", "MDP",
+                                            "Phenotypes", db_mock),
+                             [["None", "BXDPublish",
+                               "Mouse Phenome Database"]])
+
+    def test_build_datasets_with_type_phenotypes_and_no_results(self):
+        """Test that correct dataset is returned for a phenotype type with no
+        results
+
+        """
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = None
+            cursor.fetchone.return_value = (121,
+                                            "text value")
+            self.assertEqual(build_datasets("Mouse", "BXD",
+                                            "Phenotypes", db_mock),
+                             [["None", "121",
+                               "text value"]])
+            cursor.execute.assert_called_with(
+                "SELECT PublishFreeze.Name, PublishFreeze.FullName "
+                "FROM PublishFreeze, InbredSet "
+                "WHERE InbredSet.Name = 'BXD' AND "
+                "PublishFreeze.InbredSetId = InbredSet.Id "
+                "ORDER BY PublishFreeze.CreateTime ASC"
+            )
+
+    def test_build_datasets_with_type_genotypes(self):
+        """Test that correct dataset is returned for a phenotype type"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchone.return_value = (
+                635, "HLCPublish", "HLC Published Genotypes"
+            )
+            self.assertEqual(build_datasets("Mouse", "HLC",
+                                            "Genotypes", db_mock),
+                             [["635", "HLCGeno", "HLC Genotypes"]])
+            cursor.execute.assert_called_with(
+                "SELECT InfoFiles.GN_AccesionId FROM InfoFiles, "
+                "GenoFreeze, InbredSet WHERE InbredSet.Name = 'HLC' AND "
+                "GenoFreeze.InbredSetId = InbredSet.Id AND "
+                "InfoFiles.InfoPageName = GenoFreeze.ShortName "
+                "ORDER BY GenoFreeze.CreateTime DESC"
+            )
+            cursor.fetchone.return_value = ()
+            self.assertEqual(build_datasets("Mouse", "HLC",
+                                            "Genotypes", db_mock),
+                             [["None", "HLCGeno", "HLC Genotypes"]])
+
+    def test_build_datasets_with_type_mrna(self):
+        """Test that correct dataset is returned for a mRNA
+        expression/ Probeset"""
+        db_mock = mock.MagicMock()
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = (
+                (112, "HC_M2_0606_P",
+                 "Hippocampus Consortium M430v2 (Jun06) PDNN"), )
+            self.assertEqual(build_datasets("Mouse",
+                                            "HLC", "mRNA", db_mock),
+                             [["112", 'HC_M2_0606_P',
+                               "Hippocampus Consortium M430v2 (Jun06) PDNN"
+                               ]])
+            cursor.execute.assert_called_once_with(
+                "SELECT ProbeSetFreeze.Id, ProbeSetFreeze.Name, "
+                "ProbeSetFreeze.FullName FROM ProbeSetFreeze, "
+                "ProbeFreeze, InbredSet, Tissue, Species WHERE "
+                "Species.Name = 'Mouse' AND Species.Id = "
+                "InbredSet.SpeciesId AND InbredSet.Name = 'HLC' AND "
+                "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id AND "
+                "Tissue.Name = 'mRNA' AND ProbeFreeze.TissueId = "
+                "Tissue.Id AND ProbeFreeze.InbredSetId = InbredSet.Id AND "
+                "ProbeSetFreeze.public > 0 "
+                "ORDER BY -ProbeSetFreeze.OrderList DESC, "
+                "ProbeSetFreeze.CreateTime DESC")
+
+    @mock.patch('wqflask.api.gen_menu.build_datasets')
+    def test_build_types(self, datasets_mock):
+        """Test that correct tissue metadata is returned"""
+        db_mock = mock.MagicMock()
+        datasets_mock.return_value = [
+            ["112", 'HC_M2_0606_P',
+                "Hippocampus Consortium M430v2 (Jun06) PDNN"]
+        ]
+        with db_mock.cursor() as cursor:
+            cursor.fetchall.return_value = (
+                ('Mouse Tissue'), ('Human Tissue'), ('Rat Tissue')
+            )
+            self.assertEqual(build_types('mouse', 'random group', db_mock),
+                             [['M', 'M', 'Molecular Traits'],
+                              ['H', 'H', 'Molecular Traits'],
+                              ['R', 'R', 'Molecular Traits']])
+            cursor.execute.assert_called_once_with(
+                "SELECT DISTINCT Tissue.Name "
+                "FROM ProbeFreeze, ProbeSetFreeze, InbredSet, "
+                "Tissue, Species WHERE Species.Name = 'mouse' "
+                "AND Species.Id = InbredSet.SpeciesId AND "
+                "InbredSet.Name = 'random group' AND "
+                "ProbeFreeze.TissueId = Tissue.Id AND "
+                "ProbeFreeze.InbredSetId = InbredSet.Id AND "
+                "ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id "
+                "ORDER BY Tissue.Name"
+            )
+
+    @mock.patch('wqflask.api.gen_menu.build_types')
+    @mock.patch('wqflask.api.gen_menu.genotypes_exist')
+    @mock.patch('wqflask.api.gen_menu.phenotypes_exist')
+    def test_get_types_with_existing_genotype_and_phenotypes(
+            self,
+            phenotypes_exist_mock,
+            genotypes_exist_mock,
+            build_types_mock):
+        """Test that build types are constructed correctly if phenotypes and genotypes
+        exist
+
+        """
+        phenotypes_exist_mock.return_value = True
+        genotypes_exist_mock.return_value = True
+
+        expected_result = self.test_type
+
+        build_types_mock.return_value = [
+            ['M', 'M', 'Molecular Trait Datasets']
+        ]
+        self.assertEqual(get_types(self.test_group,
+                                   mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.build_types')
+    @mock.patch('wqflask.api.gen_menu.genotypes_exist')
+    @mock.patch('wqflask.api.gen_menu.phenotypes_exist')
+    def test_get_types_with_buildtype_and_non_existent_genotype_and_phenotypes(
+            self,
+            phenotypes_exist_mock,
+            genotypes_exist_mock,
+            build_types_mock):
+        """Test that build types are constructed correctly if phenotypes_exist and
+        genotypes_exist are false but build_type is falsy
+
+        """
+        phenotypes_exist_mock.return_value = False
+        genotypes_exist_mock.return_value = False
+
+        build_types_mock.return_value = []
+        self.assertEqual(get_types(self.test_group, mock.MagicMock()),
+                         {'mouse': {}, 'human': {}})
+
+    @mock.patch('wqflask.api.gen_menu.build_types')
+    @mock.patch('wqflask.api.gen_menu.genotypes_exist')
+    @mock.patch('wqflask.api.gen_menu.phenotypes_exist')
+    def test_get_types_with_non_existent_genotype_phenotypes_and_buildtype(
+            self,
+            phenotypes_exist_mock,
+            genotypes_exist_mock,
+            build_types_mock):
+        """Test that build types are constructed correctly if phenotypes_exist,
+        genotypes_exist and build_types are truthy
+
+        """
+        phenotypes_exist_mock.return_value = False
+        genotypes_exist_mock.return_value = False
+
+        build_types_mock.return_value = [
+            ['M', 'M', 'Molecular Trait Datasets']
+        ]
+        expected_result = {
+            'mouse': {
+                'H_T2': [['M', 'M', 'Molecular Trait Datasets']],
+                'H_T1': [['M', 'M', 'Molecular Trait Datasets']]},
+            'human': {
+                'HLC': [['M', 'M', 'Molecular Trait Datasets']],
+                'BXD': [['M', 'M', 'Molecular Trait Datasets']]}}
+        self.assertEqual(get_types(self.test_group, mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.build_datasets')
+    def test_get_datasets_with_existent_datasets(self,
+                                                 build_datasets_mock):
+        """Test correct dataset is returned with existent build_datasets"""
+        build_datasets_mock.return_value = "Test"
+        expected_result = {
+            'mouse': {
+                'H_T2': {'Genotypes': 'Test',
+                         'M': 'Test',
+                         'Phenotypes': 'Test'},
+                'H_T1': {'Genotypes': 'Test',
+                         'M': 'Test',
+                         'Phenotypes': 'Test'}},
+            'human': {'HLC': {'Genotypes': 'Test',
+                              'M': 'Test',
+                              'Phenotypes': 'Test'},
+                      'BXD': {'Genotypes': 'Test',
+                              'M': 'Test',
+                              'Phenotypes': 'Test'}}}
+        self.assertEqual(get_datasets(self.test_type, mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.build_datasets')
+    def test_get_datasets_with_non_existent_datasets(self,
+                                                     build_datasets_mock):
+        """Test correct dataset is returned with non-existent build_datasets"""
+        build_datasets_mock.return_value = None
+        expected_result = {
+            'mouse': {
+                'H_T2': {},
+                'H_T1': {}},
+            'human': {'HLC': {},
+                      'BXD': {}}}
+        self.assertEqual(get_datasets(self.test_type, mock.MagicMock()),
+                         expected_result)
+
+    @mock.patch('wqflask.api.gen_menu.get_datasets')
+    @mock.patch('wqflask.api.gen_menu.get_types')
+    @mock.patch('wqflask.api.gen_menu.get_groups')
+    @mock.patch('wqflask.api.gen_menu.get_all_species')
+    def test_gen_dropdown_json(self,
+                               species_mock,
+                               groups_mock,
+                               types_mock,
+                               datasets_mock):
+        "Test that the correct dictionary is constructed properly"
+        species_mock.return_value = ("speciesA speciesB speciesC speciesD"
+                                     .split(" "))
+        datasets_mock.return_value = ("datasetA datasetB datasetC datasetD"
+                                      .split(" "))
+        groups_mock.return_value = ("groupA groupB groupC groupD"
+                                    .split(" "))
+        types_mock.return_value = ("typeA typeB typeC typeD"
+                                   .split(" "))
+        datasets_mock.return_value = ("datasetA datasetB datasetC datasetD"
+                                      .split(" "))
+
+        expected_result = {
+            'datasets': ['datasetA', 'datasetB', 'datasetC', 'datasetD'],
+            'types': ['typeA', 'typeB', 'typeC', 'typeD'],
+            'groups': ['groupA', 'groupB', 'groupC', 'groupD'],
+            'species': ['speciesA', 'speciesB', 'speciesC', 'speciesD']}
+
+        self.assertEqual(gen_dropdown_json(mock.MagicMock()), expected_result)
diff --git a/gn2/tests/unit/wqflask/api/test_mapping.py b/gn2/tests/unit/wqflask/api/test_mapping.py
new file mode 100644
index 00000000..1553cbf6
--- /dev/null
+++ b/gn2/tests/unit/wqflask/api/test_mapping.py
@@ -0,0 +1,113 @@
+import unittest
+from unittest import mock
+from gn2.wqflask.api.mapping import initialize_parameters
+from gn2.wqflask.api.mapping import do_mapping_for_api
+
+
+class AttributeSetter:
+    def __init__(self, obj):
+        for key, value in obj.items():
+            setattr(self, key, value)
+
+
+class MockGroup(AttributeSetter):
+    def get_marker(self):
+        self.markers = []
+
+
+class TestMapping(unittest.TestCase):
+
+    def test_initialize_parameters(self):
+        expected_results = {
+            "format": "json",
+            "limit_to": False,
+            "mapping_method": "gemma",
+            "maf": 0.01,
+            "use_loco": True,
+            "num_perm": 0,
+            "perm_check": False,
+            "transform": False,
+            "genofile": False
+        }
+
+        results = initialize_parameters(
+            start_vars={}, dataset={}, this_trait={})
+        self.assertEqual(results, expected_results)
+
+        start_vars = {
+            "format": "F1",
+            "limit_to": "1",
+            "mapping_method": "rqtl",
+            "control_marker": True,
+            "pair_scan": "true",
+            "interval_mapping": "true",
+            "use_loco": "true",
+            "num_perm": "14",
+            "transform": "qnorm",
+            "genofile": "BXD.8.geno"
+        }
+
+        results_2 = initialize_parameters(
+            start_vars=start_vars, dataset={}, this_trait={})
+        expected_results = {
+            "format": "F1",
+            "limit_to": 1,
+            "mapping_method": "gemma",
+            "maf": 0.01,
+            "use_loco": True,
+            "num_perm": 14,
+            "perm_check": "ON",
+            "transform": "qnorm",
+            "genofile": "BXD.8.geno"
+        }
+
+        self.assertEqual(results_2, expected_results)
+
+    @mock.patch("wqflask.api.mapping.rqtl_mapping.run_rqtl")
+    @mock.patch("wqflask.api.mapping.gemma_mapping.run_gemma")
+    @mock.patch("wqflask.api.mapping.initialize_parameters")
+    @mock.patch("wqflask.api.mapping.retrieve_sample_data")
+    @mock.patch("wqflask.api.mapping.create_trait")
+    @mock.patch("wqflask.api.mapping.data_set.create_dataset")
+    def test_do_mapping_for_api(self, mock_create_dataset, mock_trait, mock_retrieve_sample, mock_param, run_gemma, run_rqtl_geno):
+        start_vars = {
+            "db": "Temp",
+            "trait_id": "dewf3232rff2",
+            "format": "F1",
+            "mapping_method": "gemma",
+            "use_loco": True
+
+        }
+        sampleList = ["S1", "S2", "S3", "S4"]
+        samplelist = ["S1", "S2", "S4"]
+        dataset = AttributeSetter({"group": samplelist})
+        this_trait = AttributeSetter({})
+        trait_data = AttributeSetter({
+            "data": {
+                "item1": AttributeSetter({"name": "S1", "value": "S1_value"}),
+                "item2": AttributeSetter({"name": "S2", "value": "S2_value"}),
+                "item3": AttributeSetter({"name": "S3", "value": "S3_value"}),
+
+            }
+        })
+        trait = AttributeSetter({
+            "data": trait_data
+        })
+
+        dataset.return_value = dataset
+        mock_trait.return_value = this_trait
+
+        mock_retrieve_sample.return_value = trait
+        mock_param.return_value = {
+            "format": "F1",
+            "limit_to": False,
+            "mapping_method": "gemma",
+            "maf": 0.01,
+            "use_loco": "True",
+            "num_perm": 14,
+            "perm_check": "ON"
+        }
+
+        run_gemma.return_value = ["results"]
+        results = do_mapping_for_api(start_vars=start_vars)
+        self.assertEqual(results, ("results", None))
diff --git a/gn2/tests/unit/wqflask/api/test_markdown_routes.py b/gn2/tests/unit/wqflask/api/test_markdown_routes.py
new file mode 100644
index 00000000..f0f93bc1
--- /dev/null
+++ b/gn2/tests/unit/wqflask/api/test_markdown_routes.py
@@ -0,0 +1,54 @@
+"""Test functions for wqflask/api/markdown.py"""
+
+import unittest
+from unittest import mock
+
+from dataclasses import dataclass
+from gn2.wqflask.api.markdown import render_markdown
+
+
+@dataclass
+class MockRequests404:
+    status_code: int = 404
+
+
+@dataclass
+class MockRequests200:
+    status_code: int = 200
+    content: str = b"""
+# Glossary
+This is some content
+
+## Sub-heading
+This is another sub-heading"""
+
+
+class TestMarkdownRoutesFunctions(unittest.TestCase):
+    """Test cases for functions in markdown"""
+
+    @mock.patch('wqflask.api.markdown.requests.get')
+    def test_render_markdown_when_fetching_locally(self, requests_mock):
+        requests_mock.return_value = MockRequests404()
+        markdown_content = render_markdown("general/glossary/glossary.md")
+        requests_mock.assert_called_with(
+            "https://raw.githubusercontent.com"
+            "/genenetwork/gn-docs/"
+            "master/general/"
+            "glossary/glossary.md")
+        self.assertRegex(markdown_content,
+                         "Content for general/glossary/glossary.md not available.")
+
+    @mock.patch('wqflask.api.markdown.requests.get')
+    def test_render_markdown_when_fetching_remotely(self, requests_mock):
+        requests_mock.return_value = MockRequests200()
+        markdown_content = render_markdown("general/glossary/glossary.md")
+        requests_mock.assert_called_with(
+            "https://raw.githubusercontent.com"
+            "/genenetwork/gn-docs/"
+            "master/general/"
+            "glossary/glossary.md")
+        self.assertEqual("""<h1>Glossary</h1>
+<p>This is some content</p>
+<h2>Sub-heading</h2>
+<p>This is another sub-heading</p>""",
+                         markdown_content)