Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UI tests to check the ability to scroll reader content and interact with the items #17536

Merged
merged 3 commits into from
Nov 26, 2021

Conversation

tiagomar
Copy link
Contributor

One of the identified critical flows to be automated was to open the Reader section, scroll content, open and close selections. This PR adds tests to cover the scenario.

To test:
ReaderTests must pass on CI.

Regression Notes

  1. Potential unintended areas of impact
    None. The changes would only impact ReaderTests.

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    N/A

  3. What automated tests I added (or what prevented me from doing so)
    N/A

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding unit tests for my changes. N/A
  • I have considered adding accessibility improvements for my changes. N/A
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary. N/A

@tiagomar tiagomar added the Testing Unit and UI Tests and Tooling label Nov 23, 2021
@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented Nov 23, 2021

You can trigger an installable build for these changes by visiting CircleCI here.

@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented Nov 23, 2021

You can trigger optional UI/connected tests for these changes by visiting CircleCI here.

@tiagomar tiagomar marked this pull request as ready for review November 23, 2021 19:24
Copy link
Contributor

@mokagio mokagio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is happy, and the tests passed locally, too 🎉

I left a few questions and suggestions. Once those are addressed, this will be ready to merge as far as I'm concerned.

@@ -20,6 +20,50 @@ public class ReaderScreen: ScreenObject {
)
}

public func openTheLastPostInApp() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Function names don't usually have articles in them. I don't see it spelled out clearly in the Swift API Guidelines and, thinking about it, I never really read this anywhere, but, based on all the code I've read over time, I think my assertion is accurate.

Suggested change
public func openTheLastPostInApp() {
public func openLastPostInApp() {

Also, I think it's safe to omit "in app" from the name. I'm guessing you did it to differentiate it from the method below that uses Safari. But, IMHO, if nothing else is specified it's safe to assume the action will occur in the app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the idea was really to differentiate it. I was actually a bit uncomfortable with "InApp" because the "InSafari" is somewhat still in app. =P

I'll get rid of the articles. =)


public func getTheLastPost() -> XCUIElement {
let postPosition = app.cells.count - 1
let post = app.cells.element(boundBy: postPosition)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, did you try the lastMatch helper here? It should return the same value.

var lastMatch: XCUIElement? {
return self.allElementsBoundByIndex.last
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tried it, probably because I started writing a more generic function to get the Nth post but then I realized I was doing premature optimization and also affecting the test readability. I'll use lastMatch. =)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, no stress. I was just curious.

There are good utilities in our XCUITestHelpers library, but one needs to know about them first, and we don't have an easy way to discover them. I guess it's just like with any other library: We get familiar with them by using them and we can all help each other out by sharing suggestions 😄

By the way: +1 for avoiding premature optimization. At the same time, if you stumble upon something that's a bit over-engineered for the current use case but looks general and something that could be useful in other tests feel free to implement it that way and extracting it into XCUITestHelpers as a followup 👍

while !element.waitForIsHittable(timeout: 3) && loopCount < 10 {
loopCount += 1
app.swipeUp(velocity: .fast)
print(loopCount)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a debug statement. Did you intend to leave it in here? If not:

Suggested change
print(loopCount)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦 Yeah, don't tell my mother.

dismissButton.tap()
} else if backButton.isHittable {
backButton.tap()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen in the tests if neither is hittable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dismissPost() is called only in tearDownWithError(). None of them being hittable will only happen if the tests fail prematurely even before opening the post and tearDownWithError() would continue its flow normally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

readerScreen.dismissPost()
}
try LoginFlow.logoutIfNeeded()
try super.tearDownWithError()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be necessary to call super here. Did you add this because of some error in the tests?

Copy link
Contributor Author

@tiagomar tiagomar Nov 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I have just followed what all the other tests were doing. I did try removing the super now but it went into a recursive call loop.

It runs just fine when removing the whole line but I would be more comfortable removing it if I knew why it was added in first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ouch! My suggestions was not clear, sorry 😳

"to call super" should have been "to call super.tearDownWithError() or "to call the super implementation".

If you updated to

-         try super.tearDownWithError()
+        try tearDownWithError()

it will indeed got into an infinite loop. ♻️

No, I have just followed what all the other tests were doing.

Fair enough. Those methods are (should be?) empty in XCTestCase so it doesn't hurt to call them. It simply adds unnecessary code to the test.

Feel free to ignore this. I plan to audit the test suite for this kind of stuff during my HACK week. 👍 #17569

WordPress/UITestsFoundation/Screens/ReaderScreen.swift Outdated Show resolved Hide resolved
return post
}

private func scrollDownUntilElementIsHittable(element: XCUIElement) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice method. Probably better than the scrollIntoView(within:, threshold:) we already have, because it doesn't rely on already knowing the scrollable container element.

I might steal it in the future 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume (I didn't test this) that this method is designed to scroll and wait for hittability of the last element only, because swiping up with fast velocity will probably will make it not suitable for the ones in the middle; and because it's called bygetLastPost().

If this is so, what do you think of renaming the method to reflect this?

@tiagomar tiagomar requested a review from mokagio November 25, 2021 17:11
Copy link
Contributor

@mokagio mokagio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for following up @tiagomar. :shipit:

Copy link
Contributor

@pachlava pachlava left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started from executing the tests on iPhone 12, and they passed. Nice job @tiagomar, the code looks solid to me 👍.

I left some notes, but none of them are blockers. Started review earlier today, but actually finished after Gio already approved the PR. Two approvals are better than one 😄

return post
}

private func scrollDownUntilElementIsHittable(element: XCUIElement) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume (I didn't test this) that this method is designed to scroll and wait for hittability of the last element only, because swiping up with fast velocity will probably will make it not suitable for the ones in the middle; and because it's called bygetLastPost().

If this is so, what do you think of renaming the method to reflect this?


override func tearDownWithError() throws {
takeScreenshotOfFailedTest()
if readerScreen != nil && !TabNavComponent.isVisible() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thinking aloud: as long as dismissPost() is used only here, it's fine to have this 'fuse' here, but once it will be used in the other places too (like inside the tests), I think this check can be moved to the dismissPost() method itself.

Copy link
Contributor Author

@tiagomar tiagomar Nov 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is so, what do you think of renaming the method to reflect this?

The idea was to have it more generic but you are right about the .fast. It wouldn't make much difference in this case though, because the posts are mocked and we have only 3 of them.

Comment on lines 57 to 61
if dismissButton.isHittable {
dismissButton.tap()
} else if backButton.isHittable {
backButton.tap()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the method assumes that the reader post will be either opened in a usual way (and then Back button should be used), or that it will be opened via More>Visit from reader list view. But there's also a third option: if it's opened in Safari from the post view (by clicking the globe button). In that case, it firstly needed to tap Dismiss and then Back. I assume that changing else if to just if would allow to also support this scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

@tiagomar tiagomar merged commit 8ceb016 into develop Nov 26, 2021
@tiagomar tiagomar deleted the reader-ui-tests-clean branch November 26, 2021 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Testing Unit and UI Tests and Tooling
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants