Testing timeout-related tests, such as Popups/Tooltips etc with Detox - ios

I've beed using detox for a while, but after upgrade to 17.5.+ I have started facing an issue with Popups testing. I haven't find useful info on a stack overflow and on detox issues.
Problem here is the following: I have a test to check if correct popup is shown. It looks like:
it('expect to see "Answer correct" popup', async () => {
await openQuestionnaire('theory_questionnaire_learn_button');
await scroll('questionnaire_scroll_view', 150);
await element(by.id('select_1_button')).tap();
await element(by.id('questionnaire_answer_button')).tap();
// #ts-ignore
await expect(element(by.id('questionnaire_simple_popup'))).toBeVisible();
// #ts-ignore
await expect(element(by.id('questionnaire_simple_popup'))).toHaveLabel('correct');
await delay(500);
// #ts-ignore
await expect(element(by.id('questionnaire_simple_popup'))).toNotExist();
});
Background for this: after questionnaire_answer_button is tapped, popup appears. It is visible for 500ms and then it disappears. For this 500ms I'm using setTimeout({ () => dismiss() }, 500).
Popup is visible on an emulator, but my test fails with Test Failed: No elements found for “MATCHER(identifier: == “questionnaire_simple_popup”)”
Checking hierarchy I haven't find this element there. Maybe someone else have already faced this and know a solution?

If the identifier is not found, it means the identifier has not been properly set with the native view’s accessibility identifier. Check with the popup developer that testID are properly forwarded to the native views.

Ok, what have I found out after several tries. It start working after increasing timeout from 500ms to 3000ms. 2500 was still failing, 2750 haven't tried. Regarding matchers. by.id and by.text works as well.
So the reason probably was a timeout duration.

Related

useNetInfo not working when connection is reestablished

I'm using react-native-netinfo to keep track of my device's internet connection. It was working fine for the most part until the point where the internet is disconnected and comes back on. At this point NetInfo does not respond with the correct internet state.
While going over the repo on github it looks like this is a known issue without a fix yet. In one of the threads, there was a mention of using the hook useNetInfo instead cos apparently that still worked fine.
So I tried that out as mentioned here https://github.com/react-native-netinfo/react-native-netinfo/issues/400#issuecomment-953177841 but even this isn't returning the correct state when the connection is established again.
I'm not sure what to do now. I don't know if there is more to this hook or if it needs to be implemented differently.
What I did to make it work was to add an event listener in componentDidMount() and remove the listener in componentWillUnMount().
componentDidMount(){
NetInfo.isConnected.fetch().then(isConnected => {
this.handleConnectivityChange(isConnected === undefined ? true : isConnected);
});
NetInfo.isConnected.addEventListener(
'connectionChange',
this.handleConnectivityChange
);}
My handleConnectivityChange() function stores the isConnected boolean in redux to be used wherever I want.
componentWillUnMount() {
NetInfo.isConnected.removeEventListener(
'connectionChange',
this.handleConnectivityChange
);
}

React Native Detox - Local and CI have different outcomes

I am having strange issue with React Native Detox testing when being ran on local and CI environments.
Following is the piece of code being ran on both of the environments:
import { E2E_IDS } from './constants';
import {
executeBeforeEachTest,
tapById,
testAccount,
typeTextById,
waitForId,
waitForText,
} from './utils';
describe('User email sign in flow test', () => {
beforeEach(executeBeforeEachTest);
it('should login with provided user credentials successfully', async () => {
await tapById(E2E_IDS.SIGN_IN);
await waitForText('Welcome back');
await tapById(E2E_IDS.SIGN_IN_VIA_EMAIL);
await typeTextById(E2E_IDS.SIGN_IN_EMAIL, testAccount.USER);
await typeTextById(E2E_IDS.SIGN_IN_PASSWORD, testAccount.PASS);
await tapById(E2E_IDS.SIGN_IN_LOGIN_BUTTON);
await waitForText('You have no classes yet.');
});
});
On my local mac machine, e2e tests runs fine as expected.
On Github CI mac machine, e2e fails because single tap on SIGN_IN_LOGIN_BUTTON is not enough, if I do the following:
await tapById(E2E_IDS.SIGN_IN_LOGIN_BUTTON, 2);
If we tap the button twice, then it passes the test. I wonder why the first tap is not being acknowledged by the CI machine, that we had to do twice.
If anyone could help narrow down the root cause of this behaviour that would be great.
The last issue was quite tricky, it was actually a UX bug. So, when user types their email and password in the login form, the keyboard doesn't drop when we tap on the login button, because we had a keyboard overlay which is blocking the login button being tapped. To circumvent this issue, we need to add keyboardShouldPersistTaps='handled' to the top level scrollView which will trigger down the tap events to it's child which will result in closing the keyboard plus the tap to right element, all in one go.
It was strange why this didn't happen on my local simulator, perhaps, we can toggle the keyboard on/off which didn't help me to narrow down the issue at hand.
Why 2 taps?
Because, first one was to drop the keyboard (inactive state) then the next one was to tap on the login button.

Why is this this error: Failed to execute 'fetch' on 'ServiceWorkerGlobalScope': 'only-if-cached' can be set only with 'same-origin' mode [duplicate]

After upgrading to Chrome 64, I realized that this error appears when I load my page on a new tab.
I can't identify where it is on the service worker. Here is my code to run the fetch:
self.addEventListener('fetch', function(event) {
if (event.request.url.startsWith(self.location.origin)) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request).then(function(fetch_resp){
return fetch_resp;
});
})
);
}
});
Could anyone here, who has more knowledge about service worker, help me to solve this error?
I believe this is a Chromium bug that has been reported here. Hopefully it will be fixed soon or some more information about the issue will be published.
Paul Irish implemented a temporary work around, which is as follows:
if (e.request.cache === 'only-if-cached' && e.request.mode !== 'same-origin') {
return;
}
I ran it inside the callback for the service worker install and fetch listeners and it prevented the error.
You can see the full commit of Paul's code here.
For those searching for this again, seems like it popped up after a while again when someone opens the devtools you can still see the error mentioned in the question.
See (new) bug report here: https://bugs.chromium.org/p/chromium/issues/detail?id=1098389
So let's hope this will be fixed again soon!
perhaps the cache name is not unique from other applications, seems to fix the issue for me.

How to test if Xamarin Android app closes

I am writing my first Android app, using Xamarin. I have an Exit button that, when clicked, closes the app. I want a test in Xamarin UITest that verifies clicking the button closes the app. I messed around with it for a while and finally found something that allows the test to pass.
In the app:
exitButton.Click += (o, e) =>
{
int pid = Android.OS.Process.MyPid();
Android.OS.Process.KillProcess(pid);
};
In UITest:
[Test]
public void ExitButtonClosesTheScreen()
{
try
{
app.Tap(c => c.Button("exitButton"));
Assert.Fail("App remains open.");
}
catch (System.Exception e)
{
Assert.AreEqual("The underlying connection was closed: The connection was closed unexpectedly.", e.InnerException.InnerException.InnerException.Message);
}
}
The test now passes so I guess I'm happy. My question is, is this really the best way to do this? Or is there a better way that I wasn't able to find?
Edit: Unfortunately, this is not the answer. This method allows the test to pass in VS but fails when I run it in App Center. Is there another way to run this test? Or is this something that is simply not testable with UITest? Thank you.
First of all the right code for closing the Application as per me is using finish affinity
In an Activity:
this.FinishAffinity();
In a Fragment:
this.Activity.FinishAffinity();
After doing this AppCenter should be able to figure that your app is closed.
I did a brief read up on this the other day for something similar and I am certain that the ActivityManager class would be the best way to go about this.
https://developer.xamarin.com/api/type/Android.App.ActivityManager/
There is a method within this class called RunningAppProcesses which returns a list of application processes that are running on the device - and from there I guess you can assert if your app process is on the list or not.
Hope this helps
After almost 4 years, i've encountered with the same issue.
I will do it this way in your case:
[Test]
public void ExitButtonClosesTheScreen()
{
app.Tap(c => c.Marked("exitButton"));
/** I asume exitButton click action will just exit,
no popups or alerts appear before exiting. **/
app.WaitForNoElement(q => q.Marked("exitButton"),
"Timeout waiting for element exitButton",
new TimeSpan(0, 0, 30));
AppResult[] result = app.Query();
Assert.IsTrue(result.Length == 0);
}
app.Query() returns all views visible by default, unless a query is especified by a lambda expression, as you should alredy know.
If the Application is gone, the Views visible will be 0, and as such, app.query() will return and array lenght of 0.
For WaitForNoElement's timeout I use a TimeSpan of 30 seconds, but you can use whatever timeout you prefer for this operation, i just considered 30 seconds will be ok.

Flutter Tests: Waiting for a certain duration

I'm trying to wait for some time after I tested tapping my button to then check the result with expect. I'm using Future.delayed for that. But that doesn't work for me. I'm getting a time out error.
TimeoutException after 0:00:05.000000: Test timed out after 5 seconds.
This is the code I use:
... // other tests
await tester.tap(find.widgetWithText(GestureDetector, "ref size"));
await new Future.delayed(new Duration(milliseconds: 50));
expect(testContainerState.childWidth, 50.0);
Does any one have an idea why this (imo) strange behavior occurs?
So, to start out with a simpler answer the correct way to wait for a period of time in a flutter test is using tester.pump.
await tester.pump(new Duration(milliseconds: 50));
The longer answer to why this happens has to do with the flutter testing environment. To make sure tests are reliable, even in the face of time-varying animations the environment mocks as much of the async behavior as possible, using utilities such as FakeAsync from package:quiver.
If you want to waiting data for Ex can you use this code :
await tester.runAsync(() async {
// test code here
});
tester is instance of WidgetTester

Resources