Skip to content

Commit

Permalink
E2E playwright (#663)
Browse files Browse the repository at this point in the history
* initial config for playwright tests

* move files

* add test for `/github setup`

* remove comment

* change test name

* point to webapp repo, and automatically adjust playwright config to use github repo

* reference mm-webapp directly via tsconfig.json, and npm runn commands

* add await for completeness

* fix plugin upload

* add assertion for connect link URL

* use cypress comment conventions

* add show-report command

* move code around

* setup and connect work with mock oauth server

* add functionality for mock oauth server

* finish setup and connect tests

* rename env var

* change oauth token env var name

* rearrange gitignore

* run oauth server inside of playwright tests

* add base github action

* changes for running playwright

* ci env var

* run ci unconditionally

* more ci changes

* change ci docker image

* remove mm-webapp dependency

* split up ci steps

* fix npm dep cache path

* use mickmister fork for webapp repo

* fix setup-environment

* fix webapp repo checkout

* change setup-environment to have webapp repo fetch its deps

* move env var to step

* move env var to test step

* run ci headless

* add longer waits

* add more screenshot steps for debugging ci

* map oauth server port in ci config

* use docker network-alias to connect to oauth server

* change image version

* typo

* use user-defined bridge network aliases

* add go build flag for compiling plugin

* change ci container image

* use go 1.18 to build plugin

* use go 1.18 for build folder go.mod

* use GO_BUILD_FLAGS when compiling build tools

* bump ci go version to make vcs error show

* force buildvcs=false go build flag

* change database connection string

* temporarily hardcode db host because env var doesn't apply in playwright test

* fix db host

* set db host manually

* npx playwright install --with-deps

* use playwright docker image

* revert changes to make it so we build on runner process again

* use docker host ubuntu ip

* test must pass

* changes for monorepo

* remove import of webapp test setup in webapp tests

* use testBrowser.login()

* try ci with just iphone platform

* upload test-results artifacts

* include test results in artifact

* mv files

* upload artifacts unconditionally

* run test for all devices

* use ldflags to communicate with mock oauth server

* use PLUGIN_GITHUB_E2E_OAUTH_TOKEN

* use custom playwright config

* fail when oauth token is not provided

* change artifact logic since we're running config in cwd now

* change telemetry key being used

* change name of oauth token secret

* change secret name pt. 2

* page.close()

* update folder paths due to additional monorepo dir changes

* more changes for directory structure changes

* test-results folder isn't produced anymore for some reason

* remove logger middleware

* remove buildvcs flags

* fix build script reference

* remove rudder key

* few cleanups

* PR feedback

* use page.watiForTimeout

* add readme for playwright setup

* change readme link
  • Loading branch information
mickmister authored Apr 4, 2023
1 parent 08e8044 commit fa1237a
Show file tree
Hide file tree
Showing 24 changed files with 2,948 additions and 1,658 deletions.
163 changes: 163 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
name: Playwright Tests
on:
schedule:
- cron: "0 0 * * *"
pull_request:
push:
branches:
- master

env:
TERM: xterm
GO_VERSION: 1.19.6
NODE_VERSION: 16.15.0

jobs:
playwright-run:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:11.13
env:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mostest
POSTGRES_DB: mattermost_test
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
minio:
image: minio/minio:RELEASE.2019-10-11T00-38-09Z
env:
MINIO_ACCESS_KEY: minioaccesskey
MINIO_SECRET_KEY: miniosecretkey
MINIO_SSE_MASTER_KEY: "my-minio-key:6368616e676520746869732070617373776f726420746f206120736563726574"
inbucket:
image: mattermost/inbucket:release-1.2.0
ports:
- 10080:10080
- 10110:10110
- 10025:10025
elasticsearch:
image: mattermost/mattermost-elasticsearch-docker:7.0.0
env:
http.host: "0.0.0.0"
http.port: 9200
http.cors.enabled: "true"
http.cors.allow-origin: "http://localhost:1358,http://127.0.0.1:1358"
http.cors.allow-headers: "X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization"
http.cors.allow-credentials: "true"
transport.host: "127.0.0.1"
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
ports:
- 9200:9200
mattermost-server:
image: mattermost/mattermost-enterprise-edition:release-7.7
env:
DB_HOST: postgres
DB_PORT_NUMBER: 5432
MM_DBNAME: mattermost_test
MM_USERNAME: mmuser
MM_PASSWORD: mostest
CI_INBUCKET_HOST: inbucket
CI_INBUCKET_PORT: 10080
CI_MINIO_HOST: minio
IS_CI: true
MM_CLUSTERSETTINGS_READONLYCONFIG: false
MM_EMAILSETTINGS_SMTPSERVER: inbucket
MM_EMAILSETTINGS_SMTPPORT: 10025
MM_ELASTICSEARCHSETTINGS_CONNECTIONURL: http://elasticsearch:9200
MM_EXPERIMENTALSETTINGS_USENEWSAMLLIBRARY: true
MM_SQLSETTINGS_DATASOURCE: "postgres://mmuser:mostest@postgres:5432/mattermost_test?sslmode=disable&connect_timeout=10"
MM_SQLSETTINGS_DRIVERNAME: postgres
MM_PLUGINSETTINGS_ENABLEUPLOADS: true
MM_SERVICESETTINGS_SITEURL: http://localhost:8065
MM_PLUGINSETTINGS_AUTOMATICPREPACKAGEDPLUGINS: false
MM_ANNOUNCEMENTSETTINGS_ADMINNOTICESENABLED: false
MM_FEATUREFLAGS_AppsEnabled: true

ports:
- 8065:8065
- 4000:4000
env:
TYPE: NONE
PULL_REQUEST: ""
HEADLESS: true
DASHBOARD_ENABLE: false
FULL_REPORT: false
MM_SERVICESETTINGS_SITEURL: http://localhost:8065
MM_ADMIN_EMAIL: sysadmin@sample.mattermost.com
MM_ADMIN_USERNAME: sysadmin
MM_ADMIN_PASSWORD: Sys@dmin-sample1
TEST_DATABASE_URL: postgres://mmuser:mostest@localhost:5432/mattermost_test
MM_SERVICESETTINGS_ENABLEDEVELOPER: true
steps:
- name: ci/checkout-repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0

- name: ci/setup-go
uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0
with:
go-version: "${{ env.GO_VERSION }}"
cache: true

- name: ci/setup-node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version-file: ".nvmrc"
cache: "npm"
cache-dependency-path: webapp/package-lock.json

- name: ci/create-admin-user
run: |
STATUSCODE=$(curl -X POST -H "Content-Type: application/json" -d '{"email": "'${MM_ADMIN_EMAIL}'", "username": "'${MM_ADMIN_USERNAME}'", "password": "'${MM_ADMIN_PASSWORD}'"}' ${MM_SERVICESETTINGS_SITEURL}/api/v4/users -w "%{http_code}" -o /dev/stderr)
if test $STATUSCODE -ne 201; then exit 1; fi
- name: ci/install-go-dependencies
run: go mod tidy
- name: ci/install-npm-dependencies
run: cd webapp && npm ci

- name: ci/build-and-install-plugin
run: make deploy
env:
PLUGIN_E2E_MOCK_OAUTH_SERVER_URL: http://172.17.0.1:8080

- name: ci/setup-node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
with:
node-version: "16"
cache: "npm"
cache-dependency-path: e2e/playwright/package-lock.json

- name: ci/install-tests-deps
run: |
cd e2e/playwright
./setup-environment
- name: ci/run-playwright-tests
run: |
cd e2e/playwright
npm run test-ci
env:
PLUGIN_E2E_MOCK_OAUTH_TOKEN: ${{ secrets.MM_GITHUB_PLUGIN_E2E_TOKEN }}
PW_BASE_URL: ${{ env.MM_SERVICESETTINGS_SITEURL }}

- name: ci/move-artifacts
if: success() || failure()
run: |
cd e2e/playwright
mkdir results
mv screenshots results
mv playwright-report results
- uses: actions/upload-artifact@v3
if: success() || failure()
with:
name: test-results
path: e2e/playwright/results
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
dist/

# Mac
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This repository is licensed under the [Apache 2.0 License](https://github.com/ma

## About the GitHub Plugin

The Mattermost GitHub plugin uses a webhook to connect your GitHub account to Mattermost to listen for incoming GitHub events. Events notifications are via DM in Mattermost. The Events don’t need separate configuration.
The Mattermost GitHub plugin uses a webhook to connect your GitHub account to Mattermost to listen for incoming GitHub events. Events notifications are via DM in Mattermost. The Events don’t need separate configuration.

After a System Admin has configured the GitHub plugin, run `/github connect` in a Mattermost channel to connect your Mattermost and GitHub accounts.

Expand All @@ -57,7 +57,7 @@ This guide assumes:

## Configuration

GitHub plugin configuration starts by registering an OAuth app in GitHub and ends in Mattermost.
GitHub plugin configuration starts by registering an OAuth app in GitHub and ends in Mattermost.

**Note:** If you're using GitHub Enterprise, replace all GitHub links below with your GitHub Enterprise URL.

Expand All @@ -69,7 +69,7 @@ You must first register the Mattermost GitHub Plugin as an authorized OAuth app
2. Set the following values:
- **Application name:** `Mattermost GitHub Plugin - <your company name>`
- **Homepage URL:** `https://github.com/mattermost/mattermost-plugin-github`
- **Authorization callback URL:** `https://your-mattermost-url.com/plugins/github/oauth/complete`, replacing `https://your-mattermost-url.com` with your Mattermost URL. This value needs to match the Mattermost server URL that you or your users users log in to.
- **Authorization callback URL:** `https://your-mattermost-url.com/plugins/github/oauth/complete`, replacing `https://your-mattermost-url.com` with your Mattermost URL. This value needs to match the Mattermost server URL that you or your users users log in to.
3. Submit.
4. Click **Generate a new client secret** and provide your GitHub password to continue.
5. Copy the **Client ID** and **Client Secret** in the resulting screen.
Expand Down Expand Up @@ -108,13 +108,13 @@ To prevent this, either:

or

- If the user is an existing user account you want to preserve, change its username and restart the Mattermost server. Once restarted, the plugin will create a bot
- If the user is an existing user account you want to preserve, change its username and restart the Mattermost server. Once restarted, the plugin will create a bot
account with the name `github`.

**Note:** For `v0.9.0` and earlier of the GitHub plugin, instead of using bot accounts, set the username the plugin is attached to in **System Console > Plugins > GitHub**.

#### Generate a Key

Open **System Console > Plugins > GitHub** and do the following:

1. Generate a new value for **At Rest Encryption Key**.
Expand All @@ -134,7 +134,7 @@ Once configuration is complete, run the `/github connect` slash command from any

When you’ve tested the plugin and confirmed it’s working, notify your team so they can connect their GitHub account to Mattermost and get started. Copy and paste the text below, edit it to suit your requirements, and send it out.

> Hi team,
> Hi team,
> We've set up the Mattermost GitHub plugin, so you can get notifications from GitHub in Mattermost. To get started, run the `/github connect` slash command from any channel within Mattermost to connect your Mattermost account with GitHub. Then, take a look at the [slash commands](#slash-commands) section for details about how to use the plugin.
Expand All @@ -150,9 +150,9 @@ When you’ve tested the plugin and confirmed it’s working, notify your team s
- The following flags are supported:
- `--features`: comma-delimited list of one or more of: issues, pulls, pulls_merged, pushes, creates, deletes, issue_creations, issue_comments, pull_reviews, label:"labelname". Defaults to pulls,issues,creates,deletes.
- `--exclude-org-member`: events triggered by organization members will not be delivered. It will be locked to the organization provided in the plugin configuration and it will only work for users whose membership is public. Note that organization members and collaborators are not the same.
- `--render-style`: notifications will be delivered in the specified style (for example, the body of a pull request will not be displayed). Supported
- `--render-style`: notifications will be delivered in the specified style (for example, the body of a pull request will not be displayed). Supported
values are `collapsed`, `skip-body` or `default` (same as omitting the flag).

* __Get to do items__ - Use `/github todo` to get an ephemeral message with items to do in GitHub, including a list of unread messages and pull requests awaiting your review.
* __Update settings__ - Use `/github settings` to update your settings for notifications and daily reminders.
* __And more!__ - Run `/github help` to see what else the slash command can do.
Expand Down Expand Up @@ -182,3 +182,7 @@ GitHub user tokens are AES encrypted with an At Rest Encryption Key configured i
## Development

This plugin contains both a server and web app portion. Read our documentation about the [Developer Workflow](https://developers.mattermost.com/extend/plugins/developer-workflow/) and [Developer Setup](https://developers.mattermost.com/extend/plugins/developer-setup/) for more information about developing and extending plugins.

### Playwright e2e tests

In order to get your environment set up to run [Playwright](https://playwright.dev) tests, please see the setup guide at [e2e/playwright](/e2e/playwright#readme).
4 changes: 4 additions & 0 deletions build/custom.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ RUDDER_WRITE_KEY = $(MM_RUDDER_PLUGINS_PROD)
endif

GO_BUILD_FLAGS += -ldflags '-X "github.com/mattermost/mattermost-plugin-api/experimental/telemetry.rudderWriteKey=$(RUDDER_WRITE_KEY)"'

ifdef PLUGIN_E2E_MOCK_OAUTH_SERVER_URL
GO_BUILD_FLAGS += -ldflags '-X "github.com/mattermost/mattermost-plugin-github/server/plugin.testOAuthServerURL=$(PLUGIN_E2E_MOCK_OAUTH_SERVER_URL)"'
endif
5 changes: 5 additions & 0 deletions e2e/playwright/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env

screenshots
playwright-report
test-results
35 changes: 35 additions & 0 deletions e2e/playwright/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
In order to get your environment set up to run [Playwright](https://playwright.dev) tests, you can run `./setup-environment`, or run equivalent commands for your current setup.

What this script does:

- Navigate to the folder above `mattermost-plugin-github`
- Clone `mattermost-server` (if it is already cloned there, please have a clean git index to avoid issues with conflicts)
- `cd mattermost-server`
- Install webapp dependencies - `cd webapp && npm i`
- Install Playwright test dependencies - `cd ../e2e-tests/playwright && npm i`
- Install Playwright - `npx install playwright`
- Install GitHub plugin e2e dependencies - `cd ../../../mattermost-plugin-github/e2e/playwright && npm i`
- Build and deploy plugin with mock OAuth server URL env var - `PLUGIN_E2E_MOCK_OAUTH_SERVER_URL=http://localhost:8080 make deploy`

-----

Then to run the tests:

Start Mattermost server:
- `cd <path>/mattermost-server/server`
- `make test-data`
- `make run-server`

Run test:
- Create a personal access token from GitHub
- Set `PLUGIN_E2E_MOCK_OAUTH_TOKEN` environment variable to access token
- `cd <path>/mattermost-plugin-github/e2e/playwright`
- `npm test`

To see the test report:
- `cd <path>/mattermost-plugin-github/e2e/playwright`
- `npm run show-report`
- Navigate to http://localhost:9323

To see test screenshots:
- `cd <path>/mattermost-plugin-github/e2e/playwright/screenshots`
28 changes: 28 additions & 0 deletions e2e/playwright/mock_oauth_server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require('dotenv').config();

import {ExpiryAlgorithms, makeOAuthServer} from './mock_oauth_server';

const mockOAuthAccessToken = process.env.MOCK_OAUTH_ACCESS_TOKEN;
if (!mockOAuthAccessToken) {
console.error('Please provide an OAuth access token to use');
process.exit(0);
}

const defaultAuthorizePrefix = '/login/oauth' // Used by GitHub
const authorizeURLPrefix = process.env.OAUTH_AUTHORIZE_URL_PREFIX || defaultAuthorizePrefix;

const mattermostSiteURL = process.env.MM_SERVICESETTINGS_SITEURL || 'http://localhost:8065';
const pluginId = process.env.MM_PLUGIN_ID || 'github';

const app = makeOAuthServer({
authorizeURLPrefix,
mattermostSiteURL,
mockOAuthAccessToken,
pluginId,
expiryAlgorithm: ExpiryAlgorithms.NO_EXPIRY,
});

const port = process.env.OAUTH_SERVER_PORT || 8080;
app.listen(port, () => {
console.log(`Mock OAuth server listening on port ${port}`);
});
52 changes: 52 additions & 0 deletions e2e/playwright/mock_oauth_server/mock_oauth_server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import express from 'express';

export enum ExpiryAlgorithms {
NO_EXPIRY = 'no_expiry',
}

export type OAuthServerOptions = {
mattermostSiteURL: string;
pluginId: string;
mockOAuthAccessToken: string;
authorizeURLPrefix: string;
expiryAlgorithm: ExpiryAlgorithms;
}

export const makeOAuthServer = ({
mattermostSiteURL,
pluginId,
mockOAuthAccessToken,
authorizeURLPrefix,
expiryAlgorithm,
}: OAuthServerOptions): express.Express => {
if (!mockOAuthAccessToken) {
throw new Error(`MockOAuthServer: Please provide an OAuth access token to use`);
}

if (expiryAlgorithm !== ExpiryAlgorithms.NO_EXPIRY) {
throw new Error(`MockOAuthServer: Unsupported OAuth token expiry algorithm: ${expiryAlgorithm}`);
}

const app = express();

const oauthRouter = express.Router();

oauthRouter.get('/authorize', function (req, res) {
const query = req.url.split('?')[1];
res.redirect(`${mattermostSiteURL}/plugins/${pluginId}/oauth/complete?${query}&code=1234`);
});

oauthRouter.post('/access_token', function (req, res) {
const token = {
access_token: mockOAuthAccessToken,
token_type: 'bearer',
expiry: '0001-01-01T00:00:00Z',
};

res.json(token);
});

app.use(authorizeURLPrefix, oauthRouter);

return app;
}
Loading

0 comments on commit fa1237a

Please sign in to comment.