amazon-sp-cli 0.2.9__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {amazon_sp_cli-0.2.9/amazon_sp_cli.egg-info → amazon_sp_cli-0.3.1}/PKG-INFO +1 -1
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/__init__.py +1 -1
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/cli.py +2 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/client.py +9 -10
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/commands/listings.py +16 -0
- amazon_sp_cli-0.3.1/amazon_sp_cli/commands/update.py +34 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/main.py +2 -2
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1/amazon_sp_cli.egg-info}/PKG-INFO +1 -1
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli.egg-info/SOURCES.txt +3 -3
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/tests/test_listings.py +84 -0
- amazon_sp_cli-0.3.1/tests/test_update.py +55 -0
- amazon_sp_cli-0.2.9/amazon_sp_cli/commands/inventory.py +0 -31
- amazon_sp_cli-0.2.9/tests/test_inventory.py +0 -118
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/LICENSE +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/MANIFEST.in +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/README.md +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/__main__.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/auth.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/commands/__init__.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/commands/a_plus.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/commands/auth.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/commands/pricing.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/models/__init__.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli/models/a_plus.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli.egg-info/dependency_links.txt +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli.egg-info/entry_points.txt +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli.egg-info/requires.txt +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/amazon_sp_cli.egg-info/top_level.txt +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/pyproject.toml +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/setup.cfg +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/setup.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/tests/__init__.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/tests/test_a_plus.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/tests/test_auth.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/tests/test_client.py +0 -0
- {amazon_sp_cli-0.2.9 → amazon_sp_cli-0.3.1}/tests/test_pricing.py +0 -0
|
@@ -8,6 +8,7 @@ from pathlib import Path
|
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
|
|
11
|
+
from . import __version__
|
|
11
12
|
from .auth import SPAPIAuth
|
|
12
13
|
from .client import SPAPIClient
|
|
13
14
|
|
|
@@ -82,6 +83,7 @@ def handle_errors(f):
|
|
|
82
83
|
return wrapper
|
|
83
84
|
|
|
84
85
|
|
|
86
|
+
@click.version_option(version=__version__, prog_name="amz-sp")
|
|
85
87
|
@click.group()
|
|
86
88
|
@click.option("--credentials", "-c", help="Path to credentials YAML file")
|
|
87
89
|
@click.pass_context
|
|
@@ -140,19 +140,18 @@ class SPAPIClient:
|
|
|
140
140
|
|
|
141
141
|
return self.request("PUT", path, data)
|
|
142
142
|
|
|
143
|
-
def
|
|
144
|
-
"""
|
|
145
|
-
path = "/
|
|
143
|
+
def search_listings_items(self, page_size: int = None, page_token: str = None, included_data: str = None) -> dict:
|
|
144
|
+
"""Search listings items for the seller."""
|
|
145
|
+
path = f"/listings/2021-08-01/items/{self.seller_id}"
|
|
146
146
|
params = {
|
|
147
|
-
"details": "true" if details else "false",
|
|
148
|
-
"granularityType": "Marketplace",
|
|
149
|
-
"granularityId": self.marketplace_id,
|
|
150
147
|
"marketplaceIds": self.marketplace_id,
|
|
151
148
|
}
|
|
152
|
-
if
|
|
153
|
-
params["
|
|
154
|
-
if
|
|
155
|
-
params["
|
|
149
|
+
if page_size is not None:
|
|
150
|
+
params["pageSize"] = str(page_size)
|
|
151
|
+
if page_token:
|
|
152
|
+
params["pageToken"] = page_token
|
|
153
|
+
if included_data:
|
|
154
|
+
params["includedData"] = included_data
|
|
156
155
|
path += "?" + urlencode(params)
|
|
157
156
|
return self.request("GET", path)
|
|
158
157
|
|
|
@@ -180,6 +180,22 @@ def register_listings_commands(cli_group, ensure_auth_client):
|
|
|
180
180
|
else:
|
|
181
181
|
click.echo(json.dumps(response, indent=2))
|
|
182
182
|
|
|
183
|
+
@cli_group.command("list-recent-listings")
|
|
184
|
+
@click.option("--page-size", type=int, default=10, help="Number of items per page (max 20)")
|
|
185
|
+
@click.option("--page-token", help="Pagination token from a previous response")
|
|
186
|
+
@click.option("--included-data", default="summaries", help="Comma-separated included data sets")
|
|
187
|
+
@click.pass_context
|
|
188
|
+
@handle_errors
|
|
189
|
+
def list_recent_listings(ctx, page_size, page_token, included_data):
|
|
190
|
+
"""List recent listings for the seller."""
|
|
191
|
+
_, client = ensure_auth_client(ctx)
|
|
192
|
+
response = client.search_listings_items(
|
|
193
|
+
page_size=page_size,
|
|
194
|
+
page_token=page_token,
|
|
195
|
+
included_data=included_data,
|
|
196
|
+
)
|
|
197
|
+
click.echo(json.dumps(response, indent=2))
|
|
198
|
+
|
|
183
199
|
@cli_group.command()
|
|
184
200
|
@click.argument("sku")
|
|
185
201
|
@click.pass_context
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Self-update command."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from ..cli import handle_errors
|
|
9
|
+
|
|
10
|
+
PACKAGE_NAME = "amazon-sp-cli"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def register_update_commands(cli_group):
|
|
14
|
+
"""Register update CLI commands."""
|
|
15
|
+
|
|
16
|
+
@cli_group.command()
|
|
17
|
+
@click.option("--dry-run", is_flag=True, help="Show the command without running it")
|
|
18
|
+
@handle_errors
|
|
19
|
+
def update(dry_run):
|
|
20
|
+
"""Update to the latest version from PyPI."""
|
|
21
|
+
cmd = [sys.executable, "-m", "pip", "install", "--upgrade", PACKAGE_NAME]
|
|
22
|
+
|
|
23
|
+
if dry_run:
|
|
24
|
+
click.echo("Would run: " + " ".join(cmd))
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
click.echo("Updating amazon-sp-cli...")
|
|
28
|
+
result = subprocess.run(cmd, capture_output=False)
|
|
29
|
+
|
|
30
|
+
if result.returncode != 0:
|
|
31
|
+
click.echo("Update failed.", err=True)
|
|
32
|
+
raise click.Abort()
|
|
33
|
+
|
|
34
|
+
click.echo("Update complete. Run 'amz-sp --version' to verify.")
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
from .cli import _ensure_auth_client, cli
|
|
4
4
|
from .commands.a_plus import register_a_plus_commands
|
|
5
5
|
from .commands.auth import register_auth_commands
|
|
6
|
-
from .commands.inventory import register_inventory_commands
|
|
7
6
|
from .commands.listings import register_listings_commands
|
|
8
7
|
from .commands.pricing import register_pricing_commands
|
|
8
|
+
from .commands.update import register_update_commands
|
|
9
9
|
|
|
10
10
|
register_auth_commands(cli)
|
|
11
11
|
register_listings_commands(cli, _ensure_auth_client)
|
|
12
12
|
register_pricing_commands(cli, _ensure_auth_client)
|
|
13
13
|
register_a_plus_commands(cli, _ensure_auth_client)
|
|
14
|
-
|
|
14
|
+
register_update_commands(cli)
|
|
@@ -18,15 +18,15 @@ amazon_sp_cli.egg-info/top_level.txt
|
|
|
18
18
|
amazon_sp_cli/commands/__init__.py
|
|
19
19
|
amazon_sp_cli/commands/a_plus.py
|
|
20
20
|
amazon_sp_cli/commands/auth.py
|
|
21
|
-
amazon_sp_cli/commands/inventory.py
|
|
22
21
|
amazon_sp_cli/commands/listings.py
|
|
23
22
|
amazon_sp_cli/commands/pricing.py
|
|
23
|
+
amazon_sp_cli/commands/update.py
|
|
24
24
|
amazon_sp_cli/models/__init__.py
|
|
25
25
|
amazon_sp_cli/models/a_plus.py
|
|
26
26
|
tests/__init__.py
|
|
27
27
|
tests/test_a_plus.py
|
|
28
28
|
tests/test_auth.py
|
|
29
29
|
tests/test_client.py
|
|
30
|
-
tests/test_inventory.py
|
|
31
30
|
tests/test_listings.py
|
|
32
|
-
tests/test_pricing.py
|
|
31
|
+
tests/test_pricing.py
|
|
32
|
+
tests/test_update.py
|
|
@@ -364,6 +364,90 @@ class TestUpdateListing:
|
|
|
364
364
|
assert call_args.kwargs["requirements"] == "LISTING_OFFER_ONLY"
|
|
365
365
|
|
|
366
366
|
|
|
367
|
+
class TestListRecentListings:
|
|
368
|
+
"""Test list-recent-listings command."""
|
|
369
|
+
|
|
370
|
+
@pytest.fixture
|
|
371
|
+
def mock_search_response(self):
|
|
372
|
+
"""Mock search listings response."""
|
|
373
|
+
return {
|
|
374
|
+
"items": [
|
|
375
|
+
{
|
|
376
|
+
"sku": "SKU-123",
|
|
377
|
+
"summaries": [{"status": ["ACTIVE"], "asin": "B09BBL8T4Z"}],
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"sku": "SKU-456",
|
|
381
|
+
"summaries": [{"status": ["ACTIVE"], "asin": "B09BBL8T5Z"}],
|
|
382
|
+
},
|
|
383
|
+
],
|
|
384
|
+
"pagination": {"nextToken": "token123"},
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@pytest.fixture
|
|
388
|
+
def runner(self):
|
|
389
|
+
"""Create Click test runner."""
|
|
390
|
+
return CliRunner()
|
|
391
|
+
|
|
392
|
+
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
393
|
+
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
394
|
+
def test_list_recent_listings(self, mock_client_class, mock_auth_class, runner, mock_search_response):
|
|
395
|
+
"""Test listing recent listings."""
|
|
396
|
+
mock_client = Mock()
|
|
397
|
+
mock_client.search_listings_items.return_value = mock_search_response
|
|
398
|
+
mock_client_class.return_value = mock_client
|
|
399
|
+
|
|
400
|
+
mock_auth = Mock()
|
|
401
|
+
mock_auth_class.return_value = mock_auth
|
|
402
|
+
|
|
403
|
+
result = runner.invoke(cli, ["list-recent-listings"])
|
|
404
|
+
|
|
405
|
+
assert result.exit_code == 0
|
|
406
|
+
output = json.loads(result.output)
|
|
407
|
+
assert len(output["items"]) == 2
|
|
408
|
+
assert output["items"][0]["sku"] == "SKU-123"
|
|
409
|
+
assert output["pagination"]["nextToken"] == "token123"
|
|
410
|
+
|
|
411
|
+
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
412
|
+
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
413
|
+
def test_list_recent_listings_with_pagination(
|
|
414
|
+
self, mock_client_class, mock_auth_class, runner, mock_search_response
|
|
415
|
+
):
|
|
416
|
+
"""Test listing recent listings with page size and token."""
|
|
417
|
+
mock_client = Mock()
|
|
418
|
+
mock_client.search_listings_items.return_value = mock_search_response
|
|
419
|
+
mock_client_class.return_value = mock_client
|
|
420
|
+
|
|
421
|
+
mock_auth = Mock()
|
|
422
|
+
mock_auth_class.return_value = mock_auth
|
|
423
|
+
|
|
424
|
+
result = runner.invoke(cli, ["list-recent-listings", "--page-size", "5", "--page-token", "abc"])
|
|
425
|
+
|
|
426
|
+
assert result.exit_code == 0
|
|
427
|
+
mock_client.search_listings_items.assert_called_once_with(
|
|
428
|
+
page_size=5,
|
|
429
|
+
page_token="abc",
|
|
430
|
+
included_data="summaries",
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
434
|
+
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
435
|
+
def test_list_recent_listings_empty(self, mock_client_class, mock_auth_class, runner):
|
|
436
|
+
"""Test listing recent listings with no results."""
|
|
437
|
+
mock_client = Mock()
|
|
438
|
+
mock_client.search_listings_items.return_value = {"items": []}
|
|
439
|
+
mock_client_class.return_value = mock_client
|
|
440
|
+
|
|
441
|
+
mock_auth = Mock()
|
|
442
|
+
mock_auth_class.return_value = mock_auth
|
|
443
|
+
|
|
444
|
+
result = runner.invoke(cli, ["list-recent-listings"])
|
|
445
|
+
|
|
446
|
+
assert result.exit_code == 0
|
|
447
|
+
output = json.loads(result.output)
|
|
448
|
+
assert output["items"] == []
|
|
449
|
+
|
|
450
|
+
|
|
367
451
|
class TestDeleteListing:
|
|
368
452
|
"""Test delete-listing command."""
|
|
369
453
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Tests for update and version commands."""
|
|
2
|
+
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from click.testing import CliRunner
|
|
7
|
+
|
|
8
|
+
from amazon_sp_cli import __version__
|
|
9
|
+
from amazon_sp_cli.main import cli
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestUpdate:
|
|
13
|
+
"""Test self-update command."""
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def runner(self):
|
|
17
|
+
"""Create Click test runner."""
|
|
18
|
+
return CliRunner()
|
|
19
|
+
|
|
20
|
+
@patch("amazon_sp_cli.commands.update.subprocess.run")
|
|
21
|
+
def test_update(self, mock_run, runner):
|
|
22
|
+
"""Test update command succeeds."""
|
|
23
|
+
mock_run.return_value.returncode = 0
|
|
24
|
+
|
|
25
|
+
result = runner.invoke(cli, ["update"])
|
|
26
|
+
|
|
27
|
+
assert result.exit_code == 0
|
|
28
|
+
assert "Updating amazon-sp-cli" in result.output
|
|
29
|
+
mock_run.assert_called_once()
|
|
30
|
+
args = mock_run.call_args[0][0]
|
|
31
|
+
assert args[-1] == "amazon-sp-cli"
|
|
32
|
+
|
|
33
|
+
@patch("amazon_sp_cli.commands.update.subprocess.run")
|
|
34
|
+
def test_update_failure(self, mock_run, runner):
|
|
35
|
+
"""Test update command aborts on failure."""
|
|
36
|
+
mock_run.return_value.returncode = 1
|
|
37
|
+
|
|
38
|
+
result = runner.invoke(cli, ["update"])
|
|
39
|
+
|
|
40
|
+
assert result.exit_code != 0
|
|
41
|
+
|
|
42
|
+
def test_update_dry_run(self, runner):
|
|
43
|
+
"""Test update --dry-run prints command without running."""
|
|
44
|
+
result = runner.invoke(cli, ["update", "--dry-run"])
|
|
45
|
+
|
|
46
|
+
assert result.exit_code == 0
|
|
47
|
+
assert "Would run:" in result.output
|
|
48
|
+
assert "amazon-sp-cli" in result.output
|
|
49
|
+
|
|
50
|
+
def test_version_flag(self, runner):
|
|
51
|
+
"""Test --version outputs version."""
|
|
52
|
+
result = runner.invoke(cli, ["--version"])
|
|
53
|
+
|
|
54
|
+
assert result.exit_code == 0
|
|
55
|
+
assert f"amz-sp, version {__version__}" in result.output
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"""Inventory commands."""
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
|
|
5
|
-
import click
|
|
6
|
-
|
|
7
|
-
from ..cli import handle_errors
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def register_inventory_commands(cli_group, ensure_auth_client):
|
|
11
|
-
"""Register inventory CLI commands."""
|
|
12
|
-
|
|
13
|
-
@cli_group.command("list-fba-inventory")
|
|
14
|
-
@click.option("--sku", help="Filter by specific SKU (comma-separated for multiple)")
|
|
15
|
-
@click.option("--next-token", help="Pagination token from a previous response")
|
|
16
|
-
@click.pass_context
|
|
17
|
-
@handle_errors
|
|
18
|
-
def list_fba_inventory(ctx, sku, next_token):
|
|
19
|
-
"""List FBA inventory summaries."""
|
|
20
|
-
_, client = ensure_auth_client(ctx)
|
|
21
|
-
response = client.get_fba_inventory(seller_skus=sku, next_token=next_token)
|
|
22
|
-
|
|
23
|
-
payload = response.get("payload", {})
|
|
24
|
-
summaries = payload.get("inventorySummaries", [])
|
|
25
|
-
result = {"inventory": summaries}
|
|
26
|
-
|
|
27
|
-
pagination = payload.get("pagination", {})
|
|
28
|
-
if pagination.get("nextToken"):
|
|
29
|
-
result["nextToken"] = pagination["nextToken"]
|
|
30
|
-
|
|
31
|
-
click.echo(json.dumps(result, indent=2))
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
"""Tests for inventory commands."""
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
from unittest.mock import Mock, patch
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from click.testing import CliRunner
|
|
8
|
-
|
|
9
|
-
from amazon_sp_cli.main import cli
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class TestListFbaInventory:
|
|
13
|
-
"""Test list-fba-inventory command."""
|
|
14
|
-
|
|
15
|
-
@pytest.fixture
|
|
16
|
-
def runner(self):
|
|
17
|
-
"""Create Click test runner."""
|
|
18
|
-
return CliRunner()
|
|
19
|
-
|
|
20
|
-
@pytest.fixture
|
|
21
|
-
def mock_inventory_response(self):
|
|
22
|
-
"""Mock FBA inventory response."""
|
|
23
|
-
return {
|
|
24
|
-
"payload": {
|
|
25
|
-
"inventorySummaries": [
|
|
26
|
-
{
|
|
27
|
-
"sellerSku": "SKU-123",
|
|
28
|
-
"asin": "B09BBL8T4Z",
|
|
29
|
-
"fnSku": "X123456789",
|
|
30
|
-
"productName": "Test Product",
|
|
31
|
-
"condition": "NewItem",
|
|
32
|
-
"inventoryDetails": {
|
|
33
|
-
"fulfillableQuantity": 10,
|
|
34
|
-
"inboundWorkingQuantity": 5,
|
|
35
|
-
},
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
"pagination": {"nextToken": "token123"},
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
43
|
-
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
44
|
-
def test_list_fba_inventory(self, mock_client_class, mock_auth_class, runner, mock_inventory_response):
|
|
45
|
-
"""Test listing FBA inventory."""
|
|
46
|
-
mock_client = Mock()
|
|
47
|
-
mock_client.get_fba_inventory.return_value = mock_inventory_response
|
|
48
|
-
mock_client_class.return_value = mock_client
|
|
49
|
-
|
|
50
|
-
mock_auth = Mock()
|
|
51
|
-
mock_auth_class.return_value = mock_auth
|
|
52
|
-
|
|
53
|
-
result = runner.invoke(cli, ["list-fba-inventory"])
|
|
54
|
-
|
|
55
|
-
assert result.exit_code == 0
|
|
56
|
-
# Strip PATH warning if present
|
|
57
|
-
output_text = result.output
|
|
58
|
-
if "{" in output_text:
|
|
59
|
-
brace_idx = output_text.index("{")
|
|
60
|
-
output_text = output_text[brace_idx:]
|
|
61
|
-
output = json.loads(output_text)
|
|
62
|
-
assert len(output["inventory"]) == 1
|
|
63
|
-
assert output["inventory"][0]["sellerSku"] == "SKU-123"
|
|
64
|
-
assert output["nextToken"] == "token123"
|
|
65
|
-
|
|
66
|
-
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
67
|
-
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
68
|
-
def test_list_fba_inventory_with_sku_filter(
|
|
69
|
-
self, mock_client_class, mock_auth_class, runner, mock_inventory_response
|
|
70
|
-
):
|
|
71
|
-
"""Test listing FBA inventory filtered by SKU."""
|
|
72
|
-
mock_client = Mock()
|
|
73
|
-
mock_client.get_fba_inventory.return_value = mock_inventory_response
|
|
74
|
-
mock_client_class.return_value = mock_client
|
|
75
|
-
|
|
76
|
-
mock_auth = Mock()
|
|
77
|
-
mock_auth_class.return_value = mock_auth
|
|
78
|
-
|
|
79
|
-
result = runner.invoke(cli, ["list-fba-inventory", "--sku", "SKU-123,SKU-456"])
|
|
80
|
-
|
|
81
|
-
assert result.exit_code == 0
|
|
82
|
-
mock_client.get_fba_inventory.assert_called_once_with(seller_skus="SKU-123,SKU-456", next_token=None)
|
|
83
|
-
|
|
84
|
-
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
85
|
-
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
86
|
-
def test_list_fba_inventory_with_next_token(
|
|
87
|
-
self, mock_client_class, mock_auth_class, runner, mock_inventory_response
|
|
88
|
-
):
|
|
89
|
-
"""Test listing FBA inventory with pagination token."""
|
|
90
|
-
mock_client = Mock()
|
|
91
|
-
mock_client.get_fba_inventory.return_value = mock_inventory_response
|
|
92
|
-
mock_client_class.return_value = mock_client
|
|
93
|
-
|
|
94
|
-
mock_auth = Mock()
|
|
95
|
-
mock_auth_class.return_value = mock_auth
|
|
96
|
-
|
|
97
|
-
result = runner.invoke(cli, ["list-fba-inventory", "--next-token", "token456"])
|
|
98
|
-
|
|
99
|
-
assert result.exit_code == 0
|
|
100
|
-
mock_client.get_fba_inventory.assert_called_once_with(seller_skus=None, next_token="token456")
|
|
101
|
-
|
|
102
|
-
@patch("amazon_sp_cli.cli.SPAPIAuth")
|
|
103
|
-
@patch("amazon_sp_cli.cli.SPAPIClient")
|
|
104
|
-
def test_list_fba_inventory_empty(self, mock_client_class, mock_auth_class, runner):
|
|
105
|
-
"""Test listing FBA inventory with no results."""
|
|
106
|
-
mock_client = Mock()
|
|
107
|
-
mock_client.get_fba_inventory.return_value = {"payload": {"inventorySummaries": []}}
|
|
108
|
-
mock_client_class.return_value = mock_client
|
|
109
|
-
|
|
110
|
-
mock_auth = Mock()
|
|
111
|
-
mock_auth_class.return_value = mock_auth
|
|
112
|
-
|
|
113
|
-
result = runner.invoke(cli, ["list-fba-inventory"])
|
|
114
|
-
|
|
115
|
-
assert result.exit_code == 0
|
|
116
|
-
output = json.loads(result.output)
|
|
117
|
-
assert output["inventory"] == []
|
|
118
|
-
assert "nextToken" not in output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|