├── .gitignore ├── README.md ├── api ├── controllers │ ├── README.md │ ├── reverse.js │ └── ticker.js ├── helpers │ └── README.md ├── mocks │ └── README.md └── swagger │ └── swagger.yaml ├── app.js ├── config ├── README.md └── default.yaml ├── images ├── quickfox-1.png ├── quickfox-2.png ├── reverse-2.png ├── reverse-done.png ├── reverse.png ├── stockbot.png └── swagger-icon.png ├── package.json └── test └── api ├── controllers ├── README.md └── hello_world.js └── helpers └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE files 2 | .idea 3 | 4 | # Logs 5 | logs 6 | *.log 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # Commenting this out is preferred by some people, see 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # Users Environment Variables 31 | .lock-wscript 32 | 33 | # Runtime configuration for swagger app 34 | config/runtime.yaml 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slack integration with swagger-node 2 | 3 | [Slack](https://slack.com/) is a popular messaging app for team communication. A nice thing about Slack is that you can easily integrate external services to provide extra features. For example, out-of-the-box integrations are available for services like GitHub, Google Drive, Heroku, Jira, and many others. In this example, we'll show how easy it is to integrate a [swagger-node](https://www.npmjs.com/package/swagger) API with Slack. 4 | 5 | ## Get the sample swagger-node app from GitHub 6 | 7 | Download or clone the [swagger-node-slack](https://github.com/apigee-127/swagger-node-slack) project on GitHub. 8 | 9 | After downloading the app, do the following: 10 | 11 | 1. cd to the root project directory `swagger-node-slack`. 12 | 2. Execute this command to get the Node.js dependencies: 13 | 14 | `npm install` 15 | 16 | 3. Execute this command to install `swagger-node` on your system. This step installs `swagger-node` and puts the `swagger` CLI in your path: 17 | 18 | `npm install -g swagger` 19 | 20 | ## About the sample swagger-node app 21 | 22 | In this example, a [swagger-node](https://github.com/swagger-api/swagger-node) API implementation provides the back-end "services" that we will integrate into Slack. We created two sample API implementations for you to try out with Slack: 23 | 24 | * An API that reverses whatever text you enter in a Slack conversation. 25 | 26 | * An API that fetches a stock quote and prints it to a Slack team conversation. 27 | 28 | In this tutorial, we'll show you how to set up Slack integrations that call these `swagger-node` APIs. 29 | 30 | ### Before you begin 31 | 32 | If you're going to try to do this tutorial, you'll need to do these steps first: 33 | 34 | 1. You need to either be a member of or create a new Slack team. In either case, you need to have permission to create integrations. 35 | 36 | 2. Your app has to be reachable by Slack via HTTP, and it must be deployed to a platform that supports Node.js. We're going to deploy it to [Apigee Edge Cloud](http://apigee.com/about/products/api-management). To do that, you'll need to [sign up for an Apigee Account](https://accounts.apigee.com/accounts/sign_up). If you don't want to do that, you can deploy the app to any other Cloud platform that supports Node.js, like Heroku or AWS. However, we won't cover any other deployment options besides Apigee Edge in this topic. 37 | 38 | 39 | ## About the integrations 40 | 41 | Here's a brief overview of the integrations we'll build here. 42 | 43 | ### Slash Command" integration (Text Reverser) 44 | 45 | Slack "slash commands" let you execute a function by entering it directly in a Slack conversation. Here's how the Text Reverser integration we'll build here works. You'll enter it like this in Slack: 46 | 47 | `/reverse Hello World` 48 | 49 | And get a reply with the characters reversed: 50 | 51 | ![alt text](./images/reverse.png) 52 | 53 | ### Incoming WebHook" integration (Ticker-bot) 54 | 55 | Incoming WebHook integrations let you post data from an external source/service into Slack. For this example, we'll call a `swagger-node` API using a curl command. This API will then post a reply directly to a Slack channel. We'll call it like this... 56 | 57 | `curl -X POST -H "Content-Type: application/x-www-form-urlencoded" http://docs-test.apigee.net/slash/ticker -d "text=AAPL` 58 | 59 | ...and get back a nicely formatted response in Slack, like this: 60 | 61 | ![alt text](./images/stockbot.png) 62 | 63 | ## Part 1: Building the Slash Command integration (Text Reverser) 64 | 65 | Let's walk through the steps for integrating the "text reverser" API with Slack. We're not going to go overboard to explain how to set things up in Slack, but we'll give pointers to keep you on track. It's remarkably easy. 66 | 67 | ### First, A quick peek under the hood 68 | 69 | Take a look at the `swagger-node-slack` project. It's a `swagger-node` project created with the `swagger project create` commmand. If you're not familiar with `swagger-node`, you can check out [the docs](https://github.com/swagger-api/swagger-node/blob/master/docs/introduction.md), and try the quick-start tutorial if you like. 70 | 71 | The key to understanding how the `swagger-node-slack` API works is to look at these two files: 72 | 73 | * `./swagger-node-slack/api/swagger/swagger.yaml` -- This is the Swagger definition for the API. Note that it defines the paths, operations, and parameters for the service. You can use the built in Swagger editor to make changes with `swagger project edit`. 74 | 75 | ``` 76 | paths: 77 | /reverse: 78 | # binds a127 app logic to a route 79 | x-swagger-router-controller: reverse 80 | post: 81 | description: take text and reverses it 82 | # used as the method name of the controller 83 | operationId: reverse 84 | consumes: 85 | + application/x-www-form-urlencoded 86 | parameters: 87 | + $ref: "#/parameters/token" 88 | + $ref: "#/parameters/command" 89 | + $ref: "#/parameters/text" 90 | + $ref: "#/parameters/team_id" 91 | + $ref: "#/parameters/team_domain" 92 | + $ref: "#/parameters/channel_id" 93 | + $ref: "#/parameters/channel_name" 94 | + $ref: "#/parameters/user_id" 95 | + $ref: "#/parameters/user_name" 96 | ``` 97 | 98 | * `./swagger-node-slack/api/controllers/*.js` -- In this example project, there are two controller files, one for the `/reverse` path and one for the `/ticker` path. As you can see, these files implement the actual operation logic for each path. Here's the `reverse()` function that gets executed when the `/reverse` path is called. 99 | 100 | ``` 101 | function reverse(req, res) { 102 | 103 | checkToken(req, res, function(err, reply) { 104 | if (err) { 105 | return res.json(err); 106 | } else if (req.swagger.params.text.value === "") { 107 | res.json("Please enter some text to reverse!"); 108 | } else { 109 | console.log(reply); 110 | var gnirts = req.swagger.params.text.value.split('').reverse().join(''); 111 | res.json(gnirts); 112 | } 113 | }); 114 | } 115 | ``` 116 | 117 | 118 | ### Try it locally 119 | 120 | You can run the `swagger-node-slack` project locally, and hit the API just to see what it does. 121 | 122 | 1. cd to the `swagger-node-slack` directory on your system. 123 | 2. If you haven't done so previously, execute this command to update the Node.js dependencies: 124 | 125 | `npm install` 126 | 127 | 2. Start the project: 128 | 129 | `swagger project start` 130 | 131 | 3. Open the file `./swagger-node-slack/api/controllers/reverse.js` in a text editor. 132 | 133 | 4. Note that the `token` var is set to `secret123`. The API requires a `token` parameter that matches this value, as we'll see. Later, we'll replace this value with a token issued by Slack. 134 | 135 | `var token = "secret123"` 136 | 137 | 3. In a separate terminal window, call the API as shown below with the `token`and `text` parameters. 138 | 139 | `curl -X POST -H "Content-Type: application/x-www-form-urlencoded" http://localhost:10010/reverse -d "token=secret123&text=hello"` 140 | 141 | The API reverses the string specified by the `text` parameter and returns: 142 | 143 | `""olleh""` 144 | 145 | Note that the API also validates the token. If you call the API with a different token, you'll get an error. For example: 146 | 147 | `curl -X POST -H "Content-Type: application/x-www-form-urlencoded" http://localhost:10010/reverse -d token=secret234&text=hello"` 148 | 149 | `"Error: Sorry, the token key is invalid."` 150 | 151 | ### Create the Slack integration 152 | 153 | Now, let's go over to the Slack side. 154 | 155 | 1. Log in to your Slack account. 156 | 157 | 1. From your Slack team menu, choose **Configure Integrations**. 158 | 159 | 2. Scroll down to **DYI Integrations & Customizations** and click **Slash Commands**. 160 | 161 | 3. In **Choose Commands**, enter the command name `/reverse`. 162 | 163 | 4. **Click Add Slash Command Configuration**. 164 | 165 | 4. Fill out the integration settings: 166 | 167 | a. Command: `/reverse`. 168 | 169 | b. URL: http://{your apigee org name}-{the apigee environment name}.apigee.net/slack/reverse 170 | 171 | For example: http://docs-test.apigee.net/slack/reverse 172 | 173 | c. Method: POST 174 | 175 | d. Token: Copy the token; you'll need it shortly. 176 | 177 | 5. Click **Save Integration**. You'll see your Slash Command integration listed in the **Configured Integrations** tab, as shown in this screen shot: 178 | 179 | ![alt text](./images/reverse-done.png) 180 | 181 | ### Add the token to the controller file 182 | 183 | Now, we're going to use the token that Slack issued when we created the Slash command. 184 | 185 | >Note: When you enter the `/reverse` slash command in a Slack conversation, Slack sends a POST request to the `swagger-node` app with a bunch of parameters. One of them is the token. Code in `./swagger-node-slack/api/controllers/reverse.js` validates this token, ensuring that the command was sent from your Slack team. 186 | 187 | 1. Copy the token from the Slash command UI in Slack. 188 | 189 | 2. Open the file `./swagger-node-slack/api/controllers/reverse.js` in a text editor. 190 | 191 | 3. Enter the token string from Slack as the value of `var token`. For example: 192 | 193 | `var token = "6dIWuDTuheXsVVJcjDVVdA"` 194 | 195 | 4. Save the file. 196 | 197 | ### Deploy it 198 | 199 | For this example, we'll deploy the app to the [Apigee Edge](http://www.apigee.com) cloud platform. As mentioned previously, you'll need an Apigee account (it's free) to do this. (However, you can publish it to any platform that supports Node.js if you wish.) 200 | 201 | 1. Install [apigeetool](https://www.npmjs.com/package/apigeetool). This utility lets you deploy Node.js apps to Apigee Edge. 202 | 203 | `npm install -g apigeetool` 204 | 205 | 2. Make sure `apigeetool` is in your PATH. Just enter `apigeetool` at the command line. If you see a list of valid commands, you're good to go. 206 | 207 | `apigeetool` 208 | 209 | 3. Be sure you're in the root directory of the `swagger-node` project: 210 | 211 | `cd swagger-node-slack` 212 | 213 | 4. Use `apigeetool` to deploy the app: 214 | 215 | `apigeetool deploynodeapp -u -o -e -n slash -d . -m app.js -b /slash -v default,secure` 216 | 217 | For example: 218 | 219 | `apigeetool deploynodeapp -u jdoe@apigee.com -o jdoe -e test -n 'slash' -d . -m app.js -b /slash` 220 | 221 | For help on this command, enter `apigeetool deploynodeapp -h`. 222 | 223 | ### Test it 224 | 225 | Now we can hit our API directly from a Slack! In your Slack team channel, enter the `/reverse` command with some text to reverse: 226 | 227 | `/reverse The quick brown fox jumps over the lazy dog` 228 | 229 | ![alt text](./images/quickfox-1.png) 230 | 231 | And Slack returns the letters in reverse: 232 | 233 | ![alt text](./images/quickfox-2.png) 234 | 235 | ### What happened? 236 | 237 | The Slack Slash Command Integration called the `swagger-node-slack` app that was deployed on Apigee Edge. Slack retrieved the response and printed it to the chat window. 238 | 239 | ## Part 2: Building the Incoming WebHooks integration (Ticker-bot) 240 | 241 | The Ticker-bot is an API implemented in `swagger-node` and added to Slack as an Incoming WebHook integration. This type of integration is designed to fetch some external data and display it in Slack. In this case, we implemented a `swagger-node` API that takes a stock symbol and sends the stock price to Slack. 242 | 243 | 244 | ### Create the Slack integration 245 | 246 | Let's go over to the Slack side first. 247 | 248 | 1. Log in to your Slack account. 249 | 250 | 1. From your Slack team menu, choose **Configure Integrations**. 251 | 252 | 2. Scroll down to **DYI Integrations & Customizations** and click **Incoming WebHooks**. 253 | 254 | 3. In **Post to Channel**, select the channel to post the API response to. In other words, whenever someone calls the Ticker-bot, a stock price is posted to this channel for everyone to see. 255 | 256 | 4. Click **Add Incoming WebHooks Integration**. 257 | 258 | 4. Review the setup instructions. 259 | 260 | 5. Copy the Webhook URL. 261 | 262 | 6. In the name field, change the default name to "Ticker-bot". 263 | 264 | 7. Add an icon or emoji if you wish. 265 | 266 | 6. Open the file `swagger-node-slack/api/controllers/ticker.js` in a text editor. 267 | 268 | 7. Locate this variable and uncomment it: 269 | 270 | `var URL = "https://hooks.slack.com/services/https://hooks.slack.com/services/GET/SLACK URL";` 271 | 272 | 8. Replace the value of the URL variable with the Webhook URL. For example: 273 | 274 | `var URL = "https://hooks.slack.com/services/https://hooks.slack.com/services/X012434/BT3899/PSbPEfQybmoyqXM10ckdQoa";` 275 | 276 | 9. Save the file. 277 | 278 | 279 | ### Try it! 280 | 281 | A nice thing about projects built with `swagger-node` is that you can build and test them locally on the built-in HTTP server. Let's try out our new Ticker-bot! 282 | 283 | >Remember, with an Incoming WebHooks integration, the idea is to send a message FROM another service INTO a Slack channel. 284 | 285 | 1. cd to the `swagger-node-slack` directory. 286 | 2. If you haven't done so previously, execute this command to update the Node.js dependencies: 287 | 288 | `npm install` 289 | 290 | 3. Start the project: 291 | 292 | `swagger project start` 293 | 294 | 4. In another terminal window, call the API, like this... 295 | 296 | `curl -X POST -H "Content-Type: application/x-www-form-urlencoded" http://localhost:10010/ticker -d "text=AAPL&user_name=marsh"` 297 | 298 | ...and you get back a nicely formatted response in your Slack session, like this: 299 | 300 | ![alt text](./images/stockbot.png) 301 | 302 | 303 | ## Extra credit 304 | 305 | 1. Deploy the Ticker-bot app to the Cloud and test it. 306 | 307 | 2. Try creating a Slack Slash command `/ticker` that calls the Ticker-bot API. The command will let users enter something like this in Slack to post a stock price: 308 | 309 | `/ticker AAPL` 310 | 311 | Be sure to add token validation to the API's controller, as implemented in the `/reverse` example. 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | -------------------------------------------------------------------------------- /api/controllers/README.md: -------------------------------------------------------------------------------- 1 | Place your controllers in this directory. 2 | -------------------------------------------------------------------------------- /api/controllers/reverse.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var util = require('util'); 4 | var request = require('request'); 5 | var token = "secret123"; 6 | 7 | module.exports = { 8 | reverse: reverse 9 | }; 10 | 11 | 12 | function checkToken(req, res, cb) { 13 | 14 | var keyParam = req.swagger.params.token.value; 15 | 16 | if (keyParam === token) { 17 | return cb ("", "Valid token received."); 18 | } else { 19 | return cb("Error: Sorry, the token key is invalid."); 20 | } 21 | } 22 | 23 | function reverse(req, res) { 24 | 25 | checkToken(req, res, function(err, reply) { 26 | if (err) { 27 | return res.json(err); 28 | } else if (req.swagger.params.text.value === "") { 29 | res.json("Please enter some text to reverse!"); 30 | } else { 31 | console.log(reply); 32 | var gnirts = req.swagger.params.text.value.split('').reverse().join(''); 33 | res.json(gnirts); 34 | } 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /api/controllers/ticker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var util = require('util'); 4 | var request = require('request'); 5 | var googleStocks = require('google-stocks'); 6 | 7 | 8 | 9 | module.exports = { 10 | ticker: ticker 11 | }; 12 | 13 | 14 | //var URL = "https://hooks.slack.com/services/GET/FROM/SLACK"; 15 | // For example: 16 | // var URL = "https://hooks.slack.com/services/T08H0A1/B08YEMHR6/v8DnEDKEuwyDj5uGEEUbGaIF"; 17 | 18 | 19 | function ticker(req, res) { 20 | var symbol = req.swagger.params.text.value.toUpperCase(); 21 | googleStocks.get([symbol], function(error, data) { 22 | console.log(symbol+": "+data[0].l); 23 | var text = symbol+" is now $"+data[0].l+" per share.\nThanks for asking, @"+req.swagger.params.user_name.value+"!"; 24 | request.post({ url:URL, body:{"text":text,"channel":"#"+req.swagger.params.channel_name.value}, json:true}); 25 | res.status(200).type('application/json').end(); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /api/helpers/README.md: -------------------------------------------------------------------------------- 1 | Place helper files in this directory. 2 | -------------------------------------------------------------------------------- /api/mocks/README.md: -------------------------------------------------------------------------------- 1 | Place controllers for mock mode in this directory. 2 | -------------------------------------------------------------------------------- /api/swagger/swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | version: "0.0.1" 4 | title: Slack Slash Integration Examples 5 | # during dev, should point to your local machine 6 | host: localhost:10010 7 | # basePath prefixes all resource paths 8 | basePath: / 9 | # 10 | schemes: 11 | # tip: remove http to make production-grade 12 | - http 13 | - https 14 | # format of bodies a client can send (Content-Type) 15 | consumes: 16 | - application/json 17 | # format of the responses to the client (Accepts) 18 | produces: 19 | - application/json 20 | paths: 21 | /reverse: 22 | # binds a127 app logic to a route 23 | x-swagger-router-controller: reverse 24 | post: 25 | description: take text and reverses it 26 | # used as the method name of the controller 27 | operationId: reverse 28 | consumes: 29 | - application/x-www-form-urlencoded 30 | parameters: 31 | - $ref: "#/parameters/token" 32 | - $ref: "#/parameters/command" 33 | - $ref: "#/parameters/text" 34 | - $ref: "#/parameters/team_id" 35 | - $ref: "#/parameters/team_domain" 36 | - $ref: "#/parameters/channel_id" 37 | - $ref: "#/parameters/channel_name" 38 | - $ref: "#/parameters/user_id" 39 | - $ref: "#/parameters/user_name" 40 | responses: 41 | "200": 42 | description: Success 43 | schema: 44 | # a pointer to a definition 45 | $ref: "#/definitions/Message" 46 | # responses may fall through to errors 47 | default: 48 | description: Error 49 | schema: 50 | $ref: "#/definitions/ErrorResponse" 51 | /ticker: 52 | # binds a127 app logic to a route 53 | x-swagger-router-controller: ticker 54 | post: 55 | description: look up a stock price 56 | # used as the method name of the controller 57 | operationId: ticker 58 | consumes: 59 | - application/x-www-form-urlencoded 60 | parameters: 61 | - $ref: "#/parameters/text" 62 | - $ref: "#/parameters/user_name" 63 | - $ref: "#/parameters/icon_url" 64 | - $ref: "#/parameters/icon_emoji" 65 | - $ref: "#/parameters/channel" 66 | responses: 67 | "200": 68 | description: Success 69 | # responses may fall through to errors 70 | default: 71 | description: Error 72 | schema: 73 | $ref: "#/definitions/ErrorResponse" 74 | parameters: 75 | token: 76 | name: token 77 | in: formData 78 | description: grants permission to run the command 79 | required: true 80 | type: string 81 | command: 82 | name: command 83 | in: formData 84 | description: What command to trigger? 85 | required: false 86 | type: string 87 | text: 88 | name: text 89 | in: formData 90 | description: The argument to the command 91 | required: true 92 | type: string 93 | team_id: 94 | name: team_id 95 | in: formData 96 | description: Identifies the team context for the command 97 | required: false 98 | type: string 99 | team_domain: 100 | name: team_domain 101 | in: formData 102 | description: The Slack domain context for the command 103 | required: false 104 | type: string 105 | channel_id: 106 | name: channel_id 107 | in: formData 108 | description: "Identifies the #channel where the command was triggered" 109 | required: false 110 | type: string 111 | channel_name: 112 | name: channel_name 113 | in: formData 114 | description: "The name of the #channel where the command was triggered" 115 | required: false 116 | type: string 117 | user_id: 118 | name: user_id 119 | in: formData 120 | description: Identifies the user who issued the command 121 | required: false 122 | type: string 123 | user_name: 124 | name: user_name 125 | in: formData 126 | description: Friendly handle of the user 127 | required: false 128 | type: string 129 | icon_url: 130 | name: icon_url 131 | in: formData 132 | description: Override the bot icon 133 | required: false 134 | type: string 135 | icon_emoji: 136 | name: icon_emoji 137 | in: formData 138 | description: Override the bot icon 139 | required: false 140 | type: string 141 | channel: 142 | name: channel 143 | in: formData 144 | description: Override the bot icon 145 | required: false 146 | type: string 147 | definitions: 148 | Message: 149 | properties: 150 | message: 151 | type: string 152 | ErrorResponse: 153 | required: 154 | - message 155 | properties: 156 | message: 157 | type: string -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var SwaggerExpress = require('swagger-express-mw'); 4 | var app = require('express')(); 5 | module.exports = app; // for testing 6 | 7 | var config = { 8 | appRoot: __dirname // required config 9 | }; 10 | 11 | SwaggerExpress.create(config, function(err, swaggerExpress) { 12 | if (err) { throw err; } 13 | 14 | // install middleware 15 | swaggerExpress.register(app); 16 | 17 | var port = process.env.PORT || 10010; 18 | app.listen(port); 19 | 20 | console.log("curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d 'token=XXXX-XXXX-XXXX&team_id=12345&team_domain=TEAM&channel_id=12345&channel_name=CHANNEL&user_id=12345&user_name=USER&command=%252Freverse&text=Apigee' 'http://127.0.0.1:10010/reverse'"); 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /config/README.md: -------------------------------------------------------------------------------- 1 | Place configuration files in this directory. 2 | -------------------------------------------------------------------------------- /config/default.yaml: -------------------------------------------------------------------------------- 1 | # swagger configuration file 2 | 3 | # values in the swagger hash are system configuration for swagger 4 | swagger: 5 | mapErrorsToJson: true 6 | docEndpoints: 7 | raw: /swagger 8 | validateResponse: false 9 | 10 | # any other values in this file are just loaded into the config for application access... 11 | -------------------------------------------------------------------------------- /images/quickfox-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/quickfox-1.png -------------------------------------------------------------------------------- /images/quickfox-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/quickfox-2.png -------------------------------------------------------------------------------- /images/reverse-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/reverse-2.png -------------------------------------------------------------------------------- /images/reverse-done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/reverse-done.png -------------------------------------------------------------------------------- /images/reverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/reverse.png -------------------------------------------------------------------------------- /images/stockbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/stockbot.png -------------------------------------------------------------------------------- /images/swagger-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apigee-127/swagger-node-slack/965021c9a62d75f65db8a1fec861460bb1385e1a/images/swagger-icon.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sed", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "New Swagger API Project", 6 | "keywords": [], 7 | "author": "", 8 | "license": "", 9 | "main": "app.js", 10 | "dependencies": { 11 | "express": "^4.12.3", 12 | "google-stocks": "^0.1.3", 13 | "request": "^2.58.0", 14 | "swagger-express-mw": "0.0.x" 15 | }, 16 | "devDependencies": { 17 | "should": "^5.2.0", 18 | "supertest": "^0.15.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/api/controllers/README.md: -------------------------------------------------------------------------------- 1 | Place your controller tests in this directory. 2 | -------------------------------------------------------------------------------- /test/api/controllers/hello_world.js: -------------------------------------------------------------------------------- 1 | var should = require('should'); 2 | var request = require('supertest'); 3 | var server = require('../../../app'); 4 | 5 | process.env.A127_ENV = 'test'; 6 | 7 | describe('controllers', function() { 8 | 9 | describe('hello_world', function() { 10 | 11 | describe('GET /hello', function() { 12 | 13 | it('should return a default string', function(done) { 14 | 15 | request(server) 16 | .get('/hello') 17 | .set('Accept', 'application/json') 18 | .expect('Content-Type', /json/) 19 | .expect(200) 20 | .end(function(err, res) { 21 | should.not.exist(err); 22 | 23 | res.body.should.eql('Hello, stranger!'); 24 | 25 | done(); 26 | }); 27 | }); 28 | 29 | it('should accept a name parameter', function(done) { 30 | 31 | request(server) 32 | .get('/hello') 33 | .query({ name: 'Scott'}) 34 | .set('Accept', 'application/json') 35 | .expect('Content-Type', /json/) 36 | .expect(200) 37 | .end(function(err, res) { 38 | should.not.exist(err); 39 | 40 | res.body.should.eql('Hello, Scott!'); 41 | 42 | done(); 43 | }); 44 | }); 45 | 46 | }); 47 | 48 | }); 49 | 50 | }); 51 | -------------------------------------------------------------------------------- /test/api/helpers/README.md: -------------------------------------------------------------------------------- 1 | Place your helper tests in this directory. 2 | --------------------------------------------------------------------------------