mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-23 17:08:34 +00:00
Added data-cy for table widget elements (#4792)
* Add data-cy to tooltip label * Add data-cy to table filter pop-over * Add data-cy to table elements * Add review changes
This commit is contained in:
parent
8824c00896
commit
1b270ab412
7 changed files with 85 additions and 23 deletions
|
|
@ -113,10 +113,12 @@ export function Filter(props) {
|
|||
<div className="table-filters card">
|
||||
<div className="card-header row">
|
||||
<div className="col">
|
||||
<h4 className="font-weight-normal">Filters</h4>
|
||||
<h4 data-cy={`header-filters`} className="font-weight-normal">
|
||||
Filters
|
||||
</h4>
|
||||
</div>
|
||||
<div className="col-auto">
|
||||
<button onClick={() => props.hideFilters()} className="btn btn-light btn-sm">
|
||||
<button data-cy={`button-close-filters`} onClick={() => props.hideFilters()} className="btn btn-light btn-sm">
|
||||
x
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -131,9 +133,9 @@ export function Filter(props) {
|
|||
{props.filters.map((filter, index) => (
|
||||
<div className="row mb-2" key={index}>
|
||||
<div className="col p-2" style={{ maxWidth: '70px' }}>
|
||||
<small>{index > 0 ? 'and' : 'column'}</small>
|
||||
<small data-cy={`label-filter-column`}>{index > 0 ? 'and' : 'column'}</small>
|
||||
</div>
|
||||
<div className="col">
|
||||
<div data-cy={`select-coloumn-dropdown-${index ?? ''}`} className="col">
|
||||
<Select
|
||||
options={props.columns}
|
||||
value={filter.id}
|
||||
|
|
@ -144,7 +146,7 @@ export function Filter(props) {
|
|||
styles={selectStyles('100%')}
|
||||
/>
|
||||
</div>
|
||||
<div className="col" style={{ maxWidth: '180px' }}>
|
||||
<div data-cy={`select-operation-dropdown-${index ?? ''}`} className="col" style={{ maxWidth: '180px' }}>
|
||||
<Select
|
||||
options={[
|
||||
{ name: 'contains', value: 'contains' },
|
||||
|
|
@ -168,11 +170,13 @@ export function Filter(props) {
|
|||
className={`${darkMode ? 'select-search-dark' : 'select-search'}`}
|
||||
placeholder={t('globals.select', 'Select') + '...'}
|
||||
styles={selectStyles('100%')}
|
||||
dataCy={`select-coloumn-dropdown-${index ?? ''}`}
|
||||
/>
|
||||
</div>
|
||||
<div className="col">
|
||||
{['isEmpty', 'isNotEmpty'].includes(filter.value.condition) || (
|
||||
<input
|
||||
data-cy={`data-filtervalue-input-${index ?? ''}`}
|
||||
type="text"
|
||||
value={filter.value.value}
|
||||
placeholder="value"
|
||||
|
|
@ -183,6 +187,7 @@ export function Filter(props) {
|
|||
</div>
|
||||
<div className="col-auto">
|
||||
<button
|
||||
data-cy={`button-close-filter-${index ?? ''}`}
|
||||
onClick={() => removeFilter(index)}
|
||||
className={`btn ${darkMode ? 'btn-dark' : 'btn-light'} btn-sm p-2 text-danger font-weight-bold`}
|
||||
>
|
||||
|
|
@ -194,16 +199,16 @@ export function Filter(props) {
|
|||
{props.filters.length === 0 && (
|
||||
<div>
|
||||
<center>
|
||||
<span>no filters yet.</span>
|
||||
<span data-cy={`label-no-filters`}>no filters yet.</span>
|
||||
</center>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="card-footer">
|
||||
<button onClick={addFilter} className="btn btn-light btn-sm">
|
||||
<button data-cy={`button-add-filter`} onClick={addFilter} className="btn btn-light btn-sm">
|
||||
+ add filter
|
||||
</button>
|
||||
<button onClick={() => clearFilters()} className="btn btn-light btn-sm mx-2">
|
||||
<button data-cy={`button-clear-filters`} onClick={() => clearFilters()} className="btn btn-light btn-sm mx-2">
|
||||
clear filters
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export const GlobalFilter = ({
|
|||
defaultValue={value || ''}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder="Search"
|
||||
data-cy="search-input-field"
|
||||
style={{
|
||||
border: '0',
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const IndeterminateCheckbox = React.forwardRef(({ indeterminate, ...rest }, ref)
|
|||
return (
|
||||
<>
|
||||
<input
|
||||
data-cy={`checkbox-input`}
|
||||
type="checkbox"
|
||||
ref={resolvedRef}
|
||||
style={{
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export const Pagination = function Pagination({
|
|||
<div className="pagination justify-content-start">
|
||||
{!serverSide && (
|
||||
<button
|
||||
data-cy={`pagination-button-to-first`}
|
||||
className={`btn btn-sm btn-light mx-2 ${pageIndex === 1 ? 'cursor-not-allowed' : ''}`}
|
||||
onClick={() => gotoPage(1)}
|
||||
disabled={pageIndex === 1}
|
||||
|
|
@ -58,13 +59,14 @@ export const Pagination = function Pagination({
|
|||
</button>
|
||||
)}
|
||||
<button
|
||||
data-cy={`pagination-button-to-previous`}
|
||||
className={`btn btn-sm btn-light ${pageIndex === 1 ? 'cursor-not-allowed' : ''}`}
|
||||
onClick={() => goToPreviousPage()}
|
||||
disabled={pageIndex === 1 || !enablePrevButton}
|
||||
>
|
||||
{'<'}
|
||||
</button>{' '}
|
||||
<small className="p-1 mx-2">
|
||||
<small className="p-1 mx-2" data-cy={`page-index-details`}>
|
||||
{serverSide && <strong>{pageIndex}</strong>}
|
||||
{!serverSide && (
|
||||
<strong>
|
||||
|
|
@ -73,6 +75,7 @@ export const Pagination = function Pagination({
|
|||
)}
|
||||
</small>
|
||||
<button
|
||||
data-cy={`pagination-button-to-next`}
|
||||
className={`btn btn-light btn-sm ${!autoCanNextPage && !serverSide ? 'cursor-not-allowed' : ''}`}
|
||||
onClick={() => goToNextPage()}
|
||||
disabled={(!autoCanNextPage && !serverSide) || !enableNextButton}
|
||||
|
|
@ -81,6 +84,7 @@ export const Pagination = function Pagination({
|
|||
</button>{' '}
|
||||
{!serverSide && (
|
||||
<button
|
||||
data-cy={`pagination-button-to-last`}
|
||||
className={`btn btn-light btn-sm mx-2 ${!autoCanNextPage && !serverSide ? 'cursor-not-allowed' : ''}`}
|
||||
onClick={() => gotoPage(pageCount)}
|
||||
disabled={!autoCanNextPage && !serverSide}
|
||||
|
|
|
|||
|
|
@ -533,10 +533,14 @@ export function Table({
|
|||
>
|
||||
<Popover.Content>
|
||||
<div className="d-flex flex-column">
|
||||
<span className="cursor-pointer" onClick={() => exportData('csv', true)}>
|
||||
<span data-cy={`option-download-CSV`} className="cursor-pointer" onClick={() => exportData('csv', true)}>
|
||||
Download as CSV
|
||||
</span>
|
||||
<span className="pt-2 cursor-pointer" onClick={() => exportData('xlsx', true)}>
|
||||
<span
|
||||
data-cy={`option-download-execel`}
|
||||
className="pt-2 cursor-pointer"
|
||||
onClick={() => exportData('xlsx', true)}
|
||||
>
|
||||
Download as Excel
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -602,20 +606,32 @@ export function Table({
|
|||
overlay={
|
||||
<Popover>
|
||||
<div
|
||||
data-cy={`dropdown-hide-column`}
|
||||
className={`dropdown-table-column-hide-common ${
|
||||
darkMode ? 'dropdown-table-column-hide-dark-themed' : 'dropdown-table-column-hide'
|
||||
} `}
|
||||
>
|
||||
<div className="dropdown-item">
|
||||
<IndeterminateCheckbox {...getToggleHideAllColumnsProps()} />
|
||||
<span className="hide-column-name"> Select All</span>
|
||||
<span className="hide-column-name" data-cy={`options-select-all-coloumn`}>
|
||||
Select All
|
||||
</span>
|
||||
</div>
|
||||
{allColumns.map((column) => (
|
||||
<div key={column.id}>
|
||||
<div>
|
||||
<label className="dropdown-item">
|
||||
<input type="checkbox" {...column.getToggleHiddenProps()} />
|
||||
<span className="hide-column-name"> {` ${column.Header}`}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
data-cy={`checkbox-coloumn-${String(column.Header).toLowerCase().replace(/\s+/g, '-')}`}
|
||||
{...column.getToggleHiddenProps()}
|
||||
/>
|
||||
<span
|
||||
className="hide-column-name"
|
||||
data-cy={`options-coloumn-${String(column.Header).toLowerCase().replace(/\s+/g, '-')}`}
|
||||
>
|
||||
{` ${column.Header}`}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -625,7 +641,7 @@ export function Table({
|
|||
}
|
||||
placement={'bottom-end'}
|
||||
>
|
||||
<span className={`btn btn-light btn-sm p-1 mb-0 mx-1 `}>
|
||||
<span data-cy={`select-column-icon`} className={`btn btn-light btn-sm p-1 mb-0 mx-1 `}>
|
||||
<IconEyeOff style={{ width: '15', height: '15', margin: '0px' }} />
|
||||
</span>
|
||||
</OverlayTrigger>
|
||||
|
|
@ -685,6 +701,9 @@ export function Table({
|
|||
}
|
||||
>
|
||||
<div
|
||||
data-cy={`column-header-${String(column.exportValue)
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')}`}
|
||||
{...column.getSortByToggleProps()}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
|
|
@ -782,6 +801,9 @@ export function Table({
|
|||
// Does not require key as its already being passed by react-table via cellProps
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<td
|
||||
data-cy={`${cell.column.columnType ?? ''}${String(
|
||||
cell.column.id === 'rightActions' || cell.column.id === 'leftActions' ? cell.column.id : ''
|
||||
)}${String(cellValue ?? '').toLocaleLowerCase()}-cell-${index}`}
|
||||
className={cx(`${wrapAction ? wrapAction : 'wrap'}-wrapper`, {
|
||||
'has-actions': cell.column.id === 'rightActions' || cell.column.id === 'leftActions',
|
||||
'has-text': cell.column.columnType === 'text' || cell.column.isEditable,
|
||||
|
|
@ -846,15 +868,20 @@ export function Table({
|
|||
handleChangesSaved();
|
||||
})
|
||||
}
|
||||
data-cy={`table-button-save-changes`}
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
<button className="btn btn-light btn-sm" onClick={() => handleChangesDiscarded()}>
|
||||
<button
|
||||
className="btn btn-light btn-sm"
|
||||
onClick={() => handleChangesDiscarded()}
|
||||
data-cy={`table-button-discard-changes`}
|
||||
>
|
||||
Discard changes
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<span>
|
||||
<span data-cy={`footer-number-of-records`}>
|
||||
{clientSidePagination && !serverSidePagination && `${globalFilteredRows.length} Records`}
|
||||
{serverSidePagination && totalRecords ? `${totalRecords} Records` : ''}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -666,8 +666,11 @@ class TableComponent extends React.Component {
|
|||
<Popover id="popover-basic" className={`${this.props.darkMode && 'popover-dark-themed theme-dark'} shadow`}>
|
||||
<Popover.Content>
|
||||
<div className="field mb-2">
|
||||
<label className="form-label">{this.props.t('widget.Table.buttonText', 'Button Text')}</label>
|
||||
<label data-cy={`label-action-button-text`} className="form-label">
|
||||
{this.props.t('widget.Table.buttonText', 'Button Text')}
|
||||
</label>
|
||||
<input
|
||||
data-cy={`action-button-text-input-field`}
|
||||
type="text"
|
||||
className="form-control text-field"
|
||||
onChange={(e) => {
|
||||
|
|
@ -677,8 +680,10 @@ class TableComponent extends React.Component {
|
|||
value={action.buttonText}
|
||||
/>
|
||||
</div>
|
||||
<div className="field mb-2">
|
||||
<label className="form-label">{this.props.t('widget.Table.buttonPosition', 'Button Position')}</label>
|
||||
<div className="field mb-2" data-cy={`dropdown-action-button-position`}>
|
||||
<label data-cy={`label-action-button-position`} className="form-label">
|
||||
{this.props.t('widget.Table.buttonPosition', 'Button Position')}
|
||||
</label>
|
||||
<SelectSearch
|
||||
className={`${this.props.darkMode ? 'select-search-dark' : 'select-search'}`}
|
||||
options={[
|
||||
|
|
@ -701,6 +706,7 @@ class TableComponent extends React.Component {
|
|||
componentMeta={this.state.componentMeta}
|
||||
definition={{ value: action.backgroundColor }}
|
||||
onChange={(name, value, color) => this.onActionButtonPropertyChanged(index, 'backgroundColor', color)}
|
||||
cyLabel={`action-button-bg`}
|
||||
/>
|
||||
|
||||
<Color
|
||||
|
|
@ -709,6 +715,7 @@ class TableComponent extends React.Component {
|
|||
componentMeta={this.state.componentMeta}
|
||||
definition={{ value: action.textColor }}
|
||||
onChange={(name, value, color) => this.onActionButtonPropertyChanged(index, 'textColor', color)}
|
||||
cyLabel={`action-button-text`}
|
||||
/>
|
||||
<EventManager
|
||||
component={dummyComponentForActionButton}
|
||||
|
|
@ -743,7 +750,14 @@ class TableComponent extends React.Component {
|
|||
<div className={`card p-2 mb-1 ${this.props.darkMode ? 'bg-secondary' : 'bg-light'}`} role="button">
|
||||
<div className={`row ${this.props.darkMode ? '' : 'bg-light'}`}>
|
||||
<div className="col-auto">
|
||||
<div className="text">{action.buttonText}</div>
|
||||
<div
|
||||
data-cy={`action-button-${String(action.buttonText ?? '')
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')}-${String(index ?? '')}`}
|
||||
className="text"
|
||||
>
|
||||
{action.buttonText}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -959,6 +973,7 @@ class TableComponent extends React.Component {
|
|||
<div className="row g-2">
|
||||
<div className="text-right mb-3">
|
||||
<button
|
||||
data-cy="button-add-new-action-button"
|
||||
onClick={this.addNewAction}
|
||||
className="btn btn-sm border-0 font-weight-normal padding-2 col-auto color-primary inspector-add-button"
|
||||
>
|
||||
|
|
@ -969,7 +984,7 @@ class TableComponent extends React.Component {
|
|||
<div>{actions.value.map((action, index) => this.actionButton(action, index))}</div>
|
||||
{actions.value.length === 0 && (
|
||||
<div className="text-center">
|
||||
<small className="color-disabled">
|
||||
<small data-cy="message-no-action-button" className="color-disabled">
|
||||
{this.props.t('widget.Table.noActionMessage', "This table doesn't have any action buttons")}
|
||||
</small>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,15 @@ export const ToolTip = ({ label, meta, labelClass }) => {
|
|||
</OverlayTrigger>
|
||||
);
|
||||
} else {
|
||||
return <label className={labelClass || 'form-label'}>{label}</label>;
|
||||
return (
|
||||
<label
|
||||
data-cy={`label-${String(label ?? '')
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')}`}
|
||||
className={labelClass || 'form-label'}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue