blob: 130b11e9021856fff63c6ef31a27bbd0b393a18c [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { Destination, DestinationErrorType, DestinationOrigin, DestinationState, DestinationStoreEventType, Error, GooglePromotedDestinationId, makeRecentDestination, NativeLayerImpl, NUM_PERSISTED_DESTINATIONS, State } from 'chrome://print/print_preview.js';
import { assert } from 'chrome://resources/js/assert.m.js';
import { flush } from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import { assertEquals, assertFalse, assertTrue } from 'chrome://webui-test/chai_assert.js';
import { eventToPromise, fakeDataBind, waitBeforeNextRender } from 'chrome://webui-test/test_util.js';
//
import { NativeLayerStub } from './native_layer_stub.js';
import { getDestinations, getSaveAsPdfDestination, setupTestListenerElement } from './print_preview_test_utils.js';
//
const destination_settings_test = {
suiteName: 'DestinationSettingsTest',
TestNames: {
ChangeDropdownState: 'change dropdown state',
NoRecentDestinations: 'no recent destinations',
RecentDestinations: 'recent destinations',
RecentDestinationsMissing: 'recent destinations missing',
SaveAsPdfRecent: 'save as pdf recent',
//
SelectSaveAsPdf: 'select save as pdf',
//
SelectRecentDestination: 'select recent destination',
OpenDialog: 'open dialog',
UpdateRecentDestinations: 'update recent destinations',
DisabledSaveAsPdf: 'disabled save as pdf',
NoDestinations: 'no destinations',
//
},
};
Object.assign(window, { destination_settings_test: destination_settings_test });
suite(destination_settings_test.suiteName, function () {
let destinationSettings;
let nativeLayer;
//
let recentDestinations = [];
let localDestinations = [];
let destinations = [];
const extraDestinations = [];
let pdfPrinterDisabled = false;
let isDriveMounted = true;
//
suiteSetup(function () {
setupTestListenerElement();
});
setup(function () {
document.body.innerHTML = '';
// Stub out native layer.
nativeLayer = new NativeLayerStub();
NativeLayerImpl.setInstance(nativeLayer);
//
localDestinations = [];
destinations = getDestinations(localDestinations);
// Add some extra destinations.
for (let i = 0; i < NUM_PERSISTED_DESTINATIONS; i++) {
const id = `e${i}`;
const name = `n${i}`;
localDestinations.push({ deviceName: id, printerName: name });
extraDestinations.push(new Destination(id, getLocalOrigin(), name));
}
nativeLayer.setLocalDestinations(localDestinations);
const model = document.createElement('print-preview-model');
document.body.appendChild(model);
destinationSettings =
document.createElement('print-preview-destination-settings');
destinationSettings.settings = model.settings;
destinationSettings.state = State.NOT_READY;
destinationSettings.disabled = true;
fakeDataBind(model, destinationSettings, 'settings');
document.body.appendChild(destinationSettings);
});
// Tests that the dropdown is enabled or disabled correctly based on
// the state.
test(assert(destination_settings_test.TestNames.ChangeDropdownState), function () {
const dropdown = destinationSettings.$.destinationSelect;
// Initial state: No destination store means that there is no
// destination yet.
assertFalse(dropdown.loaded);
// Set up the destination store, but no destination yet. Dropdown is
// still not loaded.
destinationSettings.init('FooDevice' /* printerName */, false /* pdfPrinterDisabled */, isDriveMounted, '' /* serializedDefaultDestinationSelectionRulesStr */);
assertFalse(dropdown.loaded);
return eventToPromise(DestinationStoreEventType
.SELECTED_DESTINATION_CAPABILITIES_READY, destinationSettings.getDestinationStoreForTest())
.then(() => {
// The capabilities ready event results in |destinationState|
// changing to SELECTED, which enables and shows the dropdown even
// though |state| has not yet transitioned to READY. This is to
// prevent brief losses of focus when the destination changes.
assertFalse(dropdown.disabled);
assertTrue(dropdown.loaded);
destinationSettings.state = State.READY;
destinationSettings.disabled = false;
// Simulate setting a setting to an invalid value. Dropdown is
// disabled due to validation error on another control.
destinationSettings.state = State.ERROR;
destinationSettings.disabled = true;
assertTrue(dropdown.disabled);
// Simulate the user fixing the validation error, and then
// selecting an invalid printer. Dropdown is enabled, so that the
// user can fix the error.
destinationSettings.state = State.READY;
destinationSettings.disabled = false;
destinationSettings.getDestinationStoreForTest().dispatchEvent(new CustomEvent(DestinationStoreEventType.ERROR, { detail: DestinationErrorType.INVALID }));
flush();
assertEquals(DestinationState.ERROR, destinationSettings.destinationState);
assertEquals(Error.INVALID_PRINTER, destinationSettings.error);
destinationSettings.state = State.ERROR;
destinationSettings.disabled = true;
assertFalse(dropdown.disabled);
// Simulate the user having no printers.
destinationSettings.getDestinationStoreForTest().dispatchEvent(new CustomEvent(DestinationStoreEventType.ERROR, { detail: DestinationErrorType.NO_DESTINATIONS }));
flush();
assertEquals(DestinationState.ERROR, destinationSettings.destinationState);
assertEquals(Error.NO_DESTINATIONS, destinationSettings.error);
destinationSettings.state = State.FATAL_ERROR;
destinationSettings.disabled = true;
assertTrue(dropdown.disabled);
});
});
function getLocalOrigin() {
//
//
return DestinationOrigin.LOCAL;
//
}
//
/**
* Initializes the destination store and destination settings using
* |destinations| and |recentDestinations|.
*/
function initialize() {
// Initialize destination settings.
destinationSettings.setSetting('recentDestinations', recentDestinations);
destinationSettings.init('' /* printerName */, pdfPrinterDisabled, isDriveMounted, '' /* serializedDefaultDestinationSelectionRulesStr */);
destinationSettings.state = State.READY;
destinationSettings.disabled = false;
}
/**
* @param id The id of the local destination.
* @return The key corresponding to the local destination, with the
* origin set correctly based on the platform.
*/
function makeLocalDestinationKey(id) {
return id + '/' + getLocalOrigin() + '/';
}
/**
* @param expectedDestinations An array of the expected
* destinations in the dropdown.
*/
function assertDropdownItems(expectedDestinations) {
const options = destinationSettings.$.destinationSelect.getVisibleItemsForTest();
assertEquals(expectedDestinations.length + 1, options.length);
expectedDestinations.forEach((expectedValue, index) => {
assertEquals(expectedValue, options[index].value);
});
assertEquals('seeMore', options[expectedDestinations.length].value);
}
// Tests that the dropdown contains the appropriate destinations when there
// are no recent destinations.
test(assert(destination_settings_test.TestNames.NoRecentDestinations), function () {
initialize();
return nativeLayer.whenCalled('getPrinterCapabilities').then(() => {
// This will result in the destination store setting the Save as
// PDF destination.
assertEquals(GooglePromotedDestinationId.SAVE_AS_PDF, destinationSettings.destination.id);
assertFalse(destinationSettings.$.destinationSelect.disabled);
const dropdownItems = [
'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
});
});
// Tests that the dropdown contains the appropriate destinations when there
// are 5 recent destinations.
test(assert(destination_settings_test.TestNames.RecentDestinations), function () {
recentDestinations = destinations.slice(0, 5).map(destination => makeRecentDestination(destination));
const whenCapabilitiesDone = nativeLayer.whenCalled('getPrinterCapabilities');
initialize();
// Wait for the destinations to be inserted into the store.
return whenCapabilitiesDone
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// This will result in the destination store setting the most
// recent destination.
assertEquals('ID1', destinationSettings.destination.id);
assertFalse(destinationSettings.$.destinationSelect.disabled);
const dropdownItems = [
makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID2'),
makeLocalDestinationKey('ID3'), 'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
});
});
// Tests that the dropdown contains the appropriate destinations when one of
// the destinations can no longer be found.
test(assert(destination_settings_test.TestNames.RecentDestinationsMissing), function () {
recentDestinations = destinations.slice(0, 5).map(destination => makeRecentDestination(destination));
localDestinations.splice(1, 1);
nativeLayer.setLocalDestinations(localDestinations);
const whenCapabilitiesDone = nativeLayer.whenCalled('getPrinterCapabilities');
initialize();
// Wait for the destinations to be inserted into the store.
return whenCapabilitiesDone
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// This will result in the destination store setting the most
// recent destination.
assertEquals('ID1', destinationSettings.destination.id);
assertFalse(destinationSettings.$.destinationSelect.disabled);
const dropdownItems = [
makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID3'),
'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
});
});
// Tests that the dropdown contains the appropriate destinations when Save
// as PDF is one of the recent destinations.
test(assert(destination_settings_test.TestNames.SaveAsPdfRecent), function () {
recentDestinations = destinations.slice(0, 5).map(destination => makeRecentDestination(destination));
recentDestinations.splice(1, 1, makeRecentDestination(getSaveAsPdfDestination()));
const whenCapabilitiesDone = nativeLayer.whenCalled('getPrinterCapabilities');
initialize();
return whenCapabilitiesDone
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// This will result in the destination store setting the most recent
// destination.
assertEquals('ID1', destinationSettings.destination.id);
assertFalse(destinationSettings.$.destinationSelect.disabled);
const dropdownItems = [
makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID3'),
makeLocalDestinationKey('ID4'), 'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
});
});
//
// Tests that selecting the Save as PDF destination results in the
// DESTINATION_SELECT event firing, with Save as PDF set as the current
// destination.
test(assert(destination_settings_test.TestNames.SelectSaveAsPdf), function () {
recentDestinations = destinations.slice(0, 5).map(destination => makeRecentDestination(destination));
recentDestinations.splice(1, 1, makeRecentDestination(getSaveAsPdfDestination()));
const whenCapabilitiesDone = nativeLayer.whenCalled('getPrinterCapabilities');
initialize();
const dropdown = destinationSettings.$.destinationSelect;
return whenCapabilitiesDone
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// This will result in the destination store setting the most recent
// destination.
assertEquals('ID1', destinationSettings.destination.id);
assertFalse(dropdown.disabled);
const dropdownItems = [
makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID3'),
makeLocalDestinationKey('ID4'), 'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
// Most recent destination is selected by default.
assertEquals('ID1', destinationSettings.destination.id);
// Simulate selection of Save as PDF printer.
const whenDestinationSelect = eventToPromise(DestinationStoreEventType.DESTINATION_SELECT, destinationSettings.getDestinationStoreForTest());
dropdown.dispatchEvent(new CustomEvent('selected-option-change', { bubbles: true, composed: true, detail: 'Save as PDF/local/' }));
// Ensure this fires the destination select event.
return whenDestinationSelect;
})
.then(() => {
assertEquals(GooglePromotedDestinationId.SAVE_AS_PDF, destinationSettings.destination.id);
});
});
//
// Tests that selecting a recent destination results in the
// DESTINATION_SELECT event firing, with the recent destination set as the
// current destination.
test(assert(destination_settings_test.TestNames.SelectRecentDestination), function () {
recentDestinations = destinations.slice(0, 5).map(destination => makeRecentDestination(destination));
const whenCapabilitiesDone = nativeLayer.whenCalled('getPrinterCapabilities');
initialize();
const dropdown = destinationSettings.$.destinationSelect;
return whenCapabilitiesDone
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// This will result in the destination store setting the most
// recent destination.
assertEquals('ID1', destinationSettings.destination.id);
assertFalse(dropdown.disabled);
const dropdownItems = [
makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID2'),
makeLocalDestinationKey('ID3'), 'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
// Simulate selection of Save as PDF printer.
const whenDestinationSelect = eventToPromise(DestinationStoreEventType.DESTINATION_SELECT, destinationSettings.getDestinationStoreForTest());
dropdown.dispatchEvent(new CustomEvent('selected-option-change', {
bubbles: true,
composed: true,
detail: makeLocalDestinationKey('ID2'),
}));
return whenDestinationSelect;
})
.then(() => {
assertEquals('ID2', destinationSettings.destination.id);
});
});
// Tests that selecting the 'see more' option opens the dialog.
test(assert(destination_settings_test.TestNames.OpenDialog), function () {
recentDestinations = destinations.slice(0, 5).map(destination => makeRecentDestination(destination));
const whenCapabilitiesDone = nativeLayer.whenCalled('getPrinterCapabilities');
initialize();
const dropdown = destinationSettings.$.destinationSelect;
return whenCapabilitiesDone
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// This will result in the destination store setting the most recent
// destination.
assertEquals('ID1', destinationSettings.destination.id);
assertFalse(dropdown.disabled);
const dropdownItems = [
makeLocalDestinationKey('ID1'), makeLocalDestinationKey('ID2'),
makeLocalDestinationKey('ID3'), 'Save as PDF/local/',
//
];
assertDropdownItems(dropdownItems);
dropdown.dispatchEvent(new CustomEvent('selected-option-change', { bubbles: true, composed: true, detail: 'seeMore' }));
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
assertTrue(destinationSettings.$.destinationDialog.get().isOpen());
});
});
/**
* @param expectedDestinationIds An array of the expected
* recent destination ids.
*/
function assertRecentDestinations(expectedDestinationIds) {
const recentDestinations = destinationSettings.getSettingValue('recentDestinations');
assertEquals(expectedDestinationIds.length, recentDestinations.length);
expectedDestinationIds.forEach((expectedId, index) => {
assertEquals(expectedId, recentDestinations[index].id);
});
}
function selectDestination(destination) {
const storeDestination = destinationSettings.getDestinationStoreForTest().destinations().find(d => d.key === destination.key);
destinationSettings.getDestinationStoreForTest().selectDestination(assert(storeDestination));
flush();
}
/**
* Tests that the destination being set correctly updates the recent
* destinations array.
*/
test(assert(destination_settings_test.TestNames.UpdateRecentDestinations), function () {
// Recent destinations start out empty.
assertRecentDestinations([]);
assertEquals(0, nativeLayer.getCallCount('getPrinterCapabilities'));
initialize();
return nativeLayer.whenCalled('getPrinterCapabilities')
.then(() => {
assertRecentDestinations(['Save as PDF']);
assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities'));
// Add printers to store.
nativeLayer.resetResolver('getPrinterCapabilities');
destinationSettings.getDestinationStoreForTest()
.startLoadAllDestinations();
return nativeLayer.whenCalled('getPrinters');
})
.then(() => {
// Simulate setting a destination from the dialog.
selectDestination(destinations[0]);
return nativeLayer.whenCalled('getPrinterCapabilities');
})
.then(() => {
assertRecentDestinations(['ID1', 'Save as PDF']);
assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities'));
// Reselect a recent destination. Still 2 destinations, but in a
// different order.
nativeLayer.resetResolver('getPrinterCapabilities');
destinationSettings.$.destinationSelect.dispatchEvent(new CustomEvent('selected-option-change', {
bubbles: true,
composed: true,
detail: 'Save as PDF/local/',
}));
flush();
assertRecentDestinations(['Save as PDF', 'ID1']);
// No additional capabilities call, since the destination was
// previously selected.
assertEquals(0, nativeLayer.getCallCount('getPrinterCapabilities'));
// Select a third destination.
selectDestination(destinations[1]);
return nativeLayer.whenCalled('getPrinterCapabilities');
})
.then(() => {
assertRecentDestinations(['ID2', 'Save as PDF', 'ID1']);
assertEquals(1, nativeLayer.getCallCount('getPrinterCapabilities'));
nativeLayer.resetResolver('getPrinterCapabilities');
// Fill recent destinations up to the cap, then add a couple
// more destinations. Make sure the length of the list does not
// exceed NUM_PERSISTED_DESTINATIONS.
const whenCapabilitiesDone = nativeLayer.waitForMultipleCapabilities(NUM_PERSISTED_DESTINATIONS);
for (const destination of extraDestinations) {
selectDestination(destination);
}
return whenCapabilitiesDone;
})
.then(() => {
assertRecentDestinations(extraDestinations.map(dest => dest.id).reverse());
assertEquals(NUM_PERSISTED_DESTINATIONS, nativeLayer.getCallCount('getPrinterCapabilities'));
});
});
// Tests that disabling the Save as PDF destination hides the corresponding
// dropdown item.
test(assert(destination_settings_test.TestNames.DisabledSaveAsPdf), function () {
// Initialize destination settings with the PDF printer disabled.
pdfPrinterDisabled = true;
initialize();
return nativeLayer.whenCalled('getPrinterCapabilities')
.then(() => {
return waitBeforeNextRender(destinationSettings);
})
.then(() => {
// Because the 'Save as PDF' fallback is unavailable, the first
// destination is selected.
const expectedDestination =
//
//
makeLocalDestinationKey('ID1');
//
assertDropdownItems([expectedDestination]);
});
});
// Tests that disabling the 'Save as PDF' destination and exposing no
// printers to the native layer results in a 'No destinations' option in the
// dropdown.
test(assert(destination_settings_test.TestNames.NoDestinations), function () {
nativeLayer.setLocalDestinations([]);
// Initialize destination settings with the PDF printer disabled.
pdfPrinterDisabled = true;
isDriveMounted = false;
initialize();
// 'getPrinters' will be called because there are no printers known to
// the destination store and the 'Save as PDF' fallback is
// unavailable.
return Promise
.all([
nativeLayer.whenCalled('getPrinters'),
// TODO (rbpotter): remove this wait once user manager is fully
// removed.
waitBeforeNextRender(destinationSettings),
])
.then(() => assertDropdownItems(['noDestinations']));
});
//
});