sendPushNotificationsAsync never returns

#1

I am running the basic example for the Node.js expo-server-sdk’s push notifications and the code that runs

let ticketChunk = await expo.sendPushNotificationsAsync(chunk);

never returns.

I think traced it down into the expo-server-sdk source code and this is the line that runs but never returns:

            console.log("testing start")
            let response = yield this._limitConcurrentRequests(() => node_fetch_1.default(url, {
                method: options.httpMethod,
                body: requestBody,
                headers: requestHeaders,
                agent: this._httpAgent,
            }));
            console.log("testing end")

I see the “testing start” in my console but never see the “testing end”

Here is the full code that calls it (comments removed for brevity):

const { Expo } = require('expo-server-sdk')

function sendNotification() {
    let expo = new Expo();
    let tokens = ['ExponentPushToken[____REDACTED_TOKEN____]']
    let messages = [];
    for (let pushToken of tokens) {
        if (!Expo.isExpoPushToken(pushToken)) {
            console.error(`Push token ${pushToken} is not a valid Expo push token`);
            continue;
        }
        messages.push({
            to: pushToken,
            sound: 'default',
            body: 'This is a test notification',
            data: { withSome: 'data' },
        })
    }

    let chunks = expo.chunkPushNotifications(messages);
    let tickets = [];
    (async () => {
        for (let chunk of chunks) {
            try {
               console.log('about to send')
                let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
                console.log('back from send')
                console.log(ticketChunk)
                tickets.push(...ticketChunk);
                console.log('ticket chunk pushed')
            } catch (error) {
                console.log('sendPushNotificationsAsync Error')
                console.error(error);
            }
        }
    })();
}

module.exports.sendNotification = sendNotification

And my test harness that I am using to test it:

var chai = require('chai')
var PushNotification = require('../utility_modules/pushnotification')

describe('pushNotification Tests', function () {
    it('should send a notification', (done) => {
        PushNotification.sendNotification()
        done()
    })
})

Test Results:

 pushNotification Tests
about to send
testing start
    ✓ should send a notification


  1 passing (24ms)

Hopefully I’m just missing something stupid, but I can’t seem to figure it out because my test harness returns a positive test result, no errors are generated, and the notification is never sent. Any help would be greatly appreciated.

#2

Have you tested this from the Node REPL or another environment outside of a testing framework?

#3

I just called it from a regular Expo/React-Native request to my Node.js back-end and it worked! Tried again from the test program and same result as before.

Good news and it gets me over a hump…but any idea why it doesn’t work in my Mocha/Chai test?

#4

Could be that some modules are getting mocked or that the harness isn’t set up for asynchrony. I’d recommend stepping through the internals of the harness with a debugger to figure out what’s going on.

#5

Ok thanks. Definitely seems to be something specific to the test harness…will let you know if/when I figure out the problem. Appreciate you getting me on the right track!

#6

Ok, so here’s the solution I figured out. You are correct that it had to do with the ASYNC calls

First here is my new test harness code:

var chai = require('chai')
var PushNotification = require('../utility_modules/pushnotification')
var config = require('../config')
// Test Variables

describe('pushNotification Tests', function () {
    it('should send a notification', () => {
        return new Promise((resolve) => {
            let sendToken = {}
            sendToken.to = `ExponentPushToken[____REDACTED TOKEN____]`
            sendToken.sound = 'default'
            sendToken.body = 'This is a test notification'
            sendToken.data = { data: 'myData' }

            let tokens = []
            tokens.push(sendToken)
            PushNotification.sendNotification(tokens)
                .then(function (result) {
                    resolve(true)
                })
        })
    })
})

Second, I modified the actual push notification code to make the sendNotification async, and add await to the anonymous function within it.

const { Expo } = require('expo-server-sdk')

async function sendNotification(tokens) {
    if (tokens != null && tokens.length != null) {

        let expo = new Expo();
        let messages = [];
        for (let pushToken of tokens) {
            if (!Expo.isExpoPushToken(pushToken.to)) {
                console.error(`Push token ${pushToken} is not a valid Expo push token`);
                continue;
            }

            messages.push({
                to: pushToken.to,
                sound: pushToken.sound,
                body: pushToken.body,
                data: pushToken.data,
            })
        }
        let chunks = expo.chunkPushNotifications(messages);
        let tickets = [];
        await (async () => {
            for (let chunk of chunks) {
                try {
                    console.log('about to send')
                    //console.log(chunk)
                    let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
                    console.log('back from send')
                    console.log(ticketChunk)
                    tickets.push(...ticketChunk);
                    console.log('ticket chunk pushed')
                } catch (error) {
                    console.log('sendPushNotificationsAsync Error')
                    console.error(error);
                }
            }
        })();
    } else {
        console.log('Invalid token array passed to pushnotification.sendNotification()')
    }
}

module.exports.sendNotification = sendNotification

1 Like
closed #7

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.