161 lines
6.0 KiB
Python
161 lines
6.0 KiB
Python
import pytest
|
|
|
|
from dpdapi.models import Alias, Domain
|
|
|
|
FIELDS = {"id", "created", "updated", "source", "destination", "domain", "active"}
|
|
|
|
|
|
@pytest.fixture
|
|
def aliases(domain):
|
|
other = Domain.objects.create(name="other.org")
|
|
return [
|
|
Alias.objects.create(source="ops-alert@example.com", destination="ninja@example.com", domain=domain),
|
|
Alias.objects.create(source="yolo-announce@example.com", destination="ninja@example.com", domain=domain),
|
|
Alias.objects.create(source="Ops@Other.org", destination="Boss@Other.org", domain=other),
|
|
]
|
|
|
|
|
|
def sources(res):
|
|
assert res.status_code == 200
|
|
return sorted(a["source"] for a in res.json())
|
|
|
|
|
|
def test_list(api, aliases):
|
|
res = api.get("/api/aliases/")
|
|
assert res.status_code == 200
|
|
body = res.json()
|
|
assert len(body) == 3
|
|
assert set(body[0]) == FIELDS
|
|
first = next(a for a in body if a["id"] == aliases[0].pk)
|
|
assert first["source"] == "ops-alert@example.com"
|
|
assert first["destination"] == "ninja@example.com"
|
|
assert first["domain"] == aliases[0].domain_id
|
|
assert first["active"] is True
|
|
|
|
|
|
def test_addresses_are_lowercased(aliases):
|
|
assert aliases[2].source == "ops@other.org"
|
|
assert aliases[2].destination == "boss@other.org"
|
|
assert str(aliases[2]) == "ops@other.org=boss@other.org"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("params", "expected"),
|
|
[
|
|
({"domain__name": "example.com"}, ["ops-alert@example.com", "yolo-announce@example.com"]),
|
|
({"domain__name": "nope.com"}, []),
|
|
({"source__regex": "^ops-|^ops@"}, ["ops-alert@example.com", "ops@other.org"]),
|
|
({"source__regex": "^OPS"}, []),
|
|
({"source__iregex": "^OPS"}, ["ops-alert@example.com", "ops@other.org"]),
|
|
({"destination__regex": "^boss"}, ["ops@other.org"]),
|
|
({"destination__iregex": "^NINJA"}, ["ops-alert@example.com", "yolo-announce@example.com"]),
|
|
({"domain__name": "example.com", "source__regex": "^yolo"}, ["yolo-announce@example.com"]),
|
|
],
|
|
)
|
|
def test_filters(api, aliases, params, expected):
|
|
assert sources(api.get("/api/aliases/", params)) == expected
|
|
|
|
|
|
def test_filter_by_domain_id(api, aliases):
|
|
res = api.get("/api/aliases/", {"domain": aliases[2].domain_id})
|
|
assert sources(res) == ["ops@other.org"]
|
|
|
|
|
|
def test_create_bulk(api, domain):
|
|
data = [
|
|
{"source": "A@example.com", "destination": "b@example.com", "domain": domain.pk},
|
|
{"source": "c@example.com", "destination": "d@example.com", "domain": domain.pk, "active": False},
|
|
]
|
|
res = api.post("/api/aliases/create_bulk/", data, content_type="application/json")
|
|
assert res.status_code == 201
|
|
body = res.json()
|
|
assert [(a["source"], a["destination"], a["active"]) for a in body] == [
|
|
("a@example.com", "b@example.com", True),
|
|
("c@example.com", "d@example.com", False),
|
|
]
|
|
assert all(set(a) == FIELDS for a in body)
|
|
assert Alias.objects.count() == 2
|
|
|
|
|
|
def test_create_bulk_accepts_existing(api, aliases):
|
|
existing = aliases[0]
|
|
data = [{"source": existing.source, "destination": existing.destination, "domain": existing.domain_id}]
|
|
res = api.post("/api/aliases/create_bulk/", data, content_type="application/json")
|
|
assert res.status_code == 201
|
|
assert res.json()[0]["id"] == existing.pk
|
|
assert Alias.objects.count() == 3
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"item",
|
|
[
|
|
{"source": "not-an-email", "destination": "b@example.com"},
|
|
{"source": "a@example.com"},
|
|
{"source": "a@example.com", "destination": "b@example.com", "domain": 999},
|
|
],
|
|
)
|
|
def test_create_bulk_invalid(api, domain, item):
|
|
item.setdefault("domain", domain.pk)
|
|
res = api.post("/api/aliases/create_bulk/", [item], content_type="application/json")
|
|
assert res.status_code == 400
|
|
assert Alias.objects.count() == 0
|
|
|
|
|
|
def test_create_bulk_requires_list(api, domain):
|
|
data = {"source": "a@example.com", "destination": "b@example.com", "domain": domain.pk}
|
|
res = api.post("/api/aliases/create_bulk/", data, content_type="application/json")
|
|
assert res.status_code == 400
|
|
|
|
|
|
def test_delete_bulk(api, aliases):
|
|
data = [{"source": a.source, "destination": a.destination, "domain": a.domain_id} for a in aliases[:2]]
|
|
res = api.delete("/api/aliases/delete_bulk/", data, content_type="application/json")
|
|
assert res.status_code == 204
|
|
assert list(Alias.objects.all()) == [aliases[2]]
|
|
|
|
|
|
def test_delete_bulk_empty(api, aliases):
|
|
res = api.delete("/api/aliases/delete_bulk/", [], content_type="application/json")
|
|
assert res.status_code == 204
|
|
assert Alias.objects.count() == 3
|
|
|
|
|
|
def test_delete_bulk_reports_missing(api, aliases):
|
|
data = [
|
|
{"source": aliases[0].source, "destination": aliases[0].destination, "domain": aliases[0].domain_id},
|
|
{"source": "ghost@example.com", "destination": "ninja@example.com", "domain": aliases[0].domain_id},
|
|
]
|
|
res = api.delete("/api/aliases/delete_bulk/", data, content_type="application/json")
|
|
assert res.status_code == 200
|
|
assert res.json() == {
|
|
"result": "Aliases 'ghost@example.com=ninja@example.com' could not be found and were not deleted."
|
|
}
|
|
assert Alias.objects.count() == 2
|
|
|
|
|
|
def test_delete_bulk_only_matches_exact_alias(api, aliases):
|
|
"""Extra keys must not widen the match to other aliases."""
|
|
data = [
|
|
{
|
|
"source": "ghost@example.com",
|
|
"destination": "ninja@example.com",
|
|
"domain": aliases[0].domain_id,
|
|
"source__regex": ".*",
|
|
}
|
|
]
|
|
res = api.delete("/api/aliases/delete_bulk/", data, content_type="application/json")
|
|
assert res.status_code == 200
|
|
assert Alias.objects.count() == 3
|
|
|
|
|
|
def test_delete_bulk_invalid(api, aliases):
|
|
res = api.delete("/api/aliases/delete_bulk/", [{"source": "x"}], content_type="application/json")
|
|
assert res.status_code == 400
|
|
assert Alias.objects.count() == 3
|
|
|
|
|
|
@pytest.mark.parametrize("method", ["post", "put", "patch"])
|
|
def test_alias_detail_routes_do_not_exist(api, aliases, method):
|
|
res = getattr(api, method)("/api/aliases/", {}, content_type="application/json")
|
|
assert res.status_code == 405
|