http://git-wip-us.apache.org/repos/asf/couchdb/blob/c14b2991/share/www/fauxton/src/test/mocha/testUtils.js ---------------------------------------------------------------------- diff --git a/share/www/fauxton/src/test/mocha/testUtils.js b/share/www/fauxton/src/test/mocha/testUtils.js new file mode 100644 index 0000000..f9643e8 --- /dev/null +++ b/share/www/fauxton/src/test/mocha/testUtils.js @@ -0,0 +1,50 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +define([ + "chai", + "sinon-chai", + "underscore" +], +function(chai, sinonChai) { + chai.use(sinonChai); + + var ViewSandbox = function () { + this.initialize(); + }; + + _.extend(ViewSandbox.prototype, { + initialize: function () { + this.$el = $('<div style="display:none"></div>').appendTo('body'); + this.$ = this.$el.find; + }, + views: [], + renderView: function (view) { + this.views.push(view); + this.$el.append(view.el); + view.render(); + }, + + remove: function () { + _.each(this.views, function (view) { + view.remove(); + }, this); + } + }); + + return { + chai: chai, + assert: chai.assert, + ViewSandbox: ViewSandbox + }; +}); +
http://git-wip-us.apache.org/repos/asf/couchdb/blob/c14b2991/share/www/fauxton/src/test/runner.html ---------------------------------------------------------------------- diff --git a/share/www/fauxton/src/test/runner.html b/share/www/fauxton/src/test/runner.html new file mode 100644 index 0000000..2eeb27f --- /dev/null +++ b/share/www/fauxton/src/test/runner.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<!-- + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +--> +<html> + <head> + <meta charset="utf-8"> + <title>testrunnner Fauxton</title> + <link rel="stylesheet" href="mocha/mocha.css" /> + </head> + <body> + <div id="mocha"></div> + <script type="text/javascript" src="mocha/mocha.js"></script> + <script type="text/javascript" src="mocha/sinon.js"></script> + <script type="text/javascript"> + // MOCHA SETUP + mocha.setup('bdd'); + mocha.reporter('html'); + </script> + <script data-main="./test.config.js" src="../assets/js/libs/require.js"></script> + </body> +</html> http://git-wip-us.apache.org/repos/asf/couchdb/blob/c14b2991/share/www/fauxton/src/test/test.config.underscore ---------------------------------------------------------------------- diff --git a/share/www/fauxton/src/test/test.config.underscore b/share/www/fauxton/src/test/test.config.underscore new file mode 100644 index 0000000..dda16f2 --- /dev/null +++ b/share/www/fauxton/src/test/test.config.underscore @@ -0,0 +1,15 @@ +// vim: set ft=javascript: +// Set the require.js configuration for your test setup. +require.config( +<%= JSON.stringify(configInfo, null, '\t') %> +); + +require([ + <% _.each(testFiles, function (test) {%> + '../<%= test %>', + <% }) %> +], function() { + if (window.mochaPhantomJS) { mochaPhantomJS.run(); } + else { mocha.run(); } +}); + http://git-wip-us.apache.org/repos/asf/couchdb/blob/c14b2991/share/www/fauxton/src/writing_addons.md ---------------------------------------------------------------------- diff --git a/share/www/fauxton/src/writing_addons.md b/share/www/fauxton/src/writing_addons.md new file mode 100644 index 0000000..08f44fc --- /dev/null +++ b/share/www/fauxton/src/writing_addons.md @@ -0,0 +1,173 @@ +# Addons +Addons allow you to extend Fauxton for a specific use case. Addons will usually +have the following structure: + + * templates/ + * my_addon.html - _underscore template fragments_ + * base.js - _entry point to the addon_ + * resources.js - _models and collections of the addon_ + * routes.js - _URL routing for the addon_ + * views.js - _views that the model provides_ + + [optional] + * assets/less + * my_addon.less + +## Generating an addon +We have a `grunt-init` template that lets you create a skeleton addon, +including all the boiler plate code. Run +`./node_modules/.bin/grunt-init tasks/addon` and answer the questions +it asks to create an addon: + + $ ./node_modules/.bin/grunt-init tasks/addon + path.existsSync is now called `fs.existsSync`. + Running "addon" task + + Please answer the following: + [?] Add on Name (WickedCool) SuperAddon + [?] Location of add ons (app/addons) + [?] Do you need an assets folder?(for .less) (y/N) + [?] Do you need to make any changes to the above before continuing? (y/N) + + Created addon SuperAddon in app/addons + + Done, without errors. + +Once the addon is created add the name to the settings.json file to get it +compiled and added on the next install. + +## Routes and hooks +An addon can insert itself into fauxton in two ways; via a route or via a hook. + +### Routes +An addon will override an existing route should one exist, but in all other +ways is just a normal backbone route/view. This is how you would add a whole +new feature. + +### Hooks +Hooks let you modify/extend an existing feature. They modify a DOM element by +selector for a named set of routes, for example: + + var Search = new FauxtonAPI.addon(); + Search.hooks = { + // Render additional content into the sidebar + "#sidebar-content": { + routes:[ + "database/:database/_design/:ddoc/_search/:search", + "database/:database/_design/:ddoc/_view/:view", + "database/:database/_:handler"], + callback: searchSidebar + } + }; + return Search; + +adds the `searchSidebar` callback to `#sidebar-content` for three routes. + +## Hello world addon +First create the addon skeleton: + + ± bbb addon + path.existsSync is now called `fs.existsSync`. + Running "addon" task + + Please answer the following: + [?] Add on Name (WickedCool) Hello + [?] Location of add ons (app/addons) + [?] Do you need to make any changes to the above before continuing? (y/N) + + Created addon Hello in app/addons + + Done, without errors. + +In `app/addons/hello/templates/hello.html` place: + + <h1>Hello!</h1> + +Next, we'll defined a simple view in `resources.js` (for more complex addons +you may want to have a views.js) that renders that template: + + define([ + "app", + "api" + ], + + function (app, FauxtonAPI) { + var Resources = {}; + + Resources.Hello = FauxtonAPI.View.extend({ + template: "addons/hello/templates/hello" + }); + + return Resources; + }); + + +Then define a route in `routes.js` that the addon is accessible at: + + define([ + "app", + "api", + "addons/hello/resources" + ], + + function(app, FauxtonAPI, Resources) { + var HelloRouteObject = FauxtonAPI.RouteObject.extend({ + layout: "one_pane", + + crumbs: [ + {"name": "Hello","link": "_hello"} + ], + + routes: { + "_hello": "helloRoute" + }, + + selectedHeader: "Hello", + + roles: ["_admin"], + + apiUrl:'hello', + + initialize: function () { + //put common views used on all your routes here (eg: sidebars ) + }, + + helloRoute: function () { + this.setView("#dashboard-content", new Resources.Hello({})); + } + }); + + Resources.RouteObjects = [HelloRouteObject]; + + return Resources; + + }); + + + + +Then wire it all together in base.js: + + define([ + "app", + "api", + "addons/hello/routes" + ], + + function(app, FauxtonAPI, HelloRoutes) { + + HelloRoutes.initialize = function() { + FauxtonAPI.addHeaderLink({title: "Hello", href: "#_hello"}); + }; + + return HelloRoutes; + }); + +Once the code is in place include the add on in your `settings.json` so that it +gets included by the `require` task. Your addon is included in one of three +ways; a local path, a git URL or a name. Named plugins assume the plugin is in +the fauxton base directory, addons with a git URL will be cloned into the +application, local paths will be copied. Addons included from a local path will +be cleaned out by the clean task, others are left alone. + +**TODO:** addons via npm module
