Commit d90a982c authored by Jesse Schettler's avatar Jesse Schettler Committed by Commit Bot

scanning: Add scan button to scanning app

Add a scan button to the scanning app. When the button is clicked, use
the ScanService to perform a scan with the selected scanner and
settings.

Bug: 1059779
Change-Id: I52231a5a49fa01a2b56e42bcf2f9842fdf54ddf1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2437103
Auto-Submit: Jesse Schettler <jschettler@chromium.org>
Reviewed-by: default avatarJimmy Gong <jimmyxgong@chromium.org>
Commit-Queue: Jesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814535}
parent 2e16d4ca
......@@ -11,6 +11,12 @@ import {setScanServiceForTesting} from 'chrome://scanning/mojo_interface_provide
import {ScannerArr} from 'chrome://scanning/scanning_app_types.js';
import {getSourceTypeString, tokenToString} from 'chrome://scanning/scanning_app_util.js';
const ColorMode = {
BLACK_AND_WHITE: chromeos.scanning.mojom.ColorMode.kBlackAndWhite,
GRAYSCALE: chromeos.scanning.mojom.ColorMode.kGrayscale,
COLOR: chromeos.scanning.mojom.ColorMode.kColor,
};
const SourceType = {
FLATBED: chromeos.scanning.mojom.SourceType.kFlatbed,
ADF_SIMPLEX: chromeos.scanning.mojom.SourceType.kAdfSimplex,
......@@ -65,12 +71,21 @@ class FakeScanService {
/** @private {!ScannerArr} */
this.scanners_ = [];
/**
* @private {!Map<!mojoBase.mojom.UnguessableToken,
* !chromeos.scanning.mojom.ScannerCapabilities>}
*/
this.capabilities_ = new Map();
this.resetForTest();
}
resetForTest() {
this.scanners_ = [];
this.capabilities_ = new Map();
this.resolverMap_.set('getScanners', new PromiseResolver());
this.resolverMap_.set('getScannerCapabilities', new PromiseResolver());
this.resolverMap_.set('scan', new PromiseResolver());
}
/**
......@@ -113,6 +128,14 @@ class FakeScanService {
this.scanners_ = this.scanners_.concat(scanner);
}
/**
* @param {!Map<!mojoBase.mojom.UnguessableToken,
* !chromeos.scanning.mojom.ScannerCapabilities>} capabilities
*/
setCapabilities(capabilities) {
this.capabilities_ = capabilities;
}
// scanService methods:
/** @return {!Promise<{scanners: !ScannerArr}>} */
......@@ -122,11 +145,35 @@ class FakeScanService {
resolve({scanners: this.scanners_ || []});
});
}
/**
* @param {!mojoBase.mojom.UnguessableToken} scanner_id
* @return {!Promise<{capabilities:
* !chromeos.scanning.mojom.ScannerCapabilities}>}
*/
getScannerCapabilities(scanner_id) {
return new Promise(resolve => {
this.methodCalled('getScannerCapabilities');
resolve({capabilities: this.capabilities_.get(scanner_id)});
});
}
/**
* @param {!mojoBase.mojom.UnguessableToken} scanner_id
* @param {!chromeos.scanning.mojom.ScanSettings} settings
* @return {!Promise<{success: boolean}>}
*/
scan(scanner_id, settings) {
return new Promise(resolve => {
this.methodCalled('scan');
resolve({success: true});
});
}
}
suite('ScanningAppTest', () => {
/** @type {?ScanningAppElement} */
let page = null;
let scanningApp = null;
/** @type {?chromeos.scanning.mojom.ScanServiceRemote} */
let fakeScanService_;
......@@ -138,16 +185,100 @@ suite('ScanningAppTest', () => {
setup(function() {
PolymerTest.clearBody();
page = document.createElement('scanning-app');
document.body.appendChild(page);
});
teardown(function() {
page.remove();
page = null;
fakeScanService_.resetForTest();
scanningApp.remove();
scanningApp = null;
});
test('MainPageLoaded', () => {});
/**
* @param {!ScannerArr} scanners
* @param {!Map<!mojoBase.mojom.UnguessableToken,
* !chromeos.scanning.mojom.ScannerCapabilities>} capabilities
* @return {!Promise}
*/
function initializeScanningApp(scanners, capabilities) {
fakeScanService_.setScanners(scanners);
fakeScanService_.setCapabilities(capabilities);
scanningApp = document.createElement('scanning-app');
document.body.appendChild(scanningApp);
assert(!!scanningApp);
return fakeScanService_.whenCalled('getScanners');
}
test('Scan', () => {
const firstScannerId = {high: 0, low: 1};
const firstScannerName = 'Scanner 1';
const secondScannerId = {high: 0, low: 2};
const secondScannerName = 'Scanner 2';
const expectedScanners = [
createScanner(firstScannerId, firstScannerName),
createScanner(secondScannerId, secondScannerName)
];
const firstCapabilities = {
sources: [
{type: SourceType.FLATBED, name: 'platen'},
{type: SourceType.ADF_DUPLEX, name: 'adf duplex'}
],
colorModes: [ColorMode.BLACK_AND_WHITE, ColorMode.COLOR],
resolutions: [75, 100, 300]
};
const secondCapabilities = {
sources: [{type: SourceType.ADF_SIMPLEX, name: 'adf simplex'}],
colorModes: [ColorMode.GRAYSCALE],
resolutions: [150, 600]
};
let capabilities = new Map();
capabilities.set(firstScannerId, firstCapabilities);
capabilities.set(secondScannerId, secondCapabilities);
return initializeScanningApp(expectedScanners, capabilities)
.then(() => {
return fakeScanService_.whenCalled('getScannerCapabilities');
})
.then(() => {
assertEquals(
tokenToString(firstScannerId), scanningApp.selectedScannerId);
assertEquals(
firstCapabilities.sources[0].name, scanningApp.selectedSource);
// Before the scan button is clicked, the settings and scan button
// should be enabled, and there should be no scan status.
const scannerSelect = scanningApp.$$('#scannerSelect').$$('select');
assertFalse(scannerSelect.disabled);
const sourceSelect = scanningApp.$$('#sourceSelect').$$('select');
assertFalse(sourceSelect.disabled);
const scanButton = scanningApp.$$('#scanButton');
assertFalse(scanButton.disabled);
const statusText = scanningApp.$$('#statusText');
assertEquals('', statusText.textContent.trim());
scanButton.click();
// After the scan button is clicked, the settings and scan button
// should be disabled, and the scan status should indicate that
// scanning is in progress.
assertTrue(scannerSelect.disabled);
assertTrue(sourceSelect.disabled);
assertTrue(scanButton.disabled);
assertEquals('Scanning...', statusText.textContent.trim());
return fakeScanService_.whenCalled('scan');
})
.then(() => {
// After scanning is complete, the settings and scan button should be
// enabled, and the scan status should indicate that scanning is
// complete.
assertFalse(scanningApp.$$('#scannerSelect').$$('select').disabled);
assertFalse(scanningApp.$$('#sourceSelect').$$('select').disabled);
assertFalse(scanningApp.$$('#scanButton').disabled);
assertEquals(
'Scan complete! File(s) saved to My files.',
scanningApp.$$('#statusText').textContent.trim());
});
});
});
suite('ScannerSelectTest', () => {
......
......@@ -43,12 +43,14 @@ Polymer({
loaded: Boolean,
settingsDisabled: Boolean,
/** @private */
disabled_: Boolean,
},
observers: [
'updateDisabled_(scanners.length)',
'updateDisabled_(scanners.length, settingsDisabled)',
],
/**
......@@ -73,11 +75,12 @@ Polymer({
},
/**
* Disables the dropdown based on the number of available scanners.
* @param {number} numScanners
* Disables the dropdown if settings are disabled or the number of available
* scanners is less than the number of required scanners.
* @private
*/
updateDisabled_(numScanners) {
this.disabled_ = numScanners < NUM_REQUIRED_SCANNERS;
updateDisabled_() {
this.disabled_ =
this.settingsDisabled || this.scanners.length < NUM_REQUIRED_SCANNERS;
},
});
<div id="header"></div>
<div>
<scanner-select scanners="[[scanners_]]" loaded="[[loaded_]]"
<scanner-select id="scannerSelect" scanners="[[scanners_]]"
loaded="[[loaded_]]" settings-disabled="[[settingsDisabled_]]"
selected-scanner-id="{{selectedScannerId}}"></scanner-select>
</div>
<div>
<source-select sources="[[capabilities_.sources]]"
<source-select id="sourceSelect" sources="[[capabilities_.sources]]"
settings-disabled="[[settingsDisabled_]]"
selected-source="{{selectedSource}}"></source-select>
</div>
<!-- TODO(jschettler): Replace button label with finalized i18n string. -->
<cr-button id="scanButton" on-click="onScanClick_"
disabled$="[[scanButtonDisabled_]]">
Scan
</cr-button>
<p id="statusText">[[statusText_]]</p>
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js';
import 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js';
import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js';
......@@ -50,6 +51,24 @@ Polymer({
/** @type {?string} */
selectedSource: String,
/**
* @type {?string}
* @private
*/
statusText_: String,
/** @private */
settingsDisabled_: {
type: Boolean,
value: false,
},
/** @private */
scanButtonDisabled_: {
type: Boolean,
value: true,
},
/** @private */
loaded_: {
type: Boolean,
......@@ -80,6 +99,8 @@ Polymer({
// Set the first source as the selected source since it will be the first
// option in the dropdown.
this.selectedSource = this.capabilities_.sources[0].name;
this.scanButtonDisabled_ = false;
},
/**
......@@ -112,8 +133,51 @@ Polymer({
return;
}
this.scanButtonDisabled_ = true;
this.scanService_
.getScannerCapabilities(this.scannerIds_.get(selectedScannerId))
.then(this.onCapabilitiesReceived_.bind(this));
},
/** @private */
onScanClick_() {
if (!this.selectedScannerId || !this.selectedSource) {
// TODO(jschettler): Replace status text with finalized i18n strings.
this.statusText_ = 'Failed to start scan.';
return;
}
this.statusText_ = 'Scanning...';
this.settingsDisabled_ = true;
this.scanButtonDisabled_ = true;
// TODO(jschettler): Set color mode and resolution using the selected values
// when the corresponding dropdowns are added.
const settings = {
'sourceName': this.selectedSource,
'colorMode': chromeos.scanning.mojom.ColorMode.kColor,
'resolutionDpi': 100,
};
this.scanService_
.scan(this.scannerIds_.get(this.selectedScannerId), settings)
.then(
/*@type {!{success: boolean}}*/ (response) => {
this.onScanCompleted_(response)});
},
/**
* @param {!{success: boolean}} response
* @private
*/
onScanCompleted_(response) {
if (response.success) {
this.statusText_ = 'Scan complete! File(s) saved to My files.';
} else {
this.statusText_ = 'Scan failed.';
}
this.settingsDisabled_ = false;
this.scanButtonDisabled_ = false;
},
});
......@@ -39,12 +39,14 @@ Polymer({
notify: true,
},
settingsDisabled: Boolean,
/** @private */
disabled_: Boolean,
},
observers: [
'updateDisabled_(sources.length)',
'updateDisabled_(sources.length, settingsDisabled)',
],
/**
......@@ -57,11 +59,12 @@ Polymer({
},
/**
* Disables the dropdown based on the number of available sources.
* @param {number} numSources
* Disables the dropdown if settings are disabled or the number of available
* sources is less than the number of required sources.
* @private
*/
updateDisabled_(numSources) {
this.disabled_ = numSources < NUM_REQUIRED_SOURCES;
updateDisabled_() {
this.disabled_ =
this.settingsDisabled || this.sources.length < NUM_REQUIRED_SOURCES;
},
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment