diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index 8d5acc8b..202eb3c8 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -56,6 +56,14 @@ jobs: ADMIN_URL: "//localhost:80" working-directory: "front" + - name: "Build iframe-api" + run: yarn run build-iframe-api + working-directory: "front" + + - name: "Typecheck" + run: yarn run typecheck + working-directory: "front" + - name: "Svelte check" run: yarn run svelte-check working-directory: "front" @@ -240,4 +248,4 @@ jobs: - name: "Prettier" run: yarn pretty-check - working-directory: "desktop/local-app" \ No newline at end of file + working-directory: "desktop/local-app" diff --git a/.github/workflows/end_to_end_tests.yml b/.github/workflows/end_to_end_tests.yml index f9dc832c..ad59dfc4 100644 --- a/.github/workflows/end_to_end_tests.yml +++ b/.github/workflows/end_to_end_tests.yml @@ -1,6 +1,4 @@ -# https://help.github.com/en/categories/automating-your-workflow-with-github-actions - -name: "End to end tests" +name: 'End to end tests' on: push: @@ -10,117 +8,31 @@ on: pull_request: jobs: - - start-runner: - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) - name: Start self-hosted EC2 runner + test: + timeout-minutes: 60 runs-on: ubuntu-latest - outputs: - label: ${{ steps.start-ec2-runner.outputs.label }} - ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }} steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} - - name: Start EC2 runner - id: start-ec2-runner - uses: machulav/ec2-github-runner@v2 - with: - mode: start - github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} - ec2-image-id: ami-094dbcc53250a2480 - ec2-instance-type: m5.2xlarge - subnet-id: subnet-0ac40025f559df1bc - security-group-id: sg-0e36e96e3b8ed2d64 - #iam-role-name: my-role-name # optional, requires additional permissions - #aws-resource-tags: > # optional, requires additional permissions - # [ - # {"Key": "Name", "Value": "ec2-github-runner"}, - # {"Key": "GitHubRepository", "Value": "${{ github.repository }}"} - # ] - - - end-to-end-tests: - name: "End-to-end testcafe tests" - - needs: start-runner # required to start the main job when the runner is ready - runs-on: ${{ needs.start-runner.outputs.label }} # run the job on the newly created runner - - steps: - - name: "Checkout" - uses: "actions/checkout@v2.0.0" - - - name: "Setup NodeJS" - uses: actions/setup-node@v1 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 with: node-version: '14.x' - - - name: "Install dependencies" - run: npm install - working-directory: "tests" - - - name: "Setup .env file" + - name: Install dependencies + run: npm ci + working-directory: tests + - name: Install Playwright + run: npx playwright install --with-deps + - name: 'Setup .env file' run: cp .env.template .env - - - name: "Edit ownership of file for test cases" - run: sudo chown 1000:1000 -R . - - - name: "Start environment" - run: LIVE_RELOAD=0 docker-compose up -d - - - name: "Wait for environment to build (and downloading testcafe image)" - run: (docker-compose -f docker-compose.testcafe.yml build &) && docker-compose logs -f --tail=0 front | grep -q "Compiled successfully" - -# - name: "temp debug: display logs" -# run: docker-compose logs -# -# - name: "Wait for back start" -# run: docker-compose logs -f back | grep -q "WorkAdventure HTTP API starting on port" -# -# - name: "Wait for pusher start" -# run: docker-compose logs -f pusher | grep -q "WorkAdventure starting on port" - - - name: "Run tests" - run: PROJECT_DIR=$(pwd) docker-compose -f docker-compose.testcafe.yml up --exit-code-from testcafe - - - name: Upload failed tests - if: ${{ failure() }} - uses: actions/upload-artifact@v2 + - name: Start WorkAdventure + run: docker-compose -f docker-compose.yaml -f docker-compose.e2e.yml up -d --build + - name: Wait for environment to Start + run: sleep 60 + - name: Run Playwright tests + run: npm run test-prod-like + working-directory: tests + - uses: actions/upload-artifact@v2 + if: always() with: - name: my-artifact - path: './tests/screenshots/' - - - name: Display state - if: ${{ failure() }} - run: docker-compose ps - - - name: Display logs - if: ${{ failure() }} - run: docker-compose logs - - stop-runner: - name: Stop self-hosted EC2 runner - needs: - - start-runner # required to get output from the start-runner job - - end-to-end-tests # required to wait when the main job is done - runs-on: ubuntu-latest - if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs - steps: - - name: Configure AWS credentials - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} - - name: Stop EC2 runner - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false) - uses: machulav/ec2-github-runner@v2 - with: - mode: stop - github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} - label: ${{ needs.start-runner.outputs.label }} - ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }} + name: playwright-report + path: tests/playwright-report/ + retention-days: 30 diff --git a/.github/workflows/push-to-npm.yml b/.github/workflows/push-to-npm.yml index 750ef224..b6cf4f12 100644 --- a/.github/workflows/push-to-npm.yml +++ b/.github/workflows/push-to-npm.yml @@ -22,31 +22,10 @@ jobs: run: cat package.json working-directory: "front/packages/iframe-api-typings" - - name: Install Protoc - uses: arduino/setup-protoc@v1 - with: - version: '3.x' - - name: "Install dependencies" run: yarn install working-directory: "front" - - name: "Install messages dependencies" - run: yarn install - working-directory: "messages" - - - name: "Build proto messages" - run: yarn run ts-proto && yarn run copy-to-front-ts-proto && yarn run json-copy-to-front - working-directory: "messages" - - - name: "Create index.html" - run: ./templater.sh - working-directory: "front" - - - name: "Generate i18n files" - run: yarn run typesafe-i18n - working-directory: "front" - - name: "Build" run: yarn run build-typings env: @@ -54,13 +33,6 @@ jobs: ADMIN_URL: "//localhost:80" working-directory: "front" - # We build the front to generate the typings of iframe_api, then we copy those typings in a separate package. - - name: Copy typings to package dir - run: cp front/dist/src/iframe_api.d.ts front/packages/iframe-api-typings/iframe_api.d.ts - - - name: Copy typings to package dir (2) - run: cp -R front/dist/src/Api front/packages/iframe-api-typings/Api - - name: Install dependencies in package run: yarn install working-directory: "front/packages/iframe-api-typings" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d3f5d0b..b700e5c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,46 +67,20 @@ $ docker-compose exec back yarn run pretty WorkAdventure is based on a video game engine (Phaser), and video games are not the easiest programs to unit test. -Nevertheless, if your code can be unit tested, please provide a unit test (we use Jasmine), or an end-to-end test (we use Testcafe). +Nevertheless, if your code can be unit tested, please provide a unit test (we use Jasmine), or an end-to-end test (we use Playwright). If you are providing a new feature, you should setup a test map in the `maps/tests` directory. The test map should contain some description text describing how to test the feature. * if the features is meant to be manually tested, you should modify the `maps/tests/index.html` file to add a reference to your newly created test map -* if the features can be automatically tested, please provide a testcafe test +* if the features can be automatically tested, please provide an end-to-end test -#### Running testcafe tests +#### Running end-to-end tests End-to-end tests are available in the "/tests" directory. -To run these tests locally: - -```console -$ LIVE_RELOAD=0 docker-compose up -d -$ cd tests -$ npm install -$ npm run test -``` - -Note: If your tests fail on a Javascript error in "sockjs", this is due to the -Webpack live reload. The Webpack live reload feature is conflicting with testcafe. This is why we recommend starting -WorkAdventure with the `LIVE_RELOAD=0` environment variable. - -End-to-end tests can take a while to run. To run only one test, use: - -```console -$ npm run test -- tests/[name of the test file].ts -``` - -You can also run the tests inside a container (but you will not have visual feedbacks on your test, so we recommend using -the local tests). - -```console -$ LIVE_RELOAD=0 docker-compose up -d -# Wait 2-3 minutes for the environment to start, then: -$ PROJECT_DIR=$(pwd) docker-compose -f docker-compose.testcafe.yml up -``` +More information on running end-to-end tests can be found in the [`/tests/README`](/tests/README.md). ### A bad wording or a missing language diff --git a/docker-compose.e2e.yml b/docker-compose.e2e.yml new file mode 100644 index 00000000..3330202a --- /dev/null +++ b/docker-compose.e2e.yml @@ -0,0 +1,47 @@ +version: '3.5' +services: + # overrides for e2e tests to be closer to production + # use with command: + # docker-compose -f docker-compose.yaml -f docker-compose.e2e.yml up -d --build + + front: + image: 'wa-front-e2e' + build: + context: ./ + dockerfile: front/Dockerfile + environment: + STARTUP_COMMAND_1: 'envsubst < dist/env-config.template.js > dist/env-config.js' + STARTUP_COMMAND_2: '' + command: apache2-foreground + volumes: [] + labels: + - "traefik.enable=true" + - "traefik.http.routers.front.rule=Host(`play.workadventure.localhost`)" + - "traefik.http.routers.front.entryPoints=web" + - "traefik.http.services.front.loadbalancer.server.port=80" + - "traefik.http.routers.front-ssl.rule=Host(`play.workadventure.localhost`)" + - "traefik.http.routers.front-ssl.entryPoints=websecure" + - "traefik.http.routers.front-ssl.tls=true" + - "traefik.http.routers.front-ssl.service=front" + + pusher: + image: 'wa-pusher-e2e' + build: + context: ./ + dockerfile: pusher/Dockerfile + environment: + STARTUP_COMMAND_1: '' + STARTUP_COMMAND_2: '' + command: yarn run runprod + volumes: [] + + back: + image: 'wa-back-e2e' + build: + context: ./ + dockerfile: back/Dockerfile + environment: + STARTUP_COMMAND_1: '' + STARTUP_COMMAND_2: '' + command: yarn run runprod + volumes: [] diff --git a/docker-compose.testcafe.yml b/docker-compose.testcafe.yml deleted file mode 100644 index e61db21d..00000000 --- a/docker-compose.testcafe.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: "3.5" -services: - testcafe: - build: tests/ - working_dir: /project/tests - command: - - --dev - # Run as root to have the right to access /var/run/docker.sock - user: root - environment: - BROWSER: "chromium --use-fake-device-for-media-stream" - PROJECT_DIR: ${PROJECT_DIR} - ADMIN_API_TOKEN: ${ADMIN_API_TOKEN} - volumes: - - ./:/project - - ./maps:/maps - - /var/run/docker.sock:/var/run/docker.sock - # security_opt: - # - seccomp:unconfined diff --git a/docker-compose.yaml b/docker-compose.yaml index 8489b336..2bbc6c0a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -52,7 +52,6 @@ services: MAX_USERNAME_LENGTH: "$MAX_USERNAME_LENGTH" DISABLE_ANONYMOUS: "$DISABLE_ANONYMOUS" OPID_LOGIN_SCREEN_PROVIDER: "$OPID_LOGIN_SCREEN_PROVIDER" - LIVE_RELOAD: "$LIVE_RELOAD:-true" command: yarn run start volumes: - ./front:/usr/src/app diff --git a/front/.gitignore b/front/.gitignore index d76848c8..b7cc8c89 100644 --- a/front/.gitignore +++ b/front/.gitignore @@ -1,14 +1,7 @@ /node_modules/ -/dist/*.js -/dist/*.js.map -/dist/*.js.LICENSE.txt -/dist/main.*.css -/dist/main.*.css.map -/dist/tests/ +dist/ /yarn-error.log /package-lock.json -/dist/webpack.config.js -/dist/webpack.config.js.map -/dist/src *.sh !templater.sh +/public/iframe_api.js diff --git a/front/Dockerfile b/front/Dockerfile index 14914ebf..7db1e02d 100644 --- a/front/Dockerfile +++ b/front/Dockerfile @@ -12,11 +12,7 @@ RUN cp -r ../messages/ts-proto-generated/protos/* src/Messages/ts-proto-generate RUN sed -i 's/import { Observable } from "rxjs";/import type { Observable } from "rxjs";/g' src/Messages/ts-proto-generated/messages.ts RUN cp -r ../messages/JsonMessages/* src/Messages/JsonMessages -RUN yarn install && yarn run typesafe-i18n && yarn build - -# Removing the iframe.html file from the final image as this adds a XSS attack. -# iframe.html is only in dev mode to circumvent a limitation -RUN rm dist/iframe.html +RUN yarn install && yarn run typesafe-i18n && yarn run build-iframe-api && yarn build FROM thecodingmachine/nodejs:14-apache diff --git a/front/dist/.gitignore b/front/dist/.gitignore deleted file mode 100644 index beb1ee19..00000000 --- a/front/dist/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -index.html -/js/ -/fonts/ -style.*.css -!env-config.template.js -*.png -!/resources/** diff --git a/front/dist/env-config.template.js b/front/dist/env-config.template.js deleted file mode 100644 index e672d7aa..00000000 --- a/front/dist/env-config.template.js +++ /dev/null @@ -1,27 +0,0 @@ -window.env = { - SKIP_RENDER_OPTIMIZATIONS: '${SKIP_RENDER_OPTIMIZATIONS}', - DISABLE_NOTIFICATIONS: '${DISABLE_NOTIFICATIONS}', - PUSHER_URL: '${PUSHER_URL}', - UPLOADER_URL: '${UPLOADER_URL}', - ADMIN_URL: '${ADMIN_URL}', - CONTACT_URL: '${CONTACT_URL}', - PROFILE_URL: '${PROFILE_URL}', - ICON_URL: '${ICON_URL}', - DEBUG_MODE: '${DEBUG_MODE}', - STUN_SERVER: '${STUN_SERVER}', - TURN_SERVER: '${TURN_SERVER}', - TURN_USER: '${TURN_USER}', - TURN_PASSWORD: '${TURN_PASSWORD}', - JITSI_URL: '${JITSI_URL}', - JITSI_PRIVATE_MODE: '${JITSI_PRIVATE_MODE}', - START_ROOM_URL: '${START_ROOM_URL}', - MAX_USERNAME_LENGTH: '${MAX_USERNAME_LENGTH}', - MAX_PER_GROUP: '${MAX_PER_GROUP}', - DISPLAY_TERMS_OF_USE: '${DISPLAY_TERMS_OF_USE}', - POSTHOG_API_KEY: '${POSTHOG_API_KEY}', - POSTHOG_URL: '${POSTHOG_URL}', - NODE_ENV: '${NODE_ENV}', - DISABLE_ANONYMOUS: '${DISABLE_ANONYMOUS}', - OPID_LOGIN_SCREEN_PROVIDER: '${OPID_LOGIN_SCREEN_PROVIDER}', - FALLBACK_LOCALE: '${FALLBACK_LOCALE}', -}; diff --git a/front/dist/iframe.html b/front/dist/iframe.html deleted file mode 100644 index 14e65b6f..00000000 --- a/front/dist/iframe.html +++ /dev/null @@ -1,21 +0,0 @@ - - -
- - - - diff --git a/front/dist/resources/fonts/fonts.css b/front/dist/resources/fonts/fonts.css deleted file mode 100644 index a3d3cf71..00000000 --- a/front/dist/resources/fonts/fonts.css +++ /dev/null @@ -1,5 +0,0 @@ -/*This file is a workaround to allow phaser to load directly this font */ -@font-face { - font-family: "Press Start 2P"; - src: url("/fonts/press-start-2p-latin-400-normal.woff2") format('woff2'); -} \ No newline at end of file diff --git a/front/iframe-api.vite.config.ts b/front/iframe-api.vite.config.ts new file mode 100644 index 00000000..3698647b --- /dev/null +++ b/front/iframe-api.vite.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from "vite"; +import { resolve } from "path"; + +export default defineConfig({ + publicDir: false, + build: { + outDir: "public", + emptyOutDir: false, + lib: { + entry: resolve(__dirname, "src/iframe_api.ts"), + name: "iframe_api", + formats: ["cjs"], + fileName: () => "iframe_api.js", + }, + }, +}); diff --git a/front/dist/index.ejs b/front/index.html similarity index 98% rename from front/dist/index.ejs rename to front/index.html index 11d33ad0..c941f715 100644 --- a/front/dist/index.ejs +++ b/front/index.html @@ -27,8 +27,8 @@ -