From 6c4b9e3cfdbecda51efe442aec452f2a9913b8a0 Mon Sep 17 00:00:00 2001
From: linuxdaemon <linuxdaemon.irc@gmail.com>
Date: Sun, 17 Mar 2024 21:12:16 +0000
Subject: [PATCH] Add tests for the hookup plugin

---
 plugins/hookup.py                 |   6 +-
 pytest.ini                        |   1 +
 requirements-dev.txt              |   1 +
 tests/conftest.py                 |   7 ++
 tests/plugin_tests/hookup_test.py | 125 ++++++++++++++++++++++++++++++
 5 files changed, 138 insertions(+), 2 deletions(-)
 create mode 100644 tests/plugin_tests/hookup_test.py

diff --git a/plugins/hookup.py b/plugins/hookup.py
index abb23f04..889b507f 100644
--- a/plugins/hookup.py
+++ b/plugins/hookup.py
@@ -39,21 +39,23 @@ def hookup(db, chan):
         select(
             [seen_table.c.name],
             and_(seen_table.c.chan == chan, seen_table.c.time > times),
-        )
+        ).order_by(seen_table.c.time)
     ).fetchall()
 
     if not results or len(results) < 2:
         return "something went wrong"
 
     # Make sure the list of people is unique
-    people = list({row[0] for row in results})
+    people = sorted({row[0] for row in results})
     random.shuffle(people)
     person1, person2 = people[:2]
     variables = {
         "user1": person1,
         "user2": person2,
     }
+
     generator = TextGenerator(
         hookups["templates"], hookups["parts"], variables=variables
     )
+
     return generator.generate_string()
diff --git a/pytest.ini b/pytest.ini
index c88bfb7f..c5afd130 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -7,6 +7,7 @@ addopts =
     --cov-report=html
     --doctest-modules
     --random-order
+    --pythonhashseed=123
 testpaths = .
 filterwarnings =
     error
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 15945685..0cf5b0f2 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -6,6 +6,7 @@ pytest == 8.1.1
 pytest-asyncio == 0.20.3
 pytest-cov == 4.1.0
 pytest-random-order == 1.1.1
+pytest-pythonhashseed == 1.0.1
 responses == 0.25.0
 typing_extensions == 4.10.0
 types-requests ~= 2.31.0.20240311
diff --git a/tests/conftest.py b/tests/conftest.py
index 42ceed3c..bcd5685e 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -17,6 +17,13 @@
 from tests.util.mock_db import MockDB
 
 
+@pytest.fixture(autouse=True)
+def clear_metadata():
+    database.metadata.clear()
+    yield
+    database.metadata.clear()
+
+
 @pytest.fixture()
 def tmp_logs(tmp_path):
     cloudbot._setup(tmp_path)
diff --git a/tests/plugin_tests/hookup_test.py b/tests/plugin_tests/hookup_test.py
new file mode 100644
index 00000000..5369371b
--- /dev/null
+++ b/tests/plugin_tests/hookup_test.py
@@ -0,0 +1,125 @@
+import random
+from datetime import timedelta
+from pathlib import Path
+
+from cloudbot.util import database
+from plugins import hookup, seen
+from tests.util.mock_db import MockDB
+
+
+def test_load_data(mock_bot_factory):
+    bot = mock_bot_factory(
+        base_dir=Path(__file__).parent.parent.parent.resolve()
+    )
+    hookup.load_data(bot)
+    assert hookup.hookups
+
+
+def test_hookup_no_seen(mock_db: MockDB):
+    db = mock_db.session()
+    res = hookup.hookup(db, "#chan")
+    assert res is None
+
+
+def test_hookup_no_data(mock_db: MockDB):
+    database.metadata._add_table(seen.table.name, seen.table.schema, seen.table)
+    seen.table.create(mock_db.engine)
+    db = mock_db.session()
+    res = hookup.hookup(db, "#chan")
+    assert res == "something went wrong"
+
+
+def test_hookup_one_user(mock_db: MockDB, freeze_time):
+    database.metadata._add_table(seen.table.name, seen.table.schema, seen.table)
+    seen.table.create(mock_db.engine)
+
+    mock_db.load_data(
+        seen.table,
+        [
+            {
+                "name": "testnick",
+                "time": (
+                    freeze_time.time_to_freeze - timedelta(hours=1)
+                ).timestamp(),
+                "quote": "foo bar baz",
+                "chan": "#chan",
+                "host": "user@host",
+            },
+        ],
+    )
+
+    db = mock_db.session()
+    res = hookup.hookup(db, "#chan")
+    assert res == "something went wrong"
+
+
+def test_hookup_basic(mock_db: MockDB, freeze_time):
+    hookup.hookups = {
+        "templates": [
+            "{user1} : {user2}",
+        ],
+        "parts": {},
+    }
+
+    database.metadata._add_table(seen.table.name, seen.table.schema, seen.table)
+    seen.table.create(mock_db.engine)
+    mock_db.load_data(
+        seen.table,
+        [
+            {
+                "name": "testnick",
+                "time": (
+                    freeze_time.time_to_freeze - timedelta(hours=2)
+                ).timestamp(),
+                "quote": "foo bar baz",
+                "chan": "#chan",
+                "host": "user@host",
+            },
+            {
+                "name": "testnick2",
+                "time": (
+                    freeze_time.time_to_freeze - timedelta(hours=1)
+                ).timestamp(),
+                "quote": "foo bar baz",
+                "chan": "#chan",
+                "host": "user@host",
+            },
+        ],
+    )
+
+    db = mock_db.session()
+    random.seed(1)
+    res = hookup.hookup(db, "#chan")
+    assert res == "testnick : testnick2"
+
+
+def test_hookup_active_time(mock_db: MockDB, freeze_time):
+    database.metadata._add_table(seen.table.name, seen.table.schema, seen.table)
+    seen.table.create(mock_db.engine)
+    mock_db.load_data(
+        seen.table,
+        [
+            {
+                "name": "testnick",
+                "time": (
+                    freeze_time.time_to_freeze - timedelta(weeks=1)
+                ).timestamp(),
+                "quote": "foo bar baz",
+                "chan": "#chan",
+                "host": "user@host",
+            },
+            {
+                "name": "testnick2",
+                "time": (
+                    freeze_time.time_to_freeze - timedelta(hours=1)
+                ).timestamp(),
+                "quote": "foo bar baz",
+                "chan": "#chan",
+                "host": "user@host",
+            },
+        ],
+    )
+
+    db = mock_db.session()
+    res = hookup.hookup(db, "#chan")
+    assert res == "something went wrong"