Skip to content

Commit

Permalink
Merge pull request wordpress-mobile#21042 from wordpress-mobile/test/…
Browse files Browse the repository at this point in the history
…add-scheduled-post

[UI Tests] - Create Scheduled Post Test
  • Loading branch information
jostnes authored Jul 12, 2023
2 parents 84eeabc + e2740ab commit cd0ee94
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 63 deletions.
4 changes: 2 additions & 2 deletions WordPress/UITests/Flows/LoginFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ class LoginFlow {

// Login with WP site via Site Address.
@discardableResult
static func login(siteUrl: String, email: String, password: String) throws -> MySiteScreen {
static func login(siteUrl: String, email: String, password: String, selectedSiteTitle: String? = nil) throws -> MySiteScreen {
return try PrologueScreen()
.selectSiteAddress()
.proceedWithWP(siteUrl: siteUrl)
.proceedWith(email: email)
.proceedWithValidPassword()
.continueWithSelectedSite()
.continueWithSelectedSite(title: selectedSiteTitle)
}

// Login with self-hosted site via Site Address.
Expand Down
2 changes: 1 addition & 1 deletion WordPress/UITests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ The following flows are covered/planned to be covered by UI tests. Tests that ar
- [x] Add and Remove Featured Image
- [x] Add Gallery Block
- [x] Add Media Blocks (Image, Video and Audio)
- [ ] Create Scheduled Post
- [x] Create Scheduled Post
- [ ] Pages:
- [ ] Create Page from Layout
- [ ] Create Blank Page
Expand Down
44 changes: 22 additions & 22 deletions WordPress/UITests/Tests/EditorGutenbergTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,47 @@ class EditorGutenbergTests: XCTestCase {
)

try TabNavComponent()
.gotoBlockEditorScreen()
.goToBlockEditorScreen()
}

override func tearDownWithError() throws {
takeScreenshotOfFailedTest()
}

let title = "Rich post title"
let content = "Some text, and more text"
let postTitle = "Rich post title"
let postContent = "Some text, and more text"
let videoUrlPath = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
let audioUrlPath = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4"

func testTextPostPublish() throws {

try BlockEditorScreen()
.enterTextInTitle(text: title)
.addParagraphBlock(withText: content)
.verifyContentStructure(blocks: 1, words: content.components(separatedBy: " ").count, characters: content.count)
.enterTextInTitle(text: postTitle)
.addParagraphBlock(withText: postContent)
.verifyContentStructure(blocks: 1, words: postContent.components(separatedBy: " ").count, characters: postContent.count)
.publish()
.viewPublishedPost(withTitle: title)
.verifyEpilogueDisplays(postTitle: title, siteAddress: WPUITestCredentials.testWPcomSitePrimaryAddress)
.done()
.viewPublishedPost(withTitle: postTitle)
.verifyEpilogueDisplays(postTitle: postTitle, siteAddress: WPUITestCredentials.testWPcomSitePrimaryAddress)
.tapDone()
}

func testBasicPostPublishWithCategoryAndTag() throws {

let category = getCategory()
let tag = getTag()
try BlockEditorScreen()
.enterTextInTitle(text: title)
.addParagraphBlock(withText: content)
.enterTextInTitle(text: postTitle)
.addParagraphBlock(withText: postContent)
.addImage()
.verifyContentStructure(blocks: 2, words: content.components(separatedBy: " ").count, characters: content.count)
.verifyContentStructure(blocks: 2, words: postContent.components(separatedBy: " ").count, characters: postContent.count)
.openPostSettings()
.selectCategory(name: category)
.addTag(name: tag)
.closePostSettings()
try BlockEditorScreen().publish()
.viewPublishedPost(withTitle: title)
.verifyEpilogueDisplays(postTitle: title, siteAddress: WPUITestCredentials.testWPcomSitePrimaryAddress)
.done()
.publish()
.viewPublishedPost(withTitle: postTitle)
.verifyEpilogueDisplays(postTitle: postTitle, siteAddress: WPUITestCredentials.testWPcomSitePrimaryAddress)
.tapDone()
}

func testUndoRedo() throws {
Expand All @@ -74,9 +74,9 @@ class EditorGutenbergTests: XCTestCase {
func testAddRemoveFeaturedImage() throws {

try BlockEditorScreen()
.enterTextInTitle(text: title)
.addParagraphBlock(withText: content)
.verifyContentStructure(blocks: 1, words: content.components(separatedBy: " ").count, characters: content.count)
.enterTextInTitle(text: postTitle)
.addParagraphBlock(withText: postContent)
.verifyContentStructure(blocks: 1, words: postContent.components(separatedBy: " ").count, characters: postContent.count)
.openPostSettings()
.setFeaturedImage()
.verifyPostSettings(hasImage: true)
Expand All @@ -89,10 +89,10 @@ class EditorGutenbergTests: XCTestCase {

func testAddGalleryBlock() throws {
try BlockEditorScreen()
.enterTextInTitle(text: title)
.addParagraphBlock(withText: content)
.enterTextInTitle(text: postTitle)
.addParagraphBlock(withText: postContent)
.addImageGallery()
.verifyContentStructure(blocks: 2, words: content.components(separatedBy: " ").count, characters: content.count)
.verifyContentStructure(blocks: 2, words: postContent.components(separatedBy: " ").count, characters: postContent.count)
}

func testAddMediaBlocks() throws {
Expand Down
39 changes: 39 additions & 0 deletions WordPress/UITests/Tests/PostTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import UITestsFoundation
import XCTest

class PostTests: XCTestCase {
override func setUpWithError() throws {
try super.setUpWithError()
setUpTestSuite()

try LoginFlow.login(
siteUrl: WPUITestCredentials.testWPcomSiteAddress,
email: WPUITestCredentials.testWPcomUserEmail,
password: WPUITestCredentials.testWPcomPassword,
selectedSiteTitle: WPUITestCredentials.testWPcomSiteForScheduledPost
)

try TabNavComponent()
.goToBlockEditorScreen()
}

override func tearDownWithError() throws {
try super.tearDownWithError()
takeScreenshotOfFailedTest()
}

let postTitle = "Scheduled Post"

func testCreateScheduledPost() throws {
try BlockEditorScreen()
.enterTextInTitle(text: postTitle)
.openPostSettings()
.updatePublishDateToFutureDate()
.closePublishDateSelector()
.closePostSettings()
.schedulePost()
.viewPublishedPost(withTitle: postTitle)
.verifyEpilogueDisplays(postTitle: postTitle, siteAddress: WPUITestCredentials.testWPcomSiteForScheduledPost)
.tapDone()
}
}
1 change: 1 addition & 0 deletions WordPress/UITests/WPUITestCredentials.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct WPUITestCredentials {
static let testWPcomPassword: String = "pw"
static let testWPcomSiteAddress: String = "tricountyrealestate.wordpress.com"
static let testWPcomSitePrimaryAddress: String = "tricountyrealestate.wordpress.com"
static let testWPcomSiteForScheduledPost: String = "weekendbakesblog.wordpress.com"
static let selfHostedUsername: String = "e2eflowtestingmobile"
static let selfHostedPassword: String = "mocked_password"
static let selfHostedSiteAddress: String = "\(WireMock.URL().absoluteString)"
Expand Down
38 changes: 28 additions & 10 deletions WordPress/UITestsFoundation/Screens/Editor/BlockEditorScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,20 +184,39 @@ public class BlockEditorScreen: ScreenObject {
}

public func publish() throws -> EditorNoticeComponent {
let publishButton = app.buttons["Publish"]
let publishNowButton = app.buttons["Publish Now"]
return try post(action: "Publish")
}

public func schedulePost() throws -> EditorNoticeComponent {
return try post(action: "Schedule")
}

private func post(action: String) throws -> EditorNoticeComponent {
let postButton = app.buttons[action]
let postNowButton = app.buttons["\(action) Now"]
var tries = 0
// This loop to check for Publish Now Button is an attempt to confirm that the publishButton.tap() call took effect.
// 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 {
publishButton.tap()
postButton.tap()
tries += 1
} while !publishNowButton.waitForIsHittable(timeout: 3) && tries <= 3
try confirmPublish()
} while !postNowButton.waitForIsHittable(timeout: 3) && tries <= 3
try confirmPost(button: postNowButton)

let actionInNotice: String

return try EditorNoticeComponent(withNotice: "Post published", andAction: "View")
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)", andAction: "View")
}

@discardableResult
public func openPostSettings() throws -> EditorPostSettings {
moreButton.tap()
let postSettingsButton = app.buttons["Post Settings"] // Uses a localized string
Expand Down Expand Up @@ -314,12 +333,11 @@ public class BlockEditorScreen: ScreenObject {
.selectAlbum(atIndex: 0)
}

private func confirmPublish() throws {
private func confirmPost(button: XCUIElement) throws {
if FancyAlertComponent.isLoaded() {
try FancyAlertComponent().acceptAlert()
} else {
let publishNowButton = app.buttons["Publish Now"]
publishNowButton.tap()
button.tap()
dismissBloggingRemindersAlertIfNeeded()
}
}
Expand Down
84 changes: 73 additions & 11 deletions WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift
Original file line number Diff line number Diff line change
@@ -1,20 +1,62 @@
import Nimble
import ScreenObject
import XCTest

public class EditorPostSettings: ScreenObject {

// expectedElement comes from the superclass and gets the first expectedElementGetters result
var settingsTable: XCUIElement { expectedElement }
let settingsTableGetter: (XCUIApplication) -> XCUIElement = {
$0.tables["SettingsTable"]
}

let categoriesSectionGetter: (XCUIApplication) -> XCUIElement = {
$0.cells["Categories"]
}

let tagsSectionGetter: (XCUIApplication) -> XCUIElement = {
$0.cells["Tags"]
}

let featuredImageButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.cells["SetFeaturedImage"]
}

let currentFeaturedImageGetter: (XCUIApplication) -> XCUIElement = {
$0.cells["CurrentFeaturedImage"]
}

let publishDateButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.staticTexts["Publish Date"]
}

let dateSelectorGetter: (XCUIApplication) -> XCUIElement = {
$0.staticTexts["Immediately"]
}

var categoriesSection: XCUIElement { settingsTable.cells["Categories"] }
var tagsSection: XCUIElement { settingsTable.cells["Tags"] }
var featuredImageButton: XCUIElement { settingsTable.cells["SetFeaturedImage"] }
var currentFeaturedImage: XCUIElement { settingsTable.cells["CurrentFeaturedImage"] }
let nextMonthButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Next Month"]
}

let firstCalendarDayLabelGetter: (XCUIApplication) -> XCUIElement = {
$0.staticTexts["1"]
}

init(app: XCUIApplication = XCUIApplication()) throws {
let doneButtonGetter: (XCUIApplication) -> XCUIElement = {
$0.buttons["Done"]
}

var settingsTable: XCUIElement { settingsTableGetter(app) }
var categoriesSection: XCUIElement { categoriesSectionGetter(app) }
var tagsSection: XCUIElement { tagsSectionGetter(app) }
var featuredImageButton: XCUIElement { featuredImageButtonGetter(app) }
var currentFeaturedImage: XCUIElement { currentFeaturedImageGetter(app) }
var publishDateButton: XCUIElement { publishDateButtonGetter(app) }
var dateSelector: XCUIElement { dateSelectorGetter(app) }
var nextMonthButton: XCUIElement { nextMonthButtonGetter(app) }
var firstCalendarDayLabel: XCUIElement { firstCalendarDayLabelGetter(app) }
var doneButton: XCUIElement { doneButtonGetter(app) }

public init(app: XCUIApplication = XCUIApplication()) throws {
try super.init(
expectedElementGetters: [ { $0.tables["SettingsTable"] } ],
expectedElementGetters: [ settingsTableGetter ],
app: app
)
}
Expand Down Expand Up @@ -77,12 +119,32 @@ public class EditorPostSettings: ScreenObject {
return try EditorPostSettings()
}

/// - Note: Returns `Void` because the return screen depends on which editor the user is in.
public func closePostSettings() {
@discardableResult
public func closePostSettings() throws -> BlockEditorScreen {
navigateBack()

return try BlockEditorScreen()
}

public static func isLoaded() -> Bool {
return (try? EditorPostSettings().isLoaded) ?? false
}

@discardableResult
public func updatePublishDateToFutureDate() -> Self {
publishDateButton.tap()
dateSelector.tap()

// Selects the first day of the next month
nextMonthButton.tap()
firstCalendarDayLabel.tap()

doneButton.tap()
return self
}

public func closePublishDateSelector() -> Self {
navigateBack()
return self
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class EditorPublishEpilogueScreen: ScreenObject {
}

/// - Note: Returns `Void` since the return screen depends on which screen we started from.
public func done() {
public func tapDone() {
doneButton.tap()
}

Expand Down
7 changes: 1 addition & 6 deletions WordPress/UITestsFoundation/Screens/MySiteScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,7 @@ public class MySiteScreen: ScreenObject {
return try JetpackBackupScreen()
}

public func gotoPostsScreen() throws -> PostsScreen {
// A hack for iPad, because sometimes tapping "posts" doesn't load it the first time
if XCUIDevice.isPad {
mediaButton.tap()
}

public func goToPostsScreen() throws -> PostsScreen {
postsButtonGetter(app).tap()
return try PostsScreen()
}
Expand Down
Loading

0 comments on commit cd0ee94

Please sign in to comment.