I wish to put a wait until the iPad screen is done rotating and want to have both rotate and wait in the same function. If I don't add few seconds of wait, then the app doesn't behave as expected. Below is the function:
LandScapeRight = function()
{
return UIATarget.localTarget().setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT);
}
Please suggest.
You want to use the delay() method on UIATarget. The docs for the class are here
The quick and dirty way to do the delay you want is like so:
LandScapeRight = function()
{
var target = UIATarget.localTarget();
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT);
target.delay(1); // Delay is in seconds, can be a fraction
}
Check this two method
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
Related
I'm have just starting using XCTest for UI testing.
While running my tests, execution takes forever.
I get following output:
Wait for app to idle - waits 120 seconds to fail
App animations complete notification not received, will attempt to continue.
I have looked all over and found zero answer on how to either change the timeout or how to manipulate the app to move on.
There are no animations running at all in the app. The screen is fully loaded. My developers also have zero answers as well and I have tried disabling animations which fails the tests outright.
Any ideas on how I can address this?
func testHomeScreen() {
logIn()
let home = app.navigationBars["HOME"].staticTexts["HOME"]
waitForElementToAppear(element: home)
XCTAssert(home.exists)
let myFriendsButton = app.buttons["My Friends"]
XCTAssert(myFriendsButton.exists)
let collectionViewsQuery = app.collectionViews
collectionViewsQuery.buttons["compose"].tap()
app.navigationBars["CREATE POST"].buttons["CANCEL"].tap()
collectionViewsQuery.buttons["photo"].tap()
app.navigationBars["PHOTO BOOTH"].buttons["CANCEL"].tap()
let element = collectionViewsQuery.children(matching: .cell).element(boundBy: 1).children(matching: .other).element
element.children(matching: .other).element(boundBy: 0).children(matching: .image).element(boundBy: 0).tap()
let profileCloseButton = app.buttons["profile close"]
profileCloseButton.tap()
let image = element.children(matching: .image).element
image.swipeUp()
let button = app.navigationBars["DETAILS"].buttons[" "]
let cell = collectionViewsQuery.children(matching: .cell).element(boundBy: 0)
cell.buttons["actionsheet"].tap()
app.sheets.buttons["Cancel"].tap()
cell.buttons["comment"].tap()
button.tap()
collectionViewsQuery.buttons["like selected"].tap()
Here is my LogIn func and Setup.
func logIn() {
let app = XCUIApplication()
if app.tabBars.buttons["HOME"].exists {
logOut()
}
let logInButton = app.buttons["LOG IN"]
logInButton.tap()
let elementsQuery = app.scrollViews.otherElements
let emailField = elementsQuery.textFields["example#email.com"]
emailField.tap()
emailField.typeText("***************")
let passwordSecureTextField = elementsQuery.secureTextFields["Password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("************")
app.navigationBars["LOG IN"].buttons["btn login"].tap()
if app.staticTexts["PLEASE TURN ON NOTIFICATIONS"].exists {
XCTAssert(app.staticTexts["This way you will be able to see when your friends post, message, like or comment on your stuff!"].exists)
app.buttons["NOT NOW"].tap()
}
if app.collectionViews.staticTexts["3D Rooms Now Available!"].exists {
XCTAssert(app.collectionViews.staticTexts["Chat with friends in 3D rooms wherever you go! Tap here to get started"].exists)
app.collectionViews.buttons["close"].tap()
}
if app.staticTexts["DAILY"].exists {
XCTAssert(app.staticTexts[" SPIN"].exists)
app.buttons["close"].tap()
}
}
Setup:
class HomeScreenTests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
app.launch()
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
Here is a chunk of the output from the test logs:
LogFile
I currently have an app written in objc and swift.
I would like to implement a custom popup interstitial ad that runs for a few seconds and then presents an X to close the popup and continues doing so every couple minutes unless the
Remove Ad's in-ap purchase has been purchased.
I already have the in-app purchases setup. I would really appreciate the help or a demo/sample would be fantastic!
Create a separate controller with an image view which will popup according to the timer set in app delegate. close X should also have a timer
func applicationDidEnterBackground(application: UIApplication) {
if (!isShowingAd && adTimer != nil) {
adTimerTimeLeft = adTimer!.fireDate.timeIntervalSinceNow
adTimer!.invalidate()
}
if adUpdateTimer != nil
{
adUpdateTimerTimeLeft = 60 * 60 //one hour
self.adUpdateTimer!.invalidate()
}
}
//setting timer, This way you can set timer
var adTimer: NSTimer?
timer = NSTimer.scheduledTimerWithTimeInterval(10.0, target: self, selector: #selector(AppDelegate.updateAd), userInfo: nil, repeats: true)
timer?.fire()
I would like to stop function like this:
- (void)update:(NSTimeInterval)currentTime
{
if (self.lastUpdateTimeInterval)
{
_dt1 = currentTime - _lastUpdateTimeInterval;
}
else
{
_dt1 = 0;
}
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
self.lastUpdateTimeInterval = currentTime;
[self moveObject];
}
I now timers stop like: [timer1 invalidate], but how to stop function that is running on timer interval?
If you want to stop the animation you can call removeAllActions on your sprite object:
[_sprite removeAllActions];
But I think you need to also run the animation just if the sprite is not running it already. To do that you can use:
if (![_sprite hasActions])
{
[_sprite runAction:action];
}
If you want to stop just one animation (not all) you can use runAction:withKey: method when you run action and you can see if the action is running by calling actionForKey: or you can stop it by calling removeActionForKey.
Double clicking fast on a button in Sencha Touch 2 when having a navigation view will on some Android device push the new view twice on the view stack, how to solve it? Doesnt happen on iPhone
If you're having problems with the single click, then wrap the event function in a delayed task... for instance:
tap: function(button, e, eOpts) {
if(this.delayedTask == null){
this.delayedTask = Ext.create('Ext.util.DelayedTask', function() {
this.myFunctionToCall();
this.delayedTask = null;
}, this);
this.delayedTask.delay(500);
}
}
So in the example above, if another tap is registered and this.delayedTask has yet to be null, then it will not create the new delayed task which ultimately calls whatever function you need after 500 miliseconds... hope this makes sense, it's also a way to create double tap events on buttons...
This issue is a bit old but I was facing the same issue in the app I'm working on in my company. This is especially frustrating when buttons are bound to an Ajax call.
I took back Jeff Wooden's solution to override every button in my app :
Ext.define('MyApp.override.CustomButton', {
override : 'Ext.Button',
doTap: function(me, e) {
if(this.delayedTask == null){
this.callOverridden(arguments);
this.delayedTask = Ext.create('Ext.util.DelayedTask', function() {
this.delayedTask = null;
}, this);
this.delayedTask.delay(500);
} else {
console.log("Preventing double tap");
}
}
});
How does it works?
Each button action will trigger a delayedTask which will intercept button action for 500 ms, therefore preventing doubletap
This will work for 'tap' and 'handler:', which both pass through 'doTap' method
this is linked to the current button so it won't reverberate on other buttons
To use it simply add it in your app.js 'requires' block
Ext.application({
requires: [
...
'MyApp.override.CustomButton',
...
],
Helpfull Sources :
https://www.sencha.com/forum/showthread.php?173374-Ext-override()-on-Ext-components-in-ExtJS-4-x
Best practice for overriding classes / properties in ExtJS?
this post
Is it possible through the YouTube API to fire an event when the video reaches a specified time? e.g. when the video reaches 20 sec. fire the event.
Thanks,
Mauro
not sure if you still need an answer to this (as I'm finding it 4 months later) but here's how I accomplished this with youtube's iframe embed api. It's ugly in that it requires a setInterval, but there really isn't any kind of "timeupdate" event in the YouTube API (at least not in the iframe API), so you have to kind of fake it by checking the video time every so often. It seems to run just fine.
Let's say you want to start up your player as shown here with YT.Player(), and you want to implement your own onProgress() function that is called whenever the video time changes:
In HTML:
<div id="myPlayer"></div>
In JS:
// first, load the YouTube Iframe API:
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// some variables (global here, but they don't have to be)
var player;
var videoId = 'SomeYoutubeIdHere';
var videotime = 0;
var timeupdater = null;
// load your player when the API becomes ready
function onYoutubeIframeAPIReady() {
player = new YT.Player('myPlayer', {
width: '640',
height: '390',
videoId: videoId,
events: {
'onReady': onPlayerReady
}
});
}
// when the player is ready, start checking the current time every 100 ms.
function onPlayerReady() {
function updateTime() {
var oldTime = videotime;
if(player && player.getCurrentTime) {
videotime = player.getCurrentTime();
}
if(videotime !== oldTime) {
onProgress(videotime);
}
}
timeupdater = setInterval(updateTime, 100);
}
// when the time changes, this will be called.
function onProgress(currentTime) {
if(currentTime > 20) {
console.log("the video reached 20 seconds!");
}
}
It's a little sloppy, requiring a few global variables, but you could easily refactor it into a closure and/or make the interval stop and start itself on play/pause by also including the onStateChange event when you initialize the player, and writing an onPlayerStateChange function that checks for play and pause. You'd just need to seperate the updateTime() function from onPlayerReady, and strategically call timeupdater = setInterval(updateTime, 100); and clearInterval(timeupdater); in the right event handlers. See here for more on using events with YouTube.
I think you may have a look at popcorn.js.
It's an interesting mozilla project and it seems to solve your problem.
Not sure if anyone agrees here but I might prefer to use setTimeout() over setInterval() as it avoids using event listeners, eg:
function checkTime(){
setTimeout(function(){
videotime = getVideoTime();
if(videotime !== requiredTime) {
checkTime();//Recursive call.
}else{
//run stuff you want to at a particular time.
//do not call checkTime() again.
}
},100);
}
Its a basic pseudocode but hopefully conveys the idea.