Skip to content

Commit 2a30c2e

Browse files
authored
Merge branch 'trunk' into issue/14869-use-observation-to-fix-refresh-issue
2 parents f52863b + 552d492 commit 2a30c2e

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@
423423
450106852399A7CB00E24722 /* TaxClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450106842399A7CB00E24722 /* TaxClass.swift */; };
424424
4501068F2399B19500E24722 /* TaxRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4501068E2399B19500E24722 /* TaxRemote.swift */; };
425425
450106912399B2C800E24722 /* TaxClassListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450106902399B2C800E24722 /* TaxClassListMapper.swift */; };
426+
450BFA6B2D52777500C2D1D7 /* WordPressMediaMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450BFA6A2D52777500C2D1D7 /* WordPressMediaMapperTests.swift */; };
427+
450BFA6D2D52790E00C2D1D7 /* media-library-with-empty-sizes.json in Resources */ = {isa = PBXBuildFile; fileRef = 450BFA6C2D52790200C2D1D7 /* media-library-with-empty-sizes.json */; };
426428
451274A625276C82009911FF /* product-variation.json in Resources */ = {isa = PBXBuildFile; fileRef = 451274A525276C82009911FF /* product-variation.json */; };
427429
4513382027A8227F00AE5E78 /* InboxNotesRemote.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4513381F27A8227F00AE5E78 /* InboxNotesRemote.swift */; };
428430
4513382227A8409000AE5E78 /* InboxNotesRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4513382127A8409000AE5E78 /* InboxNotesRemoteTests.swift */; };
@@ -1621,6 +1623,8 @@
16211623
450106842399A7CB00E24722 /* TaxClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxClass.swift; sourceTree = "<group>"; };
16221624
4501068E2399B19500E24722 /* TaxRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxRemote.swift; sourceTree = "<group>"; };
16231625
450106902399B2C800E24722 /* TaxClassListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxClassListMapper.swift; sourceTree = "<group>"; };
1626+
450BFA6A2D52777500C2D1D7 /* WordPressMediaMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMediaMapperTests.swift; sourceTree = "<group>"; };
1627+
450BFA6C2D52790200C2D1D7 /* media-library-with-empty-sizes.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "media-library-with-empty-sizes.json"; sourceTree = "<group>"; };
16241628
451274A525276C82009911FF /* product-variation.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-variation.json"; sourceTree = "<group>"; };
16251629
4513381F27A8227F00AE5E78 /* InboxNotesRemote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxNotesRemote.swift; sourceTree = "<group>"; };
16261630
4513382127A8409000AE5E78 /* InboxNotesRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InboxNotesRemoteTests.swift; sourceTree = "<group>"; };
@@ -3319,6 +3323,7 @@
33193323
93D8BBFE226BC1DA00AD2EB3 /* me-settings.json */,
33203324
EEDADD272B7C6A5E00F7302B /* media.json */,
33213325
02AF07EB27492FDD00B2D81E /* media-library.json */,
3326+
450BFA6C2D52790200C2D1D7 /* media-library-with-empty-sizes.json */,
33223327
EECB7EE7286555180028C888 /* media-update-product-id.json */,
33233328
B58D10C92114D22E00107ED4 /* new-order-note.json */,
33243329
022902D322E2436400059692 /* no_stats_permission_error.json */,
@@ -3908,6 +3913,7 @@
39083913
EEA1E2012AC18CD700A37ADD /* AIProductMapperTests.swift */,
39093914
EE078D922AD2F1E500C1199E /* JWTokenMapperTests.swift */,
39103915
EE065ACF2B8E56C2009848CB /* BlazeCampaignListItemsMapperTests.swift */,
3916+
450BFA6A2D52777500C2D1D7 /* WordPressMediaMapperTests.swift */,
39113917
DEDA8DA62B18399D0076BF0F /* WordPressThemeListMapperTests.swift */,
39123918
DEDA8DB82B187EC90076BF0F /* WordPressThemeMapperTests.swift */,
39133919
DEA493762B39987B00EED015 /* BlazeTargetOptionMapperTests.swift */,
@@ -4752,6 +4758,7 @@
47524758
EE065ACE2B8E51AD009848CB /* blaze-campaigns-list-success.json in Resources */,
47534759
45A4B85625D2E75300776FB4 /* shipping-label-address-validation-success.json in Resources */,
47544760
DEB3878F2C2D71A10025256E /* gla-campaign-list-without-data-envelope.json in Resources */,
4761+
450BFA6D2D52790E00C2D1D7 /* media-library-with-empty-sizes.json in Resources */,
47554762
457FC68C2382B2FD00B41B02 /* product-update.json in Resources */,
47564763
CE71E2292A4C35C900DB5376 /* reports-products.json in Resources */,
47574764
CE19CB11222486A600E8AF7A /* order-statuses.json in Resources */,
@@ -5629,6 +5636,7 @@
56295636
B5C6FCCD20A34B8300A4F8E4 /* OrderListMapperTests.swift in Sources */,
56305637
B518663520A0A2E800037A38 /* Constants.swift in Sources */,
56315638
EEA658422966C41A00112DF0 /* ProductIDMapperTests.swift in Sources */,
5639+
450BFA6B2D52777500C2D1D7 /* WordPressMediaMapperTests.swift in Sources */,
56325640
CE12AE9D29F2AD1C0056DD17 /* SubscriptionMapperTests.swift in Sources */,
56335641
D8FBFF1E22D51F39006E3336 /* OrderStatsMapperV4Tests.swift in Sources */,
56345642
02E7FFCB256218F600C53030 /* ShippingLabelRemoteTests.swift in Sources */,

Networking/Networking/Model/Media/WordPressMedia.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ public extension WordPressMedia {
7171
case fileName = "file"
7272
case sizes
7373
}
74+
75+
public init(from decoder: Decoder) throws {
76+
let container = try decoder.container(keyedBy: CodingKeys.self)
77+
width = try container.decodeIfPresent(Double.self, forKey: .width)
78+
height = try container.decodeIfPresent(Double.self, forKey: .height)
79+
fileName = try container.decodeIfPresent(String.self, forKey: .fileName)
80+
81+
do {
82+
sizes = try container.decodeIfPresent([String: MediaSizeDetails].self, forKey: .sizes)
83+
} catch {
84+
// Handle the case where sizes is an empty array. Ref: https://github.com/woocommerce/woocommerce-ios/issues/14516
85+
sizes = nil
86+
}
87+
}
7488
}
7589

7690
/// Details about a size of WordPress site media (e.g. `thumbnail`, `medium`, `2048x2048`).
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import XCTest
2+
@testable import Networking
3+
4+
final class WordPressMediaMapperTests: XCTestCase {
5+
6+
/// Tests that WordPressMediaList and consequently WordPressMedia is correctly mapped from a response where sizes is a dictionary.
7+
///
8+
/// - Throws: An error if the mapping fails.
9+
func test_it_maps_WordPressMediaList_correctly_with_sizes_as_dictionary() throws {
10+
// Given
11+
let data = try retrieveWordPressMediaResponseWithSizesAsDictionary()
12+
let mapper = WordPressMediaListMapper()
13+
14+
// When
15+
let mediaList = try mapper.map(response: data)
16+
17+
// Then
18+
XCTAssertEqual(mediaList.count, 3)
19+
let media = mediaList.first { $0.mediaID == 22 }
20+
XCTAssertNotNil(media)
21+
XCTAssertEqual(media?.details?.sizes?["medium"]?.width, 300)
22+
XCTAssertEqual(media?.details?.sizes?["medium"]?.height, 225)
23+
XCTAssertEqual(media?.details?.sizes?["large"]?.width, 1024)
24+
XCTAssertEqual(media?.details?.sizes?["large"]?.height, 768)
25+
}
26+
27+
/// Tests that WordPressMediaList and consequently WordPressMedia is correctly mapped from a response where sizes is an empty array.
28+
///
29+
/// - Throws: An error if the mapping fails.
30+
func test_it_maps_WordPressMediaList_correctly_with_sizes_as_empty_array() throws {
31+
// Given
32+
let data = try retrieveWordPressMediaResponseWithSizesAsEmptyArray()
33+
let mapper = WordPressMediaListMapper()
34+
35+
// When
36+
let mediaList = try mapper.map(response: data)
37+
38+
// Then
39+
XCTAssertEqual(mediaList.count, 2)
40+
let media = mediaList.first { $0.mediaID == 13 }
41+
XCTAssertNotNil(media)
42+
XCTAssertNil(media?.details?.sizes)
43+
}
44+
}
45+
46+
// MARK: - Test Helpers
47+
///
48+
private extension WordPressMediaMapperTests {
49+
func retrieveWordPressMediaResponseWithSizesAsDictionary() throws -> Data {
50+
guard let response = Loader.contentsOf("media-library") else {
51+
throw FileNotFoundError()
52+
}
53+
54+
return response
55+
}
56+
57+
func retrieveWordPressMediaResponseWithSizesAsEmptyArray() throws -> Data {
58+
guard let response = Loader.contentsOf("media-library-with-empty-sizes") else {
59+
throw FileNotFoundError()
60+
}
61+
62+
return response
63+
}
64+
65+
struct FileNotFoundError: Error {}
66+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
[
2+
{
3+
"slug" : "image-copy",
4+
"date_gmt" : "2025-02-04t16:08:31",
5+
"id" : 13,
6+
"media_details" : {
7+
"filesize" : 1343,
8+
"sizes" : [
9+
10+
],
11+
"image_meta" : {
12+
"caption" : "",
13+
"orientation" : "1",
14+
"aperture" : "0",
15+
"focal_length" : "0",
16+
"title" : "",
17+
"credit" : "",
18+
"camera" : "",
19+
"keywords" : [
20+
21+
],
22+
"created_timestamp" : "0",
23+
"shutter_speed" : "0",
24+
"copyright" : "",
25+
"iso" : "0"
26+
},
27+
"width" : 4,
28+
"height" : 2,
29+
"file" : "2025/02/image-copy.jpg"
30+
},
31+
"title" : {
32+
"rendered" : "image copy"
33+
},
34+
"alt_text" : "",
35+
"mime_type" : "image/jpeg",
36+
"source_url" : "https://example.com/wp-content/uploads/image-copy.jpeg"
37+
},
38+
{
39+
"slug" : "woocommerce-placeholder",
40+
"date_gmt" : "2025-02-04t16:04:33",
41+
"id" : 4,
42+
"media_details" : {
43+
"filesize" : 48149,
44+
"sizes" : {
45+
"medium" : {
46+
"filesize" : 12321,
47+
"mime_type" : "image/png",
48+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-300x300.jpeg",
49+
"file" : "woocommerce-placeholder-300x300.png",
50+
"width" : 300,
51+
"height" : 300
52+
},
53+
"woocommerce_single" : {
54+
"filesize" : 38159,
55+
"mime_type" : "image/png",
56+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-600x600.jpeg",
57+
"file" : "woocommerce-placeholder-600x600.png",
58+
"width" : 600,
59+
"height" : 600
60+
},
61+
"large" : {
62+
"filesize" : 90808,
63+
"mime_type" : "image/png",
64+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-1024x1024.jpeg",
65+
"file" : "woocommerce-placeholder-1024x1024.png",
66+
"width" : 1024,
67+
"height" : 1024
68+
},
69+
"thumbnail" : {
70+
"filesize" : 4209,
71+
"mime_type" : "image/png",
72+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-150x150.jpeg",
73+
"file" : "woocommerce-placeholder-150x150.png",
74+
"width" : 150,
75+
"height" : 150
76+
},
77+
"medium_large" : {
78+
"filesize" : 56643,
79+
"mime_type" : "image/png",
80+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-768x768.jpeg",
81+
"file" : "woocommerce-placeholder-768x768.png",
82+
"width" : 768,
83+
"height" : 768
84+
},
85+
"woocommerce_gallery_thumbnail" : {
86+
"filesize" : 2330,
87+
"mime_type" : "image/png",
88+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-100x100.jpeg",
89+
"file" : "woocommerce-placeholder-100x100.png",
90+
"width" : 100,
91+
"height" : 100
92+
},
93+
"woocommerce_thumbnail" : {
94+
"height" : 300,
95+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder-300x300.jpeg",
96+
"filesize" : 12321,
97+
"file" : "woocommerce-placeholder-300x300.png",
98+
"width" : 300,
99+
"uncropped" : false,
100+
"mime_type" : "image/png"
101+
},
102+
"full" : {
103+
"mime_type" : "image/png",
104+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder.jpeg",
105+
"file" : "woocommerce-placeholder.png",
106+
"width" : 1200,
107+
"height" : 1200
108+
}
109+
},
110+
"image_meta" : {
111+
"caption" : "",
112+
"orientation" : "0",
113+
"aperture" : "0",
114+
"focal_length" : "0",
115+
"title" : "",
116+
"credit" : "",
117+
"camera" : "",
118+
"keywords" : [
119+
120+
],
121+
"created_timestamp" : "0",
122+
"shutter_speed" : "0",
123+
"copyright" : "",
124+
"iso" : "0"
125+
},
126+
"width" : 1200,
127+
"height" : 1200,
128+
"file" : "woocommerce-placeholder.png"
129+
},
130+
"title" : {
131+
"rendered" : "woocommerce-placeholder"
132+
},
133+
"alt_text" : "",
134+
"mime_type" : "image/png",
135+
"source_url" : "https://example.com/wp-content/uploads/woocommerce-placeholder.jpeg"
136+
}
137+
]

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*** Use [*****] to indicate smoke tests of all critical flows should be run on the final IPA before release (e.g. major library or OS update).
33
21.7
44
-----
5+
- [**] Fixed an issue with the WordPress Media Library not loading due to a decoding error in media details sizes. [https://github.com/woocommerce/woocommerce-ios/pull/15056]
56
- [*] Orders: Improved accessibility UI for Tax Rates related views [https://github.com/woocommerce/woocommerce-ios/pull/15043]
67
- [*] Product Details: Display cover tag on the first product image [https://github.com/woocommerce/woocommerce-ios/pull/15041]
78
- [*] Payments: Update learn more links to open Stripe-specific docs when using that gateway [https://github.com/woocommerce/woocommerce-ios/pull/15035]

0 commit comments

Comments
 (0)