"""Personal question libraries: what they report, and who may touch them. Disposable SQLite, as everywhere in these tests. The rule the page depends on is the ordering: most recently used first, and a library nobody has opened sorts by when it was made rather than claiming a use that never happened. """ import unittest from datetime import datetime import test_quiz_builder as fixtures from app.models.collection import UserCollection from app.routers import collections class CollectionTests(unittest.TestCase): def setUp(self): self.bank = fixtures.BuilderTests() self.bank.setUp() self.client = self.bank.client self.db = self.bank.db self.client.app.include_router(collections.router, prefix='/collections') def tearDown(self): self.bank.tearDown() def make(self, title): response = self.client.post('/collections/', json={'title': title}) self.assertEqual(response.status_code, 201, response.text) return response.json() def listed(self): response = self.client.get('/collections/') self.assertEqual(response.status_code, 200, response.text) return response.json() def test_a_new_library_reports_what_the_page_shows(self): row = self.make('Cardiology misses') self.assertEqual(row['title'], 'Cardiology misses') self.assertEqual(row['question_count'], 0) self.assertTrue(row['private']) self.assertIsNone(row['last_used_at']) self.assertIsNotNone(row['created_at']) def test_adding_a_question_counts_it_and_marks_the_library_used(self): row = self.make('Saved') self.assertEqual(self.client.put(f"/collections/{row['id']}/questions/1").status_code, 200) # The same question twice is one question. self.assertFalse(self.client.put(f"/collections/{row['id']}/questions/1").json()['added']) after = self.listed()[0] self.assertEqual(after['question_count'], 1) self.assertIsNotNone(after['last_used_at']) def test_opening_a_library_is_using_it(self): row = self.make('Saved') self.assertIsNone(self.listed()[0]['last_used_at']) self.assertEqual(self.client.get(f"/collections/{row['id']}/questions").status_code, 200) self.assertIsNotNone(self.listed()[0]['last_used_at']) def test_most_recently_used_first_and_the_unused_by_age(self): from datetime import datetime old = self.make('Older') new = self.make('Newer') used = self.make('Used long ago') # An explicit clock: two rows made in the same second cannot be # ordered by when they were made. self.db.get(UserCollection, old['id']).created_at = datetime(2026, 1, 1) self.db.get(UserCollection, new['id']).created_at = datetime(2026, 6, 1) row = self.db.get(UserCollection, used['id']) row.created_at = datetime(2025, 1, 1) row.last_used_at = datetime(2026, 9, 1) self.db.commit() # Used beats made, and among the never-used the newer one is first. self.assertEqual([c['title'] for c in self.listed()], ['Used long ago', 'Newer', 'Older']) def test_a_library_belongs_to_one_person(self): row = self.make('Mine') self.bank.user = self.bank.peer self.assertEqual(self.listed(), []) self.assertEqual(self.client.patch(f"/collections/{row['id']}", json={'title': 'Yours'}).status_code, 403) self.assertEqual(self.client.delete(f"/collections/{row['id']}").status_code, 403) self.assertEqual(self.client.get(f"/collections/{row['id']}/questions").status_code, 403) def test_a_question_nobody_can_see_cannot_be_saved(self): row = self.make('Mine') # Question 4 has been removed from the bank; question 3 is an ordinary # bank question and theirs to save. self.bank.db.get(fixtures.Question, 4).deleted_at = datetime(2026, 1, 1) self.bank.db.commit() self.assertEqual(self.client.put(f"/collections/{row['id']}/questions/4").status_code, 404) self.assertEqual(self.client.put(f"/collections/{row['id']}/questions/3").status_code, 200)