Repository: adobe/react-spectrum
File: packages/react-aria-components/test/ListBox.test.js (JavaScript)

Code before:
      ${'keyboard'}
    `('should support press events on items when using $interactionType', async function ({interactionType}) {
      let onAction = jest.fn();
      let onPressStart = jest.fn();
      let onPressEnd = jest.fn();
      let onPress = jest.fn();
      let onClick = jest.fn();
      let {getByRole} = renderListbox({}, {onAction, onPressStart, onPressEnd, onPress, onClick});
      let listBoxTester = testUtilUser.createTester('ListBox', {root: getByRole('listbox')});
      await listBoxTester.triggerOptionAction({option: 1, interactionType});

      expect(onAction).toHaveBeenCalledTimes(1);
      expect(onPressStart).toHaveBeenCalledTimes(1);
      expect(onPressEnd).toHaveBeenCalledTimes(1);
      expect(onPress).toHaveBeenCalledTimes(1);
      expect(onClick).toHaveBeenCalledTimes(1);
    });
  });

  describe('onKeyDown', () => {
    it('should call onKeyDown handler when key is pressed on item', () => {
      let onKeyDown = jest.fn();
      let {getAllByRole} = renderListbox({}, {onKeyDown});
      let options = getAllByRole('option');

      fireEvent.keyDown(options[0], {key: 'Delete'});
      expect(onKeyDown).toHaveBeenCalledTimes(1);

      fireEvent.keyDown(options[1], {key: 'Backspace'});
      expect(onKeyDown).toHaveBeenCalledTimes(2);
    });
  });
});


Review comment (suggestion):
```suggestion
      await user.tab();
      await user.keyboard('ArrowDown');
```


Code after:
            <ListBox
              {...listBoxProps}
              aria-label="async virtualized listbox"
              renderEmptyState={() => renderEmptyState()}>
              <Collection items={items}>
                {(item) => (
                  <ListBoxItem id={item.name}>{item.name}</ListBoxItem>
                )}
              </Collection>
              <ListBoxLoadMoreItem isLoading={isLoading} onLoadMore={onLoadMore}>
                Loading...
              </ListBoxLoadMoreItem>
            </ListBox>
          </Virtualizer>
        );
      };

      it('should always render the sentinel even when virtualized', () => {
        let tree = render(<VirtualizedAsyncListbox isLoading items={items} />);
        let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')});
        let options = listboxTester.options();
        expect(options).toHaveLength(8);
        let loaderRow = options[7];
        expect(loaderRow).toHaveTextContent('Loading...');
        expect(loaderRow).not.toHaveAttribute('aria-posinset');
        expect(loaderRow).not.toHaveAttribute('aria-setSize');
        let loaderParentStyles = loaderRow.parentElement.style;

        // 50 items * 25px = 1250
        expect(loaderParentStyles.top).toBe('1250px');
        expect(loaderParentStyles.height).toBe('30px');

        let sentinel = within(loaderRow.parentElement).getByTestId('loadMoreSentinel');
        expect(sentinel.parentElement).toHaveAttribute('inert');
      });

      // TODO: for some reason this tree renders empty if ran with the above test...
      // Even if the above test doesn't do anything within it, the below tree won't render with content until the above test
      // is fully commented out (aka even the it(...))
      // It thinks that the contextSize is 0 and never updates
      it.skip('should not reserve room for the loader if isLoading is false', () => {
        let tree = render(<VirtualizedAsyncListbox items={items} />);
        let listboxTester = testUtilUser.createTester('ListBox', {root: tree.getByRole('listbox')});
        let options = listboxTester.options();
        expect(options).toHaveLength(7);
        expect(within(listboxTester.listbox).queryByText('Loading...')).toBeFalsy();

        let sentinel = within(listboxTester.listbox).getByTestId('loadMoreSentinel');
        let sentinelParentStyles = sentinel.parentElement.parentElement.style;
        expect(sentinelParentStyles.top).toBe('1250px');
        expect(sentinelParentStyles.height).toBe('0px');