feat(pagination): add types

This commit is contained in:
Joren Broekema 2020-09-30 12:15:56 +02:00 committed by Thomas Allmer
parent 278798636c
commit 0ed995ad06
4 changed files with 59 additions and 24 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/pagination': minor
---
Add types for pagination package.

View file

@ -1,11 +1,16 @@
import { LitElement, html, css } from '@lion/core';
import { LocalizeMixin } from '@lion/localize';
/**
* @typedef {import('lit-html').TemplateResult} TemplateResult
*/
/**
* `LionPagination` is a class for custom Pagination element (`<lion-pagination>` web component).
*
* @customElement lion-pagination
* @extends LitElement
*/
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110
export class LionPagination extends LocalizeMixin(LitElement) {
static get styles() {
return css`
@ -32,7 +37,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
static get localizeNamespaces() {
return [
{
'lion-pagination': locale => {
'lion-pagination': /** @param {string} locale */ locale => {
switch (locale) {
case 'bg-BG':
return import('../translations/bg.js');
@ -92,6 +97,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
};
}
/** @param {number} value */
set current(value) {
if (value !== this.current) {
const oldValue = this.current;
@ -101,8 +107,9 @@ export class LionPagination extends LocalizeMixin(LitElement) {
}
}
/** @returns {number} */
get current() {
return this.__current;
return this.__current || 0;
}
constructor() {
@ -144,6 +151,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
/**
* Go to the specific page
* @param {number} pageNumber
* @public
*/
goto(pageNumber) {
@ -175,7 +183,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
/**
* Calculate nav list based on current page selection.
* @returns {Array}
* @returns {(number|'...')[]}
* @private
*/
__calculateNavList() {
@ -190,29 +198,27 @@ export class LionPagination extends LocalizeMixin(LitElement) {
const pos5 = this.current + 1;
// if pos 3 is lower than 4 we have a predefined list of elements
if (pos4 <= 4) {
const list = Array(this.__visiblePages)
.fill()
.map((_, idx) => start + idx);
const list = /** @type {(number|'...')[]} */ ([...Array(this.__visiblePages)].map(
(_, idx) => start + idx,
));
list.push('...');
list.push(this.count);
return list;
}
// if we are close to the end of the list with the current page then we have again a predefined list
if (finish - pos4 <= 3) {
const list = [];
const list = /** @type {(number|'...')[]} */ ([]);
list.push(1);
list.push('...');
const listRemaining = Array(this.__visiblePages)
.fill()
.map((_, idx) => this.count - this.__visiblePages + 1 + idx);
const listRemaining = [...Array(this.__visiblePages)].map(
(_, idx) => this.count - this.__visiblePages + 1 + idx,
);
return list.concat(listRemaining);
}
return [start, '...', pos3, pos4, pos5, '...', finish];
}
return Array(finish - start + 1)
.fill()
.map((_, idx) => start + idx);
return [...Array(finish - start + 1)].map((_, idx) => start + idx);
}
/**
@ -266,7 +272,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
/**
* Render navigation list
* @returns {TemplateResult} nav list template
* @returns {TemplateResult[]} nav list template
* @protected
*/
_renderNavList() {

View file

@ -1,8 +1,15 @@
import { html, fixture, expect } from '@open-wc/testing';
import { html, fixture as _fixture, expect } from '@open-wc/testing';
import sinon from 'sinon';
import '../lion-pagination.js';
/**
* @typedef {import('../src/LionPagination').LionPagination} LionPagination
* @typedef {import('lit-html').TemplateResult} TemplateResult
*/
const fixture = /** @type {(arg: TemplateResult) => Promise<LionPagination>} */ (_fixture);
describe('Pagination', () => {
it('has states for count and current', async () => {
const el = await fixture(html` <lion-pagination count="4"></lion-pagination> `);
@ -17,34 +24,44 @@ describe('Pagination', () => {
it('disables the previous button if on first page', async () => {
const el = await fixture(html` <lion-pagination count="4"></lion-pagination> `);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
expect(buttons[0]).to.has.attribute('disabled');
});
it('disables the next button if on last page', async () => {
const el = await fixture(html` <lion-pagination count="4" current="4"></lion-pagination> `);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
expect(buttons[buttons.length - 1]).to.has.attribute('disabled');
});
describe('User interaction', () => {
it('can go to previous page with previous button', async () => {
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
buttons[0].click();
expect(el.current).to.equal(1);
});
it('can go to next page with next button', async () => {
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
buttons[buttons.length - 1].click();
expect(el.current).to.equal(3);
});
it('goes to the page when clicking on its button', async () => {
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
buttons[5].click();
expect(el.current).to.equal(5);
});
@ -54,7 +71,9 @@ describe('Pagination', () => {
const el = await fixture(html`
<lion-pagination count="6" current="2" @current-changed=${changeSpy}></lion-pagination>
`);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
const previous = buttons[0];
const next = buttons[buttons.length - 1];
const page5 = buttons[5];
@ -77,7 +96,9 @@ describe('Pagination', () => {
const el = await fixture(html`
<lion-pagination count="6" current="2" @current-changed=${changeSpy}></lion-pagination>
`);
const page2 = el.shadowRoot.querySelector("button[aria-current='true']");
const page2 = /** @type {HTMLElement} */ (el.shadowRoot?.querySelector(
"button[aria-current='true']",
));
page2.click();
expect(changeSpy).to.not.be.called;
expect(el.current).to.equal(2);
@ -111,7 +132,9 @@ describe('Pagination', () => {
describe('Accessibility', () => {
it('sets aria-current to the current page', async () => {
const el = await fixture(html` <lion-pagination count="3"></lion-pagination> `);
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
const buttons = Array.from(
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
);
// button[0] is the previous button
expect(buttons[1].getAttribute('aria-current')).to.equal('true');
expect(buttons[2].getAttribute('aria-current')).to.equal('false');

View file

@ -34,6 +34,7 @@
"packages/listbox/src/*.js",
"packages/localize/**/*.js",
"packages/overlays/**/*.js",
"packages/pagination/**/*.js",
"packages/radio-group/**/*.js",
"packages/singleton-manager/**/*.js",
"packages/tabs/**/*.js",