+ {/* Fim do modal de experimento criado */}
+
+ {/* Formulário de criação de experimento */}
+
+
+
Criar Experimento
+
+
+
+
Fatores
+ {Object.keys(factors).map((factor) => (
+
+
+ {factor}
+
+
+
+
+
+ {factors[factor].map((value) => (
+
+ {value}
+
+
+ ))}
+
+ ))}
+
+
+ >
+ );
+};
+
+export default CreateExperiment;
diff --git a/app/javascript/react/src/index.js b/app/javascript/react/src/index.js
index a9759c53..68a83910 100644
--- a/app/javascript/react/src/index.js
+++ b/app/javascript/react/src/index.js
@@ -1,5 +1,7 @@
import { define } from 'remount'
import Hello from "./components/Hello"
import Graph from "./components/Graph"
+import CreateExperiment from "./components/CreateExperiment"
+import ClassificationExperiment from './components/ClassificationExperiment'
-define({ 'hello-component': Hello, 'graph-component': Graph })
+define({ 'hello-component': Hello, 'graph-component': Graph, 'create-experiment-component': CreateExperiment, 'create-classification-experiment-component': ClassificationExperiment })
\ No newline at end of file
diff --git a/app/models/experiment.rb b/app/models/experiment.rb
index 5cf63272..e7f5e492 100644
--- a/app/models/experiment.rb
+++ b/app/models/experiment.rb
@@ -1,3 +1,5 @@
class Experiment < ApplicationRecord
has_many :trials
+ has_many :experiment_tag
+ has_many :tags, through: :experiment_tag
end
diff --git a/app/models/experiment_tag.rb b/app/models/experiment_tag.rb
new file mode 100644
index 00000000..8f6879bc
--- /dev/null
+++ b/app/models/experiment_tag.rb
@@ -0,0 +1,4 @@
+class ExperimentTag < ApplicationRecord
+ belongs_to :experiment
+ belongs_to :tag
+end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 98eba85b..5843a35c 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -1,3 +1,4 @@
class Tag < ApplicationRecord
has_many :trials, through: :classification
+ has_many :experiments, through: :experiment_tag
end
diff --git a/app/views/classification/index.html.erb b/app/views/classification/index.html.erb
new file mode 100644
index 00000000..b9c62a6e
--- /dev/null
+++ b/app/views/classification/index.html.erb
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/views/experiment/index.html.erb b/app/views/experiment/index.html.erb
new file mode 100644
index 00000000..e3a951c7
--- /dev/null
+++ b/app/views/experiment/index.html.erb
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/bun.lockb b/bun.lockb
index fbc672dd..17db9e53 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/config/routes.rb b/config/routes.rb
index a27857a6..ab880e20 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,6 +1,15 @@
Rails.application.routes.draw do
+ resources :create_experiments
get 'hello/world'
- get 'hello/worldGet', to: "hello#index"
+ get 'hello/worldGet', to: "hello#index"
+ get 'experiment/create', to: "experiment#index"
+ post 'experiment/create', to: "experiment#create"
+ get 'experiment/classification', to: "classification#index"
+ get 'experiment/get_all', to: "experiment#get_all"
+ post 'tags/create', to: "tags#create"
+ get 'tags/get_all', to: "tags#get_all"
+ post 'experiment/add_tag', to: "experiment#add_tag"
+ delete 'experiment/remove_tag', to: "experiment#remove_tag"
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
diff --git a/db/migrate/20231203174203_create_experiment_tags.rb b/db/migrate/20231203174203_create_experiment_tags.rb
new file mode 100644
index 00000000..204f79d8
--- /dev/null
+++ b/db/migrate/20231203174203_create_experiment_tags.rb
@@ -0,0 +1,9 @@
+class CreateExperimentTags < ActiveRecord::Migration[7.1]
+ def change
+ create_table :experiment_tags do |t|
+ t.belongs_to :experiment
+ t.belongs_to :tag
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 183d56d5..df8612a9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2023_11_13_225719) do
+ActiveRecord::Schema[7.1].define(version: 2023_12_03_174203) do
create_table "classifications", force: :cascade do |t|
t.integer "trial_id"
t.integer "tag_id"
@@ -20,6 +20,15 @@
t.index ["trial_id"], name: "index_classifications_on_trial_id"
end
+ create_table "experiment_tags", force: :cascade do |t|
+ t.integer "experiment_id"
+ t.integer "tag_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["experiment_id"], name: "index_experiment_tags_on_experiment_id"
+ t.index ["tag_id"], name: "index_experiment_tags_on_tag_id"
+ end
+
create_table "experiments", force: :cascade do |t|
t.string "name"
t.boolean "disabled"
@@ -44,8 +53,10 @@
create_table "trial_executions", force: :cascade do |t|
t.string "status"
t.text "log"
+ t.integer "trial_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["trial_id"], name: "index_trial_executions_on_trial_id"
end
create_table "trial_factors", force: :cascade do |t|
diff --git a/features/4_Adicionar_experimento.feature b/features/4_Adicionar_experimento.feature
new file mode 100644
index 00000000..ece7753b
--- /dev/null
+++ b/features/4_Adicionar_experimento.feature
@@ -0,0 +1,26 @@
+ Feature: Add a new experiment and Confirmation
+ @javascript
+ Scenario: Add a new experiment (Happy)
+ When the user is on the add experiment screen
+ And the user clicks on the experiment name field and types "Experiment B1"
+ And the user clicks on the factor name field and types "Velocidade"
+ And the user clicks on the add factor button
+ And the user clicks on the factor name field and types "Temperatura"
+ And the user clicks on the add factor button
+ And the user clicks on the factor value field and types "10"
+ And the user clicks on the button with id "add-to-Velocidade"
+ And the user clicks on the factor value field and types "20"
+ And the user clicks on the button with id "add-to-Velocidade"
+ And the user clicks on the factor value field and types "30"
+ And the user clicks on the button with id "add-to-Temperatura"
+ And the user clicks on the factor value field and types "40"
+ And the user clicks on the button with id "add-to-Temperatura"
+ And the user clicks on the create experiment button
+ Then the user should see a modal with the experiment details
+
+ @javascript
+ Scenario: Add a new experiment (Sad)
+ When the user is on the add experiment screen
+ And the user dont fill the fields
+ And the user clicks on the create experiment button
+ Then the user should see the fail message "Erro ao criar o experimento!"
diff --git a/features/5_Classificar_experimentos.feature b/features/5_Classificar_experimentos.feature
new file mode 100644
index 00000000..4a06870b
--- /dev/null
+++ b/features/5_Classificar_experimentos.feature
@@ -0,0 +1,14 @@
+Feature: Classify experiments with tags
+ @javascript
+ Scenario: Add tag to experiment (Happy)
+ Given I am on the "/experiment/classification" page
+ When I click on the tag with id "tag-2"
+ And I click on the add button with id "add-tag-1"
+ Then I should see the message "Tag adicionada com sucesso!"
+ And I should see the tag "Tag 2" on the experiment "experiment-1-tags"
+
+ @javascript
+ Scenario: Add tag to experiment without selecting a tag (Sad)
+ Given I am on the "/experiment/classification" page
+ And I click on the add button with id "add-tag-1"
+ Then I should see the message "Erro ao adicionar tag!"
\ No newline at end of file
diff --git a/features/step_definitions/4_Adicionar_experimento_step.rb b/features/step_definitions/4_Adicionar_experimento_step.rb
new file mode 100644
index 00000000..bd3172eb
--- /dev/null
+++ b/features/step_definitions/4_Adicionar_experimento_step.rb
@@ -0,0 +1,46 @@
+When("the user is on the add experiment screen") do
+ visit '/experiment/create'
+end
+
+And("the user clicks on the experiment name field and types {string}") do |string|
+ fill_in 'experimentName', with: string
+end
+
+And("the user clicks on the factor name field and types {string}") do |string|
+ fill_in 'factorName', with: string
+end
+
+And("the user clicks on the add factor button") do
+ click_button 'addFactor'
+end
+
+And("the user clicks on the factor value field and types {string}") do |string|
+ fill_in 'factorValue', with: string
+end
+
+And("the user clicks on the button with id {string}") do |string|
+ find(:css, '#' + string).click
+end
+
+And("the user clicks on the create experiment button") do
+ click_button 'createExperiment'
+end
+
+Then('the user should see a modal with the experiment details') do
+ expect(page).to have_content('Experimento criado')
+ expect(page).to have_content('Experiment B1')
+ expect(page).to have_content('Ensaio 10-30')
+ expect(page).to have_content('Ensaio 10-40')
+ expect(page).to have_content('Ensaio 20-30')
+ expect(page).to have_content('Ensaio 20-40')
+end
+
+And("the user dont fill the fields") do
+ fill_in 'experimentName', with: ''
+ fill_in 'factorName', with: ''
+ fill_in 'factorValue', with: ''
+end
+
+Then("the user should see the fail message {string}") do |string|
+ expect(page).to have_content(string)
+end
diff --git a/features/step_definitions/5_Classificar_experimentos_step.rb b/features/step_definitions/5_Classificar_experimentos_step.rb
new file mode 100644
index 00000000..dc1969cc
--- /dev/null
+++ b/features/step_definitions/5_Classificar_experimentos_step.rb
@@ -0,0 +1,26 @@
+Before do
+ Experiment.create(name: 'Experimento 1')
+ Tag.create(name: 'Tag 1', color: 'red')
+ Tag.create(name: 'Tag 2', color: 'blue')
+end
+
+Given("I am on the {string} page") do |string|
+ visit string
+end
+
+When("I click on the tag with id {string}") do |string|
+ find(:css, '#' + string).click
+end
+
+And("I click on the add button with id {string}") do |string|
+ find(:css, '#' + string).click
+end
+
+
+Then("I should see the message {string}") do |string|
+ expect(page).to have_content(string)
+end
+
+And("I should see the tag {string} on the experiment {string}") do |string, string2|
+ expect(page).to have_css('#'+string2, text: string)
+end
diff --git a/package.json b/package.json
index 25b33f79..94a92bb1 100644
--- a/package.json
+++ b/package.json
@@ -7,8 +7,10 @@
"dependencies": {
"@hotwired/stimulus": "^3.2.2",
"@hotwired/turbo-rails": "^7.3.0",
+ "@uidotdev/usehooks": "^2.4.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-simple-toasts": "^5.10.0",
"remount": "^1.0.0"
}
}
\ No newline at end of file
diff --git a/spec/controllers/experiment_controller_spec.rb b/spec/controllers/experiment_controller_spec.rb
new file mode 100644
index 00000000..a13da65f
--- /dev/null
+++ b/spec/controllers/experiment_controller_spec.rb
@@ -0,0 +1,220 @@
+require 'rails_helper'
+
+RSpec.describe ExperimentController, type: :controller do
+ context 'POST #create' do
+ it 'should create an experiment' do
+ post :create, params: { experimentName: 'test', factors: { 'velocidade' => ['1', '2'], 'temperatura' => ['4', '5'] } }
+
+
+ body = JSON.parse(response.body)
+ expect(body['experiment']['name']).to eq('test')
+ expect(body['experiment']['disabled']).to eq(false)
+ expect(body['trials'].length).to eq(4)
+
+ body['trials'].each do |trial|
+ expect(trial['trial']['disabled']).to eq(false)
+ expect(trial['trial']['deleted']).to eq(false)
+ expect(trial['trial']['runs']).to eq(0)
+ expect(trial['trial']['experiment_id']).to eq(body['experiment']['id'])
+ end
+
+ trial_names = body['trials'].map { |trial| trial['trial']['name'] }
+ expect(trial_names).to include('4-1', '4-2', '5-1', '5-2').or include('1-4', '1-5', '2-4', '2-5')
+
+ expect(response).to have_http_status(:ok)
+ expect(JSON.parse(response.body)['message']).to eq('success')
+ end
+
+ it 'should not create an experiment if experimentName is nil' do
+ post :create, params: {factors: { 'velocidade' => ['1', '2'], 'temperatura' => ['4', '5'] } }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+
+ it 'should not create an experiment if experimentName is empty' do
+ post :create, params: { experimentName: '', factors: { 'velocidade' => ['1', '2'], 'temperatura' => ['4', '5'] } }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+
+ it 'should not create an experiment if factors is nil' do
+ post :create, params: { experimentName: 'test' }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+
+ it 'should not create an experiment if factors is empty' do
+ post :create, params: { experimentName: 'test', factors: {} }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+
+ it 'should not create an experiment if factors array is empty' do
+ post :create, params: { experimentName: 'test', factors: { 'velocidade' => [], 'temperatura' => [] } }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+
+ it 'should not create an experiment if factors is not a hash' do
+ post :create, params: { experimentName: 'test', factors: 'velocidade' }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+
+ it 'should not create an experiment if factors is a hash with values that are not arrays' do
+ post :create, params: { experimentName: 'test', factors: { 'velocidade' => '1', 'temperatura' => ['4', '5'] } }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Invalid params')
+ end
+ end
+
+ context 'POST #add_tag' do
+ # setup
+ before(:each) do
+ Experiment.create(id: 1, name: 'test')
+ Tag.create(id: 1, name: 'tag', color: 'red')
+ end
+
+ it 'should add tag to experiment' do
+ post :add_tag, params: { experiment_id: 1, tag_id: 1 }
+
+ expect(response).to have_http_status(:ok)
+ expect(JSON.parse(response.body)['message']).to eq('success')
+ end
+
+ it 'should not add tag to experiment if experiment_id is nil' do
+ post :add_tag, params: { tag_id: 1 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment not found')
+ end
+
+ it 'should not add tag to experiment if tag_id is nil' do
+ post :add_tag, params: { experiment_id: 1 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Tag not found')
+ end
+
+ it 'should not add tag to experiment if experiment does not exist' do
+ post :add_tag, params: { experiment_id: 2, tag_id: 1 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment not found')
+ end
+
+ it 'should not add tag to experiment if tag does not exist' do
+ post :add_tag, params: { experiment_id: 1, tag_id: 2 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Tag not found')
+ end
+
+ it 'should not add tag to experiment if experiment already has tag' do
+ ExperimentTag.create(experiment_id: 1, tag_id: 1)
+ post :add_tag, params: { experiment_id: 1, tag_id: 1 }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment already has tag')
+ end
+
+ end
+
+ context 'DELETE #remove_tag' do
+
+ # setup
+ before(:each) do
+ Experiment.create(id: 1, name: 'test')
+ Tag.create(id: 1, name: 'tag', color: 'red')
+ ExperimentTag.create(experiment_id: 1, tag_id: 1)
+ Experiment.create(id: 2, name: 'test2')
+ Tag.create(id: 2, name: 'tag2', color: 'blue')
+ end
+
+ it 'should remove tag from experiment' do
+ delete :remove_tag, params: { experiment_id: 1, tag_id: 1 }
+
+ expect(response).to have_http_status(:ok)
+ expect(JSON.parse(response.body)['message']).to eq('success')
+
+ expect(ExperimentTag.where(experiment_id: 1, tag_id: 1).any?).to eq(false)
+ end
+
+ it 'should not remove tag from experiment if experiment_id is nil' do
+ delete :remove_tag, params: { tag_id: 1 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment not found')
+ end
+
+ it 'should not remove tag from experiment if tag_id is nil' do
+ delete :remove_tag, params: { experiment_id: 1 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Tag not found')
+ end
+
+ it 'should not remove tag from experiment if experiment does not exist' do
+ delete :remove_tag, params: { experiment_id: 3, tag_id: 1 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment not found')
+ end
+
+ it 'should not remove tag from experiment if tag does not exist' do
+ delete :remove_tag, params: { experiment_id: 1, tag_id: 3 }
+
+ expect(response).to have_http_status(:not_found)
+ expect(JSON.parse(response.body)['error']).to eq('Tag not found')
+ end
+
+ it 'should not remove tag from experiment if experiment does not have tag' do
+ delete :remove_tag, params: { experiment_id: 2, tag_id: 2 }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment does not have tag')
+ end
+
+ it 'should not remove tag from experiment if experiment has tag but not the one being removed' do
+ delete :remove_tag, params: { experiment_id: 1, tag_id: 2 }
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(JSON.parse(response.body)['error']).to eq('Experiment does not have tag')
+ end
+ end
+
+ context 'GET #get_all' do
+ # setup
+ before(:each) do
+ Experiment.create(id: 1, name: 'test', disabled: false)
+ Factor.create(id: 1, name: 'velocidade', value: '1')
+ Trial.create(id: 1, name: '1', experiment_id: 1, disabled: false, deleted: false, runs: 0)
+ TrialFactor.create(id: 1, trial_id: 1, factor_id: 1)
+ Tag.create(id: 1, name: 'tag', color: 'red')
+ ExperimentTag.create(id: 1, experiment_id: 1, tag_id: 1)
+ end
+
+ it 'should get all experiments' do
+ get :get_all
+
+ expect(response).to have_http_status(:ok)
+ experiments = JSON.parse(response.body)['experiments']
+
+ expect(experiments.length).to eq(1)
+ experiment = experiments[0]['experiment']
+ expect(experiment['id']).to eq(1)
+
+ tags = experiments[0]['tags']
+ expect(tags.length).to eq(1)
+ tag = tags[0]
+ expect(tag['id']).to eq(1)
+ end
+ end
+end
diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb
new file mode 100644
index 00000000..a15455f3
--- /dev/null
+++ b/spec/rails_helper.rb
@@ -0,0 +1,65 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+require 'spec_helper'
+ENV['RAILS_ENV'] ||= 'test'
+require_relative '../config/environment'
+# Prevent database truncation if the environment is production
+abort("The Rails environment is running in production mode!") if Rails.env.production?
+require 'rspec/rails'
+# Add additional requires below this line. Rails is not loaded until this point!
+
+# Requires supporting ruby files with custom matchers and macros, etc, in
+# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
+# run as spec files by default. This means that files in spec/support that end
+# in _spec.rb will both be required and run as specs, causing the specs to be
+# run twice. It is recommended that you do not name files matching this glob to
+# end with _spec.rb. You can configure this pattern with the --pattern
+# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
+#
+# The following line is provided for convenience purposes. It has the downside
+# of increasing the boot-up time by auto-requiring all files in the support
+# directory. Alternatively, in the individual `*_spec.rb` files, manually
+# require only the support files necessary.
+#
+# Rails.root.glob('spec/support/**/*.rb').sort.each { |f| require f }
+
+# Checks for pending migrations and applies them before tests are run.
+# If you are not using ActiveRecord, you can remove these lines.
+begin
+ ActiveRecord::Migration.maintain_test_schema!
+rescue ActiveRecord::PendingMigrationError => e
+ abort e.to_s.strip
+end
+RSpec.configure do |config|
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_paths = [
+ Rails.root.join('spec/fixtures')
+ ]
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+
+ # You can uncomment this line to turn off ActiveRecord support entirely.
+ # config.use_active_record = false
+
+ # RSpec Rails can automatically mix in different behaviours to your tests
+ # based on their file location, for example enabling you to call `get` and
+ # `post` in specs under `spec/controllers`.
+ #
+ # You can disable this behaviour by removing the line below, and instead
+ # explicitly tag your specs with their type, e.g.:
+ #
+ # RSpec.describe UsersController, type: :controller do
+ # # ...
+ # end
+ #
+ # The different available types are documented in the features, such as in
+ # https://rspec.info/features/6-0/rspec-rails
+ config.infer_spec_type_from_file_location!
+
+ # Filter lines from Rails gems in backtraces.
+ config.filter_rails_from_backtrace!
+ # arbitrary gems may also be filtered via:
+ # config.filter_gems_from_backtrace("gem name")
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 00000000..93399d18
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,96 @@
+require 'simplecov'
+SimpleCov.start
+# This file was generated by the `rails generate rspec:install` command. Conventionally, all
+# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
+# The generated `.rspec` file contains `--require spec_helper` which will cause
+# this file to always be loaded, without a need to explicitly require it in any
+# files.
+#
+# Given that it is always loaded, you are encouraged to keep this file as
+# light-weight as possible. Requiring heavyweight dependencies from this file
+# will add to the boot time of your test suite on EVERY test run, even for an
+# individual file that may not need all of that loaded. Instead, consider making
+# a separate helper file that requires the additional dependencies and performs
+# the additional setup, and require it from the spec files that actually need
+# it.
+#
+# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ # rspec-expectations config goes here. You can use an alternate
+ # assertion/expectation library such as wrong or the stdlib/minitest
+ # assertions if you prefer.
+ config.expect_with :rspec do |expectations|
+ # This option will default to `true` in RSpec 4. It makes the `description`
+ # and `failure_message` of custom matchers include text for helper methods
+ # defined using `chain`, e.g.:
+ # be_bigger_than(2).and_smaller_than(4).description
+ # # => "be bigger than 2 and smaller than 4"
+ # ...rather than:
+ # # => "be bigger than 2"
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ # rspec-mocks config goes here. You can use an alternate test double
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
+ config.mock_with :rspec do |mocks|
+ # Prevents you from mocking or stubbing a method that does not exist on
+ # a real object. This is generally recommended, and will default to
+ # `true` in RSpec 4.
+ mocks.verify_partial_doubles = true
+ end
+
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
+ # have no way to turn it off -- the option exists only for backwards
+ # compatibility in RSpec 3). It causes shared context metadata to be
+ # inherited by the metadata hash of host groups and examples, rather than
+ # triggering implicit auto-inclusion in groups with matching metadata.
+ config.shared_context_metadata_behavior = :apply_to_host_groups
+
+# The settings below are suggested to provide a good initial experience
+# with RSpec, but feel free to customize to your heart's content.
+=begin
+ # This allows you to limit a spec run to individual examples or groups
+ # you care about by tagging them with `:focus` metadata. When nothing
+ # is tagged with `:focus`, all examples get run. RSpec also provides
+ # aliases for `it`, `describe`, and `context` that include `:focus`
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
+ config.filter_run_when_matching :focus
+
+ # Allows RSpec to persist some state between runs in order to support
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # you configure your source control system to ignore this file.
+ config.example_status_persistence_file_path = "spec/examples.txt"
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/
+ config.disable_monkey_patching!
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = "doc"
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+=end
+end
diff --git a/test/controllers/experiment_controller_test.rb b/test/controllers/experiment_controller_test.rb
new file mode 100644
index 00000000..4e9b0163
--- /dev/null
+++ b/test/controllers/experiment_controller_test.rb
@@ -0,0 +1,9 @@
+require "test_helper"
+
+class ExperimentControllerTest < ActionDispatch::IntegrationTest
+ # test "the truth" do
+ # assert true
+ # end
+
+
+end
diff --git a/test/integration/4_Adicionar_experimento.feature b/test/integration/4_Adicionar_experimento.feature
new file mode 100644
index 00000000..e56cfe7e
--- /dev/null
+++ b/test/integration/4_Adicionar_experimento.feature
@@ -0,0 +1,44 @@
+Funcionalidade: Criar um experimento baseado em planos locais
+
+Contexto:
+Dado que sou um usuário
+E estou logado na plataforma
+E estou na tela para adicionar um novo experimento
+E não existe nenhum robô
+
+Cenário: Registrar um novo robô (Happy)
+Dado que o usuário clique no botão adicionar um novo robô
+Quando clico para registra o parâmetro nome e confirmo
+Então um novo robô é registrado com sucesso.
+
+Cenário: Registrar um novo robô (Sad)
+Dado que o usuário clique no botão adicionar um novo robô
+Quando clico para adicionar o parâmetro nome e confirmo
+Então o robô não é adicionado devido a um erro ou à sintaxe inválida dos parâmetros.
+
+Contexto:
+Dado que sou um usuário
+E estou logado na plataforma
+E estou na tela para adicionar um novo experimento
+E já existem um ou mais robôs
+
+Cenário: Registrar um novo robô (Sad - Robô Existente)
+Dado que o usuário deseja registrar um novo robô
+Quando clico para adicionar o parâmetro nome e confirmo
+Então o robô não é adicionado devido a um erro ou ao fornecimento de um nome já existente.
+
+Contexto:
+Dado que sou um usuário
+E estou logado na plataforma
+E estou na tela para adicionar um novo experimento
+E um robô já existe.
+
+Cenário: Registrar um novo experimento (Happy)
+Dado que o usuário deseja adicionar um novo experimento
+Quando forneço os parâmetros corretamente e especifico a quantidade de robôs
+Então os testes são gerados como esperado.
+
+Cenário: Registrar um novo experimento (Sad)
+Dado que o usuário deseja adicionar um novo experimento
+Quando forneço os parâmetros de forma inválida e especifico a quantidade de robôs
+Então os testes não são gerados como esperado.
diff --git a/test/integration/5_Classificar_experimento.feature b/test/integration/5_Classificar_experimento.feature
new file mode 100644
index 00000000..66e9662f
--- /dev/null
+++ b/test/integration/5_Classificar_experimento.feature
@@ -0,0 +1,21 @@
+Funcionalidade: Classificar experimentos com uma tag
+
+Contexto:
+Dado que sou um usuário
+E estou logado na plataforma
+E estou na tela de lista dos experimentos
+
+Cenário: Classificar um experimento (Happy)
+Dado que eu desejo classificar um novo experimento
+Quando seleciono o experimento desejado e atribuo o nome da tag
+Então o experimento é classificado com sucesso e a cor é atribuída ao experimento.
+
+Cenário: Classificar um experimento (Sad)
+Dado que eu desejo classificar um novo experimento
+Quando seleciono o experimento desejado e atribuo o nome da tag
+Então o experimento não pode ser classificado, pois a tag não existe.
+
+Cenário: Classificar um experimento (Sad)
+Dado que eu desejo classificar um novo experimento
+Quando seleciono o experimento desejado e atribuo um nome de tag inválido
+Então o experimento não pode ser classificado devido à tag inválida.