from emails import pop_account, peek_accounts, remaining_count, _parse_line import emails as em def test_parse_line(): acc = _parse_line("user@example.com:pass123") assert acc is not None assert acc.email == "user@example.com" assert acc.password == "pass123" def test_parse_line_with_colon_in_password(): acc = _parse_line("user@example.com:pass:with:colons") assert acc is not None assert acc.password == "pass:with:colons" def test_parse_line_empty(): assert _parse_line("") is None assert _parse_line(" ") is None assert _parse_line("# comment") is None def test_parse_line_malformed(): assert _parse_line("no-colon-here") is None def test_peek_accounts(tmp_path, monkeypatch): f = tmp_path / "emails.txt" f.write_text("a@b.com:pass1\nc@d.com:pass2\n") monkeypatch.setattr(em, "EMAILS_FILE", f) accounts = peek_accounts() assert len(accounts) == 2 assert accounts[0].email == "a@b.com" assert accounts[1].email == "c@d.com" # peek doesn't consume assert remaining_count() == 2 def test_pop_account(tmp_path, monkeypatch): f = tmp_path / "emails.txt" f.write_text("a@b.com:pass1\nc@d.com:pass2\ne@f.com:pass3\n") monkeypatch.setattr(em, "EMAILS_FILE", f) acc = pop_account() assert acc is not None assert acc.email == "a@b.com" assert remaining_count() == 2 acc = pop_account() assert acc is not None assert acc.email == "c@d.com" assert remaining_count() == 1 def test_pop_account_empty(tmp_path, monkeypatch): f = tmp_path / "emails.txt" f.write_text("") monkeypatch.setattr(em, "EMAILS_FILE", f) assert pop_account() is None def test_pop_account_missing_file(tmp_path, monkeypatch): monkeypatch.setattr(em, "EMAILS_FILE", tmp_path / "nope.txt") assert pop_account() is None def test_pop_skips_comments(tmp_path, monkeypatch): f = tmp_path / "emails.txt" f.write_text("# first is comment\na@b.com:pass1\n") monkeypatch.setattr(em, "EMAILS_FILE", f) acc = pop_account() assert acc is not None assert acc.email == "a@b.com" # Comment line stays in file remaining = f.read_text().strip() assert remaining == "# first is comment"