├── .bowerrc ├── .editorconfig ├── .ember-cli ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── .watchmanconfig ├── LICENSE ├── README.md ├── blueprints └── ember-cordova │ └── index.js ├── bower.json ├── config └── ember-try.js ├── docs └── cli.md ├── ember-cli-build.js ├── index.js ├── lib ├── .jshintrc ├── commands │ ├── -command.js │ ├── build.js │ ├── cordova.js │ ├── index.js │ ├── init.js │ ├── lint-index.js │ ├── make-icons.js │ ├── make-splashes.js │ ├── open.js │ ├── platform.js │ ├── plugin.js │ ├── prepare.js │ ├── proxy.js │ └── serve.js ├── tasks │ ├── -task.js │ ├── bash.js │ ├── cordova-build.js │ ├── cordova-raw.js │ ├── create-cordova-project.js │ ├── create-livereload-shell.js │ ├── ember-build.js │ ├── lint-index.js │ ├── open-app.js │ ├── prepare.js │ ├── run-hook.js │ ├── serve.js │ ├── setup-webview.js │ ├── update-gitignore.js │ ├── update-watchman-config.js │ └── validate │ │ ├── allow-navigation.js │ │ ├── cordova-installed.js │ │ ├── location-type.js │ │ ├── platform.js │ │ ├── plugin.js │ │ ├── root-url.js │ │ └── sanitize-addon-args.js ├── templates │ └── livereload-shell │ │ └── index.html └── utils │ ├── command-exists.js │ ├── cordova-assets.js │ ├── cordova-path.js │ ├── cordova-validator.js │ ├── create-gitkeep.js │ ├── edit-xml.js │ ├── ember-cordova-error.js │ ├── fs-utils.js │ ├── get-added-platforms.js │ ├── get-cordova-config.js │ ├── get-last-command.js │ ├── get-network-ip.js │ ├── get-project-type.js │ ├── init-project.js │ ├── logger.js │ ├── open-app-command.js │ ├── parse-cordova-build-opts.js │ ├── parse-xml.js │ ├── run-validators.js │ └── string.js ├── node-tests ├── .eslintrc.js ├── .jshintrc ├── fixtures │ └── ember-cordova-mock │ │ ├── analytics.js │ │ ├── app │ │ └── index.html │ │ ├── dist │ │ └── .gitkeep │ │ ├── ember-cordova │ │ ├── .gitignore │ │ ├── cordova │ │ │ ├── config.xml │ │ │ └── plugins │ │ │ │ ├── fetch.json │ │ │ │ └── ios.json │ │ └── hooks │ │ │ ├── hook-promise-rejected.js │ │ │ ├── hook-promise-resolved.js │ │ │ ├── hook-with-error.js │ │ │ ├── hook-with-options.js │ │ │ └── hook.js │ │ ├── package.json │ │ └── project.js ├── helpers │ └── expect.js └── unit │ ├── blueprint │ └── index-test.js │ ├── commands │ ├── build-test.js │ ├── command-test.js │ ├── init-test.js │ ├── lint-index-test.js │ ├── make-icons-test.js │ ├── make-splashes-test.js │ ├── open-test.js │ ├── platform-test.js │ ├── plugin-test.js │ ├── prepare-test.js │ ├── proxy-test.js │ └── serve-test.js │ ├── index-test.js │ ├── lint-test.js │ ├── tasks │ ├── bash-test.js │ ├── cordova-build-test.js │ ├── cordova-raw-test.js │ ├── create-cordova-project-test.js │ ├── create-cordova-shell-test.js │ ├── ember-build-test.js │ ├── lint-index-test.js │ ├── open-app-test.js │ ├── prepare-test.js │ ├── run-hook-test.js │ ├── setup-webview-test.js │ ├── update-gitignore-test.js │ ├── update-watchman-config-test.js │ └── validate │ │ ├── allow-navigation-test.js │ │ ├── cordova-installed-test.js │ │ ├── location-type-test.js │ │ ├── platform-test.js │ │ ├── plugin-test.js │ │ ├── root-url-test.js │ │ └── sanitize-addon-args-test.js │ └── utils │ ├── cordova-assets-test.js │ ├── cordova-validator-test.js │ ├── create-gitkeep-test.js │ ├── edit-xml-test.js │ ├── get-added-platforms-test.js │ ├── get-project-type-test.js │ ├── init-project-test.js │ └── parse-cordova-build-opts-test.js ├── package.json ├── public ├── .gitkeep └── cordova.js ├── tests ├── .jshintrc ├── dummy │ ├── app │ │ ├── app.js │ │ ├── components │ │ │ └── .gitkeep │ │ ├── controllers │ │ │ └── .gitkeep │ │ ├── helpers │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── models │ │ │ ├── .gitkeep │ │ │ ├── child.js │ │ │ └── parent.js │ │ ├── resolver.js │ │ ├── router.js │ │ ├── routes │ │ │ └── .gitkeep │ │ ├── styles │ │ │ └── app.css │ │ └── templates │ │ │ ├── application.hbs │ │ │ └── components │ │ │ └── .gitkeep │ ├── config │ │ └── environment.js │ └── public │ │ ├── crossdomain.xml │ │ └── robots.txt ├── helpers │ ├── destroy-app.js │ ├── module-for-acceptance.js │ ├── resolver.js │ └── start-app.js ├── index.html └── test-helper.js └── yarn.lock /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "analytics": false 4 | } 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.hbs] 17 | insert_final_newline = false 18 | 19 | [*.{diff,md}] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.ember-cli: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | Ember CLI sends analytics information by default. The data is completely 4 | anonymous, but there are times when you might want to disable this behavior. 5 | 6 | Setting `disableAnalytics` to true will prevent any data from being sent. 7 | */ 8 | "disableAnalytics": false 9 | } 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | tmp/* 2 | node_modules/* 3 | blueprints/**/files/**/*.js 4 | tests/fixtures/* 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | // ht ember-cli 3 | 4 | module.exports = { 5 | root: true, 6 | plugins: [ 7 | 'chai-expect', 8 | ], 9 | extends: 'eslint:recommended', 10 | env: { 11 | browser: false, 12 | node: true, 13 | }, 14 | globals: { 15 | }, 16 | rules: { 17 | /*** Possible Errors ***/ 18 | 19 | 'comma-dangle': 0, 20 | 21 | // JSHint "boss" 22 | 'no-cond-assign': [2, 'except-parens'], 23 | 24 | 'no-console': 0, 25 | 26 | // JSHint "debug", disabled already in .jshintrc 27 | 'no-debugger': 0, 28 | 29 | // JSHint "noempty", JSCS "disallowEmptyBlocks" 30 | 'no-empty': 2, 31 | 32 | 33 | /*** Best Practices ***/ 34 | // line-break at 80 35 | 'max-len': [2, { "ignoreUrls": true }], 36 | 37 | // JSHint "curly" 38 | 'curly': 2, 39 | 40 | // JSHint "eqeqeq" 41 | 'eqeqeq': 2, 42 | 43 | // JSHint "forin", disabled already in .jshintrc 44 | 'guard-for-in': 0, 45 | 46 | // JSHint "noarg" 47 | 'no-caller': 2, 48 | 49 | // JSHint "eqnull" 50 | 'no-eq-null': 2, 51 | 52 | // JSHint "evil" 53 | 'no-eval': 2, 54 | 55 | // JSHint "nonew", disabled already in .jshintrc 56 | 'no-new': 0, 57 | 58 | // JSHint "expr" 59 | 'no-unused-expressions': [2, { 60 | allowShortCircuit: true, 61 | allowTernary: true, 62 | }], 63 | 64 | // JSHint "immed", disabled already in .jshintrc 65 | 'wrap-iife': 0, 66 | 67 | 'yoda': 2, 68 | 69 | 70 | /*** Strict Mode ***/ 71 | 72 | // JSHint "strict" 73 | 'strict': [0, 'global'], 74 | 75 | 76 | /*** Variables ***/ 77 | 78 | // JSHint "undef" 79 | 'no-undef': 2, 80 | 81 | // JSHint "unused" 82 | 'no-unused-vars': [2, { 'args': 'none' }], 83 | 84 | // JSHint "latedef" 85 | 'no-use-before-define': [2, 'nofunc'], 86 | 87 | 88 | /*** Stylistic Issues ***/ 89 | 90 | // JSHint "camelcase" 91 | 'camelcase': 2, 92 | 93 | 'eol-last': 2, 94 | 95 | // JSHint "indent" 96 | 'indent': [2, 2, { 97 | 'SwitchCase': 1, 98 | 'VariableDeclarator': { 'var': 2, 'let': 2, 'const': 3 } 99 | }], 100 | 101 | 'keyword-spacing': 2, 102 | 103 | // JSHint "laxbreak" 104 | 'linebreak-style': [2, 'unix'], 105 | 106 | // JSHint "newcap 107 | 'new-cap': [2, { 108 | properties: false, 109 | }], 110 | 111 | // JSHint "plusplus", disabled already in .jshintrc 112 | 'no-plusplus': 0, 113 | 114 | // JSHint "trailing" 115 | 'no-trailing-spaces': 2, 116 | 117 | 'no-unneeded-ternary': 2, 118 | 'space-before-blocks': 2, 119 | 'space-in-parens': 2, 120 | 'space-infix-ops': 2, 121 | 'space-unary-ops': 2, 122 | 123 | // JSHint "quotmark" 124 | 'quotes': [2, 'single'], 125 | 126 | 127 | /*** chai-expect ***/ 128 | 129 | 'chai-expect/missing-assertion': 2, 130 | 'chai-expect/terminating-properties': 2, 131 | 'chai-expect/no-inner-compare': 2 132 | }, 133 | }; 134 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | !/dist/.keep 6 | /tmp 7 | 8 | # dependencies 9 | /node_modules 10 | /bower_components/* 11 | 12 | # misc 13 | /.sass-cache 14 | /connect.lock 15 | /coverage/* 16 | /libpeerconnection.log 17 | npm-debug.log 18 | testem.log 19 | .idea 20 | 21 | ember-cordova/tmp-livereload 22 | ember-cordova/cordova/www/* 23 | !ember-cordova/cordova/www/.gitkeep 24 | ember-cordova/cordova/plugins/* 25 | !ember-cordova/cordova/plugins/.gitkeep 26 | ember-cordova/cordova/platforms/* 27 | !ember-cordova/cordova/platforms/.gitkeep 28 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6, 3 | 4 | "predef": [ 5 | "document", 6 | "window", 7 | "-Promise" 8 | ], 9 | "browser": true, 10 | "boss": true, 11 | "curly": true, 12 | "debug": false, 13 | "devel": true, 14 | "eqeqeq": true, 15 | "evil": true, 16 | "forin": false, 17 | "immed": false, 18 | "laxbreak": false, 19 | "newcap": true, 20 | "noarg": true, 21 | "noempty": false, 22 | "nonew": false, 23 | "nomen": false, 24 | "onevar": false, 25 | "plusplus": false, 26 | "regexp": false, 27 | "undef": true, 28 | "sub": true, 29 | "strict": false, 30 | "white": false, 31 | "eqnull": true, 32 | "esnext": true, 33 | "unused": true, 34 | "moz": true 35 | } 36 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /bower_components 2 | /config/ember-try.js 3 | /dist 4 | /tests 5 | /tmp 6 | **/.gitkeep 7 | .bowerrc 8 | .editorconfig 9 | .ember-cli 10 | .gitignore 11 | .eslintrc.js 12 | .watchmanconfig 13 | .travis.yml 14 | bower.json 15 | ember-cli-build.js 16 | testem.js 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7" 4 | - "6" 5 | - "8" 6 | 7 | sudo: false 8 | 9 | cache: 10 | directories: 11 | - node_modules 12 | 13 | matrix: 14 | fast_finish: true 15 | 16 | before_install: 17 | - npm config set spin false 18 | - npm install -g bower phantomjs-prebuilt 19 | 20 | install: 21 | - npm install 22 | - bower install 23 | 24 | script: 25 | - node_modules/.bin/ember try:each --skip-cleanup 26 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Isle of Code Inc 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ember Cordova 2 | 3 | [![Build Status](https://travis-ci.org/isleofcode/ember-cordova.svg?branch=master)](https://travis-ci.org/isleofcode/ember-cordova) 4 | 5 | ## corber 6 | 7 | We have migrated ember-cordova to the corber project, which adds support for Vue/React/Webpack apps. Ember users will see no feature loss after migration. 8 | 9 | Most new features will appear in corber, however we will continue bugfixes in ember-cordova. 10 | 11 | We encourage you to migrate to corber.io. This repository is a fork of the last stable ember-cordova release. 12 | 13 | Announcement details can be found [here](http://blog.isleofcode.com/announcing-corber-ember-cordova-vue/), the repository [here](https://github.com/isleofcode/corber) and documentation [here](http://corber.io). 14 | 15 | ## ember-cordova 16 | ember-cordova simplifies building Cordova applications with Ember.js. 17 | 18 | Included is a CLI, icon generation & plugins/platforms, bindings to the Cordova platform and a growing ecosystem of Cordova plugins built to work with Ember. It is maintained by Isle of Code in Toronto, with a community of contributors. 19 | 20 | It supports Ember 1.13+ and node per [Ember Node LTS Support](http://emberjs.com/blog/2016/09/07/ember-node-lts-support.html) 21 | 22 | Given upstream changes in ember-cli, support for ember-cordova stops at 2.13.x. High versions of ember-cli are supported with corber. If you'd like to resolve that issue in ember-cordova, [this corber issue is a good starting point](https://github.com/isleofcode/corber/issues/391). 23 | 24 | ## Quickstart 25 | 26 | `ember install ember-cordova` 27 | 28 | For documentation, please visit [embercordova.com](http://embercordova.com). 29 | 30 | ## Contributing 31 | 32 | PRs are very welcome. You can read our style guides [here](https://github.com/isleofcode/style-guide). 33 | 34 | If you are unsure about your contribution idea, please feel free to 35 | open an Issue for feedback. 36 | 37 | ## Credits 38 | 39 | ember-cordova is maintained by [Isle of Code](https://isleofcode.com), and started as a fork of [ember-cli-cordova](https://github.com/poetic/ember-cli-cordova). 40 | -------------------------------------------------------------------------------- /blueprints/ember-cordova/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var initProject = require('../../lib/utils/init-project'); 4 | var chalk = require('chalk'); 5 | 6 | module.exports = { 7 | name: 'ember-cordova', 8 | 9 | availableOptions: [ 10 | { 11 | name: 'name', 12 | type: String 13 | }, { 14 | name: 'cordovaid', 15 | type: String 16 | }, { 17 | name: 'template-path', 18 | type: String 19 | } 20 | ], 21 | 22 | fileMapTokens: function() { 23 | return { 24 | __root__: function() { return '/'; } 25 | }; 26 | }, 27 | 28 | normalizeEntityName: function() { 29 | // h/t mirage 30 | // this prevents an error when the entityName is 31 | // not specified (since that doesn't actually matter 32 | // to us 33 | }, 34 | 35 | /* eslint-disable max-len */ 36 | afterInstall: function(options) { 37 | console.log(chalk.yellow( 38 | 'The ember-cordova project is migrating to corber.io, ' + 39 | 'an extension of ember-cordova with added support for Vue/React. \n \n' + 40 | 41 | 'Ember users will see no loss of features by migrating. Details:' + 42 | 'http://blog.isleofcode.com/announcing-corber-ember-cordova-vue/ \n \n' + 43 | 44 | 'We will continue fixing ember-cordova bugs, however must new features will apply to corber. \n' 45 | )); 46 | 47 | return initProject(options, this.project, this.ui); 48 | } 49 | /* eslint-enable max-len */ 50 | }; 51 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-cordova", 3 | "dependencies": {} 4 | } 5 | -------------------------------------------------------------------------------- /config/ember-try.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true*/ 2 | 3 | module.exports = function() { 4 | return { 5 | command: "./node_modules/.bin/mocha --harmony --compilers js:babel-register 'node-tests/**/*-test.js'", 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /docs/cli.md: -------------------------------------------------------------------------------- 1 | ## CLI 2 | 3 | All commands follow the pattern `ember cordova:{command}`. You can use the `cdv` alias 4 | insted of`cordova`, for example `ember cdv:{command}`. 5 | 6 | You can pass a command to cordova without 7 | ember-cordova interference with ember cdv build, vs. ember cdv:build. 8 | 9 | ### Available Commands 10 | * ember cdv:open 11 | * ember cdv:build 12 | * ember cdv:link (DEPRECATED) 13 | * ember cdv:platform 14 | * ember cdv:plugin 15 | * ember cdv:prepare 16 | * ember cdv:serve 17 | * ember cordova 18 | 19 | ### Open 20 | 21 | #### Description 22 | 23 | Open the native platform project with the default or specified application 24 | 25 | #### Available options 26 | + platform (default:ios) 27 | + application (default:system default application) 28 | 29 | #### Examples 30 | + `ember cordova:open` 31 | + `ember cordova:open --platform=android --application=eclipse` 32 | 33 | 34 | ### Build 35 | 36 | #### Description 37 | 38 | Build the ember and cordova project together running in the simulator or on a device 39 | 40 | #### Available options 41 | + environment (default:development) 42 | + platform (default:ios) 43 | + release (default: debug) 44 | + cordova-output-path (default: ember-cordova/cordova/www) 45 | 46 | #### Examples 47 | + `ember cordova:build` 48 | + `ember cordova:build --environment=production --platform=ios` 49 | + `ember cordova:build --environment=production --platform=ios --release` 50 | 51 | ### Link 52 | 53 | DEPRECATED 54 | 55 | ### Platform 56 | 57 | #### Description 58 | Add or remove cordova platforms. Use the save flag to persist new 59 | platforms to config.xml (default is true). 60 | 61 | ### Aliases 62 | + add/a 63 | + remove/rm/r 64 | 65 | #### Available options 66 | + save (default:true) 67 | 68 | #### Examples 69 | + `ember cdv:platform add ios` 70 | + `ember cdv:platform remove ios` 71 | 72 | ### Plugin 73 | 74 | #### Description 75 | Add or remove cordova plugins. Use the save flag to persist new 76 | platforms to config.xml (default is true). 77 | 78 | ### Aliases 79 | + add/a 80 | + remove/rm/r 81 | 82 | #### Available options 83 | + save (default:true) 84 | 85 | #### Examples 86 | + `ember cdv:plugin add cordova-plugin-name` 87 | + `ember cdv:plugin rm cordova-plugin-name` 88 | 89 | ### Prepare 90 | 91 | #### Description 92 | Runs cordova prepare, but also fires beforePrepare/afterPrepare hooks. 93 | 94 | If plugins or platforms have been installed to a project with ember 95 | cdv:plugin/platform add foo, running ember cdv:prepare installs these 96 | packages on a fresh clone. 97 | 98 | Think of the usage similar to package.json /w npm install. 99 | 100 | #### Examples 101 | + `ember cordova:prepare` 102 | 103 | ### Serve 104 | 105 | #### Description 106 | 107 | Runs the Ember Server for live reload. To learn more, [read 108 | here](livereload.md). 109 | 110 | #### Available options 111 | + platform (default:ios) 112 | + reloadUrl (default:localhost:4200) 113 | + cordova-output-path (default: ember-cordova/cordova/www) 114 | 115 | #### Examples 116 | + `ember cdv:serve` 117 | + `ember cordova:serve --platform=android --reloadUrl=192.168.1.1` 118 | + `ember cdv:serve --platform=browser --env "development"` 119 | 120 | ## Cordova 121 | 122 | #### Description 123 | 124 | Passes commands straight to cordova, without interference. 125 | 126 | Because this proxies to cordova-cli, you will need cordova-cli installed 127 | (this is not required for usage anywhere else). 128 | 129 | If you do not already have it installed, you can install it with: 130 | 131 | ``` 132 | npm install -g cordova 133 | ``` 134 | 135 | Our hope is you won't need this command very much. If you are, open 136 | an issue and tell us. 137 | 138 | #### Examples 139 | + `ember cordova info` 140 | 141 | #### Troubleshooting 142 | When running a proxy command, file paths are relative to 143 | your cordova directory. 144 | 145 | So for example, if you for reasons unkwown run `ember cdv plugin add ../local-plugin-path` 146 | (hint: just use `ember cdv:plugin add ../local-plugin-path`), from your 147 | ember projects root, it will probably fail. You most likely need `ember 148 | cordova plugin add ../../../local-plugin-path`. 149 | 150 | ## Configuration / Defaults 151 | 152 | If you find yourself needing to override CLI defaults, you can set 153 | new defaults in your .ember-cli file. 154 | 155 | e.g. If you are only ever building for one (android), or want to 156 | set a permanent default reload-url. 157 | 158 | in .ember-cl: 159 | ``` 160 | platform: 'android', 161 | reloadUrl: 'http://mycomputer:4200' 162 | ``` 163 | -------------------------------------------------------------------------------- /ember-cli-build.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); 3 | 4 | module.exports = function(defaults) { 5 | var app = new EmberAddon(defaults, { 6 | // Add options here 7 | }); 8 | 9 | /* 10 | This build file specifies the options for the dummy test app of this 11 | addon, located in `/tests/dummy` 12 | This build file does *not* influence how the addon or the app using it 13 | behave. You most likely want to be modifying `./index.js` or app's build file 14 | */ 15 | 16 | return app.toTree(); 17 | }; 18 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var commands = require('./lib/commands'); 4 | var getNetworkIp = require('./lib/utils/get-network-ip'); 5 | var cordovaPath = require('./lib/utils/cordova-path'); 6 | var cordovaAssets = require('./lib/utils/cordova-assets'); 7 | 8 | var mergeTrees = require('broccoli-merge-trees'); 9 | var Funnel = require('broccoli-funnel'); 10 | 11 | module.exports = { 12 | name: 'ember-cordova', 13 | 14 | contentFor: function(type) { 15 | if (this.project.targetIsCordova && type === 'body') { 16 | return ''; 17 | } 18 | }, 19 | 20 | includedCommands: function() { 21 | return commands; 22 | }, 23 | 24 | _mergeTrees: function(trees) { 25 | return mergeTrees(trees); 26 | }, 27 | 28 | //In Livereload scenarios, we need to manually include cordova assets 29 | cordovaAssetTree: function(tree) { 30 | var platform = this.project.CORDOVA_PLATFORM; 31 | var projectPath = cordovaPath(this.project); 32 | var assets = cordovaAssets.getPaths(platform, projectPath); 33 | 34 | cordovaAssets.validatePaths(assets.assetsPath, projectPath); 35 | 36 | var pluginsTree = new Funnel('ember-cordova/cordova', { 37 | srcDir: assets.assetsPath, 38 | include: assets.files 39 | }); 40 | 41 | return this._mergeTrees([tree, pluginsTree]); 42 | }, 43 | 44 | treeForPublic: function() { 45 | var tree = this._super.treeForPublic.apply(this, arguments); 46 | 47 | if (this.project.targetIsCordovaLivereload) { 48 | return this.cordovaAssetTree(tree); 49 | } 50 | 51 | return tree; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /lib/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": false, 3 | "node": true 4 | } 5 | -------------------------------------------------------------------------------- /lib/commands/-command.js: -------------------------------------------------------------------------------- 1 | var Command = require('ember-cli/lib/models/command'); 2 | var Leek = require('leek'); 3 | var ConfigStore = require('configstore'); 4 | var uuid = require('uuid'); 5 | var _get = require('lodash').get; 6 | 7 | module.exports = Command.extend({ 8 | //h/t ember-cli 9 | getUUID: function() { 10 | var configStore = new ConfigStore('ember-cordova'); 11 | var id = configStore.get('uuid'); 12 | if (id === undefined) { 13 | id = uuid.v4().toString(); 14 | configStore.set('uuid', id); 15 | } 16 | 17 | return id; 18 | }, 19 | 20 | init: function(app) { 21 | this._super.apply(this, arguments); 22 | 23 | var disabled = _get(app, 'settings.disableEcAnalytics', false); 24 | var version = _get(app, 'project.addonPackages.ember-cordova.pkg.version'); 25 | var id = this.getUUID(); 26 | 27 | this.analytics = new Leek({ 28 | silent: disabled, 29 | name: id, 30 | globalName: 'ember-cordova', 31 | trackingCode: 'UA-50368464-2', 32 | version: version 33 | }); 34 | }, 35 | 36 | run: function() { 37 | this.analytics.track({ 38 | message: this.name 39 | }); 40 | 41 | return; 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /lib/commands/build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | 5 | var CdvBuildTask = require('../tasks/cordova-build'); 6 | var HookTask = require('../tasks/run-hook'); 7 | var BuildTask = require('../tasks/ember-build'); 8 | var runValidators = require('../utils/run-validators'); 9 | var logger = require('../utils/logger'); 10 | 11 | var ValidateLocationType = require('../tasks/validate/location-type'); 12 | var ValidatePlatformTask = require('../tasks/validate/platform'); 13 | var ValidateAllowNavigation = require('../tasks/validate/allow-navigation'); 14 | var ValidateRootUrl = require('../tasks/validate/root-url'); 15 | var LintIndex = require('../tasks/lint-index'); 16 | var parseCordovaOpts = require('../utils/parse-cordova-build-opts'); 17 | var projectType = require('../utils/get-project-type'); 18 | 19 | module.exports = Command.extend({ 20 | name: 'cordova:build', 21 | aliases: ['cdv:build', 'cdv:b'], 22 | description: 'Build the ember application for cordova', 23 | works: 'insideProject', 24 | 25 | /* eslint-disable max-len */ 26 | availableOptions: [ 27 | { name: 'platform', type: String, default: 'ios' }, 28 | { name: 'verbose', type: Boolean, default: false, aliases: ['v'] }, 29 | { name: 'environment', type: String, default: 'development', aliases: ['e', 'env', { 'dev': 'development' }, { 'prod': 'production' }] }, 30 | { name: 'cordova-output-path', type: 'Path', default: 'ember-cordova/cordova/www', aliases: ['op', 'out'] }, 31 | { name: 'release', type: Boolean, default: false }, 32 | { name: 'device', type: Boolean, default: true }, 33 | { name: 'emulator', type: Boolean, default: false }, 34 | { name: 'build-config', type: 'Path', aliases: ['buildConfig'] }, 35 | { name: 'force', type: Boolean, default: false }, 36 | { name: 'skip-cordova-build', type: Boolean, default: false, aliases: ['scb']}, 37 | { name: 'skip-ember-build', type: Boolean, default: false, aliases: ['seb']}, 38 | 39 | // iOS Signing Options 40 | { name: 'code-sign-identity', type: String }, 41 | { name: 'provisioning-profile', type: String }, 42 | { name: 'codesign-resource-rules', type: String }, 43 | { name: 'development-team', type: String }, 44 | { name: 'package-type', type: String }, 45 | 46 | // android Signing Options 47 | { name: 'keystore', type: String }, 48 | { name: 'store-password', type: String }, 49 | { name: 'alias', type: String }, 50 | { name: 'password', type: String }, 51 | { name: 'keystore-type', type: String }, 52 | { name: 'gradle-arg', type: String }, 53 | { name: 'cdv-build-multiple-apks', type: Boolean }, 54 | { name: 'cdv-version-code', type: String }, 55 | { name: 'cdv-min-sdk-version', type: String }, 56 | { name: 'cdv-build-tools-version', type: String }, 57 | { name: 'cdv-compile-sdk-version', type: String }, 58 | { name: 'cdv-debug-sigining-properties-file', type: String }, 59 | { name: 'cdv-release-sigining-properties-file', type: String } 60 | 61 | ], 62 | /* eslint-enable max-len */ 63 | 64 | startValidators: function(project, options) { 65 | var validations = []; 66 | var projectConfig = project.config(options.environment); 67 | var isGlimmer = projectType.isGlimmer(this.project.root); 68 | 69 | if (isGlimmer === false) { 70 | validations.push( 71 | new ValidateRootUrl({ 72 | config: projectConfig, 73 | force: options.force 74 | }).run() 75 | ); 76 | 77 | validations.push( 78 | new ValidateLocationType({ 79 | config: projectConfig, 80 | force: options.force 81 | }).run() 82 | ); 83 | } 84 | 85 | validations.push( 86 | new ValidateAllowNavigation({ 87 | project: project, 88 | rejectIfUndefined: false 89 | }).run() 90 | ); 91 | 92 | if (options.skipCordovaBuild !== true) { 93 | validations.push( 94 | new ValidatePlatformTask({ 95 | project: project, 96 | platform: options.platform 97 | }).run() 98 | ); 99 | } 100 | 101 | return runValidators(validations); 102 | }, 103 | 104 | run: function(options) { 105 | this._super.apply(this, arguments); 106 | 107 | var project = this.project; 108 | var platform = options.platform; 109 | 110 | //Vars for live reload addon service 111 | this.project.targetIsCordova = true; 112 | this.project.CORDOVA_PLATFORM = platform; 113 | 114 | var hook = new HookTask({ 115 | project: project 116 | }); 117 | 118 | var emberBuild = new BuildTask({ 119 | project: project, 120 | environment: options.environment, 121 | outputPath: options.cordovaOutputPath 122 | }); 123 | 124 | var cordovaOpts = parseCordovaOpts(platform, options); 125 | var cordovaBuild = new CdvBuildTask({ 126 | project: project, 127 | platform: platform, 128 | cordovaOpts: cordovaOpts, 129 | verbose: options.verbose 130 | }); 131 | 132 | logger.info('ember-cordova: Building app'); 133 | 134 | return hook.run('beforeBuild', options) 135 | .then(this.startValidators.bind(this, project, options)) 136 | .then(function() { 137 | if (options.skipEmberBuild !== true) { 138 | return emberBuild.run(); 139 | } 140 | }) 141 | .then(function() { 142 | if (options.skipCordovaBuild !== true) { 143 | return cordovaBuild.run(); 144 | } 145 | }) 146 | .then(hook.prepare('afterBuild', options)) 147 | .then(function() { 148 | var lint = new LintIndex({ 149 | source: 'www/index.html', 150 | project: project 151 | }); 152 | 153 | return lint.run(); 154 | }) 155 | .then(function() { 156 | logger.success('ember-cordova project built'); 157 | }) 158 | .catch(function(e) { 159 | logger.error(e); 160 | }); 161 | } 162 | }); 163 | -------------------------------------------------------------------------------- /lib/commands/cordova.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* eslint-disable max-len */ 3 | 4 | var Command = require('./-command'); 5 | var logger = require('../utils/logger'); 6 | 7 | module.exports = Command.extend({ 8 | name: 'cordova', 9 | aliases: ['cdv'], 10 | description: 'Deprecated', 11 | works: 'insideProject', 12 | 13 | run: function(options, rawArgs) { 14 | logger.warn( 15 | 'DEPRECATION WARNING (ember-cordova): ember cdv proxy syntax has been deprecated in favor of ember cdv:proxy\n' + 16 | 'The prior proxy command was "ember cdv $COMMAND" \n' + 17 | 'To ease confusion this is now "ember cdv:proxy $COMMAND". No other changes are required. \n' + 18 | 'So ember cdv run would now be ember cdv:proxy run \n' 19 | ); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /lib/commands/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | 'cordova:build' : require('./build'), 5 | 'cordova:init' : require('./init'), 6 | 'cordova:open' : require('./open'), 7 | 'cordova:platform' : require('./platform'), 8 | 'cordova:plugin' : require('./plugin'), 9 | 'cordova:prepare' : require('./prepare'), 10 | 'cordova:proxy' : require('./proxy'), 11 | 'cordova:lint-index' : require('./lint-index'), 12 | 'cordova:serve' : require('./serve'), 13 | 'cordova:make-icons' : require('./make-icons'), 14 | 'cordova:make-splashes' : require('./make-splashes'), 15 | 'cordova' : require('./cordova') 16 | }; 17 | -------------------------------------------------------------------------------- /lib/commands/init.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* eslint-disable max-len */ 3 | 4 | var Command = require('./-command'); 5 | var initProject = require('../utils/init-project'); 6 | 7 | module.exports = Command.extend({ 8 | name: 'init', 9 | aliases: ['i'], 10 | 11 | availableOptions: [ 12 | { 13 | name: 'name', 14 | type: String 15 | }, { 16 | name: 'cordovaid', 17 | type: String 18 | }, { 19 | name: 'template-path', 20 | type: String 21 | } 22 | ], 23 | 24 | run: function(options, rawArgs) { 25 | return initProject(options, this.project, this.ui); 26 | } 27 | }); 28 | -------------------------------------------------------------------------------- /lib/commands/lint-index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | var LintTask = require('../tasks/lint-index'); 5 | 6 | module.exports = Command.extend({ 7 | name: 'cordova:lint-index', 8 | aliases: [ 9 | 'cdv:lint-index' 10 | ], 11 | description: 'Lints index.html for attributes with paths relative to root.', 12 | works: 'insideProject', 13 | 14 | availableOptions: [{ 15 | name: 'source', 16 | type: String, 17 | default: 'www/index.html' 18 | }], 19 | 20 | run: function(options) { 21 | this._super.apply(this, arguments); 22 | 23 | var lint = new LintTask({ 24 | source: options.source, 25 | project: this.project 26 | }); 27 | 28 | return lint.run(); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /lib/commands/make-icons.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | var iconTask = require('splicon/src/icon-task'); 5 | var getAddedPlatforms = require('../utils/get-added-platforms'); 6 | var logger = require('../utils/logger'); 7 | 8 | var includes = require('lodash').includes; 9 | var pull = require('lodash').pull; 10 | 11 | module.exports = Command.extend({ 12 | name: 'cordova:make-icons', 13 | aliases: ['cordova:icons', 'cdv:icon', 'cdv:make-icons'], 14 | description: 'Generates cordova icon files and updates config', 15 | works: 'insideProject', 16 | 17 | availableOptions: [{ 18 | name: 'source', 19 | type: String, 20 | default: 'ember-cordova/icon.svg' 21 | }, { 22 | name: 'platform', 23 | type: Array, 24 | values: [ 25 | 'added', 26 | 'ios', 27 | 'android', 28 | 'windows', 29 | 'blackberry' 30 | ], 31 | default: ['added'] 32 | }], 33 | 34 | run: function(options) { 35 | this._super.apply(this, arguments); 36 | 37 | if (includes(options.platform, 'added')) { 38 | var addedPlatforms = getAddedPlatforms(this.project); 39 | 40 | if (addedPlatforms.length === 0) { 41 | /* eslint-disable max-len */ 42 | throw new Error('ember-cordova: No added platforms to generate icons for'); 43 | /* eslint-enable max-len */ 44 | } 45 | 46 | options.platform = options.platform.concat(addedPlatforms); 47 | 48 | pull(options.platform, 'added'); 49 | } 50 | 51 | /* eslint-disable max-len */ 52 | logger.info('ember-cordova: Generating icons for ' + options.platform.join(', ')); 53 | /* eslint-enable max-len */ 54 | 55 | return iconTask({ 56 | source: options.source, 57 | platforms: options.platform, 58 | projectPath: 'ember-cordova/cordova' 59 | }).then(function() { 60 | logger.success('ember-cordova: icons generated'); 61 | }).catch(function(err) { 62 | logger.error(err); 63 | }); 64 | } 65 | }); 66 | -------------------------------------------------------------------------------- /lib/commands/make-splashes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | var splashTask = require('splicon/src/splash-task'); 5 | var getAddedPlatforms = require('../utils/get-added-platforms'); 6 | var logger = require('../utils/logger'); 7 | 8 | var includes = require('lodash').includes; 9 | var pull = require('lodash').pull; 10 | 11 | module.exports = Command.extend({ 12 | name: 'cordova:make-splashes', 13 | aliases: ['cordova:splashes', 'cdv:splash', 'cdv:make-splashes'], 14 | description: 'Generates cordova splash files and updates config', 15 | works: 'insideProject', 16 | 17 | availableOptions: [{ 18 | name: 'source', 19 | type: String, 20 | default: 'ember-cordova/splash.svg' 21 | }, { 22 | name: 'platform', 23 | type: Array, 24 | values: [ 25 | 'added', 26 | 'ios', 27 | 'android' 28 | ], 29 | default: ['added'] 30 | }], 31 | 32 | run: function(options) { 33 | this._super.apply(this, arguments); 34 | 35 | if (includes(options.platform, 'added')) { 36 | var addedPlatforms = getAddedPlatforms(this.project); 37 | 38 | if (addedPlatforms.length === 0) { 39 | /* eslint-disable max-len */ 40 | throw new Error('ember-cordova: No added platforms to generate icons for'); 41 | /* eslint-enable max-len */ 42 | } 43 | 44 | options.platform = options.platform.concat(addedPlatforms); 45 | 46 | pull(options.platform, 'added'); 47 | } 48 | 49 | /* eslint-disable max-len */ 50 | logger.info('ember-cordova: Generating splashes for ' + options.platform.join(', ')); 51 | /* eslint-enable max-len */ 52 | 53 | return splashTask({ 54 | source: options.source, 55 | platforms: options.platform, 56 | projectPath: 'ember-cordova/cordova' 57 | }).then(function() { 58 | logger.success('ember-cordova: splashes generated'); 59 | }).catch(function(err) { 60 | logger.error(err); 61 | }); 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /lib/commands/open.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | var OpenAppTask = require('../tasks/open-app'); 5 | var logger = require('../utils/logger'); 6 | 7 | module.exports = Command.extend({ 8 | name: 'cordova:open', 9 | aliases: ['cdv:open'], 10 | description: 'Open the native platform project with the default or ' + 11 | 'specified application', 12 | works: 'insideProject', 13 | 14 | availableOptions: [ 15 | { name: 'platform', type: String, default: 'ios' }, 16 | { name: 'application', type: String } 17 | ], 18 | 19 | run: function(options) { 20 | this._super.apply(this, arguments); 21 | 22 | var open = new OpenAppTask({ 23 | application: options.application, 24 | platform: options.platform, 25 | project: this.project 26 | }); 27 | 28 | return open.run().catch(function(err) { 29 | logger.error(err); 30 | }); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /lib/commands/platform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | var CordovaRawTask = require('../tasks/cordova-raw'); 5 | var SanitizeArgs = require('../tasks/validate/sanitize-addon-args'); 6 | var SetupWebView = require('../tasks/setup-webview'); 7 | var logger = require('../utils/logger'); 8 | 9 | module.exports = Command.extend({ 10 | name: 'cordova:platform', 11 | aliases: ['cdv:platform', 'cdv:pl'], 12 | description: 'Add/remove platforms', 13 | works: 'insideProject', 14 | 15 | /* eslint-disable max-len */ 16 | availableOptions: [ 17 | { name: 'save', type: Boolean, default: true }, 18 | { name: 'default-webview', type: Boolean, default: false }, 19 | { name: 'crosswalk', type: Boolean, default: false }, 20 | { name: 'uiwebview', type: Boolean, default: false }, 21 | { name: 'link', type: String, default: undefined } 22 | ], 23 | 24 | /* eslint-enable max-len */ 25 | run: function(options, rawArgs) { 26 | this._super.apply(this, arguments); 27 | 28 | var project = this.project; 29 | var cordovaArgValidator = new SanitizeArgs({ 30 | rawArgs: rawArgs, 31 | api: 'platform' 32 | }); 33 | 34 | var platformTask = new CordovaRawTask({ 35 | project: project, 36 | rawApi: 'platforms' 37 | }); 38 | 39 | //TODO - flatten validator /w SetupWebView 40 | return cordovaArgValidator.run() 41 | .then(function(validated) { 42 | var action = validated.action; 43 | 44 | logger.info( 45 | 'Preparing to ' + action + ' platform ' + rawArgs 46 | ); 47 | 48 | var opts = { save: options.save, link: options.link }; 49 | return platformTask.run(validated.action, validated.name, opts) 50 | .then(function() { 51 | //By default we upgrade the default WebView 52 | var platform = validated.name; 53 | 54 | if (action === 'add') { 55 | var setup = new SetupWebView({ 56 | project: project, 57 | platform: platform, 58 | crosswalk: options.crosswalk, 59 | uiwebview: options.uiwebview 60 | }); 61 | 62 | return setup.run(); 63 | } 64 | }); 65 | }).catch(function(err) { 66 | logger.error(err); 67 | }); 68 | } 69 | }); 70 | -------------------------------------------------------------------------------- /lib/commands/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //Cordova requires snaked var 4 | /* eslint-disable camelcase */ 5 | 6 | var Command = require('./-command'); 7 | var CordovaRawTask = require('../tasks/cordova-raw'); 8 | var SanitizeArgs = require('../tasks/validate/sanitize-addon-args'); 9 | var logger = require('../utils/logger'); 10 | 11 | module.exports = Command.extend({ 12 | name: 'cordova:plugin', 13 | aliases: ['cdv:plugin', 'cdv:p'], 14 | description: 'Add/remove plugins', 15 | works: 'insideProject', 16 | 17 | /* eslint-disable max-len */ 18 | availableOptions: [ 19 | { name: 'save', type: Boolean, default: true }, 20 | { name: 'variable', type: Array, aliases: ['var'] }, 21 | { name: 'searchpath', type: String }, 22 | { name: 'noregistry', type: Boolean, default: false }, 23 | { name: 'nohooks', type: Boolean, default: false }, 24 | { name: 'browserify', type: Boolean, default: false }, 25 | { name: 'link', type: String, default: undefined }, 26 | { name: 'force', type: Boolean, default: false } 27 | ], 28 | /* eslint-enable max-len */ 29 | 30 | run: function(options, rawArgs) { 31 | var cordovaArgSanitizer = new SanitizeArgs({ 32 | rawArgs: rawArgs, 33 | varOpts: options.variable, 34 | api: 'plugin' 35 | }); 36 | 37 | var pluginTask = new CordovaRawTask({ 38 | project: this.project, 39 | rawApi: 'plugins' 40 | }); 41 | 42 | return cordovaArgSanitizer.run() 43 | .then(function(validated) { 44 | logger.info( 45 | 'Preparing to ' + validated.action + ' plugins ' + rawArgs 46 | ); 47 | 48 | return pluginTask.run(validated.action, validated.name, { 49 | save: options.save, 50 | searchpath: options.searchpath, 51 | noregistry: options.noregistry, 52 | nohooks: options.nohooks, 53 | browserify: options.browserify, 54 | link: options.link, 55 | force: options.force, 56 | cli_variables: validated.varOpts 57 | }); 58 | 59 | }).catch(function(err) { 60 | logger.error(err); 61 | }); 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /lib/commands/prepare.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | var PrepareTask = require('../tasks/prepare'); 5 | var HookTask = require('../tasks/run-hook'); 6 | var logger = require('../utils/logger'); 7 | 8 | module.exports = Command.extend({ 9 | name: 'cordova:prepare', 10 | aliases: ['cdv:prepare'], 11 | description: 'Runs cordova prepare and ember cdv link', 12 | works: 'insideProject', 13 | 14 | availableOptions: [ 15 | { name: 'verbose', type: Boolean, default: false, aliases: ['v'] } 16 | ], 17 | 18 | run: function(options) { 19 | this._super.apply(this, arguments); 20 | 21 | var prepare = new PrepareTask({ 22 | project: this.project, 23 | verbose: options.verbose 24 | }); 25 | 26 | var hook = new HookTask({ 27 | project: this.project 28 | }); 29 | 30 | return hook.run('beforePrepare', options) 31 | .then(prepare.prepare()) 32 | .then(hook.prepare('afterPrepare', options)) 33 | .catch(function(err) { 34 | logger.error(err); 35 | }); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /lib/commands/proxy.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Command = require('./-command'); 4 | 5 | var BashTask = require('../tasks/bash'); 6 | var cordovaPath = require('../utils/cordova-path'); 7 | var logger = require('../utils/logger'); 8 | 9 | var ValidateCordova = require('../tasks/validate/cordova-installed'); 10 | 11 | module.exports = Command.extend({ 12 | name: 'cordova:proxy', 13 | aliases: ['cdv:proxy'], 14 | description: 'Passes commands to Cordova CLI', 15 | works: 'insideProject', 16 | 17 | supportedCommands: [ 18 | 'build', 19 | 'platform', 20 | 'platforms', 21 | 'plugin', 22 | 'plugins', 23 | 'prepare' 24 | ], 25 | 26 | knownCordovaCommands: [ 27 | 'run', 28 | 'emulate' 29 | ], 30 | 31 | validateAndRun: function(rawArgs) { 32 | var warning; 33 | 34 | if (this.supportedCommands.indexOf(rawArgs[0]) >= 0) { 35 | warning = rawArgs + 36 | ' run in cordova, but bypassed ember-cordova command.' + 37 | ' Consider running ember cdv:' + rawArgs + ' instead'; 38 | 39 | } else if (this.knownCordovaCommands.indexOf(rawArgs[0]) === -1) { 40 | warning = rawArgs + 41 | ' passed to Cordova, but is an unknown Cordova command'; 42 | 43 | } 44 | 45 | if (warning !== undefined) { 46 | logger.warn(warning); 47 | } 48 | 49 | return this.run({}, rawArgs); 50 | }, 51 | 52 | run: function(options, rawArgs) { 53 | this._super.apply(this, arguments); 54 | 55 | var project = this.project; 56 | 57 | var isInstalled = new ValidateCordova({ 58 | project: project 59 | }); 60 | 61 | return isInstalled.run().then(function() { 62 | var joinedArgs = rawArgs.join(' '); 63 | var cdvCommand = 'cordova ' + joinedArgs; 64 | 65 | var msg = 'Running \'cordova ' + joinedArgs + '\''; 66 | logger.success(msg); 67 | 68 | return new BashTask({ 69 | command: cdvCommand, 70 | options: { 71 | cwd: cordovaPath(project) 72 | } 73 | }).run(); 74 | }).catch(function(e) { 75 | logger.error(e); 76 | }); 77 | } 78 | }); 79 | -------------------------------------------------------------------------------- /lib/tasks/-task.js: -------------------------------------------------------------------------------- 1 | var Task = require('ember-cli/lib/models/task'); 2 | 3 | module.exports = Task.extend({ 4 | prepare: function() { 5 | var task = this; 6 | var args = Array.prototype.slice.call(arguments); 7 | 8 | return function preparedTask() { 9 | return task.run.apply(task, args); 10 | }; 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /lib/tasks/bash.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var Promise = require('rsvp').Promise; 5 | 6 | var childProcess = require('child_process'); 7 | var defaults = require('lodash').defaults; 8 | 9 | var BashTask = Task.extend({ 10 | command: undefined, 11 | options: undefined, 12 | 13 | run: function() { 14 | if (!this.options) { 15 | this.options = {}; 16 | } 17 | 18 | var task = this; 19 | return new Promise(function(resolve) { 20 | var options = defaults(task.options, { 21 | maxBuffer: 5000 * 1024, 22 | stdio: 'inherit' 23 | }); 24 | 25 | task.runCommand(task.command, options); 26 | resolve(); 27 | }); 28 | } 29 | }); 30 | 31 | BashTask.prototype.runCommand = function(command, options) { 32 | childProcess.execSync(command, options); 33 | }; 34 | 35 | module.exports = BashTask; 36 | -------------------------------------------------------------------------------- /lib/tasks/cordova-build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var CordovaRawTask = require('../tasks/cordova-raw'); 5 | 6 | module.exports = Task.extend({ 7 | project: undefined, 8 | 9 | platform: undefined, 10 | cordovaOpts: {}, 11 | verbose: false, 12 | 13 | run: function() { 14 | var build = new CordovaRawTask({ 15 | project: this.project, 16 | rawApi: 'build', 17 | }); 18 | 19 | return build.run({ 20 | platforms: [this.platform], 21 | options: this.cordovaOpts, 22 | verbose: this.verbose 23 | }); 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /lib/tasks/cordova-raw.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var Promise = require('rsvp').Promise; 5 | var cordovaPath = require('../utils/cordova-path'); 6 | var cordovaLib = require('cordova-lib'); 7 | var cordovaProj = cordovaLib.cordova; 8 | var events = cordovaLib.events; 9 | var cordovaLogger = require('cordova-common').CordovaLogger.get(); 10 | 11 | module.exports = Task.extend({ 12 | project: undefined, 13 | rawApi: undefined, 14 | 15 | cordovaRawPromise: function(/* rawArgs */) { 16 | return cordovaProj.raw[this.rawApi].apply(this, arguments); 17 | }, 18 | 19 | run: function() { 20 | var args = arguments; 21 | return new Promise(function(resolve, reject) { 22 | var emberPath = process.cwd(); 23 | process.chdir(cordovaPath(this.project)); 24 | 25 | cordovaLogger.subscribe(events); 26 | if (args[0] && args[0].verbose) { cordovaLogger.setLevel('verbose'); } 27 | 28 | this.cordovaRawPromise.apply(this, args).then(function() { 29 | process.chdir(emberPath); 30 | resolve(); 31 | }).catch(function(err) { 32 | reject(err); 33 | }); 34 | }.bind(this)); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /lib/tasks/create-cordova-project.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var cordovaPath = require('../utils/cordova-path'); 5 | var fsUtils = require('../utils/fs-utils'); 6 | var logger = require('../utils/logger'); 7 | var camelize = require('../../lib/utils/string.js').camelize; 8 | 9 | var path = require('path'); 10 | var Promise = require('rsvp'); 11 | 12 | var cordovaProj = require('cordova-lib').cordova; 13 | 14 | module.exports = Task.extend({ 15 | id: undefined, 16 | name: undefined, 17 | project: undefined, 18 | 19 | run: function(templatePath) { 20 | var emberCdvPath = cordovaPath(this.project, true); 21 | var cdvPath = path.join(emberCdvPath, 'cordova'); 22 | 23 | if (!fsUtils.existsSync(emberCdvPath)) { 24 | fsUtils.mkdir(emberCdvPath); 25 | } 26 | 27 | if (!fsUtils.existsSync(cdvPath)) { 28 | logger.info('Initting ember-cordova directory'); 29 | 30 | var id = camelize(this.id); 31 | var name = camelize(this.name); 32 | 33 | var config = { 34 | lib: { 35 | www: { url: 'ember-cordova-template', template: true } 36 | } 37 | }; 38 | 39 | if (templatePath !== undefined) { 40 | config.lib.www.url = templatePath; 41 | } 42 | 43 | return cordovaProj.raw.create(cdvPath, id, name, config); 44 | } else { 45 | logger.warn('Cordova dir already exists, please ensure it is valid'); 46 | return Promise.resolve(); 47 | } 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /lib/tasks/create-livereload-shell.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var Promise = require('rsvp').Promise; 5 | 6 | var cordovaPath = require('../utils/cordova-path'); 7 | var fsUtils = require('../utils/fs-utils'); 8 | 9 | var path = require('path'); 10 | 11 | module.exports = Task.extend({ 12 | project: undefined, 13 | 14 | //Read in the shell index.html file 15 | getShellTemplate: function() { 16 | var shellPath = path.join( 17 | __dirname, 18 | '../templates/livereload-shell/index.html' 19 | ); 20 | 21 | return fsUtils.read(shellPath, { encoding: 'utf8' }); 22 | }, 23 | 24 | createShell: function(outputPath, template, reloadUrl) { 25 | var regExp = new RegExp('{{liveReloadUrl}}', 'gi'); 26 | template = template.replace(regExp, reloadUrl); 27 | return fsUtils.write(outputPath, template, 'utf8'); 28 | }, 29 | 30 | run: function(reloadUrl) { 31 | var project = this.project; 32 | 33 | return this.getShellTemplate() 34 | .then(function(html) { 35 | var outputPath = path.join(cordovaPath(project), 'www/index.html'); 36 | 37 | return this.createShell(outputPath, html, reloadUrl); 38 | }.bind(this)) 39 | .catch(function(err) { 40 | return Promise.reject('Error moving index.html for livereload ' + err); 41 | }); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /lib/tasks/ember-build.js: -------------------------------------------------------------------------------- 1 | var Builder = require('ember-cli/lib/models/builder'); 2 | var Task = require('./-task'); 3 | var createGitkeep = require('../utils/create-gitkeep'); 4 | 5 | 6 | module.exports = Task.extend({ 7 | project: undefined, 8 | environment: undefined, 9 | outputPath: undefined, 10 | 11 | initBuilder: function() { 12 | return new Builder({ 13 | project: this.project, 14 | environment: this.environment, 15 | outputPath: this.outputPath 16 | }); 17 | }, 18 | 19 | run: function() { 20 | var builder = this.initBuilder.apply(this); 21 | 22 | return builder.build().then(function() { 23 | return createGitkeep('ember-cordova/cordova/www/.gitkeep'); 24 | }); 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /lib/tasks/lint-index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var HTMLParser = require('htmlparser2').Parser; 5 | var Promise = require('rsvp').Promise; 6 | var path = require('path'); 7 | var fsUtils = require('../utils/fs-utils'); 8 | var cordovaPath = require('../utils/cordova-path'); 9 | var logger = require('../utils/logger'); 10 | 11 | var ROOT_URL_PATTERN = /^\//; 12 | var NEW_LINE_PATTERN = /\n/g; 13 | 14 | module.exports = Task.extend({ 15 | source: undefined, 16 | project: undefined, 17 | 18 | getPathAttributes: function(fileContents) { 19 | return new Promise(function(resolve, reject) { 20 | var attributes = []; 21 | var line = 1; 22 | 23 | var parser = new HTMLParser({ 24 | ontext: function(text) { 25 | var matches = text.match(NEW_LINE_PATTERN); 26 | if (matches) { line += matches.length; } 27 | }, 28 | onopentag: function(name, attrs) { 29 | if (attrs.src) { 30 | attributes.push({ 31 | tagName: name, 32 | name: 'src', 33 | value: attrs.src, 34 | line: line 35 | }); 36 | } 37 | 38 | if (attrs.href) { 39 | attributes.push({ 40 | tagName: name, 41 | name: 'href', 42 | value: attrs.href, 43 | line: line 44 | }); 45 | } 46 | }, 47 | onend: function() { 48 | return resolve(attributes); 49 | } 50 | }, {decodeEntities: true}); 51 | 52 | parser.end(fileContents); 53 | }); 54 | }, 55 | 56 | validate: function(attributes) { 57 | return attributes.filter(function(attribute) { 58 | return ROOT_URL_PATTERN.test(attribute.value); 59 | }); 60 | }, 61 | 62 | print: function(path, warnings) { 63 | if (warnings.length === 0) { 64 | return logger.success('0 problems'); 65 | } 66 | 67 | var msg = '\n' + path + '\n'; 68 | msg += 'There are remaining paths beginning with / in your code.'; 69 | msg += 'They likely will not work.'; 70 | 71 | warnings.forEach(function(w) { 72 | msg += ' Line ' + w.line + ' ' + 73 | w.name + '-attribute contains unsupported path relative to root: ' + 74 | w.value + '\n'; 75 | }); 76 | 77 | msg += '\n' + '✖ ' + warnings.length + ' problem(s)'; 78 | 79 | logger.warn(msg); 80 | }, 81 | 82 | run: function() { 83 | var projectPath = cordovaPath(this.project); 84 | var indexPath = path.join(projectPath, this.source); 85 | 86 | logger.info('ember-cordova: Linting ' + indexPath + '...\n'); 87 | 88 | return fsUtils.read(indexPath).then(function(fileContents) { 89 | return this.getPathAttributes(fileContents).then(function(attributes) { 90 | var warnings = this.validate(attributes); 91 | 92 | this.print(indexPath, warnings); 93 | 94 | return Promise.resolve(warnings); 95 | }.bind(this)); 96 | }.bind(this)); 97 | } 98 | }); 99 | -------------------------------------------------------------------------------- /lib/tasks/open-app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var BashTask = require('../tasks/bash'); 5 | var Promise = require('rsvp').Promise; 6 | var logger = require('../utils/logger'); 7 | var fs = require('fs'); 8 | 9 | var path = require('path'); 10 | var getOpenCommand = require('../utils/open-app-command'); 11 | var cordovaPath = require('../utils/cordova-path'); 12 | 13 | module.exports = Task.extend({ 14 | application: undefined, 15 | platform: undefined, 16 | project: undefined, 17 | 18 | run: function() { 19 | var projectPath, open, command; 20 | var cdvPath = cordovaPath(this.project); 21 | 22 | if (this.platform === 'ios') { 23 | projectPath = path.join(cdvPath, 'platforms/ios/*.xcodeproj'); 24 | } else if (this.platform === 'android') { 25 | var projectFile = path.join(cdvPath, 'platforms/android/.project'); 26 | 27 | if (fs.existsSync(projectFile)) { 28 | projectPath = projectFile; 29 | } else { 30 | var docLink = 'http://embercordova.com/pages/cli#open'; 31 | 32 | logger.warn('Can\'t open IDE without a project being created. See' + 33 | docLink + 34 | 'for more info.' 35 | ); 36 | 37 | projectPath = path.join(cdvPath, 'platforms/android/'); 38 | } 39 | } else { 40 | return Promise.reject( 41 | 'The ' + this.platform + 42 | ' platform is not supported. Please use \'ios\' or \'android\'' 43 | ); 44 | } 45 | 46 | logger.success('Opening app for ' + this.platform); 47 | 48 | command = getOpenCommand(projectPath, this.application); 49 | open = new BashTask({ 50 | command: command, 51 | options: { 52 | cwd: this.project.root 53 | } 54 | }); 55 | 56 | return open.run(); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /lib/tasks/prepare.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var CordovaRawTask = require('../tasks/cordova-raw'); 5 | var logger = require('../utils/logger'); 6 | 7 | module.exports = Task.extend({ 8 | project: undefined, 9 | verbose: false, 10 | 11 | run: function() { 12 | logger.info('Running cordova prepare'); 13 | var prepare = new CordovaRawTask({ 14 | project: this.project, 15 | rawApi: 'prepare', 16 | }); 17 | 18 | return prepare.run({ verbose: this.verbose }); 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /lib/tasks/run-hook.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var Promise = require('rsvp').Promise; 5 | var logger = require('../utils/logger'); 6 | 7 | var cordovaPath = require('../utils/cordova-path'); 8 | var fsUtils = require('../utils/fs-utils'); 9 | var path = require('path'); 10 | 11 | module.exports = Task.extend({ 12 | project: undefined, 13 | 14 | run: function(hookName, options) { 15 | var projectPath, hookPath, hook, hookReturn; 16 | 17 | projectPath = cordovaPath(this.project, true); 18 | hookPath = path.join(projectPath, 'hooks', hookName + '.js'); 19 | 20 | if (fsUtils.existsSync(hookPath)) { 21 | logger.info('Located hook for: ' + hookName); 22 | 23 | try { 24 | hook = require(hookPath); 25 | hookReturn = hook(options); 26 | 27 | logger.success('Ran hook for: ' + hookName); 28 | 29 | return Promise.resolve(hookReturn); 30 | } catch (e) { 31 | return Promise.reject(e); 32 | } 33 | 34 | } else { 35 | return Promise.resolve(); 36 | } 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /lib/tasks/serve.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var LiveReloadServer = require('ember-cli/lib/tasks/server/livereload-server'); 4 | var ExpressServer = require('ember-cli/lib/tasks/server/express-server'); 5 | var RSVP = require('rsvp'); 6 | var Task = require('ember-cli/lib/models/task'); 7 | var Watcher = require('ember-cli/lib/models/watcher'); 8 | var Builder = require('ember-cli/lib/models/builder'); 9 | var chalk = require('chalk'); 10 | var logger = require('../utils/logger'); 11 | var rimraf = require('rimraf'); 12 | var editXml = require('../utils/edit-xml'); 13 | 14 | /* eslint-disable max-len */ 15 | /* 16 | Largely taken from: https://github.com/ember-cli/ember-cli/blob/master/lib/tasks/serve.js 17 | We simply need the Serve task without the hang build into ember-clis Task* 18 | 19 | We pass a mock analytics object, because we are importing ember-cli models 20 | 21 | That conflicts with our analyics. #TODO - better solution 22 | */ 23 | 24 | var mockAnalytics = require('../../node-tests/fixtures/ember-cordova-mock/analytics'); 25 | /* eslint-enable max-len */ 26 | 27 | module.exports = Task.extend({ 28 | project: undefined, 29 | ui: undefined, 30 | analytics: undefined, 31 | 32 | run: function(options) { 33 | this.cleanupOnExit(); 34 | 35 | var watcher = new Watcher({ 36 | ui: this.ui, 37 | builder: new Builder({ 38 | ui: this.ui, 39 | outputPath: 'ember-cordova/tmp-livereload', 40 | project: this.project, 41 | environment: options.environment 42 | }), 43 | analytics: mockAnalytics, 44 | options: options 45 | }); 46 | 47 | var expressServer = new ExpressServer({ 48 | ui: this.ui, 49 | project: this.project, 50 | watcher: watcher, 51 | serverRoot: './server', 52 | }); 53 | 54 | var liveReloadServer = new LiveReloadServer({ 55 | ui: this.ui, 56 | analytics: mockAnalytics, 57 | project: this.project, 58 | watcher: watcher, 59 | expressServer: expressServer 60 | }); 61 | 62 | // h/t ember-cli, hang until user exit 63 | this._runDeferred = RSVP.defer(); 64 | return RSVP.Promise.all([ 65 | liveReloadServer.start(options), 66 | expressServer.start(options), 67 | watcher.then() 68 | ]).then(function() { 69 | if (options.liveReload) { 70 | logger.success('ember-cordova: Device LiveReload is enabled'); 71 | } 72 | 73 | return this._runDeferred.promise; 74 | }.bind(this)); 75 | }, 76 | 77 | cleanupOnExit: function() { 78 | process.on('SIGINT', function () { 79 | editXml.removeNavigation(this.project); 80 | 81 | logger.info(chalk.blue( 82 | 'ember-cordova: Exiting, cleaning up tmp serve' 83 | )); 84 | 85 | try { 86 | rimraf.sync('ember-cordova/tmp-livereload'); 87 | } catch (err) { 88 | logger.error(err); 89 | } 90 | 91 | return this._runDeferred.resolve() 92 | }.bind(this)); 93 | } 94 | }); 95 | -------------------------------------------------------------------------------- /lib/tasks/setup-webview.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('./-task'); 4 | var CordovaRawTask = require('../tasks/cordova-raw'); 5 | var logger = require('../utils/logger'); 6 | var Promise = require('rsvp').Promise; 7 | 8 | module.exports = Task.extend({ 9 | project: undefined, 10 | platform: undefined, 11 | uiwebview: false, 12 | crosswalk: false, 13 | 14 | warnPlatform: function(platform, view) { 15 | logger.warn( 16 | 'You have specified platform=' + platform + ' and ' + view + '.' + 17 | 'Crosswalk is only available on android. This will have no effect.' 18 | ); 19 | }, 20 | 21 | warnIosView: function() { 22 | logger.warn( 23 | 'ember-cordova initializes ios with the upgraded WKWebView. ' + 24 | 'See http://ember-cordova.com/pages/default_webviews for details and flags' 25 | ); 26 | }, 27 | 28 | run: function() { 29 | var viewName, upgradeWebView; 30 | 31 | upgradeWebView = new CordovaRawTask({ 32 | project: this.project, 33 | rawApi: 'plugins' 34 | }); 35 | 36 | if (this.platform === 'ios') { 37 | if (this.crosswalk === true) { 38 | this.warnPlatform('ios', 'crosswalk=true'); 39 | } else if (this.uiwebview === false) { 40 | this.warnIosView(); 41 | viewName = 'cordova-plugin-wkwebview-engine'; 42 | } 43 | } else if (this.platform === 'android') { 44 | if (this.uiwebview === true) { 45 | this.warnPlatform('android', 'uiwebview=true'); 46 | } else if (this.crosswalk === true) { 47 | viewName = 'cordova-plugin-crosswalk-webview'; 48 | } 49 | } 50 | 51 | logger.success( 52 | 'Initializing cordova with upgraded WebView ' + viewName 53 | ); 54 | 55 | if (viewName !== undefined) { 56 | return upgradeWebView.run('add', viewName, { save: true }); 57 | } else { 58 | return Promise.resolve(); 59 | } 60 | } 61 | }); 62 | -------------------------------------------------------------------------------- /lib/tasks/update-gitignore.js: -------------------------------------------------------------------------------- 1 | var Task = require('./-task'); 2 | var fsUtils = require('../utils/fs-utils'); 3 | var logger = require('../utils/logger'); 4 | var includes = require('lodash').includes; 5 | 6 | var ignores = [ 7 | 'ember-cordova/tmp-livereload', 8 | 'ember-cordova/cordova/node_modules', 9 | 'ember-cordova/cordova/package.json', 10 | 'ember-cordova/cordova/package-lock.json' 11 | ]; 12 | 13 | var emptyCheckins = [ 14 | 'ember-cordova/cordova/platforms/', 15 | 'ember-cordova/cordova/plugins/', 16 | 'ember-cordova/cordova/www/' 17 | ]; 18 | 19 | var addLine = function(contents, path) { 20 | return '\n' + path; 21 | }; 22 | 23 | var addIfNew = function(contents, path) { 24 | if (includes(contents, path) === false) { 25 | return addLine(contents, path); 26 | } else { 27 | return ''; 28 | } 29 | }; 30 | 31 | module.exports = Task.extend({ 32 | project: undefined, 33 | 34 | run: function() { 35 | logger.info('ember-cordova: updating .gitignore'); 36 | 37 | return fsUtils.read('.gitignore', { encoding: 'utf8' }) 38 | .then(function(contents) { 39 | 40 | ignores.forEach(function(ignore) { 41 | contents += addIfNew(contents, ignore); 42 | }); 43 | 44 | emptyCheckins.forEach(function(item) { 45 | //First add each item 46 | contents += addIfNew(contents, item + '*'); 47 | 48 | //Add an empty gitKeep as these folders should be checked in 49 | var gitkeepPath = item + '.gitkeep'; 50 | contents += addIfNew(contents, '!' + gitkeepPath); 51 | 52 | //Create the empty gitkeep 53 | fsUtils.write(gitkeepPath, '', { encoding: 'utf8' }); 54 | }); 55 | 56 | return fsUtils.write('.gitignore', contents); 57 | }); 58 | } 59 | }); 60 | -------------------------------------------------------------------------------- /lib/tasks/update-watchman-config.js: -------------------------------------------------------------------------------- 1 | var Task = require('./-task'); 2 | var Promise = require('rsvp').Promise; 3 | 4 | var path = require('path'); 5 | var fsUtils = require('../utils/fs-utils'); 6 | var logger = require('../utils/logger'); 7 | var includes = require('lodash').includes; 8 | 9 | /* eslint-disable camelcase */ 10 | 11 | module.exports = Task.extend({ 12 | project: undefined, 13 | 14 | run: function() { 15 | var projectRoot = this.project.root; 16 | logger.info('ember-cordova: updating .watchmanconfig'); 17 | 18 | var configPath = path.join(projectRoot, '.watchmanconfig') 19 | 20 | return fsUtils.read(configPath, { encoding: 'utf8' }) 21 | .then(function(config) { 22 | var json = JSON.parse(config); 23 | var ignored; 24 | 25 | if (json.ignore_dirs) { 26 | ignored = json.ignore_dirs; 27 | if (includes(ignored, 'ember-cordova') === false) { 28 | ignored.push('ember-cordova'); 29 | } 30 | } else { 31 | ignored = ['ember-cordova']; 32 | } 33 | 34 | json.ignore_dirs = ignored; 35 | 36 | var contents = JSON.stringify(json); 37 | 38 | return fsUtils.write(configPath, contents, 'utf8') 39 | .then(function() { 40 | logger.success('Added ember-cordova to watchman ignore'); 41 | }); 42 | }, function(err) { 43 | return Promise.reject( 44 | 'ember-cordova: failed to update .watchmanconfig, err: ' + err 45 | ); 46 | }); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /lib/tasks/validate/allow-navigation.js: -------------------------------------------------------------------------------- 1 | var Task = require('../-task'); 2 | var Promise = require('rsvp').Promise; 3 | var chalk = require('chalk'); 4 | var logger = require('../../utils/logger'); 5 | var getCordovaConfig = require('../../utils/get-cordova-config'); 6 | 7 | var UNSAFE_PRODUCTION_VALUE = 8 | chalk.yellow('Your ember-cordova/cordova/config.xml file has set the' + 9 | 'following flag:\n') + 10 | chalk.grey('\t\n') + 11 | chalk.yellow('This is necessary for device live-reload to work,\n' + 12 | 'but is unsafe and should not be used in production.\n'); 13 | 14 | var LIVE_RELOAD_CONFIG_NEEDED = 15 | chalk.red('* ember-cordova/cordova/config.xml needs: \n') + 16 | chalk.grey('\n') + 17 | chalk.grey('This is unsafe and should not be used in production,\n' + 18 | 'but is necessary for device live-reload to work.\n'); 19 | 20 | /* 21 | * allow-navigation is considered unsafe when: 22 | * 23 | * there is a allow-href that consists of '*' 24 | * or one that contains a http or https url 25 | * 26 | * pending a users setup, one of these will be present for liveReload 27 | * 28 | */ 29 | 30 | //this is wrong because user may have multiple allow-hrefs 31 | function livereloadProp(json, field, prop) { 32 | if (json && json[field]) { 33 | 34 | var keysLength = json[field].length; 35 | while (keysLength--) { 36 | var value = json[field][keysLength].$[prop]; 37 | if (value && this.validateNavigationProp(value) !== undefined) { 38 | return value 39 | } 40 | } 41 | } 42 | return undefined; 43 | } 44 | 45 | function validateNavigationProp(prop) { 46 | if (prop && 47 | (prop.indexOf('*') === 0 || 48 | prop.indexOf('http') > -1 || 49 | prop.indexOf('https') > -1) 50 | ) { 51 | 52 | return prop; 53 | } 54 | } 55 | 56 | module.exports = Task.extend({ 57 | project: undefined, 58 | platform: undefined, 59 | rejectIfUndefined: false, 60 | 61 | livereloadProp: livereloadProp, 62 | validateNavigationProp: validateNavigationProp, 63 | 64 | run: function() { 65 | if (this.platform === 'browser') { 66 | return Promise.resolve(); 67 | } 68 | 69 | return getCordovaConfig(this.project) 70 | .then(function(config) { 71 | var livereloadProp = this.livereloadProp( 72 | config.widget, 73 | 'allow-navigation', 74 | 'href' 75 | ); 76 | 77 | if (livereloadProp !== undefined) { 78 | var msg = UNSAFE_PRODUCTION_VALUE.replace( 79 | '${allowNavigation}', 80 | livereloadProp 81 | ); 82 | logger.warn(msg); 83 | } 84 | 85 | if (this.rejectIfUndefined && livereloadProp === undefined) { 86 | return Promise.reject(LIVE_RELOAD_CONFIG_NEEDED); 87 | } 88 | }.bind(this)); 89 | } 90 | }); 91 | -------------------------------------------------------------------------------- /lib/tasks/validate/cordova-installed.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('../-task'); 4 | var Promise = require('rsvp').Promise; 5 | var commandExists = require('../../utils/command-exists'); 6 | 7 | var cordovaInstallText = '\nThe command `cordova` was not found. This likely ' + 8 | 'means you need to install cordova globally. Please run the following ' + 9 | 'command to continue.\n\t' + 10 | 'npm install cordova -g \n' + 11 | 'installed by checking that the following command returns the currently ' + 12 | 'installed version:\n\t'; 13 | 14 | module.exports = Task.extend({ 15 | options: undefined, 16 | 17 | run: function() { 18 | if (this.options && this.options.skipCordovaCheck === true) { 19 | return Promise.resolve(); 20 | } 21 | 22 | var result = commandExists('cordova'); 23 | 24 | if (result) { 25 | return Promise.resolve(); 26 | } 27 | 28 | return Promise.reject(cordovaInstallText); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /lib/tasks/validate/location-type.js: -------------------------------------------------------------------------------- 1 | var Task = require('../-task'); 2 | var Promise = require('rsvp').Promise; 3 | var chalk = require('chalk'); 4 | var logger = require('../../utils/logger'); 5 | 6 | var MUST_SPECIFY_HASH = 7 | chalk.red('* config/environment.js: Cordova applications require:') + 8 | chalk.grey('\n`ENV.locationType = \'hash\'; \n'); 9 | 10 | module.exports = Task.extend({ 11 | config: undefined, 12 | force: false, 13 | 14 | run: function() { 15 | var config = this.config; 16 | var locationType = config.locationType; 17 | var isHashLocation = locationType === 'hash'; 18 | 19 | if (!isHashLocation) { 20 | if (this.force === false) { 21 | return Promise.reject(MUST_SPECIFY_HASH); 22 | } else { 23 | var msg = MUST_SPECIFY_HASH; 24 | msg += 'You have passed the --force flag, so continuing'; 25 | logger.warn(msg); 26 | } 27 | } 28 | 29 | return Promise.resolve(); 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /lib/tasks/validate/platform.js: -------------------------------------------------------------------------------- 1 | var Task = require('../-task'); 2 | var CordovaValidator = require('../../utils/cordova-validator'); 3 | 4 | module.exports = Task.extend({ 5 | project: undefined, 6 | platform: undefined, 7 | 8 | createValidator: function() { 9 | return new CordovaValidator({ 10 | project: this.project, 11 | platform: this.platform, 12 | desiredKeyName : this.platform, 13 | type: 'platform', 14 | dir: 'platforms/', 15 | jsonPath: 'platforms/platforms.json' 16 | }); 17 | }, 18 | 19 | run: function() { 20 | var validator = this.createValidator(); 21 | 22 | return validator.validateCordovaConfig() 23 | .then(validator.validateCordovaJSON.bind(validator)) 24 | .then(validator.validateDirExists.bind(validator)); 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /lib/tasks/validate/plugin.js: -------------------------------------------------------------------------------- 1 | var Task = require('../-task'); 2 | var CordovaValidator = require('../../utils/cordova-validator'); 3 | 4 | module.exports = Task.extend({ 5 | pluginName: undefined, 6 | project: undefined, 7 | platform: undefined, 8 | 9 | createValidator: function() { 10 | return new CordovaValidator({ 11 | project: this.project, 12 | platform: this.platform, 13 | desiredKeyName: this.pluginName, 14 | type: 'plugin', 15 | dir: 'plugins/', 16 | jsonPath: 'plugins/fetch.json' 17 | }); 18 | }, 19 | 20 | run: function() { 21 | var validator = this.createValidator(); 22 | 23 | return validator.validateCordovaConfig() 24 | .then(validator.validateCordovaJSON.bind(validator)) 25 | .then(validator.validatePluginJSON.bind(validator)) 26 | .then(validator.validateDirExists.bind(validator)); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /lib/tasks/validate/root-url.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Task = require('../-task'); 4 | var Promise = require('rsvp').Promise; 5 | var chalk = require('chalk'); 6 | var pick = require('lodash').pick; 7 | var values = require('lodash').values; 8 | 9 | var logger = require('../../utils/logger'); 10 | 11 | /* eslint-disable max-len */ 12 | var URL_MSG = 13 | chalk.red('* config/environment.js: rootURL or baseURL has a leading slash. \n') + 14 | chalk.grey( 15 | 'This will not work in cordova, and needs to be removed. \n' + 16 | 'You can pass the --force flag to ignore if otherwise handled. \n' + 17 | 'See http://embercordova.com/pages/workflow/project_setup for more info.' 18 | ) 19 | /* eslint-enable max-len */ 20 | 21 | module.exports = Task.extend({ 22 | config: undefined, 23 | force: false, 24 | 25 | validRootValues: function(values) { 26 | for (var i = 0; i < values.length; i++) { 27 | var value = values[i]; 28 | if (value && value[0] === '/') { return false; } 29 | } 30 | 31 | return true; 32 | }, 33 | 34 | run: function() { 35 | var rootProps = ['baseURL', 'rootURL', 'baseUrl', 'rootUrl']; 36 | var rootValues = values(pick(this.config, rootProps)); 37 | var validRoot = this.validRootValues(rootValues); 38 | 39 | if (validRoot === false) { 40 | if (this.force === true) { 41 | var msg = URL_MSG + 'You have passed the --force flag, so continuing'; 42 | logger.warn(msg); 43 | return Promise.resolve(); 44 | } else { 45 | return Promise.reject(URL_MSG); 46 | } 47 | } else { 48 | return Promise.resolve(); 49 | } 50 | } 51 | }); 52 | -------------------------------------------------------------------------------- /lib/tasks/validate/sanitize-addon-args.js: -------------------------------------------------------------------------------- 1 | var Task = require('../-task'); 2 | var Promise = require('rsvp').Promise; 3 | var _pullAll = require('lodash').pullAll; 4 | var _intersection = require('lodash').intersection; 5 | 6 | var addCmds = ['add', 'a']; 7 | var rmCmds = ['remove', 'rm', 'r']; 8 | 9 | /* 10 | For a given platform/plugin command, return a hash with: 11 | { 12 | action: add or remove, 13 | name: name of platform/plugin, e.g. ios, 14 | varOpts: formatted plugin vars to cordova standards 15 | } 16 | */ 17 | 18 | module.exports = Task.extend({ 19 | rawArgs: undefined, 20 | api: undefined, 21 | varOpts: undefined, 22 | 23 | //cordova commands are long strings - we need to manually see if it is add/rm 24 | getAction: function(rawArgs) { 25 | if (_intersection(rawArgs, addCmds).length > 0) { 26 | return 'add'; 27 | } else if (_intersection(rawArgs, rmCmds).length > 0) { 28 | return 'remove' 29 | } 30 | }, 31 | 32 | //rm add/remove text from arguments 33 | getTargetName: function(rawArgs) { 34 | var availableActions = addCmds.concat(rmCmds); 35 | _pullAll(rawArgs, availableActions); 36 | return rawArgs[0]; 37 | }, 38 | 39 | /* 40 | Vars are passed from ember-cli as 'VAR_NAME=VALUE' 41 | Cordova requires { VAR_NAME: 'VALUE' } 42 | */ 43 | hashifyVars: function(opts) { 44 | if (opts === undefined) { return {} } 45 | 46 | var hashedOpts = {}; 47 | opts.forEach(function(s) { 48 | var eq = s.indexOf('='); 49 | var key = s.substr(0, eq).toUpperCase(); 50 | var val = s.substr(eq + 1, s.length); 51 | hashedOpts[key] = val; 52 | }); 53 | 54 | return hashedOpts; 55 | }, 56 | 57 | run: function() { 58 | var action, targetName, sanitized; 59 | 60 | action = this.getAction(this.rawArgs); 61 | if (!action) { 62 | var cmd = 'ember cdv:' + this.api + ' add ios' 63 | return Promise.reject('Missing add/rm flag, e.g. ' + cmd); 64 | } 65 | 66 | //Cooerce rawArgs/Opts to cordova spec 67 | targetName = this.getTargetName(this.rawArgs); 68 | var hashedOpts = this.hashifyVars(this.varOpts); 69 | 70 | sanitized = { 71 | action: action, 72 | name: targetName, 73 | varOpts: hashedOpts 74 | }; 75 | 76 | return Promise.resolve(sanitized); 77 | } 78 | }); 79 | -------------------------------------------------------------------------------- /lib/templates/livereload-shell/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | Starting Live Reload 11 | 12 | 13 | -------------------------------------------------------------------------------- /lib/utils/command-exists.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var childProcess = require('child_process'); 4 | 5 | var isUsingWindows = process.platform === 'win32'; 6 | 7 | module.exports = function(commandName) { 8 | var cmdStr; 9 | 10 | if (isUsingWindows) { 11 | cmdStr = 'where ' + commandName; 12 | } else { 13 | cmdStr = 'command -v ' + commandName + 14 | ' >/dev/null && { echo >&1 \'command found\'; }'; 15 | } 16 | 17 | try { 18 | childProcess.execSync(cmdStr); 19 | return true; 20 | } 21 | catch (err) { 22 | return false; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /lib/utils/cordova-assets.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var logger = require('./logger'); 3 | var fsUtils = require('./fs-utils'); 4 | var existsSync = fsUtils.existsSync; 5 | 6 | module.exports = { 7 | getPaths: function(platform, projectPath) { 8 | var platformsPath = 'platforms'; 9 | var assetsPath; 10 | 11 | if (platform === 'ios') { 12 | assetsPath = path.join(platformsPath, 'ios', 'www'); 13 | } else if (platform === 'android') { 14 | assetsPath = path.join(platformsPath, 'android', 'assets', 'www'); 15 | // cordova-android 7.0 no longer provides assets/www path. 16 | // so use android/platform_www instead 17 | if (!existsSync(assetsPath)) { 18 | assetsPath = path.join(platformsPath, 'android', 'platform_www'); 19 | } 20 | } else if (platform === 'browser') { 21 | assetsPath = path.join(platformsPath, 'browser', 'www'); 22 | } 23 | 24 | var files = ['cordova_plugins.js', 'cordova.js', 'config.xml']; 25 | 26 | var pluginPath = path.join(projectPath, assetsPath, 'plugins'); 27 | if (existsSync(pluginPath)) { 28 | files.push('plugins/**'); 29 | } 30 | 31 | return { 32 | assetsPath: assetsPath, 33 | files: files 34 | } 35 | }, 36 | 37 | /* eslint-disable max-len */ 38 | validatePaths: function(assetsPath, projectPath) { 39 | if (assetsPath === undefined) { 40 | throw new Error('ember-cordova: Platform asset path undefined, cant build'); 41 | } 42 | 43 | var platformPath = path.join(projectPath, assetsPath, 'cordova.js'); 44 | var pluginPath = path.join(projectPath, assetsPath, 'cordova_plugins.js'); 45 | 46 | if (!existsSync(platformPath) || !existsSync(pluginPath)) { 47 | logger.warn( 48 | 'Did not find cordova.js or cordova_plugins.js at ' + 49 | assetsPath + 50 | '. Ember App LiveReload will still work, but device & plugin APIS will fail.' 51 | ); 52 | } 53 | } 54 | /* eslint-enable max-len */ 55 | }; 56 | -------------------------------------------------------------------------------- /lib/utils/cordova-path.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | module.exports = function cordovaPath(project, excludeCordova) { 6 | var cdvPath = path.join(project.root, 'ember-cordova'); 7 | 8 | return excludeCordova ? 9 | cdvPath : 10 | path.join(cdvPath, 'cordova'); 11 | }; 12 | -------------------------------------------------------------------------------- /lib/utils/cordova-validator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var getCordovaConfig = require('./get-cordova-config'); 4 | var getCordovaPath = require('./cordova-path'); 5 | var fsUtils = require('./fs-utils'); 6 | 7 | var Promise = require('rsvp').Promise; 8 | var chalk = require('chalk'); 9 | var path = require('path'); 10 | 11 | var NOT_IN_CONFIGXML = 'Not found in config.xml. '; 12 | var NOT_IN_FETCHJSON = 'Not found in fetch.json. '; 13 | var NOT_IN_DIR = 'Dir not found. '; 14 | var NOT_IN_PLATFORMJSON = 'Not found in platform.json. '; 15 | 16 | var nameIsMatch = function(node, name) { 17 | return node.$.name === name; 18 | }; 19 | 20 | var isArray = function(v) { 21 | return Object.prototype.toString.call(v) === '[object Array]'; 22 | }; 23 | 24 | //type == platform || plugin 25 | //name == 'ios', 'android', 'cordova-plugin-camera' 26 | var hasByName = function(json, name, type) { 27 | if (json && json.widget) { 28 | var nodes = json.widget[type]; 29 | 30 | if (!!nodes && isArray(nodes)) { 31 | for (var i = 0; i < nodes.length; i++) { 32 | if (nameIsMatch(nodes[i], name)) { 33 | return true; 34 | } 35 | } 36 | } 37 | } 38 | 39 | return false; 40 | }; 41 | 42 | function CordovaValidator(opts) { 43 | this.project = opts.project; 44 | this.desiredKeyName = opts.desiredKeyName; 45 | this.platform = opts.platform; 46 | this.type = opts.type; 47 | this.dir = opts.dir; 48 | this.jsonPath = opts.jsonPath; 49 | } 50 | 51 | /* eslint-disable max-len */ 52 | CordovaValidator.prototype.makeError = function(error) { 53 | var message = chalk.red('* cordova ' + this.type + ' ' + this.desiredKeyName + ' is missing or not installed: \n'); 54 | message += chalk.grey('You probably need to run ember cdv:' + this.type + ' add ' + this.desiredKeyName + '. '); 55 | message += chalk.grey('cordova error: ' + error + '\n'); 56 | return message; 57 | }; 58 | /* eslint-enable max-len */ 59 | 60 | CordovaValidator.prototype.validateCordovaConfig = function() { 61 | var validator = this; 62 | 63 | return getCordovaConfig(validator.project) 64 | .then(function(cordovaConfig) { 65 | if (!hasByName(cordovaConfig, validator.desiredKeyName, validator.type)) { 66 | return Promise.reject(validator.makeError(NOT_IN_CONFIGXML)); 67 | } else { 68 | return Promise.resolve(); 69 | } 70 | }); 71 | }; 72 | 73 | CordovaValidator.prototype.validateCordovaJSON = function() { 74 | var validator = this; 75 | var cordovaPath = getCordovaPath(validator.project); 76 | var fetchPath = path.join(cordovaPath, validator.jsonPath); 77 | 78 | try { 79 | var fetchJSON = require(fetchPath); 80 | var items = Object.keys(fetchJSON); 81 | 82 | if (items.indexOf(validator.desiredKeyName) < 0) { 83 | return Promise.reject(validator.makeError(NOT_IN_FETCHJSON)); 84 | } 85 | 86 | return Promise.resolve(); 87 | } catch (e) { 88 | return Promise.reject(validator.makeError(NOT_IN_FETCHJSON)); 89 | } 90 | }; 91 | 92 | //Is only run for plugins, there is no equivalent for platform 93 | CordovaValidator.prototype.validatePluginJSON = function() { 94 | var validator = this; 95 | var cordovaPath = getCordovaPath(validator.project); 96 | var platformPath = path.join( 97 | cordovaPath, 98 | 'plugins/' + validator.platform + '.json' 99 | ); 100 | 101 | try { 102 | var platformJSON = require(platformPath); 103 | var plugins = Object.keys(platformJSON.installed_plugins); 104 | 105 | if (plugins.indexOf(validator.desiredKeyName) < 0) { 106 | return Promise.reject(validator.makeError(NOT_IN_PLATFORMJSON)); 107 | } 108 | 109 | return Promise.resolve(); 110 | } catch (e) { 111 | return Promise.reject(validator.makeError(NOT_IN_PLATFORMJSON)); 112 | } 113 | }; 114 | 115 | CordovaValidator.prototype.validateDirExists = function() { 116 | var validator = this; 117 | var cordovaPath = getCordovaPath(validator.project); 118 | var filePath = path.join( 119 | cordovaPath, 120 | validator.dir, 121 | validator.desiredKeyName 122 | ); 123 | 124 | if (fsUtils.existsSync(filePath)) { 125 | return Promise.resolve(); 126 | } else { 127 | return Promise.reject(validator.makeError(NOT_IN_DIR)); 128 | } 129 | }; 130 | 131 | module.exports = CordovaValidator; 132 | -------------------------------------------------------------------------------- /lib/utils/create-gitkeep.js: -------------------------------------------------------------------------------- 1 | var fsUtils = require('./fs-utils'); 2 | 3 | module.exports = function(gitkeepPath) { 4 | return fsUtils.write(gitkeepPath, '', { encoding: 'utf8' }); 5 | } 6 | -------------------------------------------------------------------------------- /lib/utils/edit-xml.js: -------------------------------------------------------------------------------- 1 | var cordovaPath = require('./cordova-path'); 2 | var fs = require('fs'); 3 | var parseXml = require('./parse-xml'); 4 | var path = require('path'); 5 | var xml2js = require('xml2js'); 6 | 7 | var builder = new xml2js.Builder({ 8 | renderOpts: { 9 | 'pretty': true, 10 | 'indent': ' ', 11 | 'newline': '\n' 12 | } 13 | }); 14 | 15 | module.exports = { 16 | addNavigation: function(project, host) { 17 | var cdvPath = cordovaPath(project); 18 | var configPath = path.join(cdvPath, 'config.xml'); 19 | 20 | return parseXml(configPath).then(function(json) { 21 | var navOptions = { $: { href: host, name: 'ec-nav' }}; 22 | 23 | if (!json.widget['allow-navigation']) { 24 | json.widget['allow-navigation'] = []; 25 | } 26 | 27 | json.widget['allow-navigation'].push(navOptions); 28 | 29 | var xml = builder.buildObject(json); 30 | 31 | fs.writeFileSync(configPath, xml); 32 | }); 33 | }, 34 | 35 | removeNavigation: function(project, host) { 36 | var cdvPath = cordovaPath(project); 37 | var configPath = path.join(cdvPath, 'config.xml'); 38 | 39 | parseXml(configPath).then(function(json) { 40 | var clientNavs = []; 41 | 42 | json.widget['allow-navigation'].forEach(function(nav) { 43 | if (nav.$.name !== 'ec-nav') { 44 | clientNavs.push(nav); 45 | } 46 | }); 47 | 48 | json.widget['allow-navigation'] = []; 49 | 50 | clientNavs.forEach(function(nav) { 51 | json.widget['allow-navigation'].push(nav); 52 | }); 53 | 54 | var xml = builder.buildObject(json); 55 | 56 | fs.writeFileSync(configPath, xml); 57 | }); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /lib/utils/ember-cordova-error.js: -------------------------------------------------------------------------------- 1 | var EmberCordovaError = function(content) { 2 | var message = content.message ? content.message : content; 3 | var stack = content.stack ? content.stack : (new Error()).stack; 4 | 5 | this.name = 'EmberCordovaError'; 6 | this.message = 'EmberCordovaError: ' + message; 7 | this.stack = stack.substr(stack.indexOf('\n') + 1); 8 | }; 9 | 10 | EmberCordovaError.prototype = Object.create(Error.prototype); 11 | EmberCordovaError.constructor = EmberCordovaError; 12 | 13 | module.exports = EmberCordovaError; 14 | -------------------------------------------------------------------------------- /lib/utils/fs-utils.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var RSVP = require('rsvp') 3 | 4 | var denodeify = RSVP.denodeify 5 | var fsReadFile = denodeify(fs.readFile) 6 | var fsWriteFile = denodeify(fs.writeFile); 7 | var fsMkdir = denodeify(fs.mkdir); 8 | var fsAppend = denodeify(fs.appendFile); 9 | 10 | module.exports = { 11 | read: function() { 12 | return fsReadFile.apply(this, arguments); 13 | }, 14 | 15 | readSync: function() { 16 | return fs.readFileSync.apply(this, arguments); 17 | }, 18 | 19 | write: function() { 20 | return fsWriteFile.apply(this, arguments); 21 | }, 22 | 23 | existsSync: function() { 24 | return fs.existsSync.apply(this, arguments); 25 | }, 26 | 27 | mkdir: function() { 28 | return fsMkdir.apply(this, arguments); 29 | }, 30 | 31 | append: function() { 32 | return fsAppend.apply(this, arguments); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/utils/get-added-platforms.js: -------------------------------------------------------------------------------- 1 | var getCordovaPath = require('../utils/cordova-path'); 2 | var path = require('path'); 3 | 4 | module.exports = function(project) { 5 | var cordovaPath = getCordovaPath(project); 6 | var platformsPath = path.join(cordovaPath, 'platforms/platforms.json'); 7 | var platformVersions = {}; 8 | 9 | try { 10 | platformVersions = require(platformsPath); 11 | } catch (e) { 12 | if (!e.message.match(/Cannot find module/)) { throw e; } 13 | } 14 | 15 | return Object.keys(platformVersions); 16 | } 17 | -------------------------------------------------------------------------------- /lib/utils/get-cordova-config.js: -------------------------------------------------------------------------------- 1 | var cordovaPath = require('./cordova-path'); 2 | var parseXml = require('./parse-xml'); 3 | var path = require('path'); 4 | 5 | module.exports = function getCordovaConfig(project) { 6 | var cdvPath = cordovaPath(project); 7 | var configPath = path.join(cdvPath, 'config.xml'); 8 | 9 | return parseXml(configPath); 10 | }; 11 | -------------------------------------------------------------------------------- /lib/utils/get-last-command.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function getLastCommand() { 3 | var args = Array.prototype.slice.call(process.argv); 4 | 5 | args.shift(); 6 | args.shift(); 7 | 8 | return 'ember ' + args.join(' '); 9 | }; 10 | -------------------------------------------------------------------------------- /lib/utils/get-network-ip.js: -------------------------------------------------------------------------------- 1 | var os = require('os'); 2 | 3 | module.exports = function getNetworkIp() { 4 | var interfaces = os.networkInterfaces(); 5 | var addresses = []; 6 | 7 | for (var k in interfaces) { 8 | for (var k2 in interfaces[k]) { 9 | var address = interfaces[k][k2]; 10 | if (address.family === 'IPv4' && !address.internal) { 11 | addresses.push(address.address); 12 | } 13 | } 14 | } 15 | 16 | return addresses[0]; 17 | }; 18 | -------------------------------------------------------------------------------- /lib/utils/get-project-type.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = { 4 | getPackage: function(projectRoot) { 5 | return require(path.join(projectRoot, 'package.json')); 6 | }, 7 | 8 | isGlimmer: function(projectRoot) { 9 | var packageJSON = this.getPackage(projectRoot); 10 | return packageJSON.devDependencies['@glimmer/application'] !== undefined; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /lib/utils/init-project.js: -------------------------------------------------------------------------------- 1 | var CreateTask = require('../tasks/create-cordova-project'); 2 | var UpdateGitIgnore = require('../tasks/update-gitignore'); 3 | var UpdateWatchmanIgnore = require('../tasks/update-watchman-config'); 4 | var camelize = require('../utils/string.js').camelize; 5 | 6 | var createProjectId = function(projectName) { 7 | return 'com.embercordova.' + projectName; 8 | }; 9 | 10 | module.exports = function(options, project, ui) { 11 | options.projectName = camelize(project.name()); 12 | 13 | var create = new CreateTask({ 14 | id: options.cordovaid || createProjectId(options.projectName), 15 | name: options.name || options.projectName, 16 | project: project, 17 | ui: ui 18 | }); 19 | 20 | var updateGitIgnore = new UpdateGitIgnore({ 21 | project: project, 22 | ui: ui 23 | }); 24 | 25 | var updateWatchmanIgnore = new UpdateWatchmanIgnore({ 26 | project: project, 27 | ui: ui 28 | }); 29 | 30 | return create.run(options.templatePath) 31 | .then(updateGitIgnore.prepare()) 32 | .then(updateWatchmanIgnore.prepare()); 33 | }; 34 | -------------------------------------------------------------------------------- /lib/utils/logger.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk'); 2 | 3 | var EmberCordovaError = require('./ember-cordova-error'); 4 | 5 | module.exports = { 6 | info: function(message) { 7 | console.log(message); 8 | }, 9 | 10 | success: function(message) { 11 | console.log(chalk.green(message)); 12 | }, 13 | 14 | warn: function(content) { 15 | var message = 'WARNING: ember-cordova \n'; 16 | message += content; 17 | console.log(chalk.yellow(message)); 18 | }, 19 | 20 | error: function(content) { 21 | throw new EmberCordovaError(content); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /lib/utils/open-app-command.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* 3 | This file needs to be removed when issue https://github.com/pwnall/node-open/issues/30 4 | is resolved, original file can be seen here: 5 | https://github.com/pwnall/node-open/blob/0c3ad272bfbc163cce8806e64630c623a9cfd8f4/lib/open.js 6 | */ 7 | module.exports = function(target, appName) { 8 | var opener; 9 | 10 | switch (process.platform) { 11 | case 'darwin': 12 | if (appName) { 13 | 14 | opener = 'open -a "' + appName + '"'; 15 | } else { 16 | opener = 'open'; 17 | } 18 | break; 19 | case 'win32': 20 | // if the first parameter to start is quoted, it uses that as the title 21 | // so we pass a blank title so we can quote the file we are opening 22 | if (appName) { 23 | opener = 'start "" "' + appName + '"'; 24 | } else { 25 | opener = 'start'; 26 | } 27 | break; 28 | default: 29 | if (appName) { 30 | opener = appName; 31 | } else { 32 | // use Portlands xdg-open everywhere else 33 | opener = 'xdg-open'; 34 | } 35 | break; 36 | } 37 | 38 | if (process.env.SUDO_USER) { 39 | opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener; 40 | } 41 | 42 | return opener + ' ' + target; 43 | }; 44 | -------------------------------------------------------------------------------- /lib/utils/parse-cordova-build-opts.js: -------------------------------------------------------------------------------- 1 | var _pick = require('lodash').pick; 2 | 3 | var CORDOVA_OPTS = [ 4 | 'release', 5 | 'debug', 6 | 'emulator', 7 | 'device', 8 | 'buildConfig' 9 | ]; 10 | 11 | var IOS_OPTS = [ 12 | 'codeSignIdentity', 13 | 'provisioningProfile', 14 | 'codesignResourceRules', 15 | 'developmentTeam', 16 | 'packageType' 17 | ]; 18 | 19 | var ANDROID_OPTS = [ 20 | 'keystore', 21 | 'storePassword', 22 | 'alias', 23 | 'password', 24 | 'keystoreType', 25 | 'gradleArg', 26 | 'cdvBuildMultipleApks', 27 | 'cdvVersionCode', 28 | 'cdvReleaseSigningPropertiesFile', 29 | 'cdvDebugSigningPropertiesFile', 30 | 'cdvMinSdkVersion', 31 | 'cdvBuildToolsVersion', 32 | 'cdvCompileSdkVersion' 33 | ]; 34 | 35 | module.exports = function(platform, options) { 36 | var buildKeys; 37 | 38 | if (platform === 'ios') { 39 | buildKeys = CORDOVA_OPTS.concat(IOS_OPTS); 40 | } else if (platform === 'android') { 41 | buildKeys = CORDOVA_OPTS.concat(ANDROID_OPTS); 42 | } 43 | 44 | return _pick(options, buildKeys); 45 | }; 46 | -------------------------------------------------------------------------------- /lib/utils/parse-xml.js: -------------------------------------------------------------------------------- 1 | var xml2js = require('xml2js'); 2 | var Promise = require('rsvp').Promise; 3 | 4 | var fsUtils = require('./fs-utils'); 5 | var logger = require('./logger'); 6 | 7 | module.exports = function parseXML(xmlPath) { 8 | return new Promise(function(resolve) { 9 | var contents = fsUtils.readSync(xmlPath, { encoding: 'utf8' }); 10 | var parser = new xml2js.Parser(); 11 | 12 | parser.parseString(contents, function (err, result) { 13 | if (err) { 14 | logger.error(err); 15 | } 16 | 17 | if (result) { 18 | resolve(result); 19 | } 20 | }); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /lib/utils/run-validators.js: -------------------------------------------------------------------------------- 1 | var RSVP = require('rsvp'); 2 | var chain = require('lodash').chain; 3 | 4 | module.exports = function(validators) { 5 | return RSVP.allSettled(validators).then(function(result) { 6 | var errors = chain(result) 7 | .filter({state: 'rejected'}) 8 | .map('reason') 9 | .value() 10 | 11 | if (errors.length > 0) { 12 | var message = 'Validation error(s) \n \n'; 13 | message += errors.join('\n \n'); 14 | return RSVP.reject(message); 15 | } else { 16 | return RSVP.resolve(); 17 | } 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /lib/utils/string.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | camelize: function(str) { 5 | return str.replace(/-([(a-zA-Z1-9])/g, function (m, w) { 6 | return w.toUpperCase(); 7 | }); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /node-tests/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'parserOptions': { 3 | 'ecmaVersion': 6 4 | }, 5 | 6 | 'env': { 7 | 'browser': false, 8 | 'node': true, 9 | 'mocha': true 10 | }, 11 | 12 | 'rules': { 13 | // JSHint "expr", disabled due to chai expect assertions 14 | 'no-unused-expressions': 0 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /node-tests/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "browser": false, 3 | "node": true, 4 | "esnext": true, 5 | "globals": { 6 | /* MOCHA */ 7 | "describe" : false, 8 | "it" : false, 9 | "before" : false, 10 | "beforeEach" : false, 11 | "context" : false, 12 | "after" : false, 13 | "afterEach" : false 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/analytics.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | track: function() {}, 3 | trackTiming: function() {}, 4 | trackError: function() {} 5 | } 6 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/dist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/node-tests/fixtures/ember-cordova-mock/dist/.gitkeep -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/.gitignore: -------------------------------------------------------------------------------- 1 | cordova 2 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/cordova/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | emberCordovaDummyApp 4 | 5 | A sample Apache Cordova application that responds to the deviceready event. 6 | 7 | 8 | Apache Cordova Team 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/cordova/plugins/fetch.json: -------------------------------------------------------------------------------- 1 | { 2 | "cordova-test-plugin": {} 3 | } 4 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/cordova/plugins/ios.json: -------------------------------------------------------------------------------- 1 | { 2 | "installed_plugins": { 3 | "cordova-test-plugin": {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/hooks/hook-promise-rejected.js: -------------------------------------------------------------------------------- 1 | var Promise = require('rsvp'); 2 | 3 | module.exports = function() { 4 | return Promise.reject('hook rejected'); 5 | }; 6 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/hooks/hook-promise-resolved.js: -------------------------------------------------------------------------------- 1 | var Promise = require('rsvp'); 2 | 3 | module.exports = function() { 4 | return Promise.resolve('resolved promise from hook'); 5 | }; 6 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/hooks/hook-with-error.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | throw new Error("hook failed") 3 | }; 4 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/hooks/hook-with-options.js: -------------------------------------------------------------------------------- 1 | var Promise = require('rsvp'); 2 | 3 | module.exports = function(options) { 4 | return Promise.resolve(options); 5 | }; 6 | 7 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/ember-cordova/hooks/hook.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mock-project", 3 | "devDependencies": {} 4 | } 5 | -------------------------------------------------------------------------------- /node-tests/fixtures/ember-cordova-mock/project.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | 5 | module.exports = { 6 | env: 'development', 7 | id: 'ember-cordova-mock', 8 | name: 'ember-cordova-mock', 9 | 10 | project: { 11 | root: path.resolve(__dirname, '..', '..', 'fixtures', 'ember-cordova-mock'), 12 | name: function() { return 'ember-cordova-mock' }, 13 | isEmberCLIProject: function() { return true; } 14 | }, 15 | 16 | config: function() {} 17 | } 18 | -------------------------------------------------------------------------------- /node-tests/helpers/expect.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var chai = require('chai'); 4 | var chaiAsPromised = require('chai-as-promised'); 5 | 6 | chai.use(chaiAsPromised); 7 | 8 | module.exports = chai.expect; 9 | -------------------------------------------------------------------------------- /node-tests/unit/blueprint/index-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 6 | var Promise = require('rsvp').Promise; 7 | 8 | describe('Blueprint Index', function() { 9 | var index; 10 | var called = false; 11 | 12 | beforeEach(function() { 13 | called = false; 14 | 15 | td.replace('../../../lib/utils/init-project', function() { 16 | called = true; 17 | return Promise.resolve(); 18 | }); 19 | 20 | index = require('../../../blueprints/ember-cordova/index'); 21 | index.project = mockProject.project; 22 | index.ui = mockProject.ui; 23 | }); 24 | 25 | afterEach(function() { 26 | td.reset(); 27 | }); 28 | 29 | 30 | it('runs the init util', function() { 31 | return index.afterInstall({}).then(function() { 32 | expect(called).to.equal(true); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /node-tests/unit/commands/build-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | 5 | var expect = require('../../helpers/expect'); 6 | var Promise = require('rsvp'); 7 | 8 | var BuildTask = require('../../../lib/tasks/ember-build'); 9 | var CdvBuildTask = require('../../../lib/tasks/cordova-build'); 10 | var HookTask = require('../../../lib/tasks/run-hook'); 11 | 12 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 13 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 14 | 15 | var isAnything = td.matchers.anything; 16 | 17 | /* eslint-disable max-len */ 18 | var ValidatePlatform = require('../../../lib/tasks/validate/platform'); 19 | var ValidateAllowNavigation = require('../../../lib/tasks/validate/allow-navigation'); 20 | var ValidateRootUrl = require('../../../lib/tasks/validate/root-url'); 21 | var LintIndex = require('../../../lib/tasks/lint-index'); 22 | /* eslint-enable max-len */ 23 | 24 | var setupBuild = function() { 25 | var BuildCmd = require('../../../lib/commands/build'); 26 | 27 | var project = mockProject.project; 28 | project.config = function() { 29 | return { 30 | locationType: 'hash' 31 | }; 32 | } 33 | 34 | var build = new BuildCmd({ 35 | project: project 36 | }); 37 | build.analytics = mockAnalytics; 38 | 39 | return build; 40 | }; 41 | 42 | describe('Build Command', function() { 43 | afterEach(function() { 44 | td.reset(); 45 | }); 46 | 47 | context('when locationType is hash', function() { 48 | var tasks; 49 | var cordovaPlatform; 50 | 51 | beforeEach(function() { 52 | mockTasks(); 53 | }); 54 | 55 | function mockTasks() { 56 | tasks = []; 57 | 58 | td.replace(ValidatePlatform.prototype, 'run', function() { 59 | tasks.push('validate-platform'); 60 | return Promise.resolve(); 61 | }); 62 | 63 | td.replace(ValidateAllowNavigation.prototype, 'run', function() { 64 | tasks.push('validate-allow-navigation'); 65 | return Promise.resolve(); 66 | }); 67 | 68 | td.replace(ValidateRootUrl.prototype, 'run', function() { 69 | tasks.push('validate-root-url'); 70 | return Promise.resolve(); 71 | }); 72 | 73 | td.replace(HookTask.prototype, 'run', function(hookName, options) { 74 | tasks.push('hook ' + hookName); 75 | return Promise.resolve(); 76 | }); 77 | 78 | td.replace(BuildTask.prototype, 'run', function() { 79 | tasks.push('ember-build'); 80 | return Promise.resolve(); 81 | }); 82 | 83 | td.replace(CdvBuildTask.prototype, 'run', function() { 84 | cordovaPlatform = this.platform; 85 | 86 | tasks.push('cordova-build'); 87 | return Promise.resolve(); 88 | }); 89 | 90 | td.replace(LintIndex.prototype, 'run', function() { 91 | tasks.push('lint-index'); 92 | return Promise.resolve(); 93 | }); 94 | } 95 | 96 | it('exits cleanly', function() { 97 | var build = setupBuild(); 98 | 99 | return expect(function() { 100 | build.run({}); 101 | }).not.to.throw(Error); 102 | }); 103 | 104 | it('runs tasks in the correct order', function() { 105 | var build = setupBuild(); 106 | 107 | return build.run({}) 108 | .then(function() { 109 | //h-t ember-electron for the pattern 110 | expect(tasks).to.deep.equal([ 111 | 'hook beforeBuild', 112 | 'validate-root-url', 113 | 'validate-allow-navigation', 114 | 'validate-platform', 115 | 'ember-build', 116 | 'cordova-build', 117 | 'hook afterBuild', 118 | 'lint-index' 119 | ]); 120 | }); 121 | }); 122 | 123 | it('skips ember-build with the --skip-ember-build flag', function() { 124 | var build = setupBuild(); 125 | 126 | return build.run({skipEmberBuild: true}) 127 | .then(function() { 128 | //h-t ember-electron for the pattern 129 | expect(tasks).to.deep.equal([ 130 | 'hook beforeBuild', 131 | 'validate-root-url', 132 | 'validate-allow-navigation', 133 | 'validate-platform', 134 | 'cordova-build', 135 | 'hook afterBuild', 136 | 'lint-index' 137 | ]); 138 | }); 139 | }); 140 | 141 | it('skips cordova-build with the --skip-cordova-build flag', function() { 142 | var build = setupBuild(); 143 | 144 | return build.run({skipCordovaBuild: true}) 145 | .then(function() { 146 | //h-t ember-electron for the pattern 147 | expect(tasks).to.deep.equal([ 148 | 'hook beforeBuild', 149 | 'validate-root-url', 150 | 'validate-allow-navigation', 151 | 'ember-build', 152 | 'hook afterBuild', 153 | 'lint-index' 154 | ]); 155 | }); 156 | }); 157 | 158 | it('parses cordova build opts', function() { 159 | var optDouble = td.replace('../../../lib/utils/parse-cordova-build-opts'); 160 | var build = setupBuild(); 161 | 162 | return build.run({}).then(function() { 163 | td.verify(optDouble(isAnything(), isAnything())); 164 | }); 165 | }); 166 | 167 | it('passes platform to cordova build task', function() { 168 | var passedPlatform = 'android'; 169 | var build = setupBuild(); 170 | 171 | return build.run({platform: passedPlatform}).then(function() { 172 | expect(cordovaPlatform).to.equal(passedPlatform); 173 | }); 174 | }); 175 | }); 176 | }); 177 | -------------------------------------------------------------------------------- /node-tests/unit/commands/command-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('../../helpers/expect'); 4 | var td = require('testdouble'); 5 | var Command = require('../../../lib/commands/-command'); 6 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 7 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 8 | var isAnything = td.matchers.anything(); 9 | 10 | describe('Command', function() { 11 | afterEach(function() { 12 | td.reset(); 13 | }); 14 | 15 | var setupCmd = function() { 16 | return new Command({ 17 | project: mockProject.project 18 | }); 19 | }; 20 | 21 | it('creates an analytics object on init', function() { 22 | var cmd = setupCmd(); 23 | expect(cmd.analytics).not.to.be.null; 24 | }); 25 | 26 | it('sets uuid if none exists', function(done) { 27 | td.replace(Command.prototype, 'getUUID', function() { 28 | done(); 29 | return 'name'; 30 | }); 31 | var cmd = setupCmd(); 32 | cmd.analytics = mockAnalytics; 33 | 34 | cmd.run(); 35 | }); 36 | 37 | it('tracks commands', function() { 38 | var cmd = setupCmd(); 39 | var trackDouble = td.replace(mockAnalytics, 'track'); 40 | cmd.analytics = { track: trackDouble }; 41 | 42 | cmd.run(); 43 | td.verify(trackDouble(isAnything)); 44 | }); 45 | }); 46 | 47 | -------------------------------------------------------------------------------- /node-tests/unit/commands/init-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 6 | var Promise = require('rsvp').Promise; 7 | 8 | describe('Init Command', function() { 9 | var init; 10 | var called = false; 11 | 12 | beforeEach(function() { 13 | called = false; 14 | 15 | td.replace('../../../lib/utils/init-project', function() { 16 | called = true; 17 | return Promise.resolve(); 18 | }); 19 | 20 | var InitCommand = require('../../../lib/commands/init'); 21 | init = new InitCommand({ 22 | project: mockProject.project, 23 | ui: mockProject.ui 24 | }); 25 | }); 26 | 27 | afterEach(function() { 28 | td.reset(); 29 | }); 30 | 31 | it('runs the init util', function() { 32 | return init.run({}).then(function() { 33 | expect(called).to.equal(true); 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /node-tests/unit/commands/lint-index-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var Promise = require('rsvp').Promise; 6 | var LintTask = require('../../../lib/tasks/lint-index'); 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 9 | 10 | var LintCommand = require('../../../lib/commands/lint-index'); 11 | 12 | describe('Lint Index Command', function() { 13 | var command; 14 | 15 | afterEach(td.reset); 16 | 17 | beforeEach(function() { 18 | command = new LintCommand({ 19 | project: mockProject.project 20 | }); 21 | command.analytics = mockAnalytics; 22 | }); 23 | 24 | context('when options contains source', function() { 25 | var options = { source: 'www/index.html' }; 26 | var subject, lintTaskRunCount; 27 | 28 | beforeEach(function() { 29 | lintTaskRunCount = 0; 30 | 31 | td.replace(LintTask.prototype, 'run', function() { 32 | lintTaskRunCount++; 33 | return Promise.resolve(); 34 | }); 35 | 36 | subject = command.run(options); 37 | }); 38 | 39 | it('calls Lint Index Task', function() { 40 | return subject.then(function() { 41 | expect(lintTaskRunCount).to.eql(1); 42 | }); 43 | }); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /node-tests/unit/commands/make-icons-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var Promise = require('rsvp').Promise; 6 | 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 9 | 10 | describe('Make Icons Command', function() { 11 | var iconTaskOptions, MakeIconsCmd, makeIcons; 12 | var addedPlatforms = ['ios', 'android']; 13 | 14 | beforeEach(function() { 15 | // Manually replace function because icon task returns a promise. 16 | td.replace('splicon/src/icon-task', function(options) { 17 | // Assign options for verification because td.verify doesn't work with 18 | // manually replaced functions. 19 | iconTaskOptions = options; 20 | 21 | return Promise.resolve(); 22 | }); 23 | }); 24 | 25 | afterEach(function() { 26 | iconTaskOptions = undefined; 27 | 28 | td.reset(); 29 | }); 30 | 31 | context('when added platforms', function() { 32 | var logger; 33 | 34 | beforeEach(function() { 35 | td.replace('../../../lib/utils/get-added-platforms', function() { 36 | return addedPlatforms; 37 | }); 38 | 39 | logger = td.replace('../../../lib/utils/logger'); 40 | 41 | MakeIconsCmd = require('../../../lib/commands/make-icons'); 42 | 43 | makeIcons = new MakeIconsCmd({ 44 | project: mockProject.project, 45 | analytics: mockAnalytics 46 | }); 47 | }); 48 | 49 | /* eslint-disable max-len */ 50 | context('when options and platform is `added`', function() { 51 | var options = { 52 | source: 'ember-cordova/icon.svg', 53 | platform: ['added'] 54 | }; 55 | 56 | beforeEach(function() { 57 | return makeIcons.run(options); 58 | }); 59 | 60 | it('calls icon task with passed source, added platforms, and projectPath', function() { 61 | expect(iconTaskOptions.source).to.equal(options.source); 62 | expect(iconTaskOptions.platforms).to.deep.equal(addedPlatforms); 63 | expect(iconTaskOptions.projectPath).to.equal('ember-cordova/cordova'); 64 | }); 65 | 66 | it('logs the command starting with added platforms', function() { 67 | td.verify(logger.info(`ember-cordova: Generating icons for ${addedPlatforms.join(', ')}`)); 68 | }); 69 | }); 70 | 71 | context('when options and platform is not `added`', function() { 72 | var options = { 73 | source: 'ember-cordova/icon.svg', 74 | platform: ['ios'] 75 | }; 76 | 77 | beforeEach(function() { 78 | return makeIcons.run(options); 79 | }); 80 | 81 | it('calls icon task with passed source, passed platform, and projectPath', function() { 82 | expect(iconTaskOptions.source).to.equal(options.source); 83 | expect(iconTaskOptions.platforms).to.equal(options.platform); 84 | expect(iconTaskOptions.projectPath).to.equal('ember-cordova/cordova'); 85 | }); 86 | 87 | it('logs the command starting with passed platform', function() { 88 | td.verify(logger.info(`ember-cordova: Generating icons for ${options.platform.join(', ')}`)); 89 | }); 90 | }); 91 | /* eslint-enable max-len */ 92 | }); 93 | 94 | context('when no added platforms', function() { 95 | beforeEach(function() { 96 | td.replace('../../../lib/utils/get-added-platforms', function() { 97 | return []; 98 | }); 99 | 100 | MakeIconsCmd = require('../../../lib/commands/make-icons'); 101 | 102 | makeIcons = new MakeIconsCmd({ 103 | project: mockProject.project, 104 | analytics: mockAnalytics 105 | }); 106 | }); 107 | 108 | context('when options and platform is `added`', function() { 109 | var options = { 110 | source: 'ember-cordova/icon.svg', 111 | platform: ['added'] 112 | }; 113 | 114 | it('throws an error', function() { 115 | expect(function() { makeIcons.run(options) }).to.throw(Error); 116 | }); 117 | }); 118 | }); 119 | }); 120 | -------------------------------------------------------------------------------- /node-tests/unit/commands/make-splashes-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var Promise = require('rsvp').Promise; 6 | 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 9 | 10 | describe('Make Splashes Command', function() { 11 | var splashTaskOptions, MakeSplashesCmd, makeSplashes; 12 | var addedPlatforms = ['ios', 'android']; 13 | 14 | beforeEach(function() { 15 | // Manually replace function because splash task returns a promise. 16 | td.replace('splicon/src/splash-task', function(options) { 17 | // Assign options for verification because td.verify doesn't work with 18 | // manually replaced functions. 19 | splashTaskOptions = options; 20 | 21 | return Promise.resolve(); 22 | }); 23 | }); 24 | 25 | afterEach(function() { 26 | splashTaskOptions = undefined; 27 | 28 | td.reset(); 29 | }); 30 | 31 | context('when added platforms', function() { 32 | var logger; 33 | 34 | beforeEach(function() { 35 | td.replace('../../../lib/utils/get-added-platforms', function() { 36 | return addedPlatforms; 37 | }); 38 | 39 | logger = td.replace('../../../lib/utils/logger'); 40 | 41 | MakeSplashesCmd = require('../../../lib/commands/make-splashes'); 42 | 43 | makeSplashes = new MakeSplashesCmd({ 44 | project: mockProject.project, 45 | analytics: mockAnalytics 46 | }); 47 | }); 48 | 49 | /* eslint-disable max-len */ 50 | context('when options and platform is `added`', function() { 51 | var options = { 52 | source: 'ember-cordova/splash.svg', 53 | platform: ['added'] 54 | }; 55 | 56 | beforeEach(function() { 57 | return makeSplashes.run(options); 58 | }); 59 | 60 | it('calls splash task with passed source, added platforms, and projectPath', function() { 61 | expect(splashTaskOptions.source).to.equal(options.source); 62 | expect(splashTaskOptions.platforms).to.deep.equal(addedPlatforms); 63 | expect(splashTaskOptions.projectPath).to.equal('ember-cordova/cordova'); 64 | }); 65 | 66 | it('logs the command starting with added platforms', function() { 67 | td.verify(logger.info(`ember-cordova: Generating splashes for ${addedPlatforms.join(', ')}`)); 68 | }); 69 | }); 70 | 71 | context('when options and platform is not `added`', function() { 72 | var options = { 73 | source: 'ember-cordova/splash.svg', 74 | platform: ['ios'] 75 | }; 76 | 77 | beforeEach(function() { 78 | return makeSplashes.run(options); 79 | }); 80 | 81 | it('calls splash task with passed source, passed platform, and projectPath', function() { 82 | expect(splashTaskOptions.source).to.equal(options.source); 83 | expect(splashTaskOptions.platforms).to.equal(options.platform); 84 | expect(splashTaskOptions.projectPath).to.equal('ember-cordova/cordova'); 85 | }); 86 | 87 | it('logs the command starting with passed platform', function() { 88 | td.verify(logger.info(`ember-cordova: Generating splashes for ${options.platform.join(', ')}`)); 89 | }); 90 | }); 91 | /* eslint-enable max-len */ 92 | }); 93 | 94 | context('when no added platforms', function() { 95 | beforeEach(function() { 96 | td.replace('../../../lib/utils/get-added-platforms', function() { 97 | return []; 98 | }); 99 | 100 | MakeSplashesCmd = require('../../../lib/commands/make-splashes'); 101 | 102 | makeSplashes = new MakeSplashesCmd({ 103 | project: mockProject.project, 104 | analytics: mockAnalytics 105 | }); 106 | }); 107 | 108 | context('when options and platform is `added`', function() { 109 | var options = { 110 | source: 'ember-cordova/splash.svg', 111 | platform: ['added'] 112 | }; 113 | 114 | it('throws an error', function() { 115 | expect(function() { makeSplashes.run(options) }).to.throw(Error); 116 | }); 117 | }); 118 | }); 119 | }); 120 | -------------------------------------------------------------------------------- /node-tests/unit/commands/open-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var PromiseExt = require('rsvp'); 5 | 6 | var OpenCmd = require('../../../lib/commands/open'); 7 | var OpenTask = require('../../../lib/tasks/open-app'); 8 | 9 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 10 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 11 | 12 | describe('Open Command', function() { 13 | var open; 14 | 15 | beforeEach(function() { 16 | open = new OpenCmd({ 17 | project: mockProject.project 18 | }); 19 | open.analytics = mockAnalytics; 20 | 21 | td.replace( 22 | OpenTask.prototype, 23 | 'run', 24 | function() { return PromiseExt.resolve(); } 25 | ); 26 | }); 27 | 28 | afterEach(function() { 29 | td.reset(); 30 | }); 31 | 32 | it('runs Open App Task', function() { 33 | var options = { application: 'dummy', platform: 'ios' }; 34 | 35 | return open.run(options) 36 | .then(function() { 37 | return true; 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /node-tests/unit/commands/platform-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var PlatformCmd = require('../../../lib/commands/platform'); 6 | var CdvRawTask = require('../../../lib/tasks/cordova-raw'); 7 | var SetupViewTask = require('../../../lib/tasks/setup-webview'); 8 | var Promise = require('rsvp'); 9 | 10 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 11 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 12 | 13 | describe('Platform Command', function() { 14 | var platform; 15 | 16 | beforeEach(function() { 17 | platform = new PlatformCmd({ 18 | project: mockProject.project 19 | }); 20 | platform.analytics = mockAnalytics; 21 | }); 22 | 23 | afterEach(function() { 24 | td.reset(); 25 | }); 26 | 27 | describe('Platform Install', function() { 28 | beforeEach(function() { 29 | td.replace(SetupViewTask.prototype, 'run', function() { 30 | return Promise.resolve(); 31 | }); 32 | }); 33 | 34 | it('passes command to Cordova Raw Task', function() { 35 | var rawCommand, rawPlugins; 36 | 37 | td.replace(CdvRawTask.prototype, 'run', function(cmd, plugins) { 38 | rawCommand = cmd; 39 | rawPlugins = plugins; 40 | 41 | return Promise.resolve(); 42 | }); 43 | 44 | return platform.run({}, ['add', 'ios']).then(function() { 45 | expect(rawCommand).to.equal('add'); 46 | expect(rawPlugins).to.equal('ios'); 47 | }); 48 | }); 49 | 50 | it('passes the save flag', function() { 51 | var rawOpts; 52 | var opts = { save: false }; 53 | 54 | td.replace(CdvRawTask.prototype, 'run', function(cmd, plugins, options) { 55 | rawOpts = options; 56 | return Promise.resolve(); 57 | }); 58 | 59 | return platform.run(opts, ['add', 'ios']).then(function() { 60 | expect(rawOpts).to.have.property('save').and.equal(false); 61 | }); 62 | }); 63 | }); 64 | 65 | describe('webview upgrades', function() { 66 | beforeEach(function() { 67 | td.replace(CdvRawTask.prototype, 'run', function(cmd, plugins, options) { 68 | return Promise.resolve(); 69 | }); 70 | }); 71 | 72 | it('calls SetupWebView to handle init', function() { 73 | var setupViewDouble = td.replace(SetupViewTask.prototype, 'run'); 74 | 75 | return platform.run({}, ['add', 'ios']).then(function() { 76 | td.verify(setupViewDouble()); 77 | }); 78 | }); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /node-tests/unit/commands/plugin-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var PluginCmd = require('../../../lib/commands/plugin'); 5 | var CdvRawTask = require('../../../lib/tasks/cordova-raw'); 6 | 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 9 | var isAnything = td.matchers.anything(); 10 | var contains = td.matchers.contains; 11 | 12 | describe('Plugin Command', function() { 13 | var rawDouble, plugin; 14 | 15 | beforeEach(function() { 16 | plugin = new PluginCmd({ 17 | project: mockProject.project 18 | }); 19 | plugin.analytics = mockAnalytics; 20 | 21 | rawDouble = td.replace(CdvRawTask.prototype, 'run'); 22 | }); 23 | 24 | afterEach(function() { 25 | td.reset(); 26 | }); 27 | 28 | it('passes command to Cordova Raw', function() { 29 | return plugin.run({}, ['add', 'cordova-plugin']).then(function() { 30 | td.verify(rawDouble('add', 'cordova-plugin', isAnything)); 31 | }); 32 | }); 33 | 34 | it('passes the save flag', function() { 35 | var opts = { save: false }; 36 | return plugin.run(opts, ['add', 'cordova-plugin']).then(function() { 37 | td.verify(rawDouble('add', 'cordova-plugin', contains({ save: false }))); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /node-tests/unit/commands/prepare-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var Promise = require('rsvp'); 6 | 7 | var PrepareCmd = require('../../../lib/commands/prepare'); 8 | var PrepareTask = require('../../../lib/tasks/prepare'); 9 | var HookTask = require('../../../lib/tasks/run-hook'); 10 | 11 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 12 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 13 | 14 | describe('Prepare Command', function() { 15 | var tasks, prepare; 16 | 17 | beforeEach(function() { 18 | tasks = []; 19 | 20 | prepare = new PrepareCmd({ 21 | project: mockProject.project 22 | }); 23 | prepare.analytics = mockAnalytics; 24 | 25 | td.replace(PrepareTask.prototype, 'run', function(hookName) { 26 | tasks.push('prepare'); 27 | }); 28 | 29 | td.replace(HookTask.prototype, 'run', function(hookName, options) { 30 | tasks.push('hook ' + hookName); 31 | return Promise.resolve(); 32 | }); 33 | }); 34 | 35 | afterEach(function() { 36 | PrepareTask.prototype.project = undefined; 37 | 38 | td.reset(); 39 | }); 40 | 41 | it('runs tasks in the correct order', function() { 42 | return prepare.run({}).then(function() { 43 | ////h-t ember-electron for the pattern 44 | expect(tasks).to.deep.equal([ 45 | 'hook beforePrepare', 46 | 'prepare', 47 | 'hook afterPrepare' 48 | ]); 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /node-tests/unit/commands/proxy-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var BashTask = require('../../../lib/tasks/bash'); 4 | var VerifyInstall = require('../../../lib/tasks/validate/cordova-installed'); 5 | var CordovaCmd = require('../../../lib/commands/proxy'); 6 | var logger = require('../../../lib/utils/logger'); 7 | 8 | 9 | var td = require('testdouble'); 10 | var Promise = require('rsvp'); 11 | 12 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 13 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 14 | var isObject = td.matchers.isA(Object); 15 | var contains = td.matchers.contains; 16 | 17 | describe('Cordova Command', function() { 18 | var setupCmd = function() { 19 | td.replace(VerifyInstall.prototype, 'run', function() { 20 | return Promise.resolve(); 21 | }); 22 | 23 | var cmd = new CordovaCmd({ 24 | project: mockProject.project 25 | }); 26 | cmd.analytics = mockAnalytics; 27 | 28 | return cmd; 29 | }; 30 | 31 | afterEach(function() { 32 | td.reset(); 33 | }); 34 | 35 | it('warns if an ember-cordova command is used', function() { 36 | var logDouble = td.replace(logger, 'warn'); 37 | var cmd = setupCmd(); 38 | 39 | td.replace(cmd, 'run', function() { 40 | return Promise.resolve(); 41 | }); 42 | 43 | return cmd.validateAndRun(['build']).then(function() { 44 | td.verify(logDouble(contains('bypassed ember-cordova command'))); 45 | }); 46 | }); 47 | 48 | it('warns if cordova command is unknown', function() { 49 | var logDouble = td.replace(logger, 'warn'); 50 | var cmd = setupCmd(); 51 | 52 | td.replace(cmd, 'run', function() { 53 | return Promise.resolve(); 54 | }); 55 | 56 | return cmd.validateAndRun(['foo']).then(function() { 57 | td.verify(logDouble(contains('unknown Cordova command'))); 58 | }); 59 | }); 60 | 61 | it('proxies argument commands', function(done) { 62 | var bashDouble = td.replace(BashTask.prototype, 'runCommand'); 63 | var cmd = setupCmd(); 64 | 65 | cmd.validateAndRun(['plugin add foo']).then(function() { 66 | td.verify(bashDouble('cordova plugin add foo', isObject)); 67 | done(); 68 | }).catch(function(err) { 69 | done(err); 70 | }); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /node-tests/unit/commands/serve-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var Promise = require('rsvp'); 6 | var path = require('path'); 7 | 8 | var ServeCmd = require('../../../lib/commands/serve'); 9 | var ServeTask = require('../../../lib/tasks/serve'); 10 | var CdvBuildTask = require('../../../lib/tasks/cordova-build'); 11 | var BashTask = require('../../../lib/tasks/bash'); 12 | var HookTask = require('../../../lib/tasks/run-hook'); 13 | var LRloadShellTask = require('../../../lib/tasks/create-livereload-shell'); 14 | var editXml = require('../../../lib/utils/edit-xml'); 15 | var parseXml = require('../../../lib/utils/parse-xml'); 16 | var cordovaPath = require('../../../lib/utils/cordova-path'); 17 | 18 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 19 | var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics'); 20 | 21 | /* eslint-disable max-len */ 22 | var ValidatePlatform = require('../../../lib/tasks/validate/platform'); 23 | var ValidatePlugin = require('../../../lib/tasks/validate/plugin'); 24 | var ValidateAllowNavigation = require('../../../lib/tasks/validate/allow-navigation'); 25 | var ValidateRootUrl = require('../../../lib/tasks/validate/root-url'); 26 | /* eslint-enable max-len */ 27 | 28 | describe('Serve Command', function() { 29 | var serveCmd; 30 | 31 | afterEach(function() { 32 | editXml.removeNavigation(mockProject.project); 33 | td.reset(); 34 | }); 35 | 36 | beforeEach(function() { 37 | serveCmd = new ServeCmd({ 38 | project: mockProject.project 39 | }); 40 | 41 | serveCmd.analytics = mockAnalytics; 42 | serveCmd.project.config = function() { 43 | return { 44 | locationType: 'hash', 45 | 46 | }; 47 | }; 48 | }); 49 | 50 | context('when locationType is hash', function() { 51 | var tasks = []; 52 | 53 | beforeEach(function() { 54 | mockTasks(); 55 | }); 56 | 57 | function mockTasks() { 58 | tasks = []; 59 | 60 | td.replace(HookTask.prototype, 'run', function(hookName) { 61 | tasks.push('hook ' + hookName); 62 | return Promise.resolve(); 63 | }); 64 | 65 | td.replace(ValidatePlatform.prototype, 'run', function() { 66 | tasks.push('validate-platform'); 67 | return Promise.resolve(); 68 | }); 69 | 70 | td.replace(ValidatePlugin.prototype, 'run', function() { 71 | tasks.push('validate-plugin'); 72 | return Promise.resolve(); 73 | }); 74 | 75 | td.replace(ValidateAllowNavigation.prototype, 'run', function() { 76 | tasks.push('validate-allow-navigation'); 77 | return Promise.resolve(); 78 | }); 79 | 80 | td.replace(ValidateRootUrl.prototype, 'run', function() { 81 | tasks.push('validate-root-url'); 82 | return Promise.resolve(); 83 | }); 84 | 85 | td.replace(LRloadShellTask.prototype, 'run', function() { 86 | tasks.push('create-livereload-shell'); 87 | return Promise.resolve(); 88 | }); 89 | 90 | td.replace(CdvBuildTask.prototype, 'run', function() { 91 | tasks.push('cordova-build'); 92 | return Promise.resolve(); 93 | }); 94 | 95 | td.replace(ServeTask.prototype, 'run', function() { 96 | tasks.push('ember-build-serve'); 97 | return Promise.resolve(); 98 | }); 99 | 100 | td.replace(BashTask.prototype, 'run', function() { 101 | tasks.push('serve-bash'); 102 | return Promise.resolve(); 103 | }); 104 | 105 | td.replace(ServeCmd, '_serveHang', function() { 106 | return Promise.resolve(); 107 | }); 108 | } 109 | 110 | it('exits cleanly', function() { 111 | return expect(function() { 112 | serveCmd.run({}); 113 | }).not.to.throw(Error); 114 | }); 115 | 116 | it('runs tasks in the correct order', function() { 117 | return serveCmd.run({}).then(function() { 118 | expect(tasks).to.deep.equal([ 119 | 'validate-root-url', 120 | 'validate-allow-navigation', 121 | 'validate-platform', 122 | 'validate-plugin', 123 | 'hook beforeBuild', 124 | 'create-livereload-shell', 125 | 'cordova-build', 126 | 'hook afterBuild', 127 | 'ember-build-serve' 128 | ]); 129 | }); 130 | }); 131 | 132 | it('add reloadUrl to the xml file', function() { 133 | return serveCmd.run({ 134 | reloadUrl: 'test-url' 135 | }).then(function() { 136 | var cdvPath = cordovaPath(mockProject.project); 137 | var configPath = path.join(cdvPath, 'config.xml'); 138 | var xml = parseXml(configPath); 139 | var node = xml._result.widget['allow-navigation'].pop().$.href; 140 | 141 | expect(node).to.equal('test-url'); 142 | }); 143 | }); 144 | 145 | 146 | it('skips emer & cordova builds with --skip flags', function() { 147 | return serveCmd.run({ 148 | skipEmberBuild: true, 149 | skipCordovaBuild: true 150 | }).then(function() { 151 | expect(tasks).to.deep.equal([ 152 | 'validate-root-url', 153 | 'validate-allow-navigation', 154 | 'validate-platform', 155 | 'validate-plugin', 156 | 'hook beforeBuild', 157 | 'create-livereload-shell', 158 | 'hook afterBuild' 159 | ]); 160 | }); 161 | }); 162 | }); 163 | }); 164 | -------------------------------------------------------------------------------- /node-tests/unit/index-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var fs = require('fs'); 5 | var expect = require('../helpers/expect'); 6 | var isAnything = td.matchers.anything; 7 | 8 | var stubIndex = function() { 9 | var stub = require('../../index'); 10 | stub.project = { 11 | targetIsCordova: true, 12 | RELOAD_PORT: 1, 13 | CORDOVA_PLATFORM: 'ios' 14 | }; 15 | 16 | stub._super = {}; 17 | stub._super.treeForPublic = function(tree) { return tree }; 18 | 19 | return stub; 20 | }; 21 | 22 | describe('Index', function() { 23 | afterEach(function() { 24 | td.reset(); 25 | }); 26 | 27 | context('with target cordova', function() { 28 | describe('contentFor', function() { 29 | it('adds a cordova script tag', function() { 30 | var projectIndex = stubIndex(); 31 | 32 | expect( 33 | projectIndex.contentFor('body') 34 | ).to.equal( 35 | '' 36 | ); 37 | }); 38 | }); 39 | 40 | describe('with target liveReload', function() { 41 | it('attempts to add cordova assets to tree', function() { 42 | td.replace(fs, 'existsSync', function() { 43 | return true; 44 | }); 45 | 46 | var projectIndex = stubIndex(); 47 | var buildTreeDouble = td.replace(projectIndex, 'cordovaAssetTree'); 48 | projectIndex.project.targetIsCordovaLivereload = true; 49 | 50 | projectIndex.treeForPublic() 51 | td.verify(buildTreeDouble(isAnything())); 52 | }); 53 | 54 | it('first gets cordova asset paths, then validates them', function() { 55 | var cordovaAssets = require('../../lib/utils/cordova-assets'); 56 | td.replace('../../lib/utils/cordova-path'); 57 | 58 | var assetCalls = []; 59 | td.replace(cordovaAssets, 'getPaths', function() { 60 | assetCalls.push('get-paths'); 61 | return { 62 | assetsPath: '' 63 | } 64 | }); 65 | td.replace(cordovaAssets, 'validatePaths', function() { 66 | assetCalls.push('validate-paths'); 67 | }); 68 | 69 | var projectIndex = stubIndex(); 70 | td.replace(projectIndex, '_mergeTrees'); 71 | projectIndex.cordovaAssetTree(); 72 | 73 | expect(assetCalls).to.deep.equal(['get-paths', 'validate-paths']); 74 | }); 75 | }); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /node-tests/unit/lint-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var glob = require('glob').sync; 4 | var lint = require('mocha-eslint'); 5 | var paths, options; 6 | 7 | // ht ember-cli 8 | paths = glob('node-tests/*').filter(function(path) { 9 | return !/fixtures/.test(path); 10 | }); 11 | 12 | paths = paths.concat([ 13 | 'lib', 14 | 'bin', 15 | 'blueprints' 16 | ]); 17 | 18 | options = { 19 | timeout: 5000, 20 | slow: 1000, 21 | strict: true 22 | }; 23 | 24 | lint(paths, options); 25 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/bash-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var childProcess = require('child_process'); 5 | var BashTask = require('../../../lib/tasks/bash'); 6 | 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var defaults = require('lodash').defaults; 9 | var isObject = td.matchers.isA(Object); 10 | 11 | describe('Bash Task', function() { 12 | var execDouble, bashCmd; 13 | 14 | beforeEach(function() { 15 | execDouble = td.replace(childProcess, 'execSync'); 16 | 17 | bashCmd = new BashTask(defaults(mockProject, { 18 | command: 'foo' 19 | })); 20 | }); 21 | 22 | afterEach(function() { 23 | td.reset(); 24 | }); 25 | 26 | it('attempts to exec cmd', function() { 27 | bashCmd.run(); 28 | 29 | td.verify(execDouble('foo', isObject)); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/cordova-build-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 5 | var CdvRawTask = require('../../../lib/tasks/cordova-raw'); 6 | 7 | var setupBuildTask = function() { 8 | var CdvBuildTask = require('../../../lib/tasks/cordova-build'); 9 | return new CdvBuildTask(mockProject); 10 | }; 11 | 12 | describe('Cordova Build Task', function() { 13 | afterEach(function() { 14 | td.reset(); 15 | }); 16 | 17 | it('creates a raw build task', function() { 18 | var cdvBuild = td.replace(CdvRawTask.prototype, 'run'); 19 | var build = setupBuildTask(); 20 | build.platform = 'ios'; 21 | build.run(); 22 | 23 | td.verify(cdvBuild({platforms: ['ios'], options: {}, verbose: false})); 24 | }); 25 | 26 | it('sets platform to android', function() { 27 | var cdvBuild = td.replace(CdvRawTask.prototype, 'run'); 28 | var build = setupBuildTask(); 29 | build.platform = 'android'; 30 | build.run(); 31 | 32 | td.verify(cdvBuild({platforms: ['android'], options: {}, verbose: false})); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/cordova-raw-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var RawTask = require('../../../lib/tasks/cordova-raw'); 4 | var td = require('testdouble'); 5 | var expect = require('../../helpers/expect'); 6 | var cordovaPath = require('../../../lib/utils/cordova-path'); 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var Promise = require('rsvp'); 9 | var cordovaLib = require('cordova-lib'); 10 | var cordovaProj = cordovaLib.cordova; 11 | var events = cordovaLib.events; 12 | var cordovaLogger = require('cordova-common').CordovaLogger.get(); 13 | 14 | describe('Cordova Raw Task', function() { 15 | var setupTask = function() { 16 | return new RawTask({ 17 | rawApi: 'platform', 18 | project: mockProject.project 19 | }); 20 | }; 21 | 22 | afterEach(function() { 23 | td.reset(); 24 | }); 25 | 26 | it('attempts to run a raw cordova call', function(done) { 27 | td.replace(cordovaProj.raw, 'platform', function() { 28 | done(); 29 | }); 30 | 31 | var raw = setupTask(); 32 | return raw.run(); 33 | }); 34 | 35 | describe('with a mock function', function() { 36 | var chdirDouble; 37 | 38 | beforeEach(function() { 39 | chdirDouble = td.replace(process, 'chdir'); 40 | 41 | td.replace(RawTask.prototype, 'cordovaRawPromise', function() { 42 | return Promise.resolve(); 43 | }); 44 | }); 45 | 46 | it('changes to cordova dir', function() { 47 | var cdvPath = cordovaPath(mockProject.project); 48 | var raw = setupTask(); 49 | 50 | return raw.run().then(function() { 51 | td.verify(chdirDouble(cdvPath)); 52 | }); 53 | }); 54 | 55 | it('changes back to ember dir on compvarion', function() { 56 | var emberPath = process.cwd(); 57 | var raw = setupTask(); 58 | 59 | return expect( 60 | raw.run().then(function() { 61 | var args = td.explain(chdirDouble).calls[1].args[0]; 62 | return args 63 | }) 64 | ).to.eventually.equal(emberPath); 65 | }); 66 | 67 | it('sets up Cordova logging', function() { 68 | td.replace(cordovaLogger, 'subscribe'); 69 | var raw = setupTask(); 70 | 71 | return raw.run().then(function() { 72 | td.verify(cordovaLogger.subscribe(events)); 73 | }); 74 | }); 75 | 76 | it('logs verbosely when requested', function() { 77 | td.replace(cordovaLogger, 'setLevel'); 78 | var raw = setupTask(); 79 | 80 | return raw.run({ verbose: true }).then(function() { 81 | td.verify(cordovaLogger.setLevel('verbose')); 82 | }); 83 | }); 84 | }); 85 | 86 | describe('when the raw task fails', function() { 87 | beforeEach(function() { 88 | td.replace(RawTask.prototype, 'cordovaRawPromise', function() { 89 | return Promise.reject(new Error('fail')); 90 | }); 91 | }); 92 | 93 | it('rejects run() with the failure', function() { 94 | var raw = setupTask(); 95 | 96 | return expect(raw.run()).to.be.rejectedWith( 97 | /fail/ 98 | ); 99 | }); 100 | }); 101 | }); 102 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/create-cordova-project-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var Promise = require('rsvp'); 5 | var path = require('path'); 6 | 7 | var fsUtils = require('../../../lib/utils/fs-utils'); 8 | var logger = require('../../../lib/utils/logger'); 9 | 10 | var cordovaProj = require('cordova-lib').cordova; 11 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 12 | var isObject = td.matchers.isA(Object); 13 | var isString = td.matchers.isA(String); 14 | var contains = td.matchers.contains; 15 | 16 | describe('Cordova Create Task', function() { 17 | var create, rawDouble; 18 | 19 | var setupCreateTask = function() { 20 | //TODO - factor me out 21 | rawDouble = td.replace(cordovaProj.raw, 'create'); 22 | 23 | var CreateCdvTask = require('../../../lib/tasks/create-cordova-project'); 24 | create = new CreateCdvTask(mockProject); 25 | }; 26 | 27 | beforeEach(function() { 28 | td.replace(fsUtils, 'mkdir', function() { 29 | return Promise.resolve(); 30 | }); 31 | 32 | td.replace(fsUtils, 'existsSync', function() { 33 | return false; 34 | }); 35 | }); 36 | 37 | afterEach(function() { 38 | td.reset(); 39 | }); 40 | 41 | it('creates an ember-cordova directory if one does not exist', function() { 42 | var expectedPath = path.resolve( 43 | __dirname, '..', '..', 44 | 'fixtures', 45 | 'ember-cordova-mock', 46 | 'ember-cordova' 47 | ); 48 | var mkDouble = td.replace(fsUtils, 'mkdir'); 49 | 50 | setupCreateTask(); 51 | 52 | create.run(); 53 | td.verify(mkDouble(expectedPath)); 54 | }); 55 | 56 | it('calls cordova.create.raw', function() { 57 | setupCreateTask(); 58 | create.run(); 59 | td.verify(rawDouble(isString, isString, isString, isObject)); 60 | }); 61 | 62 | it('forces camelcased ids and names', function() { 63 | setupCreateTask(); 64 | create.id = 'ember-cordova-app'; 65 | create.name = 'ember-cordova-app'; 66 | 67 | create.run(); 68 | 69 | /* eslint-disable max-len */ 70 | td.verify(rawDouble(isString, 'emberCordovaApp', 'emberCordovaApp', isObject)); 71 | /* eslint-enable max-len */ 72 | }); 73 | 74 | it('raises a warning if cordova project already exists', function() { 75 | // We can't replace existsSync again here without resetting the previous 76 | // replacement from beforeEach. Doing so will store the beforeEach 77 | // version as the "real" function and leak into other tests. 78 | td.reset(); 79 | td.replace(fsUtils, 'existsSync', function() { 80 | return true; 81 | }); 82 | var logDouble = td.replace(logger, 'warn'); 83 | 84 | setupCreateTask(); 85 | return create.run().then(function() { 86 | td.verify(logDouble(contains('dir already exists'))); 87 | }); 88 | }); 89 | 90 | it('defaults to the ember-cordova-template template', function() { 91 | setupCreateTask(); 92 | create.run(); 93 | 94 | var matcher = td.matchers.contains({ 95 | lib: { 96 | www: { 97 | url: 'ember-cordova-template' 98 | } 99 | } 100 | }); 101 | 102 | td.verify(rawDouble(isString, isString, isString, matcher)); 103 | }); 104 | 105 | it('builds with a template when provided', function() { 106 | setupCreateTask(); 107 | create.run('templatePath'); 108 | 109 | var matcher = td.matchers.contains({lib: { www: { url: 'templatePath'}}}); 110 | td.verify(rawDouble(isString, isString, isString, matcher)); 111 | }); 112 | }); 113 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/create-cordova-shell-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var Promise = require('rsvp'); 5 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 6 | var fsUtils = require('../../../lib/utils/fs-utils'); 7 | 8 | var expect = require('../../helpers/expect'); 9 | var contains = td.matchers.contains; 10 | var isObject = td.matchers.isA(Object); 11 | 12 | var setupTask = function(shouldMockTemplate) { 13 | var CreateShell = require('../../../lib/tasks/create-livereload-shell'); 14 | 15 | var shellTask = new CreateShell({ 16 | project: mockProject.project 17 | }); 18 | 19 | if (shouldMockTemplate) { 20 | td.replace(CreateShell.prototype, 'getShellTemplate', function() { 21 | return Promise.resolve('{{liveReloadUrl}}'); 22 | }); 23 | } 24 | 25 | return shellTask; 26 | }; 27 | 28 | describe('Create Cordova Shell Task', function() { 29 | beforeEach(function() { 30 | td.replace(fsUtils, 'write', function() { 31 | return Promise.resolve(); 32 | }); 33 | }); 34 | 35 | afterEach(function() { 36 | td.reset(); 37 | }); 38 | 39 | describe('getShellTemplate', function() { 40 | it('reads the right path', function() { 41 | var shellTask = setupTask(); 42 | var readDouble = td.replace(fsUtils, 'read'); 43 | 44 | shellTask.getShellTemplate(); 45 | td.verify(readDouble( 46 | contains('templates/livereload-shell/index.html'), 47 | isObject 48 | )); 49 | }); 50 | }); 51 | 52 | it('attempts to get shell template', function() { 53 | var shellTask = setupTask(); 54 | var called = false; 55 | 56 | td.replace(shellTask, 'getShellTemplate', function() { 57 | called = true; 58 | return Promise.resolve(); 59 | }); 60 | 61 | shellTask.run(); 62 | expect(called).to.equal(true); 63 | }); 64 | 65 | it('crateShell replaces {{liveReloadUrl}} and saves', function() { 66 | var shellTask = setupTask(true); 67 | var writeContent; 68 | 69 | td.replace(fsUtils, 'write', function(path, content) { 70 | writeContent = content; 71 | return Promise.resolve(); 72 | }); 73 | 74 | return shellTask.createShell('path', '{{liveReloadUrl}}', 'fakeUrl') 75 | .then(function() { 76 | expect(writeContent).to.equal('fakeUrl'); 77 | }); 78 | }); 79 | 80 | it('catches errors', function() { 81 | td.replace(fsUtils, 'write', function() { 82 | throw new Error(); 83 | }); 84 | 85 | var shellTask = setupTask(true); 86 | return expect(shellTask.run()).to.be.rejectedWith( 87 | /Error moving index\.html/ 88 | ); 89 | }); 90 | }); 91 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/ember-build-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var Promise = require('rsvp'); 5 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 6 | 7 | describe('Ember Build Task', function() { 8 | beforeEach(function() { 9 | td.reset(); 10 | }); 11 | 12 | it('stubs .gitkeep after ember build', function() { 13 | var createKeepDouble = td.replace('../../../lib/utils/create-gitkeep'); 14 | var EmberBuildTask = require('../../../lib/tasks/ember-build'); 15 | 16 | td.replace(EmberBuildTask.prototype, 'initBuilder', function() { 17 | return { 18 | build: function() { 19 | return Promise.resolve(); 20 | } 21 | } 22 | }); 23 | 24 | var build = new EmberBuildTask({ 25 | project: mockProject.project 26 | }); 27 | 28 | return build.run().then(function() { 29 | td.verify(createKeepDouble('ember-cordova/cordova/www/.gitkeep')); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/lint-index-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var Promise = require('rsvp').Promise; 6 | var path = require('path'); 7 | var cordovaPath = require('../../../lib/utils/cordova-path'); 8 | var fsUtils = require('../../../lib/utils/fs-utils'); 9 | var logger = require('../../../lib/utils/logger'); 10 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 11 | 12 | var LintTask = require('../../../lib/tasks/lint-index'); 13 | 14 | describe('Lint Index Task', function() { 15 | var projectPath = cordovaPath(mockProject.project); 16 | var source = 'www/index.html'; 17 | var task, subject, readFileArgs; 18 | 19 | afterEach(td.reset); 20 | 21 | beforeEach(function() { 22 | readFileArgs = null; 23 | 24 | task = new LintTask({ 25 | source: source, 26 | project: mockProject.project 27 | }); 28 | }); 29 | 30 | context('when source contains tags with path-attributes with paths relative to root', function() { // eslint-disable-line max-len 31 | var infoArg, warnArg; 32 | 33 | beforeEach(function() { 34 | infoArg = null; 35 | warnArg = null; 36 | 37 | td.replace(fsUtils, 'read', function(path) { 38 | readFileArgs = { path }; 39 | 40 | return Promise.resolve( 41 | '\n' + 42 | '\n' + 43 | ' \n' + 44 | ' \n' + 45 | '\n' + 46 | '\n' + 47 | ' \n' + 48 | '\n' + 49 | '' 50 | ); 51 | }); 52 | 53 | td.replace(logger, 'info', function(message) { 54 | infoArg = message; 55 | }); 56 | 57 | td.replace(logger, 'warn', function(message) { 58 | warnArg = message; 59 | }); 60 | 61 | subject = task.run(); 62 | }); 63 | 64 | it('calls fsUtils.read', function() { 65 | return subject.then(function() { 66 | expect(readFileArgs.path).to.eql(path.join(projectPath, source)); 67 | }); 68 | }); 69 | 70 | it('prints path to linted index.html', function() { 71 | return subject.then(function() { 72 | expect(infoArg).to.contain(source); 73 | }); 74 | }); 75 | 76 | it('prints warnings with path and line number and value', function() { 77 | return subject.then(function() { 78 | expect(warnArg).to.contain(source); 79 | 80 | expect(warnArg).to.contain( 81 | 'Line 3 ' + 82 | 'href-attribute contains unsupported path relative to root: ' + 83 | '/styles/foo.css' 84 | ); 85 | 86 | expect(warnArg).to.contain( 87 | 'Line 4 ' + 88 | 'src-attribute contains unsupported path relative to root: ' + 89 | '/scripts/foo.js' 90 | ); 91 | 92 | expect(warnArg).to.contain( 93 | 'Line 7 ' + 94 | 'src-attribute contains unsupported path relative to root: ' + 95 | '/images/foo.png' 96 | ); 97 | }); 98 | }); 99 | 100 | it('prints result', function() { 101 | return subject.then(function() { 102 | expect(warnArg).to.contain('✖ 3 problem(s)'); 103 | }); 104 | }); 105 | 106 | it('returns promise that rejects with attribute warnings', function() { 107 | return subject.then(function(warnings) { 108 | expect(warnings).to.deep.include({ 109 | tagName: 'link', 110 | name: 'href', 111 | value: '/styles/foo.css', 112 | line: 3 113 | }, { 114 | tagName: 'script', 115 | name: 'src', 116 | value: '/scripts/foo.js', 117 | line: 4 118 | }, { 119 | tagName: 'img', 120 | name: 'src', 121 | value: '/images/foo.png', 122 | line: 7 123 | }); 124 | }); 125 | }); 126 | }); 127 | 128 | context('when source contains no path attributes with path relative to root', function() { // eslint-disable-line max-len 129 | var infoArg, successArgs; 130 | 131 | beforeEach(function() { 132 | infoArg = null; 133 | successArgs = []; 134 | 135 | td.replace(fsUtils, 'read', function(path) { 136 | readFileArgs = { path }; 137 | 138 | return Promise.resolve( 139 | '\n' + 140 | '\n' + 141 | ' \n' + 142 | ' \n' + 143 | '\n' + 144 | '\n' + 145 | ' \n' + 146 | '\n' + 147 | '' 148 | ); 149 | }); 150 | 151 | td.replace(logger, 'info', function(message) { 152 | infoArg = message; 153 | }); 154 | 155 | td.replace(logger, 'success', function(message) { 156 | successArgs.push(message); 157 | }); 158 | 159 | subject = task.run(); 160 | }); 161 | 162 | it('calls fsUtils.read', function() { 163 | return subject.then(function() { 164 | expect(readFileArgs.path).to.eql(path.join(projectPath, source)); 165 | }); 166 | }); 167 | 168 | it('prints path to linted index.html', function() { 169 | return subject.then(function() { 170 | expect(infoArg).to.contain('ember-cordova: Linting ' + 171 | path.join(projectPath, source) + '...\n'); 172 | }); 173 | }); 174 | 175 | it('prints result', function() { 176 | return subject.then(function() { 177 | expect(successArgs).to.contain('0 problems'); 178 | }); 179 | }); 180 | 181 | it('returns promise that resolves', function() { 182 | return expect(subject).to.be.fulfilled; 183 | }); 184 | }); 185 | }); 186 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/open-app-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var path = require('path'); 5 | var BashTask = require('../../../lib/tasks/bash'); 6 | var OpenAppTask = require('../../../lib/tasks/open-app'); 7 | var expect = require('../../helpers/expect'); 8 | var openCommand = require('../../../lib/utils/open-app-command'); 9 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 10 | var _merge = require('lodash').merge; 11 | var isObject = td.matchers.isA(Object); 12 | 13 | describe('Open App Task', function() { 14 | var bashDouble, openApp, cdvPath; 15 | 16 | beforeEach(function() { 17 | bashDouble = td.replace(BashTask.prototype, 'runCommand'); 18 | cdvPath = path.resolve( 19 | __dirname, '..', '..', 20 | 'fixtures', 21 | 'ember-cordova-mock/ember-cordova/cordova' 22 | ); 23 | 24 | openApp = new OpenAppTask(_merge(mockProject, { platform: 'ios' })); 25 | }); 26 | 27 | afterEach(function() { 28 | td.reset(); 29 | }); 30 | 31 | it('runs open command for ios', function() { 32 | openApp.run(); 33 | var expectedPath = cdvPath + '/platforms/ios/*.xcodeproj'; 34 | var expectedCmd = openCommand(expectedPath); 35 | td.verify(bashDouble(expectedCmd, isObject)); 36 | }); 37 | 38 | it('runs open command for Android', function() { 39 | openApp.platform = 'android'; 40 | openApp.run(); 41 | 42 | var expectedPath = cdvPath + '/platforms/android/'; 43 | var expectedCmd = openCommand(expectedPath); 44 | td.verify(bashDouble(expectedCmd, isObject)); 45 | }), 46 | 47 | it('outputs an error if no platform is specified', function() { 48 | openApp.platform = 'invalidPlatform'; 49 | 50 | return expect(openApp.run()).to.be.rejectedWith( 51 | /platform is not supported/ 52 | ); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/prepare-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 5 | var CdvRawTask = require('../../../lib/tasks/cordova-raw'); 6 | 7 | var setupPrepareTask = function() { 8 | var PrepareTask = require('../../../lib/tasks/prepare'); 9 | return new PrepareTask(mockProject); 10 | }; 11 | 12 | describe('Prepare Task', function() { 13 | afterEach(function() { 14 | td.reset(); 15 | }); 16 | 17 | it('runs cordova prepare', function() { 18 | var rawDouble = td.replace(CdvRawTask.prototype, 'run'); 19 | var prepare = setupPrepareTask(); 20 | prepare.run(); 21 | 22 | td.verify(rawDouble({ verbose: false })); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/run-hook-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('../../helpers/expect'); 4 | var HookTask = require('../../../lib/tasks/run-hook'); 5 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 6 | var Promise = require('rsvp').Promise; 7 | 8 | describe('Run Hook Task', function() { 9 | it('runs a hook at the provided path', function() { 10 | var hookTask = new HookTask(mockProject); 11 | return expect(hookTask.run('hook')).to.be.fulfilled; 12 | }); 13 | 14 | it('passes options to the hook', function() { 15 | var options = {foo: true}; 16 | var hookTask = new HookTask(mockProject); 17 | var taskRun = hookTask.run('hook-with-options', options); 18 | return expect(taskRun).to.become(options); 19 | }); 20 | 21 | it('runs a hook at the provided path that has an error', function() { 22 | var hookTask = new HookTask(mockProject); 23 | return expect(hookTask.run('hook-with-error')).to.be.rejected; 24 | }); 25 | 26 | it('is resolved if the hook does not exist', function() { 27 | var hookTask = new HookTask(mockProject); 28 | return expect(hookTask.run('invalid')).to.be.fulfilled; 29 | }); 30 | 31 | it('is resolved if the hook is resolved', function() { 32 | var hookTask = new HookTask(mockProject); 33 | var expectation = expect(hookTask.run('hook-promise-resolved')); 34 | return Promise.all([ 35 | expectation.to.eventually.equal('resolved promise from hook'), 36 | expectation.to.be.fulfilled, 37 | ]); 38 | }); 39 | 40 | it('is rejected if the hook is rejected', function() { 41 | var hookTask = new HookTask(mockProject); 42 | var expectation = expect(hookTask.run('hook-promise-rejected')); 43 | return Promise.all([ 44 | expectation.to.eventually.equal('hook rejected'), 45 | expectation.to.be.rejected, 46 | ]); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/setup-webview-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var isAnything = td.matchers.anything(); 6 | var logger = require('../../../lib/utils/logger'); 7 | 8 | var CdvRawTask = require('../../../lib/tasks/cordova-raw'); 9 | var SetupViewTask = require('../../../lib/tasks/setup-webview'); 10 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 11 | var contains = td.matchers.contains; 12 | 13 | 14 | describe('Setup Webview Task', function() { 15 | var rawDouble, setupTask; 16 | 17 | beforeEach(function() { 18 | rawDouble = td.replace(CdvRawTask.prototype, 'run'); 19 | 20 | setupTask = new SetupViewTask({ 21 | project: mockProject.project, 22 | platform: 'ios' 23 | }); 24 | }); 25 | 26 | afterEach(function() { 27 | td.reset(); 28 | }); 29 | 30 | it('runs a corodva raw task to install plugins', function() { 31 | setupTask.run(); 32 | td.verify(rawDouble(isAnything, isAnything, isAnything)); 33 | }); 34 | 35 | it('warns the user of default changes in ios', function() { 36 | var warnDouble = td.replace(logger, 'warn'); 37 | var successDouble = td.replace(logger, 'success'); 38 | 39 | setupTask.run(); 40 | td.verify(warnDouble(contains( 41 | 'ember-cordova initializes ios with the upgraded WKWebView' 42 | ))); 43 | 44 | td.verify(successDouble(contains( 45 | 'Initializing cordova with upgraded WebView' 46 | ))); 47 | }); 48 | 49 | it('defaults to crosswalk=false', function() { 50 | expect(setupTask.crosswalk).to.equal(false); 51 | }); 52 | 53 | it('defaults to uiwebview=false', function() { 54 | expect(setupTask.uiwebview).to.equal(false); 55 | }); 56 | 57 | it('when crosswalk=false(default), it uses android default', function() { 58 | setupTask.platform = 'android'; 59 | setupTask.run(); 60 | td.verify(rawDouble(), {times: 0, ignoreExtraArgs: true}); 61 | }); 62 | 63 | it('when uiwebview=true, it uses ios default webview', function() { 64 | setupTask.uiwebview = true; 65 | setupTask.run(); 66 | td.verify(rawDouble(), {times: 0, ignoreExtraArgs: true}); 67 | }); 68 | 69 | it('when crosswalk=true, it uses crosswalk', function() { 70 | setupTask.platform = 'android'; 71 | setupTask.crosswalk = true; 72 | setupTask.run(); 73 | td.verify(rawDouble('add', 'cordova-plugin-crosswalk-webview', isAnything)); 74 | }); 75 | 76 | it('when uiwebview=false(default), it uses wkwebview', function() { 77 | setupTask.run(); 78 | td.verify(rawDouble('add', 'cordova-plugin-wkwebview-engine', isAnything)); 79 | }); 80 | 81 | describe('invalid platform/webview combinations', function() { 82 | it('warns ios users if crosswalk=true', function() { 83 | setupTask.crosswalk = true; 84 | let warnDouble = td.replace(setupTask, 'warnPlatform'); 85 | 86 | setupTask.run(); 87 | td.verify(warnDouble('ios', 'crosswalk=true')); 88 | }); 89 | 90 | it('warns android users if uiwebview=true', function() { 91 | setupTask.platform = 'android'; 92 | setupTask.uiwebview = true; 93 | let warnDouble = td.replace(setupTask, 'warnPlatform'); 94 | 95 | setupTask.run(); 96 | td.verify(warnDouble('android', 'uiwebview=true')); 97 | }); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/update-gitignore-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 5 | var fsUtils = require('../../../lib/utils/fs-utils'); 6 | var Promise = require('rsvp'); 7 | 8 | var expect = require('../../helpers/expect'); 9 | 10 | describe('Update gitignore Task', function() { 11 | var expectedGitkeep = ''; 12 | 13 | var createTask = function(ignoreStub) { 14 | td.replace(fsUtils, 'read', function() { 15 | return Promise.resolve(ignoreStub); 16 | }); 17 | 18 | var GitIgnore = require('../../../lib/tasks/update-gitignore'); 19 | return new GitIgnore({ 20 | project: mockProject.project 21 | }); 22 | }; 23 | 24 | beforeEach(function() { 25 | expectedGitkeep = '\n' + 26 | 'ember-cordova/tmp-livereload\n' + 27 | 'ember-cordova/cordova/node_modules\n' + 28 | 'ember-cordova/cordova/package.json\n' + 29 | 'ember-cordova/cordova/package-lock.json\n' + 30 | 'ember-cordova/cordova/platforms/*\n' + 31 | '!ember-cordova/cordova/platforms/.gitkeep\n' + 32 | 'ember-cordova/cordova/plugins/*\n' + 33 | '!ember-cordova/cordova/plugins/.gitkeep\n' + 34 | 'ember-cordova/cordova/www/*\n' + 35 | '!ember-cordova/cordova/www/.gitkeep'; 36 | 37 | }); 38 | 39 | afterEach(function() { 40 | td.reset(); 41 | }); 42 | 43 | it('attempts to write ignore data to .gitignore', function() { 44 | var writeContent; 45 | 46 | td.replace(fsUtils, 'write', function(path, content) { 47 | writeContent = content; 48 | return Promise.resolve(); 49 | }); 50 | 51 | var task = createTask(''); 52 | return task.run().then(function() { 53 | expect(writeContent).to.equal(expectedGitkeep); 54 | }); 55 | }); 56 | 57 | it('stubs empty gitkeeps, and then writes gitkeep', function() { 58 | var calls = []; 59 | td.replace(fsUtils, 'write', function(path, content) { 60 | calls.push(path); 61 | return; 62 | }); 63 | 64 | var task = createTask(); 65 | return task.run().then(function() { 66 | expect(calls).to.deep.equal([ 67 | 'ember-cordova/cordova/platforms/.gitkeep', 68 | 'ember-cordova/cordova/plugins/.gitkeep', 69 | 'ember-cordova/cordova/www/.gitkeep', 70 | '.gitignore' 71 | ]); 72 | }); 73 | }); 74 | 75 | it('does not clear existing content', function() { 76 | var writeContent; 77 | 78 | td.replace(fsUtils, 'write', function(path, content) { 79 | writeContent = content; 80 | return Promise.resolve(); 81 | }); 82 | 83 | var task = createTask('dist/'); 84 | return task.run().then(function() { 85 | expect(writeContent).to.equal('dist/' + expectedGitkeep); 86 | }); 87 | }); 88 | 89 | it('does not duplicate content', function() { 90 | var writeContent; 91 | 92 | td.replace(fsUtils, 'write', function(path, content) { 93 | if (path === '.gitignore') { 94 | writeContent = content; 95 | } 96 | return Promise.resolve(); 97 | }); 98 | 99 | var expected = 'dist/' + expectedGitkeep; 100 | var task = createTask(expected); 101 | return task.run().then(function() { 102 | expect(writeContent).to.equal(expected); 103 | }); 104 | }); 105 | 106 | it('outputs an error message and resolves if write fails', function() { 107 | td.replace(fsUtils, 'write', function() { 108 | return Promise.reject(); 109 | }); 110 | var task = createTask(); 111 | 112 | return expect(task.run()).to.be.rejectedWith( 113 | /failed to update \.gitignore/ 114 | ); 115 | }); 116 | }); 117 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/update-watchman-config-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var path = require('path'); 6 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 7 | var Promise = require('rsvp').Promise; 8 | 9 | var WatchmanConfig = require('../../../lib/tasks/update-watchman-config'); 10 | var fsUtils = require('../../../lib/utils/fs-utils'); 11 | 12 | describe('Update Watchman Config Task', function() { 13 | var watchmanTask; 14 | 15 | beforeEach(function() { 16 | watchmanTask = new WatchmanConfig({ 17 | project: mockProject.project 18 | }); 19 | }); 20 | 21 | afterEach(function() { 22 | td.reset(); 23 | }); 24 | 25 | it('attempts to read watchmanconfig', function() { 26 | var actualPath; 27 | var expectedPath = path.join(mockProject.project.root, '.watchmanconfig'); 28 | 29 | td.replace(fsUtils, 'write'); 30 | td.replace(fsUtils, 'read', function(path) { 31 | actualPath = path; 32 | return Promise.resolve(); 33 | }); 34 | 35 | watchmanTask.run(); 36 | 37 | expect(actualPath).to.equal(expectedPath); 38 | }); 39 | 40 | it('adds ember-cordova to existing ignore_dirs array', function() { 41 | var writeContents; 42 | var expectedWrite = '{"ignore_dirs":["tmp","dist","ember-cordova"]}'; 43 | 44 | td.replace(fsUtils, 'read', function(path) { 45 | return new Promise(function(resolve) { 46 | resolve('\{"ignore_dirs": ["tmp", "dist"]\}'); 47 | }); 48 | }); 49 | 50 | td.replace(fsUtils, 'write', function(path, contents) { 51 | writeContents = contents; 52 | return Promise.resolve(); 53 | }); 54 | 55 | return watchmanTask.run().then(function() { 56 | expect(writeContents).to.equal(expectedWrite); 57 | }); 58 | }); 59 | 60 | it('creates an ignore_dirs array if it does not exist', function() { 61 | var writeContents; 62 | 63 | td.replace(fsUtils, 'read', function(path) { 64 | return new Promise(function(resolve) { 65 | resolve('\{\}'); 66 | }); 67 | }); 68 | 69 | td.replace(fsUtils, 'write', function(path, contents) { 70 | writeContents = contents; 71 | return Promise.resolve(); 72 | }); 73 | 74 | return watchmanTask.run().then(function() { 75 | expect(writeContents).to.equal('{"ignore_dirs":["ember-cordova"]}'); 76 | }); 77 | }); 78 | 79 | it('does not duplicate content', function() { 80 | var writeContents; 81 | var expectedWrite = '{"ignore_dirs":["tmp","dist","ember-cordova"]}'; 82 | 83 | td.replace(fsUtils, 'read', function(path) { 84 | return new Promise(function(resolve) { 85 | resolve('\{"ignore_dirs": ["tmp", "dist", "ember-cordova"]\}'); 86 | }); 87 | }); 88 | 89 | td.replace(fsUtils, 'write', function(path, contents) { 90 | writeContents = contents; 91 | return Promise.resolve(); 92 | }); 93 | 94 | return watchmanTask.run().then(function() { 95 | expect(writeContents).to.equal(expectedWrite); 96 | }); 97 | }); 98 | }); 99 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/allow-navigation-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable max-len */ 4 | var td = require('testdouble'); 5 | var expect = require('../../../helpers/expect'); 6 | var mockProject = require('../../../fixtures/ember-cordova-mock/project'); 7 | var ValidateNav = require('../../../../lib/tasks/validate/allow-navigation'); 8 | var logger = require('../../../../lib/utils/logger'); 9 | var contains = td.matchers.contains; 10 | /* eslint-enable max-len */ 11 | 12 | describe('Validate Allow Navigation Test', function() { 13 | afterEach(function() { 14 | td.reset(); 15 | }); 16 | 17 | function setupTask() { 18 | return new ValidateNav({ 19 | project: mockProject.project 20 | }); 21 | } 22 | 23 | it('writes UNSAFE_PRODUCTION_VALUE if allowNavigation is unsafe', function() { 24 | td.replace(ValidateNav.prototype, 'livereloadProp', function() { 25 | return 'prop'; 26 | }); 27 | 28 | var warnDouble = td.replace(logger, 'warn'); 29 | var validateNav = setupTask(); 30 | return validateNav.run().then(function() { 31 | td.verify(warnDouble(contains( 32 | 'is unsafe and should not be used in production' 33 | ))); 34 | }); 35 | }); 36 | 37 | it('throws error with invalid setup && rejectIfUndefined', function() { 38 | td.replace(ValidateNav.prototype, 'livereloadProp', function() { 39 | return undefined; 40 | }); 41 | 42 | var validateNav = setupTask(); 43 | validateNav.rejectIfUndefined = true; 44 | return expect(validateNav.run()).to.be.rejectedWith( 45 | /allow-navigation href/ 46 | ); 47 | }); 48 | 49 | it('resolves immediately if the platform is browser', function() { 50 | //normally this would cause a rejection 51 | td.replace(ValidateNav.prototype, 'livereloadProp', function() { 52 | return undefined; 53 | }); 54 | 55 | var validateNav = setupTask(); 56 | validateNav.platform = 'browser'; 57 | 58 | return expect(validateNav.run()).to.be.fulfilled; 59 | }); 60 | 61 | context('validateNavigationProp', function() { 62 | it('returns true if the value is *', function() { 63 | var validateNav = setupTask(); 64 | expect(validateNav.validateNavigationProp('*')).to.not.equal(undefined); 65 | }); 66 | 67 | it('returns true if the value contains http', function() { 68 | var validateNav = setupTask(); 69 | expect( 70 | validateNav.validateNavigationProp('http') 71 | ).to.not.equal(undefined); 72 | }); 73 | 74 | it('returns true if the value contains https', function() { 75 | var validateNav = setupTask(); 76 | expect( 77 | validateNav.validateNavigationProp('https') 78 | ).to.not.equal(undefined); 79 | }); 80 | 81 | it('does not return true in any other context', function() { 82 | var validateNav = setupTask(); 83 | var invalidValues = [ 84 | 'file://', 85 | 'foo*' 86 | ]; 87 | 88 | var pos = invalidValues.length; 89 | while (pos--) { 90 | var value = invalidValues[pos]; 91 | expect(validateNav.validateNavigationProp(value)).to.equal(undefined); 92 | } 93 | }); 94 | }); 95 | 96 | context('livereloadProp', function() { 97 | it('checks each item in the json.field array', function() { 98 | var calls = 0; 99 | 100 | td.replace(ValidateNav.prototype, 'validateNavigationProp', function() { 101 | calls++; 102 | return undefined 103 | }); 104 | 105 | var validateNav = setupTask(); 106 | return validateNav.run().then(function() { 107 | expect(calls).to.equal(2); 108 | }); 109 | }); 110 | }); 111 | }); 112 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/cordova-installed-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var childProcess = require('child_process'); 5 | 6 | describe('Verify Cordova Installed Task', function() { 7 | var execDouble, verifyCmd; 8 | 9 | beforeEach(function() { 10 | execDouble = td.replace(childProcess, 'execSync'); 11 | 12 | /* eslint-disable max-len */ 13 | var VerifyTask = require('../../../../lib/tasks/validate/cordova-installed'); 14 | /* eslint-enable max-len */ 15 | 16 | verifyCmd = new VerifyTask({ 17 | command: 'foo', 18 | options: {} 19 | }); 20 | }); 21 | 22 | afterEach(function() { 23 | td.reset(); 24 | }); 25 | 26 | it('attempts to exec cmd', function() { 27 | var expected = 'command -v cordova >/dev/null && ' + 28 | '{ echo >&1 \'command found\'; }'; 29 | 30 | verifyCmd.run(); 31 | td.verify(execDouble(expected)); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/location-type-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../../helpers/expect'); 5 | var mockProject = require('../../../fixtures/ember-cordova-mock/project'); 6 | var ValidateLocType = require('../../../../lib/tasks/validate/location-type'); 7 | var logger = require('../../../../lib/utils/logger'); 8 | var contains = td.matchers.contains; 9 | 10 | describe('Validate Location Type', function() { 11 | var validateLoc; 12 | 13 | beforeEach(function() { 14 | validateLoc = new ValidateLocType({ 15 | project: mockProject.project 16 | }); 17 | }); 18 | 19 | afterEach(function() { 20 | td.reset(); 21 | }); 22 | 23 | it('rejects when config.locationType is not hash', function() { 24 | validateLoc.config = { locationType: 'auto' }; 25 | return expect(validateLoc.run()).to.be.rejected; 26 | }); 27 | 28 | it('throws an error with config.locationType is blank', function() { 29 | validateLoc.config = {}; 30 | return expect(validateLoc.run()).to.be.rejected; 31 | }); 32 | 33 | it('resolves if config.locationType is hash', function() { 34 | validateLoc.config = { locationType: 'hash' }; 35 | return expect(validateLoc.run()).to.be.fulfilled; 36 | }); 37 | 38 | it('when force is true, it warns vs rejects', function() { 39 | validateLoc.config = { locationType: 'auto' }; 40 | validateLoc.force = true; 41 | 42 | var warnDouble = td.replace(logger, 'warn'); 43 | 44 | return validateLoc.run().then(function() { 45 | td.verify(warnDouble(contains('You have passed the --force flag'))); 46 | }) 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/platform-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../../helpers/expect'); 5 | var Promise = require('rsvp'); 6 | 7 | var PlatformTask = require('../../../../lib/tasks/validate/platform'); 8 | var mockProject = require('../../../fixtures/ember-cordova-mock/project'); 9 | var CordovaValidator = require('../../../../lib/utils/cordova-validator'); 10 | 11 | describe('Validate Platform Tasks', function() { 12 | var tasks, validatePlatform; 13 | 14 | afterEach(function() { 15 | td.reset(); 16 | }); 17 | 18 | beforeEach(function() { 19 | tasks = []; 20 | validatePlatform = new PlatformTask({ 21 | project: mockProject.project, 22 | platform: 'ios' 23 | }); 24 | 25 | mockTasks(); 26 | }); 27 | 28 | function mockTasks() { 29 | td.replace(CordovaValidator.prototype, 'validateCordovaConfig', function() { 30 | tasks.push('validate-cordova-config'); 31 | return Promise.resolve(); 32 | }); 33 | 34 | td.replace(CordovaValidator.prototype, 'validateCordovaJSON', function() { 35 | tasks.push('validate-cordova-json'); 36 | return Promise.resolve(); 37 | }); 38 | 39 | td.replace(CordovaValidator.prototype, 'validateDirExists', function() { 40 | tasks.push('validate-dir'); 41 | return Promise.resolve(); 42 | }); 43 | } 44 | 45 | it('runs validations in the correct order', function() { 46 | var validatePlatform = new PlatformTask({ 47 | project: mockProject.project, 48 | platform: 'ios' 49 | }); 50 | 51 | return validatePlatform.run() 52 | .then(function() { 53 | expect(tasks).to.deep.equal([ 54 | 'validate-cordova-config', 55 | 'validate-cordova-json', 56 | 'validate-dir' 57 | ]); 58 | }); 59 | }); 60 | 61 | context('validator object', function() { 62 | var validator; 63 | 64 | beforeEach(function() { 65 | validator = validatePlatform.createValidator(); 66 | }); 67 | 68 | it('sets type to platform', function() { 69 | expect(validator.type).to.equal('platform'); 70 | }); 71 | 72 | it('sets dir to platforms/', function() { 73 | expect(validator.dir).to.equal('platforms/'); 74 | }); 75 | 76 | it('sets correct fetch json path', function() { 77 | expect(validator.jsonPath).to.equal('platforms/platforms.json'); 78 | }); 79 | }); 80 | }); 81 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/plugin-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../../helpers/expect'); 5 | var Promise = require('rsvp'); 6 | 7 | var PluginTask = require('../../../../lib/tasks/validate/plugin'); 8 | var mockProject = require('../../../fixtures/ember-cordova-mock/project'); 9 | var CordovaValidator = require('../../../../lib/utils/cordova-validator'); 10 | 11 | describe('Validate Plugin Tasks', function() { 12 | var tasks, validatePlugin; 13 | 14 | afterEach(function() { 15 | td.reset(); 16 | }); 17 | 18 | beforeEach(function() { 19 | tasks = []; 20 | 21 | validatePlugin = new PluginTask({ 22 | project: mockProject.project, 23 | platform: 'ios' 24 | }); 25 | 26 | mockTasks(); 27 | }); 28 | 29 | function mockTasks() { 30 | td.replace(CordovaValidator.prototype, 'validateCordovaConfig', function() { 31 | tasks.push('validate-cordova-config'); 32 | return Promise.resolve(); 33 | }); 34 | 35 | td.replace(CordovaValidator.prototype, 'validateCordovaJSON', function() { 36 | tasks.push('validate-cordova-json'); 37 | return Promise.resolve(); 38 | }); 39 | 40 | td.replace(CordovaValidator.prototype, 'validatePluginJSON', function() { 41 | tasks.push('validate-plugin-json'); 42 | return Promise.resolve(); 43 | }); 44 | 45 | td.replace(CordovaValidator.prototype, 'validateDirExists', function() { 46 | tasks.push('validate-dir'); 47 | return Promise.resolve(); 48 | }); 49 | } 50 | 51 | it('runs validations in the correct order', function() { 52 | return validatePlugin.run() 53 | .then(function() { 54 | expect(tasks).to.deep.equal([ 55 | 'validate-cordova-config', 56 | 'validate-cordova-json', 57 | 'validate-plugin-json', 58 | 'validate-dir' 59 | ]); 60 | }); 61 | }); 62 | 63 | context('validator object', function() { 64 | var validator; 65 | 66 | beforeEach(function() { 67 | validator = validatePlugin.createValidator(); 68 | }); 69 | 70 | it('sets type to plugin', function() { 71 | expect(validator.type).to.equal('plugin'); 72 | }); 73 | 74 | it('sets dir to plugins/', function() { 75 | expect(validator.dir).to.equal('plugins/'); 76 | }); 77 | 78 | it('sets correct fetch json path', function() { 79 | expect(validator.jsonPath).to.equal('plugins/fetch.json'); 80 | }); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/root-url-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../../helpers/expect'); 5 | var mockProject = require('../../../fixtures/ember-cordova-mock/project'); 6 | var logger = require('../../../../lib/utils/logger'); 7 | var contains = td.matchers.contains; 8 | 9 | var ValidateRoot = require('../../../../lib/tasks/validate/root-url'); 10 | 11 | var rejectMsg = 12 | 'Build Aborted. \n' + 13 | '{{rootURL}} or {{baseURL}} in config/environment has a leading slash. \n' + 14 | 'This will not work in cordova, and needs to be removed. \n' + 15 | 'You can pass the --force flag to ignore this if youve otherwise handled \n' + 16 | 'See http://embercordova.com/pages/workflow/project_setup for more info.'; 17 | 18 | describe('Validate Root Url', function() { 19 | var validateRoot; 20 | 21 | beforeEach(function() { 22 | validateRoot = new ValidateRoot({ 23 | project: mockProject.project, 24 | config: mockProject.config() 25 | }); 26 | }); 27 | 28 | afterEach(function() { 29 | td.reset(); 30 | }); 31 | 32 | it('resolves', function() { 33 | td.replace(validateRoot, 'validRootValues', function(path) { 34 | return true; 35 | }); 36 | 37 | return expect(validateRoot.run()).to.be.fulfilled; 38 | }); 39 | 40 | it('rejects if validRootValues is false', function() { 41 | td.replace(validateRoot, 'validRootValues', function(path) { 42 | return false; 43 | }); 44 | 45 | expect( 46 | validateRoot.run() 47 | ).to.be.rejectedWith(rejectMsg); 48 | }); 49 | 50 | it('does not error when the value is undefined', function() { 51 | validateRoot.config = { rootURL: undefined }; 52 | expect( 53 | validateRoot.run() 54 | ).to.be.fulfilled; 55 | }); 56 | 57 | it('when force is true, throws a warning vs rejection', function() { 58 | td.replace(validateRoot, 'validRootValues', function(path) { 59 | return false; 60 | }); 61 | 62 | var warnDouble = td.replace(logger, 'warn'); 63 | validateRoot.force = true; 64 | 65 | return validateRoot.run().then(function() { 66 | td.verify(warnDouble(contains('You have passed the --force flag'))); 67 | }) 68 | }); 69 | 70 | describe('validRootValues', function() { 71 | it('returns false if any values lead with /', function() { 72 | var values = ['valid', '/invalid']; 73 | expect(validateRoot.validRootValues(values)).to.equal(false); 74 | }); 75 | 76 | it('returns true if no values lead with /', function() { 77 | var values = ['valid', 'invalid']; 78 | expect(validateRoot.validRootValues(values)).to.equal(true); 79 | }); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /node-tests/unit/tasks/validate/sanitize-addon-args-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable max-len */ 4 | var td = require('testdouble'); 5 | var expect = require('../../../helpers/expect'); 6 | var mockProject = require('../../../fixtures/ember-cordova-mock/project'); 7 | var SanitizeArgs = require('../../../../lib/tasks/validate/sanitize-addon-args'); 8 | /* eslint-enable max-len */ 9 | 10 | describe('Sanitize Cordova Args Test', function() { 11 | afterEach(function() { 12 | td.reset(); 13 | }); 14 | 15 | function setupTask() { 16 | return new SanitizeArgs({ 17 | project: mockProject.project, 18 | api: 'plugin' 19 | }); 20 | } 21 | 22 | context('getAction', function() { 23 | var rawArgs = ['cordova', 'platform', 'foo']; 24 | 25 | it('returns add for any addCmds', function() { 26 | var validator = setupTask(); 27 | var addCmds = ['add', 'a']; 28 | 29 | var count = addCmds.length; 30 | while (count--) { 31 | var args = rawArgs.concat(addCmds[count]); 32 | var command = validator.getAction(args); 33 | expect(command).to.equal('add'); 34 | } 35 | }); 36 | 37 | it('returns remove for any removeCmds', function() { 38 | var validator = setupTask(); 39 | var rmCmds = ['remove', 'rm', 'r']; 40 | 41 | var count = rmCmds.length; 42 | while (count--) { 43 | var args = rawArgs.concat(rmCmds[count]); 44 | var command = validator.getAction(args); 45 | expect(command).to.equal('remove'); 46 | } 47 | }); 48 | }); 49 | 50 | context('with invalid add/remove flags', function() { 51 | beforeEach(function() { 52 | td.replace(SanitizeArgs.prototype, 'getAction', function() { 53 | return 54 | }); 55 | }); 56 | 57 | it('rejects the promise & warns if command is undefined', function() { 58 | var validator = setupTask(); 59 | return expect(validator.run()).to.eventually.be.rejected; 60 | }); 61 | 62 | it('rejects the promise & warns if command is undefined', function() { 63 | var validator = setupTask(); 64 | return validator.run().catch(function(err) { 65 | expect(err).to.include('Missing add/rm flag'); 66 | }); 67 | }); 68 | }); 69 | 70 | context('sanitized hash', function() { 71 | it('returns a target name (e.g. ios, plugn-camera)', function() { 72 | var args = ['add', 'cordova-plugin-foo']; 73 | var validator = setupTask(); 74 | validator.rawArgs = args; 75 | 76 | return expect(validator.run()).to.eventually 77 | .have.property('name') 78 | .and.equal('cordova-plugin-foo'); 79 | }); 80 | 81 | it('returns an action property', function() { 82 | var args = ['add', 'cordova-plugin-foo']; 83 | var validator = setupTask(); 84 | validator.rawArgs = args; 85 | 86 | return expect(validator.run()).to.eventually 87 | .have.property('action') 88 | .and.equal('add'); 89 | }); 90 | 91 | it('returns --variables formatted to cordova spec', function() { 92 | var args = ['add', 'cordova-plugin-foo']; 93 | var validator = setupTask(); 94 | validator.rawArgs = args; 95 | validator.varOpts = ['APP_ID=FOO', 'APP_NAME=FOO']; 96 | 97 | return expect(validator.run()).to.eventually 98 | .have.deep.property('varOpts.APP_ID') 99 | .and.equal('FOO'); 100 | }); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /node-tests/unit/utils/cordova-assets-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var cordovaAssets = require('../../../lib/utils/cordova-assets'); 5 | var expect = require('../../helpers/expect'); 6 | var fsUtils = require('../../../lib/utils/fs-utils'); 7 | var logger = require('../../../lib/utils/logger'); 8 | var contains = td.matchers.contains; 9 | 10 | describe('Get Platform Assets Util', function() { 11 | describe('getPaths', function() { 12 | it('is valid for ios', function() { 13 | var assets = cordovaAssets.getPaths('ios', 'fakeProjectPath'); 14 | var expectedPath = 'platforms/ios/www'; 15 | expect(assets.assetsPath).to.equal(expectedPath); 16 | }); 17 | 18 | it('is valid for android', function() { 19 | var assets = cordovaAssets.getPaths('android', 'fakeProjectPath'); 20 | var expectedPath = 'platforms/android/platform_www'; 21 | expect(assets.assetsPath).to.equal(expectedPath); 22 | }); 23 | 24 | it('is valid for browser', function() { 25 | var assets = cordovaAssets.getPaths('browser', 'fakeProjectPath'); 26 | var expectedPath = 'platforms/browser/www'; 27 | expect(assets.assetsPath).to.equal(expectedPath); 28 | }); 29 | 30 | it('adds cordova_plugins.js to files', function() { 31 | var assets = cordovaAssets.getPaths('ios', 'fakeProjectPath'); 32 | expect(assets.files).to.deep.equal( 33 | ['cordova_plugins.js', 'cordova.js', 'config.xml'] 34 | ); 35 | }); 36 | }); 37 | 38 | describe('validatePaths', function() { 39 | it('throws an error if assetsPath is undefined', function() { 40 | expect(function() { 41 | cordovaAssets.validatePaths(); 42 | }).to.throw( 43 | 'ember-cordova: Platform asset path undefined, cant build' 44 | ); 45 | }); 46 | 47 | it('throws an error if cordova.js does not exist', function() { 48 | td.replace(fsUtils, 'existsSync', function(path) { 49 | return path !== 'path/cordova.js' 50 | }); 51 | 52 | var warnDouble = td.replace(logger, 'warn'); 53 | cordovaAssets.validatePaths('fakeAssetPath', 'fakeProjectPath'); 54 | 55 | td.verify(warnDouble(contains('Did not find'))); 56 | td.verify(warnDouble(contains('cordova.js'))); 57 | }); 58 | 59 | it('throws an error if cordova_plugins.js does not exist', function() { 60 | td.replace(fsUtils, 'existsSync', function(path) { 61 | return path !== 'path/cordova_plugins.js' 62 | }); 63 | 64 | var warnDouble = td.replace(logger, 'warn'); 65 | cordovaAssets.validatePaths('fakeAssetPath', 'fakeProjectPath'); 66 | 67 | td.verify(warnDouble(contains('Did not find'))); 68 | td.verify(warnDouble(contains('cordova_plugins.js'))); 69 | }); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /node-tests/unit/utils/cordova-validator-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('../../helpers/expect'); 4 | var td = require('testdouble'); 5 | var fsUtils = require('../../../lib/utils/fs-utils'); 6 | 7 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 8 | var CordovaValidator = require('../../../lib/utils/cordova-validator'); 9 | 10 | describe('Cordova Validator', function() { 11 | var validator; 12 | 13 | beforeEach(function() { 14 | td.replace(CordovaValidator.prototype, 'makeError'); 15 | 16 | validator = new CordovaValidator({ 17 | project: mockProject.project, 18 | platform: 'ios', 19 | desiredKeyName : 'cordova-test-plugin', 20 | type: 'plugin', 21 | dir: 'plugins/', 22 | jsonPath: 'plugins/fetch.json' 23 | }); 24 | }); 25 | 26 | afterEach(function() { 27 | td.reset(); 28 | }); 29 | 30 | context('validateCordovaConfig', function() { 31 | it('fulfills when config.xml holds the key', function() { 32 | return expect( 33 | validator.validateCordovaConfig() 34 | ).to.eventually.be.fulfilled; 35 | }); 36 | 37 | it('rejects when config.xml does not hold the key', function() { 38 | validator.desiredKeyName = 'i-dont-exist'; 39 | return expect( 40 | validator.validateCordovaConfig() 41 | ).to.eventually.be.rejected; 42 | }); 43 | }); 44 | 45 | context('validateCordovaJSON', function() { 46 | it('fulfills when key is in json file', function() { 47 | return expect(validator.validateCordovaJSON()).to.eventually.be.fulfilled; 48 | }); 49 | 50 | it('rejects when key is not in json file', function() { 51 | validator.desiredKeyName = 'i-dont-exist'; 52 | return expect(validator.validateCordovaJSON()).to.eventually.be.rejected; 53 | }); 54 | }); 55 | 56 | context('validatePluginJSON', function() { 57 | it('fulfills when key is in plugin json file', function() { 58 | return expect(validator.validatePluginJSON()).to.eventually.be.fulfilled; 59 | }); 60 | 61 | it('rejects when key is not in plugin json file', function() { 62 | validator.desiredKeyName = 'i-dont-exist'; 63 | return expect(validator.validatePluginJSON()).to.eventually.be.rejected; 64 | }); 65 | }); 66 | 67 | context('validateDirExists', function() { 68 | it('fulfills when plugin dir exists', function() { 69 | td.replace(fsUtils, 'existsSync', function() { 70 | return true; 71 | }); 72 | 73 | return expect(validator.validateDirExists()).to.eventually.be.fulfilled; 74 | }); 75 | 76 | it('rejects when plugin dir does not exist', function() { 77 | td.replace(fsUtils, 'existsSync', function() { 78 | return false; 79 | }); 80 | 81 | return expect(validator.validateDirExists()).to.eventually.be.rejected; 82 | }); 83 | }); 84 | }); 85 | 86 | -------------------------------------------------------------------------------- /node-tests/unit/utils/create-gitkeep-test.js: -------------------------------------------------------------------------------- 1 | var td = require('testdouble'); 2 | var fsUtils = require('../../../lib/utils/fs-utils'); 3 | var createGitkeep = require('../../../lib/utils/create-gitkeep'); 4 | 5 | 6 | describe('Create gitkeep util', function() { 7 | beforeEach(function() { 8 | td.reset(); 9 | }); 10 | 11 | it('attempts to write an empty gitkeep file', function() { 12 | var writeDouble = td.replace(fsUtils, 'write'); 13 | createGitkeep('fooPath'); 14 | 15 | td.verify(writeDouble('fooPath', '', { encoding: 'utf8' })); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /node-tests/unit/utils/edit-xml-test.js: -------------------------------------------------------------------------------- 1 | var cordovaPath = require('../../../lib/utils/cordova-path'); 2 | var editXml = require('../../../lib/utils/edit-xml'); 3 | var expect = require('../../helpers/expect'); 4 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 5 | var parseXml = require('../../../lib/utils/parse-xml'); 6 | var path = require('path'); 7 | 8 | describe('Edit XML Util', function() { 9 | var host = 'http://localhost:8080'; 10 | 11 | beforeEach(function() { 12 | editXml.addNavigation(mockProject.project, host); 13 | }); 14 | 15 | describe('addNavigation function', function() { 16 | it('add node to the xml file in addition to client nodes', function() { 17 | var cdvPath = cordovaPath(mockProject.project); 18 | var configPath = path.join(cdvPath, 'config.xml'); 19 | var xml = parseXml(configPath); 20 | var nodes = xml._result.widget['allow-navigation'].length; 21 | 22 | expect(nodes).to.equal(3); 23 | }); 24 | }); 25 | 26 | describe('removeNavigation function', function() { 27 | beforeEach(function() { 28 | editXml.removeNavigation(mockProject.project); 29 | }); 30 | 31 | describe('if nodes placed by util exist', function() { 32 | it('removes util placed nodes and keep client nodes', function() { 33 | var cdvPath = cordovaPath(mockProject.project); 34 | var configPath = path.join(cdvPath, 'config.xml'); 35 | var xml = parseXml(configPath); 36 | var nodes = xml._result.widget['allow-navigation'].length; 37 | 38 | expect(nodes).to.equal(2); 39 | }); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /node-tests/unit/utils/get-added-platforms-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var getCordovaPath = require('../../../lib/utils/cordova-path'); 6 | 7 | var path = require('path'); 8 | 9 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 10 | 11 | describe('Get Added Platforms Util', function() { 12 | context('when project has platforms.json', function() { 13 | let subject; 14 | 15 | beforeEach(function() { 16 | var cordovaPath = getCordovaPath(mockProject.project); 17 | var platformsPath = path.join(cordovaPath, 'platforms/platforms.json'); 18 | 19 | td.replace(platformsPath, { 'ios': '4.3.1' }); 20 | 21 | /* eslint-disable max-len */ 22 | var getAddedPlatforms = require('../../../lib/utils/get-added-platforms'); 23 | /* eslint-enable max-len */ 24 | 25 | subject = getAddedPlatforms(mockProject.project); 26 | }); 27 | 28 | afterEach(function() { 29 | td.reset(); 30 | }); 31 | 32 | it('returns its keys', function() { 33 | expect(subject).to.deep.equal(['ios']); 34 | }); 35 | }); 36 | 37 | context('when project has no platforms.json', function() { 38 | let subject; 39 | 40 | beforeEach(function() { 41 | // Context relies on mockProject not including a platform.json. 42 | 43 | /* eslint-disable max-len */ 44 | var getAddedPlatforms = require('../../../lib/utils/get-added-platforms'); 45 | /* eslint-enable max-len */ 46 | 47 | subject = getAddedPlatforms(mockProject.project); 48 | }); 49 | 50 | it('returns an empty array', function() { 51 | expect(subject).to.be.empty; 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /node-tests/unit/utils/get-project-type-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var projectType = require('../../../lib/utils/get-project-type'); 6 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 7 | 8 | describe('Get Project Type Util', function() { 9 | describe('getPackage', function() { 10 | it('attempts to read package.json at root', function() { 11 | let packageJSON = projectType.getPackage(mockProject.project.root); 12 | expect(packageJSON.name).to.equal('mock-project'); 13 | }); 14 | }); 15 | 16 | describe('isGlimmer', function() { 17 | afterEach(function() { 18 | td.reset(); 19 | }); 20 | 21 | it('returns true if @glimmer/application is present', function() { 22 | td.replace(projectType, 'getPackage', function() { 23 | return { 24 | name: 'my-app', 25 | devDependencies: { 26 | '@glimmer/application': '^0.5.1', 27 | } 28 | }; 29 | }); 30 | 31 | expect(projectType.isGlimmer()).to.equal(true); 32 | }); 33 | 34 | it('returns false if @glimmer/application is not present', function() { 35 | td.replace(projectType, 'getPackage', function() { 36 | return { 37 | name: 'my-app', 38 | devDependencies: { 39 | 'ember-source': '^0.5.1', 40 | } 41 | }; 42 | }); 43 | 44 | expect(projectType.isGlimmer()).to.equal(false); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /node-tests/unit/utils/init-project-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var td = require('testdouble'); 4 | var expect = require('../../helpers/expect'); 5 | var mockProject = require('../../fixtures/ember-cordova-mock/project'); 6 | var Promise = require('rsvp'); 7 | var CreateCordova = require('../../../lib/tasks/create-cordova-project'); 8 | var GitIgnore = require('../../../lib/tasks/update-gitignore'); 9 | var WatchmanCfg = require('../../../lib/tasks/update-watchman-config'); 10 | 11 | describe('Blueprint initProject', function() { 12 | var initProject; 13 | var project = mockProject.project; 14 | var ui = mockProject.ui; 15 | 16 | beforeEach(function() { 17 | initProject = require('../../../lib/utils/init-project'); 18 | }); 19 | 20 | afterEach(function() { 21 | td.reset(); 22 | }); 23 | 24 | 25 | it('runs tasks in the correct order', function() { 26 | var tasks = []; 27 | 28 | td.replace(CreateCordova.prototype, 'run', function() { 29 | tasks.push('create-cordova-project'); 30 | return Promise.resolve(); 31 | }); 32 | 33 | td.replace(GitIgnore.prototype, 'run', function() { 34 | tasks.push('update-gitignore'); 35 | return Promise.resolve(); 36 | }); 37 | 38 | td.replace(WatchmanCfg.prototype, 'run', function() { 39 | tasks.push('update-watchman-config'); 40 | return Promise.resolve(); 41 | }); 42 | 43 | return initProject({}, project, ui).then(function() { 44 | expect(tasks).to.deep.equal([ 45 | 'create-cordova-project', 46 | 'update-gitignore', 47 | 'update-watchman-config' 48 | ]); 49 | }); 50 | }); 51 | 52 | it('passes template path', function() { 53 | td.replace(CreateCordova.prototype, 'run', function(path) { 54 | expect(path).to.equal('templatePath'); 55 | return Promise.resolve(); 56 | }); 57 | initProject({templatePath: 'templatePath'}, project, ui); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /node-tests/unit/utils/parse-cordova-build-opts-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('../../helpers/expect'); 4 | var parseCordovaOpts = require('../../../lib/utils/parse-cordova-build-opts'); 5 | 6 | describe('Parse Cordova Build Options Util', function() { 7 | it('sets generic flags', function() { 8 | var cordovaOpts = parseCordovaOpts('ios', { 9 | release: true, device: 'deviceName' 10 | }) 11 | 12 | expect(cordovaOpts.release).to.equal(true); 13 | expect(cordovaOpts.device).to.equal('deviceName'); 14 | }); 15 | 16 | describe('for ios', function() { 17 | it('returns ios options', function() { 18 | var options = { codeSignIdentity: 'FOO' }; 19 | var cordovaOpts = parseCordovaOpts('ios', options) 20 | 21 | expect(cordovaOpts.codeSignIdentity).to.equal('FOO'); 22 | }); 23 | 24 | it ('does not parse android options', function() { 25 | var options = { keystore: 'FOO-KEYSTORE' }; 26 | var cordovaOpts = parseCordovaOpts('ios', options) 27 | 28 | expect(cordovaOpts.keystore).to.equal(undefined); 29 | }); 30 | }); 31 | 32 | describe('for android', function() { 33 | it('returns android options', function() { 34 | var options = { keystore: 'FOO-KEYSTORE' }; 35 | var cordovaOpts = parseCordovaOpts('android', options) 36 | 37 | expect(cordovaOpts.keystore).to.equal('FOO-KEYSTORE'); 38 | }); 39 | 40 | it('does not parse ios options', function() { 41 | var options = { codeSignIdentity: 'FOO' }; 42 | var cordovaOpts = parseCordovaOpts('android', options) 43 | 44 | expect(cordovaOpts.codeSignIdentity).to.equal(undefined); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ember-cordova", 3 | "version": "1.0.9", 4 | "description": "Tooling for cordova and crosswalk hybrid applications built with Ember", 5 | "homepage": "https://github.com/isleofcode/ember-cordova", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/isleofcode/ember-cordova.git" 9 | }, 10 | "main": "index.js", 11 | "directories": { 12 | "doc": "docs", 13 | "test": "tests" 14 | }, 15 | "scripts": { 16 | "test": "./node_modules/.bin/mocha --harmony --compilers js:babel-register 'node-tests/**/*-test.js'" 17 | }, 18 | "engines": { 19 | "node": "^4.5 || >=6.*" 20 | }, 21 | "author": { 22 | "name": "Alex Blom", 23 | "email": "alex@isleofcode.com", 24 | "url": "https://isleofcode.com" 25 | }, 26 | "contributors": [ 27 | { 28 | "name": "Jake Craige", 29 | "email": "jake@poeticsystem.com" 30 | }, 31 | { 32 | "name": "Aidan Nulman", 33 | "email": "aidan@isleofcode.com", 34 | "url": "https://isleofcode.com" 35 | }, 36 | { 37 | "name": "Chris Thoburn", 38 | "email": "chris@isleofcode.com", 39 | "url": "https://isleofcode.com" 40 | } 41 | ], 42 | "license": "MIT", 43 | "ember-addon": { 44 | "configPath": "tests/dummy/config", 45 | "versionCompatibility": { 46 | "ember": ">1.13.0" 47 | } 48 | }, 49 | "keywords": [ 50 | "ember-addon", 51 | "cordova", 52 | "ember-cli-cordova", 53 | "ember", 54 | "tooling", 55 | "phonegap", 56 | "crosswalk", 57 | "hybrid", 58 | "mobile" 59 | ], 60 | "dependencies": { 61 | "broccoli-funnel": "^1.1.0", 62 | "broccoli-merge-trees": "1.2.4", 63 | "chalk": "^2.0.0", 64 | "configstore": "3.1.0", 65 | "copy-dir": "^0.3.0", 66 | "cordova-common": "^2.0.0", 67 | "cordova-lib": "7.0.1", 68 | "ember-cli-babel": "^6.0.0", 69 | "fs-extra": "^3.0.0", 70 | "htmlparser2": "^3.9.2", 71 | "leek": "0.0.24", 72 | "lodash": "^4.13.1", 73 | "portfinder": "^1.0.5", 74 | "rimraf": "^2.5.4", 75 | "rsvp": "^4.6.1", 76 | "splicon": "0.0.14", 77 | "svg2png": "^4.1.0", 78 | "uuid": "^3.0.0", 79 | "xml2js": "^0.4.17" 80 | }, 81 | "devDependencies": { 82 | "broccoli-asset-rev": "^2.4.5", 83 | "chai": "^4.0.2", 84 | "chai-as-promised": "^6.0.0", 85 | "ember-cli": "~2.13.2", 86 | "ember-cli-dependency-checker": "^2.0.0", 87 | "ember-cli-htmlbars": "^2.0.0", 88 | "ember-cli-htmlbars-inline-precompile": "^1.0.0", 89 | "ember-cli-inject-live-reload": "^1.4.1", 90 | "ember-cli-shims": "^1.0.2", 91 | "ember-disable-prototype-extensions": "^1.1.0", 92 | "ember-export-application-global": "^2.0.0", 93 | "ember-load-initializers": "^1.0.0", 94 | "ember-resolver": "^4.0.0", 95 | "ember-source": "^2.13.3", 96 | "eslint-plugin-chai-expect": "^1.1.1", 97 | "mocha": "^3.4.2", 98 | "mocha-eslint": "2.1.1", 99 | "mocha-jshint": "^2.3.1", 100 | "testdouble": "^3.0.0" 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/public/.gitkeep -------------------------------------------------------------------------------- /public/cordova.js: -------------------------------------------------------------------------------- 1 | /* 2 | No-op script for when serving to both browser and Cordova device. 3 | */ 4 | -------------------------------------------------------------------------------- /tests/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "document", 4 | "window", 5 | "location", 6 | "setTimeout", 7 | "$", 8 | "-Promise", 9 | "define", 10 | "console", 11 | "visit", 12 | "exists", 13 | "fillIn", 14 | "click", 15 | "keyEvent", 16 | "triggerEvent", 17 | "find", 18 | "findWithAssert", 19 | "wait", 20 | "DS", 21 | "andThen", 22 | "currentURL", 23 | "currentPath", 24 | "currentRouteName" 25 | ], 26 | "node": false, 27 | "browser": false, 28 | "boss": true, 29 | "curly": true, 30 | "debug": false, 31 | "devel": false, 32 | "eqeqeq": true, 33 | "evil": true, 34 | "forin": false, 35 | "immed": false, 36 | "laxbreak": false, 37 | "newcap": true, 38 | "noarg": true, 39 | "noempty": false, 40 | "nonew": false, 41 | "nomen": false, 42 | "onevar": false, 43 | "plusplus": false, 44 | "regexp": false, 45 | "undef": true, 46 | "sub": true, 47 | "strict": false, 48 | "white": false, 49 | "eqnull": true, 50 | "esversion": 6, 51 | "unused": true 52 | } 53 | -------------------------------------------------------------------------------- /tests/dummy/app/app.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import Resolver from './resolver'; 3 | import loadInitializers from 'ember-load-initializers'; 4 | import config from './config/environment'; 5 | 6 | let App; 7 | 8 | Ember.MODEL_FACTORY_INJECTIONS = true; 9 | 10 | App = Ember.Application.extend({ 11 | modulePrefix: config.modulePrefix, 12 | podModulePrefix: config.podModulePrefix, 13 | Resolver 14 | }); 15 | 16 | loadInitializers(App, config.modulePrefix); 17 | 18 | export default App; 19 | -------------------------------------------------------------------------------- /tests/dummy/app/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/controllers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/helpers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/helpers/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dummy 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | 12 | 13 | 14 | 15 | {{content-for "head-footer"}} 16 | 17 | 18 | {{content-for "body"}} 19 | 20 | 21 | 22 | 23 | {{content-for "body-footer"}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/dummy/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/models/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/models/child.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | import ChangedRelationships from 'ember-changed-relationships'; 3 | 4 | const { 5 | Model, 6 | belongsTo 7 | } = DS; 8 | 9 | export default Model.extend( 10 | ChangedRelationships, { 11 | 12 | parent: belongsTo() 13 | }); 14 | -------------------------------------------------------------------------------- /tests/dummy/app/models/parent.js: -------------------------------------------------------------------------------- 1 | import DS from 'ember-data'; 2 | import ChangedRelationships from 'ember-changed-relationships'; 3 | 4 | const { 5 | Model, 6 | hasMany 7 | } = DS; 8 | 9 | export default Model.extend( 10 | ChangedRelationships, { 11 | 12 | children: hasMany('child', { async: false }) 13 | }); 14 | -------------------------------------------------------------------------------- /tests/dummy/app/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from 'ember-resolver'; 2 | 3 | export default Resolver; 4 | -------------------------------------------------------------------------------- /tests/dummy/app/router.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import config from './config/environment'; 3 | 4 | const Router = Ember.Router.extend({ 5 | location: config.locationType, 6 | rootURL: config.rootURL 7 | }); 8 | 9 | Router.map(function() { 10 | }); 11 | 12 | export default Router; 13 | -------------------------------------------------------------------------------- /tests/dummy/app/routes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/routes/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/app/styles/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/styles/app.css -------------------------------------------------------------------------------- /tests/dummy/app/templates/application.hbs: -------------------------------------------------------------------------------- 1 | {{!-- The following component displays Ember's default welcome message. --}} 2 | {{welcome-page}} 3 | {{!-- Feel free to remove this! --}} 4 | 5 | {{outlet}} 6 | -------------------------------------------------------------------------------- /tests/dummy/app/templates/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/isleofcode/ember-cordova/9c21376e416ffa21bbeffd3e1854d9b508a499de/tests/dummy/app/templates/components/.gitkeep -------------------------------------------------------------------------------- /tests/dummy/config/environment.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | 3 | module.exports = function(environment) { 4 | var ENV = { 5 | modulePrefix: 'dummy', 6 | environment: environment, 7 | rootURL: '/', 8 | locationType: 'auto', 9 | EmberENV: { 10 | FEATURES: { 11 | // Here you can enable experimental features on an ember canary build 12 | // e.g. 'with-controller': true 13 | }, 14 | EXTEND_PROTOTYPES: { 15 | // Prevent Ember Data from overriding Date.parse. 16 | Date: false 17 | } 18 | }, 19 | 20 | APP: { 21 | // Here you can pass flags/options to your application instance 22 | // when it is created 23 | } 24 | }; 25 | 26 | if (environment === 'development') { 27 | // ENV.APP.LOG_RESOLVER = true; 28 | // ENV.APP.LOG_ACTIVE_GENERATION = true; 29 | // ENV.APP.LOG_TRANSITIONS = true; 30 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; 31 | // ENV.APP.LOG_VIEW_LOOKUPS = true; 32 | } 33 | 34 | if (environment === 'test') { 35 | // Testem prefers this... 36 | ENV.locationType = 'none'; 37 | 38 | // keep test console output quieter 39 | ENV.APP.LOG_ACTIVE_GENERATION = false; 40 | ENV.APP.LOG_VIEW_LOOKUPS = false; 41 | 42 | ENV.APP.rootElement = '#ember-testing'; 43 | } 44 | 45 | if (environment === 'production') { 46 | 47 | } 48 | 49 | return ENV; 50 | }; 51 | -------------------------------------------------------------------------------- /tests/dummy/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /tests/dummy/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /tests/helpers/destroy-app.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default function destroyApp(application) { 4 | Ember.run(application, 'destroy'); 5 | } 6 | -------------------------------------------------------------------------------- /tests/helpers/module-for-acceptance.js: -------------------------------------------------------------------------------- 1 | import { module } from 'qunit'; 2 | import Ember from 'ember'; 3 | import startApp from '../helpers/start-app'; 4 | import destroyApp from '../helpers/destroy-app'; 5 | 6 | const { RSVP: { Promise } } = Ember; 7 | 8 | export default function(name, options = {}) { 9 | module(name, { 10 | beforeEach() { 11 | this.application = startApp(); 12 | 13 | if (options.beforeEach) { 14 | return options.beforeEach.apply(this, arguments); 15 | } 16 | }, 17 | 18 | afterEach() { 19 | let afterEach = options.afterEach && options.afterEach.apply(this, arguments); 20 | return Promise.resolve(afterEach).then(() => destroyApp(this.application)); 21 | } 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /tests/helpers/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from '../../resolver'; 2 | import config from '../../config/environment'; 3 | 4 | const resolver = Resolver.create(); 5 | 6 | resolver.namespace = { 7 | modulePrefix: config.modulePrefix, 8 | podModulePrefix: config.podModulePrefix 9 | }; 10 | 11 | export default resolver; 12 | -------------------------------------------------------------------------------- /tests/helpers/start-app.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | import Application from '../../app'; 3 | import config from '../../config/environment'; 4 | 5 | export default function startApp(attrs) { 6 | let application; 7 | 8 | let attributes = Ember.merge({}, config.APP); 9 | attributes = Ember.merge(attributes, attrs); // use defaults, but you can override; 10 | 11 | Ember.run(() => { 12 | application = Application.create(attributes); 13 | application.setupForTesting(); 14 | application.injectTestHelpers(); 15 | }); 16 | 17 | return application; 18 | } 19 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Dummy Tests 7 | 8 | 9 | 10 | {{content-for "head"}} 11 | {{content-for "test-head"}} 12 | 13 | 14 | 15 | 16 | 17 | {{content-for "head-footer"}} 18 | {{content-for "test-head-footer"}} 19 | 20 | 21 | {{content-for "body"}} 22 | {{content-for "test-body"}} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {{content-for "body-footer"}} 31 | {{content-for "test-body-footer"}} 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/test-helper.js: -------------------------------------------------------------------------------- 1 | import resolver from './helpers/resolver'; 2 | import { 3 | setResolver 4 | } from 'ember-qunit'; 5 | 6 | setResolver(resolver); 7 | --------------------------------------------------------------------------------