Compare commits

...

29 Commits

Author SHA1 Message Date
filmaj
8fc099b8f1 CB-12546: tweak parsing of avdmanager output to match the old output from android list avd. also explicitly set the CWD of the spawned emulator process to workaround a recent google android sdk bug. 2017-03-08 09:12:44 -08:00
filmaj
73f28541ab CB-12546: start of work on parsing emulator info from avdmanager output. work in progress. 2017-03-07 17:04:11 -08:00
Bharath Hariharan
7d5afdebe1 Updating version
This closes #364
2017-02-27 16:03:44 -08:00
Joe Bowser
3bbc7fb328 CB-12465: Writing new JUnit Test Instrumentation to replace tests and retire problmatic tests
This closes #363
2017-02-27 09:28:02 -08:00
Bharath Hariharan
ac6ad2dea1 Adding Binary plugin to class path
This closes #361
2017-02-22 16:47:59 -08:00
Bharath Hariharan
0b116f1b5c Updating Maven settings 2017-02-14 16:31:27 -08:00
Bharath Hariharan
acdb934ef9 Add the ability to publish to Bintray jCenter repo 2017-02-13 16:37:39 -08:00
Steve Gill
5591a1a4e8 Update JS snapshot to version 6.2.0-dev (via coho) 2017-01-26 16:30:33 -08:00
Steve Gill
124574bb3a Set VERSION to 6.2.0-dev (via coho) 2017-01-26 16:30:31 -08:00
Steve Gill
a2cfaab7f4 CB-12403 Updated RELEASENOTES and Version for release 6.1.2 2017-01-26 15:21:50 -08:00
Joe Bowser
6355425a6f Change to https by default 2017-01-20 09:31:31 -08:00
audreyso
2d96995801 CB:12018 : added dev dependencies to gitignore
This closes #355
2017-01-17 09:38:14 -08:00
audreyso
3fc4daa447 CB-12018 : updated tests to work with jasmine (promise matcher tests commented out for now) 2017-01-11 17:07:17 -08:00
Julio César
c7ff24b983 Closing invalid pull request: close #350 2017-01-10 19:22:44 +01:00
Jesse MacFadyen
3f674faf30 Merge branch 'CB-5968' of https://github.com/sterlingann/cordova-android 2017-01-08 22:42:18 -08:00
Steve Gill
b9ad1b6b26 Update JS snapshot to version 6.2.0-dev (via coho) 2017-01-03 17:45:55 -08:00
Steve Gill
676f0ddc2e CB-12314 updated release notes for 6.1.1 release 2017-01-03 17:45:15 -08:00
daserge
6c60dc5dc8 CB-12159 Android: Keystore password prompt won't show up
This closes #351
2016-12-08 09:51:24 -08:00
Joe Bowser
1af5ade39a Adding isClean to the spec, this really should have failed a few commits ago
This closes #349
2016-12-05 15:32:18 -08:00
Joe Bowser
ad40d33400 Need to pass lint 2016-11-21 16:36:20 -08:00
Joe Bowser
5017e2302b CB-12169: Check for build directory before running a clean 2016-11-21 14:46:09 -08:00
Joe Bowser
3bfeda4a3b Updating the timeout due to known travis issues 2016-11-03 11:35:42 -07:00
Jesse MacFadyen
348b1b4dda Do not test for non-existent build folder
This closes #348
2016-11-03 11:23:05 -07:00
Jesse MacFadyen
0fd7e7f040 Fixed AndroidStudio tests to actually run, removed app/src/main/assets/ as a requirement and added app/src/main/res instead, added placeholder for build/ folder, Removed dupe gitignore 2016-11-02 19:46:33 -07:00
Joe Bowser
cfa0fa7243 Update JS snapshot to version 6.2.0-dev (via coho) 2016-11-02 16:32:16 -07:00
Joe Bowser
6a63d9df0a Set VERSION to 6.2.0-dev (via coho) 2016-11-02 16:32:15 -07:00
Sterling
d6a1d7a913 updated xxhdpi mipmap icon to 144x144 2016-10-28 21:57:54 -07:00
Sterling
700b425774 replaced with unstretched images 2016-10-28 17:20:56 -07:00
Sterling
e31634b0fb created directories and corresponding images for xxhdpi and xxxhdpi, both drawables and mipmaps 2016-10-28 17:03:45 -07:00
121 changed files with 3893 additions and 2688 deletions

6
.gitignore vendored
View File

@@ -40,10 +40,9 @@ Desktop.ini
*.iml
.idea
npm-debug.log
/framework/build
node_modules/jshint
node_modules/promise-matchers
node_modules/jasmine-node
node_modules/jasmine
node_modules/rewire
node_modules/istanbul
node_modules/.bin/cake
@@ -54,7 +53,7 @@ node_modules/.bin/esparse
node_modules/.bin/esvalidate
node_modules/.bin/handlebars
node_modules/.bin/istanbul
node_modules/.bin/jasmine-node
node_modules/.bin/jasmine
node_modules/.bin/js-yaml
node_modules/.bin/jshint
node_modules/.bin/mkdirp
@@ -129,5 +128,6 @@ node_modules/which/
node_modules/window-size/
node_modules/wordwrap/
node_modules/yargs/
node_modules/jasmine-core/
node_modules/fs.realpath/
/coverage

View File

@@ -20,6 +20,16 @@
-->
## Release Notes for Cordova (Android) ##
### 6.1.2 (Jan 26, 2017)
* **Security** Change to `https` by default
* [CB-12018](https://issues.apache.org/jira/browse/CB-12018): updated tests to work with jasmine (promise matcher tests commented out for now)
* created directories and corresponding images for `xxhdpi` and `xxxhdpi`, both drawables and `mipmaps`
### 6.1.1 (Jan 03, 2017)
* [CB-12159](https://issues.apache.org/jira/browse/CB-12159) **Android** Keystore password prompt won't show up
* [CB-12169](https://issues.apache.org/jira/browse/CB-12169) Check for build directory before running a clean
* Fixed `AndroidStudio` tests to actually run, removed `app/src/main/assets/` as a requirement and added `app/src/main/res` instead, added placeholder for `build/` folder, Removed dupe `gitignore`
### 6.1.0 (Nov 02, 2016)
* [CB-12108](https://issues.apache.org/jira/browse/CB-12108) Updating gradle files to work with the latest version of Android Studio
* [CB-12102](https://issues.apache.org/jira/browse/CB-12102) Bump travis to build to API 25

View File

@@ -1 +1 @@
6.1.0-dev
6.2.0-dev

View File

@@ -62,3 +62,17 @@ module.exports.run = function() {
return Q.all([get_sdks()]);
};
module.exports.version_string_to_api_level = {
"4.0": 14,
"4.0.3": 15,
"4.1": 16,
"4.2": 17,
"4.3": 18,
"4.4": 19,
"4.4W": 20,
"5.0": 21,
"5.1": 22,
"6.0": 23,
"7.0": 24,
"7.1": 25
};

View File

@@ -72,6 +72,7 @@ function Api(platform, platformRootDir, events) {
defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'),
strings: path.join(self.root, 'res/values/strings.xml'),
manifest: path.join(self.root, 'AndroidManifest.xml'),
build: path.join(self.root, 'build'),
// NOTE: Due to platformApi spec we need to return relative paths here
cordovaJs: 'bin/templates/project/assets/www/cordova.js',
cordovaJsSrc: 'cordova-js-src'
@@ -241,11 +242,12 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
// Do some basic argument parsing
var opts = {};
// Skip cleaning prepared files when not invoking via cordova CLI.
// Skip cleaning prepared files when not invoking via cordova CLI.
opts.noPrepare = true;
if(!(AndroidStudio.isAndroidStudioProject(self.root)))
if(!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
return self.clean(opts);
}
})
.then(function () {
return PluginManager.get(self.platform, self.locations, project)
@@ -396,6 +398,8 @@ Api.prototype.clean = function(cleanOptions) {
});
};
/**
* Performs a requirements check for current platform. Each platform defines its
* own set of requirements, which should be resolved before platform can be

View File

@@ -197,5 +197,14 @@ AndroidProject.prototype.getUninstaller = function (type) {
return pluginHandlers.getUninstaller(type);
};
/*
* This checks if an Android project is clean or has old build artifacts
*/
AndroidProject.prototype.isClean = function() {
var build_path = path.join(this.projectDir, 'build');
//If the build directory doesn't exist, it's clean
return !(fs.existsSync(build_path));
};
module.exports = AndroidProject;

View File

@@ -8,15 +8,20 @@
var path = require('path');
var fs = require('fs');
var CordovaError = require('cordova-common').CordovaError;
module.exports.isAndroidStudioProject = function isAndroidStudioProject(root) {
var eclipseFiles = ['AndroidManifest.xml', 'libs', 'res', 'project.properties', 'platform_www'];
var androidStudioFiles = ['app', 'gradle', 'build', 'app/src/main/assets'];
var androidStudioFiles = ['app', 'gradle', 'app/src/main/res'];
// assume it is an AS project and not an Eclipse project
var isEclipse = false;
var isAS = true;
if(!fs.existsSync(root)) {
throw new CordovaError('AndroidStudio.js:inAndroidStudioProject root does not exist: ' + root);
}
// if any of the following exists, then we are not an ASProj
eclipseFiles.forEach(function(file) {
if(fs.existsSync(path.join(root, file))) {
@@ -28,6 +33,7 @@ module.exports.isAndroidStudioProject = function isAndroidStudioProject(root) {
if(!isEclipse) {
androidStudioFiles.forEach(function(file){
if(!fs.existsSync(path.join(root, file))) {
console.log('missing file :: ' + file);
isAS = false;
}
});

View File

@@ -186,7 +186,7 @@ GradleBuilder.prototype.prepEnv = function(opts) {
// For some reason, using ^ and $ don't work. This does the job, though.
var distributionUrlRegex = /distributionUrl.*zip/;
/*jshint -W069 */
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'http\\://services.gradle.org/distributions/gradle-2.14.1-all.zip';
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip';
/*jshint +W069 */
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
shell.chmod('u+w', gradleWrapperPropertiesPath);

View File

@@ -22,6 +22,7 @@
/* jshint sub:true */
var retry = require('./retry');
var android_sdk = require('./android_sdk_version');
var build = require('./build');
var path = require('path');
var Adb = require('./Adb');
@@ -29,9 +30,11 @@ var AndroidManifest = require('./AndroidManifest');
var events = require('cordova-common').events;
var spawn = require('cordova-common').superspawn.spawn;
var CordovaError = require('cordova-common').CordovaError;
var shelljs = require('shelljs');
var Q = require('q');
var os = require('os');
var fs = require('fs');
var child_process = require('child_process');
// constants
@@ -42,18 +45,16 @@ var NUM_INSTALL_RETRIES = 3;
var CHECK_BOOTED_INTERVAL = 3 * ONE_SECOND; // in milliseconds
var EXEC_KILL_SIGNAL = 'SIGKILL';
/**
* Returns a Promise for a list of emulator images in the form of objects
* {
name : <emulator_name>,
path : <path_to_emulator_image>,
target : <api_target>,
abi : <cpu>,
skin : <skin>
}
*/
module.exports.list_images = function() {
return spawn('android', ['list', 'avds'])
function forgivingWhichSync(cmd) {
try {
return fs.realpathSync(shelljs.which(cmd));
} catch (e) {
return '';
}
}
function list_images_using_avdmanager() {
return spawn('avdmanager', ['list', 'avd'])
.then(function(output) {
var response = output.split('\n');
var emulator_list = [];
@@ -70,14 +71,30 @@ module.exports.list_images = function() {
i++;
img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
}
if (response[i + 1].match(/\(API\slevel\s/) || (response[i + 2] && response[i + 2].match(/\(API\slevel\s/))) {
if (response[i + 1].match(/Target:\s/)) {
var api = response[i + 1].split('Target: ')[1];
i++;
var secondLine = response[i + 1].match(/\(API\slevel\s/) ? response[i + 1] : '';
img_obj['target'] = (response[i] + secondLine).split('Target: ')[1].replace('\r', '');
}
if (response[i + 1].match(/ABI:\s/)) {
i++;
img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
if (response[i + 1].match(/ABI:\s/)) {
img_obj['abi'] = response[i + 1].split('ABI: ')[1].replace('\r', '');
}
// This next conditional just aims to match the old output of `android list avd`
// We do so so that we don't have to change the logic when parsing for the
// best emulator target to spawn (see below in `best_image`)
// This allows us to transitionally support both `android` and `avdmanager` binaries,
// depending on what SDK version the user has
if (response[i + 1].match(/Based\son:\s/)) {
img_obj['target'] = response[i + 1].split('Based on:')[1];
if (img_obj['target'].match(/Tag\/ABI:\s/)) {
img_obj['target'] = img_obj['target'].split('Tag/ABI:')[0].replace('\r', '').trim();
if (img_obj['target'].indexOf('(') > -1) {
img_obj['target'] = img_obj['target'].substr(0, img_obj['target'].indexOf('(') - 1).trim();
}
}
var version_string = img_obj['target'].replace(/Android\s+/, '');
if (android_sdk.version_string_to_api_level[version_string]) {
img_obj['target'] += ' (API level ' + android_sdk.version_string_to_api_level[version_string] + ')';
}
}
}
if (response[i + 1].match(/Skin:\s/)) {
i++;
@@ -94,6 +111,73 @@ module.exports.list_images = function() {
}
return emulator_list;
});
}
/**
* Returns a Promise for a list of emulator images in the form of objects
* {
name : <emulator_name>,
path : <path_to_emulator_image>,
target : <api_target>,
abi : <cpu>,
skin : <skin>
}
*/
module.exports.list_images = function() {
if (forgivingWhichSync('android')) {
return spawn('android', ['list', 'avds'])
.then(function(output) {
var response = output.split('\n');
var emulator_list = [];
for (var i = 1; i < response.length; i++) {
// To return more detailed information use img_obj
var img_obj = {};
if (response[i].match(/Name:\s/)) {
img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
if (response[i + 1].match(/Device:\s/)) {
i++;
img_obj['device'] = response[i].split('Device: ')[1].replace('\r', '');
}
if (response[i + 1].match(/Path:\s/)) {
i++;
img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
}
if (response[i + 1].match(/\(API\slevel\s/) || (response[i + 2] && response[i + 2].match(/\(API\slevel\s/))) {
i++;
var secondLine = response[i + 1].match(/\(API\slevel\s/) ? response[i + 1] : '';
img_obj['target'] = (response[i] + secondLine).split('Target: ')[1].replace('\r', '');
}
if (response[i + 1].match(/ABI:\s/)) {
i++;
img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
}
if (response[i + 1].match(/Skin:\s/)) {
i++;
img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
}
emulator_list.push(img_obj);
}
/* To just return a list of names use this
if (response[i].match(/Name:\s/)) {
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
}*/
}
return emulator_list;
}).catch(function(stderr) {
// try to use `avdmanager` in case `android` has problems
// this likely means the target machine is using a newer version of
// the android sdk, and possibly `avdmanager` is available.
return list_images_using_avdmanager();
});
} else if (forgivingWhichSync('avdmanager')) {
return list_images_using_avdmanager();
} else {
return Q().then(function() {
throw new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?');
});
}
};
/**
@@ -199,10 +283,13 @@ module.exports.start = function(emulator_ID, boot_timeout) {
}).then(function(emulatorId) {
return self.get_available_port()
.then(function (port) {
// Figure out the directory the emulator binary runs in, and set the cwd to that directory.
// Workaround for https://code.google.com/p/android/issues/detail?id=235461
var emulator_dir = path.dirname(shelljs.which('emulator'));
var args = ['-avd', emulatorId, '-port', port];
// Don't wait for it to finish, since the emulator will probably keep running for a long time.
child_process
.spawn('emulator', args, { stdio: 'inherit', detached: true })
.spawn('emulator', args, { stdio: 'inherit', detached: true, cwd: emulator_dir })
.unref();
// wait for emulator to start

View File

@@ -20,7 +20,7 @@
*/
// Coho updates this line:
var VERSION = "6.1.0-dev";
var VERSION = "6.2.0-dev";
module.exports.version = VERSION;

View File

@@ -1,5 +1,5 @@
// Platform: android
// 53ea1913735222d326e65326e03391405df3cd4e
// 7c5fcc5a5adfbf3fb8ceaf36fbdd4bd970bd9c20
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,7 +19,7 @@
under the License.
*/
;(function() {
var PLATFORM_VERSION_BUILD_LABEL = '6.1.0-dev';
var PLATFORM_VERSION_BUILD_LABEL = '6.2.0-dev';
// file: src/scripts/require.js
/*jshint -W079 */
@@ -330,7 +330,7 @@ module.exports = cordova;
});
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
define("cordova/android/nativeapiprovider", function(require, exports, module) {
/**
@@ -353,7 +353,7 @@ module.exports = {
});
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
define("cordova/android/promptbasednativeapi", function(require, exports, module) {
/**
@@ -886,7 +886,7 @@ module.exports = channel;
});
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/exec.js
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/exec.js
define("cordova/exec", function(require, exports, module) {
/**
@@ -1649,7 +1649,7 @@ exports.reset();
});
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/platform.js
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/platform.js
define("cordova/platform", function(require, exports, module) {
// The last resume event that was received that had the result of a plugin call.
@@ -1759,7 +1759,7 @@ function onMessageFromNative(msg) {
});
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/plugin/android/app.js
// file: /Users/steveng/repo/cordova/cordova-android/cordova-js-src/plugin/android/app.js
define("cordova/plugin/android/app", function(require, exports, module) {
var exec = require('cordova/exec');

View File

@@ -30,7 +30,7 @@ buildscript {
// http://tools.android.com/tech-docs/new-build-system/version-compatibility
// and https://issues.apache.org/jira/browse/CB-8143
dependencies {
classpath 'com.android.tools.build:gradle:2.2.1'
classpath 'com.android.tools.build:gradle:2.2.3'
}
}
@@ -264,7 +264,7 @@ def promptForReleaseKeyPassword() {
gradle.taskGraph.whenReady { taskGraph ->
taskGraph.getAllTasks().each() { task ->
if (task.name == 'validateReleaseSigning') {
if (task.name == 'validateReleaseSigning' || task.name == 'validateSigningRelease') {
promptForReleaseKeyPassword()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -16,28 +16,32 @@
under the License.
*/
buildscript {
repositories {
mavenCentral()
jcenter();
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.1'
}
}
apply plugin: 'com.android.library'
ext {
apply from: 'cordova.gradle'
cdvCompileSdkVersion = privateHelpers.getProjectTarget()
cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
}
}
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
group = 'org.apache.cordova'
version = '6.2.0'
android {
compileSdkVersion cdvCompileSdkVersion
buildToolsVersion cdvBuildToolsVersion
@@ -59,4 +63,73 @@ android {
assets.srcDirs = ['assets']
}
}
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
}
}
install {
repositories.mavenInstaller {
pom {
project {
packaging 'aar'
name 'Cordova'
url 'https://cordova.apache.org'
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id 'stevengill'
name 'Steve Gill'
}
}
scm {
connection 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git'
developerConnection 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git'
url 'https://git-wip-us.apache.org/repos/asf?p=cordova-android'
}
}
}
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
artifacts {
archives sourcesJar
}
bintray {
user = System.getenv('BINTRAY_USER')
key = System.getenv('BINTRAY_KEY')
configurations = ['archives']
pkg {
repo = 'maven'
name = 'cordova-android'
userOrg = 'cordova'
licenses = ['Apache-2.0']
vcsUrl = 'https://git-wip-us.apache.org/repos/asf?p=cordova-android.git'
websiteUrl = 'https://cordova.apache.org'
issueTrackerUrl = 'https://issues.apache.org/jira/browse/CB'
publicDownloadNumbers = true
licenses = ['Apache-2.0']
labels = ['android', 'cordova', 'phonegap']
version {
name = '6.2.0'
released = new Date()
vcsTag = '6.2.0'
}
}
}

View File

@@ -31,7 +31,7 @@ import android.webkit.WebChromeClient.CustomViewCallback;
* are not expected to implement it.
*/
public interface CordovaWebView {
public static final String CORDOVA_VERSION = "6.1.0-dev";
public static final String CORDOVA_VERSION = "6.2.0-dev";
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);

View File

@@ -1,49 +1,49 @@
{
"name": "cordova-android",
"version": "6.1.0",
"description": "cordova-android release",
"bin": {
"create": "bin/create"
},
"main": "bin/templates/cordova/Api.js",
"repository": {
"type": "git",
"url": "https://git-wip-us.apache.org/repos/asf/cordova-android.git"
},
"keywords": [
"android",
"cordova",
"apache"
],
"scripts": {
"test": "npm run jshint && jasmine-node --color spec/unit",
"cover": "istanbul cover --root bin/templates/cordova --print detail node_modules/jasmine-node/bin/jasmine-node -- spec/unit",
"test-build": "jasmine-node --captureExceptions --color spec/e2e",
"jshint": "node node_modules/jshint/bin/jshint bin && node node_modules/jshint/bin/jshint spec"
},
"author": "Apache Software Foundation",
"license": "Apache-2.0",
"dependencies": {
"cordova-common": "^1.5.0",
"elementtree": "^0.1.6",
"nopt": "^3.0.1",
"properties-parser": "^0.2.3",
"q": "^1.4.1",
"shelljs": "^0.5.3"
},
"bundledDependencies": [
"cordova-common",
"elementtree",
"nopt",
"properties-parser",
"q",
"shelljs"
],
"devDependencies": {
"istanbul": "^0.4.2",
"jasmine-node": "^1.14.5",
"jshint": "^2.6.0",
"promise-matchers": "~0",
"rewire": "^2.1.3"
}
"name": "cordova-android",
"version": "6.2.0-dev",
"description": "cordova-android release",
"bin": {
"create": "bin/create"
},
"main": "bin/templates/cordova/Api.js",
"repository": {
"type": "git",
"url": "https://git-wip-us.apache.org/repos/asf/cordova-android.git"
},
"keywords": [
"android",
"cordova",
"apache"
],
"scripts": {
"test": "npm run jshint && jasmine",
"cover": "istanbul cover --root bin/templates/cordova --print detail jasmine",
"test-build": "jasmine --captureExceptions --color spec/e2e/*.spec.js",
"jshint": "jshint bin && jshint spec"
},
"author": "Apache Software Foundation",
"license": "Apache-2.0",
"dependencies": {
"cordova-common": "^1.5.0",
"elementtree": "^0.1.6",
"nopt": "^3.0.1",
"properties-parser": "^0.2.3",
"q": "^1.4.1",
"shelljs": "^0.5.3"
},
"bundledDependencies": [
"cordova-common",
"elementtree",
"nopt",
"properties-parser",
"q",
"shelljs"
],
"devDependencies": {
"istanbul": "^0.4.2",
"jasmine": "^2.5.2",
"jshint": "^2.6.0",
"promise-matchers": "~0",
"rewire": "^2.1.3"
}
}

View File

@@ -35,42 +35,42 @@ function createAndBuild(projectname, projectid, done) {
describe('create', function() {
it('create project with ascii name, no spaces', function(done) {
it('Test#001 : create project with ascii name, no spaces', function(done) {
var projectname = 'testcreate';
var projectid = 'com.test.create.app1';
createAndBuild(projectname, projectid, done);
}, CREATE_TIMEOUT);
it('create project with ascii name, and spaces', function(done) {
it('Test#002 : create project with ascii name, and spaces', function(done) {
var projectname = 'test create';
var projectid = 'com.test.create.app2';
createAndBuild(projectname, projectid, done);
}, CREATE_TIMEOUT);
it('create project with unicode name, no spaces', function(done) {
it('Test#003 : create project with unicode name, no spaces', function(done) {
var projectname = '応応応応用用用用';
var projectid = 'com.test.create.app3';
createAndBuild(projectname, projectid, done);
}, CREATE_TIMEOUT);
it('create project with unicode name, and spaces', function(done) {
it('Test#004 : create project with unicode name, and spaces', function(done) {
var projectname = '応応応応 用用用用';
var projectid = 'com.test.create.app4';
createAndBuild(projectname, projectid, done);
}, CREATE_TIMEOUT);
it('create project with ascii+unicode name, no spaces', function(done) {
it('Test#005 : create project with ascii+unicode name, no spaces', function(done) {
var projectname = '応応応応hello用用用用';
var projectid = 'com.test.create.app5';
createAndBuild(projectname, projectid, done);
}, CREATE_TIMEOUT);
it('create project with ascii+unicode name, and spaces', function(done) {
it('Test#006 : create project with ascii+unicode name, and spaces', function(done) {
var projectname = '応応応応 hello 用用用用';
var projectid = 'com.test.create.app6';

View File

@@ -20,11 +20,11 @@
var path = require('path'),
actions = require('./helpers/projectActions.js');
var PLUGIN_ADD_TIMEOUT = 60000;
var PLUGIN_ADD_TIMEOUT = 90000;
describe('plugin add', function() {
it('create project and add a plugin with framework', function(done) {
it('Test#001 : create project and add a plugin with framework', function(done) {
var projectname = 'testpluginframework';
var projectid = 'com.test.plugin.framework';
var fakePluginPath = path.join(__dirname, 'fixtures/cordova-plugin-fake');

View File

@@ -56,7 +56,7 @@ function testUpdate(projectname, projectid, createfrom, updatefrom, doBuild, don
describe('preparing fixtures', function () {
it('cloning old platform', function (done) {
it('Test#001 : cloning old platform', function (done) {
var command = util.format('git clone %s --depth=1 --branch %s %s',
PLATFORM_GIT_URL, platformOld.version, platformOld.path);
shell.rm('-rf', platformOld.path);
@@ -70,7 +70,7 @@ describe('preparing fixtures', function () {
describe('update', function() {
it('should update major version and build the project', function(done) {
it('Test#002 : should update major version and build the project', function(done) {
var projectname = 'testupdate';
var projectid = 'com.test.update.app1';
@@ -78,7 +78,7 @@ describe('update', function() {
}, UPDATE_TIMEOUT);
it('should downgrade major version and build the project', function(done) {
it('Test#003 : should downgrade major version and build the project', function(done) {
var projectname = 'testupdate';
var projectid = 'com.test.update.app2';
@@ -90,7 +90,7 @@ describe('update', function() {
describe('cleanup', function () {
it('remove cloned old platform', function() {
it('Test#004 : remove cloned old platform', function() {
shell.rm('-rf', platformOld.path);
});

View File

@@ -0,0 +1 @@
Tests require that this folder exists.

View File

@@ -0,0 +1,8 @@
{
"spec_dir": "spec",
"spec_files": [
"unit/**/*[sS]pec.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}

View File

@@ -23,7 +23,7 @@ var android_project = path.join(__dirname, '../fixtures/android_project');
describe('AndroidProject class', function() {
describe('getPackageName method', function() {
it('should return an android project\'s proper package name', function() {
it('Test#001 : should return an android project\'s proper package name', function() {
expect(AndroidProject.getProjectFile(android_project).getPackageName())
.toEqual('com.alunny.childapp');
});

View File

@@ -1,14 +0,0 @@
var AndroidStudio = require('../../bin/templates/cordova/lib/AndroidStudio');
describe('AndroidStudio module', function () {
it('should detect Android Studio project', function() {
var root = './fixtures/android_studio_project';
spyOn(AndroidStudio, 'isAndroidStudioProject').andReturn(true);
AndroidStudio.isAndroidStudioProject(root);
});
it('should detect non Android Studio project', function() {
var root = './fixtures/android_project';
spyOn(AndroidStudio, 'isAndroidStudioProject').andReturn(false);
AndroidStudio.isAndroidStudioProject(root);
});
});

View File

@@ -0,0 +1,17 @@
var path = require('path');
var AndroidStudio = require('../../bin/templates/cordova/lib/AndroidStudio');
describe('AndroidStudio module', function () {
it('should return true for Android Studio project', function() {
var root = path.join(__dirname,'../fixtures/android_studio_project/');
var isAndStud = AndroidStudio.isAndroidStudioProject(root);
expect(isAndStud).toBe(true);
});
it('should return false non Android Studio project', function() {
var root = path.join(__dirname,'../fixtures/android_project/');
var isAndStud = AndroidStudio.isAndroidStudioProject(root);
expect(isAndStud).toBe(false);
});
});

View File

@@ -39,11 +39,11 @@ describe('addPlugin method', function () {
beforeEach(function() {
var pluginManager = jasmine.createSpyObj('pluginManager', ['addPlugin']);
pluginManager.addPlugin.andReturn(Q());
spyOn(common.PluginManager, 'get').andReturn(pluginManager);
pluginManager.addPlugin.and.returnValue(Q());
spyOn(common.PluginManager, 'get').and.returnValue(pluginManager);
var projectSpy = jasmine.createSpyObj('AndroidProject', ['getPackageName', 'write']);
spyOn(AndroidProject, 'getProjectFile').andReturn(projectSpy);
var projectSpy = jasmine.createSpyObj('AndroidProject', ['getPackageName', 'write', 'isClean']);
spyOn(AndroidProject, 'getProjectFile').and.returnValue(projectSpy);
oldClean = Api.__get__('Api.prototype.clean');
Api.__set__('Api.prototype.clean', Q);
@@ -51,14 +51,14 @@ describe('addPlugin method', function () {
fail = jasmine.createSpy('fail');
gradleBuilder = jasmine.createSpyObj('gradleBuilder', ['prepBuildFiles']);
spyOn(builders, 'getBuilder').andReturn(gradleBuilder);
spyOn(builders, 'getBuilder').and.returnValue(gradleBuilder);
});
afterEach(function () {
Api.__set__('Api.prototype.clean', oldClean);
});
it('should call gradleBuilder.prepBuildFiles for every plugin with frameworks', function(done) {
it('Test#001 : should call gradleBuilder.prepBuildFiles for every plugin with frameworks', function(done) {
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake')))
.catch(fail)
.fin(function () {
@@ -68,7 +68,7 @@ describe('addPlugin method', function () {
});
});
it('shouldn\'t trigger gradleBuilder.prepBuildFiles for plugins without android frameworks', function(done) {
it('Test#002 : shouldn\'t trigger gradleBuilder.prepBuildFiles for plugins without android frameworks', function(done) {
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake-ios-frameworks')))
.catch(fail)
.fin(function () {

View File

@@ -18,8 +18,6 @@
*/
/* jshint laxcomma:true */
require("promise-matchers");
var create = require("../../bin/lib/create");
describe("create", function () {
@@ -48,14 +46,27 @@ describe("create", function () {
];
valid.forEach(function(package_name) {
it("should accept " + package_name, function(done) {
expect(create.validatePackageName(package_name)).toHaveBeenResolved(done);
it("Test#001 : should accept " + package_name, function(done) {
return create.validatePackageName(package_name)
.then(function() {
//resolved
done();
}).fail(function(err) {
expect(err).toBeUndefined();
});
});
});
invalid.forEach(function(package_name) {
it("should reject " + package_name, function(done) {
expect(create.validatePackageName(package_name)).toHaveBeenRejected(done);
it("Test#002 : should reject " + package_name, function(done) {
return create.validatePackageName(package_name)
.then(function() {
//shouldn't be here
expect(true).toBe(false);
}).fail(function(err) {
expect(err).toBeDefined();
done();
});
});
});
});
@@ -73,15 +84,29 @@ describe("create", function () {
];
valid.forEach(function(project_name) {
it("should accept " + project_name, function(done) {
expect(create.validateProjectName(project_name)).toHaveBeenResolved(done);
it("Test#003 : should accept " + project_name, function(done) {
return create.validateProjectName(project_name)
.then(function() {
//resolved
done();
}).fail(function(err) {
expect(err).toBeUndefined();
});
});
});
invalid.forEach(function(project_name) {
it("should reject " + project_name, function(done) {
expect(create.validateProjectName(project_name)).toHaveBeenRejected(done);
it("Test#004 : should reject " + project_name, function(done) {
return create.validateProjectName(project_name)
.then(function() {
//shouldn't be here
expect(true).toBe(false);
}).fail(function(err) {
expect(err).toBeDefined();
done();
});
});
});
});
});

View File

@@ -38,13 +38,13 @@ var copyNewFile = common.__get__('copyNewFile');
describe('common platform handler', function() {
describe('copyFile', function() {
it('should throw if source path not found', function(){
it('Test#001 : should throw if source path not found', function(){
shell.rm('-rf', src);
expect(function(){copyFile(test_dir, src, project_dir, dest);})
.toThrow(new Error('"' + src + '" not found!'));
});
it('should throw if src not in plugin directory', function(){
it('Test#002 : should throw if src not in plugin directory', function(){
shell.mkdir('-p', project_dir);
fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
var outside_file = '../non_plugin_file';
@@ -53,7 +53,7 @@ describe('common platform handler', function() {
shell.rm('-rf', test_dir);
});
it('should allow symlink src, if inside plugin', function(){
it('Test#003 : should allow symlink src, if inside plugin', function(){
shell.mkdir('-p', java_dir);
fs.writeFileSync(java_file, 'contents', 'utf-8');
@@ -66,7 +66,7 @@ describe('common platform handler', function() {
shell.rm('-rf', project_dir);
});
it('should throw if symlink is linked to a file outside the plugin', function(){
it('Test#004 : should throw if symlink is linked to a file outside the plugin', function(){
shell.mkdir('-p', java_dir);
fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
@@ -80,7 +80,7 @@ describe('common platform handler', function() {
shell.rm('-rf', project_dir);
});
it('should throw if dest is outside the project directory', function(){
it('Test#005 : should throw if dest is outside the project directory', function(){
shell.mkdir('-p', java_dir);
fs.writeFileSync(java_file, 'contents', 'utf-8');
expect(function(){copyFile(test_dir, java_file, project_dir, non_plugin_file);}).
@@ -88,11 +88,11 @@ describe('common platform handler', function() {
shell.rm('-rf', project_dir);
});
it('should call mkdir -p on target path', function(){
it('Test#006 : should call mkdir -p on target path', function(){
shell.mkdir('-p', java_dir);
fs.writeFileSync(java_file, 'contents', 'utf-8');
var s = spyOn(shell, 'mkdir').andCallThrough();
var s = spyOn(shell, 'mkdir').and.callThrough();
var resolvedDest = path.resolve(project_dir, dest);
copyFile(test_dir, java_file, project_dir, dest);
@@ -102,11 +102,11 @@ describe('common platform handler', function() {
shell.rm('-rf', project_dir);
});
it('should call cp source/dest paths', function(){
it('Test#007 : should call cp source/dest paths', function(){
shell.mkdir('-p', java_dir);
fs.writeFileSync(java_file, 'contents', 'utf-8');
var s = spyOn(shell, 'cp').andCallThrough();
var s = spyOn(shell, 'cp').and.callThrough();
var resolvedDest = path.resolve(project_dir, dest);
copyFile(test_dir, java_file, project_dir, dest);
@@ -119,7 +119,7 @@ describe('common platform handler', function() {
});
describe('copyNewFile', function () {
it('should throw if target path exists', function(){
it('Test#008 : should throw if target path exists', function(){
shell.mkdir('-p', dest);
expect(function(){copyNewFile(test_dir, src, project_dir, dest);}).
toThrow(new Error('"' + dest + '" already exists!'));
@@ -137,21 +137,21 @@ describe('common platform handler', function() {
shell.rm('-rf', java_dir);
});
it('should call fs.unlinkSync on the provided paths', function(){
var s = spyOn(fs, 'unlinkSync').andCallThrough();
it('Test#009 : should call fs.unlinkSync on the provided paths', function(){
var s = spyOn(fs, 'unlinkSync').and.callThrough();
deleteJava(project_dir, java_file);
expect(s).toHaveBeenCalled();
expect(s).toHaveBeenCalledWith(path.resolve(project_dir, java_file));
});
it('should delete empty directories after removing source code in a java src path hierarchy', function(){
it('Test#010 : should delete empty directories after removing source code in a java src path hierarchy', function(){
deleteJava(project_dir, java_file);
expect(fs.existsSync(java_file)).not.toBe(true);
expect(fs.existsSync(java_dir)).not.toBe(true);
expect(fs.existsSync(path.join(src,'one'))).not.toBe(true);
});
it('should never delete the top-level src directory, even if all plugins added were removed', function(){
it('Test#011 : should never delete the top-level src directory, even if all plugins added were removed', function(){
deleteJava(project_dir, java_file);
expect(fs.existsSync(src)).toBe(true);
});

View File

@@ -50,7 +50,7 @@ describe('android project handler', function() {
beforeEach(function() {
shell.mkdir('-p', temp);
dummyProject = AndroidProject.getProjectFile(temp);
copyFileSpy.reset();
copyFileSpy.calls.reset();
common.__set__('copyFile', copyFileSpy);
});
@@ -60,18 +60,18 @@ describe('android project handler', function() {
});
describe('of <lib-file> elements', function() {
it('should copy files', function () {
it('Test#001 : should copy files', function () {
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject);
expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, 'src/android/TestLib.jar', temp, path.join('libs', 'TestLib.jar'), false);
});
it('should copy files for Android Studio projects', function () {
it('Test#002 : should copy files for Android Studio projects', function () {
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio: true});
expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, 'src/android/TestLib.jar', temp, path.join('app', 'libs', 'TestLib.jar'), false);
});
});
describe('of <resource-file> elements', function() {
it('should copy files', function () {
it('Test#003 : should copy files', function () {
android['resource-file'].install(valid_resources[0], dummyPluginInfo, dummyProject);
expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, 'android-resource.xml', temp, path.join('res', 'xml', 'dummy.xml'), false);
});
@@ -82,26 +82,26 @@ describe('android project handler', function() {
shell.cp('-rf', android_project, temp);
});
it('should copy stuff from one location to another by calling common.copyFile', function() {
it('Test#004 : should copy stuff from one location to another by calling common.copyFile', function() {
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject);
expect(copyFileSpy)
.toHaveBeenCalledWith(dummyplugin, 'src/android/DummyPlugin.java', temp, path.join('src/com/phonegap/plugins/dummyplugin/DummyPlugin.java'), false);
});
it('should install source files to the right location for Android Studio projects', function() {
it('Test#005 : should install source files to the right location for Android Studio projects', function() {
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject, {android_studio: true});
expect(copyFileSpy)
.toHaveBeenCalledWith(dummyplugin, 'src/android/DummyPlugin.java', temp, path.join('app/src/main/java/com/phonegap/plugins/dummyplugin/DummyPlugin.java'), false);
});
it('should throw if source file cannot be found', function() {
it('Test#006 : should throw if source file cannot be found', function() {
common.__set__('copyFile', copyFileOrig);
expect(function() {
android['source-file'].install(invalid_source[0], faultyPluginInfo, dummyProject);
}).toThrow('"' + path.resolve(faultyplugin, 'src/android/NotHere.java') + '" not found!');
}).toThrow(new Error('"' + path.resolve(faultyplugin, 'src/android/NotHere.java') + '" not found!'));
});
it('should throw if target file already exists', function() {
it('Test#007 : should throw if target file already exists', function() {
// write out a file
var target = path.resolve(temp, 'src/com/phonegap/plugins/dummyplugin');
shell.mkdir('-p', target);
@@ -110,7 +110,7 @@ describe('android project handler', function() {
expect(function() {
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject);
}).toThrow('"' + target + '" already exists!');
}).toThrow(new Error ('"' + target + '" already exists!'));
});
});
@@ -134,23 +134,23 @@ describe('android project handler', function() {
common.__set__('copyNewFile', copyNewFileOrig);
});
it('should throw if framework doesn\'t have "src" attribute', function() {
it('Test#008 : should throw if framework doesn\'t have "src" attribute', function() {
expect(function() { android.framework.install({}, dummyPluginInfo, dummyProject); }).toThrow();
});
it('should install framework without "parent" attribute into project root', function() {
it('Test#009 : should install framework without "parent" attribute into project root', function() {
var framework = {src: 'plugin-lib'};
android.framework.install(framework, dummyPluginInfo, dummyProject);
expect(dummyProject.addSystemLibrary).toHaveBeenCalledWith(dummyProject.projectDir, someString);
});
it('should install framework with "parent" attribute into parent framework dir', function() {
it('Test#010 : should install framework with "parent" attribute into parent framework dir', function() {
var childFramework = {src: 'plugin-lib2', parent: 'plugin-lib'};
android.framework.install(childFramework, dummyPluginInfo, dummyProject);
expect(dummyProject.addSystemLibrary).toHaveBeenCalledWith(path.resolve(dummyProject.projectDir, childFramework.parent), someString);
});
it('should not copy anything if "custom" attribute is not set', function() {
it('Test#011 : should not copy anything if "custom" attribute is not set', function() {
var framework = {src: 'plugin-lib'};
var cpSpy = spyOn(shell, 'cp');
android.framework.install(framework, dummyPluginInfo, dummyProject);
@@ -158,14 +158,14 @@ describe('android project handler', function() {
expect(cpSpy).not.toHaveBeenCalled();
});
it('should copy framework sources if "custom" attribute is set', function() {
it('Test#012 : should copy framework sources if "custom" attribute is set', function() {
var framework = {src: 'plugin-lib', custom: true};
android.framework.install(framework, dummyPluginInfo, dummyProject);
expect(dummyProject.addSubProject).toHaveBeenCalledWith(dummyProject.projectDir, someString);
expect(copyNewFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, framework.src, dummyProject.projectDir, someString, false);
});
it('should install gradleReference using project.addGradleReference', function() {
it('Test#013 : should install gradleReference using project.addGradleReference', function() {
var framework = {src: 'plugin-lib', custom: true, type: 'gradleReference'};
android.framework.install(framework, dummyPluginInfo, dummyProject);
expect(copyNewFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, framework.src, dummyProject.projectDir, someString, false);
@@ -183,13 +183,13 @@ describe('android project handler', function() {
platformWwwDest = path.resolve(dummyProject.platformWww, 'plugins', dummyPluginInfo.id, jsModule.src);
});
it('should put module to both www and platform_www when options.usePlatformWww flag is specified', function () {
it('Test#014 : should put module to both www and platform_www when options.usePlatformWww flag is specified', function () {
android['js-module'].install(jsModule, dummyPluginInfo, dummyProject, {usePlatformWww: true});
expect(fs.writeFileSync).toHaveBeenCalledWith(wwwDest, jasmine.any(String), 'utf-8');
expect(fs.writeFileSync).toHaveBeenCalledWith(platformWwwDest, jasmine.any(String), 'utf-8');
});
it('should put module to www only when options.usePlatformWww flag is not specified', function () {
it('Test#015 : should put module to www only when options.usePlatformWww flag is not specified', function () {
android['js-module'].install(jsModule, dummyPluginInfo, dummyProject);
expect(fs.writeFileSync).toHaveBeenCalledWith(wwwDest, jasmine.any(String), 'utf-8');
expect(fs.writeFileSync).not.toHaveBeenCalledWith(platformWwwDest, jasmine.any(String), 'utf-8');
@@ -205,13 +205,13 @@ describe('android project handler', function() {
platformWwwDest = path.resolve(dummyProject.platformWww, asset.target);
});
it('should put asset to both www and platform_www when options.usePlatformWww flag is specified', function () {
it('Test#016 : should put asset to both www and platform_www when options.usePlatformWww flag is specified', function () {
android.asset.install(asset, dummyPluginInfo, dummyProject, {usePlatformWww: true});
expect(copyFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, asset.src, dummyProject.www, asset.target);
expect(copyFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, asset.src, dummyProject.platformWww, asset.target);
});
it('should put asset to www only when options.usePlatformWww flag is not specified', function () {
it('Test#017 : should put asset to www only when options.usePlatformWww flag is not specified', function () {
android.asset.install(asset, dummyPluginInfo, dummyProject);
expect(copyFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, asset.src, dummyProject.www, asset.target);
expect(copyFileSpy).not.toHaveBeenCalledWith(dummyPluginInfo.dir, asset.src, dummyProject.platformWww, asset.target);
@@ -244,21 +244,21 @@ describe('android project handler', function() {
common.__set__('deleteJava', deleteJavaOrig);
});
describe('of <lib-file> elements', function(done) {
it('should remove jar files', function () {
describe('of <lib-file> elements', function() {
it('Test#018 : should remove jar files', function () {
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject);
android['lib-file'].uninstall(valid_libs[0], dummyPluginInfo, dummyProject);
expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('libs/TestLib.jar'));
});
it('should remove jar files for Android Studio projects', function () {
it('Test#019 : should remove jar files for Android Studio projects', function () {
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio:true});
android['lib-file'].uninstall(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio:true});
expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/libs/TestLib.jar'));
});
});
describe('of <resource-file> elements', function(done) {
it('should remove files', function () {
describe('of <resource-file> elements', function() {
it('Test#020 : should remove files', function () {
android['resource-file'].install(valid_resources[0], dummyPluginInfo, dummyProject);
android['resource-file'].uninstall(valid_resources[0], dummyPluginInfo, dummyProject);
expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('res/xml/dummy.xml'));
@@ -266,12 +266,12 @@ describe('android project handler', function() {
});
describe('of <source-file> elements', function() {
it('should remove stuff by calling common.deleteJava', function() {
it('Test#021 : should remove stuff by calling common.deleteJava', function() {
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject);
android['source-file'].uninstall(valid_source[0], dummyPluginInfo, dummyProject);
expect(deleteJavaSpy).toHaveBeenCalledWith(temp, path.join('src/com/phonegap/plugins/dummyplugin/DummyPlugin.java'));
});
it('should remove stuff by calling common.deleteJava for Android Studio projects', function() {
it('Test#022 : should remove stuff by calling common.deleteJava for Android Studio projects', function() {
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject, {android_studio:true});
android['source-file'].uninstall(valid_source[0], dummyPluginInfo, dummyProject, {android_studio:true});
expect(deleteJavaSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/java/com/phonegap/plugins/dummyplugin/DummyPlugin.java'));
@@ -290,30 +290,30 @@ describe('android project handler', function() {
spyOn(dummyProject, 'removeGradleReference');
});
it('should throw if framework doesn\'t have "src" attribute', function() {
it('Test#023 : should throw if framework doesn\'t have "src" attribute', function() {
expect(function() { android.framework.uninstall({}, dummyPluginInfo, dummyProject); }).toThrow();
});
it('should uninstall framework without "parent" attribute into project root', function() {
it('Test#024 : should uninstall framework without "parent" attribute into project root', function() {
var framework = {src: 'plugin-lib'};
android.framework.uninstall(framework, dummyPluginInfo, dummyProject);
expect(dummyProject.removeSystemLibrary).toHaveBeenCalledWith(dummyProject.projectDir, someString);
});
it('should uninstall framework with "parent" attribute into parent framework dir', function() {
it('Test#025 : should uninstall framework with "parent" attribute into parent framework dir', function() {
var childFramework = {src: 'plugin-lib2', parent: 'plugin-lib'};
android.framework.uninstall(childFramework, dummyPluginInfo, dummyProject);
expect(dummyProject.removeSystemLibrary).toHaveBeenCalledWith(path.resolve(dummyProject.projectDir, childFramework.parent), someString);
});
it('should remove framework sources if "custom" attribute is set', function() {
it('Test#026 : should remove framework sources if "custom" attribute is set', function() {
var framework = {src: 'plugin-lib', custom: true};
android.framework.uninstall(framework, dummyPluginInfo, dummyProject);
expect(dummyProject.removeSubProject).toHaveBeenCalledWith(dummyProject.projectDir, someString);
expect(removeFileSpy).toHaveBeenCalledWith(dummyProject.projectDir, someString);
});
it('should install gradleReference using project.removeGradleReference', function() {
it('Test#27 : should install gradleReference using project.removeGradleReference', function() {
var framework = {src: 'plugin-lib', custom: true, type: 'gradleReference'};
android.framework.uninstall(framework, dummyPluginInfo, dummyProject);
expect(removeFileSpy).toHaveBeenCalledWith(dummyProject.projectDir, someString);
@@ -333,19 +333,19 @@ describe('android project handler', function() {
spyOn(shell, 'rm');
var existsSyncOrig = fs.existsSync;
spyOn(fs, 'existsSync').andCallFake(function (file) {
spyOn(fs, 'existsSync').and.callFake(function (file) {
if ([wwwDest, platformWwwDest].indexOf(file) >= 0 ) return true;
return existsSyncOrig.call(fs, file);
});
});
it('should put module to both www and platform_www when options.usePlatformWww flag is specified', function () {
it('Test#028 : should put module to both www and platform_www when options.usePlatformWww flag is specified', function () {
android['js-module'].uninstall(jsModule, dummyPluginInfo, dummyProject, {usePlatformWww: true});
expect(shell.rm).toHaveBeenCalledWith('-Rf', wwwDest);
expect(shell.rm).toHaveBeenCalledWith('-Rf', platformWwwDest);
});
it('should put module to www only when options.usePlatformWww flag is not specified', function () {
it('Test#29 : should put module to www only when options.usePlatformWww flag is not specified', function () {
android['js-module'].uninstall(jsModule, dummyPluginInfo, dummyProject);
expect(shell.rm).toHaveBeenCalledWith('-Rf', wwwDest);
expect(shell.rm).not.toHaveBeenCalledWith('-Rf', platformWwwDest);
@@ -363,19 +363,19 @@ describe('android project handler', function() {
spyOn(shell, 'rm');
var existsSyncOrig = fs.existsSync;
spyOn(fs, 'existsSync').andCallFake(function (file) {
spyOn(fs, 'existsSync').and.callFake(function (file) {
if ([wwwDest, platformWwwDest].indexOf(file) >= 0 ) return true;
return existsSyncOrig.call(fs, file);
});
});
it('should put module to both www and platform_www when options.usePlatformWww flag is specified', function () {
it('Test#030 : should put module to both www and platform_www when options.usePlatformWww flag is specified', function () {
android.asset.uninstall(asset, dummyPluginInfo, dummyProject, {usePlatformWww: true});
expect(shell.rm).toHaveBeenCalledWith(jasmine.any(String), wwwDest);
expect(shell.rm).toHaveBeenCalledWith(jasmine.any(String), platformWwwDest);
});
it('should put module to www only when options.usePlatformWww flag is not specified', function () {
it('Test#31 : should put module to www only when options.usePlatformWww flag is not specified', function () {
android.asset.uninstall(asset, dummyPluginInfo, dummyProject);
expect(shell.rm).toHaveBeenCalledWith(jasmine.any(String), wwwDest);
expect(shell.rm).not.toHaveBeenCalledWith(jasmine.any(String), platformWwwDest);

View File

@@ -28,7 +28,7 @@ describe("run", function () {
var emulatorOpts = { emulator: true };
var emptyOpts = {};
it("should select correct target based on the run opts", function() {
it("Test#001 : should select correct target based on the run opts", function() {
expect(getInstallTarget(targetOpts)).toBe("emu");
expect(getInstallTarget(deviceOpts)).toBe("--device");
expect(getInstallTarget(emulatorOpts)).toBe("--emulator");

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

9
test/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>CordovaViewTestActivity</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -1,87 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="org.apache.cordova.test" android:versionName="1.0" android:versionCode="1">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="24"/>
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="org.apache.cordova.test" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name" >
<uses-library android:name="android.test.runner" />
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name="org.apache.cordova.test.CordovaWebViewTestActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name="org.apache.cordova.test.MainTestActivity" >
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name="org.apache.cordova.test.menus" >
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name="org.apache.cordova.test.userwebview" >
</activity>
</application>
</manifest>

View File

@@ -1,61 +0,0 @@
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
# Android Native Tests
These tests are designed to verify Android native features and other Android specific features.
## Initial Setup
### Setting env vars
Run:
../bin/check_reqs
Use the output to set your `ANDROID_HOME` and `JAVA_HOME` environment variables.
### Adding `gradlew`
Copy it from a freshly created project:
../bin/create foo
(cd foo && cordova/build --gradle; cp -r gradlew gradle ..)
rm -r foo
## Running
To run manual tests:
./gradlew installDebug
To run unit tests:
./gradlew connectedAndroidTest
`BUILD SUCCESSFUL` means that the tests all passed :)
## Android Studio
1. Use "Import Project" and import the `test` directory.
2. Right click on the `org.apache.cordova.test` package on the left-hand nav.
3. Select `Create Run Configuration` -> `Tests in ...` (The one with the Android icon)
4. Review options (mainly - target device)
5. Click the bug icon in the top toolbar to run with debugger attached

View File

@@ -1,194 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import android.view.KeyEvent;
import android.view.inputmethod.BaseInputConnection;
public class BackButtonMultiPageTest extends BaseCordovaIntegrationTest {
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
@Override
public void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(START_URL);
}
public void testViaHref() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.sendJavascript("window.location = 'sample2.html';");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.sendJavascript("window.location = 'sample3.html';"); }
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
assertTrue(cordovaWebView.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
assertTrue(cordovaWebView.backHistory());
}
});
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
assertFalse(cordovaWebView.backHistory());
}
});
}
public void testViaLoadUrl() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
assertTrue(cordovaWebView.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
assertTrue(cordovaWebView.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/index.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
assertFalse(cordovaWebView.backHistory());
}
});
}
public void testViaBackButtonOnView() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
cordovaWebView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
cordovaWebView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(cordovaWebView.getView(), true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("sample2.html"));
BaseInputConnection viewConnection = new BaseInputConnection(cordovaWebView.getView(), true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/index.html", testActivity.onPageFinishedUrl.take());
}
public void testViaBackButtonOnLayout() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
cordovaWebView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
cordovaWebView.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("sample3.html"));
BaseInputConnection viewConnection = new BaseInputConnection(containerView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("sample2.html"));
BaseInputConnection viewConnection = new BaseInputConnection(containerView, true);
KeyEvent backDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
KeyEvent backUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
viewConnection.sendKeyEvent(backDown);
viewConnection.sendKeyEvent(backUp);
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/index.html", testActivity.onPageFinishedUrl.take());
}
}

View File

@@ -1,52 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import android.content.Intent;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import org.apache.cordova.CordovaWebView;
public class BaseCordovaIntegrationTest extends ActivityInstrumentationTestCase2<MainTestActivity> {
protected MainTestActivity testActivity;
protected FrameLayout containerView;
protected CordovaWebView cordovaWebView;
public BaseCordovaIntegrationTest() {
super(MainTestActivity.class);
}
protected void setUpWithStartUrl(String url, String... prefsAndValues) {
Intent intent = new Intent(getInstrumentation().getContext(), MainTestActivity.class);
intent.putExtra("testStartUrl", url);
for (int i = 0; i < prefsAndValues.length; i += 2) {
intent.putExtra(prefsAndValues[i], prefsAndValues[i + 1]);
}
setActivityIntent(intent);
testActivity = getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
cordovaWebView = testActivity.getCordovaWebView();
}
}

View File

@@ -1,48 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.engine.SystemWebView;
public class CordovaActivityTest extends BaseCordovaIntegrationTest {
private ViewGroup innerContainer;
private View testView;
protected void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(null);
testView = (ViewGroup)containerView.getChildAt(0);
}
public void testBasicLoad() throws Exception {
assertTrue(testView instanceof SystemWebView);
assertTrue(((CordovaWebViewEngine.EngineView)testView).getCordovaWebView() != null);
String onPageFinishedUrl = testActivity.onPageFinishedUrl.take();
assertEquals(MainTestActivity.START_URL, onPageFinishedUrl);
}
protected void createViews() {
assertTrue(testView instanceof SystemWebView);
}
}

View File

@@ -1,68 +0,0 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.cordova.test;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import org.apache.cordova.CordovaWebView;
import java.io.IOException;
import java.lang.reflect.Method;
public class CordovaPluginTest extends BaseCordovaIntegrationTest {
protected void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(null);
}
private void invokeBlockingCallToLifeCycleEvent(final String lifeCycleEventName) {
testActivity.runOnUiThread( new Runnable() {
public void run() {
try {
Method method = getInstrumentation().getClass().getMethod(lifeCycleEventName, Activity.class);
method.invoke(getInstrumentation(), testActivity);
} catch (Exception e) {
fail("An Exception occurred in invokeBlockingCallToLifeCycleEvent while invoking " + lifeCycleEventName);
}
}
});
getInstrumentation().waitForIdleSync();
}
public void testPluginLifeCycle() throws IOException {
//TODO: add coverage for both cases where handleOnStart is called in CordovaActivity (onStart and init)
//currently only one of the cases is covered
//TODO: add coverage for both cases where onStart is called in CordovaWebViewImpl (handleOnStart and init)
//currently only one of the cases is covered
LifeCyclePlugin testPlugin = (LifeCyclePlugin)cordovaWebView.getPluginManager().getPlugin("LifeCycle");
testPlugin.calls = "";
// testOnStart
invokeBlockingCallToLifeCycleEvent("callActivityOnStart");
invokeBlockingCallToLifeCycleEvent("callActivityOnResume");
invokeBlockingCallToLifeCycleEvent("callActivityOnPause");
invokeBlockingCallToLifeCycleEvent("callActivityOnStop");
assertEquals("start,resume,pause,stop,", testPlugin.calls);
}
}

View File

@@ -1,280 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaResourceApi.OpenForReadResult;
import org.apache.cordova.PluginEntry;
import org.json.JSONArray;
import org.json.JSONException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class CordovaResourceApiTest extends BaseCordovaIntegrationTest {
CordovaResourceApi resourceApi;
String execPayload;
Integer execStatus;
protected void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(null);
resourceApi = cordovaWebView.getResourceApi();
resourceApi.setThreadCheckingEnabled(false);
cordovaWebView.getPluginManager().addService(new PluginEntry("CordovaResourceApiTestPlugin1", new CordovaPlugin() {
@Override
public Uri remapUri(Uri uri) {
if (uri.getQuery() != null && uri.getQuery().contains("pluginRewrite")) {
return cordovaWebView.getResourceApi().remapUri(
Uri.parse("data:text/plain;charset=utf-8,pass"));
}
if (uri.getQuery() != null && uri.getQuery().contains("pluginUri")) {
return toPluginUri(uri);
}
return null;
}
@Override
public OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
Uri orig = fromPluginUri(uri);
ByteArrayInputStream retStream = new ByteArrayInputStream(orig.toString().getBytes(StandardCharsets.UTF_8));
return new OpenForReadResult(uri, retStream, "text/plain", retStream.available(), null);
}
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
synchronized (CordovaResourceApiTest.this) {
execPayload = args.getString(0);
execStatus = args.getInt(1);
CordovaResourceApiTest.this.notify();
}
return true;
}
}));
}
private Uri createTestImageContentUri() {
Bitmap imageBitmap = BitmapFactory.decodeResource(testActivity.getResources(), R.drawable.icon);
String stored = MediaStore.Images.Media.insertImage(testActivity.getContentResolver(),
imageBitmap, "app-icon", "desc");
return Uri.parse(stored);
}
private void performApiTest(Uri uri, String expectedMimeType, File expectedLocalFile,
boolean expectRead, boolean expectWrite) throws IOException {
uri = resourceApi.remapUri(uri);
assertEquals(expectedLocalFile, resourceApi.mapUriToFile(uri));
try {
OpenForReadResult readResult = resourceApi.openForRead(uri);
String mimeType2 = resourceApi.getMimeType(uri);
assertEquals("openForRead mime-type", expectedMimeType, readResult.mimeType);
assertEquals("getMimeType mime-type", expectedMimeType, mimeType2);
readResult.inputStream.read();
if (!expectRead) {
fail("Expected getInputStream to throw.");
}
} catch (IOException e) {
if (expectRead) {
throw e;
}
}
try {
OutputStream outStream = resourceApi.openOutputStream(uri);
outStream.write(123);
if (!expectWrite) {
fail("Expected getOutputStream to throw.");
}
outStream.close();
} catch (IOException e) {
if (expectWrite) {
throw e;
}
}
}
public void testJavaApis() throws IOException {
// testValidContentUri
{
Uri contentUri = createTestImageContentUri();
File localFile = resourceApi.mapUriToFile(contentUri);
assertNotNull(localFile);
performApiTest(contentUri, "image/jpeg", localFile, true, true);
}
// testInvalidContentUri
{
Uri contentUri = Uri.parse("content://media/external/images/media/999999999");
performApiTest(contentUri, null, null, false, false);
}
// testValidAssetUri
{
Uri assetUri = Uri.parse("file:///android_asset/www/index.html?foo#bar"); // Also check for stripping off ? and # correctly.
performApiTest(assetUri, "text/html", null, true, false);
}
// testInvalidAssetUri
{
Uri assetUri = Uri.parse("file:///android_asset/www/missing.html");
performApiTest(assetUri, "text/html", null, false, false);
}
// testFileUriToExistingFile
{
File f = File.createTempFile("te s t", ".txt"); // Also check for dealing with spaces.
try {
Uri fileUri = Uri.parse(f.toURI().toString() + "?foo#bar"); // Also check for stripping off ? and # correctly.
performApiTest(fileUri, "text/plain", f, true, true);
} finally {
f.delete();
}
}
// testFileUriToMissingFile
{
File f = new File(Environment.getExternalStorageDirectory() + "/somefilethatdoesntexist");
Uri fileUri = Uri.parse(f.toURI().toString());
try {
performApiTest(fileUri, null, f, false, true);
} finally {
f.delete();
}
}
// testFileUriToMissingFileWithMissingParent
{
File f = new File(Environment.getExternalStorageDirectory() + "/somedirthatismissing" + System.currentTimeMillis() + "/somefilethatdoesntexist");
Uri fileUri = Uri.parse(f.toURI().toString());
performApiTest(fileUri, null, f, false, true);
}
// testUnrecognizedUri
{
Uri uri = Uri.parse("somescheme://foo");
performApiTest(uri, null, null, false, false);
}
// testRelativeUri
{
try {
resourceApi.openForRead(Uri.parse("/foo"));
fail("Should have thrown for relative URI 1.");
} catch (Throwable t) {
}
try {
resourceApi.openForRead(Uri.parse("//foo/bar"));
fail("Should have thrown for relative URI 2.");
} catch (Throwable t) {
}
try {
resourceApi.openForRead(Uri.parse("foo.png"));
fail("Should have thrown for relative URI 3.");
} catch (Throwable t) {
}
}
// testPluginOverride
{
Uri uri = Uri.parse("plugin-uri://foohost/android_asset/www/index.html?pluginRewrite=yes");
performApiTest(uri, "text/plain", null, true, false);
}
// testMainThreadUsage
{
Uri assetUri = Uri.parse("file:///android_asset/www/index.html");
resourceApi.setThreadCheckingEnabled(true);
try {
resourceApi.openForRead(assetUri);
fail("Should have thrown for main thread check.");
} catch (Throwable t) {
}
}
// testDataUriPlain
{
Uri uri = Uri.parse("data:text/plain;charset=utf-8,pa%20ss");
OpenForReadResult readResult = resourceApi.openForRead(uri);
assertEquals("text/plain", readResult.mimeType);
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals("pa ss", data);
}
// testDataUriBase64
{
Uri uri = Uri.parse("data:text/js;charset=utf-8;base64,cGFzcw==");
OpenForReadResult readResult = resourceApi.openForRead(uri);
assertEquals("text/js", readResult.mimeType);
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals("pass", data);
}
// testPluginUris
{
String origUri = "http://orig/foo?pluginUri";
Uri uri = resourceApi.remapUri(Uri.parse(origUri));
OpenForReadResult readResult = resourceApi.openForRead(uri);
assertEquals("openForRead mime-type", "text/plain", readResult.mimeType);
String data = new Scanner(readResult.inputStream, "UTF-8").useDelimiter("\\A").next();
assertEquals(origUri, data);
assertEquals(origUri.length(), readResult.length);
}
}
public void testWebViewRequestIntercept() throws Throwable
{
testActivity.onPageFinishedUrl.take();
execPayload = null;
execStatus = null;
cordovaWebView.sendJavascript(
"var x = new XMLHttpRequest;\n" +
"x.open('GET', 'file:///foo?pluginRewrite=1', false);\n" +
"x.send();\n" +
"cordova.require('cordova/exec')(null,null,'CordovaResourceApiTestPlugin1', 'foo', [x.responseText, x.status])");
try {
synchronized (this) {
this.wait(2000);
}
} catch (InterruptedException e) {
}
assertEquals("pass", execPayload);
assertEquals(execStatus.intValue(), 200);
}
public void testWebViewWhiteListRejection() throws Throwable
{
testActivity.onPageFinishedUrl.take();
execPayload = null;
execStatus = null;
cordovaWebView.sendJavascript(
"var x = new XMLHttpRequest;\n" +
"x.open('GET', 'http://foo/bar', false);\n" +
"x.send();\n" +
"cordova.require('cordova/exec')(null,null,'CordovaResourceApiTestPlugin1', 'foo', [x.responseText, x.status])");
try {
synchronized (this) {
this.wait(2000);
}
} catch (InterruptedException e) {
}
assertEquals("", execPayload);
assertEquals(execStatus.intValue(), 404);
}
}

View File

@@ -1,44 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
public class ErrorUrlTest extends BaseCordovaIntegrationTest {
private static final String START_URL = "file:///android_asset/www/htmlnotfound/index.html";
private static final String ERROR_URL = "file:///android_asset/www/htmlnotfound/error.html";
private static final String INVALID_URL = "file:///android_asset/www/invalid.html";
protected void setUp() throws Exception {
super.setUp();
// INVALID_URL tests that errorUrl and url are *not* settable via the intent.
setUpWithStartUrl(START_URL, "testErrorUrl", ERROR_URL, "errorurl", INVALID_URL, "url", INVALID_URL);
}
public void testUrl() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
assertEquals(ERROR_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run() {
assertEquals(ERROR_URL, testActivity.getCordovaWebView().getUrl());
}
});
}
}

View File

@@ -1,46 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
public class HtmlNotFoundTest extends BaseCordovaIntegrationTest {
private static final String START_URL = "file:///android_asset/www/htmlnotfound/index.html";
protected void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(START_URL);
}
public void testUrl() throws Throwable
{
runTestOnUiThread(new Runnable() {
public void run() {
assertTrue(START_URL.equals(testActivity.getCordovaWebView().getUrl()));
}
});
//loading a not-found file causes an application error and displayError is called
//the test activity overrides displayError to add message to onPageFinishedUrl
String message = testActivity.onPageFinishedUrl.take();
assertTrue(message.contains(START_URL));
assertTrue(message.contains("ERR_FILE_NOT_FOUND"));
}
}

View File

@@ -1,107 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import android.test.TouchUtils;
import org.apache.cordova.test.util.Purity;
public class IFrameTest extends BaseCordovaIntegrationTest {
private static final String START_URL = "file:///android_asset/www/iframe/index.html";
private TouchUtils touch;
private Purity touchTool;
protected void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(START_URL);
touch = new TouchUtils();
touchTool = new Purity(testActivity, getInstrumentation());
}
public void testIframeDest() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.sendJavascript("loadUrl('http://maps.google.com/maps?output=embed');");
}
});
sleep(3000);
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.sendJavascript("loadUrl('index2.html')");
}
});
sleep(1000);
runTestOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
}
});
}
public void testIframeHistory() throws Throwable
{
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.sendJavascript("loadUrl('http://maps.google.com/maps?output=embed');");
}
});
sleep(3000);
runTestOnUiThread(new Runnable() {
public void run()
{
cordovaWebView.sendJavascript("loadUrl('index2.html')");
}
});
sleep(1000);
runTestOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
cordovaWebView.backHistory();
}
});
sleep(1000);
runTestOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
}
});
}
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@@ -1,56 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import org.apache.cordova.engine.SystemWebView;
public class InflateLayoutTest extends ActivityInstrumentationTestCase2<CordovaWebViewTestActivity> {
private CordovaWebViewTestActivity testActivity;
private ViewGroup innerContainer;
private View testView;
@SuppressWarnings("deprecation")
public InflateLayoutTest()
{
super("org.apache.cordova.test",CordovaWebViewTestActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
FrameLayout containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (ViewGroup)containerView.getChildAt(0);
testView = innerContainer.getChildAt(0);
}
public void testBasicLoad() throws Exception {
assertTrue(testView instanceof SystemWebView);
assertTrue(innerContainer instanceof LinearLayout);
String onPageFinishedUrl = testActivity.onPageFinishedUrl.take();
assertEquals(CordovaWebViewTestActivity.START_URL, onPageFinishedUrl);
}
}

View File

@@ -1,44 +0,0 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import android.graphics.Color;
import org.apache.cordova.CordovaPreferences;
public class IntentPreferenceTest extends BaseCordovaIntegrationTest {
private static final String GREEN = Integer.toHexString(Color.GREEN);
private static final String START_URL = "file:///android_asset/www/index.html";
CordovaPreferences prefs;
protected void setUp() throws Exception {
super.setUp();
// INVALID_URL tests that errorUrl and url are *not* settable via the intent.
setUpWithStartUrl(START_URL, "backgroundcolor", GREEN);
prefs = cordovaWebView.getPreferences();
}
public void testUrl() throws Throwable {
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
assertFalse(prefs.getInteger("backgroundcolor", Color.BLACK) == Color.GREEN);
}
}

View File

@@ -1,171 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/*
* Purity is a small set of Android utility methods that allows us to simulate touch events on
* Android applications. This is important for simulating some of the most annoying tests.
*/
package org.apache.cordova.test.util;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Picture;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.webkit.WebView;
public class Purity {
Instrumentation inst;
int width, height;
float density;
Bitmap state;
boolean fingerDown = false;
public Purity(Context ctx, Instrumentation i)
{
inst = i;
DisplayMetrics display = ctx.getResources().getDisplayMetrics();
density = display.density;
width = display.widthPixels;
height = display.heightPixels;
}
/*
* WebKit doesn't give you real pixels anymore, this is done for subpixel fonts to appear on
* iOS and Android. However, Android automation requires real pixels
*/
private int getRealCoord(int coord)
{
return (int) (coord * density);
}
public int getViewportWidth()
{
return (int) (width/density);
}
public int getViewportHeight()
{
return (int) (height/density);
}
public void touch(int x, int y)
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
if(!fingerDown)
{
MotionEvent downEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(downEvent);
}
MotionEvent upEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, realX, realY, 0);
inst.sendPointerSync(upEvent);
}
public void touchStart(int x, int y)
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(event);
fingerDown = true;
}
//Move from the touch start
public void touchMove(int x, int y)
{
if(!fingerDown)
touchStart(x,y);
else
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, realX, realY, 0);
inst.sendPointerSync(event);
}
}
public void touchEnd(int x, int y)
{
if(!fingerDown)
{
touch(x, y);
}
else
{
int realX = getRealCoord(x);
int realY = getRealCoord(y);
long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, realX, realY, 0);
inst.sendPointerSync(event);
fingerDown = false;
}
}
public void setBitmap(WebView view)
{
Picture p = view.capturePicture();
state = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Bitmap.Config.ARGB_8888);
}
public boolean checkRenderView(WebView view)
{
if(state == null)
{
setBitmap(view);
return false;
}
else
{
Picture p = view.capturePicture();
Bitmap newState = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Bitmap.Config.ARGB_8888);
boolean result = newState.equals(state);
newState.recycle();
return result;
}
}
public void clearBitmap()
{
if(state != null)
state.recycle();
}
protected void finalize()
{
clearBitmap();
}
}

1
test/app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

35
test/app/build.gradle Normal file
View File

@@ -0,0 +1,35 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "org.apache.cordova.unittests"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
debugCompile project(path: ":CordovaLib", configuration: "debug")
releaseCompile project(path: ":CordovaLib", configuration: "release")
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
androidTestCompile ('com.android.support.test.espresso:espresso-web:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.1.1'
testCompile 'junit:junit:4.12'
testCompile 'org.json:json:20140107'
}

17
test/app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/jbowser/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -0,0 +1,158 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.unittests;
import android.content.Intent;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.apache.cordova.CordovaWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.pressBack;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.web.sugar.Web.onWebView;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.apache.cordova.unittests.R.id.cordovaWebView;
@RunWith(AndroidJUnit4.class)
public class BackButtonMultipageTest {
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private TestActivity mActivity;
// Don't launch the activity, we're going to send it intents
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class, true, false);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
mActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
@Test
public void testViaHref() throws Throwable {
final CordovaWebView webInterface = mActivity.getWebInterface();
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.sendJavascript("window.location = 'sample2.html';");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.sendJavascript("window.location = 'sample3.html';");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertFalse(webInterface.backHistory());
}
});
}
@Test
public void testViaLoadUrl() throws Throwable {
final CordovaWebView webInterface = mActivity.getWebInterface();
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertFalse(webInterface.backHistory());
}
});
}
@Test
public void testViaBackButtonOnView() throws Throwable {
final CordovaWebView webInterface = mActivity.getWebInterface();
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", mActivity.onPageFinishedUrl.take());
onView(withId(WEBVIEW_ID)).perform(pressBack());
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
onView(withId(WEBVIEW_ID)).perform(pressBack());
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
}
}

View File

@@ -0,0 +1,53 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.unittests;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertNotNull;
/*
* This test is to cover the use case of Cordova Android used as a component in a larger Android
* application. This test is strictly used to cover this use case. In this example, the WebView
* should load, not be null, and the Plugin Manager should also be initialized.
*
*/
@RunWith(AndroidJUnit4.class)
public class EmbeddedWebViewTest {
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
EmbeddedWebViewActivity.class);
@Test
public void checkWebViewTest() {
EmbeddedWebViewActivity activity = (EmbeddedWebViewActivity) mActivityRule.getActivity();
assertNotNull(activity.webInterface);
assertNotNull(activity.webInterface.getPluginManager());
}
}

View File

@@ -0,0 +1,68 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.unittests;
import android.content.Intent;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.apache.cordova.CordovaWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
@RunWith(AndroidJUnit4.class)
public class ErrorUrlTest {
private static final String START_URL = "file:///android_asset/www/htmlnotfound/index.html";
private static final String ERROR_URL = "file:///android_asset/www/htmlnotfound/error.html";
private static final String INVALID_URL = "file:///android_asset/www/invalid.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private TestActivity mActivity;
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
intent.putExtra("errorurl", INVALID_URL);
intent.putExtra("url", INVALID_URL);
mActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
@Test
public void errorUrlTest() throws Throwable {
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
assertEquals(ERROR_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertEquals(ERROR_URL, mActivity.getWebInterface().getUrl());
}
});
}
}

View File

@@ -0,0 +1,114 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.unittests;
import android.content.Intent;
import android.support.test.espresso.web.webdriver.Locator;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.apache.cordova.CordovaWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.pressBack;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.web.sugar.Web.onWebView;
import static android.support.test.espresso.web.webdriver.DriverAtoms.findElement;
import static android.support.test.espresso.web.webdriver.DriverAtoms.webClick;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class IFrameTest {
private static final String START_URL = "file:///android_asset/www/iframe/index.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private int WEBVIEW_LOAD_DELAY = 500;
private TestActivity testActivity;
// Don't launch the activity, we're going to send it intents
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class, true, false);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
testActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
@Test
public void iFrameHistory() throws Throwable {
final CordovaWebView cordovaWebView = (CordovaWebView) testActivity.getWebInterface();
onWebView().withElement(findElement(Locator.ID, "google_maps")).perform(webClick());
sleep(WEBVIEW_LOAD_DELAY);
mActivityRule.runOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
}
});
sleep(WEBVIEW_LOAD_DELAY);
onWebView().withElement(findElement(Locator.ID, "javascript_load")).perform(webClick());
mActivityRule.runOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
}
});
sleep(WEBVIEW_LOAD_DELAY);
//Espresso will kill the application and not trigger the backHistory method, which correctly
//navigates the iFrame history. backHistory is tied to the back button.
mActivityRule.runOnUiThread(new Runnable() {
public void run()
{
assertTrue(cordovaWebView.backHistory());
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
assertFalse(cordovaWebView.backHistory());
}
});
}
//BRUTE FORCE THE CRAP OUT OF CONCURRENCY ERRORS
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@@ -1,45 +1,45 @@
package org.apache.cordova.test;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.cordova.unittests;
import android.view.KeyEvent;
import android.view.inputmethod.BaseInputConnection;
import android.content.Intent;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.PluginManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MessageChannelMultiPageTest extends BaseCordovaIntegrationTest {
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.fail;
@Override
public void setUp() throws Exception {
super.setUp();
setUpWithStartUrl(START_URL);
@RunWith(AndroidJUnit4.class)
public class MessageChannelMultipageTest {
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private TestActivity testActivity;
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
testActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
//test that after a page load the cached callback id and the live callback id match
//this is to prevent a regression
//the issue was that CordovaWebViewImpl's cached instance of CoreAndroid would become stale on page load
@@ -47,7 +47,9 @@ public class MessageChannelMultiPageTest extends BaseCordovaIntegrationTest {
//the plugin manager would get a new instance which would be updated with a new callback id
//the cached instance's message channel callback id would become stale
//effectively this caused message channel events to not be delivered
@Test
public void testThatCachedCallbackIdIsValid() throws Throwable {
final CordovaWebView cordovaWebView = testActivity.getWebInterface();
Class cordovaWebViewImpl = CordovaWebViewImpl.class;
//send a test event - this initializes cordovaWebViewImpl.appPlugin (the cached instance of CoreAndroid)
Method method = cordovaWebViewImpl.getDeclaredMethod("sendJavascriptEvent", String.class);
@@ -57,7 +59,7 @@ public class MessageChannelMultiPageTest extends BaseCordovaIntegrationTest {
//load a page - this resets the plugin manager and nulls cordovaWebViewImpl.appPlugin
//(previously this resets plugin manager but did not null cordovaWebViewImpl.appPlugin, leading to the issue)
runTestOnUiThread(new Runnable() {
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
cordovaWebView.loadUrl(START_URL);
}
@@ -81,7 +83,7 @@ public class MessageChannelMultiPageTest extends BaseCordovaIntegrationTest {
CallbackContext cachedCallbackContext = (CallbackContext) messageChannelField.get(cachedAppPlugin);
//get live CoreAndroid
PluginManager pluginManager = MessageChannelMultiPageTest.this.cordovaWebView.getPluginManager();
PluginManager pluginManager = cordovaWebView.getPluginManager();
Field coreAndroidPluginNameField = coreAndroid.getField("PLUGIN_NAME");
String coreAndroidPluginName = (String) coreAndroidPluginNameField.get(null);
Object liveAppPlugin = pluginManager.getPlugin(coreAndroidPluginName);
@@ -106,5 +108,4 @@ public class MessageChannelMultiPageTest extends BaseCordovaIntegrationTest {
fail("Unexpected Timeout");
}
}
}

View File

@@ -0,0 +1,100 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.unittests;
import android.content.Intent;
import android.graphics.Color;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.widget.LinearLayout;
import org.apache.cordova.CordovaPreferences;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.engine.SystemWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertTrue;
/**
* The purpose of this test is to test the default application that is generated by Cordova itself
*
*/
@RunWith(AndroidJUnit4.class)
public class StandardActivityTest {
private static final String FALSE_URI = "http://www.google.com";
// Don't launch the activity, we're going to send it intents
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
StandardActivity.class, true, false);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", FALSE_URI);
intent.putExtra("backgroundcolor", "#0000ff");
mActivityRule.launchActivity(intent);
}
@Test
public void webViewCheck() {
StandardActivity activity = (StandardActivity) mActivityRule.getActivity();
//Fish the webview out of the mostly locked down Activity using the Android SDK
View view = activity.getWindow().getCurrentFocus();
assertEquals(SystemWebView.class, view.getClass());
}
@Test
public void startUriIntentCheck() {
StandardActivity activity = (StandardActivity) mActivityRule.getActivity();
final SystemWebView webView = (SystemWebView) activity.getWindow().getCurrentFocus();
try {
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
String uri = webView.getUrl();
assertFalse(uri.equals(FALSE_URI));
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
@Test
public void checkBackgroundIntentCheck() {
StandardActivity activity = (StandardActivity) mActivityRule.getActivity();
final SystemWebView webView = (SystemWebView) activity.getWindow().getCurrentFocus();
CordovaWebView webInterface = webView.getCordovaWebView();
CordovaPreferences prefs = webInterface.getPreferences();
assertFalse(prefs.getInteger("backgroundcolor", Color.BLACK) == Color.GREEN);
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.apache.cordova.unittests">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".EmbeddedWebViewActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".StandardActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TestActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

2208
test/app/src/main/assets/www/cordova.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@
(NOTE: THIS BEHAVIOR IS WRONG - AND NEEDS TO BE FIXED IN FUTURE RELEASE.)
</div>
<iframe id="iframe" src="" width="90%" height="200px"></iframe>
<a href="javascript:" class="btn large" onclick="loadUrl('http://maps.google.com/maps?output=embed');">Google Maps</a>
<a href="javascript:" class="btn large" onclick="loadUrl('index2.html');">Page 2</a>
<a id="google_maps" href="javascript:" class="btn large" onclick="loadUrl('http://maps.google.com/maps?output=embed');">Google Maps</a>
<a id="javascript_load" href="javascript:" class="btn large" onclick="loadUrl('index2.html');">Page 2</a>
</body>
</html>

View File

@@ -44,20 +44,13 @@
<div id="info">
<h4>Run each of the test activities below:</h4>
</div>
<button class="btn large" onclick="startActivity('jqmtabbackbutton/index.html');">Backbutton jQM tab</button>
<button class="btn large" onclick="startActivity('backbuttonmultipage/index.html');">Backbutton with multiple pages</button>
<button class="btn large" onclick="startActivity('backgroundcolor/index.html', {backgroundcolor: -16711936});">Background Color</button>
<button class="btn large" onclick="startActivity('basicauth/index.html');">Basic Authentication</button>
<button class="btn large" onclick="startActivity('errorurl/index.html', {testErrorUrl: 'file:///android_asset/www/htmlnotfound/error.html'});">Error URL</button>
<button class="btn large" onclick="startActivity('fullscreen/index.html', {fullscreen: true});">Full Screen</button>
<button class="btn large" onclick="startActivity('htmlnotfound/index.html');">HTML not found</button>
<button class="btn large" onclick="startActivity('iframe/index.html');">IFrame</button>
<button class="btn large" onclick="startActivity('lifecycle/index.html');">Lifecycle</button>
<button class="btn large" onclick="startActivity('menus/index.html', null, 'org.apache.cordova.test.menus');">Menus</button>
<button class="btn large" onclick="startActivity('background/index.html', {keeprunning: false});">No multitasking</button>
<button class="btn large" onclick="startActivity('http://www.google.com', {loadurltimeoutvalue: 10});">Load timeout</button>
<button class="btn large" onclick="startActivity('userwebview/index.html', null, 'org.apache.cordova.test.userwebview');">User WebView/Client/Chrome</button>
<button class="btn large" onclick="startActivity('whitelist/index.html');">Whitelist</button>
<button class="btn large" onclick="startActivity('xhr/index.html');">XHR</button>
</body>
</html>

View File

@@ -0,0 +1,110 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.unittests;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaInterfaceImpl;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.PluginManager;
import org.apache.cordova.engine.SystemWebView;
import org.apache.cordova.engine.SystemWebViewEngine;
import org.json.JSONException;
public class EmbeddedWebViewActivity extends AppCompatActivity {
public CordovaWebView webInterface;
private CordovaInterfaceImpl cordovaInterface = new CordovaInterfaceImpl(this);
private String TAG = "CordovaTestActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set up the webview
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(this);
SystemWebView webView = (SystemWebView) findViewById(R.id.cordovaWebView);
webInterface = new CordovaWebViewImpl(new SystemWebViewEngine(webView));
webInterface.init(cordovaInterface, parser.getPluginEntries(), parser.getPreferences());
webView.loadUrl(parser.getLaunchUrl());
}
// This is still required by Cordova
@Override
public void onDestroy()
{
super.onDestroy();
PluginManager pluginManager = webInterface.getPluginManager();
if(pluginManager != null)
{
pluginManager.onDestroy();
}
}
/**
* Called when an activity you launched exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
*
* @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
cordovaInterface.onActivityResult(requestCode, resultCode, intent);
}
/**
* Called by the system when the user grants permissions!
*
* Note: The fragment gets priority over the activity, since the activity doesn't call
* into the parent onRequestPermissionResult, which is why there's no override.
*
* @param requestCode
* @param permissions
* @param grantResults
*/
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
try
{
cordovaInterface.onRequestPermissionResult(requestCode, permissions, grantResults);
}
catch (JSONException e)
{
Log.d(TAG, "JSONException: Parameters fed into the method are not valid");
e.printStackTrace();
}
}
}

View File

@@ -16,7 +16,7 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
package org.apache.cordova.unittests;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.LOG;

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
@@ -16,16 +15,28 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<org.apache.cordova.engine.SystemWebView
android:id="@+id/cordovaWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
*/
package org.apache.cordova.unittests;
</LinearLayout>
import android.os.Bundle;
import org.apache.cordova.CordovaActivity;
public class StandardActivity extends CordovaActivity {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// enable Cordova apps to be started in the background
Bundle extras = getIntent().getExtras();
if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
moveTaskToBack(true);
}
// Set by <content src="index.html" /> in config.xml
loadUrl(launchUrl);
}
}

View File

@@ -16,23 +16,42 @@
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import android.content.Intent;
package org.apache.cordova.unittests;
import android.os.Bundle;
import org.apache.cordova.CordovaActivity;
import org.apache.cordova.CordovaWebView;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RunnableFuture;
/**
* The purpose of this activity is to allow the test framework to manipulate the start url, which
* is normally locked down by CordovaActivity to standard users who aren't editing their Java code.
*/
public class TestActivity extends CordovaActivity {
public class BaseTestCordovaActivity extends CordovaActivity {
public final ArrayBlockingQueue<String> onPageFinishedUrl = new ArrayBlockingQueue<String>(500);
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// enable Cordova apps to be started in the background
Bundle extras = getIntent().getExtras();
if (extras != null) {
if (extras.getBoolean("cdvStartInBackground", false)) {
moveTaskToBack(true);
}
launchUrl = extras.getString("startUrl", "index.html");
}
// Set by <content src="index.html" /> in config.xml
loadUrl(launchUrl);
}
@Override
@@ -43,14 +62,6 @@ public class BaseTestCordovaActivity extends CordovaActivity {
return super.onMessage(id, data);
}
public CordovaWebView getCordovaWebView() {
return appView;
}
// By default, displayError shows a dialog, but for tests we just add the message to the queue
@Override
public void displayError(String title, String message, String button, boolean exit) {
onPageFinishedUrl.add(message);
}
public CordovaWebView getWebInterface() { return this.appView; }
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="org.apache.cordova.unittests.EmbeddedWebViewActivity">
<org.apache.cordova.engine.SystemWebView
android:id="@+id/cordovaWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">UnitTests</string>
</resources>

View File

@@ -0,0 +1,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@@ -31,16 +31,14 @@
<access origin="https://*.googleapis.com/*" />
<access origin="https://*.gstatic.com/*" />
<content src="index.html" />
<preference name="errorUrl" value="file:///android_asset/www/htmlnotfound/error.html" />
<preference name="loglevel" value="DEBUG" />
<preference name="useBrowserHistory" value="true" />
<preference name="exit-on-suspend" value="false" />
<preference name="showTitle" value="true" />
<preference name="BackgroundColor" value="#000000" />
<feature name="Activity">
<param name="android-package" value="org.apache.cordova.test.ActivityPlugin" />
</feature>
<feature name="LifeCycle">
<param name="android-package" value="org.apache.cordova.test.LifeCyclePlugin" />
<param name="android-package" value="org.apache.cordova.unittests.LifeCyclePlugin" />
<param name="onload" value="true" />
</feature>
</widget>

View File

@@ -0,0 +1,126 @@
package org.apache.cordova.unittests;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.webkit.ValueCallback;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.ICordovaCookieManager;
import org.apache.cordova.NativeToJsMessageQueue;
import org.apache.cordova.PluginManager;
import org.apache.cordova.PluginResult;
import org.apache.cordova.engine.SystemWebViewEngine;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.ExecutorService;
import static org.junit.Assert.*;
public class NativeToJsMessageQueueTest {
NativeToJsMessageQueue queue = new NativeToJsMessageQueue();
private String TEST_CALLBACK_ID = "MessageQueueTest";
//A queue with no bridges should not work
@Test
public void testEmptyBridge()
{
assertFalse(queue.isBridgeEnabled());
}
//A queue with at least one bridge should work, using Eval Bridge
@Test
public void testEnabledBridge()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
assertTrue(queue.isBridgeEnabled());
}
//This test is for the undocumented encoding system setup for the bridge
//TODO: Document how the non-Javascript bridges are supposed to work
@Test
public void testPopAndEncode()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncode(false);
String [] results = resultString.split(" ");
assertEquals(TEST_CALLBACK_ID, results[2]);
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testBasicPopAndEncodeAsJs()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertTrue(resultString.startsWith("cordova.callbackFromNative"));
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testStringPopAndEncodeAsJs()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK, "String Plugin Result");
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertTrue(resultString.startsWith("cordova.callbackFromNative"));
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testJsonPopAndEncodeAsJs()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
JSONObject object = new JSONObject();
try {
object.put("test", "value");
} catch (JSONException e) {
e.printStackTrace();
}
PluginResult result = new PluginResult(PluginResult.Status.OK, object);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertTrue(resultString.startsWith("cordova.callbackFromNative"));
}
}

View File

@@ -1,103 +0,0 @@
<!DOCTYPE HTML>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Background Page 1</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function onLoad() {
console.log("Page1: onload");
log("Page1: onload @ " + new Date().toLocaleTimeString());
document.addEventListener("deviceready", onDeviceReady, false);
}
function onUnLoaded() {
console.log("Page1: onunload");
log("Page1: onunload @ " + new Date().toLocaleTimeString());
}
function onDeviceReady() {
// Register the event listener
document.getElementById("deviceready").innerHTML = "fired";
document.getElementById("cordova").innerHTML = cordova.version;
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
window.setInterval(function() {
log("Page1: Running");
}, 2000);
}
function onPause() {
console.log("Page1: onpause");
log("Page1: onpause @ " + new Date().toLocaleTimeString());
}
function onResume() {
console.log("Page1: onresume");
log("Page1: onresume @ " + new Date().toLocaleTimeString());
}
function log(s) {
var el = document.getElementById('status');
var status = el.innerHTML + s + "<br>";
el.innerHTML = status;
localStorage.backgroundstatus = status;
}
function clearStatus() {
console.log("clear()");
localStorage.backgroundstatus = "";
document.getElementById('status').innerHTML = "";
}
</script>
</head>
<body onload="onLoad()" onunload="onUnLoaded()" id="stage" class="theme">
<h1>Events</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
Press "Home" button, then return to this app to see pause/resume.<br>
There shouldn't be any "Running" entries between pause and resume.<br>
</div>
<div id="info">
<h4>Info for event testing:</h4>
<div id="status"></div>
</div>
<!-- a href="index2.html" class="btn large" >Load new page</a -->
<a href="javascript:" class="btn large" onclick="clearStatus();">Clear status</a>
<script>
document.getElementById('status').innerHTML = localStorage.backgroundstatus;
</script>
</body>
</html>

View File

@@ -1,102 +0,0 @@
<!DOCTYPE HTML>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Background Page 2</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function onLoad() {
console.log("Page2: onload");
log("Page2: onload @ " + new Date().toLocaleTimeString());
document.addEventListener("deviceready", onDeviceReady, false);
}
function onUnLoaded() {
console.log("Page2: onunload");
log("Page2: onunload @ " + new Date().toLocaleTimeString());
}
function onDeviceReady() {
// Register the event listener
document.getElementById("deviceready").innerHTML = "fired";
document.getElementById("cordova").innerHTML = cordova.version;
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
window.setInterval(function() {
log("Page2: Running");
}, 2000);
}
function onPause() {
console.log("Page2: onpause");
log("Page2: onpause @ " + new Date().toLocaleTimeString());
}
function onResume() {
console.log("Page2: onresume");
log("Page2: onresume @ " + new Date().toLocaleTimeString());
}
function log(s) {
var el = document.getElementById('status');
var status = el.innerHTML + s + "<br>";
el.innerHTML = status;
localStorage.backgroundstatus = status;
}
function clearStatus() {
console.log("clear()");
localStorage.backgroundstatus = "";
document.getElementById('status').innerHTML = "";
}
</script>
</head>
<body onload="onLoad()" onunload="onUnLoaded()" id="stage" class="theme">
<h1>Events</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
<h4>Press "Back" button to return to Page 1.</h4>
</div>
<div id="info">
<h4>Info for event testing:</h4>
<div id="status"></div>
</div>
<a href="index.html" class="btn large" >Load new page</a>
<a href="javascript:" class="btn large" onclick="clearStatus();">Clear status</a>
<script>
document.getElementById('status').innerHTML = localStorage.backgroundstatus;
</script>
</body>
</html>

View File

@@ -1,40 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Basic Auth</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
Loading link below should be successful and show page indicating username=test & password=test. <br>
</div>
<a href="http://browserspy.dk/password-ok.php" class="btn large">Test password</a>
</body>
</html>

View File

@@ -1,67 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Backbutton</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
<script type="text/javascript" src="../cordova.js"></script>
<script>
document.addEventListener("deviceready", onDeviceReady, false);
// Without backbutton handler, each tab loaded will be popped off history until history is empty, then it will exit app.
function handleBackButton() {
alert("Back Button Pressed! - exiting app");
navigator.app.exitApp();
}
function onDeviceReady() {
console.log("onDeviceReady()");
document.addEventListener("backbutton", handleBackButton, false);
}
</script>
</head>
<body>
<div data-role="page" id="tabTab">
<div data-role="header">
<h1>Main</h1>
</div>
<div data-role="content" id="tabContent">
To test, press several tabs.<br>
The "backbutton" can be pressed any time to exit app.
</div>
<div data-role="footer" data-position="fixed">
<div data-role="navbar">
<ul>
<li><a href="tab1.html" data-transition="none">Tab 1</a>
</li>
<li><a href="tab2.html" data-transition="none">Tab 2</a>
</li>
<li><a href="tab3.html" data-transition="none">Tab 3</a>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -1,47 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Tab 1</title>
</head>
<body>
<div data-role="page" id="tab1Tab">
<div data-role="header">
<h1>Tab 1</h1>
</div>
<div data-role="content" id="tab1Content">
Tab 1 content.
</div>
<div data-role="footer" data-position="fixed">
<div data-role="navbar">
<ul>
<li><a href="tab1.html" data-transition="none">Tab 1</a>
</li>
<li><a href="tab2.html" data-transition="none">Tab 2</a>
</li>
<li><a href="tab3.html" data-transition="none">Tab 3</a>
</li>
</ul>
</div>
<!-- /navbar -->
</div>
<!-- /footer -->
</div>

View File

@@ -1,48 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Tab 2</title>
</head>
<body>
<div data-role="page" id="tab2Tab">
<div data-role="header">
<h1>Tab 2</h1>
</div>
<div data-role="content" id="tab2Content">
Tab 2 content.
</div>
<div data-role="footer" data-position="fixed">
<div data-role="navbar">
<ul>
<li><a href="tab1.html" data-transition="none">Tab 1</a>
</li>
<li><a href="tab2.html" data-transition="none">Tab 2</a>
</li>
<li><a href="tab3.html" data-transition="none">Tab 3</a>
</li>
</ul>
</div>
<!-- /navbar -->
</div>
<!-- /footer -->
</div>

Some files were not shown because too many files have changed in this diff Show More