189 lines
6.4 KiB
TypeScript
189 lines
6.4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.dev/license
|
|
*/
|
|
|
|
import {$, browser, by, element, ElementFinder} from 'protractor';
|
|
import {logging} from 'selenium-webdriver';
|
|
|
|
describe('MatSlider', () => {
|
|
const getStandardSlider = () => element(by.id('standard-slider'));
|
|
const getDisabledSlider = () => element(by.id('disabled-slider'));
|
|
const getRangeSlider = () => element(by.id('range-slider'));
|
|
|
|
beforeEach(async () => await browser.get('/slider'));
|
|
|
|
describe('standard slider', async () => {
|
|
let slider: ElementFinder;
|
|
beforeEach(() => {
|
|
slider = getStandardSlider();
|
|
});
|
|
|
|
it('should update the value on click', async () => {
|
|
await setValueByClick(slider, 49);
|
|
expect(await getSliderValue(slider, Thumb.END)).toBe(49);
|
|
});
|
|
|
|
it('should update the value on slide', async () => {
|
|
await slideToValue(slider, 35, Thumb.END);
|
|
expect(await getSliderValue(slider, Thumb.END)).toBe(35);
|
|
});
|
|
|
|
it('should display the value indicator when focused', async () => {
|
|
await focusSliderThumb(slider, Thumb.END);
|
|
const rect: DOMRect = await browser.executeScript(
|
|
'return arguments[0].getBoundingClientRect();',
|
|
$('.mdc-slider__value-indicator'),
|
|
);
|
|
|
|
expect(rect.width).not.toBe(0);
|
|
expect(rect.height).not.toBe(0);
|
|
|
|
await browser.actions().mouseUp().perform();
|
|
});
|
|
|
|
it('should not cause passive event listener errors when changing the value', async () => {
|
|
// retrieving the logs clears the collection
|
|
await browser.manage().logs().get('browser');
|
|
await setValueByClick(slider, 15);
|
|
|
|
expect(await browser.manage().logs().get('browser')).not.toContain(
|
|
jasmine.objectContaining({level: logging.Level.SEVERE}),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('disabled slider', async () => {
|
|
let slider: ElementFinder;
|
|
beforeEach(() => {
|
|
slider = getDisabledSlider();
|
|
});
|
|
|
|
it('should not update the value on click', async () => {
|
|
await setValueByClick(slider, 15);
|
|
expect(await getSliderValue(slider, Thumb.END)).not.toBe(15);
|
|
});
|
|
|
|
it('should not update the value on slide', async () => {
|
|
await slideToValue(slider, 35, Thumb.END);
|
|
expect(await getSliderValue(slider, Thumb.END)).not.toBe(35);
|
|
});
|
|
});
|
|
|
|
describe('range slider', async () => {
|
|
let slider: ElementFinder;
|
|
beforeEach(() => {
|
|
slider = getRangeSlider();
|
|
});
|
|
|
|
it('should update the start thumb value on slide', async () => {
|
|
await slideToValue(slider, 35, Thumb.START);
|
|
expect(await getSliderValue(slider, Thumb.START)).toBe(35);
|
|
});
|
|
|
|
it('should update the end thumb value on slide', async () => {
|
|
await slideToValue(slider, 55, Thumb.END);
|
|
expect(await getSliderValue(slider, Thumb.END)).toBe(55);
|
|
});
|
|
|
|
it(
|
|
'should update the start thumb value on click between thumbs ' +
|
|
'but closer to the start thumb',
|
|
async () => {
|
|
await setValueByClick(slider, 49);
|
|
expect(await getSliderValue(slider, Thumb.START)).toBe(49);
|
|
expect(await getSliderValue(slider, Thumb.END)).toBe(100);
|
|
},
|
|
);
|
|
|
|
it(
|
|
'should update the end thumb value on click between thumbs ' + 'but closer to the end thumb',
|
|
async () => {
|
|
await setValueByClick(slider, 51);
|
|
expect(await getSliderValue(slider, Thumb.START)).toBe(0);
|
|
expect(await getSliderValue(slider, Thumb.END)).toBe(51);
|
|
},
|
|
);
|
|
});
|
|
});
|
|
|
|
/** Returns the current value of the slider. */
|
|
async function getSliderValue(slider: ElementFinder, thumbPosition: Thumb): Promise<number> {
|
|
const inputs = await slider.all(by.css('.mdc-slider__input'));
|
|
return thumbPosition === Thumb.END
|
|
? Number(await inputs[inputs.length - 1].getAttribute('value'))
|
|
: Number(await inputs[0].getAttribute('value'));
|
|
}
|
|
|
|
/** Focuses on the MatSlider at the coordinates corresponding to the given thumb. */
|
|
async function focusSliderThumb(slider: ElementFinder, thumbPosition: Thumb): Promise<void> {
|
|
const webElement = await slider.getWebElement();
|
|
const coords = await getCoordsForValue(slider, await getSliderValue(slider, thumbPosition));
|
|
return await browser.actions().mouseMove(webElement, coords).mouseDown().perform();
|
|
}
|
|
|
|
/** Clicks on the MatSlider at the coordinates corresponding to the given value. */
|
|
async function setValueByClick(slider: ElementFinder, value: number): Promise<void> {
|
|
return clickElementAtPoint(slider, await getCoordsForValue(slider, value));
|
|
}
|
|
|
|
/** Clicks on the MatSlider at the coordinates corresponding to the given value. */
|
|
async function slideToValue(
|
|
slider: ElementFinder,
|
|
value: number,
|
|
thumbPosition: Thumb,
|
|
): Promise<void> {
|
|
const webElement = await slider.getWebElement();
|
|
const startCoords = await getCoordsForValue(slider, await getSliderValue(slider, thumbPosition));
|
|
const endCoords = await getCoordsForValue(slider, value);
|
|
return await browser
|
|
.actions()
|
|
.mouseMove(webElement, startCoords)
|
|
.mouseDown()
|
|
.mouseMove(webElement, endCoords)
|
|
.mouseUp()
|
|
.perform();
|
|
}
|
|
|
|
/** Returns the x and y coordinates for the given slider value. */
|
|
async function getCoordsForValue(slider: ElementFinder, value: number): Promise<Point> {
|
|
const inputs = await slider.all(by.css('.mdc-slider__input'));
|
|
|
|
const min = Number(await inputs[0].getAttribute('min'));
|
|
const max = Number(await inputs[inputs.length - 1].getAttribute('max'));
|
|
const percent = (value - min) / (max - min);
|
|
|
|
const {width, height} = await slider.getSize();
|
|
|
|
// NOTE: We use Math.round here because protractor silently breaks if you pass in an imprecise
|
|
// floating point number with lots of decimals. This allows us to avoid the headache but it may
|
|
// cause some innaccuracies in places where these decimals mean the difference between values.
|
|
|
|
const x = Math.round(width * percent);
|
|
const y = Math.round(height / 2);
|
|
|
|
return {x, y};
|
|
}
|
|
|
|
enum Thumb {
|
|
START = 1,
|
|
END = 2,
|
|
}
|
|
|
|
interface Point {
|
|
x: number;
|
|
y: number;
|
|
}
|
|
|
|
/**
|
|
* Clicks an element at a specific point. Useful if there's another element
|
|
* that covers part of the target and can catch the click.
|
|
*/
|
|
async function clickElementAtPoint(target: ElementFinder, coords: Point) {
|
|
const webElement = await target.getWebElement();
|
|
await browser.actions().mouseMove(webElement, coords).click().perform();
|
|
}
|