Add CRUD operations for schedules and tasks in FeedClient; enhance tests for schedule and task management

This commit is contained in:
claudi 2026-04-07 10:53:30 +02:00
parent 184b0c6c17
commit 9592f38902
2 changed files with 340 additions and 5 deletions

View file

@ -7,7 +7,7 @@ from pytest_httpx import HTTPXMock
from ebay_client.account.client import AccountClient
from ebay_client.core.auth.models import OAuthToken
from ebay_client.core.http.transport import ApiTransport
from ebay_client.feed.client import FeedClient
from ebay_client.feed.client import CreatedFeedResource, FeedClient, FeedFileDownload
from ebay_client.fulfillment.client import FulfillmentClient
from ebay_client.generated.account.models import (
FulfillmentPolicy,
@ -19,6 +19,13 @@ from ebay_client.generated.account.models import (
ReturnPolicyRequest,
)
from ebay_client.generated.feed.models import TaskCollection
from ebay_client.generated.feed.models import (
CreateTaskRequest,
CreateUserScheduleRequest,
ScheduleTemplateResponse,
UpdateUserScheduleRequest,
UserScheduleResponse,
)
from ebay_client.generated.fulfillment.models import Order
from ebay_client.generated.inventory.models import InventoryItemWithSkuLocaleGroupid
from ebay_client.generated.media.models import (
@ -406,6 +413,158 @@ def test_feed_wrapper_returns_task_collection_model(httpx_mock: HTTPXMock) -> No
assert result.tasks and result.tasks[0].taskId == "TASK-1"
def test_feed_wrapper_supports_schedule_crud_and_template_lookup(httpx_mock: HTTPXMock) -> None:
httpx_mock.add_response(
method="POST",
url="https://api.ebay.com/sell/feed/v1/schedule",
status_code=201,
headers={"Location": "https://api.ebay.com/sell/feed/v1/schedule/SCHEDULE-1"},
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/schedule/SCHEDULE-1",
json={"scheduleId": "SCHEDULE-1", "feedType": "LMS_ORDER_REPORT"},
)
httpx_mock.add_response(
method="PUT",
url="https://api.ebay.com/sell/feed/v1/schedule/SCHEDULE-1",
status_code=204,
)
httpx_mock.add_response(
method="DELETE",
url="https://api.ebay.com/sell/feed/v1/schedule/SCHEDULE-1",
status_code=204,
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/schedule_template/TEMPLATE-1",
json={"scheduleTemplateId": "TEMPLATE-1", "feedType": "LMS_ORDER_REPORT"},
)
client = FeedClient(build_transport())
created = client.create_schedule(
CreateUserScheduleRequest(feedType="LMS_ORDER_REPORT", scheduleTemplateId="TEMPLATE-1")
)
schedule = client.get_schedule("SCHEDULE-1")
client.update_schedule("SCHEDULE-1", UpdateUserScheduleRequest(scheduleName="nightly"))
client.delete_schedule("SCHEDULE-1")
template = client.get_schedule_template("TEMPLATE-1")
assert isinstance(created, CreatedFeedResource)
assert created.resource_id == "SCHEDULE-1"
assert isinstance(schedule, UserScheduleResponse)
assert schedule.scheduleId == "SCHEDULE-1"
assert isinstance(template, ScheduleTemplateResponse)
assert template.scheduleTemplateId == "TEMPLATE-1"
create_body = json.loads(httpx_mock.get_requests()[0].content.decode("utf-8"))
assert create_body["feedType"] == "LMS_ORDER_REPORT"
update_body = json.loads(httpx_mock.get_requests()[2].content.decode("utf-8"))
assert update_body["scheduleName"] == "nightly"
def test_feed_wrapper_supports_task_create_upload_and_file_downloads(httpx_mock: HTTPXMock) -> None:
httpx_mock.add_response(
method="POST",
url="https://api.ebay.com/sell/feed/v1/task",
status_code=202,
headers={"Location": "https://api.ebay.com/sell/feed/v1/task/TASK-2"},
)
httpx_mock.add_response(
method="POST",
url="https://api.ebay.com/sell/feed/v1/task/TASK-2/upload_file",
status_code=200,
json={},
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/task/TASK-2/download_input_file",
status_code=200,
headers={"content-disposition": 'attachment; filename="input.xml"'},
content=b"<input />",
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/task/TASK-2/download_result_file",
status_code=200,
headers={"content-disposition": 'attachment; filename="result.csv"'},
content=b"id,name\n1,demo\n",
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/schedule/SCHEDULE-9/download_result_file",
status_code=200,
headers={"content-disposition": 'attachment; filename="latest.csv"'},
content=b"id,name\n2,latest\n",
)
client = FeedClient(build_transport())
created = client.create_task(
CreateTaskRequest(feedType="LMS_ORDER_REPORT", schemaVersion="1.0"),
marketplace_id="EBAY_US",
)
client.upload_file("TASK-2", file_name="input.xml", content=b"<input />", content_type="application/xml")
input_file = client.get_input_file("TASK-2")
result_file = client.get_result_file("TASK-2")
latest_file = client.get_latest_result_file("SCHEDULE-9")
assert isinstance(created, CreatedFeedResource)
assert created.resource_id == "TASK-2"
assert isinstance(input_file, FeedFileDownload)
assert input_file.file_name == "input.xml"
assert input_file.content == b"<input />"
assert result_file.file_name == "result.csv"
assert result_file.content.startswith(b"id,name")
assert latest_file.file_name == "latest.csv"
create_request = httpx_mock.get_requests()[0]
assert create_request.headers["X-EBAY-C-MARKETPLACE-ID"] == "EBAY_US"
create_body = json.loads(create_request.content.decode("utf-8"))
assert create_body["feedType"] == "LMS_ORDER_REPORT"
upload_request = httpx_mock.get_requests()[1]
assert upload_request.headers["Content-Type"].startswith("multipart/form-data;")
assert b"filename=\"input.xml\"" in upload_request.content
def test_feed_wrapper_passes_task_and_schedule_filters(httpx_mock: HTTPXMock) -> None:
httpx_mock.add_response(
method="GET",
url=(
"https://api.ebay.com/sell/feed/v1/task?feed_type=LMS_ORDER_REPORT"
"&schedule_id=SCHEDULE-1&date_range=2026-01-01T00:00:00.000Z..2026-01-02T00:00:00.000Z"
"&look_back_days=7&limit=50&offset=0"
),
json={"tasks": [], "total": 0},
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/schedule?feed_type=LMS_ORDER_REPORT&limit=25&offset=0",
json={"schedules": [], "total": 0},
)
httpx_mock.add_response(
method="GET",
url="https://api.ebay.com/sell/feed/v1/schedule_template?feed_type=LMS_ORDER_REPORT&limit=25&offset=0",
json={"scheduleTemplates": [], "total": 0},
)
client = FeedClient(build_transport())
tasks = client.get_tasks(
feed_type="LMS_ORDER_REPORT",
schedule_id="SCHEDULE-1",
date_range="2026-01-01T00:00:00.000Z..2026-01-02T00:00:00.000Z",
look_back_days=7,
limit=50,
offset=0,
)
schedules = client.get_schedules(feed_type="LMS_ORDER_REPORT", limit=25, offset=0)
templates = client.get_schedule_templates(feed_type="LMS_ORDER_REPORT", limit=25, offset=0)
assert tasks.total == 0
assert schedules.total == 0
assert templates.total == 0
def test_inventory_wrapper_accepts_readonly_or_full_scope_options(httpx_mock: HTTPXMock) -> None:
oauth_client = RecordingOAuthClient()
transport = ApiTransport(base_url="https://api.ebay.com", oauth_client=oauth_client)