1 | # Ciao
|
2 |
|
3 | Ciao is a simple command line utility for testing http(s) requests and generating API documentation.
|
4 |
|
5 | Scripts are written in coffee-script, however it's important to note that they are interpreted, not executed.
|
6 |
|
7 | ### Basic uptime script:
|
8 |
|
9 | ```coffee-script
|
10 | #> Check Google is still running
|
11 | host: 'www.google.co.uk'
|
12 |
|
13 | #? Should have company name
|
14 | response.body.should.containEql 'Google'
|
15 | ```
|
16 |
|
17 | ### HTML test script:
|
18 |
|
19 | ```coffee-script
|
20 | #> Twitter home page
|
21 | port: 443
|
22 | protocol: 'https:'
|
23 | host: 'twitter.com'
|
24 |
|
25 | #? Login form
|
26 | $('div.front-signin input#signin-email').length.should.eql 1
|
27 | $('div.front-signin input#signin-password').length.should.eql 1
|
28 | $('div.front-signin button[type="submit"]').length.should.eql 1
|
29 | ```
|
30 |
|
31 | ### JSON webservice script:
|
32 |
|
33 | ```coffee-script
|
34 | #! Requried Headers
|
35 | headers: 'User-Agent': 'Ciao/Client 1.0'
|
36 |
|
37 | #> Github API call for node.js README
|
38 | port: 443
|
39 | protocol: 'https:'
|
40 | host: 'api.github.com'
|
41 | path: '/repos/joyent/node/readme'
|
42 | headers: 'Accept': 'application/json'
|
43 |
|
44 | #? Readme is available on Github
|
45 | response.statusCode.should.equal 200
|
46 | response.should.have.header 'server', 'GitHub.com'
|
47 |
|
48 | #? Should be what we are looking for...
|
49 | json.sha.should.match /^[a-z0-9]{40}/
|
50 | json.should.containEql
|
51 | type: 'file'
|
52 | path: 'README.md'
|
53 | url: 'https://api.github.com/repos/joyent/node/contents/README.md'
|
54 | html_url: 'https://github.com/joyent/node/blob/master/README.md'
|
55 | git_url: 'https://api.github.com/repos/joyent/node/git/blobs/' + json.sha
|
56 | ```
|
57 |
|
58 | When you run a script, documentation is produced. eg:
|
59 | [Github API Example - Documentation](https://github.com/missinglink/ciao/blob/master/doc/scripts/examples/github-api.md)
|
60 |
|
61 | ---
|
62 |
|
63 | # Writing Scripts
|
64 |
|
65 | Ciao uses a special syntax to declare the start and end of code blocks.
|
66 |
|
67 | Currently 4 interpreter directives are supported:
|
68 |
|
69 | * `#! before` block, this is merged in to every `request` block.
|
70 | * `#> request` block, this is the main http(s) query definition block.
|
71 | * `#? assertion` block, this defines a test case which the `result` should conform to.
|
72 | * `## junk` block, all code in this block will be ignored by the parser.
|
73 |
|
74 | Each directive is followed by a single space and a directive title
|
75 |
|
76 | eg. `#> Contact page is available` defines a `#> request` block with the title `Contact page is available`.
|
77 |
|
78 | The title is used for reporting & documentation, so the better your titles, the easier life will be for you.
|
79 |
|
80 | ---
|
81 |
|
82 | # Installing Ciao
|
83 |
|
84 | To install the most stable `ciao` binary globally on your system via `npm` you can simply:
|
85 |
|
86 | ```bash
|
87 | $ [sudo] npm install -g ciao
|
88 | $ ciao --help
|
89 | ```
|
90 |
|
91 | [![NPM](https://nodei.co/npm/ciao.png?downloads=true&stars=true)](https://nodei.co/npm/ciao)
|
92 |
|
93 | Note: you will need `node` and `npm` installed first.
|
94 |
|
95 | The easiest way to install `node.js` is with [nave.sh](https://github.com/isaacs/nave) by executing `[sudo] ./nave.sh usemain 0.10`
|
96 |
|
97 | ---
|
98 |
|
99 | # Running Scripts
|
100 |
|
101 | ```
|
102 | peter@edgy:/var/www/ciao$ ciao --help
|
103 |
|
104 | Usage: ciao [options] <file ...>
|
105 |
|
106 | Options:
|
107 | -h, --help output usage information
|
108 | -V, --version output the version number
|
109 | -g, --gist [url] load script from github gist
|
110 | -c, --conf [dir] an additional config file to load after ciao.json
|
111 | -s, --silent disable reporters
|
112 | -v, --verbose report full requests and responses on error
|
113 | -d, --documentation [dir] generate documentation in output dir
|
114 | ```
|
115 |
|
116 | ### Running a single script
|
117 |
|
118 | ```bash
|
119 | $ ciao scripts/examples/basic.coffee
|
120 |
|
121 | GET http://www.google.co.uk/ scripts/examples/basic.coffee
|
122 | ✓ Status: 200 OK
|
123 |
|
124 | GET http://www.google.co.uk/ scripts/examples/basic.coffee
|
125 | ✓ Response.body should contain company name
|
126 | ```
|
127 |
|
128 | ### Running all scripts in a directory
|
129 |
|
130 | You can also use ciao on directories to recursively run all scripts.
|
131 |
|
132 | ```bash
|
133 | $ ciao scripts/
|
134 | ```
|
135 |
|
136 | ### Running a gist as a script
|
137 |
|
138 | You can run remote scripts from github by providing the gist suffix or url.
|
139 |
|
140 | ```bash
|
141 | $ ciao --gist missinglink/4678610
|
142 | $ ciao --gist https://gist.github.com/missinglink/4678610
|
143 | ```
|
144 |
|
145 | Note: The way the gist flag behaves has changed since `0.1.8`, please upgrade if you have issues.
|
146 |
|
147 | ---
|
148 |
|
149 | # Requests
|
150 |
|
151 | The ciao request format is the same as that of the `node.js` native http client `http.request`.
|
152 |
|
153 | All `#> request` blocks have access to an object named `config` which contains all the static configuration properties defined in the ciao config. (as discussed below)
|
154 |
|
155 | ### Request properties
|
156 |
|
157 | * `host` A domain name or IP address of the server to issue the request to. Defaults to 'www.example.com'.
|
158 | * `hostname` To support url.parse() hostname is preferred over host
|
159 | * `port` Port of remote server. Defaults to 80.
|
160 | * `method` A string specifying the HTTP request method. Defaults to 'GET'.
|
161 | * `path` Request path. Defaults to '/'. Should include query string if any. E.G. '/index.html?page=12'
|
162 | * `headers` An object containing request headers.
|
163 | * `auth` Basic authentication i.e. 'user:password' to compute an Authorization header.
|
164 | * `body` If body is an object then `JSON.stringify` will be run on it before sending.
|
165 |
|
166 | Full `http.request` reference: http://nodejs.org/api/http.html#http_http_request_options_callback
|
167 |
|
168 | ### Examples
|
169 |
|
170 | ```coffee-script
|
171 | #> Post data to a JSON web service
|
172 | path: '/blog/article'
|
173 | method: 'POST'
|
174 | headers:
|
175 | 'Accept': 'application/json'
|
176 | 'Content-Type': 'application/json'
|
177 | body:
|
178 | title: 'My amazing blog post'
|
179 | body: '@todo'
|
180 | ```
|
181 |
|
182 | ```coffee-script
|
183 | #> Get package details from the npm registry
|
184 | host: 'registry.npmjs.org'
|
185 | path: '/ciao/latest'
|
186 | headers: 'Accept': 'application/json'
|
187 |
|
188 | #? Should have preferGlobal set to true
|
189 | json.preferGlobal.should.be.true
|
190 | ```
|
191 |
|
192 | ---
|
193 |
|
194 | # Assertions
|
195 |
|
196 | You can add assertions to your scripts by including `#? assertion` blocks.
|
197 |
|
198 | Currently `#? assertion` blocks only provide the functionality of the `should` js framework, but I am looking at adding more assertion libraries in the future.
|
199 |
|
200 | Each test case has access to four objects named `title`, `response`, `json` & `$`.
|
201 |
|
202 | * `title` is simply the title specified in the interpreter directive (as discussed above)
|
203 | * `response` contains 3 properties returned by `http.request`
|
204 | * `body` contains the body of the http(s) response.
|
205 | * `statusCode` contains the status code of the http(s) response.
|
206 | * `headers` contains an array of headers that were returned.
|
207 | * `json` the result of parsing the response.body with `JSON.parse` (empty for invalid json).
|
208 | * `$` the result of parsing the response.body with `cheerio` (a familiar jQuery-like API).
|
209 |
|
210 | ### Examples
|
211 |
|
212 | ```coffee-script
|
213 | #? Test the response code
|
214 | response.statusCode.should.equal 200
|
215 |
|
216 | #? Test a header is set
|
217 | response.should.have.header 'server'
|
218 |
|
219 | #? Test a header value
|
220 | response.should.have.header 'server', 'apache'
|
221 |
|
222 | #? Test body contains string
|
223 | response.body.should.containEql 'Bingo Bango Bongo!'
|
224 |
|
225 | #? Test body contains regex
|
226 | response.body.should.match /^[a-z0-9]{40}/
|
227 |
|
228 | #? Test json object contains properties
|
229 | json.should.containEql {
|
230 | id: "10000000000000000000",
|
231 | name: "Bingo Bango Bongo!"
|
232 | }
|
233 |
|
234 | #? Check for a redirect
|
235 | response.should.have.header 'location', 'http://www.example.com/'
|
236 | ```
|
237 |
|
238 | `should.js` reference: https://github.com/visionmedia/should.js/
|
239 |
|
240 | ### Testing the DOM
|
241 |
|
242 | Since version `0.1.8` you can test DOM elements in your source using a jQuery-like syntax.
|
243 |
|
244 | ```coffee-script
|
245 | #> Wikipedia home page
|
246 | host: 'en.wikipedia.org'
|
247 | path: '/wiki/Main_Page'
|
248 |
|
249 | #? Count stylesheets
|
250 | $('link[rel="stylesheet"]').length.should.eql 2
|
251 |
|
252 | #? Page structure
|
253 | $('body.mediawiki > div#mw-page-base').length.should.eql 1
|
254 |
|
255 | #? Check headers are correctly rendered
|
256 | $('span.mw-headline').first().text().should.eql "From today's featured article"
|
257 | $('span.mw-headline').eq(1).text().should.eql "Did you know..."
|
258 | $('span.mw-headline').eq(2).text().should.eql "Today's articles for improvement"
|
259 | $('span.mw-headline').eq(3).text().should.eql "In the news"
|
260 | $('span.mw-headline').eq(4).text().should.eql "On this day..."
|
261 | $('span.mw-headline').last().text().should.eql "Wikipedia languages"
|
262 | ```
|
263 |
|
264 | `cheerio` reference: https://github.com/MatthewMueller/cheerio
|
265 |
|
266 | ---
|
267 |
|
268 | # Project Settings
|
269 |
|
270 | Ciao looks for a project-wide configuration file called `ciao.json` in your current working directory.
|
271 |
|
272 | The `defaults` section is merged in to every request that is made, it's useful for specifying global request properties such as `host` and `port`.
|
273 |
|
274 | The `config` section is useful for storing session tokens or any sort of data you would like available to `#! before` or `#> request` blocks.
|
275 |
|
276 | Example `ciao.json`
|
277 |
|
278 | ```javascript
|
279 | {
|
280 | "defaults": {
|
281 | "host": "www.google.co.uk",
|
282 | "port": 80,
|
283 | "headers": {
|
284 | "User-Agent": "Ciao/Client 1.0"
|
285 | }
|
286 | },
|
287 | "config": {
|
288 | "bingo": "bango"
|
289 | }
|
290 | }
|
291 | ```
|
292 |
|
293 | ## Dynamic Project Settings
|
294 |
|
295 | If you require your settings to be generated before the test suite runs then you may use a file called `ciao.js` or `ciao.coffee` instead of `ciao.json`.
|
296 |
|
297 | This is particularly useful for running `fixtures` or any other `local` or `remote` code before your tests start.
|
298 |
|
299 | Dynamic configurations must export their settings with `module.exports` or an error will be thrown.
|
300 |
|
301 | Note: This feature was introduced in `0.3.1`, please upgrade if you have issues.
|
302 |
|
303 | ---
|
304 |
|
305 | # Generate Documentation
|
306 |
|
307 | Ciao can generate documentation for each `#> request`, the resulting `response` and all `#? assertion` blocks.
|
308 |
|
309 | The documentation is in `markdown` format and is available in the directory specified using the `-d` flag.
|
310 |
|
311 | eg. To generate documentation in `./doc` for all scripts in `./scripts`:
|
312 | ```bash
|
313 | $ ciao -d doc scripts
|
314 | ```
|
315 |
|
316 | An example generated documentation file can be found here:
|
317 | [Github API Example - Documentation](https://github.com/missinglink/ciao/blob/master/doc/scripts/examples/github-api.md)
|
318 |
|
319 | ---
|
320 |
|
321 | ## How it works
|
322 |
|
323 | When parsing `script` & `config` files ciao launches child processes to excute the coffee-script source.
|
324 | This isolates the main thread from malicious code and ensures the fastest execution of tests.
|
325 |
|
326 | All the requests are launched asyncronously using `http.request`.
|
327 |
|
328 | After a `response` comes back from the target server; all `#? assertion` blocks are fired asyncronously in a seperate child process.
|
329 |
|
330 | ## NPM Module
|
331 |
|
332 | The `ciao` npm module can be found here:
|
333 | [https://npmjs.org/package/ciao](https://npmjs.org/package/ciao)
|
334 |
|
335 | ## Github Pages
|
336 |
|
337 | A prettier version of this readme is available here:
|
338 | [http://missinglink.github.com/ciao/](http://missinglink.github.com/ciao/)
|
339 |
|
340 | ## Contributing
|
341 |
|
342 | Please fork and pull request against upstream master on a feature branch.
|
343 |
|
344 | Pretty please; provide unit tests and script fixtures in the `test` and `fixtures` directories.
|
345 |
|
346 | ### Getting Set Up
|
347 |
|
348 | ```bash
|
349 | $ git clone git@github.com:missinglink/ciao.git ciao
|
350 | $ cd ciao
|
351 | $ npm install
|
352 | $ npm test
|
353 | $ ./bin/ciao scripts/examples
|
354 | ```
|
355 |
|
356 | ### Running Unit Tests
|
357 |
|
358 | The unit test suite is run using `mocha`
|
359 |
|
360 | ```bash
|
361 | $ npm test
|
362 | ```
|
363 |
|
364 | ### Continuous Integration
|
365 |
|
366 | Travis tests every release against node versions `0.6` `0.8` & `0.10`
|
367 |
|
368 | [![Build Status](https://travis-ci.org/missinglink/ciao.png?branch=master)](https://travis-ci.org/missinglink/ciao)
|
369 |
|
370 | ### Running Ciao test scripts
|
371 |
|
372 | This will execute all tests in the `./scripts` directory and write documentation in the `./doc` directory.
|
373 |
|
374 | ```bash
|
375 | $ npm run ciao
|
376 | ```
|
377 |
|
378 | ### Known bugs
|
379 |
|
380 | It's early stages yet; there are a bunch of issues reported here:
|
381 | https://github.com/missinglink/ciao/issues
|
382 |
|
383 | Please report everything as it comes up, no matter how small.
|
384 |
|
385 | ### Code review
|
386 |
|
387 | If you would like a code review or to open a feature discussion, please fork and pull request against upstream master.
|
388 |
|
389 | ## Project goals
|
390 |
|
391 | ### Short term
|
392 |
|
393 | * Stability
|
394 | * Cool Functionality
|
395 | * Ease of use
|
396 |
|
397 | ### Mid term
|
398 |
|
399 | * Improved reporters
|
400 | * Improved documentors
|
401 | * Web interface
|
402 |
|
403 | ### Long term
|
404 |
|
405 | * Scheduled builds
|
406 | * Hosted CI solution
|
407 |
|
408 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/missinglink/ciao/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
409 |
|