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 Nightly Race / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 00:29:55 +05:00
commit 240db4e2a7
15309 changed files with 2173406 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console @compliance_export
import {verifyExportedMessagesCount, editLastPost} from './helpers';
describe('Compliance Export', () => {
let teamName;
before(() => {
cy.apiRequireLicenseForFeature('Compliance');
cy.apiUpdateConfig({
MessageExportSettings: {
ExportFormat: 'csv',
DownloadExportResults: true,
},
});
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
cy.apiLogin(sysadmin);
cy.apiInitSetup().then(({team}) => {
teamName = team.name;
});
// # Visit a channel and post a message so it has something to be exported initially
cy.visit('/');
cy.postMessage('hello');
// # Go to compliance page, enable export and do initial export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport();
cy.uiExportCompliance();
});
});
it('MM-T1177_1 - Compliance export should include updated posts after editing multiple times, exporting multiple times', () => {
// # Visit town-square channel
cy.visit(`/${teamName}/channels/town-square`);
// # Post messages
cy.postMessage('Testing one');
cy.postMessage('Testing two');
// # Edit last post
editLastPost('This is Edit Post');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * 3 messages should be exported
verifyExportedMessagesCount('3');
});
it('MM-T1177_2 - Compliance export should include updated posts after editing multiple times, exporting multiple times', () => {
// # Visit town-square channel
cy.visit(`/${teamName}/channels/town-square`);
// # Post a Message
cy.postMessage('Testing');
// # Edit last post
editLastPost('This is Edit One');
// # Post a Message
cy.postMessage('This is Edit Two');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * 3 messages should be exported
verifyExportedMessagesCount('3');
});
it('MM-T1177_3 - Compliance export should include updated posts after editing multiple times, exporting multiple times', () => {
// # Navigate to a team and post a message
cy.visit(`/${teamName}/channels/town-square`);
cy.postMessage('Testing');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Editing previously exported post
cy.visit(`/${teamName}/channels/town-square`);
editLastPost('This is Edit Three');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * 2 messages should be exported
verifyExportedMessagesCount('2');
});
it('MM-T1177_4 - Compliance export should include updated posts after editing multiple times, exporting multiple times', () => {
// # Navigate to a team and post a Message
cy.visit(`/${teamName}/channels/town-square`);
cy.postMessage('Testing');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Editing previously exported post
cy.visit(`/${teamName}/channels/town-square`);
editLastPost('This is Edit Three');
// # Post new message
cy.postMessage('This is the post');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * 3 messages should be exported
verifyExportedMessagesCount('3');
});
it('MM-T1177_5 - Compliance export should include updated posts after editing multiple times, exporting multiple times', () => {
// # Visit town-square channel
cy.visit(`/${teamName}/channels/town-square`);
// # Navigate to a team and post a message
cy.postMessage('Testing');
// # Editing previously exported post
editLastPost('This is Edit Four');
editLastPost('This is Edit Five');
// # Go to compliance page and export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * 3 messages should be exported
verifyExportedMessagesCount('3');
});
});

View File

@@ -0,0 +1,171 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console @compliance_export
import {verifyExportedMessagesCount, gotoTeamAndPostImage} from './helpers';
import * as TIMEOUTS from '@/fixtures/timeouts';
describe('Compliance Export', () => {
let teamName;
before(() => {
cy.apiRequireLicenseForFeature('Compliance');
cy.apiUpdateConfig({
MessageExportSettings: {
ExportFormat: 'csv',
DownloadExportResults: true,
},
});
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
cy.apiLogin(sysadmin);
cy.apiInitSetup().then(({team}) => {
teamName = team.name;
});
// # Visit a channel and post a message so it has something to be exported initially
cy.visit('/');
cy.postMessage('hello');
// # Go to compliance page, enable export and do initial export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport();
cy.uiExportCompliance();
});
});
it('MM-T3435 - Download Compliance Export Files - CSV Format', () => {
// # Navigate to a team and post an attachment
cy.visit(`/${teamName}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Get the first row
cy.get('.job-table__table').find('tbody > tr').eq(0).as('firstRow');
// # Get the download link
cy.get('@firstRow').findByText('Download').parents('a').should('exist').then((fileAttachment) => {
const fileURL = fileAttachment.attr('href');
// * Download and verify export file properties
cy.apiDownloadFileAndVerifyContentType(fileURL);
});
});
it('MM-T3438 - Download Compliance Export Files when 0 messages exported', () => {
// # Navigate to a team and post an attachment
cy.visit(`/${teamName}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Get the first row
cy.get('.job-table__table').find('tbody > tr').eq(0).as('firstRow');
// # Get the download link
cy.get('@firstRow').findByText('Download').parents('a').should('exist').then((fileAttachment) => {
const fileURL = fileAttachment.attr('href');
// * Download and verify export file properties
cy.apiDownloadFileAndVerifyContentType(fileURL);
// # Export compliance again
cy.uiExportCompliance();
// * Download link should not exist this time
cy.get('.job-table__table').
find('tbody > tr:eq(0)').
findByText('Download').should('not.exist');
});
});
it('MM-T1168 - Compliance Export - Run Now, entry appears in job table', () => {
// # Navigate to a team and post an attachment
cy.visit(`/${teamName}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Get the first row
cy.get('.job-table__table').find('tbody > tr').eq(0).as('firstRow');
// * Verify table header
cy.get('@firstheader').within(() => {
cy.get('th:eq(0)').should('have.text', 'Status');
cy.get('th:eq(1)').should('have.text', 'Finish Time');
cy.get('th:eq(2)').should('have.text', 'Run Time');
cy.get('th:eq(3)').should('have.text', 'Files');
cy.get('th:eq(4)').should('have.text', 'Details');
});
// * Verify first row (last run job) data
cy.get('@firstRow').within(() => {
cy.get('td:eq(0)').should('have.text', 'Success');
cy.get('td:eq(2)').contains('seconds');
cy.get('td:eq(3)').should('have.text', 'Download');
cy.get('td:eq(4)').should('have.text', '1 message exported.');
});
});
it('MM-T1169 - Compliance Export - CSV and Global Relay', () => {
// # Navigate to a team and post an attachment
cy.visit(`/${teamName}/channels/town-square`);
gotoTeamAndPostImage();
// # Post 9 text messages
Cypress._.times(9, (i) => {
cy.postMessage(`This is the post ${i}`);
});
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * 10 messages should be exported
verifyExportedMessagesCount('10');
});
it('MM-T1165 - Compliance Export - Fields disabled when disabled', () => {
// # Go to compliance page and disable export
cy.uiGoToCompliancePage();
cy.findByTestId('enableComplianceExportfalse').click();
// * Verify that exported button is disabled
cy.findByRole('button', {name: /run compliance export job now/i}).should('be.not.enabled');
});
it('MM-T1167 - Compliance Export job can be canceled', () => {
// # Go to compliance page and enable export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport();
// # Click the export job button
cy.findByRole('button', {name: /run compliance export job now/i}).click();
// # Click X button to cancel import
cy.findByTitle(/cancel/i, {timeout: TIMEOUTS.FIVE_SEC}).should('be.visible').click();
// # Get the first row
cy.get('.job-table__table').find('tbody > tr').eq(0).as('firstRow');
// * Canceled text should be shown in the first row of the table
cy.get('@firstRow').find('td:eq(0)').should('have.text', 'Canceled');
});
});

View File

@@ -0,0 +1,306 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console
import {
gotoGlobalPolicy,
editGlobalPolicyMessageRetention,
runDataRetentionAndVerifyPostDeleted,
verifyPostNotDeleted,
} from './helpers';
describe('Data Retention - Global and Custom Policy Only', () => {
let testTeam;
let testChannel;
let users;
let channelA;
let channelB;
let channelC;
let newTeam;
const postText = 'This is testing';
before(() => {
cy.apiRequireLicenseForFeature('DataRetention');
cy.apiUpdateConfig({
ServiceSettings: {
EnableUserAccessTokens: true,
},
});
cy.apiInitSetup().then(({team, channel, user}) => {
testTeam = team;
testChannel = channel;
users = user.id;
});
});
beforeEach(() => {
cy.apiDeleteAllCustomRetentionPolicies();
cy.intercept({
method: 'POST',
url: '/api/v4/data_retention/policies',
}).as('createCustomPolicy');
// # Go to data retention settings
cy.uiGoToDataRetentionPage();
});
it('MM-T4093 - Assign Global Policy = 10 Days & Custom Policy = None to channel', () => {
gotoGlobalPolicy();
// # Edit global policy message retention
editGlobalPolicyMessageRetention('10', '10 days');
// * Verify there is no any team and channel assigned
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.get('.DataGrid_rows .DataGrid_empty').first().should('contain.text', 'No items found');
});
let testChannel2;
cy.apiCreateChannel(testTeam.id, 'test_channel', 'testChannel2').then(({channel}) => {
testChannel2 = channel;
});
// # Create 13 days older post
// # Get Epoch value
const createDate = new Date().setDate(new Date().getDate() - 13);
const createDate2 = new Date().setDate(new Date().getDate() - 7);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate);
cy.apiPostWithCreateDate(testChannel2.id, postText, token, createDate2);
// * Run the job and verify 13 days older post has been deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify 7 days older post is not deleted
verifyPostNotDeleted(testTeam, testChannel2, postText);
});
});
it('MM-T4099 - Assign Global Policy = 10 Days & Custom Policy = 5 days to Channels', () => {
// # Edit Global Policy to 10 days
gotoGlobalPolicy();
editGlobalPolicyMessageRetention('10', '10 days');
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '5');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
// # Create channel-A
cy.apiCreateChannel(testTeam.id, 'channel-test', 'GlobalChannel-1').then(({channel}) => {
channelA = channel;
});
// # Create channel-B
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Custom-Channel1').then(({channel}) => {
channelB = channel;
});
// # Create channel-C
cy.apiCreateChannel(testTeam.id, 'channel-test', 'Global-Channel-2').then(({channel}) => {
channelC = channel;
});
// * Verify create policy api response
cy.wait('@createCustomPolicy').then((interception) => {
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '5 days', '1 team, 0 channels');
});
});
// # Create more than 3,7, and 12 days older post
// # Get Epoch value
const createDate1 = new Date().setDate(new Date().getDate() - 7);
const createDate2 = new Date().setDate(new Date().getDate() - 3);
const createDate3 = new Date().setDate(new Date().getDate() - 12);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate1);
cy.apiPostWithCreateDate(channelA.id, postText, token, createDate2);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate2);
cy.apiPostWithCreateDate(channelC.id, postText, token, createDate3);
// * Run the job and verify 7 days older post is deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify 7 days older post is not deleted
verifyPostNotDeleted(testTeam, channelA, postText);
// * Verify 3 days older post is not deleted
verifyPostNotDeleted(testTeam, channelB, postText);
// * Verify 12 days older post is deleted
verifyPostNotDeleted(testTeam, channelC, postText, 1);
});
});
it('MM-T4101 - Assign Global Policy = 5 days & Custom Policy = None to Teams', () => {
// # Edit global policy to 5 days
gotoGlobalPolicy();
editGlobalPolicyMessageRetention('5', '5 days');
// * Verify there is no any team and channel assigned
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.get('.DataGrid_rows .DataGrid_empty').first().should('contain.text', 'No items found');
});
// # Create new channel
let testChannel2;
cy.apiCreateChannel(testTeam.id, 'channel-test', 'OtherChannel ').then(({channel}) => {
testChannel2 = channel;
});
// # Create new Team and Channel
cy.apiCreateTeam('team', 'Team1').then(({team}) => {
cy.apiCreateChannel(team.id, 'test_channel', 'Channel-A').then(({channel}) => {
newTeam = team;
channelA = channel;
});
});
// # Create 3 and 7 days older posts
// # Get Epoch value
const createDays1 = new Date().setDate(new Date().getDate() - 7);
const createDays2 = new Date().setDate(new Date().getDate() - 3);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDays1);
cy.apiPostWithCreateDate(testChannel2.id, postText, token, createDays1);
cy.apiPostWithCreateDate(channelA.id, postText, token, createDays2);
// * Run the job and verify 7 days older posts have been deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel2, postText);
// * Verify 3 days older post was not deleted
verifyPostNotDeleted(newTeam, channelA, postText);
});
});
it('MM-T4103 - Assign Global Policy = 10 days & Custom Policy = 5 days to Team', () => {
// # Edit global policy to 5 days
gotoGlobalPolicy();
editGlobalPolicyMessageRetention('10', '10 days');
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '5');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '5 days', '1 team, 0 channels');
});
});
// # Create channel-A
cy.apiCreateChannel(testTeam.id, 'channel-test', 'GlobalChannel-1').then(({channel}) => {
channelA = channel;
});
// # Create a new Team and Channel
cy.apiCreateTeam('team', 'Team1').then(({team}) => {
newTeam = team;
cy.apiCreateChannel(newTeam.id, 'test_channel', 'Channel-A').then(({channel}) => {
channelB = channel;
});
// # Create a new channel in newTeam
cy.apiCreateChannel(newTeam.id, 'channel-test', 'Global-Channel-2').then(({channel}) => {
channelC = channel;
});
});
// # Create more than 3,7, and 12 days older posts
// # Get Epoch value
const createDate1 = new Date().setDate(new Date().getDate() - 7);
const createDate2 = new Date().setDate(new Date().getDate() - 3);
const createDate3 = new Date().setDate(new Date().getDate() - 12);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate1);
cy.apiPostWithCreateDate(channelA.id, postText, token, createDate2);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate1);
cy.apiPostWithCreateDate(channelC.id, postText, token, createDate3);
// * Run the job and verify 7 days older post is deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify 7 days older post is not deleted
verifyPostNotDeleted(testTeam, channelA, postText);
// * Verify 3 days older post is not deleted
verifyPostNotDeleted(newTeam, channelB, postText);
// * Verify 12 days older post is deleted
verifyPostNotDeleted(newTeam, channelC, postText, 1);
});
});
it('MM-T4096 - Assign Global Policy = 1 Year & Custom Policy = None to channel', () => {
// # Edit global policy to 1 year
gotoGlobalPolicy();
editGlobalPolicyMessageRetention('365', '1 year');
// * Verify there is no any team and channel assigned
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.get('.DataGrid_rows .DataGrid_empty').first().should('contain.text', 'No items found');
});
// # Create a new channel
cy.apiCreateChannel(testTeam.id, 'channel-test', 'GlobalChannel ').then(({channel}) => {
channelA = channel;
});
// # Create less than one year and one year older post
// # Get Epoch value
const createDate1 = new Date().setMonth(new Date().getMonth() - 14);
const createDate2 = new Date().setMonth(new Date().getMonth() - 10);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate1);
cy.apiPostWithCreateDate(channelA.id, postText, token, createDate2);
// * Run the job and verify 1 year older post has been deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify less than one year post was not deleted
verifyPostNotDeleted(testTeam, channelA, postText);
});
});
});

View File

@@ -0,0 +1,350 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console
import {
runDataRetentionAndVerifyPostDeleted,
gotoGlobalPolicy,
editGlobalPolicyMessageRetention,
verifyPostNotDeleted,
} from './helpers';
describe('Data Retention - Custom Policy Only', () => {
let testTeam;
let testChannel;
let users;
const postText = 'This is testing';
before(() => {
cy.apiRequireLicenseForFeature('DataRetention');
cy.apiUpdateConfig({
ServiceSettings: {
EnableUserAccessTokens: true,
},
});
cy.apiInitSetup().then(({team, channel, user}) => {
testTeam = team;
testChannel = channel;
users = user.id;
});
});
beforeEach(() => {
cy.apiDeleteAllCustomRetentionPolicies();
cy.intercept({
method: 'POST',
url: '/api/v4/data_retention/policies',
}).as('createCustomPolicy');
// # Go to data retention settings page
cy.uiGoToDataRetentionPage();
});
it('MM-T4097 - Assign Global Policy = Forever & Custom Policy = 10 days to Channel', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '10');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '10 days', '0 teams, 1 channel');
});
});
// # Create new Channel
let channelB;
cy.apiCreateChannel(testTeam.id, 'test_channel', 'channelB').then(({channel}) => {
channelB = channel;
});
// # Create 12 days older posts
// # Get Epoch value
const createDate = new Date().setDate(new Date().getDate() - 12);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate);
// * Run the job and verify 12 days older post is deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify 12 days older post is not deleted
verifyPostNotDeleted(testTeam, channelB, postText);
});
});
it('MM-T4098 - Assign Global Policy = Forever & Custom Policy = 1 year to Channels', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '365');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '1 year', '0 teams, 1 channel');
});
});
// # Create new Channel
let channelB;
cy.apiCreateChannel(testTeam.id, 'test_channel', ' channelB').then(({channel}) => {
channelB = channel;
});
// # Create more than one year older posts
// # Get Epoch value
const createDate = new Date().setMonth(new Date().getMonth() - 14);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate);
// * Run the job and verify more than one year older post is deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify more than one year older post is not deleted
verifyPostNotDeleted(testTeam, channelB, postText);
});
});
it('MM-T4105 - Assign Global Policy = Forever & Custom Policy = 1 year to Teams', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '365');
// # Add a team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '1 year', '1 team, 0 channels');
});
});
// # Create new Team and Channel
let newTeam;
let channelB;
cy.apiCreateTeam('team', 'Team1').then(({team}) => {
cy.apiCreateChannel(team.id, 'test_channel', 'channelB').then(({channel}) => {
newTeam = team;
channelB = channel;
});
});
// # Create more than one year older posts
// # Get Epoch value
const createDate = new Date().setMonth(new Date().getMonth() - 14);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate);
// * Run the job and verify more than one year older post has been deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify more then one year older post is not deleted
verifyPostNotDeleted(newTeam, channelB, postText);
});
});
it('MM-T4102 - Assign Global Policy = Forever & Custom Policy = 30 days to Teams', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '30');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '30 days', '1 team, 0 channels');
});
});
// # Create new Team and Channel
let channelB;
let newTeam;
cy.apiCreateTeam('team', 'Team1').then(({team}) => {
cy.apiCreateChannel(team.id, 'test_channel', 'channelB').then(({channel}) => {
channelB = channel;
newTeam = team;
});
});
// # Create more than one year older post
// # Get Epoch value
const createDate = new Date().setDate(new Date().getDate() - 32);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate);
// * Run the job and verify 32 days older post is deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify 32 days old post is not deleted
verifyPostNotDeleted(newTeam, channelB, postText);
});
});
it('MM-T4104 - Assign Global policy = Forever & Custom Policy = 5 and 10 days to Teams', () => {
// # Create a new Channel
let testChannel2;
cy.apiCreateChannel(testTeam.id, 'test_channel', 'TestChannel2').then(({channel}) => {
testChannel2 = channel;
});
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '5');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '5 days', '1 team, 0 channels');
});
});
// # Create new Team and Channels
let newTeam;
let channelA;
let channelB;
cy.apiCreateTeam('team', 'Team1').then(({team}) => {
newTeam = team;
// # Create new Channel
cy.apiCreateChannel(team.id, 'test_channel', 'test_channelC').then(({channel}) => {
channelB = channel;
});
cy.apiCreateChannel(team.id, 'test_channel', 'Channel-A').then(({channel}) => {
channelA = channel;
// # Create second policy
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy1', 'days', '10');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([newTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy1', '10 days', '1 team, 0 channels');
});
});
});
});
// # Create more 3,7, and 12 days older posts
// # Get Epoch values
const createDate1 = new Date().setDate(new Date().getDate() - 7);
const createDate2 = new Date().setDate(new Date().getDate() - 3);
const createDate3 = new Date().setDate(new Date().getDate() - 12);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate1);
cy.apiPostWithCreateDate(testChannel2.id, postText, token, createDate2);
cy.apiPostWithCreateDate(channelA.id, postText, token, createDate3);
cy.apiPostWithCreateDate(channelB.id, postText, token, createDate2);
// * Run the job and Verify 7 days older post in testChannel is deleted
runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText);
// * Verify 3 days older post in testChennel2 is not deleted
verifyPostNotDeleted(testTeam, testChannel2, postText);
// * Verify 12 days older post in ChannelA is deleted
cy.visit(`/${newTeam.name}/channels/${channelA.name}`);
cy.findAllByTestId('postView').should('have.length', 1);
cy.findAllByTestId('postView').should('not.contain', postText);
// * Verify 3 days older post in channelB is not deleted
verifyPostNotDeleted(newTeam, channelB, postText);
});
});
it('MM-T4019 - Global Data Retention policy', () => {
[
{input: '365', result: '1 year'},
{input: '700', result: '700 days'},
{input: '730', result: '2 years'},
{input: '600', result: '600 days'},
].forEach(({input, result}) => {
gotoGlobalPolicy();
// # Edit global policy message retention
editGlobalPolicyMessageRetention(input, result);
});
});
});

View File

@@ -0,0 +1,107 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console
import {
runDataRetentionAndVerifyPostDeleted,
gotoGlobalPolicy,
editGlobalPolicyMessageRetention,
} from './helpers';
describe('Data Retention - Global and Custom Policy', () => {
let testTeam;
let testChannel;
let users;
const postText = 'This is testing';
before(() => {
cy.apiRequireLicenseForFeature('DataRetention');
cy.apiUpdateConfig({
ServiceSettings: {
EnableUserAccessTokens: true,
},
});
cy.apiInitSetup().then(({team, channel, user}) => {
testTeam = team;
testChannel = channel;
users = user.id;
});
});
beforeEach(() => {
cy.apiDeleteAllCustomRetentionPolicies();
cy.intercept({
method: 'POST',
url: '/api/v4/data_retention/policies',
}).as('createCustomPolicy');
// # Go to data retention settings page
cy.uiGoToDataRetentionPage();
});
it('MM-T4100 - Assign Global Policy = 5 days & Custom Policy = 10 days to channels', () => {
let newChannel;
let newTeam;
// # Edit Global Policy to 5 days
gotoGlobalPolicy();
editGlobalPolicyMessageRetention('5', '5 days');
// # Create a new team
cy.apiCreateTeam('team', 'Team1').then(({team}) => {
cy.apiCreateChannel(team.id, 'test_channel', 'Channel-A').then(({channel}) => {
newChannel = channel;
newTeam = team;
});
});
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '10');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'MyPolicy', '10 days', '0 teams, 1 channel');
});
});
// # Create more than 7 days older post
// # Get Epoch value
const createDate = new Date().setDate(new Date().getDate() - 7);
cy.apiCreateToken(users).then(({token}) => {
// # Create posts
cy.apiPostWithCreateDate(newChannel.id, postText, token, createDate);
cy.apiPostWithCreateDate(testChannel.id, postText, token, createDate);
// * Run the job and verify 7 days older post in newChannel has been deleted
runDataRetentionAndVerifyPostDeleted(newTeam, newChannel, postText);
// * Verify 7 days older post in testChannel was not deleted
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
cy.findAllByTestId('postView').should('have.length', 2);
cy.findAllByTestId('postView').should('contain', postText);
});
});
});

View File

@@ -0,0 +1,561 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @enterprise @system_console @with_feature_flag
import * as TIMEOUTS from '@/fixtures/timeouts';
describe('Data Retention', () => {
let testTeam;
let testChannel;
before(() => {
cy.apiRequireLicenseForFeature('DataRetention');
cy.apiInitSetup().then(({team, channel}) => {
testTeam = team;
testChannel = channel;
});
});
beforeEach(() => {
cy.apiDeleteAllCustomRetentionPolicies();
cy.intercept({
method: 'POST',
url: '/api/v4/data_retention/policies',
}).as('createCustomPolicy');
// # Go to data retention settings page
cy.uiGoToDataRetentionPage();
});
describe('Custom policy creation', () => {
it('MM-T4005 - Create custom policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'days', '60');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Add 1 channel to the policy from the modal
cy.uiAddRandomChannelToCustomPolicy(1);
// # Save policy
cy.uiGetButton('Save').click();
// * Check custom policy table is visible
cy.get('#custom_policy_table .DataGrid').should('be.visible');
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy response
cy.uiVerifyPolicyResponse(interception.response.body, 1, 1, 60, 'Policy 1');
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(interception.response.body.id, 'Policy 1', '60 days', '1 team, 1 channel');
});
});
});
it('MM-T4006 - Policies count', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'days', '60');
// # Add channel to the policy
cy.uiAddRandomChannelToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 2', 'days', '160');
// # Add channel to the policy
cy.uiAddRandomChannelToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 3', 'days', '100');
// # Add channel to the policy
cy.uiAddRandomChannelToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
// * Assert the pagination is correct
cy.findByText('1 - 3 of 3').scrollIntoView().should('be.visible');
cy.apiGetCustomRetentionPolicies().then((result) => {
// * Assert the total policy count is 3
expect(result.body.total_count).to.equal(3);
});
});
it('MM-T4007 - show policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'days', '60');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Add 1 channel to the policy from the modal
cy.uiAddRandomChannelToCustomPolicy(1);
// # Save policy
cy.uiGetButton('Save').click();
cy.findByText('1 - 1 of 1').scrollIntoView().should('be.visible');
});
it('MM-T4008 - Update custom policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 2', 'years', '2');
// # Add team to the policy
cy.uiAddRandomTeamToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
// * Check custom policy table is visible
cy.get('#custom_policy_table .DataGrid').should('be.visible');
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 1, 0, 730, 'Policy 2');
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 2', '2 years', '1 team, 0 channels');
// # Go to edit custom data retention page
cy.uiClickEditCustomPolicyRow(policyId);
});
// * Verify custom policy page header
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
// # Remove team from policy
cy.get('.PolicyTeamsList .DataGrid').within(() => {
cy.findByRole('link', {name: 'Remove'}).should('be.visible').click();
});
// # Add channel to the policy
cy.uiAddRandomChannelToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
// * Check custom policy table is visible
cy.get('#custom_policy_table .DataGrid').should('be.visible');
// * Verify custom policy data table
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 2', '2 years', '0 teams, 1 channel');
});
// # Send GET request to verify policy updated correctly
cy.apiGetCustomRetentionPolicy(policyId).then((result) => {
// * Assert response body team_count is 0
expect(result.body.team_count).to.equal(0);
// * Assert response body channel_count is 1
expect(result.body.channel_count).to.equal(1);
// * Assert response body post_duration is 730
expect(result.body.post_duration).to.equal(730);
// * Assert response body display_name is correct
expect(result.body.display_name).to.equal('Policy 2');
});
});
});
it('MM-T4009 - Delete a custom policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Add policy name
cy.uiGetTextbox('Policy name').clear().type('Policy 3');
// # Add channel to the policy
cy.uiAddRandomChannelToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
// * Check custom policy table is visible
cy.get('#custom_policy_table .DataGrid').should('be.visible');
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 0, 1, -1, 'Policy 3');
const policyId = interception.response.body.id;
cy.get('#custom_policy_table .DataGrid').within(() => {
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 3', 'Keep forever', '0 teams, 1 channel');
cy.get(`#customWrapper-${policyId}`).trigger('mouseover').click();
// # Delete a policy
cy.findByRole('button', {name: 'Delete'}).should('be.visible').click();
// # Wait for deletion
cy.wait(TIMEOUTS.ONE_SEC);
// * Assert the policy row no longer exists
cy.get(`#customDescription-${policyId}`).should('not.exist');
});
});
});
});
describe('Teams in a custom Policy', () => {
it('MM-T4010 - Show policy teams information', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '2');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 1, 0, 730, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '2 years', '1 team, 0 channels');
// # Go to edit custom data retention page
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiClickEditCustomPolicyRow(policyId);
});
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
// * Verify Team data table exists
cy.get('.PolicyTeamsList .DataGrid').within(() => {
cy.get(`#team-name-${testTeam.id}`).should('be.visible');
});
// * GET the team for the policy and verify it is correct
cy.apiGetCustomRetentionPolicyTeams(policyId).then((result) => {
expect(result.body.teams[0].id).to.equal(testTeam.id);
});
});
});
it('MM-T4012 - Search teams in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '2');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Add channel to the policy
cy.uiAddRandomTeamToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 2, 0, 730, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '2 years', '2 teams, 0 channels');
// # Go to edit custom data retention page
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiClickEditCustomPolicyRow(policyId);
});
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
cy.get('.PolicyTeamsList .DataGrid').within(() => {
// # Find the team table search box and type in team name
cy.findByRole('textbox').should('be.visible').clear().type(testTeam.name);
cy.wait(TIMEOUTS.ONE_SEC);
// * Verify the team is visible after search
cy.get(`#team-name-${testTeam.id}`).should('be.visible').invoke('text').should('include', testTeam.display_name);
});
// * Search the team for the policy using the API and verify it is correct
cy.apiSearchCustomRetentionPolicyTeams(policyId, testTeam.display_name).then((result) => {
expect(result.body[0].id).to.equal(testTeam.id);
});
});
});
it('MM-T4018 - Number of teams in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '2');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Add channels to the policy
cy.uiAddRandomTeamToCustomPolicy(2);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 3, 0, 730, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '2 years', '3 teams, 0 channels');
// # Go to edit custom data retention page
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiClickEditCustomPolicyRow(policyId);
});
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
// * Verify team table pagination
cy.get('.PolicyTeamsList .DataGrid').within(() => {
cy.findByText('1 - 3 of 3').scrollIntoView().should('be.visible');
});
// * GET the teams for the policy and verify the count is correct
cy.apiGetCustomRetentionPolicyTeams(policyId).then((result) => {
expect(result.body.teams.length).to.equal(3);
});
});
});
it('MM-T4011 - Add team in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('MyPolicy', 'days', '60');
// # Add team to the policy
cy.uiAddTeamsToCustomPolicy([testTeam.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
// * Verify team table pagination
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.get('.DataGrid_rows .DataGrid_cell').first().should('contain.text', 'MyPolicy').click();
});
cy.get('.DataGrid_row .DataGrid_cell').first().should('contain', testTeam.display_name);
});
});
describe('Channels in a custom Policy', () => {
it('MM-T4017 - Total channels in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '2');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Add 2 channels to the policy from the modal
cy.uiAddRandomChannelToCustomPolicy(2);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 0, 3, 730, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '2 years', '0 teams, 3 channels');
// # Go to edit custom data retention page
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiClickEditCustomPolicyRow(policyId);
});
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
// * Verify Channel pagination
cy.get('.PolicyChannelsList .DataGrid').within(() => {
cy.findByText('1 - 3 of 3').scrollIntoView().should('be.visible');
});
// * GET the channels for the policy and verify the count
cy.apiGetCustomRetentionPolicyChannels(policyId).then((result) => {
expect(result.body.channels.length).to.equal(3);
});
});
});
it('MM-T4014 - Add channel in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '2');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 0, 1, 730, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '2 years', '0 teams, 1 channel');
// * GET the channel for the policy and verify it is correct
cy.apiGetCustomRetentionPolicyChannels(policyId).then((result) => {
expect(result.body.channels[0].id).to.equal(testChannel.id);
});
});
});
it('MM-T4015 - Delete channel in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '1');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Add 2 channels to the policy
cy.uiAddRandomChannelToCustomPolicy(2);
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 0, 3, 365, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '1 year', '0 teams, 3 channels');
// # Go to edit custom data retention page
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiClickEditCustomPolicyRow(policyId);
});
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
// # Remove channel from policy
cy.get('.PolicyChannelsList .DataGrid').within(() => {
cy.findAllByRole('link', {name: 'Remove'}).first().should('exist').click();
});
// # Save policy
cy.uiGetButton('Save').click();
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '1 year', '0 teams, 2 channels');
// * GET the channel for the policy and verify the count is correct
cy.apiGetCustomRetentionPolicyChannels(policyId).then((result) => {
expect(result.body.channels.length).to.equal(2);
});
});
});
it('MM-T4016 - Search channels in policy', () => {
// # Go to create custom data retention page
cy.uiClickCreatePolicy();
// # Fill out policy details
cy.uiFillOutCustomPolicyFields('Policy 1', 'years', '2');
// # Add channel to the policy
cy.uiAddChannelsToCustomPolicy([testChannel.display_name]);
// # Add channel to the policy
cy.uiAddRandomChannelToCustomPolicy();
// # Save policy
cy.uiGetButton('Save').click();
cy.wait('@createCustomPolicy').then((interception) => {
// * Verify create policy api response
cy.uiVerifyPolicyResponse(interception.response.body, 0, 2, 730, 'Policy 1');
const policyId = interception.response.body.id;
// * Verify custom policy data table
cy.uiVerifyCustomPolicyRow(policyId, 'Policy 1', '2 years', '0 teams, 2 channels');
// # Go to edit custom data retention page
cy.get('#custom_policy_table .DataGrid').within(() => {
cy.uiClickEditCustomPolicyRow(policyId);
});
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Custom Retention Policy');
// # Scroll down the custom policy form page
cy.get('.DataRetentionSettings .admin-console__wrapper').scrollTo('bottom');
cy.get('.PolicyChannelsList .DataGrid').within(() => {
// This will not type the space for display name?
cy.findByRole('textbox').should('be.visible').clear().type(testChannel.name);
cy.wait(TIMEOUTS.ONE_SEC);
cy.get(`#channel-name-${testChannel.id}`).should('be.visible').invoke('text').should('include', testChannel.display_name);
});
cy.apiSearchCustomRetentionPolicyChannels(policyId, testChannel.display_name).then((result) => {
expect(result.body[0].id).to.equal(testChannel.id);
});
});
});
});
});

View File

@@ -0,0 +1,130 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console @compliance_export
import {
downloadAndUnzipExportFile,
verifyActianceXMLFile,
verifyPostsCSVFile,
} from './helpers';
describe('Compliance Export', () => {
const downloadsFolder = Cypress.config('downloadsFolder');
let newTeam;
let newChannel;
let botId;
let botName;
before(() => {
cy.apiRequireLicenseForFeature('Compliance');
cy.apiUpdateConfig({
MessageExportSettings: {
ExportFormat: 'csv',
DownloadExportResults: true,
},
ServiceSettings: {
EnforceMultifactorAuthentication: false,
},
});
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
cy.apiLogin(sysadmin);
//# Create a test bot
cy.apiCreateBot().then(({bot}) => {
({user_id: botId, display_name: botName} = bot);
cy.apiPatchUserRoles(bot.user_id, ['system_admin', 'system_user']);
});
cy.apiInitSetup().then(({team, channel}) => {
newTeam = team;
newChannel = channel;
// # Do initial export
exportCompliance();
});
});
});
after(() => {
cy.shellRm('-rf', downloadsFolder);
});
it('MM-T1175_1 - UserType identifies that the message is posted by a bot', () => {
const message = `This is CSV bot message from ${botName} at ${Date.now()}`;
// # Post bot message
postBotMessage(newTeam, newChannel, botId, message);
// # Go to Compliance page and run report
exportCompliance();
// # Download and Unzip exported file
const targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Export file should contain bot messages
verifyPostsCSVFile(
targetFolder,
'have.string',
`${message},message,bot`,
);
});
it('MM-T1175_2 - UserType identifies that the message is posted by a bot', () => {
const message = `This is XML bot message from ${botName} at ${Date.now()}`;
// # Post bot message
postBotMessage(newTeam, newChannel, botId, message);
// # Go to Compliance and enable run export
exportCompliance('Actiance XML');
// # Download and Unzip exported File
const targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Export file should message from bot
verifyActianceXMLFile(
targetFolder,
'have.string',
message,
);
verifyActianceXMLFile(
targetFolder,
'have.string',
'<UserType>bot</UserType>',
);
});
});
function postBotMessage(newTeam, newChannel, botId, message) {
cy.apiCreateToken(botId).then(({token}) => {
// # Logout to allow posting as bot
cy.apiLogout();
cy.apiCreatePost(newChannel.id, message, '', {attachments: [{pretext: 'Look some text', text: 'This is text'}]}, token);
// # Re-login to validate post presence
cy.apiAdminLogin();
cy.visit(`/${newTeam.name}/channels/${newChannel.name}`);
// * Validate post was created
cy.findByText(message).should('be.visible');
});
}
function exportCompliance(type) {
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport(type);
cy.uiExportCompliance();
}

View File

@@ -0,0 +1,288 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Stage: @prod
// Group: @channels @enterprise @system_console @compliance_export
import {
downloadAndUnzipExportFile,
editLastPost,
gotoTeamAndPostImage,
verifyActianceXMLFile,
verifyPostsCSVFile,
} from './helpers';
describe('Compliance Export', () => {
const ExportFormatActiance = 'Actiance XML';
const downloadsFolder = Cypress.config('downloadsFolder');
let newTeam;
let newUser;
let newChannel;
let adminUser;
before(() => {
cy.apiRequireLicenseForFeature('Compliance');
cy.apiUpdateConfig({
MessageExportSettings: {
ExportFormat: 'csv',
DownloadExportResults: true,
},
});
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
adminUser = sysadmin;
cy.apiLogin(adminUser);
cy.apiInitSetup().then(({team, user, channel}) => {
newTeam = team;
newUser = user;
newChannel = channel;
});
});
});
after(() => {
cy.shellRm('-rf', downloadsFolder);
});
it('MM-T1172 - Compliance Export - Deleted file is indicated in CSV File Export', () => {
// # Go to compliance page and enable export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport();
// # Navigate to a team and post an attachment
cy.visit(`/${newTeam.name}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Deleting last post
deleteLastPost();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Download and extract export zip file
const targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying if export file contains delete
verifyPostsCSVFile(
targetFolder,
'have.string',
'deleted attachment',
);
});
it('MM-T1173 - Compliance Export - Deleted file is indicated in Actiance XML File Export', () => {
// # Go to compliance page and enable export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport(ExportFormatActiance);
// # Navigate to a team and post an attachment
cy.visit(`/${newTeam.name}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Delete last post
deleteLastPost();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Download and extract exported zip file
const targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying if export file contains deleted image
verifyActianceXMLFile(
targetFolder,
'have.string',
'delete file uploaded-image-400x400.jpg',
);
// * Verifying if image has been downloaded
cy.shellFind(targetFolder, /image-400x400.jpg/).then((files) => {
expect(files.length).not.to.equal(0);
});
});
it('MM-T3436 - Download Compliance Export Files - Actiance XML Format', () => {
// # Go to compliance page and enable export in Actiance XML format
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport(ExportFormatActiance);
// # Navigate to a team and post a message with an attachment
cy.visit(`/${newTeam.name}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// * Verify the Download option is provided for the export job
cy.get('@firstRow').findByText('Download').should('exist');
// # Download and extract exported zip file
const targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying if export file contains the posted message content
verifyActianceXMLFile(
targetFolder,
'have.string',
'file uploaded-image-400x400.jpg',
);
// * Verifying if the attached file is included in the export
cy.shellFind(targetFolder, /image-400x400.jpg/).then((files) => {
expect(files.length).not.to.equal(0);
});
});
it('MM-T1176 - Compliance export should include updated post after editing', () => {
// # Go to compliance page and enable export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport(ExportFormatActiance);
// # Navigate to a team and post a message
cy.visit(`/${newTeam.name}/channels/town-square`);
cy.postMessage('Testing');
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Visit town-square channel and edit the last post
cy.visit(`/${newTeam.name}/channels/town-square`);
editLastPost('Hello');
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Download and extract exported zip file
const targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying if export file contains edited text
verifyActianceXMLFile(
targetFolder,
'have.string',
'<Content>Hello</Content>',
);
});
it('MM-T3305 - Verify Deactivated users are displayed properly in Compliance Exports', () => {
// # Post a message by Admin
cy.postMessageAs({
sender: adminUser,
message: `@${newUser.username} : Admin 1`,
channelId: newChannel.id,
});
cy.visit(`/${newTeam.name}/channels/${newChannel.id}`);
// # Deactivate the newly created user
cy.apiDeactivateUser(newUser.id);
// # Go to compliance page and enable export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport(ExportFormatActiance);
cy.uiExportCompliance();
// # Download and extract exported zip file
let targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying if export file contains deactivated user info
verifyActianceXMLFile(
targetFolder,
'have.string',
`<LoginName>${newUser.username}@sample.mattermost.com</LoginName>`,
);
// # Post a message by Admin
cy.postMessageAs({
sender: adminUser,
message: `@${newUser.username} : Admin2`,
channelId: newChannel.id,
});
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Download and extract exported zip file
targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying export file should not contain deactivated user name
verifyActianceXMLFile(
targetFolder,
'not.have.string',
`<LoginName>${newUser.username}@sample.mattermost.com</LoginName>`,
);
// # Re-activate the user
cy.apiActivateUser(newUser.id);
// # Post a message by Admin
cy.postMessageAs({
sender: adminUser,
message: `@${newUser.username} : Admin3`,
channelId: newChannel.id,
});
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Download and extract exported zip file
targetFolder = `${downloadsFolder}/${Date.now().toString()}`;
downloadAndUnzipExportFile(targetFolder);
// * Verifying if export file contains deactivated user name
verifyActianceXMLFile(
targetFolder,
'have.string',
`<LoginName>${newUser.username}@sample.mattermost.com</LoginName>`,
);
});
});
function deleteLastPost() {
cy.apiGetTeamsForUser().then(({teams}) => {
const team = teams[0];
cy.visit(`/${team.name}/channels/town-square`);
cy.getLastPostId().then((lastPostId) => {
// # Click post dot menu in center.
cy.clickPostDotMenu(lastPostId);
// # Scan inside the post menu dropdown
cy.get(`#CENTER_dropdown_${lastPostId}`).should('exist').within(() => {
// # Click on the delete post button from the dropdown
cy.findByText('Delete').should('exist').click();
});
});
cy.get('.a11y__modal.modal-dialog').should('exist').and('be.visible').
within(() => {
// # Confirm click on the delete button for the post
cy.findByText('Delete').should('be.visible').click();
});
});
}

View File

@@ -0,0 +1,184 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import path from 'path';
import * as TIMEOUTS from '@/fixtures/timeouts';
export function downloadAndUnzipExportFile(targetFolder = '') {
// # Get the download link
cy.get('@firstRow').findByText('Download').parents('a').should('exist').then((fileAttachment) => {
// # Getting export file url
const fileURL = fileAttachment.attr('href');
const targetFilePath = path.join(targetFolder);
const zipFile = targetFilePath + '.zip';
// # Download zip file
cy.request({url: fileURL, encoding: 'binary'}).then((response) => {
expect(response.status).to.equal(200);
cy.writeFile(zipFile, response.body, 'binary');
});
// # Unzip exported file then "csv_export.zip"
cy.shellUnzip(zipFile, targetFilePath);
cy.shellFind(targetFilePath, /csv_export.zip/).then((files) => {
cy.shellUnzip(files[files.length - 1], targetFilePath);
});
});
}
export function verifyPostsCSVFile(targetFolder, type, match) {
cy.readFile(`${targetFolder}/posts.csv`).
should('exist').
and(type, match);
}
export function verifyActianceXMLFile(targetFolder, type, match) {
cy.readFile(`${targetFolder}/actiance_export.xml`).
should('exist').
and(type, match);
}
export function verifyExportedMessagesCount(expectedNumber) {
// * Verifying number of exported messages
cy.get('@firstRow').find('td:eq(4)').should('have.text', `${expectedNumber} messages exported.`);
}
export function editLastPost(message) {
cy.getLastPostId().then(() => {
cy.uiGetPostTextBox().clear().type('{uparrow}');
// # Edit Post Input should appear
cy.get('#edit_textbox').should('be.visible');
// # Update the post message and type ENTER
cy.get('#edit_textbox').invoke('val', '').type(message);
cy.get('#create_post').findByText('Save').should('be.visible').click();
// * Edit modal should not be visible
cy.get('#edit_textbox').should('not.exist');
});
}
export function gotoTeamAndPostImage() {
cy.uiGetPostTextBox().then((createPostEl) => {
if (createPostEl.find('.file-preview__container').length === 1) {
// # Remove images from post message footer if exist
cy.waitUntil(() => cy.uiGetFileUploadPreview().then((filePreviewEl) => {
if (filePreviewEl.find('.post-image.normal').length > 0) {
cy.get('.file-preview__remove > .icon').click();
}
return filePreviewEl.find('.post-image.normal').length === 0;
}));
}
const file = {
filename: 'image-400x400.jpg',
originalSize: {width: 400, height: 400},
thumbnailSize: {width: 400, height: 400},
};
cy.get('#fileUploadInput').attachFile(file.filename);
// # Wait until the image is uploaded
cy.uiWaitForFileUploadPreview();
cy.postMessage(`file uploaded-${file.filename}`);
});
}
export function gotoGlobalPolicy() {
// # Click edit on global policy data table
cy.get('#global_policy_table .DataGrid .MenuWrapper').trigger('mouseover').click();
cy.findByRole('button', {name: /edit/i}).should('be.visible').click();
cy.get('.DataRetentionSettings .admin-console__header', {timeout: TIMEOUTS.TWO_MIN}).should('be.visible').invoke('text').should('include', 'Global Retention Policy');
}
export function editGlobalPolicyMessageRetention(input, result) {
cy.get('.DataRetentionSettings #global_direct_message_dropdown #DropdownInput_channel_message_retention').as('dropDown');
// * Checking if Global Policy is already created
cy.request({
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: '/api/v4/data_retention/policy',
method: 'GET',
}).then((response) => {
expect(response.status).to.equal(200);
if (response.body.message_deletion_enabled === true) {
// # Click message retention dropdown and select 'Keep forever' option
cy.get('@dropDown').click();
cy.get('.channel_message_retention_dropdown__menu .channel_message_retention_dropdown__option span.option_forever').should('be.visible').click();
}
});
// # Click message retention dropdown and select 'Days' option
cy.get('@dropDown').click();
cy.get('.channel_message_retention_dropdown__menu .channel_message_retention_dropdown__option span.option_days').should('be.visible').click();
// # Input retention days
cy.get('.DataRetentionSettings #global_direct_message_dropdown input#channel_message_retention_input').clear().type(input);
// # Save Global Policy
cy.findByRole('button', {name: 'Save'}).should('be.visible').click();
// * Assert global policy data table is visible
cy.get('#global_policy_table .DataGrid').should('be.visible');
// * Assert global policy message retention is correct
cy.findByTestId('global_message_retention_cell').within(() => {
cy.get('span').should('have.text', result);
});
}
export function editGlobalPolicyFileRetention(input, result) {
// # Click file retention dropdown
cy.get('.DataRetentionSettings #global_file_dropdown #DropdownInput_file_retention').should('be.visible').click();
// # Select days from file retention dropdown
cy.get('.file_retention_dropdown__menu .file_retention_dropdown__option span.option_days').should('be.visible').click();
// # Input retention days
cy.get('.DataRetentionSettings #global_file_dropdown input#file_retention_input').clear().type(input);
// # Save Global Policy
cy.findByRole('button', {name: 'Save'}).should('be.visible').click();
// * Assert global policy data table is visible
cy.get('#global_policy_table .DataGrid').should('be.visible');
// * Assert global policy file retention is correct
cy.findByTestId('global_file_retention_cell').within(() => {
cy.get('span').should('have.text', result);
});
}
export function runDataRetentionAndVerifyPostDeleted(testTeam, testChannel, postText) {
cy.uiGoToDataRetentionPage();
cy.findByRole('button', {name: 'Run Deletion Job Now'}).click();
// # Small wait to ensure new row is add
cy.wait(TIMEOUTS.FIVE_SEC);
// # Waiting for Data Retention process to finish
cy.get('.job-table__table').find('tbody > tr').eq(0).as('firstRow');
cy.get('@firstRow').within(() => {
cy.get('td:eq(0)', {timeout: TIMEOUTS.FOUR_MIN}).should('have.text', 'Success');
});
// * Verifying if post has been deleted
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
cy.reload();
cy.findAllByTestId('postView').should('have.length', 1);
cy.findAllByTestId('postView').should('not.contain', postText);
}
export function verifyPostNotDeleted(testTeam, testChannel, postText, expectedNoOfPosts = 2) {
cy.visit(`/${testTeam.name}/channels/${testChannel.name}`);
cy.findAllByTestId('postView').should('have.length', expectedNoOfPosts);
if (expectedNoOfPosts === 2) {
cy.findAllByTestId('postView').should('contain', postText);
} else {
cy.findAllByTestId('postView').should('not.contain', postText);
}
}

View File

@@ -0,0 +1,98 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************
// Group: @channels @enterprise @system_console @compliance_export @not_cloud
// Requires "mattermost-minio" docker instance to be accessible at http://localhost:9000
// and a bucket named "mattermost-test". Bucket can be created manually in the UI or by:
// ``docker exec mattermost-minio sh -c 'mkdir -p /data/mattermost-test'``
import {gotoTeamAndPostImage} from './helpers';
import * as TIMEOUTS from '@/fixtures/timeouts';
describe('Compliance Export', () => {
let teamName;
before(() => {
cy.shouldNotRunOnCloudEdition();
cy.apiRequireLicenseForFeature('Compliance');
cy.apiUpdateConfig({
MessageExportSettings: {
ExportFormat: 'csv',
DownloadExportResults: true,
},
});
cy.apiCreateCustomAdmin().then(({sysadmin}) => {
cy.apiLogin(sysadmin);
cy.apiInitSetup().then(({team}) => {
teamName = team.name;
});
// # Visit a channel and post a message so it has something to be exported initially
cy.visit('/');
cy.postMessage('hello');
// # Go to compliance page, enable export and do export
cy.uiGoToCompliancePage();
cy.uiEnableComplianceExport();
cy.uiExportCompliance();
});
});
it('MM-T3439 - Download Compliance Export Files - S3 Bucket Storage', () => {
// # Go to file storage settings Page
cy.visit('/admin_console/environment/file_storage');
cy.get('.admin-console__header', {timeout: TIMEOUTS.ONE_MIN}).should('be.visible').and('have.text', 'File Storage');
const {
minioAccessKey,
minioSecretKey,
minioS3Bucket,
minioS3Endpoint,
minioS3SSL,
} = Cypress.expose();
// # Update S3 Storage settings
cy.findByTestId('FileSettings.DriverNamedropdown').select('amazons3');
cy.findByTestId('FileSettings.AmazonS3Bucketinput').clear().type(minioS3Bucket);
cy.findByTestId('FileSettings.AmazonS3AccessKeyIdinput').clear().type(minioAccessKey);
cy.findByTestId('FileSettings.AmazonS3SecretAccessKeyinput').clear().type(minioSecretKey);
cy.findByTestId('FileSettings.AmazonS3Endpointinput').clear().type(minioS3Endpoint);
cy.findByTestId(`FileSettings.AmazonS3SSL${minioS3SSL}`).check();
// # Save file storage settings
cy.uiSaveConfig();
// # Test connection and verify that it's successful
cy.findByRole('button', {name: 'Test Connection'}).click();
cy.findByText('Connection was successful').should('be.visible');
// # Navigate to a team and post an attachment
cy.visit(`/${teamName}/channels/town-square`);
gotoTeamAndPostImage();
// # Go to compliance page and start export
cy.uiGoToCompliancePage();
cy.uiExportCompliance();
// # Get the first row
cy.get('.job-table__table').find('tbody > tr').eq(0).as('firstRow');
// # Get the download link
cy.get('@firstRow').findByText('Download').parents('a').should('exist').then((fileAttachment) => {
const fileURL = fileAttachment.attr('href');
// * Download link should not exist this time
cy.apiDownloadFileAndVerifyContentType(fileURL);
});
});
});