Fetch not working on React Native Android debug - android

I'm trying to create a very simple ReactNative app to play around with GraphQL and RN on an Android (I'm already familiar with getting it to work on an iPhone).
But I'm running into a problem -- my root component places a get request to an API. Although that request works perfectly when I spin up an XCode simulator, it completely fails when I run the Android version on my phone.
The Android/iOS versions are for now completely identical. The two index files both use react-native-router-flux and are identical, and they import shared components.
Here's the simplified code of the component:
constructor(props) {
super(props);
this.state = {
source: 'myGraphQLEndpoint'
}
}
componentDidMount() {
if (this.props.drill) { return null; }
this.serverRequest = fetch(this.state.source)
.then((result) => result.json())
.then((json) => {
this.setState({
drill: json.data.drill
});
});
}
componentWillUnmount() {
this.serverRequest.abort();
}
render() {
const { drill } = this.state;
if (!drill) { return null; }
... some view stuff
}
On my iOS simulator, this works perfectly. On my Android phone, it never sets state, and so doesn't get past the if (!drill) line. If I instead set the state to the expected API data directly (instead of making an actual call), the Android app works just fine (with the non-live data).
The phone IS connected to the internet.
Any idea what's wrong?
PS -- I've tried a number of variants, including:
Changing the request to have only one .then, which calls response.json().data.drill.
Assigning the response to a variable defined outside of the request, and setting state to equal that (which sets state to what looks like a response buffer [42, 36, ... which can't be printed to the screen.
No dice.

Related

Noticing different behavior when updating playback status on iOS and Android using Expo's Audio Module

I'm currently attempting to implement an audio player in React Native using Expo's Audio module. Everything is working as expected in Android, but on iOS, the playbackStatusUpdate() callback does not appear to be working. I've pasted the relevant snippet below.
Audio.setAudioModeAsync({
playsInSilentModeIOS: true,
interruptionModeIOS: INTERRUPTION_MODE_IOS_DO_NOT_MIX,
interruptionModeAndroid: INTERRUPTION_MODE_ANDROID_DO_NOT_MIX,
});
const { sound } = await Audio.Sound.createAsync({ uri });
await sound.setProgressUpdateIntervalAsync(100);
sound.setOnPlaybackStatusUpdate((data) => {
if (data.isLoaded) {
setCurrentPosition(data.positionMillis);
setIsPlaying(data.isPlaying);
setClipDuration(data.durationMillis || 0);
if (data.didJustFinish && !data.isLooping) {
sound.setPositionAsync(0);
options.onPlaybackComplete();
}
}
});
On iOS, the callback simply is not called at all, so no statuses, etc. are set.
I'm using the current position to update a slider at a higher level in my component tree. Again - this all works exactly as expected in Android. Any idea what could be happening here?

React native android undefined is not a function works in IOS

Works in IOS and works in Android when the debugger is running, but doesn't work via Android Simulator. I get this message via react-native log-android and basically I am just having nothing returned to the screen:
12-02 10:39:58.511 22502 24204 W ReactNativeJS: TypeError: undefined is not a function (near '...}).flat()
Android Picture
IOS Picture
Here is the fetch function I am using:
import axios from 'axios';
export const getData = async url => {
try {
const response = await axios.get(url);
const data = response.data;
return data;
} catch (error) {
console.log(error);
}
};
export default getData;
Inside of my componentDidMount, where I call the endpoint using the GetData function above:
componentDidMount() {
const teamsAPI = 'https://statsapi.web.nhl.com/api/v1/teams';
getData(teamsAPI).then(teams => {
const teamData = teams.teams
.map(({ id, name }) => ({
teamId: id,
teamName: name
}))
.flat()
this.setState({
teams: teamData
});
});
}
Everything has since been moved to REDUX, but I looked back at one of my branches today with the more basic code shared above and had the issue back then with this code as well. Unfortunately didn't realize all the differences with code compilations till now. Understand that the issue is probably because of 2 compilers, but have no idea how to approach the issue/ why there would be a type error in one and not the other.
It works with debugger I think due to what was mentioned here:
React Native behavior different in simulator / on device / with or without Chrome debugging
Edit: wanted to mention I've already done a cache reset and deleted the build folder and rebuilt
I tried out your code and the promise rejecting is happing for me in both Android and iOS. It is being caused by the .flat() removing it stops the promise rejection from occurring.
Looking at the data that you are mapping there there doesn't seem to be a need to flatten the data as it comes back as a array of objects with no other arrays inside it.
Could removing the .flat() be a possible solution for you?
You can see here for more information about .flat() and how it is still experimental array.prototype.flat is undefined in nodejs
I would also consider returning something from your getData function when it makes an error or perhaps use a promise with it that way you can handle an error.

Appium+Android+webdriverio, how to click on element of a list

I started using Appium to run UI test on Android apps (and possibly iOS once I get it to work on Android)
I'm trying to run a test using nodeJS and webdriverio.
The thing is, I can't seem to click on an element of a list (the list is dynamically created so elements all have the same id)
Here is the node code. When I run it, appium correctly starts an emulator and opens my app:
const wdio = require("webdriverio");
const opts = {
port: 4723,
desiredCapabilities: {
platformName: "Android",
platformVersion: "8.0",
deviceName: "Android Emulator",
app: "/path/to/application.apk",
appWaitActivity: "com.package.SomeActivity",
automationName: "UiAutomator2",
avd: "Nexus_5X_API_26"
}
};
const client = wdio.remote(opts);
client
.init()
.elements('id:theIdOfTheList') // This retrieves a list of 4 elements
.element()[3] // This gives a NoSuchElementError
.end();
What should I use in place of .element()[3] to make this work (or is there a completely different way I should do it?)
I see in appium that the 4 elements of the list are retrieved:
Got response with status 200: {"sessionId":"1c21baa1-60ec-4e5f-b51f-f738698660ad","status":0,"value":[{"ELEMENT":"53d31f1f-af25-4621-85cd-b2f881a5c770"},{"ELEMENT":"4c3909ab-6f65-426a-b831-9a7d5e069ba8"},{"ELEMENT":"e0fd1f12-0193-48ea-a168-4d45f63d27b3"},{"ELEMENT":"87b7abda-3738-4411-a544-572243cd7502"}]}
I'm not familiar with Node.js, but from the looks of it you're not storing that array of elements anywhere and your subsequent element() call is merely looking for another unrelated element. Since you've provided it no search parameters, it finds nothing.
Pardon my ignorance of your language, but something like the following should get you what you want:
.elements('id:theIdOfTheList')[3]
How about something like this. ( I use sync mode for webdriverio). This may work in
asyc mode.
client
.init()
.elements('id:theIdOfTheList', function(err, resp) {
resp.value.forEach(function(elem) {
// log elem
})
})
.end();

Xamarin: Differences in async handling on Android and UWP

When using async Methods of PCLStorage there is a strange behaviour on UWP.
In the Constructor of App I have to load a json file by PCLStorage. The first file Operation is a CheckFileAsync. As the App constructor is not an async method (it's ok if it blocks for a moment) I first tried this:
var catalogue =FreshTinyIOCBuiltIn.Current.Resolve<IStorageManager>().GetCatalogue(null).Result;
Which works fine on Android. But on UWP it blocks completely and never comes back.
If I do it this way:
Catalogue catalogue = null;
var t = Task.Run(async () =>
{
catalogue = await FreshTinyIOCBuiltIn.Current.Resolve<IStorageManager>().GetCatalogue(null);
});
t.Wait();
Everything is fine. What is the reason for this?

Protractor's waitForAngular() fails on angular-webapp (appium/chrome on real device)

I'm (newly) using protractor to run e2e cucumber tests.
I got a web-app which is angularJS based. I'm using appium to remotely run the test on a real android device. Here are the versions i'm using :
windows8.1
protractor#1.3.1 (with submodule selenium-webdriver#2.43.5)
appium#1.3.0beta1
android device with 4.4.4
my protractor configuration (extracts), corresponding to https://github.com/angular/protractor/blob/master/docs/browser-setup.md:
currentDeviceUDID = (...);
var appToTestURL = 'http://my.website.com:9000/app/index.html';
exports.config = {
seleniumAddress: 'http://localhost:4723/wd/hub';
chromeOnly: false,
specs: ['features/sample.feature'],
capabilities: {
browserName: 'chrome',
'appium-version': '1.0',
platformName: 'Android',
platformVersion: '4.4.4',
udid: currentDeviceUDID
},
baseUrl: appToTestURL
framework: 'cucumber',
cucumberOpts: {
require: 'features/stepDefinitionsSample.js',
tags: '#dev',
format: 'progress'
},
// configuring wd in onPrepare
onPrepare: function () {
var wd = require('wd'),
protractor = require('protractor'),
wdBridge = require('wd-bridge')(protractor, wd);
wdBridge.initFromProtractor(exports.config);
},
allScriptsTimeout: 30000,
getPageTimeout: 30000
};
As you can see, i have replaced the protractor's webdriver url with the appium webdriver. i start the appium from commandline with "appium &", then i run the test with "protactor cucumbertest.conf"
The phone opens chrome browser and navigates to the url i give it with "browser.get(url)"
the problem is the following:
the call waitForAngular(), which is asynchronously waiting for the website to load and on all open http request (as far as i understand), is not executed sucessfully on the phone. the phone does not react to the call, and the webdriver proxy returns a 500.
Corresponding to https://github.com/angular/protractor/issues/1358, i understood that the waitForAngular() function is mixed in protractor into the calls
['getCurrentUrl', 'getPageSource', 'getTitle'];
Behind waitForAngular() in the file protractor.js is the function below, which is proxied to the phone:
functions.waitForAngular = function(selector, callback) {
var el = document.querySelector(selector);
try {
if (angular.getTestability) {
angular.getTestability(el).whenStable(callback);
} else {
angular.element(el).injector().get('$browser').
notifyWhenNoOutstandingRequests(callback);
}
} catch (e) {
callback(e);
}
};
Additional information: when i stimulate an error on the webdriver (browser) object, the error message points to the chromedriver.exe inside the protractor directory. i dont understand why the error is not from appium's chromedriver
so tldr;
without the successful call waitForAngular, i cannot (stable or at all) access elements on the page on the phone, so not testing. maybe im misunderstanding some fundamental configuration detail here, all hints are welcome.
edit: added appium server logs here: http://pastebin.com/vqBGUdXH
I assume i have identified the problem. Appium and Protractor work fine.
My angularJS app causes the issue. It uses $timeout for polling (im forced on angular 1.07 which has no $interval). This causes protractor to expect the page to be still in the loading stage and not finished. Therefore the function call waitForAngular() never returns and the test timeouts after the specified timeout-timespan.
This behaviour is expected and known, also documented (better read doc first ;) ) at http://angular.github.io/protractor/#/timeouts
The doc suggests the following for continuous polling: replace $timeout with $interval:
If your application continuously polls $timeout or $http, it will never be registered as completely loaded. You should use the $interval service (interval.js) for anything that polls continuously (introduced in Angular 1.2rc3).
For now, i fixed the issue another way: disable the built-in angular sync and manually sync
this.Before(function(next){
ptor = protractor.getInstance();
ptor.ignoreSynchronization = true; //disables waitForangular()
next();
});
Sync method 1:
//at a testcase, wait for an element to be visible with a promise/then
browser.wait(function () {
element.all(by.css('.myCssClass')).then(function (items) {
items[0].getText().then(function (text) {
console.log(text);
});
});
return true;
}
Sync method 2 :
// "eventually" (chai-as-promised) internally uses "promise" (and therefore acts like "then")
browser.get(url);
expect(browser.getTitle()).to.eventually.equal("connect me").and.notify(next);

Categories

Resources