Compare commits
2 Commits
039612cb6e
...
f9c5ef36da
| Author | SHA1 | Date |
|---|---|---|
|
|
f9c5ef36da | |
|
|
ed2333d188 |
|
|
@ -6,10 +6,8 @@ import 'wordpress_product_mapper.dart';
|
||||||
|
|
||||||
/// Real [ProductPublishingRepository] backed by the WooCommerce REST API.
|
/// Real [ProductPublishingRepository] backed by the WooCommerce REST API.
|
||||||
///
|
///
|
||||||
/// Supports read-only product retrieval and status updates via
|
/// Supports product retrieval, publishing, and status updates via
|
||||||
/// `PUT /wp-json/wc/v3/products/{id}`. The [publishDraft] method throws
|
/// `PUT /wp-json/wc/v3/products/{id}`.
|
||||||
/// [UnimplementedError] — full publishing support will be added in a future
|
|
||||||
/// iteration.
|
|
||||||
class WordPressProductPublishingRepository implements ProductPublishingRepository {
|
class WordPressProductPublishingRepository implements ProductPublishingRepository {
|
||||||
final WooCommerceApiClient _apiClient;
|
final WooCommerceApiClient _apiClient;
|
||||||
final WordPressProductMapper _mapper;
|
final WordPressProductMapper _mapper;
|
||||||
|
|
@ -27,14 +25,9 @@ class WordPressProductPublishingRepository implements ProductPublishingRepositor
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ProductDraft> publishDraft(String id) {
|
Future<ProductDraft> publishDraft(String id) async {
|
||||||
// Publishing is not yet implemented for the real backend.
|
final json = await _apiClient.updateProduct(id, {'status': 'publish'});
|
||||||
// This will be added in a future iteration alongside media upload
|
return _mapper.fromJson(json);
|
||||||
// and order sync.
|
|
||||||
throw UnimplementedError(
|
|
||||||
'WordPressProductPublishingRepository.publishDraft is not yet implemented. '
|
|
||||||
'Use FakeProductPublishingRepository for development.',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -120,21 +120,106 @@ void main() {
|
||||||
expect(drafts[1].name, 'Product 2');
|
expect(drafts[1].name, 'Product 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('publishDraft throws UnimplementedError', () {
|
group('publishDraft', () {
|
||||||
final mockClient = MockClient((request) async {
|
/// Builds a single WooCommerce product JSON response with the given
|
||||||
return http.Response('[]', 200);
|
/// [id] and status set to `'publish'`.
|
||||||
|
Map<String, dynamic> buildPublishedProductJson(int id) {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'name': 'Product $id',
|
||||||
|
'description': '<p>Description</p>',
|
||||||
|
'price': '10.99',
|
||||||
|
'sku': 'SKU-$id',
|
||||||
|
'status': 'publish',
|
||||||
|
'date_modified': '2026-04-01T10:00:00',
|
||||||
|
'date_created': '2026-03-01T08:00:00',
|
||||||
|
'categories': [
|
||||||
|
{'id': 1, 'name': 'Test Category', 'slug': 'test-category'},
|
||||||
|
],
|
||||||
|
'images': [
|
||||||
|
{'id': 1, 'src': 'https://example.com/img$id.jpg'},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('sends PUT with status publish and returns mapped ProductDraft', () async {
|
||||||
|
Map<String, dynamic>? capturedBody;
|
||||||
|
Uri? capturedUri;
|
||||||
|
String? capturedMethod;
|
||||||
|
|
||||||
|
final mockClient = MockClient((request) async {
|
||||||
|
capturedMethod = request.method;
|
||||||
|
capturedUri = request.url;
|
||||||
|
capturedBody = jsonDecode(request.body) as Map<String, dynamic>;
|
||||||
|
|
||||||
|
return http.Response(jsonEncode(buildPublishedProductJson(42)), 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
final apiClient = WooCommerceApiClient(
|
||||||
|
siteUrl: 'https://store.example.com',
|
||||||
|
consumerKey: 'ck_test',
|
||||||
|
consumerSecret: 'cs_test',
|
||||||
|
httpClient: mockClient,
|
||||||
|
);
|
||||||
|
|
||||||
|
final repository = WordPressProductPublishingRepository(apiClient: apiClient);
|
||||||
|
final result = await repository.publishDraft('42');
|
||||||
|
|
||||||
|
// Verify the HTTP request shape.
|
||||||
|
expect(capturedMethod, 'PUT');
|
||||||
|
expect(capturedUri!.path, '/wp-json/wc/v3/products/42');
|
||||||
|
expect(capturedBody, {'status': 'publish'});
|
||||||
|
|
||||||
|
// Verify the returned domain object is cleanly mapped.
|
||||||
|
expect(result, isA<ProductDraft>());
|
||||||
|
expect(result.id, '42');
|
||||||
|
expect(result.name, 'Product 42');
|
||||||
|
expect(result.status, PublishStatus.published);
|
||||||
});
|
});
|
||||||
|
|
||||||
final apiClient = WooCommerceApiClient(
|
test('propagates WooCommerceApiException on non-200 response', () async {
|
||||||
siteUrl: 'https://store.example.com',
|
final mockClient = MockClient((request) async {
|
||||||
consumerKey: 'ck_test',
|
return http.Response('{"code":"rest_cannot_edit"}', 403);
|
||||||
consumerSecret: 'cs_test',
|
});
|
||||||
httpClient: mockClient,
|
|
||||||
);
|
|
||||||
|
|
||||||
final repository = WordPressProductPublishingRepository(apiClient: apiClient);
|
final apiClient = WooCommerceApiClient(
|
||||||
|
siteUrl: 'https://store.example.com',
|
||||||
|
consumerKey: 'ck_test',
|
||||||
|
consumerSecret: 'cs_test',
|
||||||
|
httpClient: mockClient,
|
||||||
|
);
|
||||||
|
|
||||||
expect(() => repository.publishDraft('1'), throwsA(isA<UnimplementedError>()));
|
final repository = WordPressProductPublishingRepository(apiClient: apiClient);
|
||||||
|
|
||||||
|
expect(() => repository.publishDraft('42'), throwsA(isA<WooCommerceApiException>()));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns ProductDraft, not raw WooCommerce JSON (package boundary)', () async {
|
||||||
|
final mockClient = MockClient((request) async {
|
||||||
|
final json = buildPublishedProductJson(9);
|
||||||
|
json['permalink'] = 'https://store.example.com/product/9';
|
||||||
|
json['meta_data'] = [
|
||||||
|
{'id': 1, 'key': '_internal', 'value': 'secret'},
|
||||||
|
];
|
||||||
|
return http.Response(jsonEncode(json), 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
final apiClient = WooCommerceApiClient(
|
||||||
|
siteUrl: 'https://store.example.com',
|
||||||
|
consumerKey: 'ck_test',
|
||||||
|
consumerSecret: 'cs_test',
|
||||||
|
httpClient: mockClient,
|
||||||
|
);
|
||||||
|
|
||||||
|
final repository = WordPressProductPublishingRepository(apiClient: apiClient);
|
||||||
|
final result = await repository.publishDraft('9');
|
||||||
|
|
||||||
|
// The result is a domain ProductDraft — no WooCommerce-specific
|
||||||
|
// fields like permalink or meta_data are exposed.
|
||||||
|
expect(result, isA<ProductDraft>());
|
||||||
|
expect(result.id, '9');
|
||||||
|
expect(result.status, PublishStatus.published);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getProductDrafts propagates API errors', () async {
|
test('getProductDrafts propagates API errors', () async {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue