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
Feature/alert controller assertion #20
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going to wait on reviewing this further until you've investigated the host application / UIWindow stuff we just discussed.
@nhgrif I've done some testing with attempting to successfully present a view controller without using a host application target. I've tried a random assortment of things, but I haven't had any luck so far. If we simply create a
From this warning, it's clear that we at least need to have a
This is a pretty vague error message, but my guess is that the window cannot become a key window without an application. However, without a host application target,
Any attempt to initialize a
Adding the code below to the test target in an attempt to designate a import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UIViewController()
window?.makeKeyAndVisible()
return true
}
} Got any other ideas for me to test out? |
4c3721f
to
89bbc12
Compare
c118948
to
1f7a438
Compare
@nhgrif I've removed the hosted tests target. Setting the view controller as the root view controller of the window doesn't seem to add the view controller's view to the window unless the window is the key window (and it can't be the key window without a host application). However, you can simply add the view controller's view as a subview to the window directly. As long as the view controller's view is a subview of the window, it can successfully present another view controller. So, that's what I did for the alert controller assertion tests. |
|
||
// MARK: Action Comparison | ||
|
||
fileprivate func matchesActualAction(_ action: UIAlertAction) -> Bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we just implement a ==
function for UIAlertAction
(and make it Equatable
)? If we did that, we could just use XCTAssertEqual
on them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, Equatable
defines an interface for equating two instances of the same type. In this case, the two things we are comparing would be ExpectedAlertAction
and UIAlertAction
. I suppose I could implement == (lhs: ExpectedAlertAction, rhs: UIAlertAction) -> Bool
for them, but since it's not actually conforming to Equatable
, I think I'd also have to implement != (lhs: ExpectedAlertAction, rhs: UIAlertAction) -> Bool
, and I think you'd have to implement the operators with the arguments in the reverse order as well. I think Equatable
just gives you all that via protocol extensions.
What are your thoughts? In the context where I'm currently using this method, it wouldn't benefit me to be able to use XCTAssertEqual
on them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha. This makes sense.
|
||
class QuotedStringTests: MTKBaseTestCase { | ||
|
||
func testQuotedString() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worthwhile to throw in a test for something that looks like this: quotedString("\"I've got quotes in me!\"")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I think so. Here's a question for you though. What would you expect the output of that to be? Should it simply add quotes around it again even if it already has quotes, or should it detect that it has quotes and not modify the original string? I'm leaning towards adding the extra quotes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it should add the extra quotes indiscriminately. It should only not add quotes in the case of nil
(which I believe is what I saw as the current behavior).
if descriptionsForUnexpectedFailures.isEmpty { | ||
expectingFailure = nil | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change primarily to allow multiple failures to be tested at once? Original implementation would only allow for a single failure at a time, correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's been a while since I made this change, so I might need to look over it again to verify, but if I recall correctly, this change makes it more obvious what was different about the actual failures in comparison with what we were expecting. I think I was having a test fail and I was having trouble figuring out what wasn't correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, that makes sense.
/// - line: The line number to report the failure for. The default value will report the line number of the calling site. | ||
public func MTKAssertAlertIsPresented(by presenter: UIViewController, style: UIAlertControllerStyle, title: String?, message: String?, actions: [ExpectedAlertAction], _ failureMessage: String? = nil, file: StaticString = #file, line: UInt = #line) { | ||
|
||
guard let alert = presenter.presentedViewController as? UIAlertController else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I can't remember how this presentedViewController
property works in the case of trying to call present
multiple times on a view control. Is that even possible or will it cause other problems?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A view controller can only present one view controller at a time. If you try to present another view controller while already presenting, it will fail and a warning will be logged to the console.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved as soon as all the automation completes.
@nhgrif This adds an assertion for testing that a view controller presented a UIAlertController with a particular style, title, message, and actions. Just so you're aware, in order to test this assertion, I had to be able to successfully present an alert which isn't possible without a window. So, I added a new test target that actually runs an empty UIKit app so I have a window to add my presenter view controller to for the tests.