unifi_access/tests/test_visitor.py

812 lines
31 KiB
Python

import datetime
import responses
from responses import matchers
from unifi_access.schemas import (
DoorGroupId,
DoorGroupResource,
DoorId,
DoorResource,
FetchAllVisitorsExpansion,
NfcCardToken,
TimePeriod,
VisitorId,
VisitReason,
WeekSchedule,
)
from .base import UnifiAccessTests
class VisitorTests(UnifiAccessTests):
@responses.activate
def test_create_visitor(self) -> None:
"""4.2 Create Visitor"""
responses.post(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.json_params_matcher(
{
"first_name": "H",
"last_name": "L",
"remarks": "",
"mobile_phone": "",
"email": "",
"visitor_company": "",
"start_time": 1688546460,
"end_time": 1788572799,
# NOTE: typo'ed in api docs to "Interviemw"
"visit_reason": "Interview",
"week_schedule": {
"sunday": [],
"monday": [],
"tuesday": [
{"start_time": "10:00:00", "end_time": "17:00:59"}
],
"wednesday": [
{"start_time": "10:00:00", "end_time": "17:00:59"}
],
"thursday": [
{"start_time": "11:00:00", "end_time": "17:00:59"}
],
"friday": [
{"start_time": "10:00:00", "end_time": "17:00:59"}
],
"saturday": [],
},
"resources": [
{
"id": "6ff875d2-af87-470b-9cb5-774c6596afc8",
"type": "door",
},
{
"id": "5c496423-6d25-4e4f-8cdf-95ad5135188a",
"type": "door_group",
},
{
"id": "d5573467-d6b3-4e8f-8e48-8a322b91664a",
"type": "door_group",
},
],
}
),
],
json={
"code": "SUCCESS",
"data": {
"first_name": "H",
"id": "fbe8d920-47d3-4cfd-bda7-bf4b0e26f73c",
"last_name": "L",
"nfc_cards": [],
"resources": [
{
"id": "5c496423-6d25-4e4f-8cdf-95ad5135188a",
"name": "Test Group",
"type": "door_group",
},
{
"id": "d5573467-d6b3-4e8f-8e48-8a322b91664a",
"name": "UNVR",
"type": "door_group",
},
{
"id": "369215b0-cabe-49b6-aeaa-e0b7ec6424d5",
"name": "visitor-1691671529285",
"type": "door_group",
},
],
"schedule": {
"id": "1fb849bb-e7e5-4516-8dd9-b78094a6708a",
"is_default": False,
"name": "schedule-1691671529237",
"type": "access",
"weekly": {
"friday": [
{"end_time": "17:00:59", "start_time": "10:00:00"}
],
"monday": [],
"saturday": [],
"sunday": [],
"thursday": [
{"end_time": "17:00:59", "start_time": "11:00:00"}
],
"tuesday": [
{"end_time": "17:00:59", "start_time": "10:00:00"}
],
"wednesday": [
{"end_time": "17:00:59", "start_time": "10:00:00"}
],
},
},
"schedule_id": "1fb849bb-e7e5-4516-8dd9-b78094a6708a",
"status": "ACTIVE",
},
"msg": "success",
},
)
resp = self.client.create_visitor(
first_name="H",
last_name="L",
remarks="",
mobile_phone="",
email="",
visitor_company="",
start_time=datetime.datetime.fromtimestamp(1688546460, tz=datetime.UTC),
end_time=datetime.datetime.fromtimestamp(1788572799, tz=datetime.UTC),
visit_reason=VisitReason.INTERVIEW,
week_schedule=WeekSchedule(
sunday=[],
monday=[],
tuesday=[
TimePeriod(
start_time=datetime.time(10, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
wednesday=[
TimePeriod(
start_time=datetime.time(10, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
thursday=[
TimePeriod(
start_time=datetime.time(11, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
friday=[
TimePeriod(
start_time=datetime.time(10, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
saturday=[],
),
resources=[
DoorResource(
id=DoorId("6ff875d2-af87-470b-9cb5-774c6596afc8"),
),
DoorGroupResource(
id=DoorGroupId("5c496423-6d25-4e4f-8cdf-95ad5135188a"),
),
DoorGroupResource(
id=DoorGroupId("d5573467-d6b3-4e8f-8e48-8a322b91664a")
),
],
)
assert resp.id == "fbe8d920-47d3-4cfd-bda7-bf4b0e26f73c"
@responses.activate
def test_fetch_visitor(self) -> None:
"""4.3 Fetch Visitor"""
visitor_id = VisitorId("76794bd8-98c0-49b6-9230-ba8c5812cf29")
responses.get(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}",
match=[
matchers.header_matcher(self.common_headers),
],
json={
"code": "SUCCESS",
"data": {
"first_name": "Hong+243",
"id": "3566867c-fa04-4752-98f6-43cf9a342d4a",
"last_name": "Lu",
"nfc_cards": [
{
"id": "100001",
"token": "d27822fc682b478dc637c6db01813e465174df6e54ca515d8427db623cfda1d0",
"type": "ua_card",
}
],
"pin_code": {
"token": "bc3e3135013e2dcae119390b7897166e8cec3bcf5becb6b05578ab67634559ed"
},
"resources": [
{
"id": "fd293ecb-98d2-425b-a020-cb9365ea48b3",
"name": "visitor-1690337152955",
"type": "door_group",
}
],
"schedule": {
"id": "6ccf9e1e-b174-476d-b2fe-96817c780fbf",
"is_default": False,
"name": "visitor-1690337152955",
"type": "access",
"weekly": None,
},
"schedule_id": "6ccf9e1e-b174-476d-b2fe-96817c780fbf",
"status": "VISITED",
},
"msg": "success",
},
)
resp = self.client.fetch_visitor(visitor_id=visitor_id)
# TODO: verify correctness of data?
@responses.activate
def test_fetch_all_visitors(self) -> None:
"""4.4 Fetch All Visitors"""
responses.get(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher({"page_num": 1, "page_size": 25}),
],
# NOTE: no example data provided in api docs, so this was
# retrieved from a running instance
json={
"code": "SUCCESS",
"data": [
{
"avatar": "",
"email": "",
"end_time": 1731880901,
"first_name": "Test",
"id": "faaffd2e-b555-4991-810f-c18b36407c55",
"inviter_id": "",
"inviter_name": "",
"last_name": "Visitor",
"location_id": "",
"mobile_phone": "",
"nfc_cards": [],
"remarks": "",
"resources": [],
"schedule": {
"holiday_group": None,
"holiday_group_id": "",
"holiday_schedule": [],
"id": "",
"is_default": False,
"name": "",
"type": "",
"weekly": None,
},
"schedule_id": "",
"start_time": 1731794501,
"status": "UPCOMING",
"visit_reason": "Business",
"visitor_company": "",
}
],
"msg": "succ",
"pagination": {"page_num": 1, "page_size": 1, "total": 1},
},
)
resp = self.client.fetch_all_visitors(page_num=1, page_size=25)
assert resp.pagination
# TODO: verify correctness of data?
@responses.activate
def test_fetch_all_visitors_by_keyword(self) -> None:
"""4.4 Fetch All Visitors"""
responses.get(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher({"keyword": "H"}),
],
# NOTE: no example data provided in api docs, so this was
# retrieved from a running instance
json={
"code": "SUCCESS",
"data": [
{
"avatar": "",
"email": "",
"end_time": 1731880901,
"first_name": "Test H",
"id": "faaffd2e-b555-4991-810f-c18b36407c55",
"inviter_id": "",
"inviter_name": "",
"last_name": "Visitor",
"location_id": "",
"mobile_phone": "",
"nfc_cards": [],
"remarks": "",
"resources": [],
"schedule": {
"holiday_group": None,
"holiday_group_id": "",
"holiday_schedule": [],
"id": "",
"is_default": False,
"name": "",
"type": "",
"weekly": None,
},
"schedule_id": "",
"start_time": 1731794501,
"status": "UPCOMING",
"visit_reason": "Business",
"visitor_company": "",
}
],
"msg": "succ",
"pagination": {"page_num": 1, "page_size": 1, "total": 1},
},
)
resp = self.client.fetch_all_visitors(keyword="H")
assert resp.pagination
# TODO: verify correctness of data?
@responses.activate
def test_fetch_all_visitors_with_expand(self) -> None:
"""4.4 Fetch All Visitors"""
responses.get(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher(
{
"expand[]": [
"access_policy",
"resource",
"schedule",
"nfc_card",
"pin_code",
]
}
),
],
# NOTE: no example data provided in api docs, so this was
# retrieved from a running instance
json={
"code": "SUCCESS",
"data": [
{
"avatar": "",
"email": "",
"end_time": 1731880901,
"first_name": "Test",
"id": "faaffd2e-b555-4991-810f-c18b36407c55",
"inviter_id": "",
"inviter_name": "",
"last_name": "Visitor",
"location_id": "",
"mobile_phone": "",
"nfc_cards": [],
"remarks": "",
"resources": [],
"schedule": {
"holiday_group": None,
"holiday_group_id": "",
"holiday_schedule": [],
"id": "",
"is_default": False,
"name": "",
"type": "",
"weekly": None,
},
"schedule_id": "",
"start_time": 1731794501,
"status": "UPCOMING",
"visit_reason": "Business",
"visitor_company": "",
}
],
"msg": "succ",
"pagination": {"page_num": 1, "page_size": 1, "total": 1},
},
)
resp = self.client.fetch_all_visitors(
expand=[
FetchAllVisitorsExpansion.ACCESS_POLICY,
FetchAllVisitorsExpansion.RESOURCE,
FetchAllVisitorsExpansion.SCHEDULE,
FetchAllVisitorsExpansion.NFC_CARD,
FetchAllVisitorsExpansion.PIN_CODE,
]
)
assert resp.pagination
# TODO: verify correctness of data?
# NOTE: not taken from API example
@responses.activate
def test_fetch_all_visitors_without_expand(self) -> None:
"""4.4 Fetch All Visitors"""
responses.get(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher({"expand[]": "none"}),
],
# NOTE: retrieved from a running instance
json={
"code": "SUCCESS",
"data": [
{
"avatar": "",
"email": "",
"end_time": 1731907089,
"first_name": "Test",
"id": "173c4cb9-e174-4a83-89fa-01ba8f25362f",
"inviter_id": "",
"inviter_name": "",
"last_name": "Visitor",
"location_id": "",
"mobile_phone": "",
"nfc_cards": [],
"pin_code": {},
"remarks": "",
"resources": [],
"schedule_id": "",
"start_time": 1731820689,
"status": "UPCOMING",
"visit_reason": "Business",
"visitor_company": "",
},
],
"msg": "succ",
"pagination": {"page_num": 1, "page_size": 1, "total": 1},
},
)
resp = self.client.fetch_all_visitors(expand=[FetchAllVisitorsExpansion.NONE])
assert resp.pagination
# TODO: verify correctness of data?
# NOTE: not taken from API docs examples
@responses.activate
def test_fetch_all_visitors__unpaged(self) -> None:
"""4.4 Fetch All Visitors"""
responses.get(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher({"page_num": 1, "page_size": 1}),
],
json={
"code": "SUCCESS",
"data": [
{
"avatar": "",
"email": "",
"end_time": 1731880901,
"first_name": "Test",
"id": "faaffd2e-b555-4991-810f-c18b36407c55",
"inviter_id": "",
"inviter_name": "",
"last_name": "Visitor",
"location_id": "",
"mobile_phone": "",
"nfc_cards": [],
"remarks": "",
"resources": [],
"schedule": {
"holiday_group": None,
"holiday_group_id": "",
"holiday_schedule": [],
"id": "",
"is_default": False,
"name": "",
"type": "",
"weekly": None,
},
"schedule_id": "",
"start_time": 1731794501,
"status": "UPCOMING",
"visit_reason": "Business",
"visitor_company": "",
}
],
"msg": "succ",
"pagination": {"page_num": 1, "page_size": 1, "total": 2},
},
)
responses.get(
f"https://{self.host}/api/v1/developer/visitors",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher({"page_num": 2, "page_size": 1}),
],
json={
"code": "SUCCESS",
"data": [
{
"avatar": "",
"email": "",
"end_time": 1731880901,
"first_name": "Test",
"id": "173c4cb9-e174-4a83-89fa-01ba8f25362f",
"inviter_id": "",
"inviter_name": "",
"last_name": "Visitor",
"location_id": "",
"mobile_phone": "",
"nfc_cards": [],
"remarks": "",
"resources": [],
"schedule": {
"holiday_group": None,
"holiday_group_id": "",
"holiday_schedule": [],
"id": "",
"is_default": False,
"name": "",
"type": "",
"weekly": None,
},
"schedule_id": "",
"start_time": 1731794501,
"status": "UPCOMING",
"visit_reason": "Business",
"visitor_company": "",
}
],
"msg": "succ",
"pagination": {"page_num": 2, "page_size": 1, "total": 2},
},
)
resp = list(self.client.fetch_all_visitors__unpaged(page_size=1))
assert resp[0].id == "faaffd2e-b555-4991-810f-c18b36407c55"
assert resp[1].id == "173c4cb9-e174-4a83-89fa-01ba8f25362f"
@responses.activate
def test_update_visitor(self) -> None:
"""4.5 Update Visitor"""
visitor_id = VisitorId("37f2b996-c2c5-487b-aa22-8b453ff14a4b")
responses.put(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}",
match=[
matchers.header_matcher(self.common_headers),
matchers.json_params_matcher(
{
"first_name": "Test",
"last_name": "L",
"remarks": "",
"mobile_phone": "",
"email": "",
"visitor_company": "",
"start_time": 1688546460,
"end_time": 1788572799,
# NOTE: typo'ed in api docs to "Interviemw"
"visit_reason": "Interview",
"week_schedule": {
"sunday": [],
"monday": [
{"start_time": "10:00:00", "end_time": "17:00:59"}
],
"tuesday": [],
"wednesday": [
{"start_time": "10:00:00", "end_time": "17:00:59"}
],
"thursday": [
{"start_time": "11:00:00", "end_time": "18:00:59"}
],
"friday": [
{"start_time": "10:00:00", "end_time": "17:00:59"}
],
"saturday": [],
},
"resources": [
{
"id": "6ff875d2-af87-470b-9cb5-774c6596afc8",
"type": "door",
},
{
"id": "5c496423-6d25-4e4f-8cdf-95ad5135188a",
"type": "door_group",
},
{
"id": "d5573467-d6b3-4e8f-8e48-8a322b91664a",
"type": "door_group",
},
],
}
),
],
json={
"code": "SUCCESS",
"data": {
"first_name": "H",
"id": "8564ce90-76ba-445f-b78b-6cca39af0130",
"last_name": "L",
"nfc_cards": [],
"pin_code": None,
"resources": [
{
"id": "5c496423-6d25-4e4f-8cdf-95ad5135188a",
"name": "Door-Group-1",
"type": "door_group",
},
{
"id": "d5573467-d6b3-4e8f-8e48-8a322b91664a",
"name": "UNVR",
"type": "door_group",
},
{
"id": "e311ca94-172c-49fe-9c91-49bd8ecef845",
"name": "visitor-1691646856144",
"type": "door_group",
},
],
"schedule": {
"id": "c03bf601-0b90-4341-bce4-6061931e9f4e",
"is_default": False,
"name": "visitor-1691646856097",
"type": "access",
"weekly": {
"friday": [
{"end_time": "17:00:59", "start_time": "10:00:00"}
],
"monday": [
{"end_time": "17:00:59", "start_time": "10:00:00"}
],
"saturday": [],
"sunday": [],
"thursday": [
{"end_time": "18:00:59", "start_time": "11:00:00"}
],
"tuesday": [],
"wednesday": [
{"end_time": "17:00:59", "start_time": "10:00:00"}
],
},
},
"schedule_id": "c03bf601-0b90-4341-bce4-6061931e9f4e",
"status": "ACTIVE",
},
"msg": "success",
},
)
resp = self.client.update_visitor(
visitor_id=visitor_id,
first_name="Test",
last_name="L",
remarks="",
mobile_phone="",
email="",
visitor_company="",
start_time=datetime.datetime.fromtimestamp(1688546460, tz=datetime.UTC),
end_time=datetime.datetime.fromtimestamp(1788572799, tz=datetime.UTC),
visit_reason=VisitReason.INTERVIEW,
week_schedule=WeekSchedule(
sunday=[],
monday=[
TimePeriod(
start_time=datetime.time(10, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
tuesday=[],
wednesday=[
TimePeriod(
start_time=datetime.time(10, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
thursday=[
TimePeriod(
start_time=datetime.time(11, 0, 0),
end_time=datetime.time(18, 0, 59),
)
],
friday=[
TimePeriod(
start_time=datetime.time(10, 0, 0),
end_time=datetime.time(17, 0, 59),
)
],
saturday=[],
),
resources=[
DoorResource(
id=DoorId("6ff875d2-af87-470b-9cb5-774c6596afc8"),
),
DoorGroupResource(
id=DoorGroupId("5c496423-6d25-4e4f-8cdf-95ad5135188a"),
),
DoorGroupResource(
id=DoorGroupId("d5573467-d6b3-4e8f-8e48-8a322b91664a")
),
],
)
@responses.activate
def test_delete_visitor(self) -> None:
"""4.6 Delete Visitor"""
visitor_id = VisitorId("c81dfee6-5970-4938-bd30-40820e16ea01")
responses.delete(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}",
match=[
matchers.header_matcher(self.common_headers),
matchers.query_param_matcher({"is_force": "true"}),
],
json={"code": "SUCCESS", "data": None, "msg": "success"},
)
self.client.delete_visitor(visitor_id=visitor_id, is_force=True)
@responses.activate
def test_assign_nfc_card_to_visitor(self) -> None:
"""4.7 Assign NFC Card To Visitor"""
visitor_id = VisitorId("60b5c15e-9aff-4fc8-9547-d21d2e39c1ff")
responses.put(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}/nfc_cards",
match=[
matchers.header_matcher(self.common_headers),
matchers.json_params_matcher(
{
"token": "d27822fc682b478dc637c6db01813e465174df6e54ca515d8427db623cfda1d0",
"force_add": True,
}
),
],
json={"code": "SUCCESS", "msg": "success"},
)
self.client.assign_nfc_card_to_visitor(
visitor_id=visitor_id,
token=NfcCardToken(
"d27822fc682b478dc637c6db01813e465174df6e54ca515d8427db623cfda1d0"
),
force_add=True,
)
@responses.activate
def test_unassign_nfc_card_from_visitor(self) -> None:
"""4.8 Unassign NFC Card From Visitor"""
visitor_id = VisitorId("60b5c15e-9aff-4fc8-9547-d21d2e39c1ff")
responses.put(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}/nfc_cards/delete",
match=[
matchers.header_matcher(self.common_headers),
matchers.json_params_matcher(
{
"token": "d27822fc682b478dc637c6db01813e465174df6e54ca515d8427db623cfda1d0"
}
),
],
json={"code": "SUCCESS", "msg": "success"},
)
self.client.unassign_nfc_card_from_visitor(
visitor_id=visitor_id,
token=NfcCardToken(
"d27822fc682b478dc637c6db01813e465174df6e54ca515d8427db623cfda1d0"
),
)
@responses.activate
def test_assign_pin_code_to_visitor(self) -> None:
"""4.9 Assign Pin Code To Visitor"""
visitor_id = VisitorId("17d2f099-99df-429b-becb-1399a6937e5a")
responses.put(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}/pin_codes",
match=[
matchers.header_matcher(self.common_headers),
matchers.json_params_matcher({"pin_code": "57301208"}),
],
json={"code": "SUCCESS", "msg": "success"},
)
self.client.assign_pin_code_to_visitor(
visitor_id=visitor_id,
pin_code="57301208",
)
@responses.activate
def test_unassign_pin_code_from_visitor(self) -> None:
"""4.10 Unassign Pin Code From Visitor"""
visitor_id = VisitorId("17d2f099-99df-429b-becb-1399a6937e5a")
responses.delete(
f"https://{self.host}/api/v1/developer/visitors/{visitor_id}/pin_codes",
match=[
matchers.header_matcher(self.common_headers),
],
json={"code": "SUCCESS", "msg": "success"},
)
self.client.unassign_pin_code_from_visitor(visitor_id=visitor_id)