From 78edba358e92ebd57da9dcc4b537be2df09aa9c6 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Tue, 1 Sep 2026 13:55:49 -0600 Subject: [PATCH 1/2] Return empty arrays from TaxonomyServiceRemoteREST tag/category mapping --- Modules/Sources/WordPressKitObjC/TaxonomyServiceRemoteREST.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Sources/WordPressKitObjC/TaxonomyServiceRemoteREST.m b/Modules/Sources/WordPressKitObjC/TaxonomyServiceRemoteREST.m index ffa31b668971..9ddf96e5d0b5 100644 --- a/Modules/Sources/WordPressKitObjC/TaxonomyServiceRemoteREST.m +++ b/Modules/Sources/WordPressKitObjC/TaxonomyServiceRemoteREST.m @@ -287,7 +287,7 @@ - (void)updateTaxonomyWithType:(NSString *)typeIdentifier { return [jsonArray wp_map:^id(NSDictionary *jsonCategory) { return [self remoteCategoryWithJSONDictionary:jsonCategory]; - }]; + }] ?: @[]; } - (RemotePostCategory *)remoteCategoryWithJSONDictionary:(NSDictionary *)jsonCategory @@ -303,7 +303,7 @@ - (RemotePostCategory *)remoteCategoryWithJSONDictionary:(NSDictionary *)jsonCat { return [jsonArray wp_map:^id(NSDictionary *jsonTag) { return [self remoteTagWithJSONDictionary:jsonTag]; - }]; + }] ?: @[]; } - (RemotePostTag *)remoteTagWithJSONDictionary:(NSDictionary *)jsonTag From 50d24ca77af86f11a189d201056919e95fb92c75 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Tue, 1 Sep 2026 14:42:53 -0600 Subject: [PATCH 2/2] Test that missing tag/category keys yield empty arrays --- .../Tests/TaxonomyServiceRemoteRESTTests.m | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Tests/WordPressKitTests/WordPressKitTests/Tests/TaxonomyServiceRemoteRESTTests.m b/Tests/WordPressKitTests/WordPressKitTests/Tests/TaxonomyServiceRemoteRESTTests.m index a026dd6178ca..dabbe6a6b240 100644 --- a/Tests/WordPressKitTests/WordPressKitTests/Tests/TaxonomyServiceRemoteRESTTests.m +++ b/Tests/WordPressKitTests/WordPressKitTests/Tests/TaxonomyServiceRemoteRESTTests.m @@ -200,6 +200,32 @@ - (void)testThatSearchCategoriesWithNameWorks failure:^(NSError * __unused error) {}]; } +/// A response missing the `categories` key must yield an empty array, not `nil` +/// (a `nil` `NSArray` traps when bridged to a non-optional Swift array). +- (void)testThatGetCategoriesWithMissingCategoriesKeyReturnsEmptyArray +{ + NSString *url = [self GETtaxonomyURLWithType:@"categories"]; + + id api = self.service.wordPressComRESTAPI; + NSDictionary *json = @{ @"found": @0 }; + NSHTTPURLResponse *response = OCMStrictClassMock([NSHTTPURLResponse class]); + OCMStub([api get:[OCMArg isEqual:url] + parameters:[OCMArg any] + success:([OCMArg invokeBlockWithArgs:json, response, nil]) + failure:[OCMArg isNotNil]]); + + XCTestExpectation *gotEmptyArray = [self expectationWithDescription:@"categories should be empty"]; + id success = ^(NSArray * _Nonnull categories) { + XCTAssertNotNil(categories); + XCTAssertEqualObjects(categories, @[]); + [gotEmptyArray fulfill]; + }; + [self.service getCategoriesWithSuccess:success + failure:^(NSError * __unused error) { XCTFail(@"should not fail"); }]; + + [self waitForExpectations:@[gotEmptyArray] timeout:0.1]; +} + #pragma mark - Tags - (void)testThatCreateTagWorks @@ -315,4 +341,30 @@ - (void)testThatSearchTagsWithNameWorks failure:^(NSError * __unused error) {}]; } +/// A response missing the `tags` key must yield an empty array, not `nil` +/// (a `nil` `NSArray` traps when bridged to a non-optional Swift array). +- (void)testThatGetTagsWithMissingTagsKeyReturnsEmptyArray +{ + NSString *url = [self GETtaxonomyURLWithType:@"tags"]; + + id api = self.service.wordPressComRESTAPI; + NSDictionary *json = @{ @"found": @0 }; + NSHTTPURLResponse *response = OCMStrictClassMock([NSHTTPURLResponse class]); + OCMStub([api get:[OCMArg isEqual:url] + parameters:[OCMArg any] + success:([OCMArg invokeBlockWithArgs:json, response, nil]) + failure:[OCMArg isNotNil]]); + + XCTestExpectation *gotEmptyArray = [self expectationWithDescription:@"tags should be empty"]; + id success = ^(NSArray * _Nonnull tags) { + XCTAssertNotNil(tags); + XCTAssertEqualObjects(tags, @[]); + [gotEmptyArray fulfill]; + }; + [self.service getTagsWithSuccess:success + failure:^(NSError * __unused error) { XCTFail(@"should not fail"); }]; + + [self waitForExpectations:@[gotEmptyArray] timeout:0.1]; +} + @end