From fdb13b15356219f03a83fe0a08f22fd7343b8a52 Mon Sep 17 00:00:00 2001 From: Andrew Kazakov Date: Thu, 7 Nov 2024 13:36:17 +0300 Subject: [PATCH] fix(Pagination): ignore clicks if pagination button is disabled (#1415) --- .../src/Pagination/Pagination.test.ts | 68 +++++++++++++++++++ .../src/Pagination/PaginationFirst.vue | 7 +- .../src/Pagination/PaginationLast.vue | 7 +- .../src/Pagination/PaginationListItem.vue | 8 ++- .../src/Pagination/PaginationNext.vue | 7 +- .../src/Pagination/PaginationPrev.vue | 7 +- .../src/Pagination/story/_Pagination.vue | 37 ++++++---- 7 files changed, 118 insertions(+), 23 deletions(-) diff --git a/packages/radix-vue/src/Pagination/Pagination.test.ts b/packages/radix-vue/src/Pagination/Pagination.test.ts index d2506f0d9..8d140af7d 100644 --- a/packages/radix-vue/src/Pagination/Pagination.test.ts +++ b/packages/radix-vue/src/Pagination/Pagination.test.ts @@ -56,6 +56,74 @@ describe('given default Pagination', () => { }) }) +const ALL_PAGINATION_BUTTONS_AS_A_PROPS = { + first: { as: 'a' }, + prev: { as: 'a' }, + listItem: { as: 'a' }, + next: { as: 'a' }, + last: { as: 'a' }, +} + +describe('given Pagination with as buttons', () => { + let wrapper: VueWrapper> + + beforeEach(() => { + document.body.innerHTML = '' + wrapper = mount(Pagination, { attachTo: document.body, props: { ...ALL_PAGINATION_BUTTONS_AS_A_PROPS } }) + }) + + it('should pass axe accessibility tests', async () => { + expect(await axe(wrapper.element)).toHaveNoViolations() + }) + + it('should not unselect page 1 after clicking on Prev Page trigger', async () => { + await wrapper.find('[aria-label="Previous Page"]').trigger('click') + expect(wrapper.find('[aria-label="Page 1"]').attributes('data-selected')).toBe('true') + }) + + it('should not unselect last page after clicking on Next Page trigger', async () => { + await wrapper.find('[aria-label="Last Page"]').trigger('click') + const lastPageLabel = wrapper.find('[data-selected="true"]').attributes('aria-label') + await wrapper.find('[aria-label="Next Page"]').trigger('click') + expect(wrapper.find('[data-selected="true"]').attributes('aria-label')).toBe(lastPageLabel) + }) +}) + +describe('given Pagination with as buttons and disabled', () => { + let wrapper: VueWrapper> + + const INITIAL_PAGE = 2 // Do not set to first or last page + + beforeEach(async () => { + document.body.innerHTML = '' + wrapper = mount(Pagination, { attachTo: document.body, props: { ...ALL_PAGINATION_BUTTONS_AS_A_PROPS } }) + await wrapper.find(`[aria-label="Page ${INITIAL_PAGE}"]`).trigger('click') + wrapper.setProps({ root: { disabled: true } }) + }) + + it('should pass axe accessibility tests', async () => { + expect(await axe(wrapper.element)).toHaveNoViolations() + }) + + it('should ignore clicking on First Page trigger', async () => { + await wrapper.find('[aria-label="First Page"]').trigger('click') + + expect(wrapper.find('[data-selected="true"]').attributes('aria-label')).toBe(`Page ${INITIAL_PAGE}`) + }) + + it('should ignore clicking on Last Page trigger', async () => { + await wrapper.find('[aria-label="Last Page"]').trigger('click') + + expect(wrapper.find('[data-selected="true"]').attributes('aria-label')).toBe(`Page ${INITIAL_PAGE}`) + }) + + it('should ignore clicking on any non-selected page', async () => { + await wrapper.find('[aria-label="Page 1"]').trigger('click') + + expect(wrapper.find('[data-selected="true"]').attributes('aria-label')).toBe(`Page ${INITIAL_PAGE}`) + }) +}) + describe('given show-edges Pagination', () => { let wrapper: VueWrapper> diff --git a/packages/radix-vue/src/Pagination/PaginationFirst.vue b/packages/radix-vue/src/Pagination/PaginationFirst.vue index 453ff6504..83ba07038 100644 --- a/packages/radix-vue/src/Pagination/PaginationFirst.vue +++ b/packages/radix-vue/src/Pagination/PaginationFirst.vue @@ -6,6 +6,7 @@ export interface PaginationFirstProps extends PrimitiveProps {}