def setUpClass(cls) -> None: super(MangadexTests, cls).setUpClass() dbutil = DbUtil(cls._conn) dbutil.add_authors([ AuthorPartial(name='Im Dal-Young', mangadex_id='d21a9418-817a-43e5-a4d2-bf1e7391d7ec') ]) dbutil.add_manga_service(MangaService( service_id=MangaDex.ID, title_id='6fe9349a-8eeb-42cf-bead-e6f40b2653de', title="I Was Born as the Demon Lord's Daughter" ), add_manga=True) api_path = os.path.join(os.path.dirname(__file__), 'api_data') with open(os.path.join(api_path, 'chapters.json'), 'r', encoding='utf-8') as f: cls.chapters_data = json.load(f) with open(os.path.join(api_path, 'manga.json'), 'r', encoding='utf-8') as f: cls.manga_data = json.load(f)
class DatabaseTestCase(unittest.TestCase): _conn: Connection = NotImplemented _generator: 'BaseTestClasses.TitleIdGenerator' = NotImplemented @classmethod def setUpClass(cls) -> None: cls._conn = get_conn() # Integers are retained during tests but they reset to the default value # for some reason. Circumvent this by using a class. cls._generator = BaseTestClasses.TitleIdGenerator() @property def conn(self) -> Connection: return self._conn def setUp(self) -> None: self.dbutil = DbUtil(self._conn) @classmethod def tearDownClass(cls) -> None: cls._conn.close() def get_str_id(self) -> str: return self._generator.generate(type(self).__name__) def get_manga_service(self, scraper: Type['BaseScraper'] = DummyScraper) -> MangaService: id_ = self.get_str_id() return MangaService(service_id=scraper.ID, title_id=id_, title=f'{id_}_manga') def create_manga_service(self, scraper: Type['BaseScraper'] = DummyScraper) -> MangaService: id_ = self.get_str_id() ms = MangaService(service_id=scraper.ID, title_id=id_, title=f'{id_}_manga') return self.dbutil.add_manga_service(ms, add_manga=True) def assertChapterEqualsRow(self, chapter: 'Chapter', row: DictRow) -> None: pairs = [ ('chapter_title', 'title'), ('chapter_number', 'chapter_number'), ('decimal', 'chapter_decimal'), ('release_date', 'release_date', lambda: (getattr(chapter, 'release_date'), date_fix(row['release_date'])) ), ('chapter_identifier', 'chapter_identifier'), ('group', 'group') ] for val in pairs: chapter_attr, row_attr = val[:2] if len(val) == 3: get_vals = val[2] else: def get_vals(): return getattr(chapter, chapter_attr), row[row_attr] c_val, r_val = get_vals() # type: ignore[operator] if c_val != r_val: self.fail( 'Chapter from database does not equal model\n' f'{chapter_attr} != {row_attr}\n' f'{c_val} != {row[row_attr]}' ) def assertDatesEqual(self, date1: datetime, date2: datetime): if date_fix(date1) != date_fix(date2): self.fail(f'Date {date1} does not match date {date2}') def assertDatesNotEqual(self, date1: datetime, date2: datetime): if date_fix(date1) == date_fix(date2): self.fail(f'Date {date1} equals date {date2}') def assertDateGreater(self, date1: datetime, date2: datetime): if date_fix(date1) <= date_fix(date2): self.fail(f'Date {date1} is earlier or equal to {date2}') def assertDateLess(self, date1: datetime, date2: datetime): if date_fix(date1) >= date_fix(date2): self.fail(f'Date {date1} is later or equal to {date2}') def assertDatesAlmostEqual(self, date1: datetime, date2: datetime, delta: timedelta = timedelta(seconds=1), msg: str = None): date1 = date_fix(date1) date2 = date_fix(date2) self.assertAlmostEqual(date1, date2, delta=delta, msg=msg) def assertMangaServiceExists(self, title_id: str, service_id: int): sql = 'SELECT 1 FROM manga_service WHERE service_id=%s AND title_id=%s' with self.conn.cursor() as cur: cur.execute(sql, (service_id, title_id)) row = cur.fetchone() self.assertIsNotNone(row, msg=f'Manga {title_id} not found') def assertMangaWithTitleFound(self, title: str): self.assertIsNotNone( self.dbutil.find_manga_by_title(title), msg=f'Manga with title {title} not found when expected to be found' ) @staticmethod def utcnow() -> datetime: """ Return utc time with psycopg2 timezone """ return datetime.utcnow().replace(tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None))