blob: de862397578ded6f84e88ae6a82a93f15a6acefc [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.
cr.define('pages_settings_test', function() {
/** @enum {string} */
const TestNames = {
PagesDropdown: 'pages dropdown',
ValidPageRanges: 'valid page ranges',
InvalidPageRanges: 'invalid page ranges',
NupChangesPages: 'nup changes pages',
ClearInput: 'clear input',
InputNotDisabledOnValidityChange: 'input not disabled on validity change',
EnterOnInputTriggersPrint: 'enter on input triggers print',
};
const suiteName = 'PagesSettingsTest';
suite(suiteName, function() {
/** @type {?PrintPreviewPagesSettingsElement} */
let pagesSection = null;
/** @type {!Array<number>} */
const oneToHundred = Array.from({length: 100}, (x, i) => i + 1);
/** @type {string} */
const limitError = 'Out of bounds page reference, limit is ';
/** @override */
setup(function() {
PolymerTest.clearBody();
const model = document.createElement('print-preview-model');
document.body.appendChild(model);
pagesSection = document.createElement('print-preview-pages-settings');
pagesSection.settings = model.settings;
pagesSection.disabled = false;
test_util.fakeDataBind(model, pagesSection, 'settings');
document.body.appendChild(pagesSection);
});
/**
* @param {string} inputString The input value to set.
* @return {!Promise} Promise that resolves when the input has been set and
* the input-change event has fired.
*/
function setCustomInput(inputString) {
const pagesInput = pagesSection.$.pageSettingsCustomInput.inputElement;
return print_preview_test_utils.triggerInputEvent(
pagesInput, inputString, pagesSection);
}
/**
* @param {!Array<number>} expectedPages The expected pages value.
* @param {!Array<{to: number, from: number>} expectedPages The expected
* pages value.
* @param {string} expectedError The expected error message.
* @param {boolean} invalid Whether the pages setting should be invalid.
*/
function validateState(
expectedPages, expectedRanges, expectedError, invalid) {
const pagesValue = pagesSection.getSettingValue('pages');
assertEquals(expectedPages.length, pagesValue.length);
expectedPages.forEach((page, index) => {
assertEquals(page, pagesValue[index]);
});
const rangesValue = pagesSection.getSettingValue('ranges');
assertEquals(expectedRanges.length, rangesValue.length);
expectedRanges.forEach((range, index) => {
assertEquals(range.to, rangesValue[index].to);
assertEquals(range.from, rangesValue[index].from);
});
assertEquals(!invalid, pagesSection.getSetting('pages').valid);
assertEquals(expectedError !== '', pagesSection.$$('cr-input').invalid);
assertEquals(expectedError, pagesSection.$$('cr-input').errorMessage);
}
// Verifies that the pages setting updates correctly when the dropdown
// changes.
test(assert(TestNames.PagesDropdown), async () => {
pagesSection.pageCount = 3;
// Default value is all pages.
const pagesSelect = pagesSection.$$('select');
const customInputCollapse = pagesSection.$$('iron-collapse');
const pagesCrInput = pagesSection.$.pageSettingsCustomInput;
const pagesInput = pagesCrInput.inputElement;
validateState([1, 2, 3], [], '', false);
assertFalse(customInputCollapse.opened);
// Set selection of pages 1 and 2.
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString());
assertTrue(customInputCollapse.opened);
await setCustomInput('1-2');
validateState([1, 2], [{from: 1, to: 2}], '', false);
// Re-select "all".
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.ALL.toString());
assertFalse(customInputCollapse.opened);
validateState([1, 2, 3], [], '', false);
// Re-select custom. The previously entered value should be
// restored.
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString());
assertTrue(customInputCollapse.opened);
validateState([1, 2], [{from: 1, to: 2}], '', false);
});
// Tests that the page ranges set are valid for different user inputs.
test(assert(TestNames.ValidPageRanges), async () => {
pagesSection.pageCount = 100;
const tenToHundred = Array.from({length: 91}, (x, i) => i + 10);
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString());
await setCustomInput('1, 2, 3, 1, 56');
validateState(
[1, 2, 3, 56], [{from: 1, to: 3}, {from: 56, to: 56}], '', false);
await setCustomInput('1-3, 6-9, 6-10');
validateState(
[1, 2, 3, 6, 7, 8, 9, 10], [{from: 1, to: 3}, {from: 6, to: 10}], '',
false);
await setCustomInput('10-');
validateState(tenToHundred, [{from: 10, to: 100}], '', false);
await setCustomInput('10-100');
validateState(tenToHundred, [{from: 10, to: 100}], '', false);
await setCustomInput('-');
validateState(oneToHundred, [{from: 1, to: 100}], '', false);
// https://crbug.com/806165
await setCustomInput('1\u30012\u30013\u30011\u300156');
validateState(
[1, 2, 3, 56], [{from: 1, to: 3}, {from: 56, to: 56}], '', false);
await setCustomInput('1,2,3\u30011\u300156');
validateState(
[1, 2, 3, 56], [{from: 1, to: 3}, {from: 56, to: 56}], '', false);
});
// Tests that the correct error messages are shown for different user
// inputs.
test(assert(TestNames.InvalidPageRanges), async () => {
pagesSection.pageCount = 100;
const syntaxError = 'Invalid page range, use e.g. 1-5, 8, 11-13';
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString());
await setCustomInput('10-100000');
validateState(oneToHundred, [], limitError + '100', true);
await setCustomInput('1, 2, 0, 56');
validateState(oneToHundred, [], syntaxError, true);
await setCustomInput('-1, 1, 2,, 56');
validateState(oneToHundred, [], syntaxError, true);
await setCustomInput('1,2,56-40');
validateState(oneToHundred, [], syntaxError, true);
await setCustomInput('101-110');
validateState(oneToHundred, [], limitError + '100', true);
await setCustomInput('1\u30012\u30010\u300156');
validateState(oneToHundred, [], syntaxError, true);
await setCustomInput('-1,1,2\u3001\u300156');
validateState(oneToHundred, [], syntaxError, true);
await setCustomInput('--');
validateState(oneToHundred, [], syntaxError, true);
await setCustomInput(' 1 1 ');
validateState(oneToHundred, [], syntaxError, true);
});
// Tests that the pages are set correctly for different values of pages per
// sheet, and that ranges remain fixed (since they are used for generating
// the print preview ticket).
test(assert(TestNames.NupChangesPages), async () => {
pagesSection.pageCount = 100;
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString());
await setCustomInput('1, 2, 3, 1, 56');
let expectedRanges = [{from: 1, to: 3}, {from: 56, to: 56}];
validateState([1, 2, 3, 56], expectedRanges, '', false);
pagesSection.setSetting('pagesPerSheet', 2);
validateState([1, 2], expectedRanges, '', false);
pagesSection.setSetting('pagesPerSheet', 4);
validateState([1], expectedRanges, '', false);
pagesSection.setSetting('pagesPerSheet', 1);
await setCustomInput('1-3, 6-9, 6-10');
expectedRanges = [{from: 1, to: 3}, {from: 6, to: 10}];
validateState([1, 2, 3, 6, 7, 8, 9, 10], expectedRanges, '', false);
pagesSection.setSetting('pagesPerSheet', 2);
validateState([1, 2, 3, 4], expectedRanges, '', false);
pagesSection.setSetting('pagesPerSheet', 3);
validateState([1, 2, 3], expectedRanges, '', false);
await setCustomInput('1-3');
expectedRanges = [{from: 1, to: 3}];
validateState([1], expectedRanges, '', false);
pagesSection.setSetting('pagesPerSheet', 1);
validateState([1, 2, 3], expectedRanges, '', false);
});
// Note: Remaining tests in this file are interactive_ui_tests, and validate
// some focus related behavior.
// Tests that the clearing a valid input has no effect, clearing an invalid
// input does not show an error message but does not reset the preview, and
// changing focus from an empty input in either case fills in the dropdown
// with the full page range.
test(assert(TestNames.ClearInput), async () => {
pagesSection.pageCount = 3;
const input = pagesSection.$.pageSettingsCustomInput.inputElement;
const select = pagesSection.$$('select');
const allValue = pagesSection.pagesValueEnum_.ALL.toString();
const customValue = pagesSection.pagesValueEnum_.CUSTOM.toString();
assertEquals(allValue, select.value);
// Selecting custom focuses the input.
await Promise.all([
print_preview_test_utils.selectOption(pagesSection, customValue),
test_util.eventToPromise('focus', input)
]);
input.focus();
await setCustomInput('1-2');
assertEquals(customValue, select.value);
validateState([1, 2], [{from: 1, to: 2}], '', false);
await setCustomInput('');
assertEquals(customValue, select.value);
validateState([1, 2], [{from: 1, to: 2}], '', false);
let whenBlurred = test_util.eventToPromise('blur', input);
input.blur();
await whenBlurred;
// Blurring a blank field sets the full page range.
assertEquals(customValue, select.value);
validateState([1, 2, 3], [{from: 1, to: 3}], '', false);
assertEquals('1-3', input.value);
input.focus();
await setCustomInput('5');
assertEquals(customValue, select.value);
// Invalid input doesn't change the preview.
validateState([1, 2, 3], [{from: 1, to: 3}], limitError + '3', true);
await setCustomInput('');
assertEquals(customValue, select.value);
validateState([1, 2, 3], [{from: 1, to: 3}], '', false);
whenBlurred = test_util.eventToPromise('blur', input);
input.blur();
// Blurring an invalid value that has been cleared should reset the
// value to all pages.
await whenBlurred;
assertEquals(customValue, select.value);
validateState([1, 2, 3], [{from: 1, to: 3}], '', false);
assertEquals('1-3', input.value);
// Re-focus and clear the input and then select "All" in the
// dropdown.
input.focus();
await setCustomInput('', 3);
select.focus();
await print_preview_test_utils.selectOption(pagesSection, allValue);
Polymer.dom.flush();
assertEquals(allValue, select.value);
validateState([1, 2, 3], [], '', false);
// Reselect custom. This should focus the input.
await Promise.all([
print_preview_test_utils.selectOption(pagesSection, customValue),
test_util.eventToPromise('focus', input),
]);
// Input has been cleared.
assertEquals('', input.value);
validateState([1, 2, 3], [], '', false);
});
// Verifies that the input is never disabled when the validity of the
// setting changes.
test(assert(TestNames.InputNotDisabledOnValidityChange), async () => {
pagesSection.pageCount = 3;
// In the real UI, the print preview app listens for this event from this
// section and others and sets disabled to true if any change from true to
// false is detected. Imitate this here. Since we are only interacting
// with the pages input, at no point should the input be disabled, as it
// will lose focus.
pagesSection.addEventListener('setting-valid-changed', function(e) {
assertFalse(pagesSection.$.pageSettingsCustomInput.disabled);
pagesSection.set('disabled', !e.detail);
assertFalse(pagesSection.$.pageSettingsCustomInput.disabled);
});
const input = pagesSection.$.pageSettingsCustomInput.inputElement;
await print_preview_test_utils.selectOption(
pagesSection, pagesSection.pagesValueEnum_.CUSTOM.toString());
await setCustomInput('1');
validateState([1], [{from: 1, to: 1}], '', false);
await setCustomInput('12');
validateState([1], [{from: 1, to: 1}], limitError + '3', true);
// Restore valid input
await setCustomInput('1');
validateState([1], [{from: 1, to: 1}], '', false);
// Invalid input again
await setCustomInput('8');
validateState([1], [{from: 1, to: 1}], limitError + '3', true);
// Clear input
await setCustomInput('');
validateState([1], [{from: 1, to: 1}], '', false);
// Set valid input
await setCustomInput('2');
validateState([2], [{from: 2, to: 2}], '', false);
});
// Verifies that the enter key event is bubbled to the pages settings
// element, so that it will be bubbled to the print preview app to trigger a
// print.
test(assert(TestNames.EnterOnInputTriggersPrint), async () => {
pagesSection.pageCount = 3;
const input = pagesSection.$.pageSettingsCustomInput.inputElement;
const whenPrintReceived =
test_util.eventToPromise('keydown', pagesSection);
// Setup an empty input by selecting custom..
const customValue = pagesSection.pagesValueEnum_.CUSTOM.toString();
const pagesSelect = pagesSection.$$('select');
await Promise.all([
print_preview_test_utils.selectOption(pagesSection, customValue),
test_util.eventToPromise('focus', input)
]);
assertEquals(customValue, pagesSelect.value);
MockInteractions.keyEventOn(input, 'keydown', 13, [], 'Enter');
await whenPrintReceived;
// Keep custom selected, but pages to print should still be all.
assertEquals(customValue, pagesSelect.value);
validateState([1, 2, 3], [], '', false);
// Select a custom input of 1.
await setCustomInput('1');
assertEquals(customValue, pagesSelect.value);
const whenSecondPrintReceived =
test_util.eventToPromise('keydown', pagesSection);
MockInteractions.keyEventOn(input, 'keydown', 13, [], 'Enter');
await whenSecondPrintReceived;
assertEquals(customValue, pagesSelect.value);
validateState([1], [{from: 1, to: 1}], '', false);
});
});
return {
suiteName: suiteName,
TestNames: TestNames,
};
});