diff --git a/.travis.yml b/.travis.yml
index c3121b0f2..947d971e0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,13 @@
sudo: required
language: node_js
-dist: trusty
+dist: xenial
addons:
firefox: "51.0"
-before_install:
-- export DISPLAY=:99.0
-- sh -e /etc/init.d/xvfb start
+services:
+- xvfb
node_js:
- 8
+- 10
notifications:
slack:
secure: TAq0S0FA/OXtLjmIlJsytzz5WMB5L2QEedW7q+rAhKHg+w9FXOkE9guP72yLe92hKLMAsitD4OSACOtIR3QSSGNden/eKYQEVikCeNKOIO/FoHOrPTkXHfW1/2ihIvOBF2NaEvIGZsjwr12wIewSSM5VrdKwl1skgd0K7CoY/Uw=
diff --git a/appveyor.yml b/appveyor.yml
index 29bb7bbf4..0e548f78d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -2,8 +2,8 @@
environment:
matrix:
# node.js
- - nodejs_version: "6"
- nodejs_version: "8"
+ - nodejs_version: "10"
# Install scripts. (runs after repo cloning)
install:
diff --git a/docMap.json b/docMap.json
new file mode 100644
index 000000000..71fd981e6
--- /dev/null
+++ b/docMap.json
@@ -0,0 +1,343 @@
+{
+ "About": {
+ "src": {
+ "path": "docs/about.md"
+ },
+ "body": "\n## Goals\n\n\n\nDoneJS has three primary goals:\n\n1. To enable developers to easily create high performance, maintainable, highly usable (amazing) applications.\n2. To continually evolve with new techniques and tools.\n3. To support the technology community.\n\n### Amazing Applications\n\nBuilding a modern application is increasingly difficult. Your app\nneeds to look good and run fast on every\nplatform and browser. And, you need to get your app done yesterday.\nNot kinda done. Done done.\n\nHelping you get a high performance, sublimely usable, and maintainable application\ndone fast is DoneJS's primary goal. This is why our logo\nis a browser that looks like a checkered flag. We're committed\nto your release.\n\nWe aim to help in three main ways:\n\n#### 1. Solving difficult technical problems\n\nDoneJS has good solutions for:\n\n - [Building mobile and desktop applications](./Features.html#ios-android-and-desktop-builds)\n - [Server Side Rendering](./Features.html#server-side-rendered)\n - [Automatic real-time updates](./Features.html#real-time-connected)\n - [Fast download times](./Features.html#progressive-loading)\n\nThese are just a few examples from our [features page](./Features.html). If\nthere's a hard problem that you keep running into, we want to solve it.\n\n#### 2. Providing an integrated solution\n\nToo many choices can make decision making difficult. DoneJS simplifies\nmatters by providing a full stack of frontend tooling tested to work\ngreat together. The start of the [features page](./Features.html)\ngoes into detail with examples of this benefit.\n\n_Note: Despite being an integrated solution, you can replace parts of\nDoneJS with alternatives._\n\n\n#### 3. Doing the right thing\n\nWriting tests and documentation, setting up continuous integration and deployment\nisn't fun or easy. DoneJS tries to lower the barrier enough to\nmaking doing the _right thing_ simply part of the normal development cycle.\n\nCheck out what DoneJS does for:\n\n- [Tests](./Features.html#comprehensive-testing)\n- [Documentation](./Features.html#documentation)\n- [Continuous Integration and Deployment](./Features.html#continuous-integration--deployment)\n- [Modlets](./Features.html#modlets)\n- [Generators](./Features.html#generators)\n\n### Evolve\n\nApplication development and maintenance often\nlasts many years. Stability is needed to release complex applications. However,\nnew techniques and best practices are constantly evolving.\n\nDoneJS's goal is to strike a balance between immovable stability and irresistible progress. We do this by evolving frequently, while maintaining backward compatibility between major releases.\n\nIt can be a bumpy road, with lots of little changes. But it\navoids rewrites, resulting in greater productivity: \n\n\n\n\nDoneJS is the successor to JavaScriptMVC. If your project chose JavaScriptMVC in 2007, you would have made a wise decision, giving your team an upgrade path to a modern application for the past 10 years.\n\nWe hope to continue this trend until programs start writing themselves.\n\n### Community\n\nSoftware is better with friends. Our goal is to establish a world-wide\ncommunity with people of all backgrounds and skill levels dedicated to\nteaching, exploring, and innovating.\n\n#### Teaching\n\nTechnology is worth nothing if people don't know how to use it. We want\nto create great learning material, but also create an environment\nwhere people feel comfortable getting help. \n\nThe core team is always available on [Slack](https://www.bitovi.com/community/slack) ([#donejs channel](https://bitovi-community.slack.com/messages/CFC80DU5B))\nand provides [weekly training](https://www.bitovi.com/blog/free-weekly-online-javascript-training). Signup for a [meetup](./community.html) and we will come to your\ncity and teach you DoneJS!\n\n\n#### Exploring\n\nDoneJS has benefited greatly from other projects ideas and technology. It should continue to enhance other communities. \n\nYou can already use many of DoneJS parts with other projects:\n\n - StealJS works great with ReactJS.\n - CanJS works with RequireJS or Browserify.\n - can-connect works on its own.\n\nWe should always seek to cooperate with others.\n\n#### Attract\n\nIf you have the next great JS idea, we want to encourage and help you to build it as part of the DoneJS family. You'll find DoneJS a supportive environment to nurture your ideas. You can even pair with the full-time developers to build out your idea. Reach out to us on\n[Slack](https://www.bitovi.com/community/slack) ([#donejs channel](https://bitovi-community.slack.com/messages/CFC80DU5B))\nor create an issue.\n\n\n## History\n\nDoneJS’s history goes back for almost a decade! Learn why JavaScriptMVC was started and how it evolved into DoneJS.\n\n### Beginning Steps\n\nWe begin [our story](https://forum.javascriptmvc.com/topic/a-brief-history-of-javascriptmvc) in 2007 when Justin Meyer, the CEO of Bitovi, was working for Accenture. He had an idea to build something like [ZoHo Creator](https://creator.zoho.com/home), so you could set up REST services and use an online IDE to write JavaScript apps from those services — you could sell your apps and everything. He called it Scaffold.\n\nHe worked with Brian, a friend from college (who’s now the CTO of Bitovi). Brian quit graduate school so they could start working on it together. They worked on it for about a year and managed to sell it to a few places, but it never really took off. They then started building JavaScript tools for Scaffold to help people write their apps.\n\nTheir initial work was based off a library called [TrimPath](https://code.google.com/archive/p/trimpath/). It had templates, an MVC pattern, etc. They worked with Steve Yen for a little bit, but their client-only focus left them to split of trimpath/trimjunction into what they called JSJunction. Eventually, they didn’t like the name JSJunction and changed it to JavaScriptMVC.\n\nIn JavaScriptMVC’s first release, it had support for things such as:\n\n- Model - View - Controller design pattern\n- History & routing\n- Templates\n- Plugins for filtering, paginating, sorting, etc.\n\nEven in JavaScriptMVC’s early days, Justin knew that [“developers need a repeatable way of building their applications and separating concerns.”](https://groups.google.com/forum/#!searchin/jquery-dev/jQuery$20enterprise/jquery-dev/HsTcpuAmFtY/mN4qFyHw54oJ) When a dev team can work with a standard set of tools and processes, their productivity can greatly increase.\n\nFuncUnit and StealJS both started in 2010, and in 2012 we started splitting JavaScriptMVC into smaller, focused projects, including CanJS, jQuery++, DocumentJS, and DocumentCSS. Then, in 2015, we rebranded JavaScriptMVC to DoneJS and released it to the public.\n\n### Tomorrow's Roadmap\n\nThe following are our highest priority, non-bug-fix features:\n\n- [can-set support sort](https://github.com/canjs/can-set/pull/10)\n- [documentjs configured in package.json](https://github.com/bitovi/documentjs/issues/202)\n- [StealJS dependency injection](https://github.com/stealjs/steal/issues/509)\n- [can-connect supporting other frameworks](https://github.com/canjs/can-connect/issues/42)\n- [Animation utilities](https://github.com/canjs/can-animate)\n- [O(log n) derived list modification](https://github.com/canjs/can-derive)\n- [CanJS Roadmap Discussion](https://forums.bitovi.com/t/canjs-roadmap-discussion/75)\n\n## Team\n\nThe DoneJS family of technologies is built by hundreds of contributors just like you! Our [contributing contribution guide] includes information about reporting bugs, finding ways to contribute, submitting new code, and more!\n\nIf you’d like to take your commitment to DoneJS or its sub-projects to the next level, you can join our core team. To become a part of the core team, you simply have to:\n\n- [Email](mailto:contact@bitovi.com) the core team expressing your interest.\n- Attend the weekly _DoneJS Contributors_ meeting twice a month. [DoneJS Calendar](https://www.google.com/calendar/embed?src=jupiterjs.com_g27vck36nifbnqrgkctkoanqb4%40group.calendar.google.com&ctz=America/Chicago)\n- Make one small contribution, even a spelling correction, each month.\n\n### Core team\n\nThe core team is made up of both part-time and full-time contributors.\n\n
\n \n
Kevin Dillon
\n
\n Kevin is a senior infrastructure engineer at The MathWorks in the Web and Mobile Tools team.\n He focuses on the development of FuncUnit and Syn.\n
\nPrashant is based in Bangalore, India. He likes the understated elegance of CanJS. He also believes DoneJS is a great framework in the making, since it makes technology selection a no-brainer by uniquely offering developers an all-in-one technology stack.\n
\nA 29 old guy from Germany, Julian started coding at the age of 16. Now he freelances with CanJS. He likes the clean structure of Model, Views, and ViewModels.\n
\nMohamed Cherif BOUCHELAGHEM from Algiers, Algeria, almost a server side developer in day work, JavaScript developer after work hours especially using DoneJS/CanJS. He likes to help people to learn and find solutions to issues with DoneJS framework and build applications and code samples that help to show the best from DoneJS/Canjs and learn it faster.\n
\nKevin is based in Chicago (well, close enough). He wants to make it easy for anyone to get started with DoneJS and will work on features that help solve complex problems.\n
\nJustin dances and plays basketball in Chicago. He created JavaScriptMVC and manages the\nDoneJS project, and shouldn't code on it as much as he does.\n
\n\n\n### Sponsors\n\nIf you'd like to support the development of DoneJS, please find available options on our [Patreon page](https://www.patreon.com/donejs). If you have other ideas, or would like to customize your support,\nplease [email us](mailto:contact@bitovi.com).\n\n\n[Bitovi](https://www.bitovi.com/), a JavaScript consulting company, is the primary sponsor of DoneJS.\n\n",
+ "description": " \n\n\nDoneJS' goal is to help the JavaScript community get amazing applications done fast.\nAmazing applications are fast, sublimely usable, and maintainable.\n\nBut times change and new techniques emerge. We strive to adopt these\ntechniques, improve the stack, and provide a simple upgrade path along the way.\n\nWe are part of a community that helps developers of all skill levels and\nbackgrounds learn the technology, excel at it, and accomplish their\ngoals.\n\nLearn about the goals, history, roadmap, and team behind DoneJS.\n\n",
+ "name": "About",
+ "type": "page",
+ "parent": "DoneJS",
+ "hideSidebar": true,
+ "outline": {
+ "depth": 2,
+ "tag": "ol"
+ },
+ "comment": " "
+ },
+ "survey": {
+ "src": {
+ "path": "docs/survey.md"
+ },
+ "body": "\n__We want to hear from you.__ What do you love and hate about CanJS, DoneJS, and\nStealJS? What can the core team work on to make you grow fonder of these\nprojects?\n\n
\n\nProvide your email address (and optionally your GitHub username) above and\nyou’ll be signed up for our survey:\n\n- You’ll receive an email about\n[every six weeks](https://calendar.google.com/calendar/embed?src=jupiterjs.com_g27vck36nifbnqrgkctkoanqb4%40group.calendar.google.com)\nwith a link to the survey.\n- Each survey will be about five questions and take just a few minutes to complete.\n- An opt-out/unsubscribe link will be included in each email.\n\n
\n\nWe will look at every single response and use it to prioritize what the team\nworks on in the coming months. Short of [hiring us](https://www.bitovi.com/contact)\nto work on something in particular, __this is the best way to have a direct impact\non our priorities.__\n\n
\n
Watch the discussion below to learn more about each item on the survey:
\n \n
\n\n[Read more about the survey in our announcement blog post.](https://www.bitovi.com/blog/help-us-improve-canjs-stealjs-and-the-rest-of-the-donejs-family)\nIf you have any questions, please don’t hesitate to ask on\n[our forums](https://forums.bitovi.com/),\n[Slack](https://www.bitovi.com/community/slack) ([#donejs channel](https://bitovi-community.slack.com/messages/CFC80DU5B)), or\n[Twitter](https://twitter.com/donejs)\n\n\n \n The core team thanks you for participating in our survey!\n\n\n",
+ "description": "Help us improve CanJS, StealJS, and the rest of the DoneJS family by taking a short email survey every six weeks.\n\n",
+ "name": "survey",
+ "title": "Community Survey",
+ "type": "page",
+ "parent": "DoneJS",
+ "hideSidebar": true,
+ "comment": " "
+ },
+ "Apis": {
+ "src": {
+ "path": "docs/apis.md"
+ },
+ "body": "\n## Application flow overview\n\nLets talk about how the typical behavior of a DoneJS application works. We'll use\nthe chat application as an example in development. We'll cover what happens when:\n\n - A user navigates their browser from a different domain to `https://chat.donejs.com/`\n - A user navigates from `https://chat.donejs.com/` to another `https://chat.donejs.com/chat`.\n\n\n### First page load\n\n1. An http request for `https://chat.donejs.com/` is sent to a node server. The node server is configured,\n in this case with express, to use [done-ssr-middleware](#done-ssr) to render a DoneJS application:\n\n ```js\n var ssr = require('done-ssr-middleware');\n\n app.use('/', ssr());\n ```\n\n2. [done-ssr](#done-ssr) uses [steal](#stealjs) to load the application's main module which results in loading the\n entire application. Loading the application only happens once for all page requests.\n\n A DoneJS's main module is specified where all configuration of a DoneJS application happens, its `package.json`.\n The main module is usually a [can-stache](#canstache) template processed with the [done-autorender](#done-autorender)\n plugin. The module name is specified like: `index.stache!done-autorender`. `index.stache` might look like:\n\n ```html\n \n \n Codestin Search App\n \n \n \n \n\n {{pageComponent}}\n\n \n \n \n ```\n\n The [done-autorender](#done-autorender) plugin, in NodeJS, exports this template so it can be rendered.\n\n3. Once [done-ssr](#done-ssr) has the [done-autorender](#done-autorender)'s `template` and `viewModel` export it:\n\n 1. Creates a new instance of the viewModel, setting properties on it\n using [can-route](#canroute)'s routing rules. \n 2. Creates a new [virtual DOM](#can-simple-dom) instance.\n 3. Renders the [template](#canstache) with the `viewModel` into the `virtual DOM` instance.\n 4. [done-autorender](#done-autorender) templates waits for all promises to complete\n before providing a final result. Once the template is finished rendering, [done-ssr](#done-ssr) converts it to a\n string and sends it back to the browser.\n 5. The browser downloads the page's HTML, which includes a `\n ```\n\n In development, this loads `steal.js` which then loads `index.stache` and processes it with\n the `done-autorender`. \n\n6. In the browser, `done-autorender`:\n\n 1. Creates a new instance of the [viewModel](#canmap), setting properties on it\n using [can-route](#canroute)'s routing rules. \n 2. Renders the [template](#canstache) with the `viewModel` into a document fragment.\n 3. Once all asynchronous activity has completed, it replaces the document with the rendered result.\n\n### Pushstate change\n\n1. A pushstate is triggered by user action, usually by clicking a link. [can-route](#canroute)'s routing rules determines the properties set on the application [viewModel](#canmap).\n\n ```js\n route.register('{page}', { page: 'home' });\n ```\n\n2. [done-autorender](#done-autorender) previously bound the AppViewModel to [can-route](#canroute) which causes any change in the route to be reflected in the ViewModel instance.\n\n3. Live binding causes the initial template to reflect in the change in route. If the new route is `/chat` it will cause the `page` to be **chat**:\n\n ```html\n \n \n Codestin Search App\n \n \n \n \n\n {{pageComponent}}\n\n \n \n \n ```\n\n## CLI and Generators\n\nAfter installing DoneJS globally with `npm install donejs -g` you will have the `donejs` command available on the command line. It lets you initialize a new application and - when navigating within a DoneJS project - run scripts provided locally by your application. Within your application folder the `donejs` command is a convenience wrapper for the functionality described below and you can also get a list of all commands by running\n\n```\ndonejs help\n```\n\n### npm scripts\n\n[npm scripts](https://docs.npmjs.com/misc/scripts) are defined in the `scripts` section of your applications `package.json`. There are some standard scripts that every Node application uses (like `npm start` or `npm test` - both of which are already set up for you) and you can add your own which is what DoneJS does with commands like `npm run develop` or `npm run build`.\nThe `donejs` command makes running those commands easier by allowing you to run them like `donejs start`, `donejs develop` or `donejs build`\n\n### Generators\n\n`donejs add` lets you run the [Yeoman](http://yeoman.io/) generators provided by [generator-donejs](https://github.com/donejs/generator-donejs/). Currently the following generators are available:\n\n- `donejs add app [folder]` which will initialize a new application (optionally within the given folder)\n- `donejs add component ` to create a new can-component\n- `donejs add supermodel ` to generate a new model\n- `donejs add plugin [folder]` which will initialize a new plugin project\n- `donejs add generator [folder]` which will initialize a new generator project\n\n### Third-party generators\n\nIf `donejs add` can’t find a built-in generator, e.g. when running `donejs add mygenerator`, DoneJS will try to install the `donejs-mygenerator` package from npm and run the Yeoman generators it provides. This is how we can enable a desktop application build of the application by simply running:\n\n```\ndonejs add electron\n```\n\nWhich will install the [donejs-electron](https://github.com/donejs/donejs-electron) package and then run its generator, which initializes everything you need. This also works for adding a mobile application build using [donejs-cordova](https://github.com/donejs/donejs-cordova) like this:\n\n```\ndonejs add cordova\n```\n\nThis way you can use DoneJS’s growing list of plugins and generators without having to add anything to your application that you don't use.\n\n## StealJS\n\nThe base of any good JavaScript application is its dependency management system. \nDoneJS uses [StealJS](https://stealjs.com/) which\nitself is split into two sub-projects:\n\n- `steal` - loads CommonJS, ES6, and AMD modules. It can also load styles, templates and more.\n- `steal-tools` - builds your application's modules for production and also provides hot-module-swapping.\n\n### steal\n\nTo use [steal](https://stealjs.com/docs/steal.html), simply add a script tag to `steal.js`\nin an HTML page or in a [done-autorender](#done-autorender) `template` and\npoint the `main` attribute to a module to load like:\n\n```html\n\n```\n\nUsing the default DoneJS [system.directories.lib](https://stealjs.com/docs/npm.html#configuration) configuration, this will load\n`my-app/src/my-module.js`. From there, use CommonJS, ES6, or AMD to load your modules:\n\n```js\n// my-app/src/my-module.js\nimport $ from \"jquery\";\nimport \"./styles.css\";\n\n$('body')\n```\n\nIf an `import`, `require` or `define` module reference ends with `\"/\"`, is a shorthand\nfor importing a module in the modlet format. The moduleName imported is the same\nas the module reference, but with the last folder name added again.\n\nSome examples:\n\n```js\n// in components/person module.\nimport \"can-component\"; //imports \"can-component\";\nimport \"./edit/\"; // imports \"components/person/edit/edit\";\n```\n\nConfigure [steal](https://stealjs.com/docs/steal.html)'s behavior in your `package.json` in the `steal` object like:\n\n```js\n// package.json\n{\n \"main\": \"index.stache!done-autorender\",\n ...\n \"steal\": {\n \"meta\": {\n \"ui/core\": {\n \"deps\": [\n \"jquery\",\n \"theme/core.css\",\n \"theme/theme.css\"\n ]\n }\n }\n }\n}\n```\n\n### steal-tools\n\nIn DoneJS applications, [steal-tools](https://stealjs.com/docs/steal-tools.html) is primarily used to:\n\n - [build](https://stealjs.com/docs/steal-tools.build.html) and minify your application to production-ready bundles.\n - add [hot module swapping](https://stealjs.com/docs/steal-tools.cmd.live-reload.html)\n\nIt can also be used to [export](https://stealjs.com/docs/steal-tools.export.html) your\nmodules to different formats.\n\nDoneJS comes with a `build.js` script that call's steal-tools' [build](https://stealjs.com/docs/steal-tools.build.html):\n\n```js\n//build.js\nvar stealTools = require(\"steal-tools\");\n\nvar buildPromise = stealTools.build({\n config: __dirname + \"/package.json!npm\"\n}, {\n bundleAssets: true\n});\n```\n\nThis is already configured to run with:\n\n```\n> donejs build\n```\n\nBut you could also run it with:\n\n```\n> node build.js\n```\n\nHot module swapping is done with [live-reload](https://stealjs.com/docs/steal-tools.cmd.live-reload.html) which\nis bundled within steal-tools. \n\nBy default `donejs develop` starts the live-reload server. However, you could start one\nyourself with:\n\n```\n> steal-tools live-reload\n```\n\n## CanJS\n\nCanJS provides:\n\n- __observables__ with [can-map](#canmap), [can-list](#canlist), and [can-compute](#cancompute).\n- __one-way and two-way binding templates__ with [can-stache](#canstache) and [can-stache-bindings](#canviewbindings).\n- __custom elements__ with [can-component](#cancomponent).\n- __routing__ with [can-route](#canroute).\n\nObservables act as the `ViewModel` and part of the `Model`.\n\nOne-way and two-way binding templates act as the `View`.\n\n[can-component](#cancomponent) is used to combine `View` and `ViewModel` into\neasy to instantiate and assemble custom elements.\n\nCheckout the following quick examples of their use:\n\n__observables__:\n\n```js\n// Observable objects:\nvar person = new DefineMap({first: \"Justin\", last: \"Meyer\"});\n\n// Observable arrays:\nvar hobbies = new DefineList([\"basketball\", \"hip-hop dancing\"]);\n\n// Observable single values:\nvar age = compute(33);\n\n// Observable computed values:\nvar info = compute(function(){\n return person.first + \" \" + person.last + \" is \" +\n \tage() + \" and likes \" + hobbies.join(\",\") + \".\";\n});\n\n// Get the compute's value\ninfo() //-> Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\n\n// Listen to changes in the compute\ninfo.bind(\"change\", function(ev, newValue){\n newValue //-> Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\n});\n\nhobbies.pop(); // causes `change` event above\n```\n\n__one and two-way binding templates__:\n\n```js\n// Programmatically create a template\n// `value:bind` cross binds the input's value\n// to `first` in the scope.\nvar template = stache(\"
{{first}}
\"+\n\t\"\");\n\n// Create observable data for the template\nvar person = new DefineMap({first: \"Payal\"});\n\n// Render the template with data\nvar frag = template(person);\n\n// Add the result to the document\ndocument.body.appendChild(frag);\n\n// Document shows rendered result\ndocument.body //->
Payal
\n\n// ... User changes the input's value to \"Ramiya\" ...\n\n// Document is updated with changes\ndocument.body //->
Ramiya
\n```\n\n__custom elements__:\n\n```js\n// Create a custom `can-define/map/map` constructor function\n// with a helper function.\nvar PersonEditViewModel = DefineMap.extend({\n first: \"string\",\n last: \"string\",\n fullName: function(){\n return this.first + \" \" + this.last;\n }\n});\n\n// Create a template that will be rendered within\n// `` elements.\nvar template = stache(`\n Update {{fullName}}:\n\t\n\t\n`);\n\n// Create the `` element with the specified\n// viewModel and template (view).\nComponent.extend({\n tag: \"person-edit\",\n ViewModel: PersonEditViewModel,\n view: view\n});\n\n// Use that custom element within another template.\n// `first.bind` cross binds ``'s\n// `first` property to `firstName` in the scope.\nvar parentTemplate = stache(`\n
{{firstName}} {{lastName}}
\n \n`);\n\n// Render the parent template with some data:\nvar frag = parentTemplate(new DefineMap({\n firstName: \"Brian\",\n lastName: \"Moschel\"\n}));\n\ndocument.body.appendChild(frag);\n```\n\n### can-define/map/map\n\n[can-define](https://canjs.com/doc/can-define.html) is used to create observable\nJavaScript Object-like objects. Create an instance of the\nbase can-define/map/map like:\n\n```js\nvar person = new DefineMap({first: \"Justin\", last: \"Meyer\"});\n```\n\nRead or write a `map`'s properties:\n\n```js\nperson.first //-> Justin\n\nperson.first = \"Ramiya\";\nperson.get() //-> {first: \"Ramiya\", last: \"Meyer\"}\n\nperson.first = \"Brian\";\nperson.last = \"Moschel\";\nperson.get() //-> {first: \"Brian\", last: \"Moschel\"}\n```\n\nBind to changes in a person's properties with [.on](https://canjs.com/doc/can-define/map/map.prototype.on.html):\n\n```js\nperson.on(\"first\", function(ev, newValue, oldValue){\n newValue //-> \"Laura\"\n oldvalue //-> \"Brian\"\n});\n\n// changing `first` causes the function\n// call above.\nperson.first = \"Laura\";\n```\n\nExtend a `DefineMap` to create a new constructor function. This is\nvery useful for creating Models and View Models:\n\n```js\n// pass extend an object of prototype values\nvar Person = DefineMap.extend({\n first: \"string\",\n last: \"string\",\n fullName: function(){\n person.first + \" \" + person.last;\n }\n})\n\nvar me = new Person({first: \"Kathrine\", last: \"Iannuzzi\"});\nme.fullName() //-> \"Kathrine Iannuzzi\"\n```\n\nThe [can-define](https://canjs.com/doc/can-define.html) allows\nyou to control the behavior of attributes. You can define\n[default values](https://canjs.com/doc/can-define.types.value.html),\n[getters](https://canjs.com/doc/can-define.types.get.html),\n[setters](https://canjs.com/doc/can-define.types.set.html), and\n[type](https://canjs.com/doc/can-define.types.type.html) converters.\n\n```js\nvar Todo = DefineMap.extend({\n percentComplete: {\n default: 0.1,\n type: \"number\",\n get: function(value){\n return \"\"+value+\"%\"\n },\n set: function(newValue){\n return newValue*100;\n }\n }\n});\n\nvar todo = new Todo();\ntodo.percentComplete //-> 10%\n```\n\nYou can even describe asynchronous behavior which is critical for working\nwith service data:\n\n```js\nvar Todo = DefineMap.extend({\n ownerId: \"number\",\n owner: {\n get: function(lastSetValue, resolve){\n User.get({id: this.ownerId}).then(resolve);\n }\n }\n});\n\ntodo = new Todo({ownerId: 5});\n\n// async values only become valid when bound\n// this isn't a problem because templates usually bind for you\ntodo.on(\"owner\", function(ev, owner){\n owner //-> a User instance\n});\n```\n\n\n### can-define/list/list\n\n[can-define/list/list](https://canjs.com/doc/can-define/list/list.html) is used to create observable\nJavaScript Array-like objects. Create an instance of the\nbase `DefineList` like:\n\n```js\nvar hobbies = new DefineList([\"basketball\",\"dancing\"]);\n```\n\nRead and write items from the list or to read the length:\n\n```js\nfor(var i = 0, len = hobbies.length; i < len; i++){\n var hobby = hobbies.get(i);\n}\nhobbies.set(1, \"hip hop dancing\");\nhobbies.get() //-> [\"basketball\", \"dancing\"]\n```\n\nUse array methods like [.push](https://canjs.com/doc/can-define/list/list.prototype.push.html), [.pop](https://canjs.com/doc/can-define/list/list.prototype.pop.html), and [.splice](https://canjs.com/doc/can-define/list/list.prototype.splice.html) to modify the array:\n\n```js\nhobbies.pop();\n\nhobbies.generated() //-> [\"basketball\"];\n\nhobbies.push(\"football\");\n\nhobbies //-> DefineList[\"basketball\",\"football\"]\n```\n\nUse [.forEach](https://canjs.com/doc/can-define/list/list.prototype.forEach.html), [.map](https://canjs.com/doc/can-define/list/list.prototype.map.html), or [.filter](https://canjs.com/doc/can-define/list/list.prototype.filter.html) to loop through the array. All\nthese methods return a `DefineList`\n\n```js\nvar intramurals = hobbies.map(function(hobby){\n return \"intramural \"+hobby;\n})\nintramurals //-> DefineList[\"intramural basketball\",\n \"intramural football\"]\n```\n\nListen to when a list changes by binding on `add` or `remove` or `length`\nevents.\n\n```js\nhobbies.on(\"add\", function(ev, newHobbies, index){\n console.log(\"added\", newHobbies,\"at\", index);\n })\n .on(\"remove\", function(ev, removedHobbies, index){\n console.log(\"removed\", newHobbies,\"at\", index);\n })\n .on(\"length\", function(ev, newVal, oldVal){\n console.log(\"length is\", newVal);\n });\n\nhobbies.splice(1,1,\"pumpkin carving\",\"gardening\");\n // console.logs:\n // removed [football] 1\n // added [\"pumpkin carving\",\"gardening\"] 1\n // length is 3\n```\n\n\nBy default, if you initialize a list with plain JavaScript objects,\nthose objects are converted to a `DefineMap`:\n\n```js\nvar people = new DefineList([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.get(0).first //-> Justin\n```\n\nYou can create your own custom `DefineList` constructor functions\nby extending `DefineList`:\n\n```js\nvar People = DefineList.extend({\n seniors: function(){\n return this.filter(function(person){\n return person.age >= 65\n });\n }\n});\n\nvar people = new People([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.seniors() //-> People[{Justin}]\n```\n\nWhen extending `DefineList` you can specify the default `Map` type\nthat's created when plain JS objects are added to the list:\n\n```js\nvar Person = can.Map.extend({\n fullName: function(){\n person.first + \" \" + person.last;\n }\n});\n\nvar People = DefineList.extend({\n \"#\": Person\n},{\n seniors: function(){\n return this.filter(function(person){\n return person.age >= 65\n });\n }\n});\n\nvar people = new People([\n {first: \"Justin\", last: \"Meyer\", age: 72},\n {first: \"David\", last: \"Luecke\", age: 20},\n {first: \"Matthew\", last: \"Phillips\", age: 30}\n]);\n\npeople.get(0).fullName() //-> \"Justin Meyer\"\n```\n\n### can-compute\n\n[can-compute](https://canjs.com/doc/can-compute.html) isn't used\ndirectly much anymore. However, it's used heavily in [can-define](#candefine)\n[getters](https://canjs.com/doc/can-define.types.get.html) and live binding\nso it's worth understanding the basics.\n\n`can-compute` allows you to define single observable values like:\n\n```js\nvar age = compute(33);\n```\n\nor derived values like:\n\n```js\nvar person = new DefineMap({first: \"Justin\", last: \"Meyer\"}),\n hobbies = new DefineList([\"basketball\", \"hip-hop dancing\"]);\n\nvar info = compute(function(){\n return person.first + \" \" + person.last + \" is \" +\n \tage() + \" and likes \" + hobbies.join(\",\") + \".\";\n});\n```\n\nRead a compute by calling it like a function:\n\n```js\ninfo() //-> \"Justin Meyer is 33 and likes\\\n // basketball, hip-hop dancing.\"\n```\n\nListen to a compute by binding on its `change` event:\n\n```js\ninfo.on(\"change\", function(ev, newVal, oldVal){\n console.log(\"IS:\\n\",newVal,\"\\nWAS:\\n\", oldVal);\n})\n```\n\nInternally, `on` runs the compute function, identifying what observable\nvalues it reads, and listening to them. It caches the return result so that\nreading the compute again like `info()` just returns the cached result.\n\nWhen any of the read observables change, it updates the cached value,\nand calls back any event handlers:\n\n```js\nperson.first = \"Brian\";\nperson.last = \"Moschel\";\n\n// console.logs:\n// IS:\n// Brian Moschel is 33 and likes basketball, hip-hop dancing.\n// WAS:\n// Justin Meyer is 33 and likes basketball, hip-hop dancing.\n```\n\n### can-stache\n\n[can-stache](https://canjs.com/doc/can-stache.html) is a Handlebars and\nMustache compliant live-binding templating language.\n\nCreate a template programmatically with `can-stache` like:\n\n```js\nvar template = stache(\"
{{first}} {{last}}
\");\n```\n\n`template` is a __renderer__ function that, when called with observable data,\nreturns a [DocumentFragment](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) that is updated when the observable data changes.\n\nAdd those fragments to the page to see the result:\n\n```js\nvar person = new DefineMap({first: \"Brian\", last: \"Moschel\"})\n\nvar frag = template(person);\n\ndocument.body.appendChild(frag);\n\ndocument.body //->
\n```\n\nIn a DoneJS application, templates are used primarily as part of\na [can-component](#cancomponent) or as the [done-autorender](#done-autorender)ed main template.\n\nWhen used in a [can-component](#cancomponent), the templates are often put in their own file. For\nexample, a `person_edit.js` component file might have a `person_edit.stache` file like:\n\n```js\n// person_edit.stache\nUpdate {{fullName}}:\n\n\n```\n\nThis template's __renderer__ function is imported in `person_edit.js` like:\n\n```js\n// person_edit.js\nimport template from \"./person_edit.stache\";\nimport Component from \"can-component\";\n\nComponent.extend({\n tag: \"person-edit\",\n template: template\n});\n```\n\n`can-stache` template behavior is controlled by what's\nwithin magic tags like `{{ }}`. There are different tag types, lots of\nhelper functions, and different ways to call methods and functions.\n\nThere's too much to cover so we will highlight the important APIs.\n\nThe different tag types:\n\n - [{{key}}](https://canjs.com/doc/can-stache.tags.escaped.html) -\n inserts an escaped value.\n\n ```js\n stache(\"{{key}}\")({key: \"Foo\"}) //-> `<b>Foo</b>`\n ```\n\n - [{{{key}}}](https://canjs.com/doc/can-stache.tags.unescaped.html) -\n inserts an unescaped value.\n\n ```js\n stache(\"{{key}}\")({key: \"Foo\"}) //-> `Foo`\n ```\n\n- [{{#key}} ... {{/key}}](https://canjs.com/doc/can-stache.tags.section.html) -\n renders a subsection depending on the value of the key.\n\n ```js\n // boolean values render the subsection or its inverse\n stache(\"{{#key}}A{{/key}}\")({key: true}) //-> `A`\n stache(\"{{#key}}A{{/key}}\")({key: false}) //-> ``\n stache(\"{{#key}}A{{else}}B{{/key}}\")({key: false}) //-> `B`\n\n // iterative values render the subsection for each value\n stache(\"{{#key}}A{{/key}}\")({key: [null,0]}) //-> `AA`\n stache(\"{{#key}}A{{/key}}\")({key: []}) //-> ``\n\n ```\n\n The subsection is rendered with the `key` value as the top of the [scope](https://canjs.com/doc/can-view-scope.html):\n\n ```js\n stache(\"{{#key}}{{child}}{{/key}}\")({key: {child:\"C\"}}) //->`C`\n ```\n\n- [{{^key}} ... {{/key}}](https://canjs.com/doc/can-stache.tags.inverse.html) -\n opposite of `{{#key}}`.\n\n ```js\n stache(\"{{^key}}A{{/key}}\")({key: true}) //-> ``\n stache(\"{{^key}}A{{/key}}\")({key: false}) //-> `A`\n stache(\"{{^key}}A{{/key}}\")({key: [null,0]}) //-> ``\n\n stache(\"{{^key}}A{{else}}B{{/key}}\")({key: false}) //-> `B`\n ```\n\nThe following are stache's most commonly used helpers:\n\n - [{{#if expr}} .. {{/if}}](https://canjs.com/doc/can-stache.helpers.if.html) - renders the subsection if the expr is truthy.\n\n ```js\n stache(\"{{#if key}}A{{/if}}\")({key: true}) //-> `A`\n stache(\"{{#if key}}A{{/if}}\")({key: false}) //-> ``\n\n stache(\"{{#if key}}A{{else}}B{{/if}}\")({key: false}) //-> `B`\n ```\n\n - [{{#is expr1 expr2}} ... {{/is}}](https://canjs.com/doc/can-stache.helpers.is.html) - compares two expressions and renders a subsection depending on the result.\n\n ```js\n stache(\"{{#is page 'A'}}A{{/is}}\")({page: 'A'}) //-> `A`\n stache(\"{{#is page 'A'}}A{{/is}}\")({page: 'B'}) //-> ``\n\n stache(\"{{#is page 'A'}}A{{else}}C{{/is}}\")({page: 'C'}) //-> `B`\n ```\n\n - [{{#each key}} ... {{/each}}](https://canjs.com/doc/can-stache.helpers.each.html) - renders a subsection for each item in a key's value.\n\n ```js\n stache('{{#each hobbies}}
{{.}}
{{/each}}')(['Hockey', 'Hiking']) //-> `
Hockey
Hiking
`\n ```\n\n If the value of a key is a [DefineList](#section=section_definelist) only the minimum amount of DOM updates occur when the list changes.\n\n - [{{routeUrl hashes}}](https://canjs.com/doc/can-stache/helpers/route.html) - generates a url using [can-route](#canroute) for the provided hashes.\n\n ```js\n stache(\"{{name}}\")({name: 'Item 23'}) //-> `Item 23`\n ```\n\n[Call methods](https://canjs.com/doc/can-stache.expressions.html#Callexpressions) in your scope like: `{{method(value)}}`\n\n```js\nstache('
\"\n```\n\n### can-stache-bindings\n\n`can-stache-bindings` allows you to bind to viewModel or DOM events and create one-way or two-way bindings on element's properties/attributes, can-component viewModels and `can-stache`'s scope.\n\nCreate a one-way binding from the parent scope to a child's properties/attributes or viewModel:\n\n- [childProp:from=\"value\"](https://canjs.com/doc/can-stache-bindings.toChild.html) - One-way bind `name` in the scope to `userName` property on the viewModel or the `value` attribute on the `input` element.\n\n\n ```html\n \n\n \n ```\n\nCreate a one-way binding from the child's properties/attributes or viewModel to the parent scope:\n\n- [childProp:to=\"name\"](https://canjs.com/doc/can-stache-bindings.toParent.html) - One-way bind the value of `userName` property on the viewModel or the `value` attribute on the `input` element to the `name` property in the parent scope.\n\n ```html\n \n\n \n ```\n\nCreate two-way bindings between the parent scope and the child's viewModel or property/attributes:\n\n- [propName:bind=\"value\"](https://canjs.com/doc/can-stache-bindings.twoWay.html) - Two-way bind the value of `userName` property in the viewModel or `value` attribute on the `input` element to the `name` in the parent scope.\n\n ```html\n \n\n \n ```\n\nCreate bindings to viewModel or DOM events:\n\n- [on:EVENT=\"handler()\"](https://canjs.com/doc/can-stache-bindings.event.html) - Listen to the DOM event or viewModel `EVENT` and use `handler` as the event handler.\n\nListen to the `click` event emitted by a DOM element:\n\n ```html\n
\n ```\n\nListen to the `show` event emitted by the viewModel, `vm`:\n\n ```html\n \n ```\n\n### can-component\n\n[can-component](https://canjs.com/doc/can-component.html) lets you\ncreate widgets with well-defined View Models and are instantiated with\ncustom elements.\n\nDefine a `can-component` by extending one with a `tag` name, [can-define](#candefine) `viewModel` and\n[can-stache template](#canstache) like:\n\n```js\n// Define the view model\nvar HelloViewModel = DefineMap.extend({\n excitedMessage: function(){\n return this.attr(\"message\")+\"!\"\n }\n});\n\nComponent.extend({\n tag: \"hello-world\",\n ViewModel: HelloViewModel,\n view: stache(\"
{{excitedMessage}}
\")\n});\n```\n\nTo instantiate this component so it says `Hello World!`, add\na `` element to the page like:\n\n```html\n\n```\n\nUse [can-stache-bindings](#canstachebindings)\nto send a value from the `can-stache` scope like:\n\n```js\n// a `DefineMap` that will be available in the scope\nvar appViewModel = new DefineMap({\n greeting: \"Howdy Planet\"\n});\n\nvar template = stache('');\n\nvar frag = template(appViewModel);\n\nfrag //-> \n //
Howdy Planet!
\n // \n```\n\n`can-component`s are usually built as [modlets](./Features.html#modlets),\nmeaning their template and styles are another file and imported:\n\n```js\n// hello-world.js\nimport Component from 'can-component';\nimport Map from 'can-define/map/map';\nimport './hello-world.less';\nimport view from './hello-world.stache';\n\nexport const ViewModel = Define.extend({\n message: \"string\",\n excitedMessage: function(){\n return this.message+\"!\"\n }\n});\n\nexport default Component.extend({\n tag: \"hello-world\",\n ViewModel: ViewModel,\n view\n});\n```\n\nSome components are so small, they they don't require three\nseparate files. For these, you can use a `.component` file:\n\n```html\n\n\">\n \n \n
{{excitedMessage}}
\n \n \n import DefineMap from 'can-define/map/map';\n\n export default DefineMap.extend({\n message: \"string\",\n excitedMessage: function(){\n return this.message+\"!\"\n }\n });\n \n\n```\n\n### can-route\n\n[can-route](https://canjs.com/doc/can-route.html) provides powerful 2-way, nested, routing to your application, supporting both hash and [pushstate](https://canjs.com/doc/can-route-pushstate.html).\n\nConfigure routing rules to define property values on your application's\nView Model when a url is matched.\n\n\nThe following sets the application ViewModel's `page` property\nto `\"chat\"` when the url looks like `/chat`:\n\n```js\nroute.register(\"{page}\");\n```\n\nYou can define defaults that get set when `{page}` is empty. The\nfollowing sets the default `page` property to `\"home\"`.\n\n```js\nroute.register(\"{page}\", { page: \"home\" });\n```\n\nYou can specify multiple properties to set for a given url:\n\n```js\nroute.register(\"{page}/{slug}\");\nroute.register(\"{page}/{slug}/{action}\");\n```\n\n\nUpdate the url by changing `can-route`:\n\n```js\nroute.attr(\"page\", \"restaurants\");\n// location.href -> \"/restaurants\"\n```\n\nOr change `route` by modifying the url:\n\n```js\nhistory.pushState(null, null, \"/\");\n// route.attr(\"page\"); // -> \"home\"\n```\n\nIn a DoneJS application can.route is bound to the [application View Model](#candefine), but you can connect `can-route` to other\nmaps:\n\n```js\nvar DefineMap = require(\"can-define/map/map\");\n\nvar AppViewModel = DefineMap.extend({\n ...\n});\n\nvar viewModel = new AppViewModel();\n\nroute.data = viewModel;\n```\n\nWhich will cause any changes in the route to reflect in the View Model instance, and any changes in the View Model instance to reflect in the route.\n\n## Data Layer APIs\n\n\n### can-realtime-rest-model\n\n[can-realtime-rest-model](https://canjs.com/doc/can-realtime-rest-model.html) is used to connect typed\ndata to backend services. In a DoneJS application, that typed data is a\n[can-define/map/map](#candefine) and [can-define/list/list](#candefinelistlist) type.\n\nTo make a simple connection to a restful interface:\n\n```js\n// First, create custom Map and List type\nvar Todo = DefineMap.extend({\n ownerId: \"number\",\n canComplete: function(ownerId) {\n return this.ownerId === ownerId;\n }\n});\n\nvar TodoList = DefineList.extend({\n \"*\": Todo\n},{\n incomplete: function(){\n return this.filter(function(todo){\n return !todo.complete;\n });\n }\n});\n\n// Then, make a connection with the right behaviors and options.\nvar todoConnection = realtimeRestModel({\n Map: Todo,\n List: TodoList,\n url: \"/services/todos\"\n});\n```\n\nThis adds a [getList](https://canjs.com/doc/can-connect/can/map/map.getList.html),\n[.get](https://canjs.com/doc/can-connect/can/map/map.get.html),\n[.save](https://canjs.com/doc/can-connect/can/map/map.prototype.save.html) and\n[.destroy](https://canjs.com/doc/can-connect/can/map/map.prototype.destroy.html) methods to\n`Todo` allowing you to CRUD `Todo`s and `TodoList`s from the service layer like:\n\n```js\n// Get a list of todos\nTodo.getList({due: \"today\"}).then(function(todos){ ... });\n\n// Get a single todo\nTodo.get({id: 5}).then(function(todo){ ... });\n\n// Create a todo\nvar todo = new Todo({name: \"dishes\"})\n\n// Create it on the server\ntodo.save().then(function(todo){\n\n // Update its properties\n todo.name = \"Do the dishes\";\n // Update the service layer with changes\n todo.save().then(function(todo){\n\n // Delete the todo on the service layer\n todo.destroy();\n });\n});\n```\n\n`can-connect` comes with a wide variety of behaviors that\ncan be mixed into a connection. Examples include:\n\n- [real-time](https://canjs.com/doc/can-connect/real-time/real-time.html) keeps `can.List`s updated with changes.\n- [fall-through-cache](https://canjs.com/doc/can-connect/fall-through-cache/fall-through-cache.html)\n\nTo make the process of creating `can.Map` based connections easier,\nDoneJS comes with a [supermodel generator](#generators)\ncreates a [super-map](https://canjs.com/doc/can-connect/can/super-map/super-map.html).\n\nA realtime rest model is just a connection with a bunch of the mostly commonly used\nbehaviors. Create one with the `superMap` function like:\n\n```js\nexport const messageConnection = realtimeRestModel({\n url: \"/services/todos\",\n Map: Todo,\n List: TodoList,\n name: 'todo'\n});\n```\n\n### can-query-logic\n\n[can-query-logic](https://canjs.com/doc/can-query-logic.html) is used to define the rules of an API service, in order to compare queries that are represented by the parameters commonly passed\nto service requests.\n\n\nFor example, if you want all todos for user `5` that are complete, you\nmight call:\n\n```js\nTodo.getList({ filter: { userId: 5, complete: true } })\n```\n\n`{userId: 5, complete: true}` represents a set. Using\n`can-query-logic` we can compare it to other sets. The following\nreturns `true` because `{userId: 5, complete: true}` represents\na subset of `{userId: 5}`.\n\n```js\nqueryLogic.isSubset({filter:{userId: 5, complete: true}}, {userId: 5}); // -> true\n```\n\nBehind the scenes can-query-logic uses `can-set` which can perform more complex logic with custom [set Algebras](https://github.com/canjs/can-set#setalgebra).\n\nThe following creates a set-algebra that is able to combine ranges:\n\n```js\n// Create a set Algebra\nvar algebra = new set.Algebra(\n set.comparators.rangeInclusive(\"start\",\"end\"));\n\n// use it\nalgebra.union({start: 1, end: 10},\n {start: 11, end: 20}) //-> {start: 1, end: 20}\n```\n\nIn a DoneJS application, you create custom query logics to pass to [realtime rest model](https://canjs.com/doc/can-realtime-rest-model.html) connections. The\nconnection's behaviors use that [querylogic](https://canjs.com/doc/can-query-logic.html) to their optimizations.\n\n## Testing APIs\n\n### QUnit\n\n[QUnit](https://qunitjs.com/) is DoneJS's default JavaScript unit testing framework. It is provided for DoneJS by the [steal-qunit](https://github.com/stealjs/steal-qunit) project. A basic unit test for a can.Component view-model looks like this:\n\n```js\nimport QUnit from 'steal-qunit';\nimport { ViewModel } from 'my/component/';\n\n// ViewModel unit tests\nQUnit.module('my/component');\n\nQUnit.test('Has message', function(){\n var vm = new ViewModel();\n QUnit.equal(vm.message, 'This is the my-component component');\n});\n```\n\nWhile the generators create QUnit tests by default you can switch your own tests easily to [Jasmine](https://github.com/stealjs/steal-jasmine) or [Mocha](https://github.com/stealjs/steal-mocha).\nTo use Mocha instead for the previous view-model example we just need to install the wrapper with\n\n```\nnpm install steal-mocha --save-dev\nnpm install assert --save-dev\n```\n\nAnd then change the test file to:\n\n```js\nimport mocha from 'steal-mocha';\nimport assert from 'assert';\nimport { ViewModel } from 'my/component/';\n\nmocha.setup('bdd');\n\n// ViewModel unit tests\ndescribe('my/component', function() {\n it('Has a message', function() {\n var vm = new ViewModel();\n assert.equal(vm.message, 'This is the my-component component');\n });\n});\n```\n\n### FuncUnit\n\n[FuncUnit](https://funcunit.com/) enhances QUnit, Mocha or Jasmine and enables them to simulate user actions, easily test asynchronous behavior, and support black box testing. It uses a jQuery-like syntax to write functional or unit tests. When generating an application, DoneJS already includes a basic FuncUnit smoke-test which runs alongside the other tests. It looks like this:\n\n```js\nimport F from 'funcunit';\nimport QUnit from 'steal-qunit';\n\nF.attach(QUnit);\n\nQUnit.module('my-app functional smoke test', {\n beforeEach() {\n F.open('../development.html');\n }\n});\n\nQUnit.test('my-app main page shows up', function() {\n F('title').text('my-app', 'Title is set');\n});\n```\n\nThis will open the main application (`development.html` is the HTML file that loads our DoneJS app without server-side-rendering) and ensures that the `Codestin Search App\n\n\n \n\n