How to test a Server Side plugin?

function(properties, context) {
var Twitter = require("twitter");
var request = require("request");

var client = new Twitter({
    consumer_key: context.keys["Consumer Key"],
    consumer_secret: context.keys["Consumer Secret"],
    access_token_key: properties.access_token,
    access_token_secret: properties.access_token_secret
});

const url = properties.image;

request.get({
    url: url,
    headers: {
        "Content-Type": "image/*"
    }
}, function(e, r, b) {
    if(!e){
    var data = new Buffer.from(b);
    var o = client.post("media/upload", { media: data.toString("base64") }, function(error, media, response) {
        if(!error){
        var status = {
            status: properties.tweet,
            media_ids: media.media_id_string
        }

        client.post("statuses/update", status, function(error, tweet, response) {
            if (!error) {
                console.log({error: error, tweet: tweet, response: response});
                return {
                    out: JSON.stringify(response)
                }
            }else{
                console.log(error)        
            }
        });
    }
    });
  }
});
     console.log("here")  
}

All it does is say “here” :frowning:

I suspect you’ll need to use Bubble’s context.async() callback. @Kfawcett sussed this all out with the help of some JS gurus. I find the async/await syntax more readable, but the “then-able” syntax should work as well.

Basically, your code needs to be in the form of a promise; otherwise, it won’t wait for a response, and you’ll just see what you’re getting now.

Good heavens. And I thought using IBM punch cards to compile a Fortran program was archaic. :neutral_face:

1 Like

Thanks :frowning:

OK, this is way beyond me. It seems a shame, I just ported the “basic” tweet over from webtask and it still doesn’t work.

Well, it works perfectly in webtask (for free) and yet not in Bubble.

function(properties, context) {

var Twitter = require('twitter');
 
var client = new Twitter({
  consumer_key: context.keys["Consumer Key"],
  consumer_secret: context.keys["Consumer Secret"],
  access_token_key: properties.access_token,
  access_token_secret: properties.access_token_secret
});
 
client.post('statuses/update', {status: 'I am a tweet'}, function(error, tweet, response) {
    if(error) console.log(error);   
}); 
}

vs

var Twitter = require('twitter');
 
 module.exports = function(context, cb) {
  var client = new Twitter({
    consumer_key: 'xxx',
    consumer_secret: 'xxxx',
    access_token_key: context.query.token,
    access_token_secret: context.query.token_secret
  });
  client.post('statuses/update', {status: context.query.tweet}, function(error, response, body) {
    if(error) return cb(error);
			cb(null, {response});
  });
  }

One sends out hundreds of tweets a day for free. The other we pay for and yet doesn’t work.

Anyway, thanks to everyone who helped :slight_smile: :slight_smile:

Back to the drawing board !

@NigelG, reach out to Nigel on Code Mentors here. He should be able to get you working in a very short amount of time and using Code Mentors is really easy. He’s very knowledgeable!

1 Like

To be fair, though, the execution environments are a bit different. That said, the cb argument in the webtask example is a “callback”. Anyway, try the following…

function( properties, context )
{
    var Twitter = require('twitter');

    var client = new Twitter({
        consumer_key: context.keys["Consumer Key"],
        consumer_secret: context.keys["Consumer Secret"],
        access_token_key: properties.access_token,
        access_token_secret: properties.access_token_secret
    });

    return context.async( async callback => {
        try {
            await client.post('statuses/update', {status: 'I am a tweet'}, function(error, tweet, response) {
                if (error) console.log( 'Error: ' + error.message );
                console.log( 'Tweet: ' + tweet );
                callback( undefined, { the_tweet: tweet.text, raw_resp: response.body } );
            });
        }
        catch ( err ) {
            callback( err );
        }
    });         
}

It’s untested but probably close tested and works. It does assume the_tweet and raw_resp are defined under Fields Return Values for the plugin.

2 Likes

@Kfawcett - Nigel is a genius :slight_smile: thanks for the rec.

This is what he came up with…

function(properties, context) {
    console.log('Starting up');
    
    var Twitter = require('twitter');

    var client = new Twitter({
        consumer_key: context.keys["xx"],
        consumer_secret: context.keys["yy"],
        access_token_key: properties.access_token,
        access_token_secret: properties.access_token_secret
    });

    return context.async( async function(cb) {
        // Normal Code Here
	    console.log('Running tweet callback');
        client.post('statuses/update', {status: 'I am a tweet'}, function(error, tweet, response) {
            if (error) console.log( 'Error: ', error );
            console.log( 'Tweet: ' + tweet );
            cb(null);
        });
    });  
     
}

It seems as long as you put your “normal” code in the function, and end it all with the callback, then bubble will happily wait.

As someone said before, Bubble is VERY pernickety about the first line being exactly right.

4 Likes

Awesome! Glad you got it working. :slight_smile:

Sweet! :+1:

Can I ask for help when I’ve seen Bubble and plugin experts together?

Can you point out what the problem in the following post is?

I’m not trying to make money by selling plug-ins, I’m looking for a way to use it in my own application.

Even the smallest help is very important, please take a look.

Thanks
Eren

The first question you need to answer is are you able to return the Auth token after running the script?

Thank you for your interest.

Can you answer the question?
@himanshu.s

What I want to know, is that how can I execute the pre-request script that return the auth header and use it for the api call, I need to know exactly how to apply the pre-request script, in the plugin editor.

Just a quick follow-up…

Finally got around to testing that code, and it worked straight away. The tweet got posted just fine. :+1:

I meant the Return Values section - not Fields.

Also, the “tweet” and “response” arguments are objects - not text - so I changed them to reference text fields. I’ve updated the original post accordingly.

If you’re referring to the following…

…I’ve found it to be a false positive if the only issue is that the main function’s opening bracket is on a new line. In other words, both of the following work perfectly fine even though Bubble complains about the first one.

function( properties, context )
{
    // function definition
}

function(properties, context){
    // function definition
}

It’s annoying, but I just put up with the red warning, since I break out in a cold sweat if the brackets don’t align for top level function definitions. :smirk: