@atlaskit/editor-plugin-table 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-table
2
2
 
3
+ ## 0.0.10
4
+
5
+ ### Patch Changes
6
+
7
+ - [`b519be31909`](https://bitbucket.org/atlassian/atlassian-frontend/commits/b519be31909) - Improve FloatingDeleteButton accessibility and update tests
8
+
9
+ ## 0.0.9
10
+
11
+ ### Patch Changes
12
+
13
+ - [`30d47a9f80d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/30d47a9f80d) - This change adds data-testid to the top and bottom sticky sentinels in TableComponent and updates tests to access the sentinels by the testId.
14
+
3
15
  ## 0.0.8
4
16
 
5
17
  ### Patch Changes
@@ -558,7 +558,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
558
558
  "data-number-column": node.attrs.isNumberColumnEnabled,
559
559
  "data-layout": node.attrs.layout
560
560
  }, stickyHeadersOptimization && /*#__PURE__*/_react.default.createElement("div", {
561
- className: _types.TableCssClassName.TABLE_STICKY_SENTINEL_TOP
561
+ className: _types.TableCssClassName.TABLE_STICKY_SENTINEL_TOP,
562
+ "data-testid": "sticky-sentinel-top"
562
563
  }), allowControls && (!isLoading || initialRenderOptimization) && rowControls, /*#__PURE__*/_react.default.createElement("div", {
563
564
  style: shadowStyle(showBeforeShadow),
564
565
  className: _types.TableCssClassName.TABLE_LEFT_SHADOW
@@ -598,7 +599,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
598
599
  top: "".concat(this.state.stickyHeader.top + this.state.stickyHeader.padding + shadowPadding + 2, "px")
599
600
  }
600
601
  })), stickyHeadersOptimization && /*#__PURE__*/_react.default.createElement("div", {
601
- className: _types.TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM
602
+ className: _types.TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM,
603
+ "data-testid": "sticky-sentinel-bottom"
602
604
  }));
603
605
  }
604
606
  }]);
@@ -27,7 +27,7 @@ var DeleteButton = function DeleteButton(_ref) {
27
27
  onMouseLeave: onMouseLeave
28
28
  }, /*#__PURE__*/_react.default.createElement("button", {
29
29
  type: "button",
30
- title: formatMessage(removeLabel, {
30
+ "aria-label": formatMessage(removeLabel, {
31
31
  0: 1
32
32
  }),
33
33
  className: _types.TableCssClassName.CONTROLS_DELETE_BUTTON,
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.0.8"
3
+ "version": "0.0.10"
4
4
  }
@@ -528,7 +528,8 @@ class TableComponent extends React.Component {
528
528
  "data-number-column": node.attrs.isNumberColumnEnabled,
529
529
  "data-layout": node.attrs.layout
530
530
  }, stickyHeadersOptimization && /*#__PURE__*/React.createElement("div", {
531
- className: ClassName.TABLE_STICKY_SENTINEL_TOP
531
+ className: ClassName.TABLE_STICKY_SENTINEL_TOP,
532
+ "data-testid": "sticky-sentinel-top"
532
533
  }), allowControls && (!isLoading || initialRenderOptimization) && rowControls, /*#__PURE__*/React.createElement("div", {
533
534
  style: shadowStyle(showBeforeShadow),
534
535
  className: ClassName.TABLE_LEFT_SHADOW
@@ -567,7 +568,8 @@ class TableComponent extends React.Component {
567
568
  top: `${this.state.stickyHeader.top + this.state.stickyHeader.padding + shadowPadding + 2}px`
568
569
  }
569
570
  })), stickyHeadersOptimization && /*#__PURE__*/React.createElement("div", {
570
- className: ClassName.TABLE_STICKY_SENTINEL_BOTTOM
571
+ className: ClassName.TABLE_STICKY_SENTINEL_BOTTOM,
572
+ "data-testid": "sticky-sentinel-bottom"
571
573
  }));
572
574
  }
573
575
 
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
- import { injectIntl } from 'react-intl-next'; // import { MessageDescriptor } from '../../../../types/i18n';
3
-
2
+ import { injectIntl } from 'react-intl-next';
4
3
  import { TableCssClassName as ClassName } from '../../types';
5
4
 
6
5
  const DeleteButton = ({
@@ -19,7 +18,7 @@ const DeleteButton = ({
19
18
  onMouseLeave: onMouseLeave
20
19
  }, /*#__PURE__*/React.createElement("button", {
21
20
  type: "button",
22
- title: formatMessage(removeLabel, {
21
+ "aria-label": formatMessage(removeLabel, {
23
22
  0: 1
24
23
  }),
25
24
  className: ClassName.CONTROLS_DELETE_BUTTON,
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.0.8"
3
+ "version": "0.0.10"
4
4
  }
@@ -543,7 +543,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
543
543
  "data-number-column": node.attrs.isNumberColumnEnabled,
544
544
  "data-layout": node.attrs.layout
545
545
  }, stickyHeadersOptimization && /*#__PURE__*/React.createElement("div", {
546
- className: ClassName.TABLE_STICKY_SENTINEL_TOP
546
+ className: ClassName.TABLE_STICKY_SENTINEL_TOP,
547
+ "data-testid": "sticky-sentinel-top"
547
548
  }), allowControls && (!isLoading || initialRenderOptimization) && rowControls, /*#__PURE__*/React.createElement("div", {
548
549
  style: shadowStyle(showBeforeShadow),
549
550
  className: ClassName.TABLE_LEFT_SHADOW
@@ -583,7 +584,8 @@ var TableComponent = /*#__PURE__*/function (_React$Component) {
583
584
  top: "".concat(this.state.stickyHeader.top + this.state.stickyHeader.padding + shadowPadding + 2, "px")
584
585
  }
585
586
  })), stickyHeadersOptimization && /*#__PURE__*/React.createElement("div", {
586
- className: ClassName.TABLE_STICKY_SENTINEL_BOTTOM
587
+ className: ClassName.TABLE_STICKY_SENTINEL_BOTTOM,
588
+ "data-testid": "sticky-sentinel-bottom"
587
589
  }));
588
590
  }
589
591
  }]);
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
- import { injectIntl } from 'react-intl-next'; // import { MessageDescriptor } from '../../../../types/i18n';
3
-
2
+ import { injectIntl } from 'react-intl-next';
4
3
  import { TableCssClassName as ClassName } from '../../types';
5
4
 
6
5
  var DeleteButton = function DeleteButton(_ref) {
@@ -17,7 +16,7 @@ var DeleteButton = function DeleteButton(_ref) {
17
16
  onMouseLeave: onMouseLeave
18
17
  }, /*#__PURE__*/React.createElement("button", {
19
18
  type: "button",
20
- title: formatMessage(removeLabel, {
19
+ "aria-label": formatMessage(removeLabel, {
21
20
  0: 1
22
21
  }),
23
22
  className: ClassName.CONTROLS_DELETE_BUTTON,
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.0.8"
3
+ "version": "0.0.10"
4
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
+ import { IntlProvider } from 'react-intl-next';
4
+ import DeleteButton from '../../../plugins/table/ui/FloatingDeleteButton/DeleteButton';
5
+ import tableMessages from '../../../plugins/table/ui/messages';
6
+
7
+ describe('<DeleteButton />', () => {
8
+ it('should fire the onMouseEnter callback', () => {
9
+ const onMouseEnter = jest.fn();
10
+ render(
11
+ <IntlProvider locale="en">
12
+ <DeleteButton
13
+ removeLabel={tableMessages.removeColumns}
14
+ onMouseEnter={onMouseEnter}
15
+ />
16
+ </IntlProvider>,
17
+ );
18
+ fireEvent.mouseEnter(screen.getByLabelText('Delete column'));
19
+ expect(onMouseEnter).toHaveBeenCalled();
20
+ });
21
+
22
+ it('should fire the onMouseLeave callback', () => {
23
+ const onMouseLeave = jest.fn();
24
+ render(
25
+ <IntlProvider locale="en">
26
+ <DeleteButton
27
+ removeLabel={tableMessages.removeColumns}
28
+ onMouseLeave={onMouseLeave}
29
+ />
30
+ </IntlProvider>,
31
+ );
32
+ fireEvent.mouseLeave(screen.getByLabelText('Delete column'));
33
+ expect(onMouseLeave).toHaveBeenCalled();
34
+ });
35
+ });
@@ -1,5 +1,4 @@
1
1
  import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
2
- import { mountWithIntl } from '@atlaskit/editor-test-helpers/enzyme';
3
2
  import {
4
3
  doc,
5
4
  table,
@@ -10,10 +9,11 @@ import {
10
9
  DocBuilder,
11
10
  } from '@atlaskit/editor-test-helpers/doc-builder';
12
11
  import { selectColumns, selectRows } from '@atlaskit/editor-test-helpers/table';
13
- import { ReactWrapper } from 'enzyme';
14
12
  import { selectTable } from '@atlaskit/editor-tables/utils';
15
13
  import { EditorView } from 'prosemirror-view';
16
14
  import React from 'react';
15
+ import { render, screen } from '@testing-library/react';
16
+ import { IntlProvider } from 'react-intl-next';
17
17
  import {
18
18
  TablePluginState,
19
19
  TableCssClassName,
@@ -21,8 +21,6 @@ import {
21
21
  import FloatingDeleteButton, {
22
22
  Props as FloatingDeleteButtonProps,
23
23
  } from '../../../plugins/table/ui/FloatingDeleteButton';
24
- import DeleteButton from '../../../plugins/table/ui/FloatingDeleteButton/DeleteButton';
25
- import tableMessages from '../../../plugins/table/ui/messages';
26
24
  import * as tableColumnControlsUtils from '../../../plugins/table/utils/column-controls';
27
25
  import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
28
26
  import tablePlugin from '../../../plugins/table-plugin';
@@ -40,7 +38,6 @@ describe('Floating Delete Button', () => {
40
38
  pluginKey,
41
39
  });
42
40
 
43
- let wrapper: ReactWrapper<FloatingDeleteButtonProps>;
44
41
  let editorView: EditorView;
45
42
 
46
43
  beforeEach(() => {
@@ -53,34 +50,31 @@ describe('Floating Delete Button', () => {
53
50
  ),
54
51
  ),
55
52
  ));
56
-
57
- wrapper = (mountWithIntl(
58
- <FloatingDeleteButton
59
- tableRef={document.querySelector('table')!}
60
- editorView={editorView}
61
- selection={editorView.state.selection}
62
- />,
63
- ) as unknown) as ReactWrapper<FloatingDeleteButtonProps>;
64
53
  });
65
54
 
66
- afterEach(() => {
67
- if (wrapper) {
68
- wrapper.unmount();
69
- }
70
- });
55
+ const component = (props: FloatingDeleteButtonProps) =>
56
+ render(
57
+ <IntlProvider locale="en">
58
+ <FloatingDeleteButton
59
+ tableRef={editorView.dom.querySelector('table')!}
60
+ {...props}
61
+ />
62
+ </IntlProvider>,
63
+ );
71
64
 
72
65
  it('should not render a delete button with no selection', () => {
73
- expect(wrapper.find(DeleteButton).length).toBe(0);
66
+ component({ selection: editorView.state.selection, editorView });
67
+
68
+ expect(screen.queryByLabelText('Popup')).toBeFalsy();
74
69
  });
75
70
 
76
71
  it('should not render a delete button with whole table selected', () => {
77
- // select the whole table
72
+ // selects the whole table
78
73
  editorView.dispatch(selectTable(editorView.state.tr));
79
74
 
80
- // We need to force renderer
81
- wrapper.setProps({ selection: editorView.state.selection });
82
- // set numberOfColumns prop to trick shouldComponentUpdate and force re-render
83
- expect(wrapper.find(DeleteButton).length).toBe(0);
75
+ component({ selection: editorView.state.selection, editorView });
76
+
77
+ expect(screen.queryByLabelText('Popup')).toBeFalsy();
84
78
  });
85
79
 
86
80
  describe('Columns', () => {
@@ -104,21 +98,18 @@ describe('Floating Delete Button', () => {
104
98
  // Select columns start from 0
105
99
  selectColumns([column - 1])(editorView.state, editorView.dispatch);
106
100
 
107
- // We need to force renderer
108
- wrapper.setProps({ selection: editorView.state.selection });
101
+ component({ selection: editorView.state.selection, editorView });
109
102
 
110
- // we should now have a delete button
111
- expect(wrapper.find(DeleteButton).length).toBe(1);
103
+ expect(screen.getAllByLabelText('Delete column').length).toBe(1);
112
104
  },
113
105
  );
114
106
 
115
107
  it('should render a single delete button over multiple column selections', () => {
116
108
  selectColumns([0, 1])(editorView.state, editorView.dispatch);
117
109
 
118
- // We need to force renderer
119
- wrapper.setProps({ selection: editorView.state.selection });
110
+ component({ selection: editorView.state.selection, editorView });
120
111
 
121
- expect(wrapper.find(DeleteButton).length).toBe(1);
112
+ expect(screen.getAllByLabelText('Delete column').length).toBe(1);
122
113
  });
123
114
  });
124
115
 
@@ -128,9 +119,9 @@ describe('Floating Delete Button', () => {
128
119
  (row) => {
129
120
  selectRows([row - 1])(editorView.state, editorView.dispatch);
130
121
 
131
- wrapper.setProps({ selection: editorView.state.selection });
122
+ component({ selection: editorView.state.selection, editorView });
132
123
 
133
- expect(wrapper.find(DeleteButton).length).toBe(1);
124
+ expect(screen.getAllByLabelText('Delete row').length).toBe(1);
134
125
  },
135
126
  );
136
127
 
@@ -138,38 +129,9 @@ describe('Floating Delete Button', () => {
138
129
  selectRows([0, 1])(editorView.state, editorView.dispatch);
139
130
 
140
131
  // selecting the row mutates the editor state (which is inside editorView)
141
- // we set tableHeight prop to trick shouldComponentUpdate and force re-render
142
- wrapper.setProps({ selection: editorView.state.selection });
143
-
144
- expect(wrapper.find(DeleteButton).length).toBe(1);
145
- });
146
- });
147
-
148
- describe('<DeleteButton />', () => {
149
- it('should fire the onMouseEnter callback', () => {
150
- const onMouseEnter = jest.fn();
151
- const button = mountWithIntl(
152
- <DeleteButton
153
- removeLabel={tableMessages.removeColumns}
154
- onMouseEnter={onMouseEnter}
155
- />,
156
- );
157
- button.simulate('mouseenter');
158
- expect(onMouseEnter).toBeCalled();
159
- button.unmount();
160
- });
132
+ component({ selection: editorView.state.selection, editorView });
161
133
 
162
- it('should fire the onMouseLeave callback', () => {
163
- const onMouseLeave = jest.fn();
164
- const button = mountWithIntl(
165
- <DeleteButton
166
- removeLabel={tableMessages.removeRows}
167
- onMouseLeave={onMouseLeave}
168
- />,
169
- );
170
- button.simulate('mouseleave');
171
- expect(onMouseLeave).toBeCalled();
172
- button.unmount();
134
+ expect(screen.getAllByLabelText('Delete row').length).toBe(1);
173
135
  });
174
136
  });
175
137
  });
@@ -33,9 +33,9 @@ jest.mock('@atlaskit/editor-common/ui', () => ({
33
33
  import { findOverflowScrollParent } from '@atlaskit/editor-common/ui';
34
34
  import { updateStickyState } from '../../../../pm-plugins/sticky-headers/commands';
35
35
  import { TableCssClassName } from '../../../../types';
36
- import { mount } from 'enzyme';
37
36
  import TableComponent from '../../../../nodeviews/TableComponent';
38
37
  import React from 'react';
38
+ import { render, screen } from '@testing-library/react';
39
39
  import {
40
40
  stickyRowOffsetTop,
41
41
  tableScrollbarOffset,
@@ -388,13 +388,13 @@ describe('TableRowNodeView', () => {
388
388
  return scrollContainer;
389
389
  }
390
390
 
391
- function mountTableComponent({
391
+ function renderTableComponent({
392
392
  disableContentDomMock,
393
393
  }: {
394
394
  disableContentDomMock?: true;
395
395
  } = {}) {
396
396
  const getNode = () => editorView.state.doc.firstChild;
397
- return mount(
397
+ return render(
398
398
  <TableComponent
399
399
  view={editorView}
400
400
  eventDispatcher={eventDispatcher}
@@ -428,28 +428,21 @@ describe('TableRowNodeView', () => {
428
428
  });
429
429
 
430
430
  it('sentinel elements are rendered inside table component', () => {
431
- const tableComponent = mountTableComponent();
432
- // rafStub.flush();
433
- const sentinelWrapperTop = tableComponent.find(
434
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_TOP}`,
435
- );
436
- const sentinelWrapperBottom = tableComponent.find(
437
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM}`,
438
- );
439
- expect(sentinelWrapperTop).toHaveLength(1);
440
- expect(sentinelWrapperBottom).toHaveLength(1);
431
+ renderTableComponent();
432
+ const sentinelTop = screen.getByTestId('sticky-sentinel-top');
433
+ const sentinelBottom = screen.getByTestId('sticky-sentinel-bottom');
434
+
435
+ expect(sentinelTop).toBeTruthy();
436
+ expect(sentinelBottom).toBeTruthy();
441
437
  });
442
438
 
443
439
  describe('updates sticky header state', () => {
444
440
  it('top sentinel does nothing if the rootBounds has height 0', () => {
445
- const tableComponent = mountTableComponent();
446
- const sentinelWrapperTop = tableComponent.find(
447
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_TOP}`,
448
- );
449
- const sentinelTop = sentinelWrapperTop.getDOMNode() as HTMLElement;
441
+ renderTableComponent();
442
+ const sentinelTop = screen.getByTestId('sticky-sentinel-top');
450
443
 
451
444
  triggerElementIntersect({
452
- target: sentinelTop,
445
+ target: sentinelTop as HTMLElement,
453
446
  isIntersecting: false,
454
447
  rootBounds: { bottom: 0, top: 0, height: 0 },
455
448
  boundingClientRect: { bottom: 0, top: 0 },
@@ -459,13 +452,10 @@ describe('TableRowNodeView', () => {
459
452
  });
460
453
 
461
454
  it('bottom sentinel does nothing if the rootBounds has height 0', () => {
462
- const tableComponent = mountTableComponent();
463
- const sentinelWrapperBottom = tableComponent.find(
464
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM}`,
465
- );
466
- const sentinelBottom = sentinelWrapperBottom.getDOMNode() as HTMLElement;
455
+ renderTableComponent();
456
+ const sentinelBottom = screen.getByTestId('sticky-sentinel-bottom');
467
457
  triggerElementIntersect({
468
- target: sentinelBottom,
458
+ target: sentinelBottom as HTMLElement,
469
459
  isIntersecting: false,
470
460
  rootBounds: { bottom: 0, top: 0, height: 0 },
471
461
  boundingClientRect: { bottom: 0, top: 0 },
@@ -474,12 +464,9 @@ describe('TableRowNodeView', () => {
474
464
  expect(updateStickyState).not.toHaveBeenCalled();
475
465
  });
476
466
 
477
- it('when top sentinel leaves scroll area', () => {
478
- const tableComponent = mountTableComponent();
479
- const sentinelWrapperTop = tableComponent.find(
480
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_TOP}`,
481
- );
482
- const sentinelTop = sentinelWrapperTop.getDOMNode() as HTMLElement;
467
+ it('updates sticky header when top of sticky header sentinel leaves scroll area', () => {
468
+ renderTableComponent();
469
+ const sentinelTop = screen.getByTestId('sticky-sentinel-top');
483
470
 
484
471
  triggerElementIntersect({
485
472
  target: sentinelTop,
@@ -512,12 +499,9 @@ describe('TableRowNodeView', () => {
512
499
  );
513
500
  });
514
501
 
515
- it('when bottom sentinel enters or leaves scroll area', () => {
516
- const tableComponent = mountTableComponent();
517
- const sentinelWrapperBottom = tableComponent.find(
518
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM}`,
519
- );
520
- const sentinelBottom = sentinelWrapperBottom.getDOMNode() as HTMLElement;
502
+ it('updates sticky header when bottom of sticky header sentinel enters or leaves scroll area', () => {
503
+ renderTableComponent();
504
+ const sentinelBottom = screen.getByTestId('sticky-sentinel-bottom');
521
505
 
522
506
  triggerElementIntersect({
523
507
  target: sentinelBottom,
@@ -560,13 +544,10 @@ describe('TableRowNodeView', () => {
560
544
  (_, contentRectSupported: boolean) => {
561
545
  const { tableWrapper } = getTableElements(tableRowDom);
562
546
  // disabled due to editorView dom being cleared by use of contentDom mocks
563
- const tableComponent = mountTableComponent({
547
+ renderTableComponent({
564
548
  disableContentDomMock: true,
565
549
  });
566
- const sentinelWrapperBottom = tableComponent.find(
567
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM}`,
568
- );
569
- const sentinelBottom = sentinelWrapperBottom.getDOMNode() as HTMLElement;
550
+ const sentinelBottom = screen.getByTestId('sticky-sentinel-bottom');
570
551
  tableWrapper?.appendChild(sentinelBottom);
571
552
  rafStub.flush();
572
553
 
@@ -584,13 +565,10 @@ describe('TableRowNodeView', () => {
584
565
  it('marks sentinels as unobserved when isHeaderRowEnabled is set to false', () => {
585
566
  const { tableWrapper } = getTableElements(tableRowDom);
586
567
  // disabled due to editorView dom being cleared by use of contentDom mocks
587
- const tableComponent = mountTableComponent({
568
+ renderTableComponent({
588
569
  disableContentDomMock: true,
589
570
  });
590
- const sentinelWrapperBottom = tableComponent.find(
591
- `.${TableCssClassName.TABLE_STICKY_SENTINEL_BOTTOM}`,
592
- );
593
- const sentinelBottom = sentinelWrapperBottom.getDOMNode() as HTMLElement;
571
+ const sentinelBottom = screen.getByTestId('sticky-sentinel-bottom');
594
572
  tableWrapper?.appendChild(sentinelBottom);
595
573
  rafStub.flush();
596
574
  expect(sentinelBottom.dataset.isObserved).toBeDefined();
@@ -394,7 +394,10 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
394
394
  data-layout={node.attrs.layout}
395
395
  >
396
396
  {stickyHeadersOptimization && (
397
- <div className={ClassName.TABLE_STICKY_SENTINEL_TOP} />
397
+ <div
398
+ className={ClassName.TABLE_STICKY_SENTINEL_TOP}
399
+ data-testid="sticky-sentinel-top"
400
+ />
398
401
  )}
399
402
  {allowControls &&
400
403
  (!isLoading || initialRenderOptimization) &&
@@ -465,7 +468,10 @@ class TableComponent extends React.Component<ComponentProps, TableState> {
465
468
  </div>
466
469
  )}
467
470
  {stickyHeadersOptimization && (
468
- <div className={ClassName.TABLE_STICKY_SENTINEL_BOTTOM} />
471
+ <div
472
+ className={ClassName.TABLE_STICKY_SENTINEL_BOTTOM}
473
+ data-testid="sticky-sentinel-bottom"
474
+ />
469
475
  )}
470
476
  </div>
471
477
  );
@@ -2,7 +2,6 @@ import React, { SyntheticEvent } from 'react';
2
2
 
3
3
  import { WrappedComponentProps, injectIntl } from 'react-intl-next';
4
4
 
5
- // import { MessageDescriptor } from '../../../../types/i18n';
6
5
  import { MessageDescriptor } from 'react-intl-next';
7
6
  import { TableCssClassName as ClassName } from '../../types';
8
7
 
@@ -30,7 +29,7 @@ const DeleteButton = ({
30
29
  >
31
30
  <button
32
31
  type="button"
33
- title={formatMessage(removeLabel, { 0: 1 })}
32
+ aria-label={formatMessage(removeLabel, { 0: 1 })}
34
33
  className={ClassName.CONTROLS_DELETE_BUTTON}
35
34
  onMouseDown={onClick}
36
35
  onMouseMove={(e) => e.preventDefault()}