Skip to content

Commit e4be046

Browse files
committed
Merge branch 'develop' into issue/2003-remove-showLoginMethods
2 parents 8923346 + 33d6f1b commit e4be046

File tree

8 files changed

+194
-28
lines changed

8 files changed

+194
-28
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)

WooCommerce/Classes/ViewRelated/Keyboard/KeyboardFrameObserver.swift

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import UIKit
22

33
/// Observes the keyboard frame and notifies its subscriber.
4-
struct KeyboardFrameObserver {
4+
final class KeyboardFrameObserver {
55
private let onKeyboardFrameUpdate: OnKeyboardFrameUpdate
66

77
/// Provides the last known keyboard state.
@@ -36,19 +36,16 @@ struct KeyboardFrameObserver {
3636
///
3737
/// - Parameter sendInitialEvent: If true, the subscriber will be immediately notified
3838
/// using the last known keyboard frame.
39-
mutating func startObservingKeyboardFrame(sendInitialEvent: Bool = false) {
40-
var observer = self
41-
notificationCenter.addObserver(forName: UIResponder.keyboardWillShowNotification,
42-
object: nil,
43-
queue: nil) { notification in
44-
observer.keyboardWillShow(notification)
45-
}
39+
func startObservingKeyboardFrame(sendInitialEvent: Bool = false) {
40+
notificationCenter.addObserver(self,
41+
selector: #selector(keyboardWillShow(_:)),
42+
name: UIResponder.keyboardWillShowNotification,
43+
object: nil)
4644

47-
notificationCenter.addObserver(forName: UIResponder.keyboardWillHideNotification,
48-
object: nil,
49-
queue: nil) { notification in
50-
observer.keyboardWillHide(notification)
51-
}
45+
notificationCenter.addObserver(self,
46+
selector: #selector(keyboardWillHide(_:)),
47+
name: UIResponder.keyboardWillHideNotification,
48+
object: nil)
5249

5350
if sendInitialEvent {
5451
keyboardFrame = keyboardStateProvider.state.frameEnd
@@ -57,14 +54,14 @@ struct KeyboardFrameObserver {
5754
}
5855

5956
private extension KeyboardFrameObserver {
60-
mutating func keyboardWillShow(_ notification: Foundation.Notification) {
57+
@objc func keyboardWillShow(_ notification: Foundation.Notification) {
6158
guard let keyboardFrame = keyboardRect(from: notification) else {
6259
return
6360
}
6461
self.keyboardFrame = keyboardFrame
6562
}
6663

67-
mutating func keyboardWillHide(_ notification: Foundation.Notification) {
64+
@objc func keyboardWillHide(_ notification: Foundation.Notification) {
6865
self.keyboardFrame = .zero
6966
}
7067
}

WooCommerce/Resources/AppStoreStrings.pot

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ msgctxt "app_store_promo_text"
4747
msgid "Run your store wherever you are. The WooCommerce app makes it easy to manage orders and inventory, track sales, and monitor store activity like new orders and reviews."
4848
msgstr ""
4949

50-
msgctxt "v4.1-whats-new"
50+
msgctxt "v4.2-whats-new"
5151
msgid ""
52-
"* We fixed an impolite bug that would sometimes crash the app while you were downloading Orders. Download away, we say!\n"
52+
"* Easier product description editing: Tap anywhere on a product cell to start editing. Need the keyboard? It pops up automatically. And while we were at it, we fixed a couple of bugs.\n"
53+
"* Up-to-the-minute order reporting: The Order list refreshes automatically every time you open the app or get a new order, and the Processing Orders list now shows upcoming future orders.\n"
5354
msgstr ""
5455

5556
#. translators: This is a promo message that will be attached on top of a screenshot in the App Store.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
* We fixed an impolite bug that would sometimes crash the app while you were downloading Orders. Download away, we say!
1+
* Easier product description editing: Tap anywhere on a product cell to start editing. Need the keyboard? It pops up automatically. And while we were at it, we fixed a couple of bugs.
2+
* Up-to-the-minute order reporting: The Order list refreshes automatically every time you open the app or get a new order, and the Processing Orders list now shows upcoming future orders.

WooCommerce/WooCommerceTests/ViewRelated/Keyboard/KeyboardFrameObserverTests.swift

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
1616

1717
var actualFrames = [CGRect]()
1818

19-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
19+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
2020
actualFrames.append(keyboardFrame)
2121
if actualFrames.count >= expectedFrames.count {
2222
XCTAssertEqual(actualFrames, expectedFrames)
@@ -47,7 +47,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
4747

4848
var actualFrames = [CGRect]()
4949

50-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
50+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
5151
actualFrames.append(keyboardFrame)
5252
if actualFrames.count >= expectedFrames.count {
5353
XCTAssertEqual(actualFrames, expectedFrames)
@@ -70,7 +70,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
7070

7171
let expectationForKeyboardFrame = expectation(description: "Wait for keyboard frame updates")
7272

73-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
73+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
7474
expectationForKeyboardFrame.fulfill()
7575
}
7676
keyboardFrameObserver.startObservingKeyboardFrame()
@@ -88,7 +88,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
8888

8989
let expectationForKeyboardFrame = expectation(description: "Wait for keyboard frame updates")
9090

91-
var keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
91+
let keyboardFrameObserver = KeyboardFrameObserver(notificationCenter: notificationCenter) { (keyboardFrame: CGRect) in
9292
expectationForKeyboardFrame.fulfill()
9393
}
9494
keyboardFrameObserver.startObservingKeyboardFrame()
@@ -101,6 +101,31 @@ final class KeyboardFrameObserverTests: XCTestCase {
101101
waitForExpectations(timeout: 0.1)
102102
}
103103

104+
func testItWillNotEmitNewEventsWhenItIsDeallocated() {
105+
// Arrange
106+
let notificationCenter = NotificationCenter()
107+
108+
var eventsLogged = 0
109+
var keyboardFrameObserver: KeyboardFrameObserver? = KeyboardFrameObserver(notificationCenter: notificationCenter) { _ in
110+
eventsLogged += 1
111+
}
112+
113+
keyboardFrameObserver?.startObservingKeyboardFrame()
114+
115+
// These should be logged
116+
notificationCenter.postKeyboardWillShowNotification(keyboardFrame: CGRect(x: 1, y: 1, width: 1, height: 1))
117+
notificationCenter.postKeyboardWillShowNotification(keyboardFrame: CGRect(x: 2, y: 2, width: 2, height: 2))
118+
119+
// Act
120+
keyboardFrameObserver = nil
121+
122+
// This should not be logged anymore
123+
notificationCenter.postKeyboardWillShowNotification(keyboardFrame: CGRect(x: 3, y: 3, width: 3, height: 3))
124+
125+
// Assert
126+
XCTAssertEqual(eventsLogged, 2)
127+
}
128+
104129
func testItCanSendInitialEvents() {
105130
// Arrange
106131
let expectedKeyboardState = KeyboardState(
@@ -110,7 +135,7 @@ final class KeyboardFrameObserverTests: XCTestCase {
110135
let keyboardStateProvider = MockKeyboardStateProvider(state: expectedKeyboardState)
111136

112137
var actualKeyboardFrame: CGRect = .zero
113-
var keyboardFrameObserver = KeyboardFrameObserver(keyboardStateProvider: keyboardStateProvider) { frame in
138+
let keyboardFrameObserver = KeyboardFrameObserver(keyboardStateProvider: keyboardStateProvider) { frame in
114139
actualKeyboardFrame = frame
115140
}
116141

fastlane/Fastfile

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ def get_required_env(key)
1313
ENV[key]
1414
end
1515

16-
before_all do
16+
before_all do |lane|
17+
# Skip these checks/steps for test lane (not needed for testing)
18+
next if lane == :test_without_building
19+
1720
# Check that the env files exist
1821
unless is_ci || File.file?(USER_ENV_FILE_PATH)
1922
UI.user_error!("~/.wcios-env.default not found: Please copy env/user.env-example to #{USER_ENV_FILE_PATH} and fill in the values")
@@ -646,4 +649,33 @@ end
646649

647650
def simulator_version()
648651
return '13.3'
652+
end
653+
654+
########################################################################
655+
# Test Lanes
656+
########################################################################
657+
#####################################################################################
658+
# test_without_building
659+
# -----------------------------------------------------------------------------------
660+
# This lane runs tests without building the app.
661+
# It requires a prebuilt xctestrun file and simulator destination where the tests will be run.
662+
# -----------------------------------------------------------------------------------
663+
# Usage:
664+
# bundle exec fastlane test_without_building [xctestrun:<Path to xctestrun file>] [destination:<Simulator>] [try_count:<Number of times to try tests>]
665+
#
666+
# Example:
667+
# bundle exec fastlane test_without_building xctestrun:WooCommerce_UITests_iphonesimulator13.2-x86_64.xctestrun destination:"platform=iOS Simulator,id=$SIMULATOR_UDID" try_count:3
668+
#####################################################################################
669+
desc "Run tests without building"
670+
lane :test_without_building do | options |
671+
multi_scan(
672+
workspace: "WooCommerce.xcworkspace",
673+
scheme: "WooCommerce",
674+
test_without_building: true,
675+
xctestrun: "#{options[:xctestrun]}",
676+
destination: options[:destination],
677+
try_count: options[:try_count],
678+
output_directory: "build/results",
679+
result_bundle: true
680+
)
649681
end

fastlane/Pluginfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ end
99
gem 'fastlane-plugin-wpmreleasetoolkit', git: 'https://github.com/wordpress-mobile/release-toolkit', tag: '0.9.2'
1010
gem 'fastlane-plugin-sentry'
1111
gem 'fastlane-plugin-appcenter', '1.6.0'
12+
gem 'fastlane-plugin-test_center'

0 commit comments

Comments
 (0)