Skip to content

Commit 4f73f14

Browse files
authored
fix: autocomplete items clicking works on webkit (#1494)
fix: autocomplete items clicking works on webkit
1 parent 54c1a13 commit 4f73f14

File tree

7 files changed

+113
-5
lines changed

7 files changed

+113
-5
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ jobs:
3939
- name: ⚗️ End-to-end tests
4040
run: |
4141
npx playwright install
42+
npx playwright install-deps
4243
yarn e2e-fixtures
43-
yarn e2e
44+
# running with --browser=all causes failures
45+
yarn e2e --browser=chromium
46+
yarn e2e --browser=webkit
47+
yarn e2e --browser=firefox
4448
env:
4549
E2E_JUMP_TO_MESSAGE_CHANNEL: jump-to-message
4650
E2E_ADD_MESSAGE_CHANNEL: add-message

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v14.0.0
1+
lts/*

e2e/autocomplete-mention.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* eslint-disable jest/no-done-callback */
2+
/* eslint-disable jest/require-top-level-describe */
3+
import { expect, test } from '@playwright/test';
4+
5+
test.describe('autocomplete a mention', () => {
6+
test('should fill in textarea with username', async ({ baseURL, page }) => {
7+
await page.goto(`${baseURL}/?story=hello--basic-setup`);
8+
await page.waitForSelector('[data-storyloaded]');
9+
await page.fill('data-testid=message-input', '@');
10+
const button = await page.locator(
11+
'button.rta__entity >> :nth-match(span.str-chat__user-item--name, 1)',
12+
);
13+
button.click();
14+
const textContent = await button.textContent();
15+
16+
await expect(page.locator('data-testid=message-input')).toContainText(`@${textContent}`);
17+
});
18+
});

e2e/fixtures.mjs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,25 @@ dotenv.config({ path: `.env.local` });
2222

2323
// 'Jump to message' channel
2424
{
25+
const MESSAGES_COUNT = 150;
2526
console.log(`Creating and populating channel '${E2E_JUMP_TO_MESSAGE_CHANNEL}'...`);
2627
const channel = chat.channel('messaging', E2E_JUMP_TO_MESSAGE_CHANNEL, {
2728
created_by_id: E2E_TEST_USER_1,
2829
members: [E2E_TEST_USER_1, E2E_TEST_USER_2],
2930
});
3031
await channel.create();
3132
await channel.truncate();
32-
for (let i = 0, len = 150; i < len; i++) {
33-
process.stdout.write(`.`);
33+
for (let i = 0; i < MESSAGES_COUNT; i++) {
34+
if (process.stdout.clearLine && process.stdout.cursorTo) {
35+
printProgress(i / MESSAGES_COUNT);
36+
}
37+
3438
await channel.sendMessage({
3539
text: `Message ${i}`,
3640
user: { id: i % 2 ? E2E_TEST_USER_1 : E2E_TEST_USER_2 },
3741
});
3842
}
43+
process.stdout.write('\n');
3944
}
4045

4146
// 'Add message' channel
@@ -50,3 +55,13 @@ dotenv.config({ path: `.env.local` });
5055
await channel.truncate();
5156
}
5257
})();
58+
59+
const printProgress = (progress) => {
60+
process.stdout.clearLine();
61+
process.stdout.cursorTo(0);
62+
63+
const BAR_LENGTH = 50;
64+
const filled = Math.ceil(BAR_LENGTH * progress);
65+
const empty = BAR_LENGTH - filled;
66+
process.stdout.write(`[${'#'.repeat(filled)}${' '.repeat(empty)}] ${Math.ceil(progress * 100)}%`);
67+
};

src/components/AutoCompleteTextarea/Item.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export const Item = React.forwardRef(function Item(props, innerRef) {
2222
onMouseEnter={selectItem}
2323
ref={innerRef}
2424
>
25-
<Component entity={item} selected={selected} />
25+
<div tabIndex={-1}>
26+
<Component entity={item} selected={selected} />
27+
</div>
2628
</button>
2729
</li>
2830
);

src/components/AutoCompleteTextarea/Textarea.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ export class ReactTextareaAutocomplete extends React.Component {
728728
>
729729
{this.renderSuggestionListContainer()}
730730
<Textarea
731+
data-testid='message-input'
731732
{...this._cleanUpProps()}
732733
className={`rta__textarea ${className || ''}`}
733734
maxRows={maxRows}

src/stories/hello.stories.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import '@stream-io/stream-chat-css/dist/css/index.css';
3+
import React, { useEffect, useState } from 'react';
4+
import { ChannelFilters, ChannelOptions, ChannelSort, Event, StreamChat } from 'stream-chat';
5+
import {
6+
Channel,
7+
ChannelHeader,
8+
ChannelList,
9+
Chat,
10+
MessageInput,
11+
MessageList,
12+
Thread,
13+
Window,
14+
} from '../index';
15+
import { apiKey, StreamChatGenerics } from './utils';
16+
17+
const channelId = import.meta.env.E2E_ADD_MESSAGE_CHANNEL;
18+
const userId = import.meta.env.E2E_TEST_USER_1 as string;
19+
const token = import.meta.env.E2E_TEST_USER_1_TOKEN as string;
20+
21+
if (!channelId || typeof channelId !== 'string') {
22+
throw new Error('expected ADD_MESSAGE_CHANNEL');
23+
}
24+
25+
// Sort in reverse order to avoid auto-selecting unread channel
26+
const sort: ChannelSort = { last_updated: 1 };
27+
const filters: ChannelFilters = { members: { $in: [userId] }, type: 'messaging' };
28+
const options: ChannelOptions = { limit: 10, presence: true, state: true };
29+
30+
const chatClient = StreamChat.getInstance<StreamChatGenerics>(apiKey);
31+
let sharedPromise = Promise.resolve();
32+
33+
export const BasicSetup = () => {
34+
const [connected, setConnected] = useState(false);
35+
36+
useEffect(() => {
37+
sharedPromise.then(() => chatClient.connectUser({ id: userId }, token));
38+
39+
const handleConnectionChange = ({ online = false }: Event) => {
40+
setConnected(online);
41+
};
42+
43+
chatClient.on('connection.changed', handleConnectionChange);
44+
45+
return () => {
46+
chatClient.off('connection.changed', handleConnectionChange);
47+
sharedPromise = chatClient.disconnectUser();
48+
};
49+
}, []);
50+
51+
if (!connected) {
52+
return <p>Connecting {userId}...</p>;
53+
}
54+
55+
return (
56+
<Chat client={chatClient}>
57+
<ChannelList filters={filters} options={options} showChannelSearch sort={sort} />
58+
<Channel>
59+
<Window>
60+
<ChannelHeader />
61+
<MessageList />
62+
<MessageInput focus />
63+
</Window>
64+
<Thread />
65+
</Channel>
66+
</Chat>
67+
);
68+
};

0 commit comments

Comments
 (0)