https://github.com/web-platform-tests/wpt
Raw File
Tip revision: 220550a5ff779548d669998a623bf6fc14f6d290 authored by Christian Biesinger on 26 January 2016, 01:17:40 UTC
[css-sizing-3] Add tests for percentage resolution
Tip revision: 220550a
generic-sensor-tests.js
// These tests rely on the User Agent providing an implementation of
// platform sensor backends.
//
// In Chromium-based browsers this implementation is provided by a polyfill
// in order to reduce the amount of test-only code shipped to users. To enable
// these tests the browser must be run with these options:
//
//   --enable-blink-features=MojoJS,MojoJSTest
let loadChromiumResources = Promise.resolve().then(() => {
  if (!MojoInterfaceInterceptor) {
    // Do nothing on non-Chromium-based browsers or when the Mojo bindings are
    // not present in the global namespace.
    return;
  }

  let chain = Promise.resolve();
  [
    '/resources/chromium/mojo_bindings.js',
    '/resources/chromium/string16.mojom.js',
    '/resources/chromium/sensor.mojom.js',
    '/resources/chromium/sensor_provider.mojom.js',
    '/resources/chromium/generic_sensor_mocks.js',
  ].forEach(path => {
    let script = document.createElement('script');
    script.src = path;
    script.async = false;
    chain = chain.then(() => new Promise(resolve => {
      script.onload = resolve;
    }));
    document.head.appendChild(script);
  });

  return chain;
});

async function initialize_generic_sensor_tests() {
  if (typeof GenericSensorTest === 'undefined') {
    await loadChromiumResources;
  }
  assert_true(typeof GenericSensorTest !== 'undefined');
  let sensorTest = new GenericSensorTest();
  await sensorTest.initialize();
  return sensorTest;
}

function sensor_test(func, name, properties) {
  promise_test(async (t) => {
    let sensorTest = await initialize_generic_sensor_tests();
    try {
      await func(t);
    } finally {
      await sensorTest.reset();
    };
  }, name, properties);
}

const properties = {
  'AmbientLightSensor' : ['timestamp', 'illuminance'],
  'Accelerometer' : ['timestamp', 'x', 'y', 'z'],
  'LinearAccelerationSensor' : ['timestamp', 'x', 'y', 'z'],
  "GravitySensor" : ['timestamp', 'x', 'y', 'z'],
  'Gyroscope' : ['timestamp', 'x', 'y', 'z'],
  'Magnetometer' : ['timestamp', 'x', 'y', 'z'],
  "UncalibratedMagnetometer" : ['timestamp', 'x', 'y', 'z',
                                'xBias', 'yBias', 'zBias'],
  'AbsoluteOrientationSensor' : ['timestamp', 'quaternion'],
  'RelativeOrientationSensor' : ['timestamp', 'quaternion'],
  'GeolocationSensor' : ['timestamp', 'latitude', 'longitude', 'altitude',
                         'accuracy', 'altitudeAccuracy', 'heading', 'speed'],
  'ProximitySensor' : ['timestamp', 'max']
};
const spatialSensors = ['Accelerometer',
                       'LinearAccelerationSensor',
                       'GravitySensor',
                       'Gyroscope',
                       'Magnetometer',
                       'UncalibratedMagnetometer',
                       'AbsoluteOrientationSensor',
                       'RelativeOrientationSensor'];

function assert_reading_not_null(sensor) {
  for (let property in properties[sensor.constructor.name]) {
    let propertyName = properties[sensor.constructor.name][property];
    assert_not_equals(sensor[propertyName], null);
  }
}

function assert_reading_null(sensor) {
  for (let property in properties[sensor.constructor.name]) {
    let propertyName = properties[sensor.constructor.name][property];
    assert_equals(sensor[propertyName], null);
  }
}

function reading_to_array(sensor) {
  const arr = new Array();
  for (let property in properties[sensor.constructor.name]) {
    let propertyName = properties[sensor.constructor.name][property];
    arr[property] = sensor[propertyName];
  }
  return arr;
}

function runGenericSensorTests(sensorName) {
  const sensorType = self[sensorName];

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("reading");
    assert_reading_not_null(sensor);
    assert_true(sensor.hasReading);

    sensor.stop();
    assert_reading_null(sensor);
    assert_false(sensor.hasReading);
  }, `${sensorName}: Test that 'onreading' is called and sensor reading is valid`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor1 = new sensorType();
    const sensor2 = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor1, ["reading", "error"]);
    sensor2.start();
    sensor1.start();

    await sensorWatcher.wait_for("reading");
    // Reading values are correct for both sensors.
    assert_reading_not_null(sensor1);
    assert_reading_not_null(sensor2);

    //After first sensor stops its reading values are null,
    //reading values for the second sensor remains
    sensor1.stop();
    assert_reading_null(sensor1);
    assert_reading_not_null(sensor2);
    sensor2.stop();
    assert_reading_null(sensor2);
  }, `${sensorName}: sensor reading is correct`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("reading");
    const cachedTimeStamp1 = sensor.timestamp;

    await sensorWatcher.wait_for("reading");
    const cachedTimeStamp2 = sensor.timestamp;

    assert_greater_than(cachedTimeStamp2, cachedTimeStamp1);
    sensor.stop();
  }, `${sensorName}: sensor timestamp is updated when time passes`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
    assert_false(sensor.activated);
    sensor.start();
    assert_false(sensor.activated);

    await sensorWatcher.wait_for("activate");
    assert_true(sensor.activated);

    sensor.stop();
    assert_false(sensor.activated);
  }, `${sensorName}: Test that sensor can be successfully created and its states are correct.`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
    const start_return = sensor.start();

    await sensorWatcher.wait_for("activate");
    assert_equals(start_return, undefined);
    sensor.stop();
  }, `${sensorName}: sensor.start() returns undefined`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
    sensor.start();
    sensor.start();

    await sensorWatcher.wait_for("activate");
    assert_true(sensor.activated);
    sensor.stop();
  }, `${sensorName}: no exception is thrown when calling start() on already started sensor`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("activate");
    const stop_return = sensor.stop();
    assert_equals(stop_return, undefined);
  }, `${sensorName}: sensor.stop() returns undefined`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("activate");
    sensor.stop();
    sensor.stop();
    assert_false(sensor.activated);
  }, `${sensorName}: no exception is thrown when calling stop() on already stopped sensor`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("reading");
    assert_true(sensor.hasReading);
    const timestamp = sensor.timestamp;
    sensor.stop();
    assert_false(sensor.hasReading);

    sensor.start();
    await sensorWatcher.wait_for("reading");
    assert_true(sensor.hasReading);
    assert_greater_than(timestamp, 0);
    assert_greater_than(sensor.timestamp, timestamp);
    sensor.stop();
  }, `${sensorName}: Test that fresh reading is fetched on start()`);

//  TBD file a WPT issue: visibilityChangeWatcher times out.
//  sensor_test(async t => {
//    const sensor = new sensorType();
//    const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
//    const visibilityChangeWatcher = new EventWatcher(t, document, "visibilitychange");
//    sensor.start();

//    await sensorWatcher.wait_for("reading");
//    assert_reading_not_null(sensor);
//    const cachedSensor1 = reading_to_array(sensor);

//    const win = window.open('', '_blank');
//    await visibilityChangeWatcher.wait_for("visibilitychange");
//    const cachedSensor2 = reading_to_array(sensor);

//    win.close();
//    sensor.stop();
//    assert_object_equals(cachedSensor1, cachedSensor2);
//  }, `${sensorName}: sensor readings can not be fired on the background tab`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    const fastSensor = new sensorType({frequency: 30});
    const slowSensor = new sensorType({frequency: 5});
    slowSensor.start();

    const fastCounter = await new Promise((resolve, reject) => {
      let fastCounter = 0;
      let slowCounter = 0;

      fastSensor.onreading = () => {
        fastCounter++;
      }
      slowSensor.onreading = () => {
        slowCounter++;
        if (slowCounter == 1) {
          fastSensor.start();
        } else if (slowCounter == 3) {
          fastSensor.stop();
          slowSensor.stop();
          resolve(fastCounter);
        }
      }
      fastSensor.onerror = reject;
      slowSensor.onerror = reject;
    });
    assert_greater_than(fastCounter, 2,
                        "Fast sensor overtakes the slow one");
  }, `${sensorName}: frequency hint works`);

  sensor_test(async t => {
    assert_true(sensorName in self);
    // Create a focused editbox inside a cross-origin iframe,
    // sensor notification must suspend.
    const iframeSrc = 'data:text/html;charset=utf-8,<html><body>'
                    + '<input type="text" autofocus></body></html>';
    const iframe = document.createElement('iframe');
    iframe.src = encodeURI(iframeSrc);

    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("reading");
    assert_reading_not_null(sensor);
    const cachedTimestamp = sensor.timestamp;
    const cachedSensor1 = reading_to_array(sensor);

    const iframeWatcher = new EventWatcher(t, iframe, "load");
    document.body.appendChild(iframe);
    await iframeWatcher.wait_for("load");
    const cachedSensor2 = reading_to_array(sensor);
    assert_array_equals(cachedSensor1, cachedSensor2);

    iframe.remove();
    await sensorWatcher.wait_for("reading");
    const cachedSensor3 = reading_to_array(sensor);
    assert_greater_than(sensor.timestamp, cachedTimestamp);

    sensor.stop();
  }, `${sensorName}: sensor receives suspend / resume notifications when\
  cross-origin subframe is focused`);

//  Re-enable after https://github.com/w3c/sensors/issues/361 is fixed.
//  test(() => {
//     assert_throws("NotSupportedError", () => { new sensorType({invalid: 1}) });
//     assert_throws("NotSupportedError", () => { new sensorType({frequency: 60, invalid: 1}) });
//     if (spatialSensors.indexOf(sensorName) == -1) {
//       assert_throws("NotSupportedError", () => { new sensorType({referenceFrame: "screen"}) });
//     }
//  }, `${sensorName}: throw 'NotSupportedError' for an unsupported sensor option`);

  test(() => {
    assert_true(sensorName in self);
    const invalidFreqs = [
      "invalid",
      NaN,
      Infinity,
      -Infinity,
      {}
    ];
    invalidFreqs.map(freq => {
      assert_throws(new TypeError(),
                    () => { new sensorType({frequency: freq}) },
                    `when freq is ${freq}`);
    });
  }, `${sensorName}: throw 'TypeError' if frequency is invalid`);

  if (spatialSensors.indexOf(sensorName) == -1) {
    // The sensorType does not represent a spatial sensor.
    return;
  }

  sensor_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType({referenceFrame: "screen"});
    const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
    sensor.start();

    await sensorWatcher.wait_for("reading");
    //TODO use mock data to verify sensor readings, blocked by issue:
    // https://github.com/web-platform-tests/wpt/issues/9686
    assert_reading_not_null(sensor);

    sensor.stop();
  }, `${sensorName}: sensor reading is correct when options.referenceFrame is 'screen'`);

  test(() => {
    assert_true(sensorName in self);
    const invalidRefFrames = [
      "invalid",
      null,
      123,
      {},
      "",
      true
    ];
    invalidRefFrames.map(refFrame => {
      assert_throws(new TypeError(),
                    () => { new sensorType({referenceFrame: refFrame}) },
                    `when refFrame is ${refFrame}`);
    });
  }, `${sensorName}: throw 'TypeError' if referenceFrame is not one of enumeration values`);
}

function runGenericSensorInsecureContext(sensorName) {
  test(() => {
    assert_false(sensorName in window, `${sensorName} must not be exposed`);
  }, `${sensorName} is not exposed in an insecure context`);
}

function runGenericSensorOnerror(sensorName) {
  const sensorType = self[sensorName];

  promise_test(async t => {
    assert_true(sensorName in self);
    const sensor = new sensorType();
    const sensorWatcher = new EventWatcher(t, sensor, ["error", "activate"]);
    sensor.start();

    const event = await sensorWatcher.wait_for("error");
    assert_false(sensor.activated);
    assert_true(event.error.name == 'NotReadableError' ||
                event.error.name == 'NotAllowedError');
  }, `${sensorName}: 'onerror' event is fired when sensor is not supported`);
}
back to top