snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,925 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {
|
||||
expect,
|
||||
isWebhookTestServerReachable,
|
||||
setupWebhookTestServer,
|
||||
test,
|
||||
testConfig,
|
||||
} from '@mattermost/playwright-lib';
|
||||
|
||||
test.describe('Interactive mm_blocks (ephemeral post)', () => {
|
||||
test(
|
||||
'renders mm_blocks in an ephemeral post created via API',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral']},
|
||||
async ({pw}) => {
|
||||
const {team, user, adminClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const marker = `E2E mm_blocks ephemeral ${pw.random.id()}`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
message: 'E2E mm_blocks (ephemeral)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: marker},
|
||||
{type: 'divider'},
|
||||
{type: 'text', text: 'Second line after divider.'},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
await expect(lastPost.container.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
await expect(lastPost.container.locator('.mm-blocks')).toBeVisible();
|
||||
await expect(lastPost.container.getByText(marker)).toBeVisible();
|
||||
await expect(lastPost.container.getByText('Second line after divider.')).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks external action reaches webhook sidecar and shows integration ephemeral',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
// Ephemeral roots have no Reply control; under CRT, integration ephemerals stay out of the center list.
|
||||
// Thread the interactive ephemeral under a normal channel post so the Thread panel can host it and the follow-up ephemeral.
|
||||
const anchorMarker = `E2E mm_blocks anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks ephemeral action ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + external action)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Ping integration',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_integration',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_integration: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
const replyOnAnchor = anchorPost.getByRole('button', {name: 'reply'});
|
||||
await expect(replyOnAnchor).toBeVisible();
|
||||
await replyOnAnchor.click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
// Thread RHS uses data-testid="rhsPostView", not "postView" (center channel only).
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
await ephemeralInThread.getByRole('button', {name: 'Ping integration'}).click();
|
||||
|
||||
const integrationEphemeral = threadPanel
|
||||
.getByTestId('rhsPostView')
|
||||
.filter({hasText: /Playwright mm_blocks integration OK \(user:/});
|
||||
await expect(integrationEphemeral).toBeVisible();
|
||||
await expect(integrationEphemeral.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks external action applies integration update in thread',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks ephemeral update ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_update`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + apply update)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Apply update',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_apply_update',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_apply_update: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
const replyOnAnchor = anchorPost.getByRole('button', {name: 'reply'});
|
||||
await expect(replyOnAnchor).toBeVisible();
|
||||
await replyOnAnchor.click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
await ephemeralInThread.getByRole('button', {name: 'Apply update'}).click();
|
||||
|
||||
await expect(
|
||||
threadPanel.getByTestId('rhsPostView').filter({hasText: 'PLAYWRIGHT_MM_BLOCKS_UPDATED'}),
|
||||
).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks username override persists after integration update in thread',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
await adminClient.patchConfig({ServiceSettings: {EnablePostUsernameOverride: true}});
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks anchor override ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const overrideAuthorName = 'Playwright mm_blocks eph override';
|
||||
const ephemeralMarker = `E2E mm_blocks ephemeral override ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_update`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + override + apply update)',
|
||||
props: {
|
||||
from_webhook: 'true',
|
||||
override_username: overrideAuthorName,
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Apply update',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_apply_update_eph_override',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_apply_update_eph_override: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
const replyOnAnchor = anchorPost.getByRole('button', {name: 'reply'});
|
||||
await expect(replyOnAnchor).toBeVisible();
|
||||
await replyOnAnchor.click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
|
||||
const author = ephemeralInThread.locator('.post__header .user-popover');
|
||||
await expect(author).toContainText(overrideAuthorName);
|
||||
|
||||
await ephemeralInThread.getByRole('button', {name: 'Apply update'}).click();
|
||||
|
||||
const updated = threadPanel.getByTestId('rhsPostView').filter({hasText: 'PLAYWRIGHT_MM_BLOCKS_UPDATED'});
|
||||
await expect(updated).toBeVisible();
|
||||
await expect(updated.locator('.post__header .user-popover')).toContainText(overrideAuthorName);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks button merges mm_blocks_actions query with block query on integration URL',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph query anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks eph query merge ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_echo_query`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + query merge)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Run query merge',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_query_btn_eph',
|
||||
query: {cli: 'from_block'},
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_query_btn_eph: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
query: {srv: 'from_action'},
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
await ephemeralInThread.getByRole('button', {name: 'Run query merge'}).click();
|
||||
|
||||
const integrationEphemeral = threadPanel
|
||||
.getByTestId('rhsPostView')
|
||||
.filter({hasText: /Playwright mm_blocks query OK \(cli=from_block&srv=from_action\)/});
|
||||
await expect(integrationEphemeral).toBeVisible();
|
||||
await expect(integrationEphemeral.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks button block query overrides duplicate mm_blocks_actions query keys',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph override anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks eph query override ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_echo_query`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + query override)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Override dup key',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_query_override_eph',
|
||||
query: {dup: 'from_block'},
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_query_override_eph: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
query: {dup: 'from_action'},
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
await ephemeralInThread.getByRole('button', {name: 'Override dup key'}).click();
|
||||
|
||||
await expect(threadPanel.getByText('Playwright mm_blocks query OK (dup=from_block)')).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks static_select merges action and element query on integration URL',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph select query anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks eph static_select query ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_echo_query`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + static_select query)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'static_select',
|
||||
action_id: 'pw_mm_blocks_static_select_query_eph',
|
||||
placeholder: 'Pick a region',
|
||||
query: {cli: 'from_block'},
|
||||
options: [
|
||||
{text: 'North', value: 'opt_north'},
|
||||
{text: 'South', value: 'opt_south'},
|
||||
],
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_static_select_query_eph: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
query: {srv: 'from_action'},
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralRow = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker}).last();
|
||||
await expect(ephemeralRow).toBeVisible();
|
||||
|
||||
const regionSelect = ephemeralRow.getByRole('combobox', {name: 'Pick a region'});
|
||||
await expect(regionSelect).toBeVisible();
|
||||
await regionSelect.click();
|
||||
await regionSelect.fill('Nor');
|
||||
await channelsPage.page.getByRole('option', {name: 'North'}).click();
|
||||
|
||||
const integrationEphemeral = threadPanel
|
||||
.getByTestId('rhsPostView')
|
||||
.filter({hasText: /Playwright mm_blocks query OK \(cli=from_block&srv=from_action\)/});
|
||||
await expect(integrationEphemeral).toBeVisible();
|
||||
await expect(integrationEphemeral.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks static_select data_source users sends selected user id to integration',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph ds users anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks eph static_select users ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_static_select`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + static_select users)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'static_select',
|
||||
action_id: 'pw_mm_blocks_ds_users_eph',
|
||||
placeholder: 'Pick a user',
|
||||
data_source: 'users',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_ds_users_eph: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralRow = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker}).last();
|
||||
await expect(ephemeralRow).toBeVisible();
|
||||
|
||||
const userSelect = ephemeralRow.getByRole('combobox', {name: 'Pick a user'});
|
||||
await expect(userSelect).toBeVisible();
|
||||
await userSelect.click();
|
||||
await userSelect.fill(user.username);
|
||||
await channelsPage.page
|
||||
.getByRole('option')
|
||||
.filter({hasText: new RegExp(`@${user.username}\\b`)})
|
||||
.first()
|
||||
.click();
|
||||
|
||||
const integrationEphemeral = threadPanel.getByTestId('rhsPostView').filter({
|
||||
hasText: new RegExp(`Playwright mm_blocks static_select OK \\(selected_option: ${user.id}\\)`),
|
||||
});
|
||||
await expect(integrationEphemeral).toBeVisible();
|
||||
await expect(integrationEphemeral.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks static_select data_source channels sends selected channel id to integration',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph ds channels anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks eph static_select channels ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_static_select`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + static_select channels)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'static_select',
|
||||
action_id: 'pw_mm_blocks_ds_channels_eph',
|
||||
placeholder: 'Pick a channel',
|
||||
data_source: 'channels',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_ds_channels_eph: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
context: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralRow = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker}).last();
|
||||
await expect(ephemeralRow).toBeVisible();
|
||||
|
||||
const channelSelect = ephemeralRow.getByRole('combobox', {name: 'Pick a channel'});
|
||||
await expect(channelSelect).toBeVisible();
|
||||
await channelSelect.click();
|
||||
await channelSelect.fill('Town');
|
||||
await channelsPage.page
|
||||
.getByRole('option', {name: /Town Square/})
|
||||
.first()
|
||||
.click();
|
||||
|
||||
const integrationEphemeral = threadPanel.getByTestId('rhsPostView').filter({
|
||||
hasText: new RegExp(`Playwright mm_blocks static_select OK \\(selected_option: ${townSquare.id}\\)`),
|
||||
});
|
||||
await expect(integrationEphemeral).toBeVisible();
|
||||
await expect(integrationEphemeral.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks button sends mm_blocks_actions context to integration',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral', '@external_service']},
|
||||
async ({pw, request}) => {
|
||||
test.skip(
|
||||
!(await isWebhookTestServerReachable(request)),
|
||||
[
|
||||
`Webhook test server is not reachable at ${testConfig.webhookBaseUrl}.`,
|
||||
'Start it from the repo: cd e2e-tests/cypress && npm run start:webhook',
|
||||
'Or set PW_WEBHOOK_BASE_URL when it runs elsewhere.',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
await setupWebhookTestServer(request, {
|
||||
mattermostBaseUrl: testConfig.internalBaseURL,
|
||||
adminUsername: testConfig.adminUsername,
|
||||
adminPassword: testConfig.adminPassword,
|
||||
});
|
||||
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
if (!townSquare) {
|
||||
throw new Error('Town Square channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph context anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const contextMarker = `ctx_${pw.random.id()}`;
|
||||
const ephemeralMarker = `E2E mm_blocks eph action_context ${pw.random.id()}`;
|
||||
const integrationUrl = `${testConfig.webhookInternalUrl}/mm_blocks_integration_echo_context`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + action context)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Verify context',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_echo_ctx_eph',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_echo_ctx_eph: {
|
||||
type: 'external',
|
||||
url: integrationUrl,
|
||||
context: {test_marker: contextMarker},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
await ephemeralInThread.getByRole('button', {name: 'Verify context'}).click();
|
||||
|
||||
const integrationEphemeral = threadPanel
|
||||
.getByTestId('rhsPostView')
|
||||
.filter({hasText: `Playwright mm_blocks context OK (test_marker: ${contextMarker})`});
|
||||
await expect(integrationEphemeral).toBeVisible();
|
||||
await expect(integrationEphemeral.getByText('(Only visible to you)', {exact: true})).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'ephemeral mm_blocks openURL action navigates with merged action query',
|
||||
{tag: ['@interactive_messages', '@mm_blocks', '@ephemeral']},
|
||||
async ({pw}) => {
|
||||
const {team, user, adminClient, userClient} = await pw.initSetup();
|
||||
|
||||
const channels = await adminClient.getMyChannels(team.id);
|
||||
const townSquare = channels.find((ch) => ch.name === 'town-square');
|
||||
const offTopic = channels.find((ch) => ch.name === 'off-topic');
|
||||
if (!townSquare || !offTopic) {
|
||||
throw new Error('Town Square or Off-Topic channel not found');
|
||||
}
|
||||
|
||||
const {channelsPage} = await pw.testBrowser.login(user);
|
||||
await channelsPage.goto(team.name, 'town-square');
|
||||
await channelsPage.toBeVisible();
|
||||
|
||||
const anchorMarker = `E2E mm_blocks eph openurl anchor ${pw.random.id()}`;
|
||||
const anchor = await userClient.createPost({
|
||||
channel_id: townSquare.id,
|
||||
message: anchorMarker,
|
||||
});
|
||||
|
||||
const ephemeralMarker = `E2E mm_blocks eph openurl ${pw.random.id()}`;
|
||||
const targetChannelPath = `/${team.name}/channels/off-topic`;
|
||||
|
||||
await adminClient.createPostEphemeral(user.id, {
|
||||
channel_id: townSquare.id,
|
||||
root_id: anchor.id,
|
||||
message: 'E2E mm_blocks (ephemeral + openURL)',
|
||||
props: {
|
||||
mm_blocks: [
|
||||
{type: 'text', text: ephemeralMarker},
|
||||
{
|
||||
type: 'button',
|
||||
text: 'Go to Off-Topic',
|
||||
style: 'primary',
|
||||
action_id: 'pw_mm_blocks_openurl_eph',
|
||||
},
|
||||
],
|
||||
mm_blocks_actions: {
|
||||
pw_mm_blocks_openurl_eph: {
|
||||
type: 'openURL',
|
||||
url: targetChannelPath,
|
||||
query: {mm_openurl: 'from_action_eph'},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastPost = await channelsPage.getLastPost();
|
||||
await lastPost.toBeVisible();
|
||||
const anchorPost = lastPost.container;
|
||||
await anchorPost.hover();
|
||||
await anchorPost.getByRole('button', {name: 'reply'}).click();
|
||||
|
||||
const threadPanel = channelsPage.page.getByRole('region', {name: /Thread/});
|
||||
await expect(threadPanel).toBeVisible();
|
||||
|
||||
const ephemeralInThread = threadPanel.getByTestId('rhsPostView').filter({hasText: ephemeralMarker});
|
||||
await expect(ephemeralInThread).toBeVisible();
|
||||
await ephemeralInThread.getByRole('button', {name: 'Go to Off-Topic'}).click();
|
||||
|
||||
await expect(channelsPage.page).toHaveURL(/\/channels\/off-topic/);
|
||||
expect(new URL(channelsPage.page.url()).searchParams.get('mm_openurl')).toBe('from_action_eph');
|
||||
},
|
||||
);
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user