blob: 2924d3da42ff046554489d50a84bd7d676fc22dd [file] [log] [blame]
/*
*
* 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.
*
*/
/* global CompassError, CompassHeading */
exports.defineAutoTests = function () {
var fail = function (done, message) {
message = typeof message !== 'string' ? 'Forced failure: wrong callback called' : message;
expect(true).toFailWithMessage(message);
done();
};
var unexpectedFailure = 'Forced failure: error callback should not have been called';
describe('Compass (navigator.compass)', function () {
beforeEach(function () {
jasmine.Expectation.addMatchers({
toFailWithMessage: function () {
return {
compare: function (actual, customMessage) {
var pass = false;
if (customMessage === undefined) {
customMessage = 'Forced failure: wrong callback called';
}
return {
pass: pass,
message: customMessage
};
}
};
}
});
});
var isCompassAvailable = null;
beforeEach(function (done) {
if (isCompassAvailable === false) {
// if we're already ensured that compass is not available, no need to check it again
done();
} else if (isCompassAvailable === null) {
// Try to access compass device, and if it is not available
// set hardwarefailure flag to mark some tests pending
navigator.compass.getCurrentHeading(
function () {
isCompassAvailable = true;
done();
},
function (error) {
if (error.code === CompassError.COMPASS_NOT_SUPPORTED) {
isCompassAvailable = false;
}
done();
}
);
} else {
// wait a little
setTimeout(function () {
done();
}, 200);
}
});
it('compass.spec.1 should exist', function () {
expect(navigator.compass).toBeDefined();
});
it('compass.spec.2 should contain a getCurrentHeading function', function () {
expect(navigator.compass.getCurrentHeading).toBeDefined();
expect(typeof navigator.compass.getCurrentHeading === 'function').toBe(true);
});
it('compass.spec.3 getCurrentHeading success callback should be called with a Heading object', function (done) {
if (!isCompassAvailable) {
pending();
}
navigator.compass.getCurrentHeading(function (a) {
expect(a instanceof CompassHeading).toBe(true);
expect(a.magneticHeading).toBeDefined();
expect(typeof a.magneticHeading === 'number').toBe(true);
expect(a.trueHeading).not.toBe(undefined);
expect(typeof a.trueHeading === 'number' || a.trueHeading === null).toBe(true);
expect(a.headingAccuracy).not.toBe(undefined);
expect(typeof a.headingAccuracy === 'number' || a.headingAccuracy === null).toBe(true);
expect(typeof a.timestamp === 'number').toBe(true);
done();
}, fail.bind(null, done, unexpectedFailure));
});
it('compass.spec.4 should contain a watchHeading function', function () {
expect(navigator.compass.watchHeading).toBeDefined();
expect(typeof navigator.compass.watchHeading === 'function').toBe(true);
});
it('compass.spec.5 should contain a clearWatch function', function () {
expect(navigator.compass.clearWatch).toBeDefined();
expect(typeof navigator.compass.clearWatch === 'function').toBe(true);
});
describe('Compass Constants (window.CompassError)', function () {
it('compass.spec.1 should exist', function () {
expect(window.CompassError).toBeDefined();
expect(window.CompassError.COMPASS_INTERNAL_ERR).toBe(0);
expect(window.CompassError.COMPASS_NOT_SUPPORTED).toBe(20);
});
});
describe('Compass Heading model (CompassHeading)', function () {
it('compass.spec.1 should exist', function () {
expect(CompassHeading).toBeDefined();
});
it('compass.spec.8 should be able to create a new CompassHeading instance with no parameters', function () {
var h = new CompassHeading();
expect(h).toBeDefined();
expect(h.magneticHeading).toBeUndefined();
expect(h.trueHeading).toBeUndefined();
expect(h.headingAccuracy).toBeUndefined();
expect(typeof h.timestamp === 'number').toBe(true);
});
it('compass.spec.9 should be able to create a new CompassHeading instance with parameters', function () {
var h = new CompassHeading(1, 2, 3, 4);
expect(h.magneticHeading).toBe(1);
expect(h.trueHeading).toBe(2);
expect(h.headingAccuracy).toBe(3);
expect(h.timestamp.valueOf()).toBe(4);
expect(typeof h.timestamp === 'number').toBe(true);
});
});
describe('Compass watch heading', function () {
it('compass.spec.10 watchCurrentHeading called with a Heading object', function (done) {
if (!isCompassAvailable) {
pending();
}
var calledOnce = false;
var watchId = navigator.compass.watchHeading(
function (a) {
expect(a instanceof CompassHeading).toBe(true);
expect(a.magneticHeading).toBeDefined();
expect(typeof a.magneticHeading === 'number').toBe(true);
expect(a.trueHeading).not.toBe(undefined);
expect(typeof a.trueHeading === 'number' || a.trueHeading === null).toBe(true);
expect(a.headingAccuracy).not.toBe(undefined);
expect(typeof a.headingAccuracy === 'number' || a.headingAccuracy === null).toBe(true);
expect(typeof a.timestamp === 'number').toBe(true);
if (calledOnce) {
navigator.compass.clearWatch(watchId);
done();
}
calledOnce = true;
},
function (compassError) {},
{ frequency: 50 }
);
});
it('compass.spec.11 the watch success callback should not be called once the watch is cleared', function (done) {
if (!isCompassAvailable) {
pending();
}
var calledOnce = false;
var watchCleared = false;
var watchId = navigator.compass.watchHeading(
function (a) {
// Don't invoke this function if we have cleared the watch
expect(watchCleared).toBe(false);
if (calledOnce && !watchCleared) {
navigator.compass.clearWatch(watchId);
watchCleared = true;
setTimeout(function () {
done();
}, 1000);
}
calledOnce = true;
},
function (compassError) {},
{ frequency: 50 }
);
});
});
});
};
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
exports.defineManualTests = function (contentEl, createActionButton) {
function roundNumber (num) {
var dec = 3;
var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
return result;
}
var watchCompassId = null;
/**
* Set compass status
*/
function setCompassStatus (status) {
document.getElementById('compass_status').innerHTML = status;
}
// Success callback for both watchHeading and getCurrentHeading
function success (a) {
var magneticHeading = document.getElementById('magneticHeading');
var trueHeading = document.getElementById('trueHeading');
var headingAccuracy = document.getElementById('headingAccuracy');
var timestamp = document.getElementById('timestamp');
magneticHeading.innerHTML = roundNumber(a.magneticHeading);
trueHeading.innerHTML = roundNumber(a.trueHeading);
headingAccuracy.innerHTML = a.headingAccuracy;
timestamp.innerHTML = a.timestamp;
}
/**
* Stop watching the acceleration
*/
function stopCompass () {
setCompassStatus('Stopped');
if (watchCompassId) {
navigator.compass.clearWatch(watchCompassId);
watchCompassId = null;
}
}
/**
* Start watching compass
*/
var watchCompass = function () {
console.log('watchCompass()');
// Fail callback
var fail = function (e) {
console.log('watchCompass fail callback with error: ' + JSON.stringify(e));
stopCompass();
setCompassStatus(e);
};
// Stop compass if running
stopCompass();
// Update heading every 1 sec
var opt = {};
opt.frequency = 1000;
watchCompassId = navigator.compass.watchHeading(success, fail, opt);
setCompassStatus('Running');
};
/**
* Get current compass
*/
var getCompass = function () {
console.log('getCompass()');
// Stop compass if running
stopCompass();
// Fail callback
var fail = function (e) {
console.log('getCompass fail callback with error: ' + JSON.stringify(e));
setCompassStatus(e);
};
// Make call
var opt = {};
navigator.compass.getCurrentHeading(success, fail, opt);
};
/******************************************************************************/
var orientation_tests =
'<h3>iOS devices may bring up a calibration screen when initiating these tests</h3>' +
'<div id="getCompass"></div>' +
'Expected result: Will update the status box with current heading. Status will read "Stopped"' +
'<p/> <div id="watchCompass"></div>' +
'Expected result: When pressed, will start a watch on the compass and update the heading value when heading changes. Status will read "Running"' +
'<p/> <div id="stopCompass"></div>' +
'Expected result: Will clear the compass watch, so heading value will no longer be updated. Status will read "Stopped"';
contentEl.innerHTML =
'<div id="info"><b>Status: </b>' +
'<span id="compass_status">Stopped</span>' +
'<table width="100%">' +
'<tr><td width="33%">Magnetic heading: <span id="magneticHeading"></span></td></tr>' +
'<tr><td width="33%">True heading: <span id="trueHeading"></span></td></tr>' +
'<tr><td width="33%">Heading accuracy: <span id="headingAccuracy"></span></td></tr>' +
'<tr><td width="33%">Timestamp: <span id="timestamp"></span></td></tr>' +
'</table></div>' +
orientation_tests;
createActionButton(
'Get Compass',
function () {
getCompass();
},
'getCompass'
);
createActionButton(
'Start Watching Compass',
function () {
watchCompass();
},
'watchCompass'
);
createActionButton(
'Stop Watching Compass',
function () {
stopCompass();
},
'stopCompass'
);
};