test: 补充权限、消息与会话服务回归用例
会话读取、接管、重分配与 Socket 订阅统一校验角色、组织与可见性。
This commit is contained in:
1 parent
5da5f910da
commit
2554eb7bc7
97 files changed
+37281
No files matched your search
@@ -0,0 +1,705 @@
|
||||
"""
|
||||
Copyright 2024-2026 ChatterMate
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import json
|
||||
from unittest.mock import patch, MagicMock, ANY
|
||||
from app.services.shopify import ShopifyService
|
||||
from app.models.shopify import ShopifyShop
|
||||
from sqlalchemy.orm import Session
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
@pytest.fixture
|
||||
def mock_db():
|
||||
"""Create a mock database session"""
|
||||
db = MagicMock(spec=Session)
|
||||
return db
|
||||
|
||||
@pytest.fixture
|
||||
def mock_shop():
|
||||
"""Create a mock Shopify shop"""
|
||||
shop = MagicMock(spec=ShopifyShop)
|
||||
shop.id = UUID("00000000-0000-0000-0000-000000000003")
|
||||
shop.organization_id = UUID("00000000-0000-0000-0000-000000000002")
|
||||
shop.shop_domain = "test-shop.myshopify.com"
|
||||
shop.access_token = "test_access_token"
|
||||
shop.is_installed = True
|
||||
return shop
|
||||
|
||||
@pytest.fixture
|
||||
def shopify_service(mock_db):
|
||||
"""Create a ShopifyService instance with mocked dependencies"""
|
||||
with patch('app.services.shopify.ShopifyShopRepository') as mock_shop_repo_class, \
|
||||
patch('app.services.shopify.AgentShopifyConfigRepository') as mock_config_repo_class:
|
||||
|
||||
# Create and configure mock repositories
|
||||
mock_shop_repo = MagicMock()
|
||||
mock_shop_repo_class.return_value = mock_shop_repo
|
||||
|
||||
mock_config_repo = MagicMock()
|
||||
mock_config_repo_class.return_value = mock_config_repo
|
||||
|
||||
# Create service instance
|
||||
service = ShopifyService(mock_db)
|
||||
|
||||
# Test access to mocks
|
||||
service._mock_shop_repo = mock_shop_repo
|
||||
service._mock_config_repo = mock_config_repo
|
||||
|
||||
return service
|
||||
|
||||
@pytest.fixture
|
||||
def mock_graphql_success_response():
|
||||
"""Create a mock successful GraphQL response"""
|
||||
return {
|
||||
"data": {
|
||||
"products": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "gid://shopify/Product/123456789",
|
||||
"title": "Test Product",
|
||||
"description": "This is a test product",
|
||||
"handle": "test-product",
|
||||
"productType": "Test Type",
|
||||
"vendor": "Test Vendor",
|
||||
"totalInventory": 10,
|
||||
"priceRangeV2": {
|
||||
"minVariantPrice": {
|
||||
"amount": "19.99",
|
||||
"currencyCode": "USD"
|
||||
},
|
||||
"maxVariantPrice": {
|
||||
"amount": "29.99",
|
||||
"currencyCode": "USD"
|
||||
}
|
||||
},
|
||||
"images": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "image-id",
|
||||
"url": "https://example.com/image.jpg",
|
||||
"altText": "Test Image"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tags": ["tag1", "tag2"],
|
||||
"createdAt": "2023-01-01T00:00:00Z",
|
||||
"updatedAt": "2023-01-02T00:00:00Z"
|
||||
}
|
||||
}
|
||||
],
|
||||
"pageInfo": {
|
||||
"hasNextPage": False,
|
||||
"endCursor": "cursor-value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@pytest.fixture
|
||||
def mock_rest_success_response():
|
||||
"""Create a mock successful REST API response"""
|
||||
return {
|
||||
"product": {
|
||||
"id": 123456789,
|
||||
"title": "Test Product",
|
||||
"description": "This is a test product",
|
||||
"handle": "test-product",
|
||||
"product_type": "Test Type",
|
||||
"vendor": "Test Vendor",
|
||||
"price": "19.99",
|
||||
"image": {"src": "https://example.com/image.jpg"},
|
||||
"tags": "tag1, tag2",
|
||||
"created_at": "2023-01-01T00:00:00Z",
|
||||
"updated_at": "2023-01-02T00:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
def test_execute_graphql_success(shopify_service, mock_shop, mock_graphql_success_response):
|
||||
"""Test successful GraphQL query execution"""
|
||||
# Arrange
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = mock_graphql_success_response
|
||||
|
||||
with patch('requests.post', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service._execute_graphql(
|
||||
shop=mock_shop,
|
||||
query="query { products { edges { node { id title } } } }",
|
||||
variables={"limit": 10}
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "data" in result
|
||||
assert "products" in result["data"]
|
||||
|
||||
def test_execute_graphql_shop_not_connected(shopify_service):
|
||||
"""Test GraphQL query with unconnected shop"""
|
||||
# Arrange
|
||||
mock_shop = MagicMock(spec=ShopifyShop)
|
||||
mock_shop.is_installed = False
|
||||
|
||||
# Act
|
||||
result = shopify_service._execute_graphql(
|
||||
shop=mock_shop,
|
||||
query="query { products { edges { node { id title } } } }"
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert "not connected" in result["message"].lower()
|
||||
|
||||
def test_execute_graphql_api_error(shopify_service, mock_shop):
|
||||
"""Test GraphQL query with API error"""
|
||||
# Arrange
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 400
|
||||
mock_response.text = "Bad Request"
|
||||
|
||||
with patch('requests.post', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service._execute_graphql(
|
||||
shop=mock_shop,
|
||||
query="query { products { edges { node { id title } } } }"
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert "Failed to execute GraphQL query" in result["message"]
|
||||
|
||||
def test_execute_graphql_with_errors(shopify_service, mock_shop):
|
||||
"""Test GraphQL query that returns errors"""
|
||||
# Arrange
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {
|
||||
"errors": [
|
||||
{"message": "Field 'product' doesn't exist"}
|
||||
]
|
||||
}
|
||||
|
||||
with patch('requests.post', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service._execute_graphql(
|
||||
shop=mock_shop,
|
||||
query="query { product { id } }"
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert "GraphQL errors" in result["message"] or "Field 'product' doesn't exist" in result["message"]
|
||||
|
||||
def test_get_products_success(shopify_service, mock_shop, mock_graphql_success_response):
|
||||
"""Test successful product retrieval"""
|
||||
# Arrange
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value={
|
||||
"success": True,
|
||||
"data": mock_graphql_success_response["data"]
|
||||
}):
|
||||
# Act
|
||||
result = shopify_service.get_products(mock_shop, 10)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "products" in result
|
||||
assert len(result["products"]) == 1
|
||||
assert result["products"][0]["title"] == "Test Product"
|
||||
|
||||
def test_get_products_failure(shopify_service, mock_shop):
|
||||
"""Test product retrieval failure"""
|
||||
# Arrange
|
||||
error_response = {
|
||||
"success": False,
|
||||
"message": "API Error"
|
||||
}
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value=error_response):
|
||||
# Act
|
||||
result = shopify_service.get_products(mock_shop)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert result["message"] == "API Error"
|
||||
|
||||
def test_get_product_success(shopify_service, mock_shop):
|
||||
"""Test successful single product retrieval"""
|
||||
# Arrange
|
||||
product_data = {
|
||||
"product": {
|
||||
"id": "gid://shopify/Product/123456789",
|
||||
"title": "Test Product",
|
||||
"description": "Product description",
|
||||
"descriptionHtml": "<p>Product description</p>",
|
||||
"handle": "test-product",
|
||||
"productType": "Test Type",
|
||||
"vendor": "Test Vendor",
|
||||
"totalInventory": 10,
|
||||
"priceRangeV2": {
|
||||
"minVariantPrice": {
|
||||
"amount": "19.99",
|
||||
"currencyCode": "USD"
|
||||
},
|
||||
"maxVariantPrice": {
|
||||
"amount": "19.99",
|
||||
"currencyCode": "USD"
|
||||
}
|
||||
},
|
||||
"images": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "gid://shopify/ProductImage/111",
|
||||
"url": "https://example.com/image.jpg",
|
||||
"altText": "Image",
|
||||
"width": 800,
|
||||
"height": 600
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"variants": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "gid://shopify/ProductVariant/222",
|
||||
"title": "Default",
|
||||
"price": "19.99",
|
||||
"compareAtPrice": None,
|
||||
"inventoryQuantity": 10,
|
||||
"sku": "SKU123",
|
||||
"barcode": "BARCODE123"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"tags": ["tag1", "tag2"],
|
||||
"collections": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "gid://shopify/Collection/333",
|
||||
"title": "Featured"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": "2023-01-01T00:00:00Z",
|
||||
"updatedAt": "2023-01-02T00:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value={
|
||||
"success": True,
|
||||
"data": product_data
|
||||
}):
|
||||
# Act
|
||||
result = shopify_service.get_product(mock_shop, "123456789")
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "product" in result
|
||||
assert result["product"]["title"] == "Test Product"
|
||||
assert "images" in result["product"]
|
||||
assert "variants" in result["product"]
|
||||
assert "collections" in result["product"]
|
||||
|
||||
def test_get_product_not_found(shopify_service, mock_shop):
|
||||
"""Test product retrieval when product doesn't exist"""
|
||||
# Arrange
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value={
|
||||
"success": True,
|
||||
"data": {}
|
||||
}):
|
||||
# Act
|
||||
result = shopify_service.get_product(mock_shop, "999999")
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert "not found" in result["message"].lower()
|
||||
|
||||
def test_create_product_success(shopify_service, mock_shop, mock_rest_success_response):
|
||||
"""Test successful product creation"""
|
||||
# Arrange
|
||||
product_data = {
|
||||
"title": "New Product",
|
||||
"body_html": "Product description",
|
||||
"vendor": "Test Vendor",
|
||||
"product_type": "Test Type",
|
||||
"tags": ["tag1", "tag2"]
|
||||
}
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 201
|
||||
mock_response.json.return_value = mock_rest_success_response
|
||||
|
||||
with patch('requests.post', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service.create_product(mock_shop, product_data)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "product" in result
|
||||
assert "created successfully" in result["message"].lower()
|
||||
|
||||
def test_create_product_failure(shopify_service, mock_shop):
|
||||
"""Test product creation failure"""
|
||||
# Arrange
|
||||
product_data = {"title": "New Product"}
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 422
|
||||
mock_response.text = "Validation error"
|
||||
|
||||
with patch('requests.post', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service.create_product(mock_shop, product_data)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert "Failed to create product" in result["message"]
|
||||
|
||||
def test_update_product_success(shopify_service, mock_shop, mock_rest_success_response):
|
||||
"""Test successful product update"""
|
||||
# Arrange
|
||||
product_id = "123456789"
|
||||
product_data = {"title": "Updated Product"}
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = mock_rest_success_response
|
||||
|
||||
with patch('requests.put', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service.update_product(mock_shop, product_id, product_data)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "product" in result
|
||||
assert "updated successfully" in result["message"].lower()
|
||||
|
||||
def test_delete_product_success(shopify_service, mock_shop):
|
||||
"""Test successful product deletion"""
|
||||
# Arrange
|
||||
product_id = "123456789"
|
||||
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
|
||||
with patch('requests.delete', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service.delete_product(mock_shop, product_id)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "deleted successfully" in result["message"].lower()
|
||||
|
||||
def test_search_products_success(shopify_service, mock_shop, mock_graphql_success_response):
|
||||
"""Test successful product search"""
|
||||
# Arrange
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value={
|
||||
"success": True,
|
||||
"data": mock_graphql_success_response["data"]
|
||||
}):
|
||||
# Act
|
||||
result = shopify_service.search_products(mock_shop, "test", 10)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "products" in result
|
||||
assert len(result["products"]) == 1
|
||||
assert result["products"][0]["title"] == "Test Product"
|
||||
|
||||
def test_search_orders_success(shopify_service, mock_shop):
|
||||
"""Test successful order search"""
|
||||
# Arrange
|
||||
mock_order_response = {
|
||||
"data": {
|
||||
"orders": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "gid://shopify/Order/987654321",
|
||||
"name": "#1001",
|
||||
"email": "customer@example.com",
|
||||
"createdAt": "2023-01-01T00:00:00Z",
|
||||
"displayFinancialStatus": "PAID",
|
||||
"displayFulfillmentStatus": "FULFILLED",
|
||||
"subtotalLineItemsQuantity": 2,
|
||||
"currentSubtotalPriceSet": {
|
||||
"shopMoney": {
|
||||
"amount": "24.99",
|
||||
"currencyCode": "USD"
|
||||
}
|
||||
},
|
||||
"currentTotalPriceSet": {
|
||||
"shopMoney": {
|
||||
"amount": "29.99",
|
||||
"currencyCode": "USD"
|
||||
}
|
||||
},
|
||||
"originalTotalPriceSet": {
|
||||
"shopMoney": {
|
||||
"amount": "29.99",
|
||||
"currencyCode": "USD"
|
||||
}
|
||||
},
|
||||
"customer": {
|
||||
"id": "customer-id",
|
||||
"firstName": "John",
|
||||
"lastName": "Doe",
|
||||
"email": "john.doe@example.com"
|
||||
},
|
||||
"lineItems": {"edges": []},
|
||||
"shippingAddress": {},
|
||||
"fulfillments": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"pageInfo": {
|
||||
"hasNextPage": False,
|
||||
"endCursor": "cursor-value"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value={
|
||||
"success": True,
|
||||
"data": mock_order_response["data"]
|
||||
}):
|
||||
# Act
|
||||
result = shopify_service.search_orders(mock_shop, {"query": "test"}, 10)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "orders" in result
|
||||
assert len(result["orders"]) == 1
|
||||
assert result["orders"][0]["name"] == "#1001"
|
||||
|
||||
def test_get_order_success(shopify_service, mock_shop):
|
||||
"""Test successful order retrieval"""
|
||||
# Arrange
|
||||
mock_order_data = {
|
||||
"order": {
|
||||
"id": "gid://shopify/Order/987654321",
|
||||
"name": "#1001",
|
||||
"email": "customer@example.com",
|
||||
"processedAt": "2023-01-01T00:01:00Z",
|
||||
"createdAt": "2023-01-01T00:00:00Z",
|
||||
"updatedAt": "2023-01-01T00:02:00Z",
|
||||
"cancelledAt": None,
|
||||
"cancelReason": None,
|
||||
"displayFinancialStatus": "PAID",
|
||||
"displayFulfillmentStatus": "FULFILLED",
|
||||
"customerJourneySummary": {
|
||||
"customerOrderIndex": 1,
|
||||
"daysToConversion": 2
|
||||
},
|
||||
"customer": {
|
||||
"id": "gid://shopify/Customer/123",
|
||||
"firstName": "John",
|
||||
"lastName": "Doe",
|
||||
"email": "john.doe@example.com",
|
||||
"phone": "+1234567890"
|
||||
},
|
||||
"currentTotalPrice": {
|
||||
"amount": "29.99",
|
||||
"currencyCode": "USD"
|
||||
},
|
||||
"originalTotalPrice": {
|
||||
"amount": "29.99",
|
||||
"currencyCode": "USD"
|
||||
},
|
||||
"shippingAddress": {
|
||||
"address1": "123 Test St",
|
||||
"address2": "",
|
||||
"city": "Test City",
|
||||
"country": "US",
|
||||
"zip": "12345",
|
||||
"phone": "+1234567890",
|
||||
"name": "John Doe"
|
||||
},
|
||||
"fulfillments": [
|
||||
{
|
||||
"status": "SUCCESS",
|
||||
"trackingInfo": [
|
||||
{
|
||||
"number": "12345",
|
||||
"url": "https://tracking.example.com/12345"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"lineItems": {
|
||||
"edges": [
|
||||
{
|
||||
"node": {
|
||||
"id": "gid://shopify/LineItem/111",
|
||||
"name": "Test Product",
|
||||
"quantity": 1,
|
||||
"originalTotalPrice": {
|
||||
"amount": "19.99",
|
||||
"currencyCode": "USD"
|
||||
},
|
||||
"variant": {
|
||||
"id": "gid://shopify/ProductVariant/222",
|
||||
"title": "Default",
|
||||
"sku": "SKU123"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
with patch.object(shopify_service, '_execute_graphql', return_value={
|
||||
"success": True,
|
||||
"data": mock_order_data
|
||||
}):
|
||||
# Act
|
||||
result = shopify_service.get_order(mock_shop, "987654321")
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
assert "order" in result
|
||||
assert result["order"]["name"] == "#1001"
|
||||
assert "line_items" in result["order"]
|
||||
assert "fulfillments" in result["order"]
|
||||
assert "customer" in result["order"]
|
||||
assert "shipping_address" in result["order"]
|
||||
|
||||
def test_make_rest_request_success(shopify_service, mock_shop):
|
||||
"""Test successful REST API request"""
|
||||
# Arrange
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {"products": [{"id": 123, "title": "Test Product"}]}
|
||||
|
||||
with patch('requests.request', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service._make_rest_request(
|
||||
shop=mock_shop,
|
||||
method="GET",
|
||||
endpoint="products.json",
|
||||
payload=None
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert "success" in result and result["success"] is True
|
||||
assert "products" in result["data"]
|
||||
|
||||
def test_make_rest_request_rate_limit(shopify_service, mock_shop):
|
||||
"""Test REST API request with rate limit response"""
|
||||
# Arrange
|
||||
mock_response = MagicMock()
|
||||
mock_response.status_code = 429
|
||||
mock_response.headers = {"Retry-After": "5"}
|
||||
|
||||
with patch('requests.request', return_value=mock_response):
|
||||
# Act
|
||||
result = shopify_service._make_rest_request(
|
||||
shop=mock_shop,
|
||||
method="GET",
|
||||
endpoint="products.json"
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is False
|
||||
assert "Rate limit exceeded" in result["message"]
|
||||
assert result["status_code"] == 429
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_execute_graphql_async_success(shopify_service, mock_shop, mock_graphql_success_response):
|
||||
"""Test successful async GraphQL query execution"""
|
||||
# Arrange
|
||||
mock_response = MagicMock()
|
||||
mock_response.status = 200
|
||||
mock_response.json = MagicMock(return_value=mock_graphql_success_response)
|
||||
|
||||
mock_session = MagicMock()
|
||||
mock_session.__aenter__.return_value = mock_session
|
||||
mock_session.post.return_value.__aenter__.return_value = mock_response
|
||||
|
||||
mock_client_session = MagicMock()
|
||||
mock_client_session.__aenter__.return_value = mock_session
|
||||
|
||||
with patch('aiohttp.ClientSession', return_value=mock_client_session):
|
||||
# Act
|
||||
with patch.object(shopify_service, '_execute_graphql_async', return_value={
|
||||
"success": True,
|
||||
"data": mock_graphql_success_response["data"]
|
||||
}):
|
||||
result = await shopify_service._execute_graphql_async(
|
||||
shop=mock_shop,
|
||||
query="query { products { edges { node { id title } } } }",
|
||||
variables={"limit": 10}
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert result["success"] is True
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def reload_shopify_urls(monkeypatch):
|
||||
"""Re-import shopify_urls under a given SHOPIFY_ADMIN_BASE, then restore it."""
|
||||
import importlib
|
||||
import app.services.shopify_urls as shopify_urls
|
||||
|
||||
def _reload(admin_base=None):
|
||||
monkeypatch.delenv("SHOPIFY_ADMIN_BASE", raising=False)
|
||||
if admin_base is not None:
|
||||
monkeypatch.setenv("SHOPIFY_ADMIN_BASE", admin_base)
|
||||
return importlib.reload(shopify_urls)
|
||||
|
||||
yield _reload
|
||||
monkeypatch.delenv("SHOPIFY_ADMIN_BASE", raising=False)
|
||||
importlib.reload(shopify_urls)
|
||||
|
||||
|
||||
def test_shopify_urls_default_to_the_shop_host(reload_shopify_urls):
|
||||
urls = reload_shopify_urls()
|
||||
assert urls.shopify_admin_url("test-shop.myshopify.com", "graphql.json") == (
|
||||
"https://test-shop.myshopify.com/admin/api/2025-10/graphql.json"
|
||||
)
|
||||
assert urls.shopify_oauth_token_url("test-shop.myshopify.com") == (
|
||||
"https://test-shop.myshopify.com/admin/oauth/access_token"
|
||||
)
|
||||
|
||||
|
||||
def test_shopify_admin_base_puts_the_shop_under_the_override(reload_shopify_urls):
|
||||
urls = reload_shopify_urls("http://127.0.0.1:14020/shopify/")
|
||||
assert urls.shopify_admin_url("test-shop.myshopify.com", "products/1.json") == (
|
||||
"http://127.0.0.1:14020/shopify/test-shop.myshopify.com/admin/api/2025-10/products/1.json"
|
||||
)
|
||||
assert urls.shopify_oauth_token_url("test-shop.myshopify.com") == (
|
||||
"http://127.0.0.1:14020/shopify/test-shop.myshopify.com/admin/oauth/access_token"
|
||||
)
|
||||
|
||||
|
||||
def test_execute_graphql_posts_to_the_admin_url(mock_db, mock_shop, monkeypatch):
|
||||
monkeypatch.setattr("app.services.shopify_urls.SHOPIFY_ADMIN_BASE", "http://fake/shopify")
|
||||
response = MagicMock(status_code=200)
|
||||
response.json.return_value = {"data": {}}
|
||||
with patch("requests.post", return_value=response) as mock_post:
|
||||
ShopifyService(mock_db)._execute_graphql(mock_shop, "{ shop { name } }")
|
||||
assert mock_post.call_args.args[0] == (
|
||||
"http://fake/shopify/test-shop.myshopify.com/admin/api/2025-10/graphql.json"
|
||||
)
|
||||
Reference in new issue
Block a user