Fixtures that allow install of a plugin from a target repo (#34520)
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Blocked by required conditions
Web App CI / check-types (push) Blocked by required conditions
Web App CI / test (platform) (push) Blocked by required conditions
Web App CI / test (mattermost-redux) (push) Blocked by required conditions
Web App CI / test (channels shard 1/4) (push) Blocked by required conditions
Web App CI / test (channels shard 2/4) (push) Blocked by required conditions
Web App CI / test (channels shard 3/4) (push) Blocked by required conditions
Web App CI / test (channels shard 4/4) (push) Blocked by required conditions
Web App CI / upload-coverage (push) Blocked by required conditions
Web App CI / build (push) Blocked by required conditions

* Fixtures that allow install of a plugin from a target repo

* Fixed linting error and applied `prettier` formating.

* Implemeted feedback from code review

* Remove unused AdminConfig import

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Dylan Haussermann 2026-01-27 08:41:49 -05:00 committed by GitHub
parent dfbe788732
commit 8e7b3da702
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 116 additions and 0 deletions

View file

@ -8,3 +8,5 @@ export {initSetup, getAdminClient} from './init';
export {createRandomPost} from './post';
export {createNewTeam, createRandomTeam} from './team';
export {createNewUserProfile, createRandomUser, getDefaultAdminUser, isOutsideRemoteUserHour} from './user';
export {installAndEnablePlugin, isPluginActive, getPluginStatus} from './plugin';
//getPluginStatus

View file

@ -0,0 +1,56 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Client4} from '@mattermost/client';
import {PluginManifest} from '@mattermost/types/plugins';
export async function isPluginActive(client: Client4, pluginId: string): Promise<boolean> {
const plugins = await client.getPlugins();
return plugins.active.some((plugin: PluginManifest) => plugin.id === pluginId);
}
export async function getPluginStatus(
client: Client4,
pluginId: string,
): Promise<{isInstalled: boolean; isActive: boolean}> {
const plugins = await client.getPlugins();
const isActive = plugins.active.some((plugin: PluginManifest) => plugin.id === pluginId);
const isInactive = plugins.inactive.some((plugin: PluginManifest) => plugin.id === pluginId);
return {
isInstalled: isActive || isInactive,
isActive,
};
}
/**
* Installs and enables a plugin with smart status checking
* - If already active: does nothing
* - If already installed: just enables it
* - Otherwise: installs from URL, then enables
*/
export async function installAndEnablePlugin(
client: Client4,
pluginUrl: string,
pluginId: string,
force = true,
): Promise<void> {
// Check current status
const status = await getPluginStatus(client, pluginId);
// If already active, nothing to do
if (status.isActive) {
return;
}
// If already installed but not active, just enable it
if (status.isInstalled) {
await client.enablePlugin(pluginId);
return;
}
// Not installed - install from URL then enable
await client.installPluginFromUrl(pluginUrl, force);
await client.enablePlugin(pluginId);
}

View file

@ -29,6 +29,8 @@ import {
isOutsideRemoteUserHour,
makeClient,
mergeWithOnPremServerConfig,
installAndEnablePlugin,
isPluginActive,
} from './server';
import {
toBeFocusedWithFocusVisible,
@ -89,6 +91,8 @@ export class PlaywrightExtended {
readonly getAdminClient;
readonly mergeWithOnPremServerConfig;
readonly initSetup;
readonly installAndEnablePlugin;
readonly isPluginActive;
// ./test_action
readonly toBeFocusedWithFocusVisible;
@ -149,6 +153,8 @@ export class PlaywrightExtended {
this.getAdminClient = getAdminClient;
this.mergeWithOnPremServerConfig = mergeWithOnPremServerConfig;
this.isOutsideRemoteUserHour = isOutsideRemoteUserHour;
this.installAndEnablePlugin = installAndEnablePlugin;
this.isPluginActive = isPluginActive;
// ./test_action
this.toBeFocusedWithFocusVisible = toBeFocusedWithFocusVisible;

View file

@ -0,0 +1,52 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {test, expect} from '@mattermost/playwright-lib';
test('should install and enable demo plugin from URL', async ({pw}) => {
// Create and navigate to channels page
const {adminClient, user} = await pw.initSetup();
const {channelsPage} = await pw.testBrowser.login(user);
await channelsPage.goto();
await channelsPage.toBeVisible();
// Enable public links before installing plugin
await adminClient.patchConfig({
FileSettings: {EnablePublicLink: true},
ServiceSettings: {
EnableOnboardingFlow: false,
EnableTutorial: false,
},
});
// Install and enable
await pw.installAndEnablePlugin(
adminClient,
'https://github.com/mattermost/mattermost-plugin-demo/releases/download/v0.10.3/mattermost-plugin-demo-v0.10.3.tar.gz',
'com.mattermost.demo-plugin',
);
// Verify it's active (API validation, no UI)
await expect
.poll(async () => {
return await pw.isPluginActive(adminClient, 'com.mattermost.demo-plugin');
})
.toBe(true);
// Optional: Get plugin details
const plugins = await adminClient.getPlugins();
const demoPlugin = plugins.active.find((p) => p.id === 'com.mattermost.demo-plugin');
expect(demoPlugin).toBeDefined();
// Dismiss overlay again if it reappeared after plugin activation
await channelsPage.page.keyboard.press('Escape');
await channelsPage.page.waitForTimeout(500);
// UI Validation: Execute slash command and verify response
await channelsPage.postMessage('/demo_plugin true');
const post = await channelsPage.getLastPost();
await post.toBeVisible();
await post.toContainText('enabled');
});