blob: ed63f1d13da2d502a9cae5cad785840490b4c587 [file] [log] [blame]
<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="resources/bluetooth-helpers.js"></script>
<script>
'use strict';
test(function(t) { assert_exists(window, 'testRunner'); t.done(); },
'window.testRunner is required for the following tests.');
promise_test(() => {
testRunner.setBluetoothMockDataSet('GenericAccessAdapter');
return requestDeviceWithKeyDown({filters: [{services: ['generic_access']}]})
.then(device => device.connectGATT())
.then(gattServer => gattServer.getPrimaryService('generic_access'))
.then(service => service.getCharacteristic('gap.device_name'))
.then(characteristic => {
testRunner.setBluetoothMockDataSet('EmptyAdapter');
return assert_promise_rejects_with_message(
characteristic.writeValue(new ArrayBuffer(1 /* length */)), {
name: 'NetworkError',
message: 'Bluetooth Device is no longer in range.'
}, 'Device went out of range.');
});
}, 'Device goes out of range. Reject with NetworkError.');
promise_test(() => {
testRunner.setBluetoothMockDataSet('GenericAccessAdapter');
return requestDeviceWithKeyDown({filters: [{services: ['generic_access']}]})
.then(device => device.connectGATT())
.then(gattServer => gattServer.getPrimaryService('generic_access'))
.then(service => service.getCharacteristic('gap.device_name'))
.then(characteristic => {
testRunner.setBluetoothMockDataSet('MissingServiceGenericAccessAdapter');
return assert_promise_rejects_with_message(
characteristic.writeValue(new ArrayBuffer(1 /* length */)), {
name: 'InvalidStateError',
message: 'GATT Service no longer exists.'
}, 'Service got removed.');
});
}, 'Service gets removed. Reject with InvalidStateError.');
promise_test(() => {
testRunner.setBluetoothMockDataSet('GenericAccessAdapter');
return requestDeviceWithKeyDown({filters: [{services: ['generic_access']}]})
.then(device => device.connectGATT())
.then(gattServer => gattServer.getPrimaryService('generic_access'))
.then(service => service.getCharacteristic('gap.device_name'))
.then(characteristic => {
testRunner.setBluetoothMockDataSet('MissingCharacteristicGenericAccessAdapter');
return assert_promise_rejects_with_message(
characteristic.writeValue(new ArrayBuffer(1 /* length */)), {
name: 'InvalidStateError',
message: 'GATT Characteristic no longer exists.'
}, 'Characteristic got removed.');
});
}, 'Characteristic gets removed. Reject with InvalidStateError.');
// The following tests make sure the Web Bluetooth implementation
// responds correctly to the different types of errors the
// underlying platform might return for GATT operations.
// Each implementation maps these characteristics to specific code paths
// that result in different errors thus increasing code coverage
// when testing. Therefore some of these characteristics might not be useful
// for all implementations.
[{
testName: 'GATT Error: Unknown.',
uuid: errorUUID(0xA1),
error: {
name: 'NotSupportedError',
message: 'GATT Error Unknown.'
}
}, {
testName: 'GATT Error: Failed.',
uuid: errorUUID(0xA2),
error: {
name: 'NotSupportedError',
message: 'GATT operation failed for unknown reason.'
}
}, {
testName: 'GATT Error: In Progress.',
uuid: errorUUID(0xA3),
error: {
name: 'NetworkError',
message: 'GATT operation already in progress.'
}
}, {
testName: 'GATT Error: Invalid Length.',
uuid: errorUUID(0xA4),
error: {
name: 'InvalidModificationError',
message: 'GATT Error: invalid attribute length.'
}
}, {
testName: 'GATT Error: Not Permitted.',
uuid: errorUUID(0xA5),
error: {
name: 'NotSupportedError',
message: 'GATT operation not permitted.'
}
}, {
testName: 'GATT Error: Not Authorized.',
uuid: errorUUID(0xA6),
error: {
name: 'SecurityError',
message: 'GATT operation not authorized.'
}
}, {
testName: 'GATT Error: Not Paired.',
uuid: errorUUID(0xA7),
// TODO(ortuno): Change to InsufficientAuthenticationError or similiar
// once https://github.com/WebBluetoothCG/web-bluetooth/issues/137 is
// resolved.
error: {
name: 'NetworkError',
message: 'GATT Error: Not paired.'
}
}, {
testName: 'GATT Error: Not Supported.',
uuid: errorUUID(0xA8),
error: {
name: 'NotSupportedError',
message: 'GATT Error: Not supported.'
}
}].forEach(testSpec => {
promise_test(() => {
testRunner.setBluetoothMockDataSet('FailingGATTOperationsAdapter');
return requestDeviceWithKeyDown({filters: [{services: [errorUUID(0xA0)]}]})
.then(device => device.connectGATT())
.then(gattServer => gattServer.getPrimaryService(errorUUID(0xA0)))
.then(service => service.getCharacteristic(testSpec.uuid))
.then(characteristic => {
return assert_promise_rejects_with_message(
characteristic.writeValue(new Uint8Array([1])),
testSpec.error,
'Trying to write to a characteristic failed.');
});
}, testSpec.testName);
});
promise_test(() => {
testRunner.setBluetoothMockDataSet('GenericAccessAdapter');
return requestDeviceWithKeyDown({filters: [{services: ['generic_access']}]})
.then(device => device.connectGATT())
.then(gattServer => gattServer.getPrimaryService('generic_access'))
.then(service => service.getCharacteristic('gap.device_name'))
.then(characteristic => {
return assert_promise_rejects_with_message(
characteristic.writeValue(new Uint8Array(513 /* length */)), {
name: 'InvalidModificationError',
message: 'Value can\'t exceed 512 bytes.'
}, 'Value passed was too long.');
});
}, 'Trying to write more than 512 bytes should return an error.');
promise_test(() => {
testRunner.setBluetoothMockDataSet('GenericAccessAdapter');
return requestDeviceWithKeyDown({filters: [{services: ['generic_access']}]})
.then(device => device.connectGATT())
.then(gattServer => gattServer.getPrimaryService('generic_access'))
.then(service => service.getCharacteristic('gap.device_name'))
.then(characteristic => Promise.all(
[characteristic.writeValue(new Uint8Array(1 /* length */)),
characteristic.writeValue(new ArrayBuffer(1 /* length */)),
characteristic.writeValue(new DataView(new ArrayBuffer(1 /* length */)))]));
}, 'A regular write request to a writable characteristic should succeed.');
</script>