I've completed my first JavaScript course and am now following a course on React. I've created a simple backend using Express and MongoDB.
I've created a frontend using npx create-react-app, added axios to communicate with the backend and am using antd for the UI. So far so good! The following code works on my laptop running Windows 10 and Edge 94 to insert a new Year into MongoDB using a simple input:
Client uses:
const onFinish = async (values) => {
await api.createYear(values).then((res) => {
console.log("onFinish", values);
console.log(res);
});
};
API uses:
import axios from 'axios'
const api = axios.create({
baseURL: 'http://localhost:3000/api/v1',
})
export const createYear = values => api.post(`/year`, values)
Server (controller) uses:
const Year = require('../models/year-model')
createYear = (req, res) => {
const body = req.body
if (!body) {
return res.status(400).json({
success: false,
error: 'You must provide a year!',
})
}
const year = new Year(body)
if (!year) {
return res.status(400).json({ success: false, error: err })
}
year
.save()
.then(() => {
return res.status(201).json({
success: true,
id: year._id,
message: 'Year created!',
})
})
.catch(error => {
return res.status(400).json({
error,
message: 'Year not created!',
})
})
}
Server (model) uses:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const yearSchema = new Schema(
{
year: { type: Number, required: true }
},
{ timestamps: false },
)
module.exports = mongoose.model('Year', yearSchema)
However, the same code does not work on my Samsung Galaxy S21 using Edge 93 and Chrome 94. Based on what I found so far, this could be caused by this browser not supporting async/await (ES2017 feature). This could probably be resolved by Babel?
I'm sorry that this part is pretty vague: the information I found is a kind of overwhelming considering my limited experience and all variables involved (React version, Babel version, Babel plugins, Webpack etc). I would gladly provide more information if you could point me in the right direction.
Could anyone perhaps tell me if and how I should change Babel or Webpack to make async/await work in mobile browsers?
If the problem is that async/await doesn't work on those browsers, then I think you can change your .babelrc file to target older browsers.
However, to address #ammar's points, maybe double check that:
you can see web pages served by your laptop on your phone
your phone browser doesn't work with async/await
I would create a simple html page that looks like this to make sure that this is the problem.
<html>
<head></head>
<body>
<div>TEST PAGE<div>
<div id='test'></div>
<script>
function sleep(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
(async function() {
for (let x = 0; x < 1000; x++) {
document.getElementById('test').innerHTML = x;
await sleep(1000);
}
})();
</script>
<body>
</html>
I would attack it like this:
save the above as test.html
open the file directly with your laptop browser and see the count-up
figure out how to serve the same file as static content with the webpack dev server, and open it in the laptop browser
open the same file on your mobile device to prove that you can see the page at all, and that async/await is not working
Related
I'm developing a webapp authentication system using Firebase. When I login and use the webapp from my computer everything works fine but when I use it on mobile appcheck does not work anymore and it gives me the following error in the console:
https://content-firebaseappcheck.googleapis.com/v1/projects/nameoftheproject/apps/1:784721317237:web:5db5892bc06253ab6b173c:exchangeRecaptchaEnterpriseToken?key=myKey
Failed to load resource: the server responded with a status of 403 ()
This is the code I'm using to create initialise appCheck in my webapp:
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider(config[process.env.REACT_APP_ENV]['recaptcha-key']),
isTokenAutoRefreshEnabled: true
});
export const getAppCheckToken = async () => {
let appCheckTokenResponse;
try {
appCheckTokenResponse = await getToken(appCheck, false);
} catch(err) {
console.log(err);
}
return appCheckTokenResponse.token;
}
So a typical use case for that function is this:
//This is the code from one of my functions, it's just an example to show you how I use appcheck tokens
if (querySnapshot.docs.length === 0) {
headerAPI.headers['X-Firebase-AppCheck'] = await getAppCheckToken();
await axios.post(signupAPI, {
email: email,
username: displayName
}, headerAPI);
await sendEmailVerification(auth.currentUser, {
url: config[process.env.REACT_APP_ENV]['url-used-to-send-mail-auth-signup'],
handleCodeInApp: true
})
props.cookieAlert('Info', 'Cookies', 'Informations here...');
} else {
window.location.href = '/dashboard/home';
}
Now, I can't understand why it doesn't work on mobile...I hope my code is clear enough to let you understand my troubles, thank you in advance.
My Firebase web project has been working for several months now. But on Sunday June 3, 2018, my application stopped sending tweets with media (images) attached. Before this, it was working for several months. I have not changed the failing code before the 3rd and I have even reverted to code that worked before that date but the app still fails :(
SDK versions:
I am using the most up to date versions of Firebase tools (3.18.6), and cloud functions (1.0.3). Along with twit (2.2.10) a javascript library for twitter api.
Do note my project was also working on older versions of the above including pre v1.0 cloud functions. Also note, I am still able to send regular text tweets just not ones with any media (image,gif,mp4).
This mainly relates to Twitter's API, but I cannot rule out something funky going on in Firebase's Node.js environment.
How to reproduce:
For simplicity, I will link to the code in a tutorial which I originally used when starting the project.
Setup a twitter account and retrieve all the necessary tokens as outlined in the tutorial. Then simply call the cloud function below and it will attempt to tweet the NASA image of the day.
The function is able to upload the picture to the twitter server and the response I get is expected:
{ media_id: 1004461244487643100,
media_id_string: '1004461244487643136',
media_key: '5_1004461244487643136',
size: 92917,
expires_after_secs: 86400,
image: { image_type: 'image/jpeg', w: 960, h: 1318 } }
However, once it attempts to post the tweet with the media attached, I receive an error
code 324: 'Unsupported raw media category'
which doesn't exist in Twitter's docs: https://developer.twitter.com/en/docs/basics/response-codes.html
Now, Code 324 does exist but in Twitter's docs there is a different description:
"The validation of media ids failed"
Which I have yet to receive. So my media id is valid, so something else is wrong? No where on the internet can I find someone with this exact error.
Link to tutorial code:
https://medium.freecodecamp.org/how-to-build-and-deploy-a-multifunctional-twitter-bot-49e941bb3092
Javascript code that reproduces the issue:
**index.js
'use strict';
const functions = require('firebase-functions');
const request = require('request');
const path = require('path');
const os = require('os');
const fs = require('fs');
const tmpDir = os.tmpdir(); // Ref to the temporary dir on worker machine
const Twit = require('twit');
const T = new Twit({
consumer_key: 'your twitter key'
,consumer_secret: 'your twitter secret'
,access_token: 'your twitter token'
,access_token_secret: 'your twitter token secret'
});
exports.http_testMediaTweet = functions.https.onRequest((req, res) => {
function getPhoto() {
const parameters = {
url: 'https://api.nasa.gov/planetary/apod',
qs: {
api_key: 'DEMO_KEY'
},
encoding: 'binary'
};
request.get(parameters, (err, response, body) => {
if (err) {console.log('err: ' + err)}
body = JSON.parse(body);
var f = path.join(tmpDir, 'nasa.jpg');
saveFile(body, f);
});
}
function saveFile(body, fileName) {
const file = fs.createWriteStream(fileName);
request(body).pipe(file).on('close', err => {
if (err) {
console.log(err)
} else {
console.log('Media saved! '+body.title)
const descriptionText = body.title
uploadMedia(descriptionText, fileName);
}
})
}
function uploadMedia(descriptionText, fileName) {
const filePath = path.join(__dirname, `../${fileName}`)
console.log(`uploadMedia: file PATH ${fileName}`)
T.postMediaChunked({
file_path: fileName
}, (err, data, respone) => {
if (err) {
console.log(err)
} else {
console.log(data)
const params = {
status: descriptionText,
media_ids: data.media_id_string
}
postStatus(params);
}
})
}
function postStatus(params) {
T.post('statuses/update', params, (err, data, respone) => {
if (err) {
console.log(err)
res.status(500).send('Error: ' + err);
} else {
console.log('Status posted!')
res.status(200).send('success');
}
})
}
// Do thing
getPhoto();
});
I was hoping to launch my app next week but this has become a major issue for me. I've tried everything I can think of and consulted the docs for Twitter and the js library but I seem to be doing everything right. Hopefully someone can shed some light on this, thanks.
This question might have been asked by many people, but I have no luck to get answer from researching.
My ultimately plan is running a web app with Web Bluetooth API in smartphone with FLIC button to control audios to play. One click, play one audio.
I'm testing the program in my MAC laptop with my iPhoneX first, because I'm thinking if I can get both of them connected, then when I run the web app in smartphone, then I can connect to the FLIC button.
However, I got this error.
Something went wrong. NotSupportedError: GATT Error: Not supported.
Am I missing something? I saw someone mentioned iPhone cannot connect Latop, hopefully this is not true
Below is the code:
$("#bluetooth").on("click", function(){
const controlServiceUUID = '00001805-0000-1000-8000-00805f9b34fb'; // Full UUID
const commandCharacteristicUUID = '00002a0f-0000-1000-8000-00805f9b34fb'; //
var myCharacteristic;
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: [controlServiceUUID]
})
.then(device => {
console.log("Got device name: ", device.name);
console.log("id: ", device.id);
return device.gatt.connect();
console.log("Here");
})
.then(server => {
serverInstance = server;
console.log("Getting PrimaryService");
return server.getPrimaryService(controlServiceUUID);
})
.then(service => {
console.log("Getting Characteristic");
return service.getCharacteristic(commandCharacteristicUUID);
})
.then(characteristic => {
// 0x01,3,0x02,0x03,0x01
myCharacteristic = characteristic;
return myCharacteristic.startNotifications().then(_ => {
log('Notifications started');
myCharacteristic.addEventListener('characteristicvaluechanged', test);
});
})
.catch(function(error) {
console.log("Something went wrong. " + error);
});
function test(event) {
if (myCharacteristic) {
myCharacteristic.startNotifications()
.then(_ => {
console.log("Notification stopped!");
})
.catch(error => {
console.log("Argh!" + error);
});
}
}
});
Web Bluetooth API is only available on ChromeOS and Android 6 or later with flag option.
(https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API)
Different platforms are at different points in implementation. I have been using this repo for updates on the status of the API:
WebBluetoothCG/web-bluetooth
Note the lack of support for ios
Not sure if this fixes your problem (i'm working on muse eeg), but one "hack" to get rid of this error is to wait some time (e.g. 500ms) after each characteristic write. Most platforms don't support write responses yet and writing multiple commands in parallel will cause this error.
https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md
Is your command characteristic UUID filled in incorrectly? Try replacing it with one that can be written?
const controlServiceUUID = 0xfff0; // Full UUID
const commandCharacteristicUUID = 0xfff4; //
Does anyone have a proper example on how to configure BrowserMobProxy with WebDriverIO? This is so I can capture network traffic. I previously had it working with WebDriverJS, which is essentially a deprecated version of WebDriverIO.
You can use the below code to do that. Make sure your browsermob proxy and selenium server is running. Then copy paste below code in a test.js file and put it in webdriverio installed folder. From cmd go to that folder and run node test.js . stuff.har should be generated where test.js is located.
var Proxy = require('browsermob-proxy').Proxy
, webdriverio = require("./node_modules/webdriverio/")
, fs = require('fs')
, proxy = new Proxy()
;
proxy.cbHAR('search.yahoo.com', doSeleniumStuff, function(err, data) {
if (err) {
console.error('ERR: ' + err);
} else {
fs.writeFileSync('stuff.har', data, 'utf8');
}
});
function doSeleniumStuff(proxy, cb) {
var browser = webdriverio.remote({
host: 'localhost'
, port: 4444
, desiredCapabilities: { browserName: 'firefox', seleniumProtocol: 'WebDriver', proxy: { httpProxy: proxy } }
});
browser
.init()
.url("http://search.yahoo.com")
.setValue("#yschsp", "javascript")
.submitForm("#sf")
.end().then(cb);
}
If you just want to capture the network traffic, then there is one more way to do it.
Webdriverio allows you to use Chrome Dev Tools Protocol.
Please read webdriverio blog
This is one of the examples on how to use chrome dev tools along with webdriverio, do let me know in case you need more help.
const { remote } = require('webdriverio')
let browser;
(async () => {
browser = await remote({
automationProtocol: 'devtools',
capabilities: {
browserName: 'chrome'
}
})
await browser.url('https://webdriver.io')
await browser.call(async () => {
const puppeteerBrowser = browser.getPuppeteer()
const page = (await puppeteerBrowser.pages())[0]
await page.setRequestInterception(true)
page.on('request', interceptedRequest => {
if (interceptedRequest.url().endsWith('webdriverio.png')) {
return interceptedRequest.continue({
url: 'https://user-images.githubusercontent.com/10379601/29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png'
})
}
interceptedRequest.continue()
})
})
// continue with WebDriver commands
await browser.refresh()
await browser.pause(2000)
await browser.deleteSession()
})().catch(async (e) => {
console.error(e)
await browser.deleteSession()
})
Since I had no luck solving this problem using browsermob proxy (AFAIK it wasn't updated in a while)
I created a small npm module to capture selenium tests as HAR files - https://www.npmjs.com/package/har-recorder
I took #Raulster24 suggestion and implemented it using the Chrome Dev Tools Protocol - https://github.com/loadmill/har-recorder/blob/master/index.js
I am having issue with imports during my testing. The test framework is Mocha, and I am using chai and sinon. I think this is an issue with my understanding with how scope works in Javascript. Nonetheless.
Here's my test file:
test/action/forgot-password
const middlewares = [ thunk];
const mockStore = configureMockStore(middlewares);
describe('forgot password async actions', () => {
afterEach(()=> {
nock.cleanAll();
});
it('should show a request for a password reset and that it succeeded ', (done) => {
nock('http://localhost:8080/')
.post('/password-reset-requests')
.reply(200);
var email = "test#email.com";
const expectedActions= [
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST},
{type: REQUEST_ADD_PASSWORD_RESET_REQUEST_SUCCESS}
];
const store = mockStore({}, expectedActions, done);
store.dispatch(Actions.addPasswordResetRequest(email));
});
});
Here is the api call my action makes
api/users.js
'use strict';
export const addPasswordResetRequest = (email) => {
console.log(NC_SETTINGS.API_ROOT);
return fetch(
NC_SETTINGS.API_ROOT + '/password-reset-requests',
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
code: NC_SETTINGS.GROUP.code
})
}
)
.then(handleResponse);
};
So when I run it normally, in a browser, I get no errors. Fetch gets called just fine, and the file knows where the NC_SETTINGS file is.
I should mention the file structure of my project.
-project
--app folder
---js folder
----api folder
-----users.js(this makes the call to fetch)
--settings folder
---settings.js file(this has nc_settings)
--test folder
---testing file
They get imported just fine when on local_web.
But when I am testing, neither fetch nor nc_settings is found.
To get around fetch, I did import isomorphic fetch in my api/users.js, which fixes the fetch issue during testing. I then tried to import app/settings/settings, and it does find the file. However it still doesn't solve the issue. It now comes up as undefined.
What's the reasoning behind this? Is this a hoisting scope issue? How is this resolved?