Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions WordPress/UITests/Tests/EditorGutenbergTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ class EditorGutenbergTests: XCTestCase {
.enterTextInTitle(text: postTitle)
.addParagraphBlock(withText: postContent)
.verifyContentStructure(blocks: 1, words: postContent.components(separatedBy: " ").count, characters: postContent.count)
.publish()
.viewPublishedPost(withTitle: postTitle)
.postAndViewEpilogue(action: .publish)
.verifyEpilogueDisplays(postTitle: postTitle, siteAddress: WPUITestCredentials.testWPcomPaidSite)
.tapDone()
}
Expand All @@ -48,8 +47,7 @@ class EditorGutenbergTests: XCTestCase {
.selectCategory(name: category)
.addTag(name: tag)
.closePostSettings()
.publish()
.viewPublishedPost(withTitle: postTitle)
.postAndViewEpilogue(action: .publish)
.verifyEpilogueDisplays(postTitle: postTitle, siteAddress: WPUITestCredentials.testWPcomPaidSite)
.tapDone()
}
Expand Down
10 changes: 6 additions & 4 deletions WordPress/UITests/Tests/PostTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ class PostTests: XCTestCase {
.updatePublishDateToFutureDate()
.closePublishDateSelector()
.closePostSettings()
.schedulePost()
.viewPublishedPost(withTitle: postTitle)
.verifyEpilogueDisplays(postTitle: postTitle, siteAddress: WPUITestCredentials.testWPcomSiteForScheduledPost)
.tapDone()
.post(action: .schedule)

try MySiteScreen()
.goToPostsScreen()
.showOnly(.scheduled)
.verifyPostExists(withTitle: postTitle)
}
}
117 changes: 58 additions & 59 deletions WordPress/UITestsFoundation/Screens/Editor/BlockEditorScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,80 +4,88 @@ import XCUITestHelpers

public class BlockEditorScreen: ScreenObject {

private let editorCloseButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"].buttons["Close"]
}

private let undoButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"].buttons["Undo"]
}

private let redoButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"].buttons["Redo"]
}

private let addBlockButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["add-block-button"]
}

private let moreButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["more_post_options"]
private let applyButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Apply"]
}

private let insertFromUrlButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Insert from URL"]
private let chooseFromDeviceButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Choose from device"]
}

private let applyButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Apply"]
private let closeButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Close"]
}

private let discardButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Discard"]
}

private let firstParagraphBlockGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["Paragraph Block. Row 1. Empty"]
private let dismissPopoverRegionGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["PopoverDismissRegion"]
}

private let postTitleViewGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["Post title. Empty"]
private let editorCloseButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"].buttons["Close"]
}

private let editorNavigationBarGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"]
}

private let closeButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Close"]
private let firstParagraphBlockGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["Paragraph Block. Row 1. Empty"]
}

private let dismissPopoverRegionGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["PopoverDismissRegion"]
private let fullScreenImageGetter: (XCUIApplication) -> XCUIElement = {
$0.images["Fullscreen view of image. Double tap to dismiss"]
}

private let insertFromUrlButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Insert from URL"]
}

private let keepEditingButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Keep Editing"]
}

private let moreButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["more_post_options"]
}

private let noticeViewButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["View"]
}

private let noticeViewTitleGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["notice_title_and_message"]
}

private let postSettingsButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Post Settings"]
}

private let switchToHTMLModeButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Switch to HTML Mode"]
private let postTitleViewGetter: (XCUIApplication) -> XCUIElement = {
$0.otherElements["Post title. Empty"]
}

private let chooseFromDeviceButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Choose from device"]
private let redoButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"].buttons["Redo"]
}

private let setRemindersButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Set reminders"]
}

private let fullScreenImageGetter: (XCUIApplication) -> XCUIElement = {
$0.images["Fullscreen view of image. Double tap to dismiss"]
private let switchToHTMLModeButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Switch to HTML Mode"]
}

private let undoButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.navigationBars["Gutenberg Editor Navigation Bar"].buttons["Undo"]
}

private let unsavedChangesLabelGetter: (XCUIApplication) -> XCUIElement = {
Expand All @@ -97,11 +105,13 @@ public class BlockEditorScreen: ScreenObject {
var insertFromUrlButton: XCUIElement { insertFromUrlButtonGetter(app) }
var keepEditingButton: XCUIElement { keepEditingButtonGetter(app) }
var moreButton: XCUIElement { moreButtonGetter(app) }
var noticeViewButton: XCUIElement { noticeViewButtonGetter(app) }
var noticeViewTitle: XCUIElement { noticeViewTitleGetter(app) }
var postSettingsButton: XCUIElement { postSettingsButtonGetter(app) }
var switchToHTMLModeButton: XCUIElement { switchToHTMLModeButtonGetter(app) }
var postTitleView: XCUIElement { postTitleViewGetter(app) }
var redoButton: XCUIElement { redoButtonGetter(app) }
var setRemindersButton: XCUIElement { setRemindersButtonGetter(app) }
var switchToHTMLModeButton: XCUIElement { switchToHTMLModeButtonGetter(app) }
var undoButton: XCUIElement { undoButtonGetter(app) }
var unsavedChangesLabel: XCUIElement { unsavedChangesLabelGetter(app) }

Expand Down Expand Up @@ -234,37 +244,29 @@ public class BlockEditorScreen: ScreenObject {
}
}

public func publish() throws -> EditorNoticeComponent {
return try post(action: "Publish")
public enum postAction: String {
case publish = "Publish"
case schedule = "Schedule"
}

public func schedulePost() throws -> EditorNoticeComponent {
return try post(action: "Schedule")
public func postAndViewEpilogue(action: postAction) throws -> EditorPublishEpilogueScreen {
try post(action: action)
waitAndTap(noticeViewButton)
return try EditorPublishEpilogueScreen()
}

private func post(action: String) throws -> EditorNoticeComponent {
let postButton = app.buttons[action]
let postNowButton = app.buttons["\(action) Now"]
public func post(action: postAction) throws {
let postButton = app.buttons[action.rawValue]
let postNowButton = app.buttons["\(action.rawValue) Now"]
var tries = 0
// This loop to check for Publish/Schedule Now Button is an attempt to confirm that the postButton.tap() call took effect.
// The tests would fail sometimes in the pipeline with no apparent reason.
repeat {
postButton.tap()
tries += 1
} while !postNowButton.waitForIsHittable(timeout: 3) && tries <= 3
try confirmPost(button: postNowButton)

let actionInNotice: String

if action == "Schedule" {
actionInNotice = "scheduled"
} else if action == "Publish" {
actionInNotice = "published"
} else {
throw NSError(domain: "InvalidAction", code: 0, userInfo: [NSLocalizedDescriptionKey: "Invalid action: \(action)"])
}

return try EditorNoticeComponent(withNotice: "Post \(actionInNotice)")
try confirmPost(button: postNowButton, action: action)
}

@discardableResult
Expand Down Expand Up @@ -398,13 +400,10 @@ public class BlockEditorScreen: ScreenObject {
return try PHPickerScreen()
}

private func confirmPost(button: XCUIElement) throws {
if FancyAlertComponent.isLoaded() {
try FancyAlertComponent().acceptAlert()
Comment on lines -402 to -403
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 don't know which FancyAlert we could expect here. I've run all the editor tests several times and haven't seen it. We are saving some time here but it doesn't impact the target issue as it comes before tapping the Schedule Now button.

} else {
button.tap()
dismissBloggingRemindersAlertIfNeeded()
}
private func confirmPost(button: XCUIElement, action: postAction) throws {
button.tap()
guard action == .publish else { return }
dismissBloggingRemindersAlertIfNeeded()
Comment on lines +405 to +406
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Blogging Reminder is only displayed when a post is published, so we can save the 3 seconds timeout from dismissBloggingRemindersAlertIfNeeded() when scheduling a post. ⏱️

}

public func dismissBloggingRemindersAlertIfNeeded() {
Expand Down
3 changes: 2 additions & 1 deletion WordPress/UITestsFoundation/Screens/MySiteScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ public class MySiteScreen: ScreenObject {
}

public func goToPostsScreen() throws -> PostsScreen {
goToMenu()
postsButton.tap()
return try PostsScreen()
}
Expand Down Expand Up @@ -219,7 +220,7 @@ public class MySiteScreen: ScreenObject {
@discardableResult
public func goToMenu() -> Self {
// On iPad, the menu items are already listed on screen, so we don't need to tap the menu button
guard XCUIDevice.isPhone else {
guard XCUIDevice.isPhone && !segmentedControlMenuButton.isSelected else {
return self
}

Expand Down
9 changes: 9 additions & 0 deletions WordPress/UITestsFoundation/Screens/PostsScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public class PostsScreen: ScreenObject {
public enum PostStatus {
case published
case drafts
case scheduled
}

private var currentlyFilteredPostStatus: PostStatus = .published
Expand Down Expand Up @@ -56,6 +57,8 @@ public class PostsScreen: ScreenObject {
publishedButton.tap()
case .drafts:
draftsButton.tap()
case .scheduled:
scheduledButton.tap()
}

currentlyFilteredPostStatus = status
Expand Down Expand Up @@ -89,6 +92,12 @@ public class PostsScreen: ScreenObject {
autosaveAlert.buttons.firstMatch.tap()
}
}

public func verifyPostExists(withTitle title: String) {
let expectedPost = app.cells.containing(.staticText, identifier: title).element

XCTAssertTrue(expectedPost.exists)
}
}

public struct EditorScreen {
Expand Down