├── www ├── assets │ ├── jasmine │ │ └── .gitignore │ ├── main-bootstrap.js │ ├── index.html │ ├── jasmine-medic.js │ └── main.css ├── medic.js ├── jasmine_helpers.js ├── tests.js └── main.js ├── NOTICE ├── .github ├── ISSUE_TEMPLATE │ ├── FEATURE_REQUEST.md │ ├── SUPPORT_QUESTION.md │ └── BUG_REPORT.md ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md └── workflows │ ├── ci.yml │ └── release-audit.yml ├── package.json ├── .eslintignore ├── .npmrc ├── .gitignore ├── .ratignore ├── licence_checker.yml ├── .asf.yaml ├── .eslintrc.yml ├── scripts └── postinstall.js ├── CONTRIBUTING.md ├── plugin.xml ├── RELEASENOTES.md ├── README.md └── LICENSE /www/assets/jasmine/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache Cordova 2 | Copyright 2014 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: A suggestion for a new functionality 4 | 5 | --- 6 | 7 | # Feature Request 8 | 9 | ## Motivation Behind Feature 10 | 11 | 12 | 13 | 14 | ## Feature Description 15 | 20 | 21 | 22 | 23 | ## Alternatives or Workarounds 24 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-test-framework", 3 | "version": "2.0.0-dev", 4 | "description": "Cordova Test Framework Plugin", 5 | "cordova": { 6 | "id": "cordova-plugin-test-framework", 7 | "platforms": [] 8 | }, 9 | "repository": "github:apache/cordova-plugin-test-framework", 10 | "bugs": "https://github.com/apache/cordova-plugin-test-framework/issues", 11 | "keywords": [ 12 | "cordova", 13 | "test", 14 | "ecosystem:cordova" 15 | ], 16 | "scripts": { 17 | "test": "npm run lint", 18 | "lint": "eslint .", 19 | "postinstall": "node scripts/postinstall.js" 20 | }, 21 | "author": "Apache Software Foundation", 22 | "license": "Apache-2.0", 23 | "devDependencies": { 24 | "@cordova/eslint-config": "^5.1.0" 25 | }, 26 | "dependencies": { 27 | "jasmine-core": "^5.9.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | www/assets/jasmine 19 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | registry=https://registry.npmjs.org 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | # OS X 19 | .DS_Store 20 | 21 | node_modules 22 | -------------------------------------------------------------------------------- /.ratignore: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | .git/ 19 | node_modules/ 20 | www/assets/jasmine/ 21 | -------------------------------------------------------------------------------- /licence_checker.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | # Empty for the release audit workflow. 19 | # The `license-config` is required even if there are no custom configs 20 | -------------------------------------------------------------------------------- /www/assets/main-bootstrap.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | document.addEventListener('deviceready', function () { 21 | 'use strict'; 22 | 23 | cordova.require('cordova-plugin-test-framework.main').init(); 24 | }); 25 | -------------------------------------------------------------------------------- /.asf.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | notifications: 19 | commits: commits@cordova.apache.org 20 | issues: issues@cordova.apache.org 21 | pullrequests_status: issues@cordova.apache.org 22 | pullrequests_comment: issues@cordova.apache.org 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/SUPPORT_QUESTION.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 💬 Support Question 3 | about: If you have a question, please check out our Slack or StackOverflow! 4 | 5 | --- 6 | 7 | 8 | 9 | Apache Cordova uses GitHub Issues as a feature request and bug tracker _only_. 10 | For usage and support questions, please check out the resources below. Thanks! 11 | 12 | --- 13 | 14 | You can get answers to your usage and support questions about **Apache Cordova** on: 15 | 16 | * Slack Community Chat: https://cordova.slack.com (you can sign-up at http://slack.cordova.io/) 17 | * StackOverflow: https://stackoverflow.com/questions/tagged/cordova using the tag `cordova` 18 | 19 | --- 20 | 21 | If you are using a tool that uses Cordova internally, like e.g. Ionic, check their support channels: 22 | 23 | * **Ionic Framework** 24 | * [Ionic Community Forum](https://forum.ionicframework.com/) 25 | * [Ionic Worldwide Slack](https://ionicworldwide.herokuapp.com/) 26 | * **PhoneGap** 27 | * [PhoneGap Developer Community](https://forums.adobe.com/community/phonegap) 28 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | root: true 19 | extends: '@cordova/eslint-config/browser' 20 | globals: 21 | cordova: true 22 | WinJS: true 23 | describe: true 24 | jasmineRequire: true 25 | device: true 26 | 27 | overrides: 28 | - files: [scripts/**/*.js] 29 | extends: '@cordova/eslint-config/node' 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG_REPORT.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: If something isn't working as expected. 4 | 5 | --- 6 | 7 | # Bug Report 8 | 9 | ## Problem 10 | 11 | ### What is expected to happen? 12 | 13 | 14 | 15 | ### What does actually happen? 16 | 17 | 18 | 19 | ## Information 20 | 21 | 22 | 23 | 24 | ### Command or Code 25 | 26 | 27 | 28 | 29 | ### Environment, Platform, Device 30 | 31 | 32 | 33 | 34 | ### Version information 35 | 42 | 43 | 44 | 45 | ## Checklist 46 | 47 | 48 | - [ ] I searched for existing GitHub issues 49 | - [ ] I updated all Cordova tooling to most recent version 50 | - [ ] I included all the necessary information above 51 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Platforms affected 10 | 11 | 12 | 13 | ### Motivation and Context 14 | 15 | 16 | 17 | 18 | 19 | ### Description 20 | 21 | 22 | 23 | 24 | ### Testing 25 | 26 | 27 | 28 | 29 | ### Checklist 30 | 31 | - [ ] I've run the tests to see all new and existing tests pass 32 | - [ ] I added automated test coverage as appropriate for this change 33 | - [ ] Commit is prefixed with `(platform)` if this change only applies to one platform (e.g. `(android)`) 34 | - [ ] If this Pull Request resolves an issue, I linked to the issue in the text above (and used the correct [keyword to close issues using keywords](https://help.github.com/articles/closing-issues-using-keywords/)) 35 | - [ ] I've updated the documentation if necessary 36 | -------------------------------------------------------------------------------- /scripts/postinstall.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | const { cpSync, rmSync } = require('node:fs'); 21 | const path = require('node:path'); 22 | 23 | const jasmineSrc = path.join(path.dirname(require.resolve('jasmine-core')), 'jasmine-core'); 24 | const jasmineDest = path.join(__dirname, '..', 'www', 'assets', 'jasmine'); 25 | 26 | cpSync(jasmineSrc, jasmineDest, { recursive: true, force: true }); 27 | rmSync(path.join(jasmineDest, 'example'), { recursive: true, force: true }); 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | ### Issue Type 7 | 8 | 9 | - [ ] Bug Report 10 | - [ ] Feature Request 11 | - [ ] Support Question 12 | 13 | ## Description 14 | 15 | ## Information 16 | 17 | 18 | ### Command or Code 19 | 20 | 21 | ### Environment, Platform, Device 22 | 23 | 24 | 25 | 26 | ### Version information 27 | 34 | 35 | 36 | 37 | ## Checklist 38 | 39 | 40 | - [ ] I searched for already existing GitHub issues about this 41 | - [ ] I updated all Cordova tooling to their most recent version 42 | - [ ] I included all the necessary information above 43 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | # Contributing to Apache Cordova 23 | 24 | Anyone can contribute to Cordova. And we need your contributions. 25 | 26 | There are multiple ways to contribute: report bugs, improve the docs, and 27 | contribute code. 28 | 29 | For instructions on this, start with the 30 | [contribution overview](http://cordova.apache.org/contribute/). 31 | 32 | The details are explained there, but the important items are: 33 | - Check for Github issues that corresponds to your contribution and link or create them if necessary. 34 | - Run the tests so your patch doesn't break existing functionality. 35 | 36 | We look forward to your contributions! 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | name: Node CI 19 | 20 | on: [push, pull_request] 21 | 22 | jobs: 23 | test: 24 | name: NodeJS ${{ matrix.node-version }} on ${{ matrix.os }} 25 | runs-on: ${{ matrix.os }} 26 | strategy: 27 | matrix: 28 | node-version: [20.x, 22.x, 24.x] 29 | os: [ubuntu-latest, windows-latest, macos-latest] 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - name: Use Node.js ${{ matrix.node-version }} 35 | uses: actions/setup-node@v4 36 | with: 37 | node-version: ${{ matrix.node-version }} 38 | 39 | - name: Environment Information 40 | run: | 41 | node --version 42 | npm --version 43 | 44 | - name: npm install and test 45 | run: npm cit 46 | env: 47 | CI: true 48 | -------------------------------------------------------------------------------- /www/medic.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 'use strict'; 21 | 22 | exports.logurl = 'http://127.0.0.1:7800'; 23 | 24 | exports.enabled = false; 25 | 26 | exports.load = function (callback) { 27 | var cfg = null; 28 | 29 | try { 30 | // attempt to synchronously load medic config 31 | var xhr = new XMLHttpRequest(); 32 | xhr.open('GET', '../medic.json', false); 33 | xhr.send(null); 34 | cfg = JSON.parse(xhr.responseText); 35 | } catch (ex) { } 36 | 37 | // config is available 38 | if (cfg) { 39 | exports.logurl = cfg.couchdb || cfg.logurl; 40 | exports.sha = cfg.sha; 41 | exports.enabled = true; 42 | console.log('Loaded Medic Config: logurl=' + exports.logurl); 43 | } else { 44 | // config does not exist 45 | console.log('Did not find medic config file'); 46 | } 47 | 48 | setTimeout(function () { 49 | callback(); 50 | }, 0); 51 | }; 52 | -------------------------------------------------------------------------------- /.github/workflows/release-audit.yml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | name: Release Auditing 19 | 20 | on: 21 | push: 22 | branches-ignore: 23 | - 'dependabot/**' 24 | pull_request: 25 | branches: 26 | - '*' 27 | 28 | permissions: 29 | contents: read 30 | 31 | jobs: 32 | test: 33 | name: Audit Licenses 34 | runs-on: ubuntu-latest 35 | steps: 36 | # Checkout project 37 | - uses: actions/checkout@v6 38 | 39 | # Check license headers (v2.0.0) 40 | - uses: erisu/apache-rat-action@46fb01ce7d8f76bdcd7ab10e7af46e1ea95ca01c 41 | 42 | # Setup environment with node 43 | - uses: actions/setup-node@v6 44 | with: 45 | node-version: 24 46 | 47 | # Install node packages 48 | - name: npm install packages 49 | run: npm ci 50 | 51 | # Check node package licenses (v2.0.1) 52 | - uses: erisu/license-checker-action@99cffa11264fe545fd0baa6c13bca5a00ae608f2 53 | with: 54 | license-config: 'licence_checker.yml' 55 | include-asf-category-a: true 56 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 26 | Test Framework 27 | Cordova Test Framework Plugin 28 | Apache 2.0 29 | cordova,test 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /www/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 31 | 32 | 33 | Cordova tests 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
Log
64 |
65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /www/jasmine_helpers.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 'use strict'; 21 | 22 | exports.setUpJasmine = function () { 23 | // Set up jasmine 24 | var jasmine = jasmineRequire.core(jasmineRequire); 25 | jasmineRequire.html(jasmine); 26 | var jasmineEnv = jasmine.currentEnv_ = new jasmine.Env(); 27 | 28 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; 29 | 30 | // Set up jasmine interface 31 | var jasmineInterface = jasmineRequire.interface(jasmine, jasmineEnv); 32 | 33 | // Add Reporters 34 | addJasmineReporters(jasmineInterface, jasmineEnv); 35 | 36 | // Add Spec Filter 37 | jasmineEnv.specFilter = function (spec) { 38 | // console.log(spec.getFullName()); 39 | return true; 40 | }; 41 | 42 | // Jasmine 2.2.0 moved this symbol, so we add a shim here. 43 | jasmine.Expectation.addMatchers = jasmine.Expectation.addMatchers || function () { 44 | return jasmine.addMatchers.apply(this, arguments); 45 | }; 46 | 47 | return jasmineInterface; 48 | }; 49 | 50 | function addJasmineReporters (jasmineInterface, jasmineEnv) { 51 | jasmineInterface.jsApiReporter = new jasmineInterface.jasmine.JsApiReporter({ timer: new jasmineInterface.jasmine.Timer() }); 52 | jasmineEnv.addReporter(jasmineInterface.jsApiReporter); 53 | 54 | jasmineInterface.htmlReporter = new jasmineInterface.jasmine.HtmlReporter({ 55 | env: jasmineEnv, 56 | queryString: function () { return null; }, 57 | onRaiseExceptionsClick: function () { }, 58 | onThrowExpectationsClick: function () { }, 59 | getContainer: function () { return document.getElementById('content'); }, 60 | createElement: function () { return document.createElement.apply(document, arguments); }, 61 | createTextNode: function () { return document.createTextNode.apply(document, arguments); }, 62 | timer: new jasmineInterface.jasmine.Timer() 63 | }); 64 | jasmineInterface.htmlReporter.initialize(); 65 | jasmineEnv.addReporter(jasmineInterface.htmlReporter); 66 | 67 | var medic = require('cordova-plugin-test-framework.medic'); 68 | 69 | if (medic.enabled) { 70 | jasmineRequire.medic(jasmineInterface.jasmine); 71 | jasmineInterface.MedicReporter = new jasmineInterface.jasmine.MedicReporter({ 72 | env: jasmineEnv, 73 | log: { logurl: medic.logurl }, 74 | sha: medic.sha 75 | }); 76 | jasmineInterface.MedicReporter.initialize(); 77 | jasmineEnv.addReporter(jasmineInterface.MedicReporter); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /RELEASENOTES.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | # Release Notes 23 | 24 | ### 1.1.6 (Nov 06, 2017) 25 | * [CB-12895](https://issues.apache.org/jira/browse/CB-12895) replaced `jshint` with `eslint` 26 | * [CB-12847](https://issues.apache.org/jira/browse/CB-12847) added `bugs` entry to `package.json`. 27 | 28 | ### 1.1.5 (Feb 28, 2017) 29 | * [CB-12236](https://issues.apache.org/jira/browse/CB-12236) - Fixed `RELEASENOTES` for `cordova-plugin-test-framework` 30 | 31 | ### 1.1.4 (Dec 07, 2016) 32 | * [CB-12224](https://issues.apache.org/jira/browse/CB-12224) Updated version and RELEASENOTES.md for release 1.1.4 33 | * [CB-11917](https://issues.apache.org/jira/browse/CB-11917) - Remove pull request template checklist item: "iCLA has been submitted…" 34 | * Edit package.json license to match SPDX id 35 | * [CB-11832](https://issues.apache.org/jira/browse/CB-11832) Incremented plugin version. 36 | 37 | ### 1.1.3 (Sep 08, 2016) 38 | * [CB-9071](https://issues.apache.org/jira/browse/CB-9071) Update test framework plugin to use Jasmine 2.4.1 39 | * Add pull request template. 40 | * [CB-11124](https://issues.apache.org/jira/browse/CB-11124) Fixing cordova-ios build failure due to unnecessary post calls to couchdb and adding handlers to xhr call 41 | * Add spec started/completed log 42 | 43 | ### 1.1.2 (Apr 15, 2016) 44 | * [CB-10876](https://issues.apache.org/jira/browse/CB-10876) Enable inertia scrolling in test framework 45 | * [CB-10636](https://issues.apache.org/jira/browse/CB-10636) Add `JSHint` for plugins 46 | 47 | ### 1.1.1 (Jan 15, 2016) 48 | * [CB-10318](https://issues.apache.org/jira/browse/CB-10318) Do not wrap test title 49 | 50 | ### 1.1.0 (Nov 18, 2015) 51 | * [CB-10035](https://issues.apache.org/jira/browse/CB-10035) Updated `RELEASENOTES` to be newest to oldest 52 | * [CB-8973](https://issues.apache.org/jira/browse/CB-8973): Changed the functionality of making the `log` appear and disappear 53 | * Ensure `WinJS` is available when adding **Windows** unhandled error hook 54 | 55 | ### 1.0.1 (Jun 17, 2015) 56 | * added ratignore file 57 | 58 | ### 1.0.0 (Apr 15, 2015) 59 | * [CB-8746](https://issues.apache.org/jira/browse/CB-8746) gave plugin major version bump 60 | * [CB-8683](https://issues.apache.org/jira/browse/CB-8683) changed plugin-id to pacakge-name 61 | * [CB-8653](https://issues.apache.org/jira/browse/CB-8653) Updated Readme 62 | * [CB-8528](https://issues.apache.org/jira/browse/CB-8528) Add a shim for `jasmine.Expectation.addMatchers` being moved in jasmine 2.2.0 63 | * [CB-8528](https://issues.apache.org/jira/browse/CB-8528) Update test framework plugin to use Jasmine 2.2.0 (close #11) 64 | * Close already merged PR (close #10) 65 | * [CB-8538](https://issues.apache.org/jira/browse/CB-8538) Added package.json file 66 | * [CB-8385](https://issues.apache.org/jira/browse/CB-8385) Ensure plugin-test-framework trigger tests only once 67 | 68 | ### 0.0.1 (Feb 04, 2015) 69 | * Initial release 70 | -------------------------------------------------------------------------------- /www/tests.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 'use strict'; 21 | 22 | exports.tests = Object.create(null); 23 | 24 | function TestModule (api) { 25 | var name = api; 26 | var enabled = true; 27 | 28 | var enabledPref = localStorage.getItem('cordova-tests-enabled-' + name); 29 | if (enabledPref) { 30 | enabled = (enabledPref === true.toString()); 31 | } 32 | 33 | this.getEnabled = function () { 34 | return enabled; 35 | }; 36 | 37 | this.setEnabled = function (isEnabled) { 38 | enabled = isEnabled; 39 | localStorage.setItem('cordova-tests-enabled-' + name, enabled); 40 | }; 41 | } 42 | 43 | function getTestsObject (api) { 44 | exports.tests[api] = exports.tests[api] || new TestModule(api); 45 | return exports.tests[api]; 46 | } 47 | 48 | function requireAllTestModules () { 49 | // This finds all js-modules named "tests" (regardless of plugins they came from) 50 | var test_modules = cordova.require('cordova/plugin_list') 51 | .map(function (jsmodule) { 52 | return jsmodule.id; 53 | }) 54 | .filter(function (id) { 55 | return /\.tests$/.test(id); 56 | }); 57 | 58 | // Map auto / manual test definitions for each, but without actually running the handlers 59 | test_modules.forEach(function (id) { 60 | try { 61 | var plugintests = cordova.require(id); 62 | 63 | if (Object.prototype.hasOwnProperty.call(plugintests, 'defineAutoTests')) { 64 | getTestsObject(id).defineAutoTests = function () { 65 | describe(id + ' >>', plugintests.defineAutoTests.bind(plugintests)); 66 | }; 67 | } 68 | 69 | if (Object.prototype.hasOwnProperty.call(plugintests, 'defineManualTests')) { 70 | getTestsObject(id).defineManualTests = plugintests.defineManualTests.bind(plugintests); 71 | } 72 | } catch (ex) { 73 | console.warn('Failed to load tests: ', id); 74 | } 75 | }); 76 | } 77 | 78 | function createJasmineInterface () { 79 | var jasmine_helpers = require('cordova-plugin-test-framework.jasmine_helpers'); 80 | var jasmineInterface = jasmine_helpers.setUpJasmine(); 81 | return jasmineInterface; 82 | } 83 | 84 | function attachJasmineInterfaceToGlobal () { 85 | var jasmineInterface = createJasmineInterface(); 86 | for (var property in jasmineInterface) { 87 | window[property] = jasmineInterface[property]; 88 | } 89 | } 90 | 91 | function detachJasmineInterfaceFromGlobal () { 92 | var jasmineInterface = createJasmineInterface(); 93 | for (var property in jasmineInterface) { 94 | delete window[property]; 95 | } 96 | } 97 | 98 | exports.defineAutoTests = function () { 99 | requireAllTestModules(); 100 | attachJasmineInterfaceToGlobal(); 101 | 102 | Object.keys(exports.tests).forEach(function (key) { 103 | if (!exports.tests[key].getEnabled()) { return; } 104 | if (!Object.prototype.hasOwnProperty.call(exports.tests[key], 'defineAutoTests')) { return; } 105 | exports.tests[key].defineAutoTests(); 106 | }); 107 | }; 108 | 109 | exports.defineManualTests = function (contentEl, beforeEach, createActionButton) { 110 | requireAllTestModules(); 111 | detachJasmineInterfaceFromGlobal(); 112 | 113 | Object.keys(exports.tests).forEach(function (key) { 114 | if (!exports.tests[key].getEnabled()) { return; } 115 | if (!Object.prototype.hasOwnProperty.call(exports.tests[key], 'defineManualTests')) { return; } 116 | createActionButton(key, function () { 117 | beforeEach(key); 118 | exports.tests[key].defineManualTests(contentEl, createActionButton); 119 | }); 120 | }); 121 | }; 122 | 123 | exports.init = function () { 124 | requireAllTestModules(); 125 | }; 126 | -------------------------------------------------------------------------------- /www/assets/jasmine-medic.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | jasmineRequire.medic = function (j$) { 21 | j$.MedicReporter = jasmineRequire.MedicReporter(j$); 22 | }; 23 | 24 | jasmineRequire.MedicReporter = function (j$) { 25 | var noopTimer = { 26 | start: function () {}, 27 | elapsed: function () { return 0; } 28 | }; 29 | 30 | var platformMap = { 31 | 'ipod touch': 'ios', 32 | iphone: 'ios' 33 | }; 34 | 35 | function MedicReporter (options) { 36 | var logoptions = options.log || { logurl: 'http://127.0.0.1:5984/' }; // TODO: http://localhost:6800 37 | var timer = options.timer || noopTimer; 38 | var results = []; 39 | var specsExecuted = 0; 40 | var failureCount = 0; 41 | var pendingSpecCount = 0; // eslint-disable-line 42 | 43 | var serverurl = logoptions.logurl; 44 | 45 | this.initialize = function () { 46 | }; 47 | 48 | var totalSpecsDefined; // eslint-disable-line 49 | this.jasmineStarted = function (options) { 50 | totalSpecsDefined = options.totalSpecsDefined || 0; 51 | timer.start(); 52 | }; 53 | 54 | this.suiteStarted = function (result) { 55 | }; 56 | 57 | this.suiteDone = function (result) { 58 | 59 | }; 60 | 61 | this.specStarted = function (result) { 62 | console.log('>>>>> Spec started: ' + result.description); 63 | }; 64 | 65 | this.specDone = function (result) { 66 | if (result.status !== 'disabled') { 67 | specsExecuted++; 68 | } 69 | if (result.status === 'failed') { 70 | failureCount++; 71 | results.push(result); 72 | } 73 | if (result.status === 'pending') { 74 | pendingSpecCount++; 75 | } 76 | console.log('>>>>> Spec completed: ' + result.description); 77 | }; 78 | 79 | var buildResults = function () { 80 | var json = { specs: specsExecuted, failures: failureCount, results }; 81 | return json; 82 | }; 83 | 84 | this.jasmineDone = function () { 85 | var p = 'Desktop'; 86 | var devmodel = 'none'; 87 | var version = cordova.version; 88 | if (typeof device !== 'undefined') { 89 | p = device.platform.toLowerCase(); 90 | devmodel = device.model || device.name; 91 | version = device.version.toLowerCase(); 92 | } 93 | 94 | this.postTests({ 95 | mobilespec: buildResults(), 96 | platform: (Object.prototype.hasOwnProperty.call(platformMap, p) ? platformMap[p] : p), 97 | version, 98 | sha: options.sha, 99 | timestamp: Math.round(Math.floor((new Date()).getTime() / 1000)), 100 | model: devmodel 101 | }); 102 | }; 103 | 104 | this.postTests = function (json) { 105 | console.log('posting tests'); 106 | 107 | var xhr = new XMLHttpRequest(); 108 | var doc_id = [options.sha, json.version, json.model].map(encodeURIComponent).join('__'); 109 | var doc_url = serverurl + '/mobilespec_results/' + doc_id; 110 | xhr.open('PUT', doc_url, true); 111 | xhr.onload = function (e) { 112 | if (xhr.readyState === 4) { 113 | if (xhr.status === 200) { 114 | console.log('Posting results to CouchDB succeeded: ' + xhr.responseText); 115 | } else { 116 | console.log('Error posting to CouchDB: ' + xhr.statusText); 117 | } 118 | } 119 | }; 120 | xhr.onerror = function (e) { 121 | console.log('Error posting to CouchDB: ' + xhr.statusText); 122 | }; 123 | xhr.setRequestHeader('Content-Type', 'application/json'); 124 | xhr.send(JSON.stringify(json)); 125 | }; 126 | return this; 127 | } 128 | 129 | return MedicReporter; 130 | }; 131 | -------------------------------------------------------------------------------- /www/assets/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | *, *:before, *:after { 21 | -webkit-box-sizing: border-box; 22 | box-sizing: border-box; 23 | } 24 | 25 | html, body { 26 | height: 100vh; 27 | width: 100vw; 28 | 29 | margin: 0; 30 | padding: 0; 31 | -webkit-overflow-scrolling: touch; 32 | 33 | display: flex; 34 | flex-direction: column; 35 | } 36 | 37 | #title { 38 | background-color: #75B2F0; 39 | font-size: 25px; 40 | text-align: center; 41 | font-weight: bold; 42 | white-space: nowrap; 43 | } 44 | 45 | #middle { 46 | overflow-y: auto; 47 | overflow-x: auto; 48 | } 49 | 50 | #middle > div#test-controls > div#buttons { 51 | display: flex; 52 | justify-content: center; 53 | margin-top: 10px; 54 | gap: 5px; 55 | flex-wrap: wrap; 56 | } 57 | 58 | #middle div#test-list > label { 59 | display: flex; 60 | gap: 5px; 61 | align-items: center; 62 | } 63 | 64 | #log { 65 | position: fixed; 66 | height: 20px; 67 | width: 100%; 68 | bottom: 0; 69 | z-index: 1000; 70 | border-top: 2px solid #777; 71 | transition: 0.25s ease; 72 | } 73 | 74 | body.expanded-log #middle { 75 | margin-bottom: 40%; 76 | } 77 | 78 | body.expanded-log #log { 79 | height: 40%; 80 | } 81 | 82 | #log--title { 83 | position: absolute; 84 | top: 0; 85 | height: 20px; 86 | width: 100%; 87 | background-color: #93AAC2; 88 | } 89 | 90 | #log--content { 91 | position: absolute; 92 | top: 20px; 93 | bottom: 0; 94 | width: 100%; 95 | overflow-x: none; 96 | overflow-y: scroll; 97 | background-color: white; 98 | } 99 | 100 | .log--content--line { 101 | border-bottom: 1px solid #ccc; 102 | white-space: pre; 103 | } 104 | 105 | .log--content--line--log { 106 | background-color: white; 107 | } 108 | 109 | .log--content--line--warn { 110 | background-color: #FCFFA6; 111 | } 112 | 113 | .log--content--line--error { 114 | background-color: #FFA6A6; 115 | } 116 | 117 | #info{ 118 | background:#ffa; 119 | border: 1px solid #ffd324; 120 | -webkit-border-radius: 5px; 121 | border-radius: 5px; 122 | clear:both; 123 | margin:15px 6px 0; 124 | min-width:295px; 125 | max-width:97%; 126 | padding:4px 0px 2px 10px; 127 | word-wrap:break-word; 128 | margin-bottom:10px; 129 | display:inline-block; 130 | min-height: 160px; 131 | max-height: 300px; 132 | overflow: auto; 133 | -webkit-overflow-scrolling: touch; 134 | } 135 | 136 | #test-enablers-container { 137 | margin: 10px 5px; 138 | } 139 | 140 | #test-expander { 141 | text-decoration: underline; 142 | } 143 | 144 | #test-list { 145 | display: none; 146 | } 147 | 148 | #test-list.expanded { 149 | display: inherit; 150 | } 151 | 152 | #test-list label { 153 | display: block; 154 | } 155 | 156 | 157 | :root { 158 | --button-background-color: #54738e; 159 | --button-border-color: #4c6880; 160 | --button-color: #ffffff; 161 | --button-hover-background-color: #445f76; 162 | --button-hover-border-color: #3e5569; 163 | --button-hover-color: #ffffff; 164 | } 165 | 166 | @media (max-width: 560px) { 167 | .button-group { 168 | flex-direction: column; 169 | line-height: 1; 170 | } 171 | } 172 | 173 | .button-group { 174 | display: flex; 175 | flex-direction: row; 176 | gap: 0; 177 | width: 100%; 178 | } 179 | 180 | .button-group .cdv-btn { 181 | padding: 8px 12px; 182 | line-height: 1; 183 | } 184 | 185 | .button-group .cdv-btn:first-child { 186 | border-radius: 8px 0 0 8px; 187 | } 188 | 189 | .button-group .cdv-btn:last-child { 190 | border-radius: 0 8px 8px 0; 191 | } 192 | 193 | .cdv-btn { 194 | color: var(--button-color); 195 | background-color: var(--button-background-color); 196 | padding: 8px; 197 | font-size: 1rem; 198 | line-height: 2.5; 199 | border-radius: 8px; 200 | cursor: pointer; 201 | border: 1px solid var(--button-border-color); 202 | text-decoration: none; 203 | text-align: center; 204 | } 205 | 206 | .cdv-btn:hover { 207 | color: var(--button-hover-color); 208 | background-color: var(--button-hover-background-color); 209 | border-color: var(--button-hover-border-color); 210 | text-decoration: none; 211 | } 212 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | [![Node CI](https://github.com/apache/cordova-plugin-test-framework/workflows/Node%20CI/badge.svg?branch=master)](https://github.com/apache/cordova-plugin-test-framework/actions?query=branch%3Amaster) 23 | [![GitHub version](https://badge.fury.io/gh/apache%2Fcordova-plugin-test-framework.svg)](https://github.com/apache/cordova-plugin-test-framework/releases) 24 | [![npm version](https://badge.fury.io/js/cordova-plugin-test-framework.svg)](https://www.npmjs.com/package/cordova-plugin-test-framework) 25 | 26 | # Cordova Plugin Test Framework 27 | 28 | The `cordova-plugin-test-framework` plugin allows plugin authors to add tests (manual and automated) to their plugins. To achieve this it 29 | 30 | 1. [defines the interface for Cordova plugins to write tests](#interface) and 31 | 2. [provides a test harness for actually running those tests](#harness) 32 | 33 | Tests run directly inside existing Cordova projects, so you can rapidly switch between testing and development. You can also be sure that your test suite is testing the exact versions of plugins and platforms that your app is using. 34 | 35 | # TLDR; Try it 36 | 37 | 1. Use your existing Cordova app, or create a new one. 38 | 2. Plugins bundle their tests using a nested plugin in a `/tests` directory. Here are a few examples how install both: 39 | 40 | ```shell 41 | cordova plugin add cordova-plugin-device 42 | cordova plugin add plugins/cordova-plugin-device/tests 43 | 44 | cordova plugin add cordova-plugin-device-motion 45 | cordova plugin add plugins/cordova-plugin-device-motion/tests 46 | 47 | cordova plugin add cordova-plugin-geolocation 48 | cordova plugin add plugins/cordova-plugin-geolocation/tests 49 | ``` 50 | 51 | To install the plugin from `master` on GitHub instead of npm, replace e.g. `cordova-plugin-device` with `https://github.com/apache/cordova-plugin-device.git` 52 | 53 | 3. Follow the docs for [Setting up the test harness](#harness). 54 | 55 | 56 | 57 | 58 | ## Writing Plugin Tests 59 | 60 | ### Where do tests live? 61 | 62 | Add a directory named `tests` to the root of your plugin. Within this directory, create a nested `plugin.xml` for the tests plugin. It should have a plugin id with the form `pluginid-tests` (e.g. the `cordova-plugin-device` plugin has the nested id `cordova-plugin-device-tests`) and should contain a `` named `tests`. E.g: 63 | 64 | ``` 65 | 66 | 67 | ``` 68 | 69 | For example, the `cordova-plugin-device` plugin has this nested [`plugin.xml`](https://github.com/apache/cordova-plugin-device/blob/master/tests/plugin.xml). 70 | 71 | Create a `package.json` inside your project's `tests/` folder. Plugins require a `package.json` now and tests are considered their own plugins. The latest version of the tools ensure to run `npm install` on any plugin added to a project and pull in any dependencies. Therefore, plugin authors can now put npm dependencies around their tests into the `package.json` file. 72 | 73 | For example, the `cordova-plugin-device` plugin contains a [`package.json`](https://github.com/apache/cordova-plugin-device/blob/master/tests/package.json). 74 | 75 | The `cordova-plugin-test-framework` plugin will automatically find all `tests` modules across all plugins for which the nested tests plugin is installed. 76 | 77 | ### Defining Auto Tests 78 | 79 | Export a function named `defineAutoTests`, which defines your auto-tests when run. Use the [`jasmine-2.9`](https://jasmine.github.io/2.9/introduction.html) format. E.g.: 80 | 81 | ``` 82 | exports.defineAutoTests = function() { 83 | 84 | describe('awesome tests', function() { 85 | it('do something sync', function() { 86 | expect(1).toBe(1); 87 | ... 88 | }); 89 | 90 | it('do something async using callbacks', function(done) { 91 | setTimeout(function() { 92 | expect(1).toBe(1); 93 | ... 94 | done(); 95 | }, 100); 96 | }); 97 | 98 | it("do something async using promises", function() { 99 | return soon().then(function() { 100 | value++; 101 | expect(value).toBeGreaterThan(0); 102 | }); 103 | }); 104 | 105 | it("do something async using async/await", async function() { 106 | await soon(); 107 | value++; 108 | expect(value).toBeGreaterThan(0); 109 | }); 110 | }); 111 | 112 | describe('more awesome tests', function() { 113 | ... 114 | }); 115 | 116 | }; 117 | ``` 118 | 119 | Note: Your tests will automatically be labeled with your plugin id, so do not prefix your test descriptions. 120 | 121 | 122 | ### Defining Manual Tests 123 | 124 | Export a function named `defineManualTests`, which defines your manual-tests when run. Manual tests do *not* any test runner, and success/failure results are not officially reported in any standard way. Instead, create buttons to run arbitrary javascript when clicked, and display output to user using `console` or by manipulating a provided DOM element. E.g.: 125 | 126 | ``` 127 | exports.defineManualTests = function(contentEl, createActionButton) { 128 | 129 | createActionButton('Simple Test', function() { 130 | console.log(JSON.stringify(foo, null, '\t')); 131 | }); 132 | 133 | createActionButton('Complex Test', function() { 134 | contentEl.innerHTML = ...; 135 | }); 136 | 137 | }; 138 | ``` 139 | 140 | Make sure to document the expected outcome. 141 | 142 | Note: Your tests will automatically be labeled with your plugin id, so do not prefix your test descriptions. 143 | 144 | 145 | 146 | 147 | ### Example 148 | 149 | See: [`cordova-plugin-device` tests](https://github.com/apache/cordova-plugin-device/blob/master/tests/tests.js). 150 | 151 | 152 | 153 | ## Running Plugin Tests 154 | 155 | 1. Use your existing Cordova app, or create a new one. 156 | 2. Add this plugin: 157 | 158 | ``` 159 | cordova plugin add cordova-plugin-test-framework 160 | // or 161 | cordova plugin add https://github.com/apache/cordova-plugin-test-framework.git 162 | ``` 163 | 164 | 3. Change the start page in `config.xml` with `` or add a link to `cdvtests/index.html` from within your app. 165 | 4. Thats it! 166 | 167 | 168 | ## FAQ 169 | 170 | * Q: Should I add `cordova-plugin-test-framework` as a `` of my plugin? 171 | * A: No. The end-user should decide if they want to install the test framework, not your plugin (most users won't). 172 | 173 | * Q: What do I do if my plugin tests must have very large assets? 174 | * A: Don't bundle those assets with your plugin. If you can, have your tests fail gracefully if those assets don't don't exist (perhaps log a warning, perhaps fail a single asset-checking test, and skip the rest). Then, ideally download those assets automatically into local storage the first time tests run. Or create a manual test step to download and install assets. As a final alternative, split those test assets into a separate plugin, and instruct users to install that plugin to run your full test suite. 175 | 176 | * Q: Should I ship my app with the test framework plugin installed? 177 | * A: Not likely. If you want, you can. Then your app could even embed a link to the test page (`cdvtests/index.html`) from a help section of your app, to give end users a way to run your test suite out in the feild. That may help diagnose causes of issues within your app. Maybe. 178 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /www/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var LOG_HEADER_HEIGHT = 20; 23 | var CONTENT_TOP_OFFSET = 30; 24 | 25 | var isWin = cordova.platformId === 'windows'; 26 | var isWP8 = cordova.platformId === 'windowsphone'; 27 | 28 | /******************************************************************************/ 29 | 30 | function getMode (callback) { 31 | var mode = localStorage.getItem('cdvtests-mode') || 'main'; 32 | callback(mode); 33 | } 34 | 35 | function setMode (mode) { 36 | var handlers = { 37 | main: runMain, 38 | auto: runAutoTests, 39 | manual: runManualTests 40 | }; 41 | if (!Object.prototype.hasOwnProperty.call(handlers, mode)) { 42 | console.error('Unsupported mode: ' + mode); 43 | console.error("Defaulting to 'main'"); 44 | mode = 'main'; 45 | } 46 | 47 | localStorage.setItem('cdvtests-mode', mode); 48 | clearContent(); 49 | 50 | handlers[mode](); 51 | } 52 | 53 | /******************************************************************************/ 54 | 55 | function clearContent () { 56 | var content = document.getElementById('content'); 57 | content.innerHTML = ''; 58 | var log = document.getElementById('log--content'); 59 | log.innerHTML = ''; 60 | var buttons = document.getElementById('buttons'); 61 | buttons.innerHTML = ''; 62 | 63 | setLogVisibility(false); 64 | } 65 | 66 | /******************************************************************************/ 67 | 68 | function setTitle (title) { 69 | var el = document.getElementById('title'); 70 | el.textContent = title; 71 | } 72 | 73 | /******************************************************************************/ 74 | 75 | function setLogVisibility (visible) { 76 | if (visible) { 77 | document.querySelector('body').classList.add('expanded-log'); 78 | 79 | if (isWin || isWP8) { 80 | var h = document.querySelector('body').offsetHeight; 81 | 82 | document.getElementById('middle').style.height = (h * 0.6 - LOG_HEADER_HEIGHT - CONTENT_TOP_OFFSET) + 'px'; 83 | document.getElementById('middle').style.marginBottom = (h * 0.4) + 'px'; 84 | document.getElementById('middle').style.paddingBottom = (h * 0.4) + 'px'; 85 | } 86 | } else { 87 | document.querySelector('body').classList.remove('expanded-log'); 88 | 89 | if (isWin || isWP8) { 90 | document.getElementById('middle').style.height = ''; 91 | document.getElementById('middle').style.marginBottom = ''; 92 | document.getElementById('middle').style.paddingBottom = ''; 93 | } 94 | } 95 | } 96 | 97 | window.onresize = function (event) { 98 | // Update content and log heights 99 | if (isWin || isWP8) { 100 | setLogVisibility(getLogVisibility()); 101 | } 102 | }; 103 | 104 | function getLogVisibility () { 105 | var e = document.querySelector('body'); 106 | return e.classList.contains('expanded-log'); 107 | } 108 | 109 | function toggleLogVisibility () { 110 | if (getLogVisibility()) { 111 | setLogVisibility(false); 112 | } else { 113 | setLogVisibility(true); 114 | } 115 | } 116 | 117 | /******************************************************************************/ 118 | 119 | function attachEvents () { 120 | document.getElementById('log--title').addEventListener('click', toggleLogVisibility); 121 | } 122 | 123 | /******************************************************************************/ 124 | 125 | var origConsole = window.console; 126 | 127 | exports.wrapConsole = function () { 128 | function appendToOnscreenLog (type, args) { 129 | var el = document.getElementById('log--content'); 130 | var div = document.createElement('div'); 131 | div.classList.add('log--content--line'); 132 | div.classList.add('log--content--line--' + type); 133 | div.textContent = Array.prototype.slice.apply(args).map(function (arg) { 134 | return (typeof arg === 'string') ? arg : JSON.stringify(arg); 135 | }).join(' '); 136 | el.appendChild(div); 137 | // scroll to bottom 138 | el.scrollTop = el.scrollHeight; 139 | } 140 | 141 | function createCustomLogger (type) { 142 | return function () { 143 | origConsole[type].apply(origConsole, arguments); 144 | appendToOnscreenLog(type, arguments); 145 | setLogVisibility(true); 146 | }; 147 | } 148 | 149 | window.console = { 150 | log: createCustomLogger('log'), 151 | warn: createCustomLogger('warn'), 152 | error: createCustomLogger('error') 153 | }; 154 | }; 155 | 156 | exports.unwrapConsole = function () { 157 | window.console = origConsole; 158 | }; 159 | 160 | /******************************************************************************/ 161 | 162 | function createActionButton (title, callback, appendTo) { 163 | appendTo = appendTo || 'buttons'; 164 | var buttons = document.getElementById(appendTo); 165 | var div = document.createElement('div'); 166 | var button = document.createElement('a'); 167 | button.textContent = title; 168 | button.onclick = function (e) { 169 | e.preventDefault(); 170 | callback(); 171 | }; 172 | button.classList.add('cdv-btn'); 173 | div.appendChild(button); 174 | buttons.appendChild(div); 175 | } 176 | 177 | /******************************************************************************/ 178 | 179 | function setupAutoTestsEnablers (cdvtests) { 180 | var enablerList = createEnablerList(); 181 | 182 | // Iterate over all the registered test modules 183 | iterateAutoTests(cdvtests, function (api, testModule) { 184 | // For "standard" plugins remove the common/repetitive bits of 185 | // the api key, for use as the title. For third-party plugins, the full 186 | // api will be used as the title 187 | var title = api.replace(/org\.apache\.cordova\./i, '').replace(/\.tests.tests/i, ''); 188 | 189 | createEnablerCheckbox(api, title, testModule.getEnabled(), enablerList.id, toggleTestHandler); 190 | }); 191 | 192 | updateEnabledTestCount(); 193 | } 194 | 195 | /******************************************************************************/ 196 | 197 | function createEnablerList () { 198 | var buttons = document.getElementById('buttons'); 199 | 200 | var enablerContainer = document.createElement('div'); 201 | enablerContainer.id = 'test-enablers-container'; 202 | 203 | // Create header to show count of enabled/total tests 204 | var header = document.createElement('h3'); 205 | header.id = 'tests-enabled'; 206 | 207 | // Create widget to show/hide list 208 | var expander = document.createElement('span'); 209 | expander.id = 'test-expander'; 210 | expander.innerText = 'Show/hide tests to be run'; 211 | expander.onclick = toggleEnablerVisibility; 212 | 213 | // Create list to contain checkboxes for each test 214 | var enablerList = document.createElement('div'); 215 | enablerList.id = 'test-list'; 216 | 217 | // Create select/deselect all buttons (in button bar) 218 | var checkButtonBar = document.createElement('div'); 219 | checkButtonBar.classList.add('button-group'); 220 | checkButtonBar.role = 'group'; 221 | 222 | function createSelectToggleButton (title, selected) { 223 | var link = document.createElement('a'); 224 | link.classList.add('cdv-btn'); 225 | link.innerText = title; 226 | link.href = null; 227 | link.onclick = function (e) { 228 | e.preventDefault(); 229 | toggleSelected(enablerList.id, selected); 230 | return false; 231 | }; 232 | 233 | checkButtonBar.appendChild(link); 234 | } 235 | 236 | createSelectToggleButton('Check all', true); 237 | createSelectToggleButton('Uncheck all', false); 238 | enablerList.appendChild(checkButtonBar); 239 | 240 | enablerContainer.appendChild(header); 241 | enablerContainer.appendChild(expander); 242 | enablerContainer.appendChild(enablerList); 243 | 244 | buttons.appendChild(enablerContainer); 245 | 246 | return enablerList; 247 | } 248 | 249 | /******************************************************************************/ 250 | 251 | function updateEnabledTestCount () { 252 | var enabledLabel = document.getElementById('tests-enabled'); 253 | 254 | // Determine how many tests are currently enabled 255 | var cdvtests = cordova.require('cordova-plugin-test-framework.cdvtests'); 256 | var total = 0; 257 | var enabled = 0; 258 | iterateAutoTests(cdvtests, function (api, testModule) { 259 | total++; 260 | if (testModule.getEnabled()) { 261 | enabled++; 262 | } 263 | }); 264 | 265 | if (enabled === total) { 266 | enabledLabel.innerText = 'Running All Tests.'; 267 | } else { 268 | enabledLabel.innerText = 'Running ' + enabled + ' of ' + total + ' Tests.'; 269 | } 270 | } 271 | 272 | /******************************************************************************/ 273 | 274 | function toggleSelected (containerId, newCheckedValue) { 275 | [].forEach.call(document.getElementById(containerId).getElementsByTagName('input'), function (input) { 276 | if (input.type !== 'checkbox') return; 277 | input.checked = newCheckedValue; 278 | toggleTestEnabled(input); 279 | }); 280 | updateEnabledTestCount(); 281 | } 282 | 283 | /******************************************************************************/ 284 | 285 | function toggleEnablerVisibility () { 286 | var enablerList = document.getElementById('test-list'); 287 | if (enablerList.classList.contains('expanded')) { 288 | enablerList.classList.remove('expanded'); 289 | } else { 290 | enablerList.classList.add('expanded'); 291 | } 292 | } 293 | 294 | /******************************************************************************/ 295 | 296 | function createEnablerCheckbox (api, title, isEnabled, appendTo, callback) { 297 | var container = document.getElementById(appendTo); 298 | 299 | var label = document.createElement('label'); 300 | label.classList.add('form-check-label'); 301 | 302 | var checkbox = document.createElement('input'); 303 | checkbox.classList.add('form-check-input'); 304 | checkbox.type = 'checkbox'; 305 | checkbox.value = api; 306 | checkbox.checked = isEnabled; 307 | label.htmlFor = checkbox.id = 'enable_' + api; 308 | 309 | checkbox.onchange = function (e) { 310 | e.preventDefault(); 311 | callback(e); 312 | }; 313 | 314 | var div = document.createElement('div'); 315 | var text = document.createElement('span'); 316 | text.innerText = title; 317 | 318 | label.appendChild(checkbox); 319 | label.appendChild(div); 320 | label.appendChild(text); 321 | 322 | container.appendChild(label); 323 | } 324 | 325 | /******************************************************************************/ 326 | 327 | function toggleTestHandler (event) { 328 | var checkbox = event.target; 329 | 330 | toggleTestEnabled(checkbox); 331 | updateEnabledTestCount(); 332 | } 333 | 334 | /******************************************************************************/ 335 | 336 | function toggleTestEnabled (checkbox) { 337 | var cdvtests = cordova.require('cordova-plugin-test-framework.cdvtests'); 338 | cdvtests.tests[checkbox.value].setEnabled(checkbox.checked); 339 | } 340 | 341 | /******************************************************************************/ 342 | 343 | function iterateAutoTests (cdvtests, callback) { 344 | Object.keys(cdvtests.tests).forEach(function (api) { 345 | var testModule = cdvtests.tests[api]; 346 | if (!Object.prototype.hasOwnProperty.call(testModule, 'defineAutoTests')) { 347 | return; 348 | } 349 | callback(api, testModule); 350 | }); 351 | } 352 | 353 | /******************************************************************************/ 354 | 355 | function runAutoTests () { 356 | setTitle('Auto Tests'); 357 | 358 | createActionButton('Run', setMode.bind(null, 'auto')); 359 | createActionButton('Reset App', location.reload.bind(location)); 360 | createActionButton('Back', setMode.bind(null, 'main')); 361 | 362 | var cdvtests = cordova.require('cordova-plugin-test-framework.cdvtests'); 363 | cdvtests.init(); 364 | setupAutoTestsEnablers(cdvtests); 365 | 366 | cdvtests.defineAutoTests(); 367 | 368 | // Run the tests! 369 | var jasmineEnv = window.jasmine.getEnv(); 370 | 371 | jasmineEnv.execute(); 372 | } 373 | 374 | /******************************************************************************/ 375 | 376 | function runManualTests () { 377 | setTitle('Manual Tests'); 378 | 379 | createActionButton('Reset App', location.reload.bind(location)); 380 | createActionButton('Back', setMode.bind(null, 'main')); 381 | 382 | var contentEl = document.getElementById('content'); 383 | var beforeEach = function (title) { 384 | clearContent(); 385 | setTitle(title || 'Manual Tests'); 386 | createActionButton('Reset App', location.reload.bind(location)); 387 | createActionButton('Back', setMode.bind(null, 'manual')); 388 | }; 389 | var cdvtests = cordova.require('cordova-plugin-test-framework.cdvtests'); 390 | cdvtests.defineManualTests(contentEl, beforeEach, createActionButton); 391 | } 392 | 393 | /******************************************************************************/ 394 | 395 | function runMain () { 396 | setTitle('Apache Cordova Plugin Tests'); 397 | 398 | createActionButton('Auto Tests', setMode.bind(null, 'auto')); 399 | createActionButton('Manual Tests', setMode.bind(null, 'manual')); 400 | createActionButton('Reset App', location.reload.bind(location)); 401 | if (/showBack/.exec(location.hash)) { 402 | createActionButton('Back', function () { 403 | history.go(-1); 404 | }); 405 | } 406 | 407 | if (isWin && typeof WinJS !== 'undefined') { 408 | var app = WinJS.Application; 409 | app.addEventListener('error', function () { 410 | // We do not want an unhandled exception to crash the test app 411 | // Returning true marks it as being handled 412 | return true; 413 | }); 414 | } 415 | } 416 | 417 | /******************************************************************************/ 418 | 419 | exports.init = function () { 420 | // TODO: have a way to opt-out of console wrapping in case line numbers are important. 421 | // ...Or find a custom way to print line numbers using stack or something. 422 | // make sure to always wrap when using medic. 423 | attachEvents(); 424 | exports.wrapConsole(); 425 | 426 | var medic = require('cordova-plugin-test-framework.medic'); 427 | medic.load(function () { 428 | if (medic.enabled) { 429 | setMode('auto'); 430 | } else { 431 | getMode(setMode); 432 | } 433 | }); 434 | }; 435 | 436 | /******************************************************************************/ 437 | --------------------------------------------------------------------------------