From 0c841de5b5500eec8938075366c4f9240a666961 Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Sat, 1 Jun 2024 15:20:35 +0200
Subject: [PATCH 01/17] Don't just mount `spec` folder, but complete `app`
folder for tests (#648)
* Don't just mount `spec` folder, but complete `app` folder for tests
This is to ensure that local changes in the `app` folder are reflected
in the Docker container such that newly written tests can be run through
without having to rebuild the whole Docker image.
* Exclude `public/` folder from mount
Also see: https://stackoverflow.com/a/56361190/
* Copy everything to `usr/src/app` for precompiling to work & fix `public/` folder mount
Also see https://stackoverflow.com/a/37898591/
---
docker/test/Dockerfile | 3 ++-
docker/test/docker-compose.yml | 10 +++-------
2 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/docker/test/Dockerfile b/docker/test/Dockerfile
index 74cdc9b38..470e065f5 100644
--- a/docker/test/Dockerfile
+++ b/docker/test/Dockerfile
@@ -58,6 +58,7 @@ RUN apt update && \
RUN sed -i '/disable ghostscript format types/,+6d' /etc/ImageMagick-6/policy.xml
WORKDIR /usr/src/app
+ENTRYPOINT ["./entrypoint.sh"]
COPY ./Gemfile ./Gemfile.lock ./yarn.lock ./package.json /usr/src/app/
RUN bundle install
@@ -66,7 +67,7 @@ RUN yarn install --production=false
COPY --from=build-pdfcomprezzor /go/src/pdfcomprezzor.wasm /go/src/wasm_exec.js /usr/src/app/public/pdfcomprezzor/
COPY --from=build-pdfcomprezzor /go/src/pdfcomprezzor.wasm /go/src/wasm_exec.js /
-COPY . /usr/src/app/
+COPY . /usr/src/app
COPY ./docker/production/docker.env ./docker-dummy.env
RUN set -o allexport && . ./docker-dummy.env && set +o allexport && \
diff --git a/docker/test/docker-compose.yml b/docker/test/docker-compose.yml
index f8b21e7eb..eac665df1 100644
--- a/docker/test/docker-compose.yml
+++ b/docker/test/docker-compose.yml
@@ -37,9 +37,6 @@ services:
context: ./../..
dockerfile: docker/test/Dockerfile
image: mampf:tests
- # TODO: Use this
- # entrypoint: /usr/src/app/docker/test/run_tests.sh
- entrypoint: /usr/src/app/entrypoint.sh
environment:
RAILS_ENV: test
TEST_DATABASE_ADAPTER: postgresql
@@ -68,10 +65,9 @@ services:
SPROCKETS_CACHE: /cache
BLOG: https://mampf.blog
volumes:
- - type: bind
- source: ../../spec/
- target: /usr/src/app/spec/
- - ../../coverage:/usr/src/app/coverage
+ - ../../:/usr/src/app/
+ - ../../coverage:/usr/src/app/coverage/
+ - "/usr/src/app/public/"
depends_on:
- db
- solr
From ed867fb2c084de24ce50e2b06373b5296b269359 Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Wed, 5 Jun 2024 20:09:18 +0200
Subject: [PATCH 02/17] Make watchlist test cases a bit more robust (#650)
---
spec/models/watchlist_entry_spec.rb | 10 ++++++----
spec/models/watchlist_spec.rb | 4 ++--
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/spec/models/watchlist_entry_spec.rb b/spec/models/watchlist_entry_spec.rb
index 4e938f777..f76eacda4 100644
--- a/spec/models/watchlist_entry_spec.rb
+++ b/spec/models/watchlist_entry_spec.rb
@@ -7,14 +7,16 @@
it "must have a medium" do
entry = FactoryBot.build(:watchlist_entry, :with_watchlist)
- entry.valid?
- expect(entry.errors[:medium]).to include("muss ausgefüllt werden")
+ expect(entry).not_to be_valid
+ expect(entry.errors).to have_key(:medium)
+ expect(entry.errors).not_to have_key(:watchlist)
end
it "must have a watchlist" do
entry = FactoryBot.build(:watchlist_entry, :with_medium)
- entry.valid?
- expect(entry.errors[:watchlist]).to include("muss ausgefüllt werden")
+ expect(entry).not_to be_valid
+ expect(entry.errors).to have_key(:watchlist)
+ expect(entry.errors).not_to have_key(:medium)
end
it "can only be once inside a watchlist" do
diff --git a/spec/models/watchlist_spec.rb b/spec/models/watchlist_spec.rb
index 5c511bf37..1432eccc2 100644
--- a/spec/models/watchlist_spec.rb
+++ b/spec/models/watchlist_spec.rb
@@ -7,8 +7,8 @@
it "must have a name" do
watchlist = Watchlist.new(name: nil)
- watchlist.valid?
- expect(watchlist.errors[:name]).to include("muss ausgefüllt werden")
+ expect(watchlist).not_to be_valid
+ expect(watchlist.errors).to have_key(:name)
end
it "must have a unique name" do
From 6bde35d606cf982fd72d4934db2d222c50915de2 Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Tue, 2 Jul 2024 23:50:24 +0200
Subject: [PATCH 03/17] Get Cypress up and running again (with docker and
interactive testing) (#652)
* Setup X11 Cypress GUI forwarding
Also see my StackOverflow question:
https://stackoverflow.com/q/78639075
* Delete unnecessary Cypress sample files
* Simplify Cypress config setup
* Use internal docker host port
* Delete old cypress helper
* Remove e2e configuration
* Fix wrong network assignment in Docker
* Add cypress ESLint plugin back
* Copy up-to-date on-rails commands from GitHub
See this file:
https://github.com/shakacode/cypress-on-rails/blob/master/lib/generators/cypress_on_rails/templates/spec/cypress/support/on-rails.js
* Init dummy submission cypress test
* Clean up comments in cypress-interactive Dockerfile
* Outsource cypress docker setup in separate file
* Remove `run_tests.sh` file
* Add `createUserAndLogin` cypress command
Also updated the cypress user emails and passwords.
* Name cypress users more creatively
* Add own Cypress FactoryBot implementation
* Move cypress controller to subfolder
* Remove cypress-on-rails dependency
Note that at this point, some cypress commands don't work yet.
* Outsource js error parsing logic to its own file
* Add database cleaner and user creator for cypress
* Fix RuboCop errors and improve documentation
* Remove unnecessary `Cypress::` specifier
* Remove unnecessary `index.js` file
* Improve documentation for FactoryBot
* Start Cypress UI automatically with open browser
* Add Cypress tests to GitHub Actions CI/CD
* Pass ./cypress.yml file to docker & split lines
* Disable existing cypress tests for now
will bring them back in a subsequent PR
* Rename submissions spec
* Rename cypress route subjects
* Don't clear entrypoint for cypress tests
* Execute "cypress run" in entrypoint
* Rename archived tests and exclude them from ESLint
* Temporarily disable docker compose cache
* Disable old migrations stemming from globalize gem
Along side this, the schema was automatically updated and got rid of
old translation tables originally created by the globalize gem.
They were still in here as remnant of #609.
* Add back docker compose cache to cypress workflow
* Revert "Disable old migrations stemming from globalize gem"
This reverts commit 88f369e7194ba07cc7c1c0a6d44b3b73bec28834.
* Use `db:schema:load` instead of `db:migrate`
See https://github.com/rails/rails/blob/d43ee2088118425e493766aeb20575e9ce7159d1/actionmailbox/test/dummy/db/schema.rb#L5-L9
We also abort the script if it is called from the production
environment. It's only intended for usage in the dev/test environment.
For production, we have the respective master and worker entrypoints.
* Wait for MaMpf before opening cypress UI
---
.config/.cypress.js | 6 +
.config/eslint.mjs | 19 +-
.github/workflows/tests.yml | 36 ++++
Gemfile | 1 -
Gemfile.lock | 3 -
TESTING.md | 2 +-
app/controllers/cypress/cypress_controller.rb | 24 +++
.../cypress/database_cleaner_controller.rb | 10 ++
.../cypress/factories_controller.rb | 36 ++++
.../cypress/user_creator_controller.rb | 22 +++
config/initializers/cypress_on_rails.rb | 11 --
config/routes.rb | 8 +
docker/test/Dockerfile_cypress | 5 +-
docker/test/cypress-interactive.yml | 17 ++
docker/test/cypress.yml | 25 +++
docker/test/docker-compose.local.yml | 90 ----------
docker/test/docker-compose.yml | 3 +
docker/test/run_tests.sh | 11 --
initialize.sh | 17 +-
package.json | 1 +
spec/cypress.config.js | 13 --
.../app_commands/activerecord_fixtures.rb | 25 ---
spec/cypress/app_commands/clean.rb | 10 --
spec/cypress/app_commands/eval.rb | 1 -
spec/cypress/app_commands/factory_bot.rb | 14 --
spec/cypress/app_commands/log_fail.rb | 29 ----
spec/cypress/app_commands/scenarios/admin.rb | 2 -
spec/cypress/app_commands/scenarios/editor.rb | 3 -
.../app_commands/scenarios/non_admin.rb | 3 -
.../cypress/app_commands/scenarios/teacher.rb | 3 -
spec/cypress/cypress_helper.rb | 32 ----
...in_spec.cy.js => admin_spec.cy.archive.js} | 0
..._spec.cy.js => courses_spec.cy.archive.js} | 0
...ia_spec.cy.js => media_spec.cy.archive.js} | 0
...h_spec.cy.js => search_spec.cy.archive.js} | 0
.../e2e/submissions_spec.cy.archive.js | 153 +++++++++++++++++
spec/cypress/e2e/submissions_spec.cy.js | 162 ++----------------
...spec.cy.js => thredded_spec.cy.archive.js} | 0
...pec.cy.js => tutorials_spec.cy.archive.js} | 0
...ec.cy.js => watchlists_spec.cy.archive.js} | 0
spec/cypress/fixtures/example.json | 5 -
spec/cypress/plugins/index.js | 21 ---
spec/cypress/support/backend_caller.js | 31 ++++
spec/cypress/support/commands.js | 58 ++++---
spec/cypress/support/e2e.js | 1 -
spec/cypress/support/factorybot.js | 22 +++
spec/cypress/support/index.js | 21 ---
spec/cypress/support/on-rails.js | 59 -------
yarn.lock | 19 ++
49 files changed, 491 insertions(+), 543 deletions(-)
create mode 100644 .config/.cypress.js
create mode 100644 app/controllers/cypress/cypress_controller.rb
create mode 100644 app/controllers/cypress/database_cleaner_controller.rb
create mode 100644 app/controllers/cypress/factories_controller.rb
create mode 100644 app/controllers/cypress/user_creator_controller.rb
delete mode 100644 config/initializers/cypress_on_rails.rb
create mode 100644 docker/test/cypress-interactive.yml
create mode 100644 docker/test/cypress.yml
delete mode 100644 docker/test/docker-compose.local.yml
delete mode 100755 docker/test/run_tests.sh
delete mode 100644 spec/cypress.config.js
delete mode 100644 spec/cypress/app_commands/activerecord_fixtures.rb
delete mode 100644 spec/cypress/app_commands/clean.rb
delete mode 100644 spec/cypress/app_commands/eval.rb
delete mode 100644 spec/cypress/app_commands/factory_bot.rb
delete mode 100644 spec/cypress/app_commands/log_fail.rb
delete mode 100644 spec/cypress/app_commands/scenarios/admin.rb
delete mode 100644 spec/cypress/app_commands/scenarios/editor.rb
delete mode 100644 spec/cypress/app_commands/scenarios/non_admin.rb
delete mode 100644 spec/cypress/app_commands/scenarios/teacher.rb
delete mode 100644 spec/cypress/cypress_helper.rb
rename spec/cypress/e2e/{admin_spec.cy.js => admin_spec.cy.archive.js} (100%)
rename spec/cypress/e2e/{courses_spec.cy.js => courses_spec.cy.archive.js} (100%)
rename spec/cypress/e2e/{media_spec.cy.js => media_spec.cy.archive.js} (100%)
rename spec/cypress/e2e/{search_spec.cy.js => search_spec.cy.archive.js} (100%)
create mode 100644 spec/cypress/e2e/submissions_spec.cy.archive.js
rename spec/cypress/e2e/{thredded_spec.cy.js => thredded_spec.cy.archive.js} (100%)
rename spec/cypress/e2e/{tutorials_spec.cy.js => tutorials_spec.cy.archive.js} (100%)
rename spec/cypress/e2e/{watchlists_spec.cy.js => watchlists_spec.cy.archive.js} (100%)
delete mode 100644 spec/cypress/fixtures/example.json
delete mode 100644 spec/cypress/plugins/index.js
create mode 100644 spec/cypress/support/backend_caller.js
create mode 100644 spec/cypress/support/factorybot.js
delete mode 100644 spec/cypress/support/index.js
delete mode 100644 spec/cypress/support/on-rails.js
diff --git a/.config/.cypress.js b/.config/.cypress.js
new file mode 100644
index 000000000..cfc19cc0d
--- /dev/null
+++ b/.config/.cypress.js
@@ -0,0 +1,6 @@
+module.exports = {
+ e2e: {
+ // Add configuration here
+ // Base URL is set via Docker environment variable
+ },
+};
diff --git a/.config/eslint.mjs b/.config/eslint.mjs
index 008e58374..6c611016c 100644
--- a/.config/eslint.mjs
+++ b/.config/eslint.mjs
@@ -11,6 +11,7 @@
import js from "@eslint/js";
import stylistic from "@stylistic/eslint-plugin";
import erb from "eslint-plugin-erb";
+import pluginCypress from "eslint-plugin-cypress/flat";
import globals from "globals";
const ignoreFilesWithSprocketRequireSyntax = [
@@ -22,6 +23,17 @@ const ignoreFilesWithSprocketRequireSyntax = [
"vendor/assets/javascripts/thredded_timeago.js",
];
+const ignoreCypressArchivedTests = [
+ "spec/cypress/e2e/admin_spec.cy.archive.js",
+ "spec/cypress/e2e/courses_spec.cy.archive.js",
+ "spec/cypress/e2e/media_spec.cy.archive.js",
+ "spec/cypress/e2e/search_spec.cy.archive.js",
+ "spec/cypress/e2e/submissions_spec.cy.archive.js",
+ "spec/cypress/e2e/thredded_spec.cy.archive.js",
+ "spec/cypress/e2e/tutorials_spec.cy.archive.js",
+ "spec/cypress/e2e/watchlists_spec.cy.archive.js",
+];
+
const customGlobals = {
TomSelect: "readable",
bootstrap: "readable",
@@ -89,14 +101,11 @@ const customGlobals = {
renderMathInElement: "readable",
};
-// We don't have cypress linting yet, as the Cypress ESLint plugin
-// doesn't support the new flat config yet
-// https://github.com/cypress-io/eslint-plugin-cypress/issues/146
-
export default [
js.configs.recommended,
// Allow linting of ERB files, see https://github.com/Splines/eslint-plugin-erb
erb.configs.recommended,
+ pluginCypress.configs.recommended,
// Globally ignore the following paths
{
ignores: [
@@ -107,8 +116,8 @@ export default [
"public/packs-test/",
"public/uploads/",
"public/pdfcomprezzor/",
- "spec/cypress/",
...ignoreFilesWithSprocketRequireSyntax,
+ ...ignoreCypressArchivedTests,
],
},
{
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index db47d5027..87bb2ec24 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -60,3 +60,39 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
codecov_yml_path: ./config/codecov.yml
+
+ # Cypress end-to-end tests
+ e2e-tests:
+ name: e2e (Cypress)
+ environment: testing
+ runs-on: ubuntu-latest
+ permissions: write-all
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: Setup Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ # see https://github.com/orgs/MaMpf-HD/packages?repo_name=mampf
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build docker images
+ # As the docker-compose.yml file uses contexts like "./../..", we have
+ # to change the working directory here.
+ working-directory: docker/test
+ run: >
+ docker buildx bake -f ./docker-compose.yml -f ./cypress.yml
+ -f ./../../.github/workflows/docker-compose-cache.json
+
+ - name: Run Cypress tests
+ working-directory: docker/test
+ # "cypress run" is defined in the cypress.yml entrypoint
+ run: docker compose -f ./docker-compose.yml -f ./cypress.yml run cypress
diff --git a/Gemfile b/Gemfile
index 81419a97c..88a53f4e6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -136,7 +136,6 @@ group :test, :development, :docker_development do
gem "factory_bot_rails"
gem "rspec-rails"
- gem "cypress-on-rails", "~> 1.0"
gem "simplecov-cobertura"
gem "rspec-github"
diff --git a/Gemfile.lock b/Gemfile.lock
index 87e30b105..2c50d5a08 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -211,8 +211,6 @@ GEM
crass (1.0.6)
css_parser (1.17.1)
addressable
- cypress-on-rails (1.17.0)
- rack
dalli (3.2.8)
database_cleaner-active_record (2.1.0)
activerecord (>= 5.a)
@@ -690,7 +688,6 @@ DEPENDENCIES
coffee-rails (~> 5.0.0)
commontator
coveralls
- cypress-on-rails (~> 1.0)
dalli (>= 2.7)
database_cleaner-active_record
devise
diff --git a/TESTING.md b/TESTING.md
index e45526234..4179a8019 100644
--- a/TESTING.md
+++ b/TESTING.md
@@ -18,7 +18,7 @@ Furthermore, you can setup special scenarios by providing a file in `spec/cypres
that can be called by `cy.appScenario("setup")` for example. Always try to
create as much as you can in the scenario and then test the interaction!
-For more information visit [cypress-documentation](https://docs.cypress.io) and the used gem [cypress-on-rails](https://github.com/shakacode/cypress-on-rails)
+For more information visit [cypress-documentation](https://docs.cypress.io).
# Testing rspec
diff --git a/app/controllers/cypress/cypress_controller.rb b/app/controllers/cypress/cypress_controller.rb
new file mode 100644
index 000000000..3e043ba15
--- /dev/null
+++ b/app/controllers/cypress/cypress_controller.rb
@@ -0,0 +1,24 @@
+module Cypress
+ # Handles Cypress requests for interactive UI testing.
+ #
+ # The main purpose of this class is to send back errors as JSON object
+ # to parse them in the Cypress test UI. This way, we can display the error
+ # message and the stacktrace in the Cypress test.
+ class CypressController < ApplicationController
+ respond_to :json
+ rescue_from Exception, with: :show_errors
+ skip_before_action :authenticate_user!
+
+ private
+
+ # Returns the error as JSON such that it can be displayed in the Cypress test.
+ def show_errors(exception)
+ error = {
+ error: "#{exception.class}: #{exception}",
+ stacktrace: exception.backtrace.join("\n")
+ }
+
+ render json: error, status: :bad_request
+ end
+ end
+end
diff --git a/app/controllers/cypress/database_cleaner_controller.rb b/app/controllers/cypress/database_cleaner_controller.rb
new file mode 100644
index 000000000..21748c015
--- /dev/null
+++ b/app/controllers/cypress/database_cleaner_controller.rb
@@ -0,0 +1,10 @@
+module Cypress
+ # Cleans the database for use in Cypress tests.
+ class DatabaseCleanerController < CypressController
+ def create
+ res = DatabaseCleaner.clean_with(:truncation)
+
+ render json: res.to_json, status: :created
+ end
+ end
+end
diff --git a/app/controllers/cypress/factories_controller.rb b/app/controllers/cypress/factories_controller.rb
new file mode 100644
index 000000000..db0677755
--- /dev/null
+++ b/app/controllers/cypress/factories_controller.rb
@@ -0,0 +1,36 @@
+module Cypress
+ # Handles Cypress requests to create factories via FactoryBot.
+ # See the factorybot.js file in the Cypress support folder.
+ #
+ # It is inspired by this blog post by Tom Conroy:
+ # https://tbconroy.com/2018/04/07/creating-data-with-factorybot-for-rails-cypress-tests/
+ class FactoriesController < CypressController
+ # Wrapper around FactoryBot.create to create a factory via a POST request.
+ def create
+ unless params["0"].is_a?(String)
+ msg = "First argument must be a string indicating the factory name."
+ msg += " But we got: '#{params["0"]}'"
+ raise(ArgumentError, msg)
+ end
+
+ attributes = params_to_attributes(params.except(:controller, :action, :number))
+ res = FactoryBot.create(*attributes)
+
+ render json: res.to_json, status: :created
+ end
+
+ private
+
+ def params_to_attributes(params)
+ params.to_unsafe_hash.map do |_key, value|
+ if value.is_a?(Hash)
+ value.transform_keys(&:to_sym)
+ elsif value.is_a?(String)
+ value.to_sym
+ else
+ throw("Value is neither a hash nor a string: #{value}")
+ end
+ end
+ end
+ end
+end
diff --git a/app/controllers/cypress/user_creator_controller.rb b/app/controllers/cypress/user_creator_controller.rb
new file mode 100644
index 000000000..f82b4dd18
--- /dev/null
+++ b/app/controllers/cypress/user_creator_controller.rb
@@ -0,0 +1,22 @@
+module Cypress
+ # Creates a user for use in Cypress tests.
+ class UserCreatorController < CypressController
+ def create
+ unless params[:role].is_a?(String)
+ msg = "First argument must be a string indicating the user role."
+ msg += " But we got: '#{params["0"]}'"
+ raise(ArgumentError, msg)
+ end
+
+ role = params[:role]
+ is_admin = (role == "admin")
+
+ user = User.create(name: "#{role} Cypress", email: "#{role}@mampf.cypress",
+ password: "cypress123", consents: true, admin: is_admin,
+ locale: I18n.default_locale)
+ user.confirm
+
+ render json: user.to_json, status: :created
+ end
+ end
+end
diff --git a/config/initializers/cypress_on_rails.rb b/config/initializers/cypress_on_rails.rb
deleted file mode 100644
index a9839d66b..000000000
--- a/config/initializers/cypress_on_rails.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-if defined?(CypressOnRails)
- CypressOnRails.configure do |c|
- c.install_folder = File.expand_path("#{__dir__}/../../spec/cypress")
-
- # WARNING!! CypressOnRails can execute arbitrary ruby code
- # please use with extra caution if enabling on hosted servers
- # or starting your local server on 0.0.0.0
- c.use_middleware = Rails.env.test?
- c.logger = Rails.logger
- end
-end
diff --git a/config/routes.rb b/config/routes.rb
index cb0b1c763..33f2dac29 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -8,6 +8,14 @@
mount Sidekiq::Web => "/sidekiq"
end
+ if Rails.env.test?
+ namespace :cypress do
+ resources :factories, only: :create
+ resources :database_cleaner, only: :create
+ resources :user_creator, only: :create
+ end
+ end
+
# mount commontator engine
mount Commontator::Engine => "/commontator"
diff --git a/docker/test/Dockerfile_cypress b/docker/test/Dockerfile_cypress
index 684b8e9d3..62ac8cefe 100644
--- a/docker/test/Dockerfile_cypress
+++ b/docker/test/Dockerfile_cypress
@@ -1,5 +1,4 @@
-FROM cypress/included:12.9.0
+FROM cypress/included:13.11.0
-COPY ./spec/cypress/support /cypress/support
-# install the needed support stuff
+# Install curl
RUN apt-get update && apt-get install curl -y
diff --git a/docker/test/cypress-interactive.yml b/docker/test/cypress-interactive.yml
new file mode 100644
index 000000000..b4ce01f59
--- /dev/null
+++ b/docker/test/cypress-interactive.yml
@@ -0,0 +1,17 @@
+# Instructions for interactive mode
+# https://www.cypress.io/blog/2019/05/02/run-cypress-with-a-single-docker-command#Interactive-mode
+services:
+ cypress:
+ # https://on.cypress.io/command-line#cypress-open
+ entrypoint: >
+ bash -c "while ! curl -s $$CYPRESS_baseUrl > /dev/null;
+ do echo waiting for MaMpf to come online at $$CYPRESS_baseUrl;
+ sleep 1; done;
+ cypress open --project /mampf-tests/ --e2e --browser chrome"
+ environment:
+ # for X11/Wayland in WSLg
+ - DISPLAY
+ volumes:
+ # for Cypress to communicate with the X11 server pass this socket file
+ # in addition to any other mapped volumes
+ - /tmp/.X11-unix:/tmp/.X11-unix
diff --git a/docker/test/cypress.yml b/docker/test/cypress.yml
new file mode 100644
index 000000000..6e25fca67
--- /dev/null
+++ b/docker/test/cypress.yml
@@ -0,0 +1,25 @@
+services:
+ cypress:
+ depends_on:
+ - mampf
+ build:
+ context: ./../..
+ dockerfile: docker/test/Dockerfile_cypress
+ environment:
+ CYPRESS_baseUrl: http://mampf:3000
+ entrypoint: >
+ bash -c "while ! curl -s $$CYPRESS_baseUrl > /dev/null;
+ do echo waiting for MaMpf to come online at $$CYPRESS_baseUrl;
+ sleep 1; done;
+ RAILS_ENV=test cypress run --project /mampf-tests/ --e2e --browser chrome"
+ volumes:
+ - ../../.config/.cypress.js:/mampf-tests/cypress.config.js:ro
+ - ../../spec/cypress/e2e/:/mampf-tests/cypress/e2e/:ro
+ - ../../spec/cypress/support/:/mampf-tests/cypress/support/:ro
+ - ../../spec/cypress/fixtures/:/mampf-tests/cypress/fixtures/:ro
+ # Cypress video/screenshot output (only necessary locally)
+ - ../../cypress/videos/:/mampf-tests/cypress/videos/
+ - ../../cypress/screenshots/:/mampf-tests/cypress/screenshots/
+ networks:
+ - frontend
+ - backend
diff --git a/docker/test/docker-compose.local.yml b/docker/test/docker-compose.local.yml
deleted file mode 100644
index a4affb2be..000000000
--- a/docker/test/docker-compose.local.yml
+++ /dev/null
@@ -1,90 +0,0 @@
-services:
- redis:
- image: "redis:alpine"
-
- solr:
- image: "solr:8.11.1"
- ports:
- - "127.0.0.1:8983:8983"
- volumes:
- - type: bind
- source: ../../solr/development/conf/
- target: /solrconfig/
- read_only: true
- command: ["solr-precreate", "test", "/solrconfig"]
-
- db:
- image: postgres
- environment:
- - POSTGRES_USER=mampf
- - POSTGRES_HOST_AUTH_METHOD=trust
-
- mailcatcher:
- restart: on-failure:10
- image: dockage/mailcatcher:latest
- ports:
- - "127.0.0.1:1080:1080"
-
- mampf:
- build:
- context: ./../..
- dockerfile: docker/test/Dockerfile
- image: mampf:tests
- ports:
- - "127.0.0.1:3000:3000"
- # TODO: Use this
- # entrypoint: /usr/src/app/docker/test/run_tests.sh
- entrypoint: ./entrypoint.sh
- environment:
- RAILS_ENV: test
- TEST_DATABASE_ADAPTER: postgresql
- TEST_DATABASE_DATABASE: mampf
- TEST_DATABASE_INTERACTIONS: interactions
- TEST_DATABASE_USERNAME: mampf
- TEST_DATABASE_HOST: db
- TEST_DATABASE_PORT: 5432
- MAILSERVER: mailcatcher
- FROM_ADDRESS: development@localhost
- URL_HOST: mampf
- URL_HOST_SHORT: mampf
- SECRET_KEY_BASE: testenvironment
- ERDBEERE_SERVER: https://erdbeere.mathi.uni-heidelberg.de
- ERDBEERE_API: https://erdbeere.mathi.uni-heidelberg.de/api/v1
- MUESLI_SERVER: https://muesli.mathi.uni-heidelberg.de
- PROJECT_EMAIL: project@localhost
- FEEDBACK_EMAIL: feedback@localhost
- PROJECT_NOTIFICATION_EMAIL: project+notification@localhost
- MEDIA_FOLDER: mampf
- REDIS_URL: redis://redis:6379/1
- SOLR_HOST: solr
- SOLR_PORT: 8983
- SOLR_PATH: /solr/test
- SPROCKETS_CACHE: /cache
- volumes:
- - type: bind
- source: ../../spec/
- target: /usr/src/app/spec/
- depends_on:
- - db
- - solr
- - redis
- - mailcatcher
-
- cypress_runner:
- image: mampf-cypress
- build:
- context: ./../..
- dockerfile: docker/test/Dockerfile_cypress
- environment:
- CYPRESS_baseUrl: http://mampf:3000
- entrypoint: bash -c "while ! curl -s $$CYPRESS_baseUrl > /dev/null; do echo waiting for MaMpf to come online at $$CYPRESS_baseUrl; sleep 1; done; npx cypress run $$@"
- volumes:
- - ../../spec/cypress/e2e:/cypress/e2e:ro
- - ../../spec/cypress/fixtures:/cypress/fixtures:ro
- - ../../spec/cypress.config.js:/cypress.config.js:ro
- - ../../.git:/.git:ro
- # cypress outputs are saved here (needed only locally)
- - ../../cypress/videos:/cypress/videos
- - ../../cypress/screenshots:/cypress/screenshots
- depends_on:
- - mampf
diff --git a/docker/test/docker-compose.yml b/docker/test/docker-compose.yml
index eac665df1..34916abd1 100644
--- a/docker/test/docker-compose.yml
+++ b/docker/test/docker-compose.yml
@@ -37,6 +37,8 @@ services:
context: ./../..
dockerfile: docker/test/Dockerfile
image: mampf:tests
+ ports:
+ - "3000:3000"
environment:
RAILS_ENV: test
TEST_DATABASE_ADAPTER: postgresql
@@ -76,3 +78,4 @@ services:
networks:
- backend
- frontend
+
\ No newline at end of file
diff --git a/docker/test/run_tests.sh b/docker/test/run_tests.sh
deleted file mode 100755
index 8edb321e7..000000000
--- a/docker/test/run_tests.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-
-cd /usr/src/app
-
-./initialize.sh &> >(tee -a /usr/src/app/log/initialisation.log)
-
-rm -f tmp/pids/server.pid
-bin/rails server -e test -p 3000
-
-# in separate window start cypress
-yarn cypress open --project ./specs
diff --git a/initialize.sh b/initialize.sh
index e47cdab0b..75e8588f2 100755
--- a/initialize.sh
+++ b/initialize.sh
@@ -10,7 +10,7 @@ check_for_preseeds() {
done
rails db:restore pattern=$(echo $latest | rev | cut -d "/" -f1 | rev | cut -d "_" -f1)
rails db:create:interactions
- rails db:migrate
+ rails db:schema:load
fi
if [[ "${UPLOADS_PRESEED_URL}" ]]; then
echo "Found Upload Preseed with URL: $UPLOAD_PRESEED_URL"
@@ -20,6 +20,12 @@ check_for_preseeds() {
fi
}
+if [ "$RAILS_ENV" = "production" ]
+then
+ echo "This script is not intended for usage with RAILs_ENV=production. Aborting."
+ exit 1
+fi
+
echo Waiting for redis to come online
wait-for-it redis:6379 -t 30 || exit 1
if ! [ -f /completed_initial_run ]
@@ -41,13 +47,8 @@ then
bundle exec rails db:create:interactions
bundle exec rails db:create
fi
- echo running: bundle exec rails db:migrate
- bundle exec rails db:migrate
- if [ "$RAILS_ENV" = "production" ]
- then
- echo running: bundle exec rails assets:precompile
- bundle exec rails assets:precompile
- fi
+ echo running: bundle exec rails db:schema:load
+ bundle exec rails db:schema:load
echo Waiting for SOLR to come online
wait-for-it ${SOLR_HOST}:${SOLR_PORT} -t 30 || exit 1
bundle exec rake sunspot:solr:reindex &
diff --git a/package.json b/package.json
index 9110e2ed6..e426ab660 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"devDependencies": {
"@stylistic/eslint-plugin": "^1.8.0",
"eslint": "^9.1.1",
+ "eslint-plugin-cypress": "^3.3.0",
"eslint-plugin-erb": "^2.0.0",
"globals": "^15.1.0"
}
diff --git a/spec/cypress.config.js b/spec/cypress.config.js
deleted file mode 100644
index e289330b7..000000000
--- a/spec/cypress.config.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const { defineConfig } = require("cypress");
-
-module.exports = defineConfig({
- e2e: {
- baseUrl: "http://localhost:3000",
- defaultCommandTimeout: 10000,
- projectId: "v45wg9",
- retries: {
- runMode: 2,
- openMode: 0,
- },
- },
-});
diff --git a/spec/cypress/app_commands/activerecord_fixtures.rb b/spec/cypress/app_commands/activerecord_fixtures.rb
deleted file mode 100644
index 881319b7a..000000000
--- a/spec/cypress/app_commands/activerecord_fixtures.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# you can delete this file if you don't use Rails Test Fixtures
-
-fixtures_dir = command_options.try(:[], "fixtures_dir")
-fixture_files = command_options.try(:[], "fixtures")
-
-if defined?(ActiveRecord)
- require "active_record/fixtures"
-
- fixtures_dir ||= ActiveRecord::Tasks::DatabaseTasks.fixtures_path
- fixture_files ||= Dir["#{fixtures_dir}/**/*.yml"]
- .pluck((fixtures_dir.size + 1)..-5)
-
- logger.debug("loading fixtures: { dir: #{fixtures_dir}, " \
- "files: #{fixture_files} }")
- ActiveRecord::FixtureSet.reset_cache
- ActiveRecord::FixtureSet.create_fixtures(fixtures_dir, fixture_files)
- "Fixtures Done" # this gets returned
-else # this else part can be removed
- logger.error("Looks like activerecord_fixtures has to be modified to suite " \
- "your need")
- Post.create(title: "MyCypressFixtures")
- Post.create(title: "MyCypressFixtures2")
- Post.create(title: "MyRailsFixtures")
- Post.create(title: "MyRailsFixtures2")
-end
diff --git a/spec/cypress/app_commands/clean.rb b/spec/cypress/app_commands/clean.rb
deleted file mode 100644
index 798ca3338..000000000
--- a/spec/cypress/app_commands/clean.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-if defined?(DatabaseCleaner)
- # cleaning the database using database_cleaner
- DatabaseCleaner.strategy = :truncation
- DatabaseCleaner.clean
-else
- logger.warn("add database_cleaner or update cypress/app_commands/clean.rb")
- Post.delete_all if defined?(Post)
-end
-
-Rails.logger.info("APPCLEANED") # used by log_fail.rb
diff --git a/spec/cypress/app_commands/eval.rb b/spec/cypress/app_commands/eval.rb
deleted file mode 100644
index 3a39bf3e2..000000000
--- a/spec/cypress/app_commands/eval.rb
+++ /dev/null
@@ -1 +0,0 @@
-Kernel.eval(command_options) unless command_options.nil?
diff --git a/spec/cypress/app_commands/factory_bot.rb b/spec/cypress/app_commands/factory_bot.rb
deleted file mode 100644
index 135d955b4..000000000
--- a/spec/cypress/app_commands/factory_bot.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require "cypress_on_rails/smart_factory_wrapper"
-Array.wrap(command_options).map do |factory_options|
- factory_method = factory_options.shift
- begin
- logger.debug("running #{factory_method}, #{factory_options}")
- CypressOnRails::SmartFactoryWrapper.public_send(factory_method,
- *factory_options)
- rescue StandardError => e
- logger.error("#{e.class}: #{e.message}")
- logger.error(e.backtrace.join("\n"))
- logger.error(e.record.inspect.to_s) if e.is_a?(ActiveRecord::RecordInvalid)
- raise(e)
- end
-end
diff --git a/spec/cypress/app_commands/log_fail.rb b/spec/cypress/app_commands/log_fail.rb
deleted file mode 100644
index ed25a5927..000000000
--- a/spec/cypress/app_commands/log_fail.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file is called when a cypress spec fails and allows for extra logging
-# to be captured
-filename = command_options.fetch("runnable_full_title", "no title")
- .gsub(/[^[:print:]]/, "")
-
-# grab last lines until "APPCLEANED"
-# (Make sure in clean.rb to log the text "APPCLEANED")
-system "tail -n 10000 -r log/#{Rails.env}.log | " \
- "sed \"/APPCLEANED/ q\" | sed 'x;1!H;$!d;x' > 'log/#{filename}.log'"
-
-# create a json debug file for server debugging
-json_result = {}
-json_result["error"] = command_options.fetch("error_message",
- "no error message")
-
-if defined?(ActiveRecord::Base)
- json_result["records"] =
- ActiveRecord::Base.descendants
- .each_with_object({}) do |record_class, records|
- records[record_class.to_s] = record_class.limit(100).map(&:attributes)
- rescue StandardError # rubocop:todo Lint/SuppressedException
- end
-end
-
-filename = command_options.fetch("runnable_full_title", "no title")
- .gsub(/[^[:print:]]/, "")
-File.open(Rails.root.join("log/#{filename}.json").to_s, "w+") do |file|
- file << JSON.pretty_generate(json_result)
-end
diff --git a/spec/cypress/app_commands/scenarios/admin.rb b/spec/cypress/app_commands/scenarios/admin.rb
deleted file mode 100644
index 9505d4dcf..000000000
--- a/spec/cypress/app_commands/scenarios/admin.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-User.create(name: "Admin", email: "administrator@mampf.edu",
- password: "test123456", admin: true, consents: true).confirm
diff --git a/spec/cypress/app_commands/scenarios/editor.rb b/spec/cypress/app_commands/scenarios/editor.rb
deleted file mode 100644
index f1dbbc3b5..000000000
--- a/spec/cypress/app_commands/scenarios/editor.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-User.create(name: "Max Mustermann", email: "editor@mampf.edu",
- password: "test123456", consents: true,
- locale: I18n.default_locale).confirm
diff --git a/spec/cypress/app_commands/scenarios/non_admin.rb b/spec/cypress/app_commands/scenarios/non_admin.rb
deleted file mode 100644
index 9d76635d4..000000000
--- a/spec/cypress/app_commands/scenarios/non_admin.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-User.create(name: "Max Mustermann", email: "max@mampf.edu",
- password: "test123456", consents: true,
- locale: I18n.default_locale).confirm
diff --git a/spec/cypress/app_commands/scenarios/teacher.rb b/spec/cypress/app_commands/scenarios/teacher.rb
deleted file mode 100644
index d9eb4fd9f..000000000
--- a/spec/cypress/app_commands/scenarios/teacher.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-User.create(name: "Max Mustermann", email: "teacher@mampf.edu",
- password: "test123456", consents: true,
- locale: I18n.default_locale).confirm
diff --git a/spec/cypress/cypress_helper.rb b/spec/cypress/cypress_helper.rb
deleted file mode 100644
index 6e5fc804e..000000000
--- a/spec/cypress/cypress_helper.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# This is loaded once before the first command is executed
-
-begin
- require "database_cleaner"
-rescue LoadError => e
- puts e.message
-end
-
-begin
- require "factory_bot_rails"
-rescue LoadError => e
- puts e.message
- begin
- require "factory_girl_rails"
- rescue LoadError => e
- puts e.message
- end
-end
-
-require "cypress_on_rails/smart_factory_wrapper"
-
-factory = CypressOnRails::SimpleRailsFactory
-factory = FactoryBot if defined?(FactoryBot)
-factory = FactoryGirl if defined?(FactoryGirl)
-
-CypressOnRails::SmartFactoryWrapper.configure(
- always_reload: !Rails.configuration.cache_classes,
- factory: factory,
- files: [
- Rails.root.join("spec/factories/**/*.rb")
- ]
-)
diff --git a/spec/cypress/e2e/admin_spec.cy.js b/spec/cypress/e2e/admin_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/admin_spec.cy.js
rename to spec/cypress/e2e/admin_spec.cy.archive.js
diff --git a/spec/cypress/e2e/courses_spec.cy.js b/spec/cypress/e2e/courses_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/courses_spec.cy.js
rename to spec/cypress/e2e/courses_spec.cy.archive.js
diff --git a/spec/cypress/e2e/media_spec.cy.js b/spec/cypress/e2e/media_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/media_spec.cy.js
rename to spec/cypress/e2e/media_spec.cy.archive.js
diff --git a/spec/cypress/e2e/search_spec.cy.js b/spec/cypress/e2e/search_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/search_spec.cy.js
rename to spec/cypress/e2e/search_spec.cy.archive.js
diff --git a/spec/cypress/e2e/submissions_spec.cy.archive.js b/spec/cypress/e2e/submissions_spec.cy.archive.js
new file mode 100644
index 000000000..adcd0b5f6
--- /dev/null
+++ b/spec/cypress/e2e/submissions_spec.cy.archive.js
@@ -0,0 +1,153 @@
+describe("Submissions", () => {
+ beforeEach(() => {
+ cy.app("clean");
+ });
+ describe("Administration", () => {
+ beforeEach(() => {
+ cy.app("clean");
+ cy.appScenario("admin");
+ cy.visit("/users/sign_in");
+ cy.get('input[type="email"]').type("administrator@mampf.edu");
+ cy.get('input[type="password"]').type("test123456");
+ cy.get('input[type="submit"]').click();
+ });
+ it("can create tutorial", () => {
+ cy.appFactories([
+ ["create",
+ "lecture", {
+ teacher_id: 1,
+ },
+ ],
+ ["create", "user", "auto_confirmed"],
+ ]).then((lectures) => {
+ cy.visit(`lectures/${lectures[0].id}/edit`);
+ cy.contains("Tutorien").should("exist");
+ cy.contains("Tutorien").click();
+ cy.contains("Neues Tutorium anlegen").click();
+ cy.get('input[name="tutorial[title]"]').type("Tutorium A");
+ cy.get("#tutorial_tutor_ids_-ts-control").type(lectures[1].name);
+ cy.contains(lectures[1].name).click();
+ cy.get("#exercises_collapse").contains("Speichern").click();
+ });
+ });
+ it("can create assignment", () => {
+ cy.appFactories([
+ ["create",
+ "lecture", {
+ teacher_id: 1,
+ },
+ ],
+ [
+ "create", "tutorial", {
+ lecture_id: 1,
+ },
+ ],
+ ]).then((tutorials) => {
+ console.log(tutorials[1]);
+ cy.visit(`/lectures/${tutorials[1].lecture_id}/edit`);
+ cy.contains("Hausaufgaben").should("exist");
+ cy.contains("Hausaufgaben").click();
+ cy.contains("Neue Hausaufgabe anlegen").click();
+ cy.get('input[name="assignment[title]"]').type("Assignment A");
+ cy.get('input[name="assignment[deadline]"]').type((new Date()).toLocaleTimeString("de"));
+ cy.get("#assignments_collapse").contains("Speichern").click();
+ cy.contains("Assignment A").should("exist");
+ });
+ });
+ });
+ describe("User", () => {
+ beforeEach(() => {
+ cy.app("clean");
+ cy.appScenario("non_admin");
+ cy.visit("/users/sign_in");
+ cy.get('input[type="email"]').type("max@mampf.edu");
+ cy.get('input[type="password"]').type("test123456");
+ cy.get('input[type="submit"]').click();
+
+ cy.appFactories([
+ ["create", "lecture", "released_for_all"],
+ ["create", "lecture_user_join", {
+ user_id: 1,
+ lecture_id: 1,
+ }],
+ ]).then((_lectures) => {});
+ });
+ it("can create submission", () => {
+ cy.appFactories([
+ [
+ "create",
+ "tutorial", "with_tutors", {
+ lecture_id: 1,
+ },
+ ],
+ [
+ "create", "assignment", {
+ lecture_id: 1,
+ },
+ ],
+ ]).then((assignments) => {
+ cy.visit(`lectures/${assignments[0].lecture_id}/submissions`);
+ cy.contains("Anlegen").click();
+ const yourFixturePath = "cypress/fixtures/files/manuscript.pdf";
+ cy.get("#upload-userManuscript").selectFile(yourFixturePath, { force: true });
+ cy.get('input[type="checkbox"]').check();
+ cy.contains("Hochladen").click();
+ cy.get(".submissionFooter").contains("Speichern").click();
+ cy.contains("Du").should("exist");
+ });
+ });
+ it("can process multiple files", () => {
+ cy.appFactories([
+ [
+ "create",
+ "tutorial", "with_tutors", {
+ lecture_id: 1,
+ },
+ ],
+ [
+ "create", "assignment", {
+ lecture_id: 1,
+ },
+ ],
+ ]).then((assignments) => {
+ cy.visit(`lectures/${assignments[0].lecture_id}/submissions`);
+ cy.contains("Anlegen").click();
+ const yourFixturePath = "cypress/fixtures/files/manuscript.pdf";
+ cy.get("#upload-userManuscript").selectFile([yourFixturePath, yourFixturePath, yourFixturePath], { force: true });
+ cy.get("#userManuscript-merge-btn").should("exist");
+ cy.get("#userManuscript-merge-btn").click();
+ cy.get("#multiple-files-selected").should("have.attr", "style", "display: none;");
+ cy.get('input[type="checkbox"]').check();
+ cy.get("#userManuscript-uploadButton-call").click();
+ cy.get("#userManuscript-uploadButton-call").contains("Erfolgreich hochgeladen");
+ });
+ });
+ it("can join submission", () => {
+ cy.appFactories([
+ [
+ "create",
+ "tutorial", "with_tutors", {
+ lecture_id: 1,
+ },
+ ],
+ [
+ "create", "assignment", {
+ lecture_id: 1,
+ },
+ ],
+ ["create", "submission", "with_users", "with_manuscript", {
+ assignment_id: 1,
+ tutorial_id: 1,
+ }],
+ ]).then((assignments) => {
+ cy.visit(`lectures/${assignments[0].lecture_id}/submissions`);
+ cy.contains("Beitreten").click();
+ cy.contains("Code").should("exist");
+ console.log(assignments[2]);
+ cy.get('input[name="join[code]"]').type(assignments[2].token);
+ cy.contains("Beitreten").click();
+ cy.contains("Du").should("exist");
+ });
+ });
+ });
+});
diff --git a/spec/cypress/e2e/submissions_spec.cy.js b/spec/cypress/e2e/submissions_spec.cy.js
index adcd0b5f6..5cc454703 100644
--- a/spec/cypress/e2e/submissions_spec.cy.js
+++ b/spec/cypress/e2e/submissions_spec.cy.js
@@ -1,152 +1,26 @@
+import FactoryBot from "../support/factorybot";
+
describe("Submissions", () => {
- beforeEach(() => {
- cy.app("clean");
- });
- describe("Administration", () => {
- beforeEach(() => {
- cy.app("clean");
- cy.appScenario("admin");
- cy.visit("/users/sign_in");
- cy.get('input[type="email"]').type("administrator@mampf.edu");
- cy.get('input[type="password"]').type("test123456");
- cy.get('input[type="submit"]').click();
- });
- it("can create tutorial", () => {
- cy.appFactories([
- ["create",
- "lecture", {
- teacher_id: 1,
- },
- ],
- ["create", "user", "auto_confirmed"],
- ]).then((lectures) => {
- cy.visit(`lectures/${lectures[0].id}/edit`);
- cy.contains("Tutorien").should("exist");
- cy.contains("Tutorien").click();
- cy.contains("Neues Tutorium anlegen").click();
- cy.get('input[name="tutorial[title]"]').type("Tutorium A");
- cy.get("#tutorial_tutor_ids_-ts-control").type(lectures[1].name);
- cy.contains(lectures[1].name).click();
- cy.get("#exercises_collapse").contains("Speichern").click();
- });
- });
- it("can create assignment", () => {
- cy.appFactories([
- ["create",
- "lecture", {
- teacher_id: 1,
- },
- ],
- [
- "create", "tutorial", {
- lecture_id: 1,
- },
- ],
- ]).then((tutorials) => {
- console.log(tutorials[1]);
- cy.visit(`/lectures/${tutorials[1].lecture_id}/edit`);
- cy.contains("Hausaufgaben").should("exist");
- cy.contains("Hausaufgaben").click();
- cy.contains("Neue Hausaufgabe anlegen").click();
- cy.get('input[name="assignment[title]"]').type("Assignment A");
- cy.get('input[name="assignment[deadline]"]').type((new Date()).toLocaleTimeString("de"));
- cy.get("#assignments_collapse").contains("Speichern").click();
- cy.contains("Assignment A").should("exist");
- });
- });
- });
describe("User", () => {
beforeEach(() => {
- cy.app("clean");
- cy.appScenario("non_admin");
- cy.visit("/users/sign_in");
- cy.get('input[type="email"]').type("max@mampf.edu");
- cy.get('input[type="password"]').type("test123456");
- cy.get('input[type="submit"]').click();
-
- cy.appFactories([
- ["create", "lecture", "released_for_all"],
- ["create", "lecture_user_join", {
- user_id: 1,
- lecture_id: 1,
- }],
- ]).then((_lectures) => {});
- });
- it("can create submission", () => {
- cy.appFactories([
- [
- "create",
- "tutorial", "with_tutors", {
- lecture_id: 1,
- },
- ],
- [
- "create", "assignment", {
- lecture_id: 1,
- },
- ],
- ]).then((assignments) => {
- cy.visit(`lectures/${assignments[0].lecture_id}/submissions`);
- cy.contains("Anlegen").click();
- const yourFixturePath = "cypress/fixtures/files/manuscript.pdf";
- cy.get("#upload-userManuscript").selectFile(yourFixturePath, { force: true });
- cy.get('input[type="checkbox"]').check();
- cy.contains("Hochladen").click();
- cy.get(".submissionFooter").contains("Speichern").click();
- cy.contains("Du").should("exist");
- });
+ cy.createUserAndLogin("generic");
+ FactoryBot.create("lecture", "released_for_all");
});
- it("can process multiple files", () => {
- cy.appFactories([
- [
- "create",
- "tutorial", "with_tutors", {
- lecture_id: 1,
- },
- ],
- [
- "create", "assignment", {
- lecture_id: 1,
- },
- ],
- ]).then((assignments) => {
- cy.visit(`lectures/${assignments[0].lecture_id}/submissions`);
- cy.contains("Anlegen").click();
- const yourFixturePath = "cypress/fixtures/files/manuscript.pdf";
- cy.get("#upload-userManuscript").selectFile([yourFixturePath, yourFixturePath, yourFixturePath], { force: true });
- cy.get("#userManuscript-merge-btn").should("exist");
- cy.get("#userManuscript-merge-btn").click();
- cy.get("#multiple-files-selected").should("have.attr", "style", "display: none;");
- cy.get('input[type="checkbox"]').check();
- cy.get("#userManuscript-uploadButton-call").click();
- cy.get("#userManuscript-uploadButton-call").contains("Erfolgreich hochgeladen");
+
+ // TODO: this is just a dummy test right now
+ it("can create a submission", function () {
+ FactoryBot.create("tutorial", "with_tutors", { lecture_id: 1 }).as("tutorial");
+ FactoryBot.create("assignment", { lecture_id: 1 }).as("assignment");
+ cy.createUser("admin").as("user");
+
+ cy.then(() => {
+ console.log(this.tutorial);
+ console.log(this.assignment);
+ console.log(this.user);
});
- });
- it("can join submission", () => {
- cy.appFactories([
- [
- "create",
- "tutorial", "with_tutors", {
- lecture_id: 1,
- },
- ],
- [
- "create", "assignment", {
- lecture_id: 1,
- },
- ],
- ["create", "submission", "with_users", "with_manuscript", {
- assignment_id: 1,
- tutorial_id: 1,
- }],
- ]).then((assignments) => {
- cy.visit(`lectures/${assignments[0].lecture_id}/submissions`);
- cy.contains("Beitreten").click();
- cy.contains("Code").should("exist");
- console.log(assignments[2]);
- cy.get('input[name="join[code]"]').type(assignments[2].token);
- cy.contains("Beitreten").click();
- cy.contains("Du").should("exist");
+
+ cy.then(() => {
+ cy.visit("/lectures/1/");
});
});
});
diff --git a/spec/cypress/e2e/thredded_spec.cy.js b/spec/cypress/e2e/thredded_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/thredded_spec.cy.js
rename to spec/cypress/e2e/thredded_spec.cy.archive.js
diff --git a/spec/cypress/e2e/tutorials_spec.cy.js b/spec/cypress/e2e/tutorials_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/tutorials_spec.cy.js
rename to spec/cypress/e2e/tutorials_spec.cy.archive.js
diff --git a/spec/cypress/e2e/watchlists_spec.cy.js b/spec/cypress/e2e/watchlists_spec.cy.archive.js
similarity index 100%
rename from spec/cypress/e2e/watchlists_spec.cy.js
rename to spec/cypress/e2e/watchlists_spec.cy.archive.js
diff --git a/spec/cypress/fixtures/example.json b/spec/cypress/fixtures/example.json
deleted file mode 100644
index da18d9352..000000000
--- a/spec/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"
-}
\ No newline at end of file
diff --git a/spec/cypress/plugins/index.js b/spec/cypress/plugins/index.js
deleted file mode 100644
index 3596c1897..000000000
--- a/spec/cypress/plugins/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-///
+ <%= truncate(annotation[:text], length: 100) %>
+
+
+ <%= t('time.last_updated',
+ time_ago: time_ago_in_words(annotation[:updated_at])) %>
+
+
+ <%= t('admin.annotation.none_yet_students') %> +
++ <%= t('admin.annotation.overview_description_students_annotations') %> +
+ + <%= render 'annotations/index_accordion', + annotations_by_lecture: @student_annotations_by_lecture, + is_students_annotations: true %> + + <% end %> + ++ <%= t('admin.annotation.none_yet_html') %> +
++ <%= t('admin.annotation.overview_description') %> +
+ + <%= render 'annotations/index_accordion', + annotations_by_lecture: @annotations_by_lecture, + is_students_annotations: false %> + + <% end %> + + ++ <%= t('mailer.deletion_body_html') %> +
++ <%= t('mailer.pending_deletion_body_html', + num_days_until_deletion: @num_days_until_deletion) %> +
+