Closed davidrothera closed 8 years ago
+1 I just upgraded snapshot and I'm noticing the same thing. I have a Cordova app which has a toolbar along the bottom and the app recognizes the "snapshot swipe" as a press & hold on the bottom right button and it pops up the Safari "open in new tab" interface buttons.
+1 I can't use snapshot to do a screenshot because it will always tap on the settings of my app when snapshot is run. Update: I fixed this by disabling (self.tabbarItem.enabled = NO) the last UITTabbarItem but that will make that item greyed out.
I'm really sorry about this, I couldn't find a better solution. Check out this for more information about why. Also, please duplicate the radar and let me know if you have an idea on how to implement this the right way.
One (probably bad) solution could be to send cmd + s to the simulator and collect the shots from the desktop by the time stamp?
@plaetzchen I tried that, it's only possible using Apple Script, I don't think we should go that road.
It didn't really work
I agree that using AppleScript is the worst solution. Is there any official documentation how one uses the tap methods you use? Maybe the upper right corner would lead to less problems.
@KrauseFx would it at least be possible to retrieve the screenshot from before the event was synthesized, instead of after? that way we don't have a weird mid-transition screenshot, and then we just have to write code to restore the state we need to restore.
Additional documentation on the "swipe" being done in func snapshot
would be handy as well. Then we could customize where the action is being done so it doesn't interfere with our interface. I tried playing around with different numbers, but it either doesn't make too much of a difference or it causes the screenshot to not be found at the end of snapshot
32.1 is a magic number that snapshot looks for. You'd need to inject that dependency if you want to workaround that.
I suspected that might be the case. Maybe we can have an option in the snapfile for magic swipe number
so those of us who need to can override that. For example 0.1111, 0
and 0.1, 0
seem to not hit anything in my app, so I could do 0.111 as my magic number to look for.
Edit:
Working to keep 32.1 in my code, I've found 32.1, 0
and 32.11, 0
in SnapshotHelper.swift
don't trigger the bottom right toolbar button in my app but still generate a screenshot. I'm not sure where the swipe is happening haha, but its not hitting any of the buttons in the corners of my app :)
@swizzlr
@KrauseFx would it at least be possible to retrieve the screenshot from before the event was synthesized, instead of after? that way we don't have a weird mid-transition screenshot, and then we just have to write code to restore the state we need to restore.
interesting, that sounds like a good idea
@zineer solution works for me (it doesn't tap on the last item of the UITabBar), but I don't get the right screenshots.
Maybe there could be a way to get all the screenshots on a first pass and then we can select the ones we want... snapshot([1, 2, 6, 7, 9, 14]). Obviously not the best solution, but would help for the time being.
Same problem here... I end up disabling the last item...
self.tabBar.items.lastObject.enabled = NO
is a working solution for now!
Disabling the last tab bar item works, but it also causes it to be greyed out in the screenshots.
I've found another tricky workaround: add a 1x1 sized view to bottom right corner of the screen:
if let rootView = window?.rootViewController?.view {
let s = rootView.frame.size
let view = UIView(frame: CGRectMake(s.width - 1, s.height - 1, 1, 1))
//view.backgroundColor = UIColor.redColor()
rootView.addSubview(view)
}
@safx that's gross but that's for that!-Working for now :game_die:
@safx This is a really good solution. I use this code in my UITabbarController subclass's viewDidLoad :
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"-ui_testing"]) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame)-1, CGRectGetHeight(self.view.frame)-1, 1, 1)];
[view setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:view];
}
@plaetzchen Thanks for the tip. To make it a bit easier to reuse, I put this in my AppDelegate:
- (void)addSnapshotSwipeGuardView {
#ifdef DEBUG
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"-ui_testing"]) {
UIView *swipeBlockingView = [UIView new];
[self.window addSubview:swipeBlockingView];
// PureLayout code to make building constraints easier. Replace this with normal NSLayoutConstraint code if you don't already use PureLayout in your project.
[swipeBlockingView autoPinEdgeToSuperviewEdge:ALEdgeRight];
[swipeBlockingView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[swipeBlockingView autoSetDimensionsToSize:CGSizeMake(1, 1)];
}
#endif
}
Then I just call addSnapshotSwipeGuardView
in application:didFinishLaunchingWithOptions:
. While I generally try to keep my AppDelegates clean, putting it here ensures that no views will ever be messed with by snapshot, regardless of the type of view or the view controller they're in (I was having issues with UITextViews getting their text highlighted by snapshot).
@EricKuck You are totally right this seems like a better solution but since I already use a subclass of UITabbarController it was the obvious choice for me but AppDelegate is a good place as well.
BTW: Did someone already write an article called "Massive App Delegate" on Medium ;)
I hade the same issue, I changed the sign on the Y coordinate here:
let start = view.coordinateWithNormalizedOffset(CGVectorMake(32.10, -30000))
let finish = view.coordinateWithNormalizedOffset(CGVectorMake(31, -30000))
Ugly, but it works :grimacing:
:+1:
Sadly, changing the sign make a tap on the top bar right button item.
Anything that doesn't involve intercepting the touch is just going to change what the problem is, not fix it. Every other solution just makes the gesture happen somewhere else so that it avoids one specific view, but touches another. The cleanest solution is going to be what I posted above until Apple creates a way to take screenshots without gestures.
Argh, I would really love to use snapshot so much. I really like it. However right now sadly I can't. The 'snapshot swipe' is affecting my UI. I've tried giving the snapshot
function extra parameters so I can change the direction and position of the 'snapshot swipe' for a given screen, but on some views it will always bring me into a state I don't want to be in.
I duplicated the radar for now.
@KrauseFx Do you think it will be possible to combine a screenshot feature from within the App(http://stackoverflow.com/a/29702270)? This of course would then have to be activated somehow from the screenshot test suite.
I really love the work you've done with Fastlane. Thank you for all your hard work!
I tried the workaround from @EricKuck and @andreamazz but didn't work for me. Someone has another idea?
I think ultimately unless someone finds an awesome undocumented method to trigger a screenshot without actually interacting with the app we are going to have to wait and see if Apple ever responds to the Radar :-1:
How about using the screenshots Xcode already makes while running UI Tests? (In Xcode 7.1 right click on test and select "Jump to report"). The eye icon displays the screenshot made by xcode at that point.
@mihahribar If I understand this correctly, that is exactly what snapshot does. The gesture is used to "remember" the timestamp and later map the remembered timestamps to the existing screenshots and copy the ones which correlate to the timestamps
:+1:
In case anyone of you is using Swift
, the "translated" version of this answer works for me:
class AppDelegate: UIResponder, UIApplicationDelegate {
//...
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
#if DEBUG
addSnapshotSwipeGuardView()
#endif
return true
}
//...
private func addSnapshotSwipeGuardView() {
#if DEBUG
if NSProcessInfo.processInfo().arguments.contains("-ui_testing") {
let swipeBlockView = UIView()
swipeBlockView.translatesAutoresizingMaskIntoConstraints = false
window?.rootViewController?.view.addSubview(swipeBlockView)
let horizontalConstraint = NSLayoutConstraint(item: swipeBlockView, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: window?.rootViewController?.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0)
window?.rootViewController?.view.addConstraint(horizontalConstraint)
let verticalConstraint = NSLayoutConstraint(item: swipeBlockView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: window?.rootViewController?.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
window?.rootViewController?.view.addConstraint(verticalConstraint)
let widthConstraint = NSLayoutConstraint(item: swipeBlockView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 1)
window?.rootViewController?.view.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: swipeBlockView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 1)
window?.rootViewController?.view.addConstraint(heightConstraint)
}
#endif
}
}
Don't forget to set the DEBUG
flag!
This is what I ended up doing. No changes to test target necessary: http://codehardstare.swizzlr.co/post/132335036254/a-new-approach-to-automating-screenshots
I haven't got anywhere with this - but thought I'd post something to see if anyone can take it further.
XCUIElement has a private method
_dispatchEvent:block: of encoding 'v32@0:8@16@?24'
I have tried sending events to that, and it seems to require that events
1) implement copyWithZone: 2) implement utf8String
Which my events don't. Perhaps someone else can make something useful of this.
I just pushed a new release https://github.com/fastlane/snapshot/releases/tag/1.2.0 Please update to the latest version, make sure to read the release notes and let me know if it works for you :+1:
This issue was migrated to https://github.com/fastlane/fastlane/issues/2597. Please post all further comments there.
fastlane
is now a mono repo, you can read more about the change in our blog post. All tools are now available in the fastlane main repo :rocket:
When using the snapshot helper on an application that has a tabBar on it the lower right object is clicked erroneously.
I have created a simple example application showing this, https://github.com/davidrothera/snapshot_test run snapshot on that application and you will see it clicks into the second view controller.