Skip to content

Commit

Permalink
chore: revive e2e (#2309)
Browse files Browse the repository at this point in the history
### 🎯 Goal

Bring our e2e tests to at least minimally useful state.

1. Added Playwright browser binaries to cache so that they are not
downloaded each time.
2. Removed flaky tests.
3. Removed all browsers except for Chromium - hopefully temporary, but
some tests were flaky particularly on WebKit.
4. Playwright will now stop after the first failed tests, so that tests
don't hang for 30 mins.
5. Added the whole job to a single concurrency group, because two tests
running at once on the same app will conflict.
  • Loading branch information
myandrienko authored Mar 6, 2024
1 parent 135e4c4 commit ce5cef9
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 154 deletions.
21 changes: 13 additions & 8 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,32 @@ jobs:
e2e:
runs-on: ubuntu-latest
name: End-to-end tests
concurrency:
group: react-e2e
cancel-in-progress: false
env:
PLAYWRIGHT_BROWSERS_PATH: ./pw-browsers
steps:
- uses: actions/checkout@v3

- name: 💾 Cache Dependencies
uses: actions/cache@v3
with:
path: ./node_modules
key: ${{ runner.os }}-${{ matrix.node }}-modules-${{ hashFiles('**/yarn.lock') }}
path: |
./node_modules
./pw-browsers
key: ${{ runner.os }}-${{ matrix.node }}-modules-${{ hashFiles('./yarn.lock') }}

- name: 🔨 Install Dependencies
run: yarn install --frozen-lockfile --ignore-engines --ignore-scripts
run: |
yarn install --frozen-lockfile --ignore-engines --ignore-scripts
npx playwright install chromium
npx playwright install-deps
- name: ⚗️ End-to-end tests
run: |
npx playwright install
npx playwright install-deps
yarn e2e-fixtures
# running with --browser=all causes failures
yarn e2e --browser=chromium
yarn e2e --browser=webkit
yarn e2e --browser=firefox
env:
E2E_JUMP_TO_MESSAGE_CHANNEL: jump-to-message
E2E_ADD_MESSAGE_CHANNEL: add-message
Expand Down
16 changes: 0 additions & 16 deletions e2e/attachment-sizing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,4 @@ test.describe('add height to video and image attachments', () => {
.sees(MessageList)
.isScrolledToBottom(`${USER1_CHAT_VIEW_CLASSNAME} ${selectors.messageListContainer}`);
});

test('should add height for gallery image attachments', async ({ page, user }) => {
const imageElementsLocator = page.locator(
'[data-testid="gallery-image-last"],[data-testid="gallery-image"]',
);
const result = await imageElementsLocator.evaluateAll(
(imageElements) =>
imageElements.length > 0 &&
imageElements.every((element) => getComputedStyle(element).height.includes('px')),
);

expect(result).toBe(true);
await user
.sees(MessageList)
.isScrolledToBottom(`${USER1_CHAT_VIEW_CLASSNAME} ${selectors.messageListContainer}`);
});
});
Empty file removed e2e/fixtures.mjs
Empty file.
29 changes: 0 additions & 29 deletions e2e/jump-to-message.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
/* eslint-disable jest/expect-expect */
/* eslint-disable jest/no-done-callback */
/* eslint-disable jest/require-top-level-describe */
import { expect } from '@playwright/test';
import { test } from './user/test';

import MessageNotification from './user/components/MessageList/MessageNotification';
import Message from './user/components/Message/MessageSimple';
import QuotedMessage from './user/components/Message/QuotedMessage';
import MessageList from './user/components/MessageList/MessageList';

const suiteArray = [
['virtualized', 'jump-to-message--jump-in-virtualized-message-list'],
['regular', 'jump-to-message--jump-in-regular-message-list'],
];

const controlsButtonSelector = 'data-testid=jump-to-message';
const onPageLoadWaitForMessage149 = 'data-testid=message-text-inner-wrapper >> text=Message 149';

suiteArray.forEach(([mode, story]) => {
Expand All @@ -23,35 +19,10 @@ suiteArray.forEach(([mode, story]) => {
await controller.openStory(story, onPageLoadWaitForMessage149);
});

test(`${mode} jumps to message 29 and then back to bottom`, async ({ page, user }) => {
const message29 = await user.sees(Message).not.displayed('Message 29');
await page.click(controlsButtonSelector);
await expect(message29).toBeVisible();
const message149 = await user.sees(Message).not.displayed('Message 149');
await user.clicks(MessageNotification).text('Latest Messages');
await expect(message149).toBeVisible();
});

test(`${mode} jumps to quoted message`, async ({ user }) => {
const text = 'Message 20';
await user.clicks(QuotedMessage).nth(text);
await user.sees(Message).displayed(text);
});
});
});

test.describe('jump to message - dataset', () => {
test('only the current message set is loaded', async ({ controller, page, user }) => {
await controller.openStory(
'jump-to-message--jump-in-regular-message-list',
onPageLoadWaitForMessage149,
);

await Promise.all([
page.waitForSelector('text=Message 29'),
page.click(controlsButtonSelector),
]);

await user.sees(MessageList).hasLength(100 + 1);
});
});
86 changes: 0 additions & 86 deletions e2e/navigate-long-message-lists.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,6 @@ test.describe('thread autoscroll', () => {
await message.scrollIntoViewIfNeeded();
await expectToOpenThreadAndSeeLatestMessage(page, user, MESSAGES_WITH_REPLIES[1]);
});

test('if I scroll primary message list by clicking a quoted message already loaded in state', async ({
page,
user,
}) => {
await user.clicks(QuotedMessage).nth(QUOTED_MESSAGES[0]);
await expectToOpenThreadAndSeeLatestMessage(page, user, QUOTED_MESSAGES[0]);
});

test('if I scroll primary message list by clicking a quoted message that has to be loaded in state', async ({
page,
user,
}) => {
await user.clicks(QuotedMessage).nth(QUOTED_MESSAGES[1], 2);
await Promise.all([
page.waitForResponse((r) => r.url().includes('/messages') && r.ok()),
expectToOpenThreadAndSeeLatestMessage(page, user, QUOTED_MESSAGES[1]),
]);
});
});

test.describe('on new message', () => {
Expand Down Expand Up @@ -185,71 +166,4 @@ test.describe('scroll to the bottom', () => {
.sees(MessageList)
.isScrolledToBottom(`${USER1_CHAT_VIEW_CLASSNAME} ${selectors.messageListContainer}`);
});

test('after loading more messages on new message notification click', async ({
controller,
page,
user,
}) => {
// scroll without loading more messages
await scrollInSteps(user);

// trigger load more messages
const firstLoadedMessage = await page.locator(
`${USER1_CHAT_VIEW_CLASSNAME} ${selectors.messageListContainer} li:first-of-type`,
);
await firstLoadedMessage.scrollIntoViewIfNeeded();
await controller.sendOtherUserMessage();

// click the notification
await page.waitForSelector(getMessageNotificationSelector(NEW_MESSAGE_NOTIFICATION_TEXT));
await user.clicks(MessageNotification).text(NEW_MESSAGE_NOTIFICATION_TEXT);

// check that you are at the bottom
await user
.sees(MessageList)
.isScrolledToBottom(`${USER1_CHAT_VIEW_CLASSNAME} ${selectors.messageListContainer}`);
});
});

test.describe('pagination', () => {
test.beforeEach(async ({ controller, user }) => {
await controller.openStory(
'navigate-long-message-lists--user1',
selectors.channelPreviewButton,
);
await user.clicks(ChannelPreview).text(CHANNEL_NAME);
});

test('does not lead to the viewport content change', async ({ page, user }) => {
const messageList = await page.locator(`${USER1_CHAT_VIEW_CLASSNAME} ${selectors.messageList}`);

const firstMessageFirstPage = await user.get(Message)(FIRST_MESSAGE_FIRST_PAGE);

let firstLoadedMessageBoxBeforePagination;
const msgListBoxBeforePagination = await messageList.boundingBox();

// get message position before the next page of messages is received
page.once('request', async () => {
firstLoadedMessageBoxBeforePagination = await firstMessageFirstPage.boundingBox();
});

await Promise.all([
page.waitForResponse((r) => r.url().includes('/query') && r.ok()),
firstMessageFirstPage.scrollIntoViewIfNeeded(),
]);

const msgListBoxAfterPagination = await messageList.boundingBox();
const firstLoadedMessageBoxAfterPagination = await firstMessageFirstPage.boundingBox();

const firstMessageShiftDistanceYToViewport =
firstLoadedMessageBoxBeforePagination.y - firstLoadedMessageBoxAfterPagination.y;
expect(firstMessageShiftDistanceYToViewport).toBeLessThanOrEqual(
firstLoadedMessageBoxBeforePagination.height,
);
expect(firstMessageShiftDistanceYToViewport).toBeGreaterThanOrEqual(
-firstLoadedMessageBoxBeforePagination.height,
);
expect(msgListBoxBeforePagination.height).not.toStrictEqual(msgListBoxAfterPagination.height);
});
});
2 changes: 1 addition & 1 deletion e2e/user/components/Message/MessageSimple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default (page: Page) => ({
not: {
async displayed(text?: string, nth?: number) {
const target = getMessage(page, text, nth);
await expect(target).not.toBeVisible();
await expect(target).not.toBeInViewport();
return target;
},
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
"@emoji-mart/data": "^1.1.2",
"@emoji-mart/react": "^1.1.1",
"@ladle/react": "^0.16.0",
"@playwright/test": "^1.29.1",
"@playwright/test": "^1.42.1",
"@rollup/plugin-babel": "^5.2.1",
"@rollup/plugin-commonjs": "^23.0.2",
"@rollup/plugin-image": "^2.1.1",
Expand Down
5 changes: 2 additions & 3 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ const config: PlaywrightTestConfig = {
maxDiffPixels: 100,
},
},
maxFailures: 1,
retries: 2,
testDir: './e2e',
timeout: 15 * 1000,
use: {
headless: true,
screenshot: 'only-on-failure',
viewport: { height: 920, width: 1280 },
},
webServer: {
command: 'ladle serve --open none',
command: 'npx ladle serve --open none',
port: 61000,
reuseExistingServer: !process.env.CI,
timeout: 120 * 1000,
},

workers: 1,
};

Expand Down
33 changes: 23 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1927,13 +1927,12 @@
dependencies:
"@octokit/openapi-types" "^16.0.0"

"@playwright/test@^1.29.1":
version "1.29.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.29.1.tgz#f2ed4dc143b9c7825a7ad2703b2f1ac4354e1145"
integrity sha512-iQxk2DX5U9wOGV3+/Jh9OHPsw5H3mleUL2S4BgQuwtlAfK3PnKvn38m4Rg9zIViGHVW24opSm99HQm/UFLEy6w==
"@playwright/test@^1.42.1":
version "1.42.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.42.1.tgz#9eff7417bcaa770e9e9a00439e078284b301f31c"
integrity sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==
dependencies:
"@types/node" "*"
playwright-core "1.29.1"
playwright "1.42.1"

"@pnpm/network.ca-file@^1.0.1":
version "1.0.2"
Expand Down Expand Up @@ -6880,6 +6879,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==

[email protected]:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==

fsevents@^1.2.7:
version "1.2.13"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
Expand Down Expand Up @@ -11525,10 +11529,19 @@ pkg-up@^3.1.0:
dependencies:
find-up "^3.0.0"

[email protected]:
version "1.29.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.29.1.tgz#9ec15d61c4bd2f386ddf6ce010db53a030345a47"
integrity sha512-20Ai3d+lMkWpI9YZYlxk8gxatfgax5STW8GaMozAHwigLiyiKQrdkt7gaoT9UQR8FIVDg6qVXs9IoZUQrDjIIg==
[email protected]:
version "1.42.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.42.1.tgz#13c150b93c940a3280ab1d3fbc945bc855c9459e"
integrity sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==

[email protected]:
version "1.42.1"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.42.1.tgz#79c828b51fe3830211137550542426111dc8239f"
integrity sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==
dependencies:
playwright-core "1.42.1"
optionalDependencies:
fsevents "2.3.2"

portfinder@^1.0.26:
version "1.0.32"
Expand Down

0 comments on commit ce5cef9

Please sign in to comment.