From daf78c8e15acce6137e5a64f8f1d5e9190afa871 Mon Sep 17 00:00:00 2001 From: Matt Mayfield Date: Mon, 18 Nov 2024 16:48:51 -0500 Subject: [PATCH] Add docker stack for e2e tests, remove cypress (#524) * Add docker stack for e2e tests * Remove cypress * Split CI into lint and component-tests * Fix vue proxy settings and remove nginx proxy --------- Co-authored-by: James Perretta Co-authored-by: James Perretta --- .eslintrc.json | 4 +- .github/workflows/node.js.yml | 34 ++++-- .gitmodules | 3 + cypress.config.ts | 16 --- cypress/fixtures/example.json | 5 - cypress/support/commands.ts | 37 ------- cypress/support/component-index.html | 12 --- cypress/support/component.ts | 40 ------- cypress/support/e2e.ts | 20 ---- docker-compose.yml | 149 --------------------------- e2e_test_stack/autograder-server | 1 + e2e_test_stack/docker-compose.yml | 65 ++++++++++++ nginx/conf.d/default.conf | 14 --- package-lock.json | 33 +++--- static_analysis.bash | 8 +- tsconfig.json | 3 +- vue.config.js | 6 +- 17 files changed, 120 insertions(+), 330 deletions(-) create mode 100644 .gitmodules delete mode 100644 cypress.config.ts delete mode 100644 cypress/fixtures/example.json delete mode 100644 cypress/support/commands.ts delete mode 100644 cypress/support/component-index.html delete mode 100644 cypress/support/component.ts delete mode 100644 cypress/support/e2e.ts delete mode 100644 docker-compose.yml create mode 160000 e2e_test_stack/autograder-server create mode 100644 e2e_test_stack/docker-compose.yml delete mode 100644 nginx/conf.d/default.conf diff --git a/.eslintrc.json b/.eslintrc.json index 6f5558a0b..5b554d03f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,9 +6,11 @@ "extends": [ "eslint:recommended", "plugin:vue/essential", - "plugin:@typescript-eslint/recommended" + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-type-checked" ], "parserOptions": { + "project": true, "ecmaVersion": 12, "parser": "@typescript-eslint/parser", "sourceType": "module" diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index ad62a3803..c4fa07098 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -7,11 +7,9 @@ on: push: branches: [ develop ] pull_request: - branches: [ develop ] jobs: - build: - + lint: runs-on: ubuntu-latest strategy: @@ -21,14 +19,36 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} cache: 'npm' - - run: npm install + + - run: npm ci - run: npm run lint - - run: npm run build - - run: npm test - - run: npx cypress run --component + component-tests: + # Lint is fast. If we wait for it we guarantee a cache hit on dependencies. + needs: lint + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - run: npm ci + - run: npm run build + - run: npm run test diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..8b3b645aa --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "e2e_test_stack/autograder-server"] + path = e2e_test_stack/autograder-server + url = git@github.com:eecs-autograder/autograder-server.git diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 6efe82ab7..000000000 --- a/cypress.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from "cypress"; - -export default defineConfig({ - component: { - devServer: { - framework: "vue-cli", - bundler: "webpack", - }, - }, - - e2e: { - setupNodeEvents(on, config) { - // implement node event listeners here - }, - }, -}); diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index 02e425437..000000000 --- a/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts deleted file mode 100644 index 95857aea4..000000000 --- a/cypress/support/commands.ts +++ /dev/null @@ -1,37 +0,0 @@ -/// -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -// -// declare global { -// namespace Cypress { -// interface Chainable { -// login(email: string, password: string): Chainable -// drag(subject: string, options?: Partial): Chainable -// dismiss(subject: string, options?: Partial): Chainable -// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable -// } -// } -// } diff --git a/cypress/support/component-index.html b/cypress/support/component-index.html deleted file mode 100644 index ac6e79fd8..000000000 --- a/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Components App - - -
- - \ No newline at end of file diff --git a/cypress/support/component.ts b/cypress/support/component.ts deleted file mode 100644 index d3592dbf1..000000000 --- a/cypress/support/component.ts +++ /dev/null @@ -1,40 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import "./commands"; - -// Alternatively you can use CommonJS syntax: -// require('./commands') - -import { mount } from "cypress/vue2"; - -// Augment the Cypress namespace to include type definitions for -// your custom command. -// Alternatively, can be defined in cypress/support/component.d.ts -// with a at the top of your spec. -declare global { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace Cypress { - interface Chainable { - mount: typeof mount; - } - } -} - -Cypress.Commands.add("mount", mount); - -// Example use: -// cy.mount(MyComponent) diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts deleted file mode 100644 index 6a173d6fc..000000000 --- a/cypress/support/e2e.ts +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/e2e.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import "./commands"; - -// Alternatively you can use CommonJS syntax: -// require('./commands') diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 19b7bacca..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,149 +0,0 @@ -version: '3' - -services: - nginx: - image: nginx:latest - restart: unless-stopped - container_name: ag-vue-dev-nginx - ports: - - "8080:80" - volumes: - - ./nginx/conf.d:/etc/nginx/conf.d - - website: - restart: unless-stopped - build: - context: . - dockerfile: Dockerfile-website-dev - container_name: ag-vue-dev-website - expose: - - "8080" - volumes: - - ./src:/usr/src/app/src - - ./tests:/usr/src/app/tests - - ./public:/usr/src/app/public - command: npm run serve -- --host website - - django: - restart: unless-stopped - build: - context: ./autograder-server - dockerfile: Dockerfile-django-dev - container_name: ag-vue-dev-django - expose: - - "8001" - ports: - - "9001:8001" - volumes: - - ./autograder-server:/usr/src/app - command: /usr/local/bin/uwsgi --py-autoreload 1 --ini /usr/src/app/uwsgi/uwsgi.ini - env_file: - - ./autograder-server/_dev.env - environment: - # Set to false to disable real authentication. Any other string value - # will enable real authentication. - # Then, using a browser plugin such as EditThisCookie, set the - # cookie "username=" to set which user you want to - # authenticate as. - USE_REAL_AUTH: 'false' - - postgres: - restart: unless-stopped - image: postgres:latest - container_name: ag-vue-dev-postgres - expose: - - "5432" - volumes: - - pgdata:/var/lib/postgresql/data/ - environment: - POSTGRES_PASSWORD: 'postgres' - - redis: - restart: unless-stopped - image: redis:latest - container_name: ag-vue-dev-redis - expose: - - "6379" - volumes: - - redisdata:/data - - rabbitmq: - image: 127.0.0.1:5000/rabbitmq - restart: unless-stopped - image: rabbitmq:latest - container_name: ag-vue-dev-rabbitmq - hostname: rabbit - expose: - - "5672" - - celery_small_tasks: - restart: unless-stopped - build: - context: ./autograder-server - dockerfile: Dockerfile-django-dev - container_name: ag-vue-dev-celery-small-tasks - volumes: - - ./autograder-server:/usr/src/app - command: /usr/local/bin/celery worker -c 1 -A autograder -l info -Q small_tasks -n small_tasks@%h - env_file: - - ./autograder-server/_dev.env - - celery_project_downloads: - restart: unless-stopped - build: - context: ./autograder-server - dockerfile: Dockerfile-django-dev - container_name: ag-vue-dev-celery-project-downloads - volumes: - - ./autograder-server:/usr/src/app - command: /usr/local/bin/celery worker -c 1 -A autograder -l info -Q project_downloads -n project_downloads@%h - env_file: - - ./autograder-server/_dev.env - - celerybeat: - container_name: ag-vue-dev-celerybeat - restart: unless-stopped - build: - context: ./autograder-server - dockerfile: Dockerfile-django-dev - env_file: - - ./autograder-server/_dev.env - volumes: - - ./autograder-server:/usr/src/app - command: /usr/local/bin/celery worker --beat -c 1 -A autograder -l info -Q periodic_tasks -n periodic_tasks@%h - - # environment: - # AG_SUBMISSION_LISTENER_INTERVAL: 5 - - grader: - container_name: ag-vue-dev-grader - build: - dockerfile: Dockerfile-grader-dev - context: ./autograder-server - - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./autograder-server:/usr/src/app - - env_file: - - ./autograder-server/_dev.env - - command: /usr/local/bin/celery -A autograder worker -n submission_grader@%h --loglevel=info -c 1 - - deferred_grader: - container_name: ag-vue-dev-deferred-grader - build: - dockerfile: Dockerfile-grader-dev - context: ./autograder-server - - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./autograder-server:/usr/src/app - env_file: - - ./autograder-server/_dev.env - - command: /usr/local/bin/celery -A autograder worker -Q deferred,rerun -n deferred@%h --loglevel=info -c 1 - -volumes: - redisdata: {} - pgdata: {} diff --git a/e2e_test_stack/autograder-server b/e2e_test_stack/autograder-server new file mode 160000 index 000000000..3a9045f11 --- /dev/null +++ b/e2e_test_stack/autograder-server @@ -0,0 +1 @@ +Subproject commit 3a9045f11456216a1d098495c243ea10f416a4df diff --git a/e2e_test_stack/docker-compose.yml b/e2e_test_stack/docker-compose.yml new file mode 100644 index 000000000..2b9e77b7a --- /dev/null +++ b/e2e_test_stack/docker-compose.yml @@ -0,0 +1,65 @@ +version: "3" + +services: + website: + restart: no + build: + context: ../ + dockerfile: Dockerfile-website-dev + container_name: ag-vue-e2e-website + ports: + - 8080:8080 + # expose: + # - "8080" + volumes: + - ../src:/usr/src/app/src + - ../tests:/usr/src/app/tests + - ../public:/usr/src/app/public + command: npm run serve + + django: + restart: no + build: + context: ./autograder-server + dockerfile: Dockerfile-django-dev + container_name: ag-vue-e2e-django + expose: + - "8000" + volumes: + - ./autograder-server:/usr/src/app + command: >- + python3 manage.py runserver 0.0.0.0:8000 + + env_file: + - ./autograder-server/_dev.env + environment: + # Set to false to disable real authentication. Any other string value + # will enable real authentication. + # Then, using a browser plugin such as EditThisCookie, set the + # cookie "username=" to set which user you want to + # authenticate as. + USE_REAL_AUTH: "false" + + postgres: + restart: no + image: postgres:latest + container_name: ag-vue-e2e-postgres + expose: + - "5432" + environment: + POSTGRES_PASSWORD: "postgres" + + redis: + restart: no + image: redis:latest + container_name: ag-vue-e2e-redis + expose: + - "6379" + + rabbitmq: + restart: no + image: rabbitmq:latest + container_name: ag-vue-e2e-rabbitmq + hostname: rabbit + expose: + - "5672" diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/default.conf deleted file mode 100644 index f798be974..000000000 --- a/nginx/conf.d/default.conf +++ /dev/null @@ -1,14 +0,0 @@ -server { - listen 80; - listen 443; - - root /usr/src/app/dist; - - location = / { - index /index.html; - } - - location /web { - try_files /index.html =404; - } -} diff --git a/package-lock.json b/package-lock.json index 29a9b85ce..37a79419f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,7 @@ "eslint": "^7.32.0", "eslint-plugin-vue": "^7.20.0", "jest": "^25.0.0", - "prettier": "^3.3.3", + "prettier": "3.3.3", "sass": "^1.66.1", "sass-loader": "^10.1.1", "sinon": "^7.5.0", @@ -8996,12 +8996,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -11354,15 +11355,16 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -17431,10 +17433,11 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/multicast-dns": { "version": "6.2.3", @@ -20667,12 +20670,6 @@ "node": ">=4" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/serialize-javascript": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", diff --git a/static_analysis.bash b/static_analysis.bash index 7b59abf98..2681c846d 100755 --- a/static_analysis.bash +++ b/static_analysis.bash @@ -1,12 +1,6 @@ set -ex -npx eslint \ - 'cypress/**/*.ts' \ - '**/*.cy.ts' - npx prettier --check \ - './*.js' \ - 'cypress/**/*.ts' \ - '**/*.cy.ts' + './*.js' ./check_subscribe_unsubscribe.py 'src/**/*.vue' diff --git a/tsconfig.json b/tsconfig.json index 8a5b13d63..56985738c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -47,6 +47,7 @@ "tests/**/*.tsx" ], "exclude": [ - "node_modules" + "node_modules", + "e2e_test_stack" ] } diff --git a/vue.config.js b/vue.config.js index 43025699a..ec4e739a9 100644 --- a/vue.config.js +++ b/vue.config.js @@ -2,13 +2,13 @@ module.exports = { devServer: { proxy: { "/api": { - target: "http://django:8001", + target: "http://django:8000", }, "/static": { - target: "http://django:8001", + target: "http://django:8000", }, "/__debug__/": { - target: "http://django:8001", + target: "http://django:8000", }, }, },