spences10/twitter-bot-bootstrap

Example of making it an npm module

MarcL opened this issue ยท 15 comments

MarcL commented

As we were discussing on Twitter, how I'd make the ES6 branch into an exportable module for npm.

So at the moment, package.json has main as index.js which would just start the bot. Instead, export the bot itself.

{
  "name": "twitter-bot-bootstrap",
  "version": "0.0.0-development",
  "description": "twitter bot bootstrap",
  "main": "src/bot.js",
...

Because you're transpiling this with babel, you might want to build the whole project to a build or lib directory instead and reference that but I'll leave that for you to look at if you do. Also don't forget to set the name to the name of your NPM package.

Then update your src/bot.js so that it exports something that I can use if I install your bot NPM package into my project.

import Twit from 'twit'
import config from './config'

class ScottBot {
    constructor(config) {
        this.bot = new Twit(config);
    }

    tweetNow(text) {
        const tweet = {status: text}
        this.bot.post('statuses/update', tweet, (err, data, response) => {
            if (err) {
                console.log('ERROR: ', err)
            }
            console.log('SUCCESS: Replied to Follower')
        }
    }
}

export default ScottBot;

I've rewritten your bot as a class. You don't have to do this. You could export a function which returns you a bot (from new Twit(config)) and then export a 2nd function where you pass that bot through to it perhaps?

if I import your package file, I expect to pull it in and be able to use it:

// We exported with `default` above so I can just import it like this
import ScottBot from 'scotts-twitter-bot';

// Rename this to whatever the config property names are
const twitterConfig = {
    apiKey: 'myAppKey',
    apiSecret: 'myAppSecret'
};

// Initialise the bot that you've kindly built for me
const myBot = new ScottBot(twitterConfig);

// Some point later in my app
myBot.tweetNow('This is my Twitter bot!');

Does that make sense? I've exported something in bot.js which we expose to the package.json file in "main" to tell the importing module (i.e. my code) what to pull in from that export.

Shout tomorrow if it doesn't make sense. Also, there might be typos in the above code. Not tried it! :)

Cheers,
Marc

MarcL commented

Just had an idea. Why not release it as a command line package instead?
You could take parameters from the command line - meow might be helpful here if you want a nice CLI interface.
Use the "bin" property of "package.json" and then when you install with npm -g scott-tweet-bot you can just run it on the command line like:

$ scott-tweet-bot "Hello! I'm tweeting from the command line"

Pretty cool!!

Thanks for this @MarcL your initial suggestion is what I think I'm aiming at where there'll be minimal coding involved, but the CLI sounds like a pretty neat thing to do as well.

I think initially that I'd just like to get the bot up and running with ES6 style, then use babel to transpile to a build folder like you suggested so I can deploy to Heroku/now/wherever else.

I'd have got back to you this morning but my wifi adapter on my machine decided it wasn't going to connect this morning so I missed out on a few hours of coding today ๐Ÿ˜ญ

I really liked using Jest for the [simple] testing of the config parameters and saw that other users when developing wrote the test first then the code, which I had heard of but never tried. So I think I'm going to try writing everything in Jest first then code for the test, I have a feeling that it's going to be pretty slow going to start but this will put me in good stead for the future.

So I think my plan is:

  1. get a working build! ๐Ÿ˜„ < by far the biggest part
  2. look into packaging it
  3. make a CLI out of it as a separate branch/repo
MarcL commented

Cool. All sounds good. Shout if you want some help with tests too.

Hey @MarcL looks like someone has already done something similar, is this along the lines of what you meant?

 "main": "./lib/twitter-bot.js",
MarcL commented

Yes. If you add that "main" directive then it defines the entry point for the package. ๐Ÿ‘

Yeah, so I'll need to get webpack configured to build it as well wont it?

MarcL commented

No mate. Avoid adding more tooling if you can.
Think you said you're using Babel to transpile right?

So add a task in the "scripts" section:

"scripts": {
    "build": "babel src -d lib"
...

So you can run npm run build to transpile from ES6 in src/ to ES5 in lib/.
Then you'll need a prepublish script if you're publishing to npm:

"scripts": {
    "build": "babel src -d lib",
    "prepublish": "npm run build"
...

When you attempt to publish, you'll publish the built ES5 code rather than ES6 so everyone can use it.

You might want to add an .npmignore file too so you can get the published package to not publish the src/ directory.

Yes Babel to transpile, I think I have used the babel src -d lib before, I'll do that, thanks mate ๐Ÿป

I'm currently working out how to not have mt tests fail in travis as my config keys are in a .env file I have added env variables in travis but still failing ๐Ÿ˜จ

MarcL commented

Do you need to integrate Travis yet? Might be worth getting package working without it for now.

Also, I'd avoid having your unit tests rely on your API keys or environment variables.
You don't want to have to have the unit tests explicitly call a 3rd party service (i.e. the Twitter API in this case). It could fail and/or you will be tweeting every time your tests run.

Instead, look at stubbing the services so you don't need to.

I've had a quick look at your tests in the branch here: https://github.com/spences10/twitter-bot-bootstrap/blob/dev-es6/src/config.test.js

For me, this config code doesn't need to be tested. You're just testing that environment variables and object property assignment work in Node and not your code. Instead, I'd probably add some code to bot.js which throws an error if the config is empty - either the whole object or you could be more explicit and check each property. Then you're testing your code acts in the right way when a bad config is passed.

Does that make sense?

BTW: I could walk you through some testing one night if you want me to - perhaps screen share or something? I've got to write a talk for a meetup next Tuesday but I'm free after that.

Travis integration was part of the semantic-versioning setup, it's not needed

This is gold, thanks mate ๐Ÿ‘ I've heard about stubbing [toolsday.io podcast] think I'll go listen to it again, it was a pretty good one actually.

For me, this config code doesn't need to be tested. You're just testing that environment variables and object property assignment work in Node and not your code. Instead, I'd probably add some code to bot.js which throws an error if the config is empty - either the whole object or you could be more explicit and check each property. Then you're testing your code acts in the right way when a bad config is passed.

Does that make sense?

Makes perfect sense, thanks for all the pointers @MarcL

If you can afford that time then yes! I that would be really, really useful and foolish of me not to take such an opportunity, really appreciate you'd be willing to do that ๐Ÿ˜„ There's code along channels on Twitch isn't there? Or something similar I'm sure

MarcL commented

We use ScreenHero here but Slack bought them and not sure if you can register for an account any more! ๐Ÿ˜ข We'll get it working.

Think it would be useful for you, as a relative beginner to JS testing, and really useful for me to understand the problems you have. Would love to be able to make a PDF with the basics for you (or whatever you think would be relevant). Want to help people how to do solid testing (as I've said before).

re: stubbing/spies/mocks - I think Jest auto-mocks everything so you can probably use that to your advantage. Will have to investigate Jest a bit more to understand how that works as I'm pretty good with Sinon for stubbing but not really used Jest much.

My talk has been moved to 25th April so can probably do 1 night next week. Will orchestrate via Twitter.

Cool! I had a look at ScreenHero and found Existing users can still invite new users. ๐Ÿ‘

Would be good to have a GitBook maybe? I'm going to check if there are any Awesome resources for testing.

I started... https://github.com/MarcL/awesome-javascript-testing

Cool! ๐Ÿ˜Ž looking now

MarcL commented

Feel free to PR. Started it a while ago but meant to update it and put some additional info on it.
Will do so in the next week or so. Busy, busy... ;)