diff --git a/CHANGELOG.md b/CHANGELOG.md index a28c287..f7c5d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * add support for providing a custom `requests.Session` in client ([#39](/~https://github.com/at-gmbh/personio-py/pull/39) +* add pagination to get employees method + ([#42](/~https://github.com/at-gmbh/personio-py/pull/42)) + ## [0.2.3](/~https://github.com/at-gmbh/personio-py/tree/v0.2.3) - 2023-05-05 * add support for Projects ([#36](/~https://github.com/at-gmbh/personio-py/pull/36)) diff --git a/src/personio_py/client.py b/src/personio_py/client.py index d16191f..78517f3 100644 --- a/src/personio_py/client.py +++ b/src/personio_py/client.py @@ -38,6 +38,7 @@ class Personio: ATTENDANCE_URL = 'company/attendances' ABSENCE_URL = 'company/time-offs' PROJECT_URL = 'company/attendances/projects' + EMPLOYEES_URL = 'company/employees' def __init__(self, base_url: str = None, client_id: str = None, client_secret: str = None, dynamic_fields: List[DynamicMapping] = None, @@ -170,6 +171,9 @@ def request_paginated(self, path: str, method='GET', params: Dict[str, Any] = No elif self.ATTENDANCE_URL == path: offset = 0 url_type = 'attendance' + elif self.EMPLOYEES_URL == path: + offset = 0 + url_type = 'employees' else: raise ValueError(f"Invalid path: {path}") @@ -182,24 +186,51 @@ def request_paginated(self, path: str, method='GET', params: Dict[str, Any] = No response = self.request_json(path, method, params, data, auth_rotation=auth_rotation) resp_data = response.get('data') if resp_data: - if url_type == 'absence': - data_acc.extend(resp_data) - if response['metadata']['current_page'] == response['metadata']['total_pages']: - break - else: - params['offset'] += 1 - elif url_type == 'attendance': - if params['offset'] >= response['metadata']['total_elements']: - break - else: - data_acc.extend(resp_data) - params['offset'] += limit + if url_type == 'absence' and self._handle_absence_pagination( + data_acc, resp_data, response, params + ): + break + elif url_type == 'attendance' and self._handle_attendance_pagination( + data_acc, resp_data, response, params + ): + break + elif url_type == 'employees' and self._handle_employees_pagination( + data_acc, resp_data, response, params + ): + break else: break # return the accumulated data response['data'] = data_acc return response + def _handle_absence_pagination(self, data_acc, resp_data, response, params) -> bool: + """Handle pagination logic for absences.""" + data_acc.extend(resp_data) + if response['metadata']['current_page'] == response['metadata']['total_pages']: + return True + params['offset'] += 1 + return False + + def _handle_attendance_pagination(self, data_acc, resp_data, response, params) -> bool: + """Handle pagination logic for attendance.""" + if params['offset'] >= response['metadata']['total_elements']: + return True + data_acc.extend(resp_data) + params['offset'] += params['limit'] + return False + + def _handle_employees_pagination(self, data_acc, resp_data, response, params): + """Handle pagination logic for employees.""" + data_acc.extend(resp_data) + total_pages = response['metadata']['total_pages'] + current_page = response['metadata']['current_page'] + if current_page + 1 == total_pages: + return True + else: + params['offset'] += 1 + return False + def request_image(self, path: str, method='GET', params: Dict[str, Any] = None, auth_rotation=False) -> Optional[bytes]: """ @@ -230,11 +261,11 @@ def request_image(self, path: str, method='GET', params: Dict[str, Any] = None, def get_employees(self) -> List[Employee]: """ Get a list of all employee records in your account. - Does not involve pagination. + Requires pagination. Max page size is 100. :return: list of ``Employee`` instances """ - response = self.request_json('company/employees') + response = self.request_paginated(path='company/employees', limit=100) employees = [Employee.from_dict(d, self) for d in response['data']] return employees diff --git a/tests/mock_data.py b/tests/mock_data.py index f53b7b1..cf0bd4a 100644 --- a/tests/mock_data.py +++ b/tests/mock_data.py @@ -3,6 +3,13 @@ json_string_employees = """ { "success": true, + "metadata": { + "total_elements": 2, + "current_page": 0, + "total_pages": 1 + }, + "offset": 0, + "limit": 10, "data": [{ "type": "Employee", "attributes": { @@ -525,6 +532,1068 @@ """ json_dict_employees = json.loads(json_string_employees) +json_string_employees_page1 = """{ + "success": true, + "metadata": { + "total_elements": 150, + "current_page": 0, + "total_pages": 2 + }, + "offset": 0, + "limit": 100, + "data": [{ + "type": "Employee", + "attributes": { + "id": { + "label": "ID", + "value": 2116366 + }, + "first_name": { + "label": "First name", + "value": "Richard" + }, + "last_name": { + "label": "Last name", + "value": "Stallman" + }, + "email": { + "label": "Email", + "value": "rms@example.org" + }, + "gender": { + "label": "Gender", + "value": "male" + }, + "status": { + "label": "Status", + "value": "active" + }, + "position": { + "label": "Position", + "value": "St. IGNUcius" + }, + "supervisor": { + "label": "Supervisor", + "value": null + }, + "employment_type": { + "label": "Employment type", + "value": "internal" + }, + "weekly_working_hours": { + "label": "Weekly hours", + "value": "40" + }, + "hire_date": { + "label": "Hire date", + "value": "1983-09-01T00:00:00+02:00" + }, + "contract_end_date": { + "label": "Contract ends", + "value": null + }, + "termination_date": { + "label": "Termination date", + "value": null + }, + "termination_type": { + "label": "Termination type", + "value": "" + }, + "termination_reason": { + "label": "Termination reason", + "value": "" + }, + "probation_period_end": { + "label": "Probation period end", + "value": null + }, + "created_at": { + "label": "created_at", + "value": "2020-07-23T19:57:57+02:00" + }, + "last_modified_at": { + "label": "Last modified", + "value": "2020-07-23T19:57:57+02:00" + }, + "subcompany": { + "label": "Subcompany", + "value": null + }, + "office": { + "label": "Office", + "value": null + }, + "department": { + "label": "Department", + "value": null + }, + "cost_centers": { + "label": "Cost center", + "value": [] + }, + "holiday_calendar": { + "label": "Public holidays", + "value": { + "type": "HolidayCalendar", + "attributes": { + "id": 1, + "name": "Deutschland Feiertage", + "country": "DE", + "state": null + } + } + }, + "absence_entitlement": { + "label": "Absence entitlement", + "value": [{ + "type": "TimeOffType", + "attributes": { + "id": 195824, + "name": "Vacation", + "entitlement": 0 + } + } + ] + }, + "work_schedule": { + "label": "Work schedule", + "value": { + "type": "WorkSchedule", + "attributes": { + "id": 232617, + "name": "40 hours", + "valid_from": null, + "monday": "08:00", + "tuesday": "08:00", + "wednesday": "08:00", + "thursday": "08:00", + "friday": "08:00", + "saturday": "00:00", + "sunday": "00:00" + } + } + }, + "fix_salary": { + "label": "Fix salary", + "value": 0 + }, + "fix_salary_interval": { + "label": "Salary interval", + "value": "" + }, + "hourly_salary": { + "label": "Hourly salary", + "value": 0 + }, + "vacation_day_balance": { + "label": "Vacation day balance", + "value": 25 + }, + "last_working_day": { + "label": "Last day of work", + "value": null + }, + "profile_picture": { + "label": "Profile Picture", + "value": null + }, + "team": { + "label": "Team", + "value": null + }, + "dynamic_1146702": { + "label": "Country of Birth", + "value": "USA" + }, + "dynamic_1146666": { + "label": "Birthday", + "value": "1953-03-16T00:00:00+01:00" + } + } + }, { + "type": "Employee", + "attributes": { + "id": { + "label": "ID", + "value": 2116365 + }, + "first_name": { + "label": "First name", + "value": "Alan" + }, + "last_name": { + "label": "Last name", + "value": "Turing" + }, + "email": { + "label": "Email", + "value": "alan@example.org" + }, + "gender": { + "label": "Gender", + "value": "male" + }, + "status": { + "label": "Status", + "value": "active" + }, + "position": { + "label": "Position", + "value": "Chief Cryptanalyst" + }, + "supervisor": { + "label": "Supervisor", + "value": null + }, + "employment_type": { + "label": "Employment type", + "value": "internal" + }, + "weekly_working_hours": { + "label": "Weekly hours", + "value": "40" + }, + "hire_date": { + "label": "Hire date", + "value": "1932-01-01T00:00:00+01:00" + }, + "contract_end_date": { + "label": "Contract ends", + "value": "1954-06-07T00:00:00+01:00" + }, + "termination_date": { + "label": "Termination date", + "value": null + }, + "termination_type": { + "label": "Termination type", + "value": "" + }, + "termination_reason": { + "label": "Termination reason", + "value": "" + }, + "probation_period_end": { + "label": "Probation period end", + "value": null + }, + "created_at": { + "label": "created_at", + "value": "2020-07-23T19:51:46+02:00" + }, + "last_modified_at": { + "label": "Last modified", + "value": "2020-07-23T19:53:48+02:00" + }, + "subcompany": { + "label": "Subcompany", + "value": null + }, + "office": { + "label": "Office", + "value": null + }, + "department": { + "label": "Department", + "value": null + }, + "cost_centers": { + "label": "Cost center", + "value": [] + }, + "holiday_calendar": { + "label": "Public holidays", + "value": { + "type": "HolidayCalendar", + "attributes": { + "id": 1, + "name": "Deutschland Feiertage", + "country": "DE", + "state": null + } + } + }, + "absence_entitlement": { + "label": "Absence entitlement", + "value": [{ + "type": "TimeOffType", + "attributes": { + "id": 195824, + "name": "Vacation", + "entitlement": 0 + } + } + ] + }, + "work_schedule": { + "label": "Work schedule", + "value": { + "type": "WorkSchedule", + "attributes": { + "id": 232617, + "name": "40 hours", + "valid_from": null, + "monday": "08:00", + "tuesday": "08:00", + "wednesday": "08:00", + "thursday": "08:00", + "friday": "08:00", + "saturday": "00:00", + "sunday": "00:00" + } + } + }, + "fix_salary": { + "label": "Fix salary", + "value": 0 + }, + "fix_salary_interval": { + "label": "Salary interval", + "value": "" + }, + "hourly_salary": { + "label": "Hourly salary", + "value": 0 + }, + "vacation_day_balance": { + "label": "Vacation day balance", + "value": 25 + }, + "last_working_day": { + "label": "Last day of work", + "value": null + }, + "profile_picture": { + "label": "Profile Picture", + "value": null + }, + "team": { + "label": "Team", + "value": null + }, + "dynamic_1146702": { + "label": "Country of Birth", + "value": "England" + }, + "dynamic_1146666": { + "label": "Birthday", + "value": "1912-06-23T00:00:00+01:00" + } + } + }, { + "type": "Employee", + "attributes": { + "id": { + "label": "ID", + "value": 2040614 + }, + "first_name": { + "label": "First name", + "value": "Ada" + }, + "last_name": { + "label": "Last name", + "value": "Lovelace" + }, + "email": { + "label": "Email", + "value": "ada@example.org" + }, + "gender": { + "label": "Gender", + "value": "female" + }, + "status": { + "label": "Status", + "value": "active" + }, + "position": { + "label": "Position", + "value": "first programmer ever" + }, + "supervisor": { + "label": "Supervisor", + "value": null + }, + "employment_type": { + "label": "Employment type", + "value": "internal" + }, + "weekly_working_hours": { + "label": "Weekly hours", + "value": "35" + }, + "hire_date": { + "label": "Hire date", + "value": "1835-02-01T00:00:00+00:53" + }, + "contract_end_date": { + "label": "Contract ends", + "value": null + }, + "termination_date": { + "label": "Termination date", + "value": null + }, + "termination_type": { + "label": "Termination type", + "value": "" + }, + "termination_reason": { + "label": "Termination reason", + "value": "" + }, + "probation_period_end": { + "label": "Probation period end", + "value": null + }, + "created_at": { + "label": "created_at", + "value": "2020-06-18T18:43:44+02:00" + }, + "last_modified_at": { + "label": "Last modified", + "value": "2020-07-23T18:00:26+02:00" + }, + "subcompany": { + "label": "Subcompany", + "value": null + }, + "office": { + "label": "Office", + "value": null + }, + "department": { + "label": "Department", + "value": { + "type": "Department", + "attributes": { + "id": 625448, + "name": "Operations" + } + } + }, + "cost_centers": { + "label": "Cost center", + "value": [] + }, + "holiday_calendar": { + "label": "Public holidays", + "value": { + "type": "HolidayCalendar", + "attributes": { + "id": 1, + "name": "Deutschland Feiertage", + "country": "DE", + "state": null + } + } + }, + "absence_entitlement": { + "label": "Absence entitlement", + "value": [{ + "type": "TimeOffType", + "attributes": { + "id": 195824, + "name": "Vacation", + "entitlement": 0 + } + } + ] + }, + "work_schedule": { + "label": "Work schedule", + "value": { + "type": "WorkSchedule", + "attributes": { + "id": 232617, + "name": "Vollzeit, 40 Stunden ohne Zeiterfassung, (Mo,Di,Mi,Do,Fr) ", + "valid_from": null, + "monday": "08:00", + "tuesday": "08:00", + "wednesday": "08:00", + "thursday": "08:00", + "friday": "08:00", + "saturday": "00:00", + "sunday": "00:00" + } + } + }, + "fix_salary": { + "label": "Fix salary", + "value": 0 + }, + "fix_salary_interval": { + "label": "Salary interval", + "value": "" + }, + "hourly_salary": { + "label": "Hourly salary", + "value": 0 + }, + "vacation_day_balance": { + "label": "Vacation day balance", + "value": 25 + }, + "last_working_day": { + "label": "Last day of work", + "value": null + }, + "profile_picture": { + "label": "Profile Picture", + "value": null + }, + "team": { + "label": "Team", + "value": null + }, + "dynamic_1146702": { + "label": "Country of Birth", + "value": "England" + }, + "dynamic_1146666": { + "label": "Birthday", + "value": "1815-12-10T00:00:00+01:00" + } + } + } + ] +} +""" +json_dict_employees_page1 = json.loads(json_string_employees_page1) + +json_string_employees_page2 = """{ + "success": true, + "metadata": { + "total_elements": 150, + "current_page": 1, + "total_pages": 2 + }, + "offset": 0, + "limit": 100, + "data": [{ + "type": "Employee", + "attributes": { + "id": { + "label": "ID", + "value": 2116366 + }, + "first_name": { + "label": "First name", + "value": "Richard" + }, + "last_name": { + "label": "Last name", + "value": "Stallman" + }, + "email": { + "label": "Email", + "value": "rms@example.org" + }, + "gender": { + "label": "Gender", + "value": "male" + }, + "status": { + "label": "Status", + "value": "active" + }, + "position": { + "label": "Position", + "value": "St. IGNUcius" + }, + "supervisor": { + "label": "Supervisor", + "value": null + }, + "employment_type": { + "label": "Employment type", + "value": "internal" + }, + "weekly_working_hours": { + "label": "Weekly hours", + "value": "40" + }, + "hire_date": { + "label": "Hire date", + "value": "1983-09-01T00:00:00+02:00" + }, + "contract_end_date": { + "label": "Contract ends", + "value": null + }, + "termination_date": { + "label": "Termination date", + "value": null + }, + "termination_type": { + "label": "Termination type", + "value": "" + }, + "termination_reason": { + "label": "Termination reason", + "value": "" + }, + "probation_period_end": { + "label": "Probation period end", + "value": null + }, + "created_at": { + "label": "created_at", + "value": "2020-07-23T19:57:57+02:00" + }, + "last_modified_at": { + "label": "Last modified", + "value": "2020-07-23T19:57:57+02:00" + }, + "subcompany": { + "label": "Subcompany", + "value": null + }, + "office": { + "label": "Office", + "value": null + }, + "department": { + "label": "Department", + "value": null + }, + "cost_centers": { + "label": "Cost center", + "value": [] + }, + "holiday_calendar": { + "label": "Public holidays", + "value": { + "type": "HolidayCalendar", + "attributes": { + "id": 1, + "name": "Deutschland Feiertage", + "country": "DE", + "state": null + } + } + }, + "absence_entitlement": { + "label": "Absence entitlement", + "value": [{ + "type": "TimeOffType", + "attributes": { + "id": 195824, + "name": "Vacation", + "entitlement": 0 + } + } + ] + }, + "work_schedule": { + "label": "Work schedule", + "value": { + "type": "WorkSchedule", + "attributes": { + "id": 232617, + "name": "40 hours", + "valid_from": null, + "monday": "08:00", + "tuesday": "08:00", + "wednesday": "08:00", + "thursday": "08:00", + "friday": "08:00", + "saturday": "00:00", + "sunday": "00:00" + } + } + }, + "fix_salary": { + "label": "Fix salary", + "value": 0 + }, + "fix_salary_interval": { + "label": "Salary interval", + "value": "" + }, + "hourly_salary": { + "label": "Hourly salary", + "value": 0 + }, + "vacation_day_balance": { + "label": "Vacation day balance", + "value": 25 + }, + "last_working_day": { + "label": "Last day of work", + "value": null + }, + "profile_picture": { + "label": "Profile Picture", + "value": null + }, + "team": { + "label": "Team", + "value": null + }, + "dynamic_1146702": { + "label": "Country of Birth", + "value": "USA" + }, + "dynamic_1146666": { + "label": "Birthday", + "value": "1953-03-16T00:00:00+01:00" + } + } + }, { + "type": "Employee", + "attributes": { + "id": { + "label": "ID", + "value": 2116365 + }, + "first_name": { + "label": "First name", + "value": "Alan" + }, + "last_name": { + "label": "Last name", + "value": "Turing" + }, + "email": { + "label": "Email", + "value": "alan@example.org" + }, + "gender": { + "label": "Gender", + "value": "male" + }, + "status": { + "label": "Status", + "value": "active" + }, + "position": { + "label": "Position", + "value": "Chief Cryptanalyst" + }, + "supervisor": { + "label": "Supervisor", + "value": null + }, + "employment_type": { + "label": "Employment type", + "value": "internal" + }, + "weekly_working_hours": { + "label": "Weekly hours", + "value": "40" + }, + "hire_date": { + "label": "Hire date", + "value": "1932-01-01T00:00:00+01:00" + }, + "contract_end_date": { + "label": "Contract ends", + "value": "1954-06-07T00:00:00+01:00" + }, + "termination_date": { + "label": "Termination date", + "value": null + }, + "termination_type": { + "label": "Termination type", + "value": "" + }, + "termination_reason": { + "label": "Termination reason", + "value": "" + }, + "probation_period_end": { + "label": "Probation period end", + "value": null + }, + "created_at": { + "label": "created_at", + "value": "2020-07-23T19:51:46+02:00" + }, + "last_modified_at": { + "label": "Last modified", + "value": "2020-07-23T19:53:48+02:00" + }, + "subcompany": { + "label": "Subcompany", + "value": null + }, + "office": { + "label": "Office", + "value": null + }, + "department": { + "label": "Department", + "value": null + }, + "cost_centers": { + "label": "Cost center", + "value": [] + }, + "holiday_calendar": { + "label": "Public holidays", + "value": { + "type": "HolidayCalendar", + "attributes": { + "id": 1, + "name": "Deutschland Feiertage", + "country": "DE", + "state": null + } + } + }, + "absence_entitlement": { + "label": "Absence entitlement", + "value": [{ + "type": "TimeOffType", + "attributes": { + "id": 195824, + "name": "Vacation", + "entitlement": 0 + } + } + ] + }, + "work_schedule": { + "label": "Work schedule", + "value": { + "type": "WorkSchedule", + "attributes": { + "id": 232617, + "name": "40 hours", + "valid_from": null, + "monday": "08:00", + "tuesday": "08:00", + "wednesday": "08:00", + "thursday": "08:00", + "friday": "08:00", + "saturday": "00:00", + "sunday": "00:00" + } + } + }, + "fix_salary": { + "label": "Fix salary", + "value": 0 + }, + "fix_salary_interval": { + "label": "Salary interval", + "value": "" + }, + "hourly_salary": { + "label": "Hourly salary", + "value": 0 + }, + "vacation_day_balance": { + "label": "Vacation day balance", + "value": 25 + }, + "last_working_day": { + "label": "Last day of work", + "value": null + }, + "profile_picture": { + "label": "Profile Picture", + "value": null + }, + "team": { + "label": "Team", + "value": null + }, + "dynamic_1146702": { + "label": "Country of Birth", + "value": "England" + }, + "dynamic_1146666": { + "label": "Birthday", + "value": "1912-06-23T00:00:00+01:00" + } + } + }, { + "type": "Employee", + "attributes": { + "id": { + "label": "ID", + "value": 2040614 + }, + "first_name": { + "label": "First name", + "value": "Ada" + }, + "last_name": { + "label": "Last name", + "value": "Lovelace" + }, + "email": { + "label": "Email", + "value": "ada@example.org" + }, + "gender": { + "label": "Gender", + "value": "female" + }, + "status": { + "label": "Status", + "value": "active" + }, + "position": { + "label": "Position", + "value": "first programmer ever" + }, + "supervisor": { + "label": "Supervisor", + "value": null + }, + "employment_type": { + "label": "Employment type", + "value": "internal" + }, + "weekly_working_hours": { + "label": "Weekly hours", + "value": "35" + }, + "hire_date": { + "label": "Hire date", + "value": "1835-02-01T00:00:00+00:53" + }, + "contract_end_date": { + "label": "Contract ends", + "value": null + }, + "termination_date": { + "label": "Termination date", + "value": null + }, + "termination_type": { + "label": "Termination type", + "value": "" + }, + "termination_reason": { + "label": "Termination reason", + "value": "" + }, + "probation_period_end": { + "label": "Probation period end", + "value": null + }, + "created_at": { + "label": "created_at", + "value": "2020-06-18T18:43:44+02:00" + }, + "last_modified_at": { + "label": "Last modified", + "value": "2020-07-23T18:00:26+02:00" + }, + "subcompany": { + "label": "Subcompany", + "value": null + }, + "office": { + "label": "Office", + "value": null + }, + "department": { + "label": "Department", + "value": { + "type": "Department", + "attributes": { + "id": 625448, + "name": "Operations" + } + } + }, + "cost_centers": { + "label": "Cost center", + "value": [] + }, + "holiday_calendar": { + "label": "Public holidays", + "value": { + "type": "HolidayCalendar", + "attributes": { + "id": 1, + "name": "Deutschland Feiertage", + "country": "DE", + "state": null + } + } + }, + "absence_entitlement": { + "label": "Absence entitlement", + "value": [{ + "type": "TimeOffType", + "attributes": { + "id": 195824, + "name": "Vacation", + "entitlement": 0 + } + } + ] + }, + "work_schedule": { + "label": "Work schedule", + "value": { + "type": "WorkSchedule", + "attributes": { + "id": 232617, + "name": "Vollzeit, 40 Stunden ohne Zeiterfassung, (Mo,Di,Mi,Do,Fr) ", + "valid_from": null, + "monday": "08:00", + "tuesday": "08:00", + "wednesday": "08:00", + "thursday": "08:00", + "friday": "08:00", + "saturday": "00:00", + "sunday": "00:00" + } + } + }, + "fix_salary": { + "label": "Fix salary", + "value": 0 + }, + "fix_salary_interval": { + "label": "Salary interval", + "value": "" + }, + "hourly_salary": { + "label": "Hourly salary", + "value": 0 + }, + "vacation_day_balance": { + "label": "Vacation day balance", + "value": 25 + }, + "last_working_day": { + "label": "Last day of work", + "value": null + }, + "profile_picture": { + "label": "Profile Picture", + "value": null + }, + "team": { + "label": "Team", + "value": null + }, + "dynamic_1146702": { + "label": "Country of Birth", + "value": "England" + }, + "dynamic_1146666": { + "label": "Birthday", + "value": "1815-12-10T00:00:00+01:00" + } + } + } + ] +} +""" +json_dict_employees_page2 = json.loads(json_string_employees_page2) + json_string_employee_ada = """ { "success": true, diff --git a/tests/test_mock_api.py b/tests/test_mock_api.py index 886bcc7..98d23cd 100644 --- a/tests/test_mock_api.py +++ b/tests/test_mock_api.py @@ -146,6 +146,35 @@ def mock_employees(): json=json_dict_employees, adding_headers={'Authorization': 'Bearer rotated_dummy_token'}) +@responses.activate +def test_get_employees_with_pagination(): + # Mock the paginated responses + responses.add( + responses.GET, + 'https://api.personio.de/v1/company/employees', + json=json_dict_employees_page1, + match=[responses.matchers.query_param_matcher({'limit': '100', 'offset': '0'})], + adding_headers={'Authorization': 'Bearer rotated_dummy_token'}, + status=200 + ) + responses.add( + responses.GET, + 'https://api.personio.de/v1/company/employees', + json=json_dict_employees_page2, + match=[responses.matchers.query_param_matcher({'limit': '100', 'offset': '1'})], + adding_headers={'Authorization': 'Bearer rotated_dummy_token'}, + status=200 + ) + # mock personio + personio = mock_personio() + employees = personio.get_employees() + + # Validate the number of calls made + assert len(responses.calls) == 3 # one for initializing client, two for employee pages + # Validate the combined response + assert len(employees) == len(json_dict_employees_page2["data"]) + len(json_dict_employees_page2["data"]) + + def compare_labeled_attributes(expected: Dict, actual: Dict): if actual == expected: # fast lane - exact match diff --git a/tests/test_mock_api_project.py b/tests/test_mock_api_project.py index 48c5110..0c06db2 100644 --- a/tests/test_mock_api_project.py +++ b/tests/test_mock_api_project.py @@ -87,4 +87,4 @@ def mock_update_project(): def mock_delete_project(): responses.add( responses.DELETE, 'https://api.personio.de/v1/company/attendances/projects/238751', - status=204, json=json_dict_project_delete, adding_headers={'Authorization': 'Bearer bar'}) + status=204, adding_headers={'Authorization': 'Bearer bar'})