Skip to content

Commit 213d3c4

Browse files
committed
Merge branch 'develop' into issue/2053-add-product-details-bottom-sheet
2 parents 3c36d06 + 5f38e3b commit 213d3c4

File tree

22 files changed

+799
-77
lines changed

22 files changed

+799
-77
lines changed

.circleci/config.yml

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ orbs:
44
# Using 1.0 of the Orbs means it will use the latest 1.0.x version from https://github.com/wordpress-mobile/circleci-orbs
55
ios: wordpress-mobile/[email protected]
66
git: wordpress-mobile/[email protected]
7+
slack: circleci/[email protected]
78

89
commands:
910
fix-circleci:
@@ -32,22 +33,80 @@ jobs:
3233
root: ./
3334
paths:
3435
- DerivedData/Build/Products
36+
- vendor/bundle
3537

3638
Unit Tests:
3739
executor:
3840
name: ios/default
3941
xcode-version: "11.2.1"
4042
steps:
43+
- git/shallow-checkout
4144
- ios/boot-simulator:
4245
xcode-version: "11.2.1"
4346
device: iPhone 11
4447
- attach_workspace:
4548
at: ./
49+
- run:
50+
name: Prepare Bundle
51+
command: bundle --path vendor/bundle
4652
- ios/wait-for-simulator
47-
- ios/xcodebuild:
48-
command: test-without-building
49-
arguments: -xctestrun DerivedData/Build/Products/WooCommerce_UnitTests_iphonesimulator13.2-x86_64.xctestrun -destination "platform=iOS Simulator,id=$SIMULATOR_UDID"
50-
- ios/save-xcodebuild-artifacts
53+
- run:
54+
name: Run Unit Tests
55+
command: >
56+
bundle exec fastlane test_without_building
57+
xctestrun:DerivedData/Build/Products/WooCommerce_UnitTests_iphonesimulator13.2-x86_64.xctestrun
58+
destination:"platform=iOS Simulator,id=$SIMULATOR_UDID" try_count:3
59+
- ios/save-xcodebuild-artifacts:
60+
result-bundle-path: build/results
61+
UI Tests:
62+
parameters:
63+
device:
64+
type: string
65+
post-to-slack:
66+
description: Post to Slack when tests fail. SLACK_WEBHOOK ENV variable must be set.
67+
type: boolean
68+
default: false
69+
executor:
70+
name: ios/default
71+
xcode-version: "11.2.1"
72+
steps:
73+
- git/shallow-checkout
74+
- ios/boot-simulator:
75+
xcode-version: "11.2.1"
76+
device: << parameters.device >>
77+
- attach_workspace:
78+
at: ./
79+
- run:
80+
name: Prepare Bundle
81+
command: bundle --path vendor/bundle
82+
- run:
83+
name: Run mocks
84+
command: ./WooCommerce/WooCommerceUITests/Mocks/scripts/start.sh 8282
85+
background: true
86+
- ios/wait-for-simulator
87+
- run:
88+
name: Run UI Tests
89+
command: >
90+
bundle exec fastlane test_without_building
91+
xctestrun:DerivedData/Build/Products/WooCommerce_UITests_iphonesimulator13.2-x86_64.xctestrun
92+
destination:"platform=iOS Simulator,id=$SIMULATOR_UDID" try_count:3
93+
- ios/save-xcodebuild-artifacts:
94+
result-bundle-path: build/results
95+
- when:
96+
condition: << parameters.post-to-slack >>
97+
steps:
98+
- run:
99+
name: Prepare Slack message
100+
when: always
101+
command: |
102+
# Get the name of the device that is running. Using "<< parameters.device >>" can cause slack formatting errors.
103+
DEVICE_NAME=$(xcrun simctl list -j | jq -r --arg UDID $SIMULATOR_UDID '.devices[] | .[] | select(.udid == "\($UDID)") | .name')
104+
echo "export SLACK_FAILURE_MESSAGE=':red_circle: WooCommerce iOS UI tests failed on ${DEVICE_NAME} in \`${CIRCLE_BRANCH}\` branch by ${CIRCLE_USERNAME}.\n\nPlease reach out in #platform9 if you think this failure is not caused by your changes, so we can investigate.'" >> $BASH_ENV
105+
- slack/status:
106+
fail_only: true
107+
include_job_number_field: false
108+
include_project_field: false
109+
failure_message: '${SLACK_FAILURE_MESSAGE}'
51110
Installable Build:
52111
executor:
53112
name: ios/default
@@ -105,6 +164,47 @@ workflows:
105164
- Build Tests
106165
- Unit Tests:
107166
requires: [ "Build Tests" ]
167+
# Always run UI tests on develop and release branches
168+
- UI Tests:
169+
name: UI Tests (iPhone 11)
170+
device: iPhone 11
171+
post-to-slack: true
172+
requires: [ "Build Tests" ]
173+
filters:
174+
branches:
175+
only:
176+
- develop
177+
- /^release.*/
178+
- UI Tests:
179+
name: UI Tests (iPad Air 3rd generation)
180+
device: iPad Air \\(3rd generation\\)
181+
post-to-slack: true
182+
requires: [ "Build Tests" ]
183+
filters:
184+
branches:
185+
only:
186+
- develop
187+
- /^release.*/
188+
#Optionally run UI tests on PRs
189+
Optional Tests:
190+
jobs:
191+
- Hold:
192+
type: approval
193+
filters:
194+
branches:
195+
ignore:
196+
- develop
197+
- /^release.*/
198+
- Build Tests:
199+
requires: [ "Hold" ]
200+
- UI Tests:
201+
name: Optional UI Tests (iPhone 11)
202+
device: iPhone 11
203+
requires: [ "Build Tests" ]
204+
- UI Tests:
205+
name: Optional UI Tests (iPad Air 3rd generation)
206+
device: iPad Air \\(3rd generation\\)
207+
requires: [ "Build Tests" ]
108208
Installable Build:
109209
jobs:
110210
- Hold:

Gemfile.lock

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ GEM
7373
cocoapods-try (1.1.0)
7474
colored (1.2)
7575
colored2 (3.1.2)
76+
colorize (0.8.1)
7677
commander-fastlane (4.4.6)
7778
highline (~> 1.7.2)
7879
concurrent-ruby (1.1.5)
@@ -135,6 +136,12 @@ GEM
135136
xcpretty-travis-formatter (>= 0.0.3)
136137
fastlane-plugin-appcenter (1.6.0)
137138
fastlane-plugin-sentry (1.6.0)
139+
fastlane-plugin-test_center (3.10.2)
140+
colorize
141+
json
142+
plist
143+
xcodeproj
144+
xctest_list (>= 1.1.8)
138145
ffi (1.12.2)
139146
fourflusher (2.3.1)
140147
fuzzy_match (2.0.4)
@@ -262,6 +269,7 @@ GEM
262269
rouge (~> 2.0.7)
263270
xcpretty-travis-formatter (1.0.0)
264271
xcpretty (~> 0.2, >= 0.0.7)
272+
xctest_list (1.1.8)
265273

266274
PLATFORMS
267275
ruby
@@ -272,6 +280,7 @@ DEPENDENCIES
272280
fastlane (~> 2)!
273281
fastlane-plugin-appcenter (= 1.6.0)
274282
fastlane-plugin-sentry
283+
fastlane-plugin-test_center
275284
fastlane-plugin-wpmreleasetoolkit!
276285
rake!
277286
rmagick (~> 3.2.0)

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@
6565
45ED4F10239E8A54004F1BE3 /* TaxClassListMapperTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45ED4F0F239E8A54004F1BE3 /* TaxClassListMapperTest.swift */; };
6666
45ED4F12239E8C57004F1BE3 /* taxes-classes.json in Resources */ = {isa = PBXBuildFile; fileRef = 45ED4F11239E8C57004F1BE3 /* taxes-classes.json */; };
6767
45ED4F14239E8F2E004F1BE3 /* TaxClassRemoteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45ED4F13239E8F2E004F1BE3 /* TaxClassRemoteTests.swift */; };
68+
5726F72E2460A2820031CAAC /* Copiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5726F72D2460A2820031CAAC /* Copiable.swift */; };
69+
5726F7312460A8510031CAAC /* ProductImage+Copiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5726F7302460A8510031CAAC /* ProductImage+Copiable.swift */; };
70+
5726F7342460A8F00031CAAC /* CopiableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5726F7332460A8F00031CAAC /* CopiableTests.swift */; };
6871
57BE08D82409B63800F6DCED /* reviews-missing-avatar-urls.json in Resources */ = {isa = PBXBuildFile; fileRef = 57BE08D72409B63700F6DCED /* reviews-missing-avatar-urls.json */; };
6972
6647C0161DAC6AB6570C53A7 /* Pods_Networking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3F25DC15EC1D7C631169CB5 /* Pods_Networking.framework */; };
7073
6856DE98F90AC6E4743D18CA /* XCTestCase+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6856D1228ADBC14D8202E49D /* XCTestCase+Wait.swift */; };
@@ -393,6 +396,9 @@
393396
45ED4F0F239E8A54004F1BE3 /* TaxClassListMapperTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxClassListMapperTest.swift; sourceTree = "<group>"; };
394397
45ED4F11239E8C57004F1BE3 /* taxes-classes.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "taxes-classes.json"; sourceTree = "<group>"; };
395398
45ED4F13239E8F2E004F1BE3 /* TaxClassRemoteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxClassRemoteTests.swift; sourceTree = "<group>"; };
399+
5726F72D2460A2820031CAAC /* Copiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Copiable.swift; sourceTree = "<group>"; };
400+
5726F7302460A8510031CAAC /* ProductImage+Copiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProductImage+Copiable.swift"; sourceTree = "<group>"; };
401+
5726F7332460A8F00031CAAC /* CopiableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopiableTests.swift; sourceTree = "<group>"; };
396402
573B448C242422DB00E71ADC /* orders-load-all-2.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "orders-load-all-2.json"; sourceTree = "<group>"; };
397403
57BE08D72409B63700F6DCED /* reviews-missing-avatar-urls.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "reviews-missing-avatar-urls.json"; sourceTree = "<group>"; };
398404
6856D1228ADBC14D8202E49D /* XCTestCase+Wait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Wait.swift"; sourceTree = "<group>"; };
@@ -713,6 +719,30 @@
713719
path = Refund;
714720
sourceTree = "<group>";
715721
};
722+
5726F72C2460A25F0031CAAC /* Copiable */ = {
723+
isa = PBXGroup;
724+
children = (
725+
5726F72D2460A2820031CAAC /* Copiable.swift */,
726+
);
727+
path = Copiable;
728+
sourceTree = "<group>";
729+
};
730+
5726F72F2460A83D0031CAAC /* Copiable */ = {
731+
isa = PBXGroup;
732+
children = (
733+
5726F7302460A8510031CAAC /* ProductImage+Copiable.swift */,
734+
);
735+
path = Copiable;
736+
sourceTree = "<group>";
737+
};
738+
5726F7322460A8E30031CAAC /* Copiable */ = {
739+
isa = PBXGroup;
740+
children = (
741+
5726F7332460A8F00031CAAC /* CopiableTests.swift */,
742+
);
743+
path = Copiable;
744+
sourceTree = "<group>";
745+
};
716746
6856DE4E23A475D8CEBD10C1 /* Testing */ = {
717747
isa = PBXGroup;
718748
children = (
@@ -852,6 +882,7 @@
852882
B557D9E5209753AA005962F4 /* Networking */ = {
853883
isa = PBXGroup;
854884
children = (
885+
5726F72C2460A25F0031CAAC /* Copiable */,
855886
B5A0369F214C0F4C00774E2C /* Internal */,
856887
B5BB1D0A20A204F400112D92 /* Extensions */,
857888
B567AF2720A0FA0A00AB6C62 /* Mapper */,
@@ -871,6 +902,7 @@
871902
B557D9F0209753AA005962F4 /* NetworkingTests */ = {
872903
isa = PBXGroup;
873904
children = (
905+
5726F7322460A8E30031CAAC /* Copiable */,
874906
B559EBA820A0B5B100836CD4 /* Responses */,
875907
B518663220A0A2E800037A38 /* Settings */,
876908
B5C6FCC620A32E3100A4F8E4 /* Extensions */,
@@ -939,6 +971,7 @@
939971
B557DA1B20979E6D005962F4 /* Model */ = {
940972
isa = PBXGroup;
941973
children = (
974+
5726F72F2460A83D0031CAAC /* Copiable */,
942975
B50A583A21AD872E00617455 /* Devices */,
943976
020D07B623D852AB00FD9580 /* Media */,
944977
CE6BFEE62236CF0D005C79FB /* Product */,
@@ -1585,6 +1618,7 @@
15851618
B556FD69211CE2EC00B5DAE7 /* NetworkError.swift in Sources */,
15861619
B557DA0D20975DB1005962F4 /* WordPressAPIVersion.swift in Sources */,
15871620
7412A8EC21B6E286005D182A /* ReportOrderTotalsMapper.swift in Sources */,
1621+
5726F72E2460A2820031CAAC /* Copiable.swift in Sources */,
15881622
74A1D26F21189EA100931DFA /* SiteVisitStatsRemote.swift in Sources */,
15891623
B557DA1D20979E7D005962F4 /* Order.swift in Sources */,
15901624
74159625224D4045003C21CF /* SiteSettingGroup.swift in Sources */,
@@ -1633,6 +1667,7 @@
16331667
026CF61A237D607A009563D4 /* ProductVariationAttribute.swift in Sources */,
16341668
748D424A210F92EA00CF7D1B /* OrderStatsItem.swift in Sources */,
16351669
D8FBFF1A22D4DF7A006E3336 /* OrderStatsV4.swift in Sources */,
1670+
5726F7312460A8510031CAAC /* ProductImage+Copiable.swift in Sources */,
16361671
74A1D26B21189B8100931DFA /* SiteVisitStatsItem.swift in Sources */,
16371672
B505F6EC20BEFDC200BB1B69 /* Loader.swift in Sources */,
16381673
74D3BD142114FE6900A6E85E /* MIContainer.swift in Sources */,
@@ -1695,6 +1730,7 @@
16951730
74AB0ACA21948CE4008220CD /* CommentResultMapperTests.swift in Sources */,
16961731
B524194921AC659500D6FC0A /* DevicesRemoteTests.swift in Sources */,
16971732
B505F6D320BEE3A500BB1B69 /* AccountMapperTests.swift in Sources */,
1733+
5726F7342460A8F00031CAAC /* CopiableTests.swift in Sources */,
16981734
26615479242DA54D00A31661 /* ProductCategoyListMapperTests.swift in Sources */,
16991735
B5C6FCC820A32E4800A4F8E4 /* DateFormatterWooTests.swift in Sources */,
17001736
74C8F06A20EEBC8C00B6EDC9 /* OrderMapperTests.swift in Sources */,
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
2+
import Foundation
3+
4+
/// A typealias for arguments of `copy()` methods signifying that the required property's value
5+
/// will be copied by default if no value is given.
6+
///
7+
/// For example:
8+
///
9+
/// ```
10+
/// struct Person {
11+
/// let id: Int
12+
/// let name: String
13+
///
14+
/// func copy(id: CopiableProp<Int> = .copy,
15+
/// name: CopiableProp<String> = .copy) -> Person {
16+
/// Person(id: id ?? self.id,
17+
/// name: name ?? self.name)
18+
/// }
19+
/// }
20+
///
21+
/// let luke = Person(id: 1, name: "Luke")
22+
///
23+
/// let leia = luke.copy(name: "Leia")
24+
/// ```
25+
///
26+
/// The variable `leia` will have the same `id` as `luke`:
27+
///
28+
/// ```
29+
/// { id: 1, name: "Leia" }
30+
/// ```
31+
///
32+
public typealias CopiableProp<Wrapped> = Optional<Wrapped>
33+
34+
/// A typealias for arguments of `copy()` methods signifying that the property is `Optional` and
35+
/// that the existing value will be copied by default if no value is given.
36+
///
37+
/// Using `NullableCopiableProp` allows us to set an `Optional` property to `nil` when copying.
38+
/// For example, if passing a variable as an argument, the property will be set to `nil` as
39+
/// expected:
40+
///
41+
/// ```
42+
/// struct Person {
43+
/// let id: Int
44+
/// let name: String
45+
/// let address: String?
46+
///
47+
/// func copy(id: CopiableProp<Int> = .copy,
48+
/// name: CopiableProp<String> = .copy,
49+
/// address: NullableCopiableProp<String> = .copy) -> Person {
50+
/// Person(id: id ?? self.id,
51+
/// name: name ?? self.name,
52+
/// address: address ?? self.address)
53+
/// }
54+
/// }
55+
///
56+
/// let luke = Person(id: 1, name: "Luke", address: "Jakku")
57+
///
58+
/// let address: String? = nil
59+
///
60+
/// let lukeWithNoAddress = luke.copy(address: address)
61+
/// ```
62+
///
63+
/// The variable `lukeWithNoAddress` will have a `nil` `address` as expected:
64+
///
65+
/// ```
66+
/// { id: 1, name: "Luke", address: nil }
67+
/// ```
68+
///
69+
/// In order to **directly** set a `NullableCopiableProp` to `nil`, the argument `.some(nil)`
70+
/// must be passed:
71+
///
72+
/// ```
73+
/// let lukeWithNoAddress = luke.copy(address: .some(nil))
74+
/// ```
75+
///
76+
/// We will still end up with the same result:
77+
///
78+
/// ```
79+
/// { id: 1, name: "Luke", address: nil }
80+
/// ```
81+
///
82+
public typealias NullableCopiableProp<Wrapped> = CopiableProp<Wrapped?>
83+
84+
// MARK: - Support for `.copy` alias
85+
86+
extension CopiableProp {
87+
/// Allow `CopiableProp<>` declarations to use a `.copy` alias as the default value instead of
88+
/// using `nil`.
89+
///
90+
/// For example, instead of declaring `copy()` arguments like this:
91+
///
92+
/// ```
93+
/// func copy(orderID: CopiableProp<Int> = nil)
94+
/// ```
95+
///
96+
/// We can declare them like this:
97+
///
98+
/// ```
99+
/// func copy(orderID: CopiableProp<Int> = .copy)
100+
/// ```
101+
///
102+
/// Using `.copy` makes it a bit more clearer what will happen if you don't declare or
103+
/// provide a different value.
104+
///
105+
public static var copy: Wrapped? {
106+
nil
107+
}
108+
}

0 commit comments

Comments
 (0)