Align project files with CodeHarbor

Since both projects are developed together and by the same team, we also want to have the same code structure and utility methods available in both projects. Therefore, this commit changes many files, but without a functional change.
This commit is contained in:
Sebastian Serth
2023-10-10 23:25:02 +02:00
parent fb3e8972d9
commit 99bd46af1a
112 changed files with 433 additions and 320 deletions

View File

@ -1,6 +1,7 @@
name: CI
on:
- push
jobs:
test:
runs-on: ubuntu-latest

51
.gitignore vendored
View File

@ -1,27 +1,52 @@
# Ignore application configuration
/config/action_mailer.yml
/config/code_ocean.yml
/config/content_security_policy.yml
/config/database.yml
/config/docker.yml.erb
/config/mnemosyne.yml
/config/secrets.yml
/config/docker.yml.erb
/config/content_security_policy.yml
/config/settings.local.yml
/config/settings/*.local.yml
/config/environments/*.local.yml
# Ignore temporary files
/coverage
/log/*.*
/public/assets
/public/uploads
/log
/rubocop.html
/tmp
/vagrant/
/.capistrano
/.vagrant
*.sublime-*
/.idea
/.vagrant
*.iml
*.DS_Store
## Ignore editor-specific artifacts
# Vagrant
/.vagrant
/vagrant
# Sublime
*.sublime-*
# IntelliJ
/.idea
*.iml
## Environment normalisation:
/.bundle
/vendor/bundle
# Ignore Byebug command history file.
.byebug_history
# Ignore node_modules
node_modules/
# Ignore precompiled javascript packs
/public/packs
/public/packs-test
/node_modules
/public/assets
# Ignore yarn files
/yarn-error.log
yarn-debug.log*
.yarn-integrity
# Ignore uploaded files in development
/storage
/public/uploads

View File

@ -15,6 +15,7 @@ RSpec/DescribeClass:
Enabled: false
Exclude:
- "spec/views/**/*_spec.rb"
- "spec/custom_matchers/*"
RSpec/ExampleLength:
Enabled: false

View File

@ -3,6 +3,7 @@
source 'https://rubygems.org'
gem 'bcrypt'
gem 'bootsnap', require: false
gem 'bootstrap-will_paginate'
gem 'carrierwave'
gem 'charlock_holmes', require: 'charlock_holmes/string'
@ -66,7 +67,6 @@ end
group :development, :staging do
gem 'better_errors'
gem 'binding_of_caller'
gem 'bootsnap', require: false
gem 'letter_opener'
gem 'listen'
gem 'pry-byebug'

View File

@ -1,5 +1,4 @@
CodeOcean
==========
# CodeOcean
[![Build Status](https://github.com/openHPI/codeocean/workflows/CI/badge.svg)](https://github.com/openHPI/codeocean/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/openHPI/codeocean/branch/master/graph/badge.svg?token=imei686C2r)](https://codecov.io/gh/openHPI/codeocean)
@ -39,14 +38,12 @@ In order to execute code submissions using the [DockerContainerPool](https://git
- is always writeable by the user executing the web server (in this case the `codeocean` user): `setfacl -Rdm user:codeocean:rwx /var/www/app/current/tmp/files`.
### Optional Steps
- Use Docker Machine or vagrant if there is no native support for docker on your OS
- If you want to use the app without docker (and hence without code execution) comment the validation `validate :working_docker_image?` in `models/execution_environments.rb` otherwise the seed will fail (because of missing docker connection)
- Create seed data by executing `rake db:seed`
- Use Docker Machine or Vagrant if there is no native support for Docker on your OS
- If you want to use the app without Docker or a Runner management (and hence without code execution), comment the validation `validate :working_docker_image?` in `models/execution_environments.rb`. Otherwise the seed will fail.
- Create seed data by executing `rails db:seed`
- If you already created a configuration for your local installation and want to use vagrant, too, be sure to log into the vagrant instance via ssh and add your database user manually to the database. Afterwards, create, migrate and seed.
## Production Setup
- We recommend using [Capistrano](https://capistranorb.com/) for deployment.
- Once deployed, CodeOcean assumes to run exclusively under a (sub)domain. If you want to use it under a custom subpath, you can specify the desired path using an environment variable: `RAILS_RELATIVE_URL_ROOT=/codeocean`. Please ensure to rebuild all assets and restart the server to apply the new path.
- When using [PgBouncer](https://www.pgbouncer.org), please make sure to correctly set the `intervalstyle` to `iso_8601` for the database. Otherwise, the application will not be able to parse timestamps correctly. See [a similar issue here](https://gitlab.com/gitlab-org/gitlab/-/issues/349912) and [our migration](./db/migrate/20221206221333_set_database_interval_style.rb) for more details.
@ -57,7 +54,6 @@ In order to execute code submissions using the [DockerContainerPool](https://git
- The Prometheus Exporter must be started separately **before** running the Rails server via `bundle exec prometheus_exporter`
- The InfluxDB data can be visualized using Grafana, for example. There is also an adapted [dashboard](docs/grafana/prometheus_exporter_grafana_dashboard.json) for this purpose
## Additional Note
- If you want to change the default port of the underlying rails server, you can use [authbind](https://www.mwells.org/coding/2016/authbind-port-80-443/) to bind it to the regular 80/443 port.

View File

@ -2,12 +2,12 @@
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require turbolinks

View File

@ -17,4 +17,4 @@
*
* app/assets
*= require_tree .
*/
*/

View File

@ -33,6 +33,31 @@ class ApplicationController < ActionController::Base
end
helper_method :current_contributor
def welcome
# Show root page
redirect_to ping_index_path if MONITORING_USER_AGENT.match?(request.user_agent)
end
private
def require_user!
raise Pundit::NotAuthorizedError unless current_user
end
def deny_access_from_render_host
raise Pundit::NotAuthorizedError if RENDER_HOST.present? && request.host == RENDER_HOST
end
def load_embed_options
@embed_options = if session[:embed_options].present? && session[:embed_options].is_a?(Hash)
session[:embed_options].symbolize_keys
else
{}
end
Sentry.set_extras(@embed_options)
@embed_options
end
def find_or_login_current_user
login_from_authentication_token ||
login_from_lti_session ||
@ -40,21 +65,6 @@ class ApplicationController < ActionController::Base
login_from_other_sources ||
nil
end
private :find_or_login_current_user
def require_user!
raise Pundit::NotAuthorizedError unless current_user
end
def mnemosyne_trace
yield
ensure
if ::Mnemosyne::Instrumenter.current_trace.present?
::Mnemosyne::Instrumenter.current_trace.meta['session_id'] = session[:session_id]
::Mnemosyne::Instrumenter.current_trace.meta['csrf_token'] = session[:_csrf_token]
::Mnemosyne::Instrumenter.current_trace.meta['external_user_id'] = session[:external_user_id]
end
end
def login_from_lti_session
return unless session[:external_user_id]
@ -81,12 +91,6 @@ class ApplicationController < ActionController::Base
end
end
def set_document_policy
# Instruct browsers to capture profiling data
response.set_header('Document-Policy', 'js-profiling')
end
private :set_document_policy
def set_sentry_context
return if current_user.blank?
@ -96,17 +100,19 @@ class ApplicationController < ActionController::Base
consumer: current_user.consumer&.name
)
end
private :set_sentry_context
def set_document_policy
# Instruct browsers to capture profiling data
response.set_header('Document-Policy', 'js-profiling')
end
def render_csrf_error
render_error t('sessions.expired'), :unprocessable_entity
end
private :render_csrf_error
def render_not_authorized
render_error t('application.not_authorized'), :unauthorized
end
private :render_not_authorized
def render_not_found
if current_user&.admin?
@ -115,7 +121,6 @@ class ApplicationController < ActionController::Base
render_not_authorized
end
end
private :render_not_authorized
def render_error(message, status)
set_sentry_context
@ -134,7 +139,16 @@ class ApplicationController < ActionController::Base
format.json { render json: {error: message}, status: }
end
end
private :render_error
def mnemosyne_trace
yield
ensure
if ::Mnemosyne::Instrumenter.current_trace.present?
::Mnemosyne::Instrumenter.current_trace.meta['session_id'] = session[:session_id]
::Mnemosyne::Instrumenter.current_trace.meta['csrf_token'] = session[:_csrf_token]
::Mnemosyne::Instrumenter.current_trace.meta['external_user_id'] = session[:external_user_id]
end
end
def switch_locale(&)
session[:locale] = sanitize_locale(params[:custom_locale] || params[:locale] || session[:locale])
@ -142,27 +156,6 @@ class ApplicationController < ActionController::Base
Sentry.set_extras(locale:)
I18n.with_locale(locale, &)
end
private :switch_locale
def deny_access_from_render_host
raise Pundit::NotAuthorizedError if RENDER_HOST.present? && request.host == RENDER_HOST
end
def welcome
# Show root page
redirect_to ping_index_path if MONITORING_USER_AGENT.match?(request.user_agent)
end
def load_embed_options
@embed_options = if session[:embed_options].present? && session[:embed_options].is_a?(Hash)
session[:embed_options].symbolize_keys
else
{}
end
Sentry.set_extras(@embed_options)
@embed_options
end
private :load_embed_options
# Sanitize given locale.
#
@ -176,5 +169,4 @@ class ApplicationController < ActionController::Base
locale
end
private :sanitize_locale
end

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
module ProformaXML
class ExerciseNotOwned < StandardError; end
class ExerciseNotOwned < ApplicationError; end
end

View File

@ -50,7 +50,7 @@ module ApplicationHelper
end
def render_markdown(markdown)
ActionController::Base.helpers.sanitize Kramdown::Document.new(markdown).to_html
ActionController::Base.helpers.sanitize Kramdown::Document.new(markdown).to_html.strip
end
def row(options = {}, &)

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
module ErrorTemplateAttributesHelper
end

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
module ErrorTemplatesHelper
end

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
# stolen from https://github.com/rails/rails/issues/25894#issuecomment-777516944
# this serializer can be used by a model to make sure the hash from a jsonb field can be accessed with symbols instead of string-keys.
class HashAsJsonbSerializer
def self.dump(hash)
hash
end
def self.load(hash)
hash.is_a?(Hash) ? hash.deep_symbolize_keys : {}
end
end

View File

@ -1,7 +1,7 @@
#flash-container.container
#flash.container.fixed_error_messages data-message-failure=t('shared.message_failure') data-websocket-failure=t('shared.websocket_failure')
- %w[alert danger info notice success warning].each do |severity|
- flash_mapping = {'alert' => 'warning', 'notice' => 'success'}
- ApplicationController._flash_types.each do |severity|
- flash_mapping = {alert: :warning, notice: :success}
div.alert.flash class="alert-#{flash_mapping.fetch(severity, severity)} alert-dismissible fade show"
p.mb-0 id="flash-#{severity}" == flash[severity]
button.btn-close type="button" data-bs-dismiss="alert" aria-label="Close"

View File

@ -9,10 +9,10 @@ html lang="#{I18n.locale || I18n.default_locale}" data-default-locale="#{I18n.de
= favicon_link_tag('/favicon.png', type: 'image/png')
= favicon_link_tag('/favicon.png', rel: 'apple-touch-icon', type: 'image/png')
= action_cable_meta_tag
= stylesheet_pack_tag('application', 'stylesheets', media: 'all', 'data-turbolinks-track': true, integrity: true, crossorigin: 'anonymous')
= stylesheet_link_tag('application', media: 'all', 'data-turbolinks-track': true, integrity: true, crossorigin: 'anonymous')
= javascript_pack_tag('application', 'data-turbolinks-track': true, defer: false, integrity: true, crossorigin: 'anonymous')
= javascript_include_tag('application', 'data-turbolinks-track': true, integrity: true, crossorigin: 'anonymous')
= stylesheet_pack_tag('application', 'stylesheets', media: 'all', 'data-turbolinks-track': 'reload', integrity: true, crossorigin: 'anonymous')
= stylesheet_link_tag('application', media: 'all', 'data-turbolinks-track': 'reload', integrity: true, crossorigin: 'anonymous')
= javascript_pack_tag('application', 'data-turbolinks-track': 'reload', defer: false, integrity: true, crossorigin: 'anonymous')
= javascript_include_tag('application', 'data-turbolinks-track': 'reload', integrity: true, crossorigin: 'anonymous')
= yield(:head)
= csrf_meta_tags
meta name='sentry' data-enabled=SentryJavascript.active?.to_s data-release=SentryJavascript.release data-dsn=SentryJavascript.dsn data-environment=SentryJavascript.environment
@ -25,7 +25,7 @@ html lang="#{I18n.locale || I18n.default_locale}" data-default-locale="#{I18n.de
.navbar-brand
i.fa-solid.fa-code
= application_name
button.navbar-toggler data-bs-target='#navbar-collapse' data-bs-toggle='collapse' type='button' aria-expanded='false' aria-label='Toggle navigation'
button.navbar-toggler data-bs-target='#navbar-collapse' data-bs-toggle='collapse' type='button' aria-expanded='false' aria-label='Toggle navigation' aria-controls='navbar-collapse'
span.navbar-toggler-icon
#navbar-collapse.collapse.navbar-collapse
= render('navigation', cached: true)

View File

@ -45,6 +45,9 @@ module CodeOcean
config.action_cable.mount_path = "#{ENV.fetch('RAILS_RELATIVE_URL_ROOT', '')}/cable"
# Disable concurrent ActionCable workers to ensure ACE change events keep their order
config.action_cable.worker_pool_size = 1
config.telegraf.tags = {application: 'codeocean'}
config.after_initialize do
@ -55,13 +58,15 @@ module CodeOcean
Runner.strategy_class.initialize_environment
end
# Specify default options for Rails generators
config.generators do |g|
g.orm :active_record, primary_key_type: :uuid
end
# Allow tables in addition to existing default tags
config.action_view.sanitized_allowed_tags = ActionView::Base.sanitized_allowed_tags + %w[table thead tbody tfoot td tr]
# Extract Sentry-related parameters from WebSocket connection
config.middleware.insert_before 0, Middleware::WebSocketSentryHeaders
# Disable concurrent ActionCable workers to ensure ACE change events keep their order
config.action_cable.worker_pool_size = 1
end
end

View File

@ -13,6 +13,9 @@ production:
<<: *default
database: codeocean_production
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: codeocean_test

View File

@ -5,6 +5,7 @@ require 'active_support/core_ext/integer/time'
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Allowed IPs for the Vagrant setup
config.web_console.allowed_ips = '192.168.0.0/16'
# In the development environment your application's code is reloaded any time
@ -43,10 +44,6 @@ Rails.application.configure do
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Perform deliveries via letter opener
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.perform_caching = false
# Print deprecation notices to the Rails logger.

View File

@ -22,6 +22,7 @@ Rails.application.configure do
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
config.read_encrypted_secrets = true
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
@ -67,7 +68,7 @@ Rails.application.configure do
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "code_ocean_production"
# config.active_job.queue_name_prefix = "codeocean_production"
config.action_mailer.perform_caching = false

View File

@ -59,8 +59,8 @@ Rails.application.configure do
config.active_support.disallowed_deprecation_warnings = []
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true
config.i18n.raise_on_missing_translations = true
# Annotate rendered view with file names.
# config.action_view.annotate_rendered_view_with_filenames = true
config.action_view.annotate_rendered_view_with_filenames = true
end

View File

@ -1,4 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# ActiveSupport::Reloader.to_prepare do

View File

@ -1,4 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:

View File

@ -8,14 +8,13 @@ RailsAdmin.config do |config|
# config.authenticate_with do
# warden.authenticate! scope: :user
# end
# config.current_user_method(&:current_user)
config.current_user_method(&:current_user)
## == CancanCan ==
# config.authorize_with :cancancan
## == Pundit ==
# config.authorize_with :pundit
config.parent_controller = '::RailsAdminController'
config.authorize_with do
# Important! We need to check the authorization here, we skip Pundit checks in the RailsAdminController.
@ -30,6 +29,9 @@ RailsAdmin.config do |config|
### More at https://github.com/sferik/rails_admin/wiki/Base-configuration
config.parent_controller = '::RailsAdminController'
config.excluded_models = %w[Generators::TestingFrameworkAdapterGenerator]
## == Gravatar integration ==
## To disable Gravatar integration in Navigation Bar set to false
# config.show_gravatar = true
@ -51,8 +53,6 @@ RailsAdmin.config do |config|
end
end
config.excluded_models = %w[Generators::TestingFrameworkAdapterGenerator]
config.actions do
# mandatory
dashboard do

View File

@ -7,16 +7,16 @@ default: &default
# Alternatively, you can use '/' to use the whole source_path directory.
source_entry_path: /
# If nested_entries is true, then we'll pick up subdirectories within the source_entry_path.
# You cannot set this option to true if you set source_entry_path to '/'
nested_entries: false
# While using a File-System-based automated bundle generation feature, miscellaneous warnings suggesting css order
# conflicts may arise due to the mini-css-extract-plugin. For projects where css ordering has been mitigated through
# consistent use of scoping or naming conventions, the css order warnings can be disabled by setting
# css_extract_ignore_order_warnings to true
css_extract_ignore_order_warnings: false
# If nested_entries is true, then we'll pick up subdirectories within the source_entry_path.
# You cannot set this option to true if you set source_entry_path to '/'
nested_entries: false
public_root_path: public
public_output_path: packs
cache_path: tmp/shakapacker
@ -38,7 +38,7 @@ default: &default
webpack_loader: 'babel'
# Set to true to enable check for matching versions of shakapacker gem and NPM package - will raise an error if there is a mismatch or wildcard versioning is used
ensure_consistent_versioning: true
ensure_consistent_versioning: false
# Select whether the compiler will use SHA digest ('digest' option) or most most recent modified timestamp ('mtime') to determine freshness
compiler_strategy: digest
@ -60,10 +60,10 @@ development:
# If HMR is on, CSS will by inlined by delivering it as part of the script payload via style-loader. Be sure
# that you add style-loader to your project dependencies.
#
# If you want to instead deliver CSS via <link> with the mini-extract-css-plugin, set inline_css to false.
# If you want to instead deliver CSS via <link> with the mini-css-extract-plugin, set inline_css to false.
# In that case, style-loader is not needed as a dependency.
#
# mini-extract-css-plugin is a required dependency in both cases.
# mini-css-extract-plugin is a required dependency in both cases.
inline_css: true
# Defaults to the inverse of hmr. Uncomment to manually set this.
# live_reload: true

View File

@ -20,7 +20,7 @@ const public_output_path = webpackConfig.output.publicPath;
const envConfig = module.exports = {
node: {
global: false,
global: false,
},
module: {
rules: [

View File

@ -1,5 +1,13 @@
# frozen_string_literal: true
# Meta seed file that required depending on the Rails env different files from
# db/seeds/ Please put the seed in the best matching file
#
# * all: Objects are needed in every environment (production, development)
# * production: Objects are only needed for deployment
# * development: Only needed for local development
#
def find_factories_by_class(klass)
FactoryBot.factories.select do |factory|
factory.instance_variable_get(:@class_name).to_s == klass.to_s || factory.instance_variable_get(:@name) == klass.model_name.singular.to_sym
@ -22,12 +30,15 @@ end
Rails.application.eager_load!
(ApplicationRecord.descendants - [ActiveRecord::SchemaMigration, User]).each(&:delete_all)
# Set the default intervalstyle to iso_8601
dbname = ApplicationRecord.connection.current_database
ApplicationRecord.connection.exec_query("ALTER DATABASE \"#{dbname}\" SET intervalstyle = 'iso_8601';")
# delete file uploads
FileUtils.rm_rf(Rails.public_path.join('uploads'))
# load environment-dependent seeds
load(Rails.root.join("db/seeds/#{Rails.env}.rb"))
['all', Rails.env].each do |seed|
seed_file = Rails.root.join("db/seeds/#{seed}.rb")
if seed_file.exist?
puts "*** Loading \"#{seed}\" seed data" # rubocop:disable Rails/Output
load seed_file
else
puts "*** Skipping \"#{seed}\" seed data: \"#{seed_file}\" not found" # rubocop:disable Rails/Output
end
end

View File

@ -1,12 +0,0 @@
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
]
}

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Momentan nehmen wir Wartungs- und Optimierungsarbeiten vor. Probieren Sie es in Kürze noch einmal.</title>
<title>We're sorry, but something went wrong (500)</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {

View File

@ -6,7 +6,7 @@ class Controller < AnonymousController
include FileParameters
end
describe FileParameters do
RSpec.describe FileParameters do
let(:controller) { Controller.new }
let(:hello_world) { create(:hello_world) }

View File

@ -6,7 +6,7 @@ class Controller < AnonymousController
include Lti
end
describe Lti do
RSpec.describe Lti do
let(:controller) { Controller.new }
let(:session) { double }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Admin::DashboardController do
RSpec.describe Admin::DashboardController do
render_views
let(:codeocean_config) { instance_double(CodeOcean::Config) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ApplicationController do
RSpec.describe ApplicationController do
render_views
describe '#current_user' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeOcean::FilesController do
RSpec.describe CodeOcean::FilesController do
render_views
let(:contributor) { create(:admin) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeharborLinksController do
RSpec.describe CodeharborLinksController do
render_views
let(:user) { create(:teacher) }
@ -44,14 +44,13 @@ describe CodeharborLinksController do
context 'with invalid params' do
let(:params) { {push_url: '', check_uuid_url: '', api_key: ''} }
before { post_request }
it 'does not create a codeharbor_link' do
expect { post_request }.not_to change(CodeharborLink, :count)
end
it 'redirects to user show' do
post_request
expect(response).to render_template(:new)
end
expect_template(:new)
end
end
@ -79,14 +78,13 @@ describe CodeharborLinksController do
context 'with invalid params' do
let(:params) { {push_url: '', check_uuid_url: '', api_key: ''} }
before { put_request }
it 'does not change codeharbor_link' do
expect { put_request }.not_to(change { codeharbor_link.reload.attributes })
end
it 'redirects to user show' do
put_request
expect(response).to render_template(:edit)
end
expect_template(:edit)
end
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CommentsController do
RSpec.describe CommentsController do
render_views
let(:user) { create(:learner) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ConsumersController do
RSpec.describe ConsumersController do
render_views
let(:consumer) { create(:consumer) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ErrorTemplateAttributesController do
RSpec.describe ErrorTemplateAttributesController do
render_views
let!(:error_template_attribute) { create(:error_template_attribute) }
@ -10,39 +10,67 @@ describe ErrorTemplateAttributesController do
before { allow(controller).to receive(:current_user).and_return(user) }
it 'gets index' do
get :index
expect(response).to have_http_status(:ok)
expect(assigns(:error_template_attributes)).not_to be_nil
describe 'GET #index' do
before { get :index }
expect_assigns(error_template_attributes: ErrorTemplateAttribute.all)
expect_http_status(:ok)
expect_template(:index)
end
it 'gets new' do
get :new
expect(response).to have_http_status(:ok)
describe 'GET #new' do
before { get :new }
expect_http_status(:ok)
expect_template(:new)
end
it 'creates error_template_attribute' do
expect { post :create, params: {error_template_attribute: {}} }.to change(ErrorTemplateAttribute, :count).by(1)
expect(response).to redirect_to(error_template_attribute_path(assigns(:error_template_attribute)))
describe 'POST #create' do
before { post :create, params: {error_template_attribute: {}} }
expect_assigns(error_template_attribute: ErrorTemplateAttribute)
it 'creates the error template attribute' do
expect { post :create, params: {error_template_attribute: {}} }.to change(ErrorTemplateAttribute, :count).by(1)
end
expect_redirect { error_template_attribute_path(assigns(:error_template_attribute)) }
end
it 'shows error_template_attribute' do
get :show, params: {id: error_template_attribute}
expect(response).to have_http_status(:ok)
describe 'GET #show' do
before { get :show, params: {id: error_template_attribute} }
expect_assigns(error_template_attribute: ErrorTemplateAttribute)
expect_http_status(:ok)
expect_template(:show)
end
it 'gets edit' do
get :edit, params: {id: error_template_attribute}
expect(response).to have_http_status(:ok)
describe 'GET #edit' do
before { get :edit, params: {id: error_template_attribute} }
expect_assigns(error_template_attribute: ErrorTemplateAttribute)
expect_http_status(:ok)
expect_template(:edit)
end
it 'updates error_template_attribute' do
patch :update, params: {id: error_template_attribute, error_template_attribute: attributes_for(:error_template_attribute)}
expect(response).to redirect_to(error_template_attribute_path(assigns(:error_template_attribute)))
describe 'PATCH #update' do
before { patch :update, params: {id: error_template_attribute, error_template_attribute: attributes_for(:error_template_attribute)} }
expect_assigns(error_template_attribute: ErrorTemplateAttribute)
expect_redirect { error_template_attribute }
end
it 'destroys error_template_attribute' do
expect { delete :destroy, params: {id: error_template_attribute} }.to change(ErrorTemplateAttribute, :count).by(-1)
expect(response).to redirect_to(error_template_attributes_path)
describe 'DELETE #destroy' do
before { delete :destroy, params: {id: error_template_attribute} }
expect_assigns(error_template_attribute: ErrorTemplateAttribute)
it 'destroys the error template attribute' do
error_template_attribute = create(:error_template_attribute)
expect { delete :destroy, params: {id: error_template_attribute} }.to change(ErrorTemplateAttribute, :count).by(-1)
end
expect_redirect { error_template_attribute }
end
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ErrorTemplatesController do
RSpec.describe ErrorTemplatesController do
render_views
let!(:error_template) { create(:error_template) }
@ -10,39 +10,67 @@ describe ErrorTemplatesController do
before { allow(controller).to receive(:current_user).and_return(user) }
it 'gets index' do
get :index
expect(response).to have_http_status(:ok)
expect(assigns(:error_templates)).not_to be_nil
describe 'GET #index' do
before { get :index }
expect_assigns(error_templates: ErrorTemplate.all)
expect_http_status(:ok)
expect_template(:index)
end
it 'gets new' do
get :new
expect(response).to have_http_status(:ok)
describe 'GET #new' do
before { get :new }
expect_http_status(:ok)
expect_template(:new)
end
it 'creates error_template' do
expect { post :create, params: {error_template: {execution_environment_id: error_template.execution_environment.id}} }.to change(ErrorTemplate, :count).by(1)
expect(response).to redirect_to(error_template_path(assigns(:error_template)))
describe 'POST #create' do
before { post :create, params: {error_template: {execution_environment_id: error_template.execution_environment.id}} }
expect_assigns(error_template: ErrorTemplate)
it 'creates the error template' do
expect { post :create, params: {error_template: {execution_environment_id: error_template.execution_environment.id}} }.to change(ErrorTemplate, :count).by(1)
end
expect_redirect { error_template_path(assigns(:error_template)) }
end
it 'shows error_template' do
get :show, params: {id: error_template}
expect(response).to have_http_status(:ok)
describe 'GET #show' do
before { get :show, params: {id: error_template} }
expect_assigns(error_template: ErrorTemplate)
expect_http_status(:ok)
expect_template(:show)
end
it 'gets edit' do
get :edit, params: {id: error_template}
expect(response).to have_http_status(:ok)
describe 'GET #edit' do
before { get :edit, params: {id: error_template} }
expect_assigns(error_template: ErrorTemplate)
expect_http_status(:ok)
expect_template(:edit)
end
it 'updates error_template' do
patch :update, params: {id: error_template, error_template: attributes_for(:error_template)}
expect(response).to redirect_to(error_template_path(assigns(:error_template)))
describe 'PATCH #update' do
before { patch :update, params: {id: error_template, error_template: attributes_for(:error_template)} }
expect_assigns(error_template: ErrorTemplate)
expect_redirect { error_template }
end
it 'destroys error_template' do
expect { delete :destroy, params: {id: error_template} }.to change(ErrorTemplate, :count).by(-1)
expect(response).to redirect_to(error_templates_path)
describe 'DELETE #destroy' do
before { delete :destroy, params: {id: error_template} }
expect_assigns(error_template: ErrorTemplate)
it 'destroys the error template' do
error_template = create(:error_template)
expect { delete :destroy, params: {id: error_template} }.to change(ErrorTemplate, :count).by(-1)
end
expect_redirect { error_template }
end
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe EventsController do
RSpec.describe EventsController do
render_views
let(:user) { create(:admin) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExecutionEnvironmentsController do
RSpec.describe ExecutionEnvironmentsController do
render_views
let(:execution_environment) { create(:ruby) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExercisesController do
RSpec.describe ExercisesController do
render_views
let(:exercise) { create(:dummy) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExternalUsersController do
RSpec.describe ExternalUsersController do
render_views
let(:user) { build(:admin) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe FileTypesController do
RSpec.describe FileTypesController do
render_views
let(:file_type) { create(:dot_rb) }

View File

@ -2,13 +2,14 @@
require 'rails_helper'
describe InternalUsersController do
RSpec.describe InternalUsersController do
render_views
let(:user) { create(:admin) }
let(:consumer) { create(:consumer) }
let(:user) { create(:admin, consumer:) }
describe 'GET #activate' do
let(:user) { InternalUser.create(attributes_for(:teacher)) }
let(:user) { InternalUser.create(attributes_for(:teacher).merge(consumer:)) }
before do
user.send(:setup_activation)
@ -40,7 +41,7 @@ describe InternalUsersController do
end
describe 'PUT #activate' do
let(:user) { InternalUser.create(build(:teacher).attributes) }
let(:user) { InternalUser.create(build(:teacher, consumer:).attributes) }
let(:password) { SecureRandom.hex }
before do
@ -145,8 +146,8 @@ describe InternalUsersController do
end
describe 'DELETE #destroy' do
let(:second_user) { create(:teacher) }
let(:third_user) { create(:teacher) }
let(:second_user) { create(:teacher, consumer:) }
let(:third_user) { create(:teacher, consumer:) }
before do
allow(controller).to receive(:current_user).and_return(user)

View File

@ -5,13 +5,13 @@ require 'rails_helper'
RSpec.describe PingController do
render_views
describe 'index' do
before { allow(Runner.strategy_class).to receive(:health).and_return(true) }
it 'returns the wanted page and answer with HTTP Status 200' do
describe 'GET #index' do
before do
allow(Runner.strategy_class).to receive(:health).and_return(true)
get :index
expect(response).to have_http_status :ok
end
expect_json
expect_http_status(:ok)
end
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe RequestForCommentsController do
RSpec.describe RequestForCommentsController do
render_views
let(:user) { create(:admin) }
@ -61,12 +61,10 @@ describe RequestForCommentsController do
end
describe 'GET #index' do
it 'renders the index template' do
get :index
before { get :index }
expect(response).to have_http_status :ok
expect(response).to render_template :index
end
expect_template(:index)
expect_http_status(:ok)
it 'shows only rfc`s belonging to selected study group' do
my_study_group = create(:study_group)

View File

@ -2,14 +2,14 @@
require 'rails_helper'
describe SessionsController do
RSpec.describe SessionsController do
render_views
let(:consumer) { create(:consumer) }
describe 'POST #create' do
let(:password) { attributes_for(:teacher)[:password] }
let(:user) { InternalUser.create(user_attributes.merge(password:)) }
let(:user) { InternalUser.create(user_attributes.merge(password:, consumer:)) }
let(:user_attributes) { build(:teacher).attributes }
context 'with valid credentials' do
@ -76,7 +76,7 @@ describe SessionsController do
context 'with valid launch parameters' do
let(:locale) { :de }
let(:perform_request) { post :create_through_lti, params: {custom_locale: locale, custom_token: exercise.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id} }
let(:user) { create(:external_user, consumer_id: consumer.id) }
let(:user) { create(:external_user, consumer:) }
before { allow_any_instance_of(IMS::LTI::ToolProvider).to receive(:valid_request?).and_return(true) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe StatisticsController do
RSpec.describe StatisticsController do
render_views
let(:user) { create(:admin) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe SubmissionsController do
RSpec.describe SubmissionsController do
render_views
let(:exercise) { create(:math) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'seeds' do
RSpec.describe 'seeds' do
subject(:seed) { Rake::Task['db:seed'].invoke }
before do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'Authentication' do
RSpec.describe 'Authentication' do
let(:user) { create(:admin) }
let(:password) { attributes_for(:admin)[:password] }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'Authorization' do
RSpec.describe 'Authorization' do
before { allow(Runner.strategy_class).to receive(:available_images).and_return([]) }
context 'when being an admin' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'Editor', :js do
RSpec.describe 'Editor', :js do
let(:exercise) { create(:audio_video, description: Forgery(:lorem_ipsum).sentence) }
let(:scoring_response) do
[{

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'ExternalUserStatistics', :js do
RSpec.describe 'ExternalUserStatistics', :js do
let(:learner) { create(:external_user) }
let(:exercise) { create(:dummy, user:) }
let(:study_group) { create(:study_group) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'Factories' do
RSpec.describe 'Factories' do
it 'are all valid', permitted_execution_time: 30 do
expect { FactoryBot.lint }.not_to raise_error
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Prometheus::Controller do
RSpec.describe Prometheus::Controller do
let(:codeocean_config) { instance_double(CodeOcean::Config) }
let(:prometheus_config) { {prometheus_exporter: {enabled: true}} }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe 'Request_for_Comments' do
RSpec.describe 'Request_for_Comments' do
let(:user) { create(:teacher) }
before do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Admin::DashboardHelper do
RSpec.describe Admin::DashboardHelper do
before do
create(:ruby)
dcp = class_double Runner::Strategy::DockerContainerPool

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ApplicationHelper do
RSpec.describe ApplicationHelper do
describe '#code_tag' do
context 'with code' do
let(:code) { 'puts 42' }
@ -80,7 +80,7 @@ describe ApplicationHelper do
end
describe '#row' do
let(:html) { row(label: 'foo', value: 42) }
let(:html) { row(label: 'shared.show', value: 42) }
it "builds nested 'div' tags" do
expect(html).to have_css('div.attribute-row.row div.col-md-3 + div.col-md-9')

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe AuthenticatedUrlHelper do
RSpec.describe AuthenticatedUrlHelper do
describe '#add_query_parameters' do
it 'adds the given parameters to the given url' do
expect(described_class.add_query_parameters(root_url, {foo: 'bar'})).to eq(root_url(foo: 'bar'))

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExerciseHelper do
RSpec.describe ExerciseHelper do
describe '#embedding_parameters' do
let(:exercise) { build(:dummy) }

View File

@ -4,7 +4,7 @@ require 'find'
require 'active_support'
require 'rails'
describe 'yaml config files' do
RSpec.describe 'yaml config files' do
Find.find(__dir__, 'config') do |path|
next unless /.*.\.yml/.match?(path)

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Assessor do
RSpec.describe Assessor do
let(:assessor) { described_class.new(execution_environment: build(:ruby)) }
describe '#assess' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeOcean::Config do
RSpec.describe CodeOcean::Config do
describe '#read' do
let(:content) { {'foo' => 'bar'} }
let(:filename) { :foo }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe FileTree do
RSpec.describe FileTree do
let(:file_tree) { described_class.new }
describe '#file_icon' do

View File

@ -4,7 +4,7 @@ require 'rails/generators'
require 'generators/testing_framework_adapter_generator'
require 'rails_helper'
describe TestingFrameworkAdapterGenerator do
RSpec.describe TestingFrameworkAdapterGenerator do
include Silencer
describe '#create_testing_framework_adapter' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe JunitAdapter do
RSpec.describe JunitAdapter do
let(:adapter) { described_class.new }
describe '#parse_output' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe MochaAdapter do
RSpec.describe MochaAdapter do
let(:adapter) { described_class.new }
let(:count) { 42 }
let(:failed) { 25 }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe NonceStore do
RSpec.describe NonceStore do
let(:nonce) { SecureRandom.hex }
before do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe PyUnitAdapter do
RSpec.describe PyUnitAdapter do
let(:adapter) { described_class.new }
let(:count) { 42 }
let(:failed) { 25 }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe RspecAdapter do
RSpec.describe RspecAdapter do
let(:adapter) { described_class.new }
let(:count) { 42 }
let(:failed) { 25 }

View File

@ -3,7 +3,7 @@
require 'rails_helper'
require 'pathname'
describe Runner::Strategy::DockerContainerPool do
RSpec.describe Runner::Strategy::DockerContainerPool do
let(:runner_id) { attributes_for(:runner)[:runner_id] }
let(:execution_environment) { create(:ruby) }
let(:container_pool) { described_class.new(runner_id, execution_environment) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Runner::Strategy::Poseidon::Connection do
RSpec.describe Runner::Strategy::Poseidon::Connection do
let(:runner_id) { attributes_for(:runner)[:runner_id] }
let(:execution_environment) { create(:ruby) }
let(:strategy) { Runner::Strategy::Poseidon.new(runner_id, execution_environment) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Runner::Strategy::Poseidon do
RSpec.describe Runner::Strategy::Poseidon do
let(:runner_id) { attributes_for(:runner)[:runner_id] }
let(:execution_environment) { create(:ruby) }
let(:poseidon) { described_class.new(runner_id, execution_environment) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe SqlResultSetComparatorAdapter do
RSpec.describe SqlResultSetComparatorAdapter do
let(:adapter) { described_class.new }
describe '#parse_output' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe TestingFrameworkAdapter do
RSpec.describe TestingFrameworkAdapter do
let(:adapter) { described_class.new }
let(:count) { 42 }
let(:failed) { 25 }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe UserMailer do
RSpec.describe UserMailer do
let(:user) { InternalUser.create(attributes_for(:teacher)) }
describe '#activation_needed_email' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeOcean::File do
RSpec.describe CodeOcean::File do
let(:file) { described_class.create.tap {|file| file.update(content: nil, hidden: nil, read_only: nil) } }
it 'validates the presence of a file type' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeharborLink do
RSpec.describe CodeharborLink do
it { is_expected.to validate_presence_of(:check_uuid_url) }
it { is_expected.to validate_presence_of(:push_url) }
it { is_expected.to validate_presence_of(:api_key) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Consumer do
RSpec.describe Consumer do
let(:consumer) { described_class.create }
let(:valid_consumer) { create(:consumer) }

View File

@ -2,12 +2,13 @@
require 'rails_helper'
describe ExecutionEnvironment do
RSpec.describe ExecutionEnvironment do
let(:execution_environment) { described_class.create.tap {|execution_environment| execution_environment.update(network_enabled: nil, privileged_execution: nil) } }
it 'validates that the Docker image works' do
allow(execution_environment).to receive_messages(validate_docker_image?: true, working_docker_image?: true)
execution_environment.update(build(:ruby).attributes)
execution_environment.assign_attributes(build(:ruby).attributes)
execution_environment.save(validate: false)
expect(execution_environment).to have_received(:working_docker_image?)
end

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Exercise do
RSpec.describe Exercise do
let(:exercise) { described_class.create.tap {|exercise| exercise.update(public: nil, token: nil) } }
let(:users) { create_list(:external_user, 10) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExternalUser do
RSpec.describe ExternalUser do
let(:user) { described_class.create }
it 'validates the presence of a consumer' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe FileType do
RSpec.describe FileType do
let(:file_type) { described_class.create.tap {|file_type| file_type.update(binary: nil, executable: nil, renderable: nil) } }
it 'validates the presence of the binary flag' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe InternalUser do
RSpec.describe InternalUser do
let(:password) { SecureRandom.hex }
let(:user) { described_class.create }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe RequestForComment do
RSpec.describe RequestForComment do
let!(:rfc) { create(:rfc) }
describe 'scope with_comments' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Runner do
RSpec.describe Runner do
let(:runner_id) { attributes_for(:runner)[:runner_id] }
let(:strategy_class) { described_class.strategy_class }
let(:strategy) { instance_double(strategy_class) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Submission do
RSpec.describe Submission do
let(:submission) { create(:submission, exercise: create(:dummy)) }
it 'validates the presence of a cause' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe Admin::DashboardPolicy do
RSpec.describe Admin::DashboardPolicy do
subject(:policy) { described_class }
permissions :show? do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ApplicationPolicy do
RSpec.describe ApplicationPolicy do
describe '#initialize' do
context 'without a user' do
it 'raises an error' do

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeOcean::FilePolicy do
RSpec.describe CodeOcean::FilePolicy do
subject(:policy) { described_class }
let(:exercise) { create(:fibonacci) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe CodeharborLinkPolicy do
RSpec.describe CodeharborLinkPolicy do
subject(:policy) { described_class }
let(:codeharbor_link) { create(:codeharbor_link) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ConsumerPolicy do
RSpec.describe ConsumerPolicy do
subject(:policy) { described_class }
%i[create? destroy? edit? index? new? show? update?].each do |action|

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExecutionEnvironmentPolicy do
RSpec.describe ExecutionEnvironmentPolicy do
subject(:policy) { described_class }
let(:execution_environment) { build(:ruby) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExercisePolicy do
RSpec.describe ExercisePolicy do
subject(:policy) { described_class }
let(:exercise) { build(:dummy, public: true) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ExternalUserPolicy do
RSpec.describe ExternalUserPolicy do
subject(:policy) { described_class }
%i[create? destroy? edit? new? show? update?].each do |action|

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe FileTypePolicy do
RSpec.describe FileTypePolicy do
subject(:policy) { described_class }
let(:file_type) { build(:dot_rb) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe InternalUserPolicy do
RSpec.describe InternalUserPolicy do
subject(:policy) { described_class }
%i[create? edit? new? show? update?].each do |action|

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe ProgrammingGroupPolicy do
RSpec.describe ProgrammingGroupPolicy do
subject(:policy) { described_class }
let(:programming_group) { build(:programming_group) }

View File

@ -2,7 +2,7 @@
require 'rails_helper'
describe RequestForCommentPolicy do
RSpec.describe RequestForCommentPolicy do
subject(:policy) { described_class }
context 'when the RfC visibility is not considered' do

Some files were not shown because too many files have changed in this diff Show More