# dropbox.js Development

Read this document if you want to build `dropbox.js` or modify its source code.
If you want to write applications using dropbox.js, check out the
[Getting Started doc](getting_started.md).

The library is written using [CoffeeScript](http://coffeescript.org/), built
using [cake](http://coffeescript.org/documentation/docs/cake.html), minified
using [uglify.js](https://github.com/mishoo/UglifyJS/), tested using
[mocha](http://visionmedia.github.com/mocha/) and
[chai.js](http://chaijs.com/), and packaged using [npm](https://npmjs.org/).

If you don't "speak" CoffeeScript, [this document](./coffee_faq.md) might
address some of your concerns.


## Dev Environment Setup

Install [node.js](http://nodejs.org/#download) to get `npm` (the node package
manager), then use it to install the libraries required by the test suite.

```bash
git clone https://github.com/dropbox/dropbox-js.git
cd dropbox-js
npm install
```

## Build

Run `npm pack` and ignore any deprecation warnings that might come up.

```bash
npm pack
```

The build output is in the `lib/` directory. `dropbox.js` is the compiled
library that ships in the npm package, and `dropbox.min.js` is a minified
version, optimized for browser apps.

### Documentation

Building the API documentation requires CoffeeScript installed globally.

```bash
npm install -g coffee-script
```

The following command builds the documentation.

```bash
cake doc
```

The documentation can be viewed in any modern browser.

```bash
open doc/index.html
```

By default, the generated documentation does not include private methods. Being
able to browse through these methods can be helpful when writing new code.

```bash
cake devdoc
```

The documentation on `dropbox.com/developers` is generated by the command
below. The output is in `sitedoc/html`.

```bash
cake sitedoc
```


## Test

Install the CoffeeScript npm package globally, so you can type `cake` instead
of `node_modules/coffee-script/bin/cake`.

```bash
npm install -g coffee-script
```

First, you will need to obtain a couple of Dropbox tokens that will be used by
the automated tests.

```bash
cake tokens
```

Re-run the command above if the tests fail due to authentication errors.

Once you have Dropbox tokens, you can run the test suite in node.js, in your
default browser, or as a Chrome application.

```bash
cake test
cake webtest
cake chrometest
```

The library is automatically re-built when running tests, so you don't need to
run `npm pack`. Please run the tests in both node.js and a browser before
submitting pull requests.

The tests store all their data in folders named along the lines of
`js tests.0.ac1n6lgs0e3lerk9`. If tests fail, you might have to clean up these
folders yourself.


### Solving node.js Issues

If the node.js tests exit abruptly, the command below will help zoom in on the
troublesome test.

```bash
LIST=1 cake test
```


### Solving Browser Issues

An easy method to test a browser in a virtual machine is to skip the automated
browser opening.

```bash
BROWSER=false cake webtest
```

A similar method can be used to launch a specific browser.

```bash
BROWSER=firefox cake webtest
```

When fighting a bug, it can be useful to keep the server process running after
the test suite completes, so tests can be re-started with a browser refresh.

```bash
BROWSER=false NO_EXIT=1 cake webtest
```

[Mocha's exclusive tests](http://visionmedia.github.com/mocha/#exclusive-tests)
(`it.only` and `describe.only`) are very useful for quickly iterating while
figuring out a bug.


### Chrome Application / Extension Testing

The tests for Chrome apps / extensions require manual intervention right now.

The `cake chrometest` command will open a Google Chrome instance. The
`dropbox.js Test Suite` application must be clicked.


### Cordova Testing

The Cordova tests run against Android by default.

```bash
cake cordovatest
```

They can be customized to run against any platform.

```bash
CORDOVA_PLATFORM=ios cake cordovatest
```

Some platforms, such as Android, require that an emulator image be configured
and started before running the tests.


### Fully Automated Tests

The test suite opens up the Dropbox authorization page a few times, and also
pops up a page that cannot close itself. dropbox.js ships with a Google Chrome
extension that can fully automate the testing process on Chrome / Chromium.

The extension is written in CoffeeScript, so you will have to compile it.

```bash
cake extension
```

After compilation, have Chrome load the unpacked extension at
`test/chrome_extension` and click on the scary-looking toolbar icon to activate
the extension. The icon's color should turn red, to indicate that it is active.

The extension performs some checks to prevent against attacks. However, you
should still disable the automation (by clicking on the extension icon) when
you're not testing dropbox.js, just in case the extension code has bugs.


### Custom Server

The test suite can be ran against a custom API server. This is only likely to
be useful to Dropbox employees. The steps in this section document the process
of pointing the test suite to a custom server.

First, create two applications on the custom server, configured as follows.

An "App folder" app:
* Type: Dropbox API App
* Store: Files and datastores
* Private folder: Yes
* Name: `Automated Testing Keys`

A "Full Dropbox" app:
* Type: Dropbox API App
* Store: Files and datastores
* Private folder: No
* Type of files: All files
* Name: `Automated Testing Keys (Full Access)`

Both applications should whitelist the following OAuth redirect URLs:
* Node tests: https://localhost:8912/oauth_callback
* Browser tests: https://localhost:8911/test/html/oauth_receiver.html
* Browser tests: https://localhost:8911/test/html/redirect_driver_test.html
* IE VM tests: https://10.0.2.2:8911/test/html/oauth_receiver.html
* IE VM tests: https://10.0.2.2:8911/test/html/redirect_driver_test.html
* Chrome tests: chrome-extension://nibiohflpcgopggnnboelamnhcnnpinm/test/html/chrome_oauth_receiver.html
* Chrome tests: https://nibiohflpcgopggnnboelamnhcnnpinm.chromiumapp.org/
* Cordova tests: https://www.dropbox.com/1/oauth2/redirect_receiver

Second, open `test/config/api.json` in a text editor. Plug in the "Full
Dropbox" application's API key and secret into the `"full"` section, and the
"App folder" application's API key and secret into the `"sandbox"` section.
Change the server URLs to point to the custom server.

After changing the `api.json` file, it might be helpful to ask git to ignore
the changes, so the custom configuration is not accidentally included in a pull
request.

```bash
git update-index --assume-unchanged test/config/api.json
```

Third, obtain API tokens that point to the custom server.

```bash
API_CONFIG=test/config/api.json cake tokens
```

The custom server's URL is embedded in the API tokens, so all future tests will
use the custom server. To get back to using the official Dropbox API server,
re-generate the API tokens.

```bash
cake tokens
```


## Release Process

1. Go to the master branch.

    ```bash
    git checkout master
    ```

1. At the very least, test in node.js and in a browser before releasing.

    ```bash
    cake test
    cake webtest
    ```

1. Bump the version in `package.json`.

1. Publish a new npm package.

    ```bash
    npm publish
    ```

1. Commit and tag the version bump on GitHub.

    ```bash
    git add package.json
    git commit -m "Release X.Y.Z."
    git tag -a -m "Release X.Y.Z" vX.Y.Z
    git push origin master
    git push origin --tags
    ```

1. If you haven't already, go to the
   [cdnjs GitHub page](https://github.com/cdnjs/cdnjs) and fork it.

1. If you haven't already, set up cdnjs on your machine.

    ```bash
    cd ..
    git clone git@github.com:you/cdnjs.git
    cd cdnjs
    git remote add up https://github.com/cdnjs/cdnjs.git
    cd ../dropbox-js
    ```

1. Add the new release to your cdnjs fork.

    ```bash
    cd ../cdnjs
    git checkout master
    git pull up master
    npm install
    git checkout -b dbXYZ
    mkdir ajax/libs/dropbox.js/X.Y.Z
    cp ../dropbox-js/lib/dropbox.* ajax/libs/dropbox.js/X.Y.Z/
    vim ajax/libs/dropbox.js/package.json  # Replace "version"'s value with "X.Y.Z"
    npm test
    git add -A
    git commit -m "Added dropbox.js X.Y.Z"
    git push origin dbXYZ
    ```

1. Go to your cdnjs for on GitHub and open a pull request. Use these examples
of accepted
[major release pull request](https://github.com/cdnjs/cdnjs/pull/735) and
[minor release pull request](https://github.com/cdnjs/cdnjs/pull/753).

1. When the pull request is accepted, merge the master branch into the stable
branch.

    ```bash
    cd ../dropbox-js
    git checkout stable
    git merge --ff-only master
    git push origin master
    ```
