Merge branch 'master' into MM-51692-delete-reason-feedback-is-sending-notifications-with-translated-text
Этот коммит содержится в:
12
.github/PULL_REQUEST_TEMPLATE.md
поставляемый
12
.github/PULL_REQUEST_TEMPLATE.md
поставляемый
@@ -19,6 +19,18 @@ If this pull request addresses a Help Wanted ticket, please link the relevant Gi
|
||||
Otherwise, link the JIRA ticket.
|
||||
-->
|
||||
|
||||
#### Screenshots
|
||||
<!--
|
||||
If the PR includes UI changes, include screenshots/GIFs.
|
||||
|
||||
For an easier comparison of UI changes a table (template below) can be used.
|
||||
|
||||
| before | after |
|
||||
|----|----|
|
||||
| <insert before screenshot here> | <insert after screenshot here> |
|
||||
|
||||
-->
|
||||
|
||||
#### Release Note
|
||||
<!--
|
||||
Add a release note for each of the following conditions:
|
||||
|
||||
124
.github/workflows/artifacts.yml
поставляемый
Обычный файл
124
.github/workflows/artifacts.yml
поставляемый
Обычный файл
@@ -0,0 +1,124 @@
|
||||
name: Artifacts generation and upload
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Mattermost Build"]
|
||||
types:
|
||||
- completed
|
||||
jobs:
|
||||
upload-s3:
|
||||
name: cd/Upload artifacts to S3
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
REPO_NAME: ${{ github.event.repository.name }}
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: cd/Configure AWS
|
||||
uses: aws-actions/configure-aws-credentials@07c2f971bac433df982ccc261983ae443861db49 # v1-node16
|
||||
with:
|
||||
aws-region: us-east-1
|
||||
aws-access-key-id: ${{ secrets.PR_BUILDS_BUCKET_AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.PR_BUILDS_BUCKET_AWS_SECRET_ACCESS_KEY }}
|
||||
- name: cd/Download artifacts
|
||||
uses: dawidd6/action-download-artifact@0c49384d39ceb023b8040f480a25596fd6cf441b # v2.26.0
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
workflow_conclusion: success
|
||||
name: server-dist-artifact
|
||||
path: server/dist
|
||||
# Get Branch name from calling workflow
|
||||
# Search for the string "pull" and replace it with "PR" in branch-name
|
||||
- name: cd/Get branch name
|
||||
run: echo "BRANCH_NAME=$(echo ${{ github.event.workflow_run.head_branch }} | sed 's/^pull\//PR-/g')" >> $GITHUB_ENV
|
||||
- name: cd/Upload artifacts to S3
|
||||
run: |
|
||||
aws s3 cp server/dist/ s3://pr-builds.mattermost.com/$REPO_NAME/$BRANCH_NAME/ --acl public-read --cache-control "no-cache" --recursive --no-progress
|
||||
aws s3 cp server/dist/ s3://pr-builds.mattermost.com/$REPO_NAME/commit/${{ github.sha }}/ --acl public-read --cache-control "no-cache" --recursive --no-progress
|
||||
build-docker:
|
||||
name: cd/Build and push docker image
|
||||
needs: upload-s3
|
||||
env:
|
||||
REPO_NAME: ${{ github.event.repository.name }}
|
||||
runs-on: ubuntu-22.04
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: cd/Login to Docker Hub
|
||||
uses: docker/login-action@3da7dc6e2b31f99ef2cb9fb4c50fb0971e0d0139 # v2.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_DEV_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_DEV_TOKEN }}
|
||||
- name: cd/Download artifacts
|
||||
uses: dawidd6/action-download-artifact@0c49384d39ceb023b8040f480a25596fd6cf441b # v2.26.0
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
workflow_conclusion: success
|
||||
name: server-build-artifact
|
||||
path: server/build/
|
||||
- name: cd/Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@11e8a2e2910826a92412015c515187a2d6750279 # v2.4
|
||||
- name: cd/Docker build and push
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: enabled
|
||||
run: |
|
||||
export TAG=$(echo "${{ github.event.pull_request.head.sha || github.sha }}" | cut -c1-7)
|
||||
cd server/build
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
export MM_PACKAGE=https://pr-builds.mattermost.com/$REPO_NAME/commit/${{ github.sha }}/mattermost-team-linux-amd64.tar.gz
|
||||
docker buildx build --push --build-arg MM_PACKAGE=$MM_PACKAGE -t mattermostdevelopment/mm-te-test:${TAG} .
|
||||
# Temporary uploading also to mattermost/mm-te-test:${TAG} except mattermostdevelopment/mm-te-test:${TAG}
|
||||
# Context: https://community.mattermost.com/private-core/pl/3jzzxzfiji8hx833ewyuthzkjh
|
||||
build-docker-temp:
|
||||
name: cd/Build and push docker image
|
||||
needs: upload-s3
|
||||
env:
|
||||
REPO_NAME: ${{ github.event.repository.name }}
|
||||
runs-on: ubuntu-22.04
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: cd/Login to Docker Hub
|
||||
uses: docker/login-action@3da7dc6e2b31f99ef2cb9fb4c50fb0971e0d0139 # v2.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: cd/Download artifacts
|
||||
uses: dawidd6/action-download-artifact@0c49384d39ceb023b8040f480a25596fd6cf441b # v2.26.0
|
||||
with:
|
||||
workflow: ${{ github.event.workflow_run.workflow_id }}
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
workflow_conclusion: success
|
||||
name: server-build-artifact
|
||||
path: server/build/
|
||||
- name: cd/Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@11e8a2e2910826a92412015c515187a2d6750279 # v2.4
|
||||
- name: cd/Docker build and push
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: enabled
|
||||
run: |
|
||||
export TAG=$(echo "${{ github.event.pull_request.head.sha || github.sha }}" | cut -c1-7)
|
||||
cd server/build
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
export MM_PACKAGE=https://pr-builds.mattermost.com/$REPO_NAME/commit/${{ github.sha }}/mattermost-team-linux-amd64.tar.gz
|
||||
docker buildx build --push --build-arg MM_PACKAGE=$MM_PACKAGE -t mattermost/mm-te-test:${TAG} .
|
||||
sentry:
|
||||
name: Send build info to sentry
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.MM_SERVER_SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ${{ secrets.MM_SERVER_SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.MM_SERVER_SENTRY_PROJECT }}
|
||||
steps:
|
||||
- name: cd/Checkout mattermost-server
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
- name: cd/Create Sentry release
|
||||
uses: getsentry/action-release@85e0095193a153d57c458995f99d0afd81b9e5ea # v1.3.0
|
||||
|
||||
77
.github/workflows/ci.yml
поставляемый
77
.github/workflows/ci.yml
поставляемый
@@ -1,4 +1,4 @@
|
||||
name: mattermost-build
|
||||
name: Mattermost Build
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
@@ -232,77 +232,4 @@ jobs:
|
||||
with:
|
||||
name: server-build-artifact
|
||||
path: server/build/
|
||||
retention-days: 14
|
||||
upload-s3:
|
||||
name: Upload to S3 bucket
|
||||
runs-on: ubuntu-22.04
|
||||
needs: build-mattermost-server
|
||||
env:
|
||||
REPO_NAME: ${{ github.event.repository.name }}
|
||||
steps:
|
||||
- name: Download dist artifacts
|
||||
uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b # v3.0.2
|
||||
with:
|
||||
name: server-dist-artifact
|
||||
path: server/dist/
|
||||
- name: Configure AWS
|
||||
uses: aws-actions/configure-aws-credentials@07c2f971bac433df982ccc261983ae443861db49 # v1-node16
|
||||
with:
|
||||
aws-region: us-east-1
|
||||
aws-access-key-id: ${{ secrets.MM_SERVER_AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.MM_SERVER_AWS_SECRET_ACCESS_KEY }}
|
||||
# We need to sanitize the branch name before using it
|
||||
- name: ci/sanitize-branch-name
|
||||
id: branch
|
||||
uses: transferwise/sanitize-branch-name@b10b4d524ac5a7b645b43a3527db3a6cca017b9d # v1
|
||||
# Search for the string "pull" and replace it with "PR" in branch-name
|
||||
- name: ci/sanitize-branch-name-replace-pull-with-PR-
|
||||
run: echo "BRANCH_NAME=$(echo ${{ steps.branch.outputs.sanitized-branch-name }} | sed 's/^pull\//PR-/g')" >> $GITHUB_ENV
|
||||
- name: ci/artifact-upload
|
||||
run: |
|
||||
aws s3 cp server/dist/ s3://pr-builds.mattermost.com/$REPO_NAME/$BRANCH_NAME/ --acl public-read --cache-control "no-cache" --recursive
|
||||
aws s3 cp server/dist/ s3://pr-builds.mattermost.com/$REPO_NAME/commit/${{ github.sha }}/ --acl public-read --cache-control "no-cache" --recursive
|
||||
build-docker:
|
||||
name: Build docker image
|
||||
runs-on: ubuntu-22.04
|
||||
needs: upload-s3
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b # v3.0.2
|
||||
with:
|
||||
name: server-build-artifact
|
||||
path: server/build/
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@3da7dc6e2b31f99ef2cb9fb4c50fb0971e0d0139 # v2.1.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@11e8a2e2910826a92412015c515187a2d6750279 # v2.4
|
||||
- name: Docker build and push
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: enabled
|
||||
run: |
|
||||
export TAG=$(echo "${{ github.event.pull_request.head.sha || github.sha }}" | cut -c1-7)
|
||||
cd server/build
|
||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
export MM_PACKAGE=https://pr-builds.mattermost.com/mattermost-server/commit/${GITHUB_SHA}/mattermost-team-linux-amd64.tar.gz
|
||||
docker buildx build --push --build-arg MM_PACKAGE=$MM_PACKAGE -t mattermost/mm-te-test:${TAG} .
|
||||
sentry:
|
||||
name: Send build info to sentry
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- test-postgres-binary
|
||||
- test-postgres-normal
|
||||
- test-mysql
|
||||
- build-mattermost-server
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.MM_SERVER_SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ${{ secrets.MM_SERVER_SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.MM_SERVER_SENTRY_PROJECT }}
|
||||
steps:
|
||||
- name: Checkout mattermost-server
|
||||
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0
|
||||
- name: Create Sentry release
|
||||
uses: getsentry/action-release@85e0095193a153d57c458995f99d0afd81b9e5ea # v1.3.0
|
||||
retention-days: 14
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
/plugin/ @mattermost/toolkit
|
||||
|
||||
/.github/workflows/channels-ci.yml @mattermost/web-platform
|
||||
/webapp/package.json @mattermost/web-platform
|
||||
/webapp/channels/package.json @mattermost/web-platform
|
||||
/webapp/Makefile @mattermost/web-platform
|
||||
/webapp/package-lock.json @mattermost/web-platform
|
||||
/webapp/platform/*/package.json @mattermost/web-platform
|
||||
/webapp/scripts @mattermost/web-platform
|
||||
/webapp/scripts @mattermost/web-platform
|
||||
|
||||
@@ -22,8 +22,6 @@ describe('New Channel modal with Boards enabled', () => {
|
||||
cy.apiLogin(sysadmin);
|
||||
cy.visit(`/${testTeam.name}/channels/town-square`);
|
||||
});
|
||||
|
||||
cy.shouldHaveFeatureFlag('BoardsProduct', true);
|
||||
});
|
||||
|
||||
it('MM-T5141 New Channel is created with an associated Board', () => {
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
// Stage: @prod
|
||||
// Group: @channels @collapsed_reply_threads
|
||||
|
||||
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||
|
||||
describe('Collapsed Reply Threads', () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
@@ -174,4 +176,45 @@ describe('Collapsed Reply Threads', () => {
|
||||
cy.uiCloseRHS();
|
||||
});
|
||||
});
|
||||
|
||||
it('MM-T5413 should auto-scroll to bottom upon pasting long text in reply', () => {
|
||||
// # Post a root post as current user
|
||||
cy.postMessageAs({
|
||||
sender: testUser,
|
||||
message: 'Another interesting post,',
|
||||
channelId: testChannel.id,
|
||||
}).then(({id: rootId}) => {
|
||||
// # Post multiple replies as other user so that the new messages line is pushed up
|
||||
Cypress._.times(20, (i) => {
|
||||
cy.postMessageAs({
|
||||
sender: otherUser,
|
||||
message: 'Reply ' + i,
|
||||
channelId: testChannel.id,
|
||||
rootId,
|
||||
});
|
||||
});
|
||||
|
||||
// # Click root post
|
||||
cy.get(`#post_${rootId}`).click();
|
||||
|
||||
// # Wait for RHS to open and scroll to position
|
||||
cy.wait(TIMEOUTS.ONE_SEC);
|
||||
|
||||
// * RHS should open and the editor's actions should not be visible.
|
||||
cy.get('#rhsContainer').findByTestId('SendMessageButton').should('not.be.visible');
|
||||
|
||||
// # Close RHS
|
||||
cy.uiCloseRHS();
|
||||
|
||||
// # Click root post
|
||||
cy.get(`#post_${rootId}`).click();
|
||||
|
||||
// # Paste a multiline string in the RHS textbox.
|
||||
const text = 'word '.repeat(2000);
|
||||
cy.get('#rhsContainer').findByTestId('reply_textbox').clear().invoke('val', text).trigger('input');
|
||||
|
||||
// * RHS should open and the editor should be visible and focused
|
||||
cy.get('#rhsContainer').findByTestId('SendMessageButton').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('admin console', () => {
|
||||
describe('admin console', {testIsolation: true}, () => {
|
||||
let testUser;
|
||||
let testTeam;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('api > runs', () => {
|
||||
describe('api > runs', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import {onlyOn} from '@cypress/skip-test';
|
||||
|
||||
describe('channels > App Bar', () => {
|
||||
describe('channels > App Bar', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > broadcast', () => {
|
||||
describe('channels > broadcast', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testAdmin;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import {onlyOn} from '@cypress/skip-test';
|
||||
|
||||
describe('channels > channel header', () => {
|
||||
describe('channels > channel header', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// Group: @playbooks
|
||||
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > general actions', () => {
|
||||
describe('channels > general actions', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testSysadmin;
|
||||
let testUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > actions', () => {
|
||||
describe('channels > actions', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testSysadmin;
|
||||
let testUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > post type components', () => {
|
||||
describe('channels > post type components', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testChannel;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > retrospective', () => {
|
||||
describe('runs > retrospective', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybookWithMetrics;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > rhs > header', () => {
|
||||
describe('channels > rhs > header', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import {HALF_SEC, ONE_SEC} from '../../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > rhs > checklist', () => {
|
||||
describe('channels > rhs > checklist', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
@@ -164,7 +164,7 @@ describe('channels > rhs > checklist', () => {
|
||||
});
|
||||
|
||||
// * Verify the expected error message.
|
||||
cy.verifyEphemeralMessage('Failed to execute slash command /invalid');
|
||||
cy.verifyEphemeralMessage('Failed to find slash command /invalid');
|
||||
});
|
||||
|
||||
it('successfully runs a valid slash command', () => {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > rhs > header', () => {
|
||||
describe('channels > rhs > header', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > rhs > home', () => {
|
||||
describe('channels > rhs > home', {testIsolation: true}, () => {
|
||||
let testSysadmin;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > rhs > runlist', () => {
|
||||
describe('channels > rhs > runlist', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels rhs > start a run', () => {
|
||||
describe('channels rhs > start a run', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testChannel;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import * as TIMEOUTS from '../../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > rhs > status update', () => {
|
||||
describe('channels > rhs > status update', {testIsolation: true}, () => {
|
||||
const defaultReminderMessage = '# Default reminder message';
|
||||
let testTeam;
|
||||
let testChannel;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > rhs > template', () => {
|
||||
describe('channels > rhs > template', {testIsolation: true}, () => {
|
||||
let team1;
|
||||
let testUser;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > rhs > title', () => {
|
||||
describe('channels > rhs > title', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > rhs', () => {
|
||||
describe('channels > rhs', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > run dialog', () => {
|
||||
describe('channels > run dialog', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > run', () => {
|
||||
describe('channels > run', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPrivateChannel;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import {switchToChannel} from '../../../channels/mark_as_unread/helpers';
|
||||
|
||||
describe('channels > slash command > owner', () => {
|
||||
describe('channels > slash command > owner', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > slash command > info', () => {
|
||||
describe('channels > slash command > info', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > slash command > owner', () => {
|
||||
describe('channels > slash command > owner', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > slash command > test', () => {
|
||||
describe('channels > slash command > test', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('channels > slash command > todo', () => {
|
||||
describe('channels > slash command > todo', {testIsolation: true}, () => {
|
||||
let team1;
|
||||
let team2;
|
||||
let testUser;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||
|
||||
describe('channels > update request post', () => {
|
||||
describe('channels > update request post', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testParticipant;
|
||||
let testChannelMemberOnly;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('digest messages', () => {
|
||||
describe('digest messages', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import {HALF_SEC} from '../../fixtures/timeouts';
|
||||
import {stubClipboard} from '../../utils';
|
||||
|
||||
describe('lhs', () => {
|
||||
describe('lhs', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPublicPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('navigation', () => {
|
||||
describe('navigation', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbooks > edit', () => {
|
||||
describe('playbooks > edit', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbooks > creation button', () => {
|
||||
describe('playbooks > creation button', {testIsolation: true}, () => {
|
||||
let testSysadmin;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
//
|
||||
import * as TIMEOUTS from '../../../../fixtures/timeouts';
|
||||
|
||||
describe('playbooks > edit > task actions', () => {
|
||||
describe('playbooks > edit > task actions', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/* eslint-disable no-only-tests/no-only-tests */
|
||||
|
||||
describe('playbooks > edit_metrics', () => {
|
||||
describe('playbooks > edit_metrics', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||
|
||||
describe('playbooks > edit', () => {
|
||||
describe('playbooks > edit', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testSysadmin;
|
||||
let testUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbooks > feedback', () => {
|
||||
describe('playbooks > feedback', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbooks > list', () => {
|
||||
describe('playbooks > list', {testIsolation: true}, () => {
|
||||
const playbookTitle = 'The Playbook Name';
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import {stubClipboard} from '../../../utils';
|
||||
|
||||
describe('playbooks > overview', () => {
|
||||
describe('playbooks > overview', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testOtherTeam;
|
||||
let testUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbooks > list pagination', () => {
|
||||
describe('playbooks > list pagination', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
const ExtraPlaybooks = 20;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
const RUN_NAME_MAX_LENGTH = 64;
|
||||
|
||||
describe('playbooks > start a run', () => {
|
||||
describe('playbooks > start a run', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbooks > edit status update', () => {
|
||||
describe('playbooks > edit status update', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPlaybook;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > list', () => {
|
||||
describe('runs > list', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testAnotherUser;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import {getRandomId} from '../../../utils';
|
||||
|
||||
describe('runs > permissions', () => {
|
||||
describe('runs > permissions', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testOtherTeam;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page', () => {
|
||||
describe('runs > run details page', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testPublicPlaybook;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// Note that this test checks the basic behavior in Run details page as participant / viewer
|
||||
// It relies on the Channel RHS Checklist test to cover the full behavior of the checklists
|
||||
|
||||
describe('runs > run details page > checklist', () => {
|
||||
describe('runs > run details page > checklist', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > finish', () => {
|
||||
describe('runs > run details page > finish', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import {stubClipboard} from '../../../utils';
|
||||
|
||||
describe('runs > run details page > header', () => {
|
||||
describe('runs > run details page > header', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > restart run', () => {
|
||||
describe('runs > run details page > restart run', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -62,7 +62,7 @@ const verifyMetricInput = (index, title, target, description, placeholder) => {
|
||||
|
||||
const getRetro = () => cy.findByTestId('run-retrospective-section');
|
||||
|
||||
describe('runs > run details page', () => {
|
||||
describe('runs > run details page', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/* eslint-disable no-only-tests/no-only-tests */
|
||||
|
||||
describe('runs > run details page > status update', () => {
|
||||
describe('runs > run details page > status update', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > summary', () => {
|
||||
describe('runs > run details page > summary', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testRun;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import * as TIMEOUTS from '../../../fixtures/timeouts';
|
||||
|
||||
describe('runs > task actions', () => {
|
||||
describe('runs > task actions', {testIsolation: true}, () => {
|
||||
let testPlaybook;
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > rhs > participants', () => {
|
||||
describe('runs > run details page > rhs > participants', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testUser2;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > run info', () => {
|
||||
describe('runs > run details page > run info', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > RHS', () => {
|
||||
describe('runs > run details page > RHS', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('runs > run details page > status update', () => {
|
||||
describe('runs > run details page > status update', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testViewerUser;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('Task Inbox >', () => {
|
||||
describe('Task Inbox >', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// Stage: @prod
|
||||
// Group: @playbooks
|
||||
|
||||
describe('playbook tour points', () => {
|
||||
describe('playbook tour points', {testIsolation: true}, () => {
|
||||
let testTeam;
|
||||
let testUser;
|
||||
let testSysadmin;
|
||||
|
||||
@@ -176,7 +176,7 @@ Cypress.Commands.add('updateStatus', (message, reminderQuery) => {
|
||||
|
||||
if (reminderQuery) {
|
||||
cy.get('#reminder_timer_datetime').within(() => {
|
||||
cy.get('input').type(reminderQuery, {delay: TIMEOUTS.TWO_HUNDRED_MILLIS, force: true}).type('{enter}', {force: true});
|
||||
cy.get('input').type(reminderQuery, {delay: TIMEOUTS.TWO_HUNDRED_MILLIS, force: true}).wait(TIMEOUTS.ONE_SEC).type('{enter}');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import {expect} from '@playwright/test';
|
||||
import {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {Client, createRandomTeam, getAdminClient, getDefaultAdminUser, makeClient} from './support/server';
|
||||
import {boardsPluginId, callsPluginId} from './support/constant';
|
||||
import {defaultTeam} from './support/util';
|
||||
import testConfig from './test.config';
|
||||
|
||||
@@ -97,26 +96,15 @@ async function printClientInfo(client: Client) {
|
||||
- BuildHashEnterprise = ${config.BuildHashEnterprise}
|
||||
- BuildEnterpriseReady = ${config.BuildEnterpriseReady}
|
||||
- FeatureFlagAppsEnabled = ${config.FeatureFlagAppsEnabled}
|
||||
- FeatureFlagBoardsProduct = ${config.FeatureFlagBoardsProduct}
|
||||
- FeatureFlagCallsEnabled = ${config.FeatureFlagCallsEnabled}
|
||||
- TelemetryId = ${config.TelemetryId}`);
|
||||
}
|
||||
|
||||
function getProductsAsPlugin() {
|
||||
const productsAsPlugin = [callsPluginId];
|
||||
|
||||
if (!testConfig.boardsProductEnabled) {
|
||||
productsAsPlugin.push(boardsPluginId);
|
||||
}
|
||||
|
||||
return productsAsPlugin;
|
||||
}
|
||||
|
||||
async function ensurePluginsLoaded(client: Client) {
|
||||
const pluginStatus = await client.getPluginStatuses();
|
||||
const plugins = await client.getPlugins();
|
||||
|
||||
getProductsAsPlugin().forEach(async (pluginId) => {
|
||||
testConfig.ensurePluginsInstalled.forEach(async (pluginId) => {
|
||||
const isInstalled = pluginStatus.some((plugin) => plugin.plugin_id === pluginId);
|
||||
if (!isInstalled) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export const appsPluginId = 'com.mattermost.apps';
|
||||
export const boardsPluginId = 'focalboard';
|
||||
export const boardsProductId = 'boards';
|
||||
export const callsPluginId = 'com.mattermost.calls';
|
||||
|
||||
@@ -5,22 +5,10 @@ import os from 'node:os';
|
||||
|
||||
import {expect, test} from '@playwright/test';
|
||||
|
||||
import {boardsPluginId, callsPluginId} from './constant';
|
||||
import {callsPluginId} from './constant';
|
||||
import {getAdminClient} from './server/init';
|
||||
import {isSmallScreen} from './util';
|
||||
|
||||
export async function shouldHaveBoardsEnabled(enabled = true) {
|
||||
const {adminClient} = await getAdminClient();
|
||||
const config = await adminClient.getConfig();
|
||||
|
||||
const boardsEnabled =
|
||||
(typeof config.FeatureFlags.BoardsProduct === 'boolean' && config.FeatureFlags.BoardsProduct) ||
|
||||
config.PluginSettings.PluginStates[boardsPluginId].Enable;
|
||||
|
||||
const matched = boardsEnabled === enabled;
|
||||
expect(matched, matched ? '' : `Boards expect "${enabled}" but actual "${boardsEnabled}"`).toBeTruthy();
|
||||
}
|
||||
|
||||
export async function shouldHaveCallsEnabled(enabled = true) {
|
||||
const {adminClient} = await getAdminClient();
|
||||
const config = await adminClient.getConfig();
|
||||
|
||||
@@ -167,8 +167,9 @@ async function makeClient(userRequest?: UserRequest, useCache = true): Promise<C
|
||||
|
||||
const userProfile = await client.login(userRequest.username, userRequest.password);
|
||||
const user = {...userProfile, password: userRequest.password};
|
||||
const config = await client.getClientConfigOld();
|
||||
client.setUseBoardsProduct(config.FeatureFlagBoardsProduct === 'true');
|
||||
|
||||
// Manually do until boards as product is consistent in all the codebase.
|
||||
client.setUseBoardsProduct(true);
|
||||
|
||||
if (useCache) {
|
||||
clients[cacheKey] = {client, user};
|
||||
|
||||
@@ -6,7 +6,6 @@ import merge from 'deepmerge';
|
||||
import {
|
||||
AdminConfig,
|
||||
ExperimentalSettings,
|
||||
FeatureFlags,
|
||||
PasswordSettings,
|
||||
ServiceSettings,
|
||||
TeamSettings,
|
||||
@@ -23,7 +22,6 @@ export function getOnPremServerConfig(): AdminConfig {
|
||||
type TestAdminConfig = {
|
||||
ClusterSettings: Partial<ClusterSettings>;
|
||||
ExperimentalSettings: Partial<ExperimentalSettings>;
|
||||
FeatureFlags: Partial<FeatureFlags>;
|
||||
PasswordSettings: Partial<PasswordSettings>;
|
||||
PluginSettings: Partial<PluginSettings>;
|
||||
ServiceSettings: Partial<ServiceSettings>;
|
||||
@@ -40,9 +38,6 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
ExperimentalSettings: {
|
||||
EnableAppBar: true,
|
||||
},
|
||||
FeatureFlags: {
|
||||
BoardsProduct: testConfig.boardsProductEnabled,
|
||||
},
|
||||
PasswordSettings: {
|
||||
MinimumLength: 5,
|
||||
Lowercase: false,
|
||||
@@ -57,11 +52,6 @@ const onPremServerConfig = (): Partial<TestAdminConfig> => {
|
||||
defaultenabled: true,
|
||||
},
|
||||
},
|
||||
PluginStates: {
|
||||
focalboard: {
|
||||
Enable: !testConfig.boardsProductEnabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
ServiceSettings: {
|
||||
SiteURL: testConfig.baseURL,
|
||||
@@ -686,7 +676,6 @@ const defaultServerConfig: AdminConfig = {
|
||||
GraphQL: false,
|
||||
InsightsEnabled: true,
|
||||
CommandPalette: false,
|
||||
BoardsProduct: false,
|
||||
SendWelcomePost: true,
|
||||
WorkTemplate: false,
|
||||
PostPriority: true,
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import {test as base, Browser} from '@playwright/test';
|
||||
|
||||
import {TestBrowser} from './browser_context';
|
||||
import {
|
||||
shouldHaveBoardsEnabled,
|
||||
shouldHaveCallsEnabled,
|
||||
shouldHaveFeatureFlag,
|
||||
shouldSkipInSmallScreen,
|
||||
shouldRunInLinux,
|
||||
} from './flag';
|
||||
import {shouldHaveCallsEnabled, shouldHaveFeatureFlag, shouldSkipInSmallScreen, shouldRunInLinux} from './flag';
|
||||
import {initSetup, getAdminClient} from './server';
|
||||
import {hideDynamicChannelsContent, waitForAnimationEnd, waitUntil} from './test_action';
|
||||
import {pages} from './ui/pages';
|
||||
@@ -36,7 +30,6 @@ class PlaywrightExtended {
|
||||
readonly testBrowser: TestBrowser;
|
||||
|
||||
// ./flag
|
||||
readonly shouldHaveBoardsEnabled;
|
||||
readonly shouldHaveCallsEnabled;
|
||||
readonly shouldHaveFeatureFlag;
|
||||
readonly shouldSkipInSmallScreen;
|
||||
@@ -62,7 +55,6 @@ class PlaywrightExtended {
|
||||
this.testBrowser = new TestBrowser(browser);
|
||||
|
||||
// ./flag
|
||||
this.shouldHaveBoardsEnabled = shouldHaveBoardsEnabled;
|
||||
this.shouldHaveCallsEnabled = shouldHaveCallsEnabled;
|
||||
this.shouldHaveFeatureFlag = shouldHaveFeatureFlag;
|
||||
this.shouldSkipInSmallScreen = shouldSkipInSmallScreen;
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
import {Page, ViewportSize} from '@playwright/test';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
import {appsPluginId, callsPluginId} from '@e2e-support/constant';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
export type TestArgs = {
|
||||
@@ -17,7 +20,7 @@ export type TestConfig = {
|
||||
adminUsername: string;
|
||||
adminPassword: string;
|
||||
adminEmail: string;
|
||||
boardsProductEnabled: boolean;
|
||||
ensurePluginsInstalled: string[];
|
||||
resetBeforeTest: boolean;
|
||||
haClusterEnabled: boolean;
|
||||
haClusterNodeCount: number;
|
||||
@@ -41,7 +44,10 @@ const config: TestConfig = {
|
||||
adminUsername: process.env.PW_ADMIN_USERNAME || 'sysadmin',
|
||||
adminPassword: process.env.PW_ADMIN_PASSWORD || 'Sys@dmin-sample1',
|
||||
adminEmail: process.env.PW_ADMIN_EMAIL || 'sysadmin@sample.mattermost.com',
|
||||
boardsProductEnabled: parseBool(process.env.PW_BOARDS_PRODUCT_ENABLED, true),
|
||||
ensurePluginsInstalled:
|
||||
typeof process.env?.PW_ENSURE_PLUGINS_INSTALLED === 'string'
|
||||
? process.env.PW_ENSURE_PLUGINS_INSTALLED.split(',')
|
||||
: [appsPluginId, callsPluginId],
|
||||
haClusterEnabled: parseBool(process.env.PW_HA_CLUSTER_ENABLED, false),
|
||||
haClusterNodeCount: parseNumber(process.env.PW_HA_CLUSTER_NODE_COUNT, 2),
|
||||
haClusterName: process.env.PW_HA_CLUSTER_NAME || 'mm_dev_cluster',
|
||||
|
||||
@@ -7,8 +7,6 @@ import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('MM-T4274 Create an Empty Board', async ({pw, pages}) => {
|
||||
await pw.shouldHaveBoardsEnabled();
|
||||
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('Board template', async ({pw, pages, browserName, viewport}, testInfo) => {
|
||||
await pw.shouldHaveBoardsEnabled();
|
||||
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ import {shouldSkipInSmallScreen} from '@e2e-support/flag';
|
||||
shouldSkipInSmallScreen();
|
||||
|
||||
test('View untitled board', async ({pw, pages, browserName, viewport}, testInfo) => {
|
||||
await pw.shouldHaveBoardsEnabled();
|
||||
|
||||
// Create and sign in a new user
|
||||
const {user} = await pw.initSetup();
|
||||
|
||||
|
||||
@@ -19,9 +19,6 @@ type CommandArgs struct {
|
||||
T i18n.TranslateFunc `json:"-"`
|
||||
UserMentions UserMentionMap `json:"-"`
|
||||
ChannelMentions ChannelMentionMap `json:"-"`
|
||||
|
||||
// DO NOT USE Session field is deprecated. MM-26398
|
||||
Session Session `json:"-"`
|
||||
}
|
||||
|
||||
func (o *CommandArgs) Auditable() map[string]interface{} {
|
||||
|
||||
@@ -239,10 +239,10 @@ const (
|
||||
Office365SettingsDefaultTokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
|
||||
Office365SettingsDefaultUserAPIEndpoint = "https://graph.microsoft.com/v1.0/me"
|
||||
|
||||
CloudSettingsDefaultCwsURL = "https://customers.mattermost.com"
|
||||
CloudSettingsDefaultCwsURL = "https://customers.cloud.mattermost.com"
|
||||
CloudSettingsDefaultCwsAPIURL = "https://portal.internal.prod.cloud.mattermost.com"
|
||||
// TODO: update to "https://portal.test.cloud.mattermost.com" when ready to use test license key
|
||||
CloudSettingsDefaultCwsURLTest = "https://customers.mattermost.com"
|
||||
CloudSettingsDefaultCwsURLTest = "https://customers.cloud.mattermost.com"
|
||||
// TODO: update to // "https://api.internal.test.cloud.mattermost.com" when ready to use test license key
|
||||
CloudSettingsDefaultCwsAPIURLTest = "https://portal.internal.prod.cloud.mattermost.com"
|
||||
|
||||
|
||||
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.10.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.23.2. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make plugin-mocks`.
|
||||
|
||||
@@ -22,13 +22,16 @@ func (_m *Driver) Conn(isMaster bool) (string, error) {
|
||||
ret := _m.Called(isMaster)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(bool) (string, error)); ok {
|
||||
return rf(isMaster)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(bool) string); ok {
|
||||
r0 = rf(isMaster)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(bool) error); ok {
|
||||
r1 = rf(isMaster)
|
||||
} else {
|
||||
@@ -57,13 +60,16 @@ func (_m *Driver) ConnExec(connID string, q string, args []driver.NamedValue) (p
|
||||
ret := _m.Called(connID, q, args)
|
||||
|
||||
var r0 plugin.ResultContainer
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, string, []driver.NamedValue) (plugin.ResultContainer, error)); ok {
|
||||
return rf(connID, q, args)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string, []driver.NamedValue) plugin.ResultContainer); ok {
|
||||
r0 = rf(connID, q, args)
|
||||
} else {
|
||||
r0 = ret.Get(0).(plugin.ResultContainer)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, []driver.NamedValue) error); ok {
|
||||
r1 = rf(connID, q, args)
|
||||
} else {
|
||||
@@ -92,13 +98,16 @@ func (_m *Driver) ConnQuery(connID string, q string, args []driver.NamedValue) (
|
||||
ret := _m.Called(connID, q, args)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, string, []driver.NamedValue) (string, error)); ok {
|
||||
return rf(connID, q, args)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string, []driver.NamedValue) string); ok {
|
||||
r0 = rf(connID, q, args)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, []driver.NamedValue) error); ok {
|
||||
r1 = rf(connID, q, args)
|
||||
} else {
|
||||
@@ -141,20 +150,23 @@ func (_m *Driver) RowsColumnTypePrecisionScale(rowsID string, index int) (int64,
|
||||
ret := _m.Called(rowsID, index)
|
||||
|
||||
var r0 int64
|
||||
var r1 int64
|
||||
var r2 bool
|
||||
if rf, ok := ret.Get(0).(func(string, int) (int64, int64, bool)); ok {
|
||||
return rf(rowsID, index)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, int) int64); ok {
|
||||
r0 = rf(rowsID, index)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
var r1 int64
|
||||
if rf, ok := ret.Get(1).(func(string, int) int64); ok {
|
||||
r1 = rf(rowsID, index)
|
||||
} else {
|
||||
r1 = ret.Get(1).(int64)
|
||||
}
|
||||
|
||||
var r2 bool
|
||||
if rf, ok := ret.Get(2).(func(string, int) bool); ok {
|
||||
r2 = rf(rowsID, index)
|
||||
} else {
|
||||
@@ -227,13 +239,16 @@ func (_m *Driver) Stmt(connID string, q string) (string, error) {
|
||||
ret := _m.Called(connID, q)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, string) (string, error)); ok {
|
||||
return rf(connID, q)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string) string); ok {
|
||||
r0 = rf(connID, q)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||
r1 = rf(connID, q)
|
||||
} else {
|
||||
@@ -262,13 +277,16 @@ func (_m *Driver) StmtExec(stID string, args []driver.NamedValue) (plugin.Result
|
||||
ret := _m.Called(stID, args)
|
||||
|
||||
var r0 plugin.ResultContainer
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, []driver.NamedValue) (plugin.ResultContainer, error)); ok {
|
||||
return rf(stID, args)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, []driver.NamedValue) plugin.ResultContainer); ok {
|
||||
r0 = rf(stID, args)
|
||||
} else {
|
||||
r0 = ret.Get(0).(plugin.ResultContainer)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, []driver.NamedValue) error); ok {
|
||||
r1 = rf(stID, args)
|
||||
} else {
|
||||
@@ -297,13 +315,16 @@ func (_m *Driver) StmtQuery(stID string, args []driver.NamedValue) (string, erro
|
||||
ret := _m.Called(stID, args)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, []driver.NamedValue) (string, error)); ok {
|
||||
return rf(stID, args)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, []driver.NamedValue) string); ok {
|
||||
r0 = rf(stID, args)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, []driver.NamedValue) error); ok {
|
||||
r1 = rf(stID, args)
|
||||
} else {
|
||||
@@ -318,13 +339,16 @@ func (_m *Driver) Tx(connID string, opts driver.TxOptions) (string, error) {
|
||||
ret := _m.Called(connID, opts)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, driver.TxOptions) (string, error)); ok {
|
||||
return rf(connID, opts)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, driver.TxOptions) string); ok {
|
||||
r0 = rf(connID, opts)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, driver.TxOptions) error); ok {
|
||||
r1 = rf(connID, opts)
|
||||
} else {
|
||||
@@ -361,3 +385,18 @@ func (_m *Driver) TxRollback(txID string) error {
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewDriver interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewDriver creates a new instance of Driver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewDriver(t mockConstructorTestingTNewDriver) *Driver {
|
||||
mock := &Driver{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.10.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.23.2. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make plugin-mocks`.
|
||||
|
||||
@@ -30,6 +30,10 @@ func (_m *Hooks) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo
|
||||
ret := _m.Called(c, args)
|
||||
|
||||
var r0 *model.CommandResponse
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.CommandArgs) (*model.CommandResponse, *model.AppError)); ok {
|
||||
return rf(c, args)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.CommandArgs) *model.CommandResponse); ok {
|
||||
r0 = rf(c, args)
|
||||
} else {
|
||||
@@ -38,7 +42,6 @@ func (_m *Hooks) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*mo
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, *model.CommandArgs) *model.AppError); ok {
|
||||
r1 = rf(c, args)
|
||||
} else {
|
||||
@@ -55,6 +58,10 @@ func (_m *Hooks) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, fil
|
||||
ret := _m.Called(c, info, file, output)
|
||||
|
||||
var r0 *model.FileInfo
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.FileInfo, io.Reader, io.Writer) (*model.FileInfo, string)); ok {
|
||||
return rf(c, info, file, output)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.FileInfo, io.Reader, io.Writer) *model.FileInfo); ok {
|
||||
r0 = rf(c, info, file, output)
|
||||
} else {
|
||||
@@ -63,7 +70,6 @@ func (_m *Hooks) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, fil
|
||||
}
|
||||
}
|
||||
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, *model.FileInfo, io.Reader, io.Writer) string); ok {
|
||||
r1 = rf(c, info, file, output)
|
||||
} else {
|
||||
@@ -78,6 +84,10 @@ func (_m *Hooks) GetAllCollectionIDsForUser(c *plugin.Context, userID string, co
|
||||
ret := _m.Called(c, userID, collectionType)
|
||||
|
||||
var r0 []string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) ([]string, error)); ok {
|
||||
return rf(c, userID, collectionType)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) []string); ok {
|
||||
r0 = rf(c, userID, collectionType)
|
||||
} else {
|
||||
@@ -86,7 +96,6 @@ func (_m *Hooks) GetAllCollectionIDsForUser(c *plugin.Context, userID string, co
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string) error); ok {
|
||||
r1 = rf(c, userID, collectionType)
|
||||
} else {
|
||||
@@ -101,6 +110,10 @@ func (_m *Hooks) GetAllUserIdsForCollection(c *plugin.Context, collectionType st
|
||||
ret := _m.Called(c, collectionType, collectionID)
|
||||
|
||||
var r0 []string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) ([]string, error)); ok {
|
||||
return rf(c, collectionType, collectionID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) []string); ok {
|
||||
r0 = rf(c, collectionType, collectionID)
|
||||
} else {
|
||||
@@ -109,7 +122,6 @@ func (_m *Hooks) GetAllUserIdsForCollection(c *plugin.Context, collectionType st
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string) error); ok {
|
||||
r1 = rf(c, collectionType, collectionID)
|
||||
} else {
|
||||
@@ -124,6 +136,10 @@ func (_m *Hooks) GetCollectionMetadataByIds(c *plugin.Context, collectionType st
|
||||
ret := _m.Called(c, collectionType, collectionIds)
|
||||
|
||||
var r0 map[string]*model.CollectionMetadata
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) (map[string]*model.CollectionMetadata, error)); ok {
|
||||
return rf(c, collectionType, collectionIds)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) map[string]*model.CollectionMetadata); ok {
|
||||
r0 = rf(c, collectionType, collectionIds)
|
||||
} else {
|
||||
@@ -132,7 +148,6 @@ func (_m *Hooks) GetCollectionMetadataByIds(c *plugin.Context, collectionType st
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, string, []string) error); ok {
|
||||
r1 = rf(c, collectionType, collectionIds)
|
||||
} else {
|
||||
@@ -147,6 +162,10 @@ func (_m *Hooks) GetTopicMetadataByIds(c *plugin.Context, topicType string, topi
|
||||
ret := _m.Called(c, topicType, topicIds)
|
||||
|
||||
var r0 map[string]*model.TopicMetadata
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) (map[string]*model.TopicMetadata, error)); ok {
|
||||
return rf(c, topicType, topicIds)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, []string) map[string]*model.TopicMetadata); ok {
|
||||
r0 = rf(c, topicType, topicIds)
|
||||
} else {
|
||||
@@ -155,7 +174,6 @@ func (_m *Hooks) GetTopicMetadataByIds(c *plugin.Context, topicType string, topi
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, string, []string) error); ok {
|
||||
r1 = rf(c, topicType, topicIds)
|
||||
} else {
|
||||
@@ -170,13 +188,16 @@ func (_m *Hooks) GetTopicRedirect(c *plugin.Context, topicType string, topicID s
|
||||
ret := _m.Called(c, topicType, topicID)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) (string, error)); ok {
|
||||
return rf(c, topicType, topicID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string) string); ok {
|
||||
r0 = rf(c, topicType, topicID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string) error); ok {
|
||||
r1 = rf(c, topicType, topicID)
|
||||
} else {
|
||||
@@ -191,6 +212,10 @@ func (_m *Hooks) Implemented() ([]string, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func() ([]string, error)); ok {
|
||||
return rf()
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func() []string); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
@@ -199,7 +224,6 @@ func (_m *Hooks) Implemented() ([]string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
@@ -224,6 +248,10 @@ func (_m *Hooks) MessageWillBePosted(c *plugin.Context, post *model.Post) (*mode
|
||||
ret := _m.Called(c, post)
|
||||
|
||||
var r0 *model.Post
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.Post) (*model.Post, string)); ok {
|
||||
return rf(c, post)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.Post) *model.Post); ok {
|
||||
r0 = rf(c, post)
|
||||
} else {
|
||||
@@ -232,7 +260,6 @@ func (_m *Hooks) MessageWillBePosted(c *plugin.Context, post *model.Post) (*mode
|
||||
}
|
||||
}
|
||||
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, *model.Post) string); ok {
|
||||
r1 = rf(c, post)
|
||||
} else {
|
||||
@@ -247,6 +274,10 @@ func (_m *Hooks) MessageWillBeUpdated(c *plugin.Context, newPost *model.Post, ol
|
||||
ret := _m.Called(c, newPost, oldPost)
|
||||
|
||||
var r0 *model.Post
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.Post, *model.Post) (*model.Post, string)); ok {
|
||||
return rf(c, newPost, oldPost)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, *model.Post, *model.Post) *model.Post); ok {
|
||||
r0 = rf(c, newPost, oldPost)
|
||||
} else {
|
||||
@@ -255,7 +286,6 @@ func (_m *Hooks) MessageWillBeUpdated(c *plugin.Context, newPost *model.Post, ol
|
||||
}
|
||||
}
|
||||
|
||||
var r1 string
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, *model.Post, *model.Post) string); ok {
|
||||
r1 = rf(c, newPost, oldPost)
|
||||
} else {
|
||||
@@ -361,13 +391,16 @@ func (_m *Hooks) RunDataRetention(nowTime int64, batchSize int64) (int64, error)
|
||||
ret := _m.Called(nowTime, batchSize)
|
||||
|
||||
var r0 int64
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(int64, int64) (int64, error)); ok {
|
||||
return rf(nowTime, batchSize)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(int64, int64) int64); ok {
|
||||
r0 = rf(nowTime, batchSize)
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(int64, int64) error); ok {
|
||||
r1 = rf(nowTime, batchSize)
|
||||
} else {
|
||||
@@ -417,13 +450,16 @@ func (_m *Hooks) UserHasPermissionToCollection(c *plugin.Context, userID string,
|
||||
ret := _m.Called(c, userID, collectionType, collectionId, permission)
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string, string, *model.Permission) (bool, error)); ok {
|
||||
return rf(c, userID, collectionType, collectionId, permission)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*plugin.Context, string, string, string, *model.Permission) bool); ok {
|
||||
r0 = rf(c, userID, collectionType, collectionId, permission)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*plugin.Context, string, string, string, *model.Permission) error); ok {
|
||||
r1 = rf(c, userID, collectionType, collectionId, permission)
|
||||
} else {
|
||||
@@ -451,3 +487,18 @@ func (_m *Hooks) UserWillLogIn(c *plugin.Context, user *model.User) string {
|
||||
func (_m *Hooks) WebSocketMessageHasBeenPosted(webConnID string, userID string, req *model.WebSocketRequest) {
|
||||
_m.Called(webConnID, userID, req)
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewHooks interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewHooks creates a new instance of Hooks. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewHooks(t mockConstructorTestingTNewHooks) *Hooks {
|
||||
mock := &Hooks{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ TEMPLATES_DIR=templates
|
||||
PLUGIN_PACKAGES ?= mattermost-plugin-antivirus-v0.1.2
|
||||
PLUGIN_PACKAGES += mattermost-plugin-autolink-v1.2.2
|
||||
PLUGIN_PACKAGES += mattermost-plugin-aws-SNS-v1.2.0
|
||||
PLUGIN_PACKAGES += mattermost-plugin-calls-v0.14.0
|
||||
PLUGIN_PACKAGES += mattermost-plugin-calls-v0.15.0
|
||||
PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0
|
||||
PLUGIN_PACKAGES += mattermost-plugin-confluence-v1.3.0
|
||||
PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.1
|
||||
@@ -318,11 +318,11 @@ i18n-check: ## Exit on empty translation strings and translation source strings
|
||||
$(GOBIN)/mmgotool i18n check-empty-src --portal-dir=""
|
||||
|
||||
store-mocks: ## Creates mock files.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir channels/store --name ".*Store" --output channels/store/storetest/mocks --note 'Regenerate this file using `make store-mocks`.'
|
||||
|
||||
telemetry-mocks: ## Creates mock files.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir platform/services/telemetry --all --output platform/services/telemetry/mocks --note 'Regenerate this file using `make telemetry-mocks`.'
|
||||
|
||||
store-layers: ## Generate layers for the store
|
||||
@@ -340,39 +340,39 @@ new-migration: ## Creates a new migration. Run with make new-migration name=<>
|
||||
$(GOBIN)/morph generate $(name) --driver postgres --dir channels/db/migrations --sequence
|
||||
|
||||
filestore-mocks: ## Creates mock files.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir platform/shared/filestore --all --output platform/shared/filestore/mocks --note 'Regenerate this file using `make filestore-mocks`.'
|
||||
|
||||
ldap-mocks: ## Creates mock files for ldap.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir $(BUILD_ENTERPRISE_DIR)/ldap --all --output $(BUILD_ENTERPRISE_DIR)/ldap/mocks --note 'Regenerate this file using `make ldap-mocks`.'
|
||||
|
||||
plugin-mocks: ## Creates mock files for plugins.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir ../plugin --name API --output ../plugin/plugintest --outpkg plugintest --case underscore --note 'Regenerate this file using `make plugin-mocks`.'
|
||||
$(GOBIN)/mockery --dir ../plugin --name Hooks --output ../plugin/plugintest --outpkg plugintest --case underscore --note 'Regenerate this file using `make plugin-mocks`.'
|
||||
$(GOBIN)/mockery --dir ../plugin --name Driver --output ../plugin/plugintest --outpkg plugintest --case underscore --note 'Regenerate this file using `make plugin-mocks`.'
|
||||
|
||||
einterfaces-mocks: ## Creates mock files for einterfaces.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir channels/einterfaces --all --output channels/einterfaces/mocks --note 'Regenerate this file using `make einterfaces-mocks`.'
|
||||
|
||||
searchengine-mocks: ## Creates mock files for searchengines.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir platform/services/searchengine --all --output platform/services/searchengine/mocks --note 'Regenerate this file using `make searchengine-mocks`.'
|
||||
|
||||
sharedchannel-mocks: ## Creates mock files for shared channels.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir=./platform/services/sharedchannel --name=ServerIface --output=./platform/services/sharedchannel --inpackage --outpkg=sharedchannel --testonly --note 'Regenerate this file using `make sharedchannel-mocks`.'
|
||||
$(GOBIN)/mockery --dir=./platform/services/sharedchannel --name=AppIface --output=./platform/services/sharedchannel --inpackage --outpkg=sharedchannel --testonly --note 'Regenerate this file using `make sharedchannel-mocks`.'
|
||||
|
||||
misc-mocks: ## Creates mocks for misc interfaces.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir channels/utils --name LicenseValidatorIface --output channels/utils/mocks --note 'Regenerate this file using `make misc-mocks`.'
|
||||
$(GOBIN)/mockery --dir channels/app --name WorkTemplateExecutor --output channels/app/mocks --note 'Regenerate this file using `make misc-mocks`.'
|
||||
|
||||
email-mocks: ## Creates mocks for misc interfaces.
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.10.4
|
||||
$(GO) install github.com/vektra/mockery/v2/...@v2.23.2
|
||||
$(GOBIN)/mockery --dir channels/app/email --name ServiceInterface --output channels/app/email/mocks --note 'Regenerate this file using `make email-mocks`.'
|
||||
|
||||
platform-mocks: ## Creates mocks for platform interfaces.
|
||||
|
||||
@@ -77,10 +77,13 @@ func TestSetConfiguration(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("test enable shared boards", func(t *testing.T) {
|
||||
baseProductSettings := &model.ProductSettings{
|
||||
EnablePublicSharedBoards: &falseRef,
|
||||
}
|
||||
|
||||
mmConfig := baseConfig
|
||||
mmConfig.PluginSettings.Plugins = make(map[string]map[string]interface{})
|
||||
mmConfig.PluginSettings.Plugins[server.PluginName] = make(map[string]interface{})
|
||||
mmConfig.PluginSettings.Plugins[server.PluginName][server.SharedBoardsName] = true
|
||||
mmConfig.ProductSettings = *baseProductSettings
|
||||
mmConfig.ProductSettings.EnablePublicSharedBoards = &boolTrue
|
||||
config := server.CreateBoardsConfig(*mmConfig, "", "")
|
||||
assert.Equal(t, true, config.EnablePublicSharedBoards)
|
||||
})
|
||||
|
||||
@@ -388,6 +388,11 @@ func (th *TestHelper) TearDown() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = th.Server.Store().Shutdown()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
os.RemoveAll(th.Server.Config().FilesPath)
|
||||
|
||||
if err := os.Remove(th.Server.Config().DBConfigString); err == nil {
|
||||
|
||||
@@ -59,8 +59,8 @@ func CreateBoardsConfig(mmconfig mm_model.Config, baseURL string, serverID strin
|
||||
}
|
||||
|
||||
enablePublicSharedBoards := false
|
||||
if mmconfig.PluginSettings.Plugins[PluginName][SharedBoardsName] == true {
|
||||
enablePublicSharedBoards = true
|
||||
if mmconfig.ProductSettings.EnablePublicSharedBoards != nil {
|
||||
enablePublicSharedBoards = *mmconfig.ProductSettings.EnablePublicSharedBoards
|
||||
}
|
||||
|
||||
enableBoardsDeletion := false
|
||||
|
||||
@@ -355,7 +355,7 @@ func (s *Server) Shutdown() error {
|
||||
|
||||
defer s.logger.Info("Server.Shutdown")
|
||||
|
||||
return s.store.Shutdown()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Config() *config.Configuration {
|
||||
|
||||
@@ -177,7 +177,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
|
||||
*cfg.PasswordSettings.Symbol = false
|
||||
*cfg.PasswordSettings.Number = false
|
||||
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
})
|
||||
if err := th.Server.Start(); err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -353,7 +353,6 @@ func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
commandArgs.UserId = c.AppContext.Session().UserId
|
||||
commandArgs.T = c.AppContext.T
|
||||
commandArgs.SiteURL = c.GetSiteURLHeader()
|
||||
commandArgs.Session = *c.AppContext.Session()
|
||||
|
||||
response, err := c.App.ExecuteCommand(c.AppContext, &commandArgs)
|
||||
if err != nil {
|
||||
@@ -424,7 +423,6 @@ func listCommandAutocompleteSuggestions(c *Context, w http.ResponseWriter, r *ht
|
||||
RootId: query.Get("root_id"),
|
||||
UserId: c.AppContext.Session().UserId,
|
||||
T: c.AppContext.T,
|
||||
Session: *c.AppContext.Session(),
|
||||
SiteURL: c.GetSiteURLHeader(),
|
||||
Command: userInput,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestAppRace(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
a, err := New()
|
||||
require.NoError(t, err)
|
||||
a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
|
||||
a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = "localhost:0" })
|
||||
serverErr := a.StartServer()
|
||||
require.NoError(t, serverErr)
|
||||
a.Srv().Shutdown()
|
||||
|
||||
@@ -278,6 +278,7 @@ func TestGetDraftsForUser(t *testing.T) {
|
||||
assert.Nil(t, createDraftErr2)
|
||||
|
||||
t.Run("get drafts", func(t *testing.T) {
|
||||
t.Skip("MM-52088")
|
||||
draftResp, err := th.App.GetDraftsForUser(user.Id, th.BasicTeam.Id)
|
||||
assert.Nil(t, err)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.10.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.23.2. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make email-mocks`.
|
||||
|
||||
@@ -44,6 +44,10 @@ func (_m *ServiceInterface) CreateVerifyEmailToken(userID string, newEmail strin
|
||||
ret := _m.Called(userID, newEmail)
|
||||
|
||||
var r0 *model.Token
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, string) (*model.Token, error)); ok {
|
||||
return rf(userID, newEmail)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string) *model.Token); ok {
|
||||
r0 = rf(userID, newEmail)
|
||||
} else {
|
||||
@@ -52,7 +56,6 @@ func (_m *ServiceInterface) CreateVerifyEmailToken(userID string, newEmail strin
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||
r1 = rf(userID, newEmail)
|
||||
} else {
|
||||
@@ -326,6 +329,10 @@ func (_m *ServiceInterface) SendInviteEmailsToTeamAndChannels(team *model.Team,
|
||||
ret := _m.Called(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||
|
||||
var r0 []*model.EmailInviteWithError
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool, bool, bool) ([]*model.EmailInviteWithError, error)); ok {
|
||||
return rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool, bool, bool) []*model.EmailInviteWithError); ok {
|
||||
r0 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||
} else {
|
||||
@@ -334,7 +341,6 @@ func (_m *ServiceInterface) SendInviteEmailsToTeamAndChannels(team *model.Team,
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool, bool, bool) error); ok {
|
||||
r1 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||
} else {
|
||||
@@ -433,13 +439,16 @@ func (_m *ServiceInterface) SendPasswordResetEmail(_a0 string, token *model.Toke
|
||||
ret := _m.Called(_a0, token, locale, siteURL)
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, *model.Token, string, string) (bool, error)); ok {
|
||||
return rf(_a0, token, locale, siteURL)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, *model.Token, string, string) bool); ok {
|
||||
r0 = rf(_a0, token, locale, siteURL)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, *model.Token, string, string) error); ok {
|
||||
r1 = rf(_a0, token, locale, siteURL)
|
||||
} else {
|
||||
@@ -454,13 +463,16 @@ func (_m *ServiceInterface) SendPaymentFailedEmail(_a0 string, locale string, fa
|
||||
ret := _m.Called(_a0, locale, failedPayment, planName, siteURL)
|
||||
|
||||
var r0 bool
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.FailedPayment, string, string) (bool, error)); ok {
|
||||
return rf(_a0, locale, failedPayment, planName, siteURL)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(string, string, *model.FailedPayment, string, string) bool); ok {
|
||||
r0 = rf(_a0, locale, failedPayment, planName, siteURL)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, string, *model.FailedPayment, string, string) error); ok {
|
||||
r1 = rf(_a0, locale, failedPayment, planName, siteURL)
|
||||
} else {
|
||||
@@ -544,3 +556,18 @@ func (_m *ServiceInterface) SendWelcomeEmail(userID string, _a1 string, verified
|
||||
func (_m *ServiceInterface) Stop() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewServiceInterface interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewServiceInterface creates a new instance of ServiceInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewServiceInterface(t mockConstructorTestingTNewServiceInterface) *ServiceInterface {
|
||||
mock := &ServiceInterface{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 50 })
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.RateLimitSettings.Enable = false })
|
||||
prevListenAddress := *th.App.Config().ServiceSettings.ListenAddress
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = "localhost:0" })
|
||||
serverErr := th.Server.Start()
|
||||
if serverErr != nil {
|
||||
panic(serverErr)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.10.4. DO NOT EDIT.
|
||||
// Code generated by mockery v2.23.2. DO NOT EDIT.
|
||||
|
||||
// Regenerate this file using `make misc-mocks`.
|
||||
|
||||
@@ -22,13 +22,16 @@ func (_m *WorkTemplateExecutor) CreateBoard(c *request.Context, wtcr *worktempla
|
||||
ret := _m.Called(c, wtcr, cBoard, linkToChannelID)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplateBoard, string) (string, error)); ok {
|
||||
return rf(c, wtcr, cBoard, linkToChannelID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplateBoard, string) string); ok {
|
||||
r0 = rf(c, wtcr, cBoard, linkToChannelID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplateBoard, string) error); ok {
|
||||
r1 = rf(c, wtcr, cBoard, linkToChannelID)
|
||||
} else {
|
||||
@@ -43,13 +46,16 @@ func (_m *WorkTemplateExecutor) CreateChannel(c *request.Context, wtcr *worktemp
|
||||
ret := _m.Called(c, wtcr, cChannel)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplateChannel) (string, error)); ok {
|
||||
return rf(c, wtcr, cChannel)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplateChannel) string); ok {
|
||||
r0 = rf(c, wtcr, cChannel)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplateChannel) error); ok {
|
||||
r1 = rf(c, wtcr, cChannel)
|
||||
} else {
|
||||
@@ -64,13 +70,16 @@ func (_m *WorkTemplateExecutor) CreatePlaybook(c *request.Context, wtcr *worktem
|
||||
ret := _m.Called(c, wtcr, playbook, channel)
|
||||
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplatePlaybook, model.WorkTemplateChannel) (string, error)); ok {
|
||||
return rf(c, wtcr, playbook, channel)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplatePlaybook, model.WorkTemplateChannel) string); ok {
|
||||
r0 = rf(c, wtcr, playbook, channel)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*request.Context, *worktemplates.ExecutionRequest, *model.WorkTemplatePlaybook, model.WorkTemplateChannel) error); ok {
|
||||
r1 = rf(c, wtcr, playbook, channel)
|
||||
} else {
|
||||
@@ -93,3 +102,18 @@ func (_m *WorkTemplateExecutor) InstallPlugin(c *request.Context, wtcr *worktemp
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewWorkTemplateExecutor interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewWorkTemplateExecutor creates a new instance of WorkTemplateExecutor. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewWorkTemplateExecutor(t mockConstructorTestingTNewWorkTemplateExecutor) *WorkTemplateExecutor {
|
||||
mock := &WorkTemplateExecutor{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
|
||||
@@ -309,6 +309,10 @@ func (a *App) GetOAuthAccessTokenForCodeFlow(clientId, grantType, redirectURI, c
|
||||
return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "", http.StatusNotFound)
|
||||
}
|
||||
|
||||
if user.DeleteAt != 0 {
|
||||
return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "", http.StatusForbidden)
|
||||
}
|
||||
|
||||
accessData, nErr = a.Srv().Store().OAuth().GetPreviousAccessData(user.Id, clientId)
|
||||
if nErr != nil {
|
||||
return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal.app_error", nil, "", http.StatusBadRequest)
|
||||
|
||||
@@ -633,3 +633,47 @@ func TestDeauthorizeOAuthApp(t *testing.T) {
|
||||
require.Equal(t, store.NewErrNotFound("AuthData", fmt.Sprintf("code=%s", code)), nErr)
|
||||
assert.Nil(t, data)
|
||||
}
|
||||
|
||||
func TestDeactivatedUserOAuthApp(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableOAuthServiceProvider = true })
|
||||
|
||||
oapp := &model.OAuthApp{
|
||||
Name: "fakeoauthapp" + model.NewRandomString(10),
|
||||
CreatorId: th.BasicUser2.Id,
|
||||
Homepage: "https://nowhere.com",
|
||||
Description: "test",
|
||||
CallbackUrls: []string{"https://nowhere.com"},
|
||||
}
|
||||
|
||||
oapp, err := th.App.CreateOAuthApp(oapp)
|
||||
require.Nil(t, err)
|
||||
|
||||
authRequest := &model.AuthorizeRequest{
|
||||
ResponseType: model.ImplicitResponseType,
|
||||
ClientId: oapp.Id,
|
||||
RedirectURI: oapp.CallbackUrls[0],
|
||||
Scope: "",
|
||||
State: "123",
|
||||
}
|
||||
|
||||
redirectUrl, err := th.App.GetOAuthCodeRedirect(th.BasicUser.Id, authRequest)
|
||||
assert.Nil(t, err)
|
||||
|
||||
uri, uErr := url.Parse(redirectUrl)
|
||||
require.NoError(t, uErr)
|
||||
|
||||
queryParams := uri.Query()
|
||||
code := queryParams.Get("code")
|
||||
|
||||
_, appErr := th.App.UpdateActive(th.Context, th.BasicUser, false)
|
||||
require.Nil(t, appErr)
|
||||
|
||||
resp, accErr := th.App.GetOAuthAccessTokenForCodeFlow(oapp.Id, model.AccessTokenGrantType, oapp.CallbackUrls[0], code, oapp.ClientSecret, "")
|
||||
assert.Nil(t, resp)
|
||||
require.NotNil(t, accErr, "Should not get access token")
|
||||
require.Equal(t, http.StatusBadRequest, accErr.StatusCode)
|
||||
assert.Equal(t, "api.oauth.get_access_token.expired_code.app_error", accErr.Id)
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
|
||||
*memoryConfig.AnnouncementSettings.AdminNoticesEnabled = false
|
||||
*memoryConfig.AnnouncementSettings.UserNoticesEnabled = false
|
||||
*memoryConfig.MetricsSettings.Enable = true
|
||||
*memoryConfig.ServiceSettings.ListenAddress = ":0"
|
||||
*memoryConfig.MetricsSettings.ListenAddress = ":0"
|
||||
*memoryConfig.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*memoryConfig.MetricsSettings.ListenAddress = "localhost:0"
|
||||
configStore.Set(memoryConfig)
|
||||
|
||||
ps, err := New(ServiceConfig{
|
||||
|
||||
@@ -112,6 +112,7 @@ func TestMetrics(t *testing.T) {
|
||||
|
||||
require.NotNil(t, th.Service.metrics)
|
||||
metricsAddr := strings.Replace(th.Service.metrics.listenAddr, "[::]", "http://localhost", 1)
|
||||
metricsAddr = strings.Replace(metricsAddr, "127.0.0.1", "http://localhost", 1)
|
||||
|
||||
resp, err := http.Get(metricsAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -547,6 +547,16 @@ func (a *App) SendEphemeralPost(c request.CTX, userID string, post *model.Post)
|
||||
post = a.PreparePostForClientWithEmbedsAndImages(c, post, true, false, true)
|
||||
post = model.AddPostActionCookies(post, a.PostActionCookieSecret())
|
||||
|
||||
sanitizedPost, appErr := a.SanitizePostMetadataForUser(c, post, userID)
|
||||
if appErr != nil {
|
||||
mlog.Error("Failed to sanitize post metadata for user", mlog.String("user_id", userID), mlog.Err(appErr))
|
||||
|
||||
// If we failed to sanitize the post, we still want to remove the metadata.
|
||||
sanitizedPost = post.Clone()
|
||||
sanitizedPost.Metadata = nil
|
||||
}
|
||||
post = sanitizedPost
|
||||
|
||||
postJSON, jsonErr := post.ToJSON()
|
||||
if jsonErr != nil {
|
||||
mlog.Warn("Failed to encode post to JSON", mlog.Err(jsonErr))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
@@ -764,7 +765,24 @@ func cacheLinkMetadata(requestURL string, timestamp int64, og *opengraph.OpenGra
|
||||
platform.LinkCache().SetWithExpiry(strconv.FormatInt(model.GenerateLinkMetadataHash(requestURL, timestamp), 16), metadata, platform.LinkCacheDuration)
|
||||
}
|
||||
|
||||
// peekContentType peeks at the first 512 bytes of p, and attempts to detect
|
||||
// the content type. Returns empty string if error occurs.
|
||||
func peekContentType(p *bufio.Reader) string {
|
||||
byt, err := p.Peek(512)
|
||||
if err != nil && err != bufio.ErrBufferFull && err != io.EOF {
|
||||
return ""
|
||||
}
|
||||
return http.DetectContentType(byt)
|
||||
}
|
||||
|
||||
func (a *App) parseLinkMetadata(requestURL string, body io.Reader, contentType string) (*opengraph.OpenGraph, *model.PostImage, error) {
|
||||
if contentType == "" {
|
||||
bufRd := bufio.NewReader(body)
|
||||
// If the content-type is missing we try to detect it from the actual data.
|
||||
contentType = peekContentType(bufRd)
|
||||
body = bufRd
|
||||
}
|
||||
|
||||
if contentType == "image/svg+xml" {
|
||||
image := &model.PostImage{
|
||||
Format: "svg",
|
||||
|
||||
@@ -2595,6 +2595,18 @@ func TestParseLinkMetadata(t *testing.T) {
|
||||
}, dimensions)
|
||||
})
|
||||
|
||||
t.Run("image with no content-type given", func(t *testing.T) {
|
||||
og, dimensions, err := th.App.parseLinkMetadata(imageURL, makeImageReader(), "")
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Nil(t, og)
|
||||
assert.Equal(t, &model.PostImage{
|
||||
Format: "png",
|
||||
Width: 408,
|
||||
Height: 336,
|
||||
}, dimensions)
|
||||
})
|
||||
|
||||
t.Run("malformed image", func(t *testing.T) {
|
||||
og, dimensions, err := th.App.parseLinkMetadata(imageURL, makeOpenGraphReader(), "image/png")
|
||||
assert.Error(t, err)
|
||||
|
||||
@@ -47,7 +47,7 @@ func newServerWithConfig(t *testing.T, f func(cfg *model.Config)) (*Server, erro
|
||||
|
||||
func TestStartServerSuccess(t *testing.T) {
|
||||
s, err := newServerWithConfig(t, func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -65,7 +65,7 @@ func TestStartServerPortUnavailable(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Listen on the next available port
|
||||
listener, err := net.Listen("tcp", ":0")
|
||||
listener, err := net.Listen("tcp", "localhost:0")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Attempt to listen on the port used above.
|
||||
@@ -104,7 +104,7 @@ func TestStartServerNoS3Bucket(t *testing.T) {
|
||||
AmazonS3PathPrefix: model.NewString(""),
|
||||
AmazonS3SSL: model.NewBool(false),
|
||||
}
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
_, _, err := store.Set(cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestStartServerTLSSuccess(t *testing.T) {
|
||||
s, err := newServerWithConfig(t, func(cfg *model.Config) {
|
||||
testDir, _ := fileutils.FindDir("tests")
|
||||
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*cfg.ServiceSettings.ConnectionSecurity = "TLS"
|
||||
*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
|
||||
*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
|
||||
@@ -185,7 +185,7 @@ func TestStartServerTLSVersion(t *testing.T) {
|
||||
cfg := store.Get()
|
||||
testDir, _ := fileutils.FindDir("tests")
|
||||
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*cfg.ServiceSettings.ConnectionSecurity = "TLS"
|
||||
*cfg.ServiceSettings.TLSMinVer = "1.2"
|
||||
*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
|
||||
@@ -229,7 +229,7 @@ func TestStartServerTLSOverwriteCipher(t *testing.T) {
|
||||
s, err := newServerWithConfig(t, func(cfg *model.Config) {
|
||||
testDir, _ := fileutils.FindDir("tests")
|
||||
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*cfg.ServiceSettings.ConnectionSecurity = "TLS"
|
||||
cfg.ServiceSettings.TLSOverwriteCiphers = []string{
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
@@ -328,7 +328,7 @@ func TestPanicLog(t *testing.T) {
|
||||
|
||||
testDir, _ := fileutils.FindDir("tests")
|
||||
s.platform.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*cfg.ServiceSettings.ConnectionSecurity = "TLS"
|
||||
*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
|
||||
*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
|
||||
@@ -404,7 +404,7 @@ func TestSentry(t *testing.T) {
|
||||
SentryDSN = dsn.String()
|
||||
|
||||
s, err := newServerWithConfig(t, func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*cfg.LogSettings.EnableSentry = false
|
||||
*cfg.ServiceSettings.ConnectionSecurity = "TLS"
|
||||
*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
|
||||
@@ -448,7 +448,7 @@ func TestSentry(t *testing.T) {
|
||||
SentryDSN = dsn.String()
|
||||
|
||||
s, err := newServerWithConfig(t, func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ListenAddress = ":0"
|
||||
*cfg.ServiceSettings.ListenAddress = "localhost:0"
|
||||
*cfg.ServiceSettings.ConnectionSecurity = "TLS"
|
||||
*cfg.ServiceSettings.TLSKeyFile = path.Join(testDir, "tls_test_key.pem")
|
||||
*cfg.ServiceSettings.TLSCertFile = path.Join(testDir, "tls_test_cert.pem")
|
||||
|
||||
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Ссылка в новой задаче
Block a user