Skip to content

Commit 1d022ab

Browse files
authored
[WC-1388]: enable e2e (#175)
2 parents e3d43b0 + bfa9419 commit 1d022ab

34 files changed

+1479
-817
lines changed

.github/workflows/WebAutomatedTests.yml

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,79 +2,84 @@ name: Run automated end-to-end tests
22

33
on:
44
push:
5-
branches: [master]
5+
branches: [main]
66

77
pull_request:
8-
branches: [master]
8+
branches: [main]
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
913

1014
jobs:
15+
harden-security:
16+
name: Check SHA in GH Actions
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
21+
- uses: zgosalvez/github-actions-ensure-sha-pinned-actions@570fff1eb64d52ffae87990c117c2748c317b58c # v2.0.0
22+
1123
test:
12-
name: "Automated tests"
24+
# Run job only if it's push to main or PR from web-widgets, don't run for fork PRs
25+
if: >-
26+
${{ github.event_name == 'push' ||
27+
github.event_name == 'pull_request' &&
28+
github.event.pull_request.head.repo.full_name == 'mendix/web-widgets' }}
29+
name: Automated tests
1330
runs-on: ubuntu-latest
31+
needs: [harden-security]
32+
1433
permissions:
1534
packages: read
1635
contents: read
36+
1737
strategy:
1838
# when one test fails, DO NOT cancel the other
1939
fail-fast: false
2040
matrix:
2141
# run 3 copies of the current job in parallel
22-
containers: [0, 1, 2]
42+
index: [0, 1, 2]
2343

2444
steps:
25-
- name: "Checking changed files"
26-
id: files
27-
uses: softprops/diffset@d5947696689a571f7a984a52505e2649eead5c22 # v1
28-
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
29-
with:
30-
global_files: |
31-
!{packages/**/*,configs/e2e/*.json,detox/**/*,scripts/**/*,data/**/*}
32-
not_atlas_native_files: |
33-
!packages/theming/atlas/src/**/native/**
34-
env:
35-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36-
- name: "Checking-out code"
37-
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2
45+
- name: Checkout
46+
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
3847
with:
39-
submodules: false
40-
- name: "Fetching master to compare"
41-
if: github.event_name == 'pull_request' && (steps.files.outputs.global_files == '' || github.event.pull_request.head.repo.full_name != github.repository)
42-
run: git fetch --no-tags --prune --depth=1 origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}
43-
- name: "Defining environment variables"
44-
id: variables
45-
run: echo ::set-output name=arg::$(if [ "${{ steps.files.outputs.global_files }}" = "" ] && ${{ github.event_name == 'pull_request' }}; then echo '--since origin/${{ github.base_ref }}'; else echo ''; fi)
46-
- name: "Defining cache"
47-
uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7 # v2
48-
env:
49-
cache-name: cache-node-modules
48+
fetch-depth: 0
49+
- name: Setup pnpm
50+
uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd # v2.2.4
5051
with:
51-
path: ~/.npm
52-
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}
53-
- name: "Defining node version"
54-
uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v2
52+
version: ^7.13.4
53+
- name: Setup node
54+
uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3.5.1
5555
with:
5656
node-version-file: ".nvmrc"
57-
- name: "Installing dependencies"
58-
run: npm install
59-
- name: Login to GitHub Container Registry
60-
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
61-
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
57+
cache: "pnpm"
58+
- name: Get sha of main
59+
run: echo "main_sha=$(git rev-parse origin/main)" >> ${{ runner.os == 'Windows' && '$env:GITHUB_ENV' || '$GITHUB_ENV' }}
60+
- name: Restore Turbo Cache
61+
uses: actions/cache@9b0c1fce7a93df8e3bb8926b0d6e9d89e92f20a7 # v3.0.11
6262
with:
63-
registry: ghcr.io
64-
username: ${{ github.actor }}
65-
password: ${{ secrets.GITHUB_TOKEN }}
63+
path: node_modules/.cache/turbo
64+
key: turbo-cache-${{ runner.os }}-e2e-chunk-${{ matrix.index }}-${{ env.main_sha }}
65+
restore-keys: |
66+
turbo-cache-${{ runner.os }}-e2e-chunk-${{ matrix.index }}
67+
- name: Install dependencies
68+
run: pnpm install
6669
- name: "Executing E2E tests"
67-
if: github.event_name == 'push' || steps.files.outputs.not_atlas_native_files != '' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository)
68-
run: CIRCLE_NODE_INDEX=${{ matrix.containers }} npm run test:e2e -- ${{ steps.variables.outputs.arg }}
69-
env:
70-
FORKED: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
70+
run: >-
71+
node
72+
./automation/run-e2e/bin/run-e2e-in-chunks.mjs
73+
--chunks 3
74+
--index ${{ matrix.index }}
75+
--event-name ${{ github.event_name }}
7176
- name: "Fixing files permissions"
7277
if: failure()
7378
run: |
7479
sudo find ${{ github.workspace }}/packages/* -type d -exec chmod 755 {} \;
7580
sudo find ${{ github.workspace }}/packages/* -type f -exec chmod 644 {} \;
7681
- name: "Archive test screenshot diff results"
77-
uses: actions/upload-artifact@82c141cc518b40d92cc801eee768e7aafc9c2fa2 # v2
82+
uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb # v3.1.1
7883
if: failure()
7984
with:
8085
name: test-screenshot-results

.github/workflows/WeeklyWebAutomatedTests.yml

Lines changed: 0 additions & 57 deletions
This file was deleted.

automation/e2e/package.json

Lines changed: 0 additions & 15 deletions
This file was deleted.

automation/run-e2e/.eslintrc.cjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module.exports = {
2+
root: true,
3+
env: {
4+
node: true,
5+
es2021: true
6+
},
7+
extends: ["eslint:recommended", "plugin:cypress/recommended"],
8+
parserOptions: {
9+
sourceType: "module",
10+
ecmaVersion: 2021
11+
}
12+
};

automation/run-e2e/.prettierrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("../../prettier.config");
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#!/usr/bin/env node
2+
3+
import c from "ansi-colors";
4+
import { execSync } from "node:child_process";
5+
import parseArgs from "yargs-parser";
6+
import assert from "node:assert/strict";
7+
8+
function main() {
9+
const parseArgsOptions = {
10+
number: ["index", "chunks"],
11+
string: ["event-name"],
12+
coerce: {},
13+
default: {
14+
chunks: 3,
15+
"event-name": "push"
16+
}
17+
};
18+
19+
const options = parseArgs(process.argv.slice(2), parseArgsOptions);
20+
const index = validateParam(options.index, "index");
21+
const chunks = validateParam(options.chunks, "chunks");
22+
const eventName = options.eventName;
23+
24+
if (index < 0 || index >= chunks) {
25+
const message = `Out of range. Received: index - ${index}, chunks - ${chunks}`;
26+
throw new Error(message);
27+
}
28+
29+
const packages = getPackages({ onlyChanged: eventName === "pull_request" });
30+
const chunkSize = Math.ceil(packages.length / chunks);
31+
const start = index * chunkSize;
32+
const end = start + chunkSize;
33+
const sorted = [...packages].sort((a, b) => a.name.normalize().localeCompare(b.name.normalize()));
34+
const filters = sorted.slice(start, end).map(pkg => `--filter=${pkg.name}`);
35+
const command = [
36+
// <- prevent format in one line
37+
`pnpm`,
38+
`--workspace-root`,
39+
`exec`,
40+
`turbo run e2e`,
41+
// turbo options
42+
`--concurrency=1`,
43+
...filters
44+
].join(" ");
45+
46+
// Run e2e only we have packages in chunk
47+
if (filters.length > 0) {
48+
execSync(command, { stdio: "inherit" });
49+
} else {
50+
console.log(c.yellow("No packages in chunk, skip e2e."));
51+
}
52+
}
53+
54+
main();
55+
56+
function validateParam(value, option) {
57+
const n = parseInt(value, 10);
58+
assert.notStrictEqual(n, NaN, `option ${option} should be integer`);
59+
assert.ok(n > -1, `option ${option} should be non negative`);
60+
return n;
61+
}
62+
63+
function getPackages({ onlyChanged = false } = {}) {
64+
const args = [
65+
// <- prevent format in one line
66+
`--recursive`,
67+
`--json`,
68+
`--depth -1`,
69+
`--filter !web-widgets`,
70+
onlyChanged ? '--filter "...[origin/main]"' : ""
71+
].filter(v => !!v);
72+
const command = [`pnpm ls`, ...args].join(" ");
73+
74+
const listing = execSync(command, { encoding: "utf-8" });
75+
return JSON.parse(listing === "" ? "[]" : listing);
76+
}

automation/run-e2e/bin/run-e2e.mjs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env node
2+
3+
import parseArgs from "yargs-parser";
4+
import { ci } from "../lib/ci.mjs";
5+
import { dev } from "../lib/dev.mjs";
6+
7+
async function main() {
8+
const {
9+
_: [command]
10+
} = parseArgs(process.argv.slice(2));
11+
12+
switch (command) {
13+
case "ci": {
14+
await ci();
15+
break;
16+
}
17+
case "dev": {
18+
await dev();
19+
break;
20+
}
21+
default: {
22+
throw new Error(`Unknown command: ${command}`);
23+
}
24+
}
25+
}
26+
27+
main().catch(err => {
28+
console.error(err);
29+
process.exit(1);
30+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Once cypress-image-diff-js and cypress-terminal-report will be published as ES Modules, we finally
2+
// can convert config to ES Module.
13
const { defineConfig } = require("cypress");
24
const getCompareSnapshotsPlugin = require("cypress-image-diff-js/dist/plugin");
35
const installLogsPrinter = require("cypress-terminal-report/src/installLogsPrinter");

automation/run-e2e/docker/m2ee.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
m2ee:
2+
app_name: Test App
3+
app_base: /source/tests/testProject/deployment
4+
model_upload_path: /source/tests/testProject
5+
admin_port: 8090
6+
admin_pass: Password1!
7+
runtime_port: 8080
8+
runtime_listen_addresses: "*"
9+
javaopts: ["-Dfile.encoding=UTF-8", "-XX:MaxPermSize=128M", "-Xmx512M", "-Xms512M", "-Djava.io.tmpdir=/source/tests/testProject/deployment/data/tmp"]
10+
javabin: /usr/bin/java
11+
pidfile: /var/run/m2ee.pid
12+
mxruntime:
13+
DTAPMode: T
14+
ApplicationRootUrl: http://runtime:8080/
15+
DatabaseType: HSQLDB
16+
DatabaseName: default
17+
DatabasePassword: ""
18+
BuiltInDatabasePath: /source/tests/testProject/deployment/data/database
19+
logging:
20+
- type: file
21+
name: FileSubscriber
22+
autosubscribe: INFO
23+
filename: /source/results/runtime.log
24+
max_size: 10485760
25+
max_rotation: 10
26+
mxnode:
27+
mxjar_repo: /var/opt/runtime
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
FROM mono:6.12
2+
ARG MENDIX_VERSION
3+
4+
RUN \
5+
echo "Installing Java..." && \
6+
apt-get -qq update && \
7+
apt-get -qq install -y wget && \
8+
wget -q https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz -O /tmp/openjdk.tar.gz && \
9+
mkdir /usr/lib/jvm && \
10+
tar xfz /tmp/openjdk.tar.gz --directory /usr/lib/jvm && \
11+
rm /tmp/openjdk.tar.gz && \
12+
\
13+
echo "Downloading mxbuild ${MENDIX_VERSION}..." && \
14+
wget -q https://cdn.mendix.com/runtime/mxbuild-${MENDIX_VERSION}.tar.gz -O /tmp/mxbuild.tar.gz && \
15+
mkdir /tmp/mxbuild && \
16+
tar xfz /tmp/mxbuild.tar.gz --directory /tmp/mxbuild && \
17+
rm /tmp/mxbuild.tar.gz && \
18+
\
19+
apt-get -qq remove -y wget && \
20+
apt-get clean && \
21+
\
22+
echo "#!/bin/bash -x" >/bin/mxbuild && \
23+
echo "mono /tmp/mxbuild/modeler/mxbuild.exe --java-home=/usr/lib/jvm/jdk-11.0.2 --java-exe-path=/usr/lib/jvm/jdk-11.0.2/bin/java \$@" >>/bin/mxbuild && \
24+
chmod +x /bin/mxbuild && \
25+
\
26+
echo "#!/bin/bash -x" >/bin/mx && \
27+
echo "mono /tmp/mxbuild/modeler/mx.exe \$@" >>/bin/mx && \
28+
chmod +x /bin/mx

0 commit comments

Comments
 (0)