'FIRESTORE INTERNAL ASSERTION FAILED: Unexpected state' when unit testing with Jest - node.js

I'ḿ setting up a jest test suite for a Node.js and Express REST API i'm building, i'm using #firebase/testing module to initialize a testing app, however when i try to perform any sort of operation to the database this error comes out:
FIRESTORE (7.17.2) INTERNAL ASSERTION FAILED: Unexpected state
at fail (/home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/util/assert.ts:39:9)
at hardAssert (/home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/util/assert.ts:53:5)
at fromBytes (/home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/remote/serializer.ts:270:5)
at fromWatchChange (/home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/remote/serializer.ts:486:25)
at PersistentListenStream.onMessage (/home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/remote/persistent_stream.ts:576:25)
at /home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/remote/persistent_stream.ts:456:21
at /home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/remote/persistent_stream.ts:509:18
at /home/cardonapablo/Documentos/Proyectos/Optica (Ilicit)../../../../../node_modules/#firebase/testing/node_modules/#firebase/firestore/src/util/async_queue.ts:369:14
I also tried connecting to my regular firestore database with the credentials i have been using to develop the endpoints and same error pops out even tho it's the app i use daily
Weird thing is, data is being written to the database, but error still stops testing
Here is firebase setup:
(src/db/functions.js)
let app = initializeTestApp({
projectId: "illicit"
})
db = app.firestore()
module.exports = { db }
Function throwing the error
(tests/fixtures/db.js)
const { db } = require('../../src/db/functions')
const bcrypt = require('bcrypt');
const createAdmin = async function() {
// Encrypt password
let encPass = await bcrypt.hash("admin", 8)
let admin = {
name: "Admin Test User",
email: "admin#test.com",
password: encPass,
tokens: []
}
// Add to db
let docRef = await db.collection('admins').add(admin) // <- This line throws the error
return;
}
module.exports = {
createAdmin
}
And finally testing file
(tests/glasses.test.js)
const supertest = require('supertest');
const app = require('../src/app')
const functions = require('./fixtures/db')
let adminToken;
let glassesId;
//Executes before any test, here is where error occurs, before any tests
beforeAll( async () => {
await functions.createAdmin()
return
})
test('Should log in an admin', async () => {
let response = await supertest(app)
.post('/admins/login')
.send({
email: 'admin#test.com',
password: 'admin'
})
.expect(200);
expect(response.body.token).toEqual(expect.any(String))
adminToken = response.token;
});
This only happens only when i try to test, regular app works just fine
Things i've tried:
Firestore rules are read and write true, so it's not a rules error
Mocked Firestore with firebase-mock and Jest seems to work fine, however this is not a
solution, since i need to test data inside the database
Hope you can help me :)

You should change Jest's test environment from the default jsdom to node using jest --env=node or by setting the testEnvironment option to node in your Jest config.

Solved the problem myself, i was using the Firebase web client, I switched to the Admin SDK made specifically for servers, i guess it was some sort of auth problem, because the admin sdk automatically authenticates you in the db

This is a open issue on GitHub. I'm pasting my comment from that issue here to hopefully help some other people:
I experienced the same error message on 9.6.6 with NextJS. I believe
this error message could be presented due to a range of errors - as I
see 100+ Stackoverflow questions with this error message.
After lots of debugging I realized I accidently used SQL
capitalization:
.orderBy('time', 'ASC') = "INTERNAL ASSERTION FAILED: Unexpected state" .orderBy('time', 'asc') = No Errors!
This was a pain to debug, and my mistake was so small. Maybe better
error reporting is needed in cases like this? When you get then Google
this error message it easily leads you down a path of debugging things
completely irrelevant to the real error.
So pretty much - a tiny syntax error can cause the error message and lead you down a road of debugging the wrong things. To solve this you have to find exactly where it is happening and narrow in your debuging.

execute this command with what is indicated a little above yarn test jest --env=node
after this the error disappears

Related

OpenAI Fine tuned engine not working in Node - "Engine not found"

I have fine-tuned an engine on OpenAI using my own data. I can access the engine in the Playground with no issues, however, when I try to access it programmatically using Node & the openai Node library, I get an "Engine not found" error. The weird thing is, I could have sworn it worked before.
Anyway, here is my code:
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
async function getDream() {
const completion = await openai.createCompletion("davinci:ft-personal-2022-04-09-19-12-54", {
prompt: "I dreamed",
});
console.log(completion.data.choices[0].text);
}
getDream();
Here's the error:
error: {
message: 'Engine not found',
type: 'invalid_request_error',
param: null,
code: null
}
I tried running the same code but with a regular engine (davinci). Works fine that way. I've double-checked that I have the name of my fine-tuned engine right and tried it using the engine ID just in case. Nothing seems to work.
PS - I have run this using the OpenAI CLI as well using openai api completions.create -m davinci:ft-personal-2022-04-09-19-12-54 -p "I dreamed" and that works as well.
I'm back, answering my own question in hopes that it will help others.
It seems that if you are using your own fine-tuned model, you have to use a different method than if you use one of the default models. Instead of createCompletion, you should use createCompletionFromModel. So the function above (getDream) should actually look like this:
async function getDream() {
const response = await openai.createCompletionFromModel({
model: 'davinci:ft-personal-2022-04-09-19-12-54',
prompt: 'I dreamed'
// add other parameters here
});
}
You can add other completion parameters to this below prompt, e.g. temperature, frequency_penalty, etc.

In a callable Firebase Cloud Function, how do i discern which code to use when i throw an error?

When catching an error in a Firebase Cloud Function, the Firebase documentation for handling errors does not explain clearly which error code is appropriate to set for failed reads/writes to Firestore.
Given the following function:
exports.myCustomFunction = functions.https.onCall( async (data, context) => {
if (!context.auth) {
// Throwing this error is self explanatory and works as expected.
throw new functions.https.HttpsError("unauthenticated", "User must be authenticated.");
}
const uid = context.auth.uid;
const userQuery = admin.firestore().collection("users").where("userId", "==", uid);
try {
const user = await userQuery.limit(1).get();
// do stuff...
} catch (error) {
// ******* THIS IS THE ERROR I NEED HELP WITH *******
throw new functions.https.HttpsError("aborted", "user_query", {error: error});
}
});
If a Firestore query, as i have set in the above function, fails, or for that matter, if any Firestore read/write, or a Firestore batch set, fails for any reason, what would be the appropriate error code to set?
The options seem limited. Should it be aborted or unknown?
The error codes that you can pass to the HttpsError constructor are listed in the API documentation. If you encounter an error that your code can't resolve now or in the foreseeable future, usually you use "internal", which translates to the usual 500 HTTP status code. This lets the client know that something went wrong that was the fault of the backend and can't necessarily be fixed by a simple retry.

GraphqQL Cannot set headers after they are sent to the client

I have tried looking at other articles on SO related to this question, but I am unable to resolve this issue.
I have a graphql api and in my component on the UI side, I am calling it as such
useEffect(()=>{
const leaders = graphQLClient.request(GetLeadersQuery)
if(leaders && leaders.leaders) {
let leadersList = JSON.parse(leaders.leaders)
setLeaders(leadersList)
}
}, [leaders])
On the server side, this looks like this
leaders: (_parent, args, _context) => {
return (JSON.stringify({
name:"Jane Dooe"
}))
This is the query that I am using
query {
leaders
}
Now everytime, my client side code is hit, I see the following error in my terminal.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
My use case is very simple and yet , I am unable to see why I am encountering this error.
Update
On my client side, I tried doing the following, just to make sure that I am resolving the promises, but I am still getting the same result.
useEffect(()=>{
async function getLeaders(){
const leaders = await graphQLClient.request(GetLeadersQuery)
console.log({ leaders })
if (leaders && leaders.leaders) {
let leadersList = JSON.parse(leaders.leaders)
setLeaders(leadersList)
}
}
getLeaders()
}, [])
On the server side I am using
NextJS
apollo-server-micro
On the client side I am using
React
graphql-request
Can you please help ?
Thanks

Error snap.data is not a function with firebase cloud function and onCreate

I have a cloud function that sends a welcome email every time a new user registers in the database.
The function correctly executes everything, sends the emails and these are received by the recipient, so far, everything is fine.
It works when I manually write the email address in the function, but when I want it to get the data from the realtime database, it gives me the error:
TypeError: snap.data is not a function
This is the code of my function:
const functions = require('firebase-functions');
const nodemailer = require("nodemailer");
const transport = nodemailer.createTransport({
service: "Gmail",
auth: {
user: "MY_EMAIL",
pass: "MY_EMAIL_PASSWORD"
}
})
exports.welcomeMail = functions.database.ref('/paso1/{id}').onCreate((snap, context) => {
const _name = snap.data().name;
return sendWelcomeMail(_name)
});
// aux functions
function sendWelcomeMail(name) {
return transport.sendMail({
from: "JohnDoe <sender#test.com>",
to: "myfriendemail#gmail.com",
subject: "Hello",
html: `
<h1<Hello ${name} </h1>
<p>nice to seeyou</p>
`
})
.then(r => r)
.catch(e => e);
}
This is my realtime database:
I have reviewed the documentation several times, I have tested with snap.val().{uid}; but all without success, I cannot recover the "name" field from the database.
Using const _name = snap.val().name; I get the same error
I am not sure what is failing.
The method you're looking for is snap.val(), not snap.data(). You might be confusing Realtime Database with Firestore. Firestore uses data() to get the raw data out of a DocumentSnapshot, but that's different than Realtime Database.
You have a typo. You declare snap and then refer to it as snapshot. To fix this problem, make sure the declaration and use match.
You're also using snapshot.data(), while data() doesn't exist on a Realtime Database snapshot (you're probably confusing it with Cloud Firestore).
So combining those two fixes, this should be much closer:
exports.welcomeMail = functions.database.ref('/paso1/{id}')
.onCreate((snapshot, context) => { // this line changed
const _name = snapshot.val().name;
...
I finally found what the mistake was.
Indeed, as you have indicated to me, the correct way to extract the data from the realtime database is by using .val()
However, I told you in the comments to the answers that I kept returning error.
It didn't work because I wasn't initializing the firebase SDK as an ADMIN, necessary to access, among other things, the realtime database.
https://firebase.google.com/docs/admin/setup
I hope my mistake will save other programmers time.
Thanks to all for the help

Make data pulled from a remote source available in NodeJS App

I'm just getting going with NodeJS and am trying to use jsforce (salesforce) to populate a dropdown on a form.
I've written a module the requires jsforce, sets login params, and connects.
``modules/sftools.js
const jsforce = require('jsforce')
const conn = new jsforce.Connection({
loginUrl: process.env.SF_LOGINURL
})
conn.login(process.env.SF_USER, process.env.SF_PASS)
exports.metaDropDown = async (field) =>
conn.sobject...describe..
return arrayOfValues
}
I want to make the value returned available throughout my app, so in index.js I've got
``index.js
const sftools= require('../modules/sftools')
const roles = sftools.metaDropDown(process.env.SF_ROLES)
and then I use some middleware to always set req.roles = roles.
I think the problem is that I'm requesting the roles before the connection is established, but I can't figure out the flow.
I tried logging in before the exports code, but I get an Invalid URL error, presumably because it isn't logged in yet.
I tried to put the login code directly into the metaDropdown export, which got rid of the error, but there is still no data returned.
Any suggestions?
I think the issue your having is that for the login function is expecting a callback as the third argument.
conn.login(process.env.SF_USER, process.env.SF_PASS, function() {
// do your role logic here.
})
Hope this helps.

Resources