diff --git a/cypress/component/Table.cy.tsx b/cypress/component/Table.cy.tsx
new file mode 100644
index 0000000000..9991e6ae99
--- /dev/null
+++ b/cypress/component/Table.cy.tsx
@@ -0,0 +1,60 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 - present Instructure, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import React from 'react'
+import '../support/component'
+import 'cypress-real-events'
+
+import { Table } from '../../packages/ui'
+
+describe('
', () =>
+ it('can render table head as a combobox when in stacked layout', async () => {
+ const sortFoo = cy.stub()
+ cy.mount(
+
+
+
+
+ Foo
+
+
+ Bar
+
+
+
+
+
+
+
+
+ )
+
+ const input = cy.get('input[role="combobox"]')
+
+ input.click()
+
+ cy.get('[role="option"]').first().click()
+
+ cy.wrap(sortFoo).should('have.been.calledOnce')
+ }))
diff --git a/package-lock.json b/package-lock.json
index f67d379cac..d61692c0fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10679,14 +10679,13 @@
}
},
"node_modules/@vitest/expect": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.2.tgz",
- "integrity": "sha512-nKAvxBYqcDugYZ4nJvnm5OR8eDJdgWjk4XM9owQKUjzW70q0icGV2HVnQOyYsp906xJaBDUXw0+9EHw2T8e0mQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.4.tgz",
+ "integrity": "sha512-39jr5EguIoanChvBqe34I8m1hJFI4+jxvdOpD7gslZrVQBKhh8H9eD7J/LJX4zakrw23W+dITQTDqdt43xVcJw==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@vitest/spy": "2.0.2",
- "@vitest/utils": "2.0.2",
+ "@vitest/spy": "2.0.4",
+ "@vitest/utils": "2.0.4",
"chai": "^5.1.1",
"tinyrainbow": "^1.2.0"
},
@@ -10699,7 +10698,6 @@
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
"integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=12"
}
@@ -10709,7 +10707,6 @@
"resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz",
"integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"assertion-error": "^2.0.1",
"check-error": "^2.1.1",
@@ -10726,7 +10723,6 @@
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
"integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 16"
}
@@ -10736,7 +10732,6 @@
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
"integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -10746,7 +10741,6 @@
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz",
"integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"get-func-name": "^2.0.1"
}
@@ -10756,17 +10750,15 @@
"resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
"integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">= 14.16"
}
},
"node_modules/@vitest/pretty-format": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.2.tgz",
- "integrity": "sha512-SBCyOXfGVvddRd9r2PwoVR0fonQjh9BMIcBMlSzbcNwFfGr6ZhOhvBzurjvi2F4ryut2HcqiFhNeDVGwru8tLg==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.4.tgz",
+ "integrity": "sha512-RYZl31STbNGqf4l2eQM1nvKPXE0NhC6Eq0suTTePc4mtMQ1Fn8qZmjV4emZdEdG2NOWGKSCrHZjmTqDCDoeFBw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"tinyrainbow": "^1.2.0"
},
@@ -10775,13 +10767,12 @@
}
},
"node_modules/@vitest/runner": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.2.tgz",
- "integrity": "sha512-OCh437Vi8Wdbif1e0OvQcbfM3sW4s2lpmOjAE7qfLrpzJX2M7J1IQlNvEcb/fu6kaIB9n9n35wS0G2Q3en5kHg==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.0.4.tgz",
+ "integrity": "sha512-Gk+9Su/2H2zNfNdeJR124gZckd5st4YoSuhF1Rebi37qTXKnqYyFCd9KP4vl2cQHbtuVKjfEKrNJxHHCW8thbQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@vitest/utils": "2.0.2",
+ "@vitest/utils": "2.0.4",
"pathe": "^1.1.2"
},
"funding": {
@@ -10789,13 +10780,12 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.2.tgz",
- "integrity": "sha512-Yc2ewhhZhx+0f9cSUdfzPRcsM6PhIb+S43wxE7OG0kTxqgqzo8tHkXFuFlndXeDMp09G3sY/X5OAo/RfYydf1g==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.0.4.tgz",
+ "integrity": "sha512-or6Mzoz/pD7xTvuJMFYEtso1vJo1S5u6zBTinfl+7smGUhqybn6VjzCDMhmTyVOFWwkCMuNjmNNxnyXPgKDoPw==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.0.2",
+ "@vitest/pretty-format": "2.0.4",
"magic-string": "^0.30.10",
"pathe": "^1.1.2"
},
@@ -10804,11 +10794,10 @@
}
},
"node_modules/@vitest/spy": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.2.tgz",
- "integrity": "sha512-MgwJ4AZtCgqyp2d7WcQVE8aNG5vQ9zu9qMPYQHjsld/QVsrvg78beNrXdO4HYkP0lDahCO3P4F27aagIag+SGQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.4.tgz",
+ "integrity": "sha512-uTXU56TNoYrTohb+6CseP8IqNwlNdtPwEO0AWl+5j7NelS6x0xZZtP0bDWaLvOfUbaYwhhWp1guzXUxkC7mW7Q==",
"dev": true,
- "license": "MIT",
"dependencies": {
"tinyspy": "^3.0.0"
},
@@ -10817,13 +10806,12 @@
}
},
"node_modules/@vitest/utils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.2.tgz",
- "integrity": "sha512-pxCY1v7kmOCWYWjzc0zfjGTA3Wmn8PKnlPvSrsA643P1NHl1fOyXj2Q9SaNlrlFE+ivCsxM80Ov3AR82RmHCWQ==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.4.tgz",
+ "integrity": "sha512-Zc75QuuoJhOBnlo99ZVUkJIuq4Oj0zAkrQ2VzCqNCx6wAwViHEh5Fnp4fiJTE9rA+sAoXRf00Z9xGgfEzV6fzQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "2.0.2",
+ "@vitest/pretty-format": "2.0.4",
"estree-walker": "^3.0.3",
"loupe": "^3.1.1",
"tinyrainbow": "^1.2.0"
@@ -10837,7 +10825,6 @@
"resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz",
"integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==",
"dev": true,
- "license": "MIT",
"dependencies": {
"get-func-name": "^2.0.1"
}
@@ -35889,7 +35876,6 @@
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
"integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@@ -35899,7 +35885,6 @@
"resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.0.tgz",
"integrity": "sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=14.0.0"
}
@@ -37413,11 +37398,10 @@
}
},
"node_modules/vite-node": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.2.tgz",
- "integrity": "sha512-w4vkSz1Wo+NIQg8pjlEn0jQbcM/0D+xVaYjhw3cvarTanLLBh54oNiRbsT8PNK5GfuST0IlVXjsNRoNlqvY/fw==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.0.4.tgz",
+ "integrity": "sha512-ZpJVkxcakYtig5iakNeL7N3trufe3M6vGuzYAr4GsbCTwobDeyPJpE4cjDhhPluv8OvQCFzu2LWp6GkoKRITXA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"cac": "^6.7.14",
"debug": "^4.3.5",
@@ -37842,19 +37826,18 @@
}
},
"node_modules/vitest": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.2.tgz",
- "integrity": "sha512-WlpZ9neRIjNBIOQwBYfBSr0+of5ZCbxT2TVGKW4Lv0c8+srCFIiRdsP7U009t8mMn821HQ4XKgkx5dVWpyoyLw==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.0.4.tgz",
+ "integrity": "sha512-luNLDpfsnxw5QSW4bISPe6tkxVvv5wn2BBs/PuDRkhXZ319doZyLOBr1sjfB5yCEpTiU7xCAdViM8TNVGPwoog==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
- "@vitest/expect": "2.0.2",
- "@vitest/pretty-format": "^2.0.2",
- "@vitest/runner": "2.0.2",
- "@vitest/snapshot": "2.0.2",
- "@vitest/spy": "2.0.2",
- "@vitest/utils": "2.0.2",
+ "@vitest/expect": "2.0.4",
+ "@vitest/pretty-format": "^2.0.4",
+ "@vitest/runner": "2.0.4",
+ "@vitest/snapshot": "2.0.4",
+ "@vitest/spy": "2.0.4",
+ "@vitest/utils": "2.0.4",
"chai": "^5.1.1",
"debug": "^4.3.5",
"execa": "^8.0.1",
@@ -37865,8 +37848,8 @@
"tinypool": "^1.0.0",
"tinyrainbow": "^1.2.0",
"vite": "^5.0.0",
- "vite-node": "2.0.2",
- "why-is-node-running": "^2.2.2"
+ "vite-node": "2.0.4",
+ "why-is-node-running": "^2.3.0"
},
"bin": {
"vitest": "vitest.mjs"
@@ -37880,8 +37863,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "2.0.2",
- "@vitest/ui": "2.0.2",
+ "@vitest/browser": "2.0.4",
+ "@vitest/ui": "2.0.4",
"happy-dom": "*",
"jsdom": "*"
},
@@ -38907,9 +38890,9 @@
}
},
"node_modules/why-is-node-running": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz",
- "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
"dependencies": {
"siginfo": "^2.0.0",
@@ -47536,15 +47519,72 @@
"prop-types": "^15.8.1"
},
"devDependencies": {
+ "@instructure/ui-axe-check": "9.5.0",
"@instructure/ui-babel-preset": "9.5.0",
"@instructure/ui-color-utils": "9.5.0",
"@instructure/ui-test-utils": "9.5.0",
- "@instructure/ui-themes": "9.5.0"
+ "@instructure/ui-themes": "9.5.0",
+ "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "vitest": "^2.0.2"
},
"peerDependencies": {
"react": ">=16.8 <=18"
}
},
+ "packages/ui-table/node_modules/@testing-library/dom": {
+ "version": "10.3.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.2.tgz",
+ "integrity": "sha512-0bxIdP9mmPiOJ6wHLj8bdJRq+51oddObeCGdEf6PNEhYd93ZYAN+lPRnEOVFtheVwDM7+p+tza3LAQgp0PTudg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "packages/ui-table/node_modules/@testing-library/react": {
+ "version": "15.0.7",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz",
+ "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@testing-library/dom": "^10.0.0",
+ "@types/react-dom": "^18.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "packages/ui-table/node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"packages/ui-tabs": {
"name": "@instructure/ui-tabs",
"version": "9.5.0",
diff --git a/packages/ui-table/package.json b/packages/ui-table/package.json
index d7987201ff..954539ddd4 100644
--- a/packages/ui-table/package.json
+++ b/packages/ui-table/package.json
@@ -23,10 +23,15 @@
},
"license": "MIT",
"devDependencies": {
+ "@instructure/ui-axe-check": "9.5.0",
"@instructure/ui-babel-preset": "9.5.0",
"@instructure/ui-color-utils": "9.5.0",
"@instructure/ui-test-utils": "9.5.0",
- "@instructure/ui-themes": "9.5.0"
+ "@instructure/ui-themes": "9.5.0",
+ "@testing-library/jest-dom": "^6.4.6",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "vitest": "^2.0.2"
},
"dependencies": {
"@babel/runtime": "^7.24.5",
diff --git a/packages/ui-table/src/Table/__tests__/Table.test.tsx b/packages/ui-table/src/Table/__new-tests__/Table.test.tsx
similarity index 54%
rename from packages/ui-table/src/Table/__tests__/Table.test.tsx
rename to packages/ui-table/src/Table/__new-tests__/Table.test.tsx
index b99bb2f3ff..799c2bab27 100644
--- a/packages/ui-table/src/Table/__tests__/Table.test.tsx
+++ b/packages/ui-table/src/Table/__new-tests__/Table.test.tsx
@@ -23,113 +23,136 @@
*/
import React from 'react'
-import { expect, mount, stub, find, within } from '@instructure/ui-test-utils'
-//TODO
-/* eslint-disable no-restricted-imports */
-// @ts-ignore: Cannot find module
-import { SimpleSelectLocator } from '@instructure/ui-simple-select/es/SimpleSelect/SimpleSelectLocator'
+import { render, screen, waitFor } from '@testing-library/react'
+import { vi } from 'vitest'
+import { userEvent } from '@testing-library/user-event'
+import '@testing-library/jest-dom'
+
import { Table } from '../index'
import type { TableProps } from '../props'
import type { TableColHeaderProps } from '../ColHeader/props'
+import { runAxeCheck } from '@instructure/ui-axe-check'
+
describe('', async () => {
- const render = (props?: TableProps) =>
- mount(
+ let consoleErrorMock: any
+
+ beforeEach(() => {
+ // Mocking console to prevent test output pollution
+ consoleErrorMock = vi.spyOn(console, 'error').mockImplementation(() => {})
+ })
+
+ afterEach(() => {
+ consoleErrorMock.mockRestore()
+ })
+
+ const renderTable = (props?: TableProps) =>
+ render(
- Foo
- Bar
+ ColHeader
+ Bar-header
- foo
- bar
+ RowHeader
+ Cell
)
it('should render a caption', async () => {
- await render()
- const table = await find('table')
+ const { container } = renderTable()
+ const caption = container.querySelector('caption')
- expect(await table.find('caption:contains(Test table)')).to.exist()
+ expect(caption).toBeInTheDocument()
+ expect(caption).toHaveTextContent('Test table')
})
it('should meet a11y standards', async () => {
- await render()
- const table = await find('table')
- expect(await table.accessible()).to.be.true()
+ const { container } = renderTable()
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
})
it('applies a fixed column layout', async () => {
- await render({
+ await renderTable({
layout: 'fixed'
})
- const table = await find('table')
- const tableNode = within(table.getDOMNode())
+ const table = screen.getByRole('table')
- expect(tableNode.getComputedStyle().tableLayout).to.equal('fixed')
+ expect(table).toHaveStyle({ tableLayout: 'fixed' })
})
it('passes hover to table row', async () => {
- await render({
+ renderTable({
hover: true
})
- const tr = await find('tbody tr')
- const trNode = within(tr.getDOMNode())
+ const tableRows = screen.getAllByRole('row')
- expect(trNode.getComputedStyle().borderLeftStyle).to.not.equal('none')
- expect(trNode.getComputedStyle().borderRightStyle).to.not.equal('none')
+ tableRows.forEach((tableRow) => {
+ expect(tableRow).not.toHaveAttribute('border-left', 'none')
+ expect(tableRow).not.toHaveAttribute('border-right', 'none')
+ })
})
it('sets the scope of column header to col', async () => {
- await render()
- const th = await find('thead th')
- const thNode = within(th.getDOMNode())
+ await renderTable()
+ const columnHeaders = screen.getAllByRole('columnheader')
- expect(thNode.getAttribute('scope')).to.equal('col')
+ columnHeaders.forEach((columnHeader) => {
+ expect(columnHeader).toHaveAttribute('scope', 'col')
+ })
})
it('sets the scope of row header to row', async () => {
- await render()
- const th = await find('tbody th')
- const thNode = within(th.getDOMNode())
+ renderTable()
+ const rowHeaders = screen.getAllByRole('rowheader')
- expect(thNode.getAttribute('scope')).to.equal('row')
+ rowHeaders.forEach((rowHeader) => {
+ expect(rowHeader).toHaveAttribute('scope', 'row')
+ })
})
it('can render table in stacked layout', async () => {
- const stackedTable = await render({
+ renderTable({
layout: 'stacked'
})
+ const stackedTable = screen.getByRole('table')
- expect(stackedTable).to.exist()
+ expect(stackedTable).toBeInTheDocument()
+ expect(stackedTable).toHaveTextContent('RowHeader')
+ expect(stackedTable).toHaveTextContent('Cell')
+ expect(stackedTable).not.toHaveTextContent('ColHeader')
})
it('can handle non-existent head in stacked layout', async () => {
- const stackedTable = await mount(
+ render(
)
+ const stackedTable = screen.getByRole('table')
- expect(stackedTable).to.exist()
+ expect(stackedTable).toBeInTheDocument()
})
it('can handle empty head in stacked layout', async () => {
- const stackedTable = await mount(
+ render(
)
+ const stackedTable = screen.getByRole('table')
- expect(stackedTable).to.exist()
+ expect(stackedTable).toBeInTheDocument()
})
it('can handle invalid header in stacked layout', async () => {
- const stackedTable = await mount(
+ render(
@@ -138,8 +161,10 @@ describe('', async () => {
)
+ const stackedTable = screen.getByRole('table')
- expect(stackedTable).to.exist()
+ expect(stackedTable).toBeInTheDocument()
+ expect(stackedTable).not.toHaveTextContent('Foo')
})
describe('when table is sortable', async () => {
@@ -148,7 +173,7 @@ describe('', async () => {
handlers = {},
layout: TableProps['layout'] = 'auto'
) =>
- mount(
+ render(
@@ -168,29 +193,28 @@ describe('', async () => {
)
it('can render up arrow for ascending order', async () => {
- await renderSortableTable({
+ const { container } = renderSortableTable({
id: 'id',
sortDirection: 'ascending'
})
- const arrow = await find('svg[name="IconMiniArrowUp"]')
+ const arrow = container.querySelector('svg')
- expect(arrow).to.exist()
+ expect(arrow).toHaveAttribute('name', 'IconMiniArrowUp')
})
it('can render down arrow for descending order', async () => {
- await renderSortableTable({
+ const { container } = renderSortableTable({
id: 'id',
sortDirection: 'descending'
})
- const arrow = await find('svg[name="IconMiniArrowDown"]')
+ const arrow = container.querySelector('svg')
- expect(arrow).to.exist()
+ expect(arrow).toHaveAttribute('name', 'IconMiniArrowDown')
})
it('calls onRequestSort when column header is clicked', async () => {
- const onRequestSort = stub()
-
- await renderSortableTable(
+ const onRequestSort = vi.fn()
+ renderSortableTable(
{
id: 'id'
},
@@ -198,95 +222,72 @@ describe('', async () => {
onRequestSort
}
)
- const button = await find('th button')
-
- await button.click()
- expect(onRequestSort).to.have.been.calledOnce()
- })
-
- it('can render table head as a combobox when in stacked layout', async () => {
- const sortFoo = stub()
-
- await renderSortableTable(
- {
- id: 'id'
- },
- {
- onRequestSort: sortFoo
- },
- 'stacked'
- )
- const select = await SimpleSelectLocator.find()
- const input = await select.findInput()
+ const button = screen.getByRole('button', { name: 'Foo' })
- await input.click()
+ userEvent.click(button)
- const list = await select.findOptionsList()
- const options = await list.findAll('[role="option"]')
-
- await options[1].click()
- expect(sortFoo).to.have.been.calledOnce()
+ await waitFor(() => {
+ expect(onRequestSort).toHaveBeenCalledTimes(1)
+ })
})
it('can display custom label in the select in stacked layout', async () => {
- await renderSortableTable(
+ renderSortableTable(
{
id: 'id',
stackedSortByLabel: 'Custom Text'
},
{
- onRequestSort: stub()
+ onRequestSort: vi.fn()
},
'stacked'
)
- const select = await SimpleSelectLocator.find()
- const input = await select.findInput()
+ const input = screen.getByRole('combobox')
- await input.click()
+ userEvent.click(input)
- const list = await select.findOptionsList()
- const options = await list.findAll('[role="option"]')
+ await waitFor(async () => {
+ const options = screen.getAllByRole('option')
- // with stackedSortByLabel provided
- expect(options[0].text()).to.equal('Custom Text')
- // the id by default
- expect(options[1].text()).to.equal('bar')
+ expect(options[0]).toHaveTextContent('Custom Text')
+ expect(options[1]).toHaveTextContent('bar')
+ })
})
it('can render check mark for sorted column in stacked layout', async () => {
- await renderSortableTable(
+ const { container } = renderSortableTable(
{
id: 'id',
sortDirection: 'ascending'
},
{
- onRequestSort: stub()
+ onRequestSort: vi.fn()
},
'stacked'
)
- const icon = await find('svg[name="IconCheck"]')
+ const icon = container.querySelector('svg')
- expect(icon).to.exist()
+ expect(icon).toHaveAttribute('name', 'IconCheck')
})
it('creates proper aria-sort attributes (ascending)', async () => {
- await renderSortableTable({
+ renderSortableTable({
id: 'id',
sortDirection: 'ascending'
})
- const sortedHeader = await find('th[aria-sort="ascending"]')
+ const header = screen.getByRole('columnheader', { name: 'Foo' })
- expect(sortedHeader).to.exist()
+ expect(header).toHaveAttribute('aria-sort', 'ascending')
})
it('creates proper aria-sort attributes (descending)', async () => {
- await renderSortableTable({
+ renderSortableTable({
id: 'id',
sortDirection: 'descending'
})
- const sortedHeader = await find('th[aria-sort="descending"]')
+ const header = screen.getByRole('columnheader', { name: 'Foo' })
- expect(sortedHeader).to.exist()
+ expect(header).toHaveAttribute('aria-sort', 'descending')
})
})
})
diff --git a/packages/ui-table/tsconfig.build.json b/packages/ui-table/tsconfig.build.json
index 0ffd8f3545..795ebf6e1b 100644
--- a/packages/ui-table/tsconfig.build.json
+++ b/packages/ui-table/tsconfig.build.json
@@ -7,6 +7,7 @@
},
"include": ["src"],
"references": [
+ { "path": "../ui-axe-check/tsconfig.build.json" },
{ "path": "../ui-babel-preset/tsconfig.build.json" },
{ "path": "../ui-color-utils/tsconfig.build.json" },
{ "path": "../ui-test-utils/tsconfig.build.json" },