From 6f29ae12ded3052ce6506f2444c3690f14df1684 Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Mon, 15 Jul 2024 12:13:17 -0400 Subject: [PATCH 1/8] Moves javascript into asset pipeline. --- app/assets/javascripts/custom.js | 126 +++++++++++++ app/views/layouts/application.html.erb | 150 +++------------- app/views/layouts/software_records.html.erb | 187 ++------------------ config/initializers/assets.rb | 1 + 4 files changed, 165 insertions(+), 299 deletions(-) create mode 100644 app/assets/javascripts/custom.js diff --git a/app/assets/javascripts/custom.js b/app/assets/javascripts/custom.js new file mode 100644 index 00000000..8ce1eaf0 --- /dev/null +++ b/app/assets/javascripts/custom.js @@ -0,0 +1,126 @@ +function openNav() { + document.getElementById("mySidenav").style.visibility = "visible"; + document.getElementById("mySidenav").style.width = "250px"; + document.getElementById("main").style.marginLeft = "250px"; +} + +function closeNav() { + document.getElementById("mySidenav").style.visibility = "hidden"; + document.getElementById("mySidenav").style.width = "0"; + document.getElementById("main").style.marginLeft = "0"; +} + +var dropdown = document.getElementsByClassName("dropdown-btn"); +var i; +for (i = 0; i < dropdown.length; i++) { + dropdown[i].addEventListener("click", function() { + this.classList.toggle("active"); + var dropdownContent = this.nextElementSibling; + if (dropdownContent.style.display === "block") { + dropdownContent.style.display = "none"; + } else { + dropdownContent.style.display = "block"; + } + }); +} + +window.onload = function() { + window.count_developers = 2; + window.count_tech_leads = 2; + window.count_departments = 2; + window.count_product_owners = 2; + window.count_admin_users = 2; +} + +function add(name, value) { + var element = document.createElement("div"); + var inputelement = document.createElement("input"); + var inputgroupappend = document.createElement("div"); + var spanelement = document.createElement("span"); + var removebutton = document.createElement("i"); + element.className = "input-group mt-2"; + if(name == "departments") { + element.id = name + window.count_departments; + } + else if(name == "product_owners") { + element.id = name + window.count_product_owners; + } + else if(name == "admin_users") { + element.id = name + window.count_admin_users; + } + inputelement.type = "text"; + inputelement.required = true; + if(value != "") { + inputelement.innerHTML = value; + } + inputelement.name = "software_record[" + name + "][]"; + inputelement.id = "software_record_"+ name + "_" ; + inputelement.className = "form-control"; + element.appendChild(inputelement); + inputgroupappend.className = "input-group-append btnRemove"; + element.appendChild(inputgroupappend); + spanelement.className = "input-group-text"; + inputgroupappend.appendChild(spanelement); + removebutton.className = "fas fa-minus remove"; + removebutton.innerHTML = " Delete"; + spanelement.appendChild(removebutton); + inputgroupappend.onclick = function() { + document.getElementById(element.id).remove(); + }; + var valued = "multiple_"+name; + var multi_valued = document.getElementById(valued); + multi_valued.appendChild(element); +} + +document.getElementById("btnAddProductOwners").onclick = function() { + add("product_owners", ""); + window.count_product_owners++; +}; + +document.getElementById("btnAddAdminUsers").onclick = function() { + add("admin_users", ""); + window.count_admin_users++; +}; + +document.getElementById("btnAddDepartments").onclick = function() { + add("departments", ""); + window.count_departments++; +}; + +function remove(id){ + document.getElementById(id).remove(); +} + +var createdbyfield = document.getElementsByClassName('regex-createdby')[0]; +createdbyfield.onkeyup = function() { + createdbyfield.value = createdbyfield.value.replace(/[^a-zA-Z0-9 ]/, ''); +} + +// Specific to software_records.html.erb +function clearFilters() { + document.getElementById("vendor-record-filter").style.display = "none"; + document.getElementById("software-type-filter").style.display = "none"; + var loaded = window.location.host; + window.location = "software_records"; +} + +function handleRadio(myRadio) { + if(myRadio.value === "vendor_records") { + document.getElementById("vendor-record-filter").style.display = "block"; + document.getElementById("software-type-filter").style.display = "none"; + } else { + document.getElementById("vendor-record-filter").style.display = "none"; + document.getElementById("software-type-filter").style.display = "block"; + } +} + +document.getElementById("btnAddDevelopers").onclick = function() { + add("developers", ""); + window.count_developers++; +}; + +document.getElementById("btnAddTechLeads").onclick = function() { + add("tech_leads", ""); + window.count_tech_leads++; +}; + diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index bbec0fdd..db4bc2c0 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -6,138 +6,30 @@ <%= csp_meta_tag %> <%= favicon_link_tag asset_path('favicon.ico'), :rel => 'icon', :type => 'image/x-icon' %> - + - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> - - <%= render 'shared/dashboard_menu' %> -
- <%= render 'shared/dashboard_header' %> - <% if current_user %>
Menu ☰
<% end %> - <%= yield %> - <%= alerts %> - <% if @controller == "users" %> - <% %> - <% elsif @controller!=("front") %> - <%= render 'shared/application_footer' %> - <% end %> -
+ <%= render 'shared/dashboard_menu' %> +
+ <%= render 'shared/dashboard_header' %> + <% if current_user %> +
+ Menu ☰ +
+ <% end %> + <%= yield %> + <%= alerts %> + <% if @controller == "users" %> + <% %> + <% elsif @controller!=("front") %> + <%= render 'shared/application_footer' %> + <% end %> +
+ <%= javascript_include_tag 'custom' %> - - - + diff --git a/app/views/layouts/software_records.html.erb b/app/views/layouts/software_records.html.erb index a314361c..4369ba19 100644 --- a/app/views/layouts/software_records.html.erb +++ b/app/views/layouts/software_records.html.erb @@ -6,179 +6,26 @@ <%= csp_meta_tag %> <%= favicon_link_tag asset_path('favicon.ico'), :rel => 'icon', :type => 'image/x-icon' %> - + - <%= stylesheet_link_tag 'software_records', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= stylesheet_link_tag 'software_records', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> - - <%= render 'shared/dashboard_menu' %> -
- <%= render 'shared/dashboard_header' %> - <% if current_user %>
Menu ☰
<% end %> - <%= yield %> - <%= alerts %> - <%= render 'shared/dashboard_footer' %> -
+ <%= render 'shared/dashboard_menu' %> +
+ <%= render 'shared/dashboard_header' %> + <% if current_user %> +
+ Menu ☰ +
+ <% end %> + <%= yield %> + <%= alerts %> + <%= render 'shared/dashboard_footer' %> +
+ <%= javascript_include_tag 'custom' %> - - - - + diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 13a8f3f2..dc49f927 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -14,3 +14,4 @@ # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w( admin.js admin.css ) +Rails.application.config.assets.precompile += %w( custom.js ) From a188cb3d9eef8f51b569370afecac7e7cd79243a Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Mon, 15 Jul 2024 13:34:36 -0400 Subject: [PATCH 2/8] Refactors form view to handle the multi-value ids. --- app/assets/javascripts/custom.js | 134 +++-- .../software_records/_form_general.html.erb | 462 +++++++----------- 2 files changed, 227 insertions(+), 369 deletions(-) diff --git a/app/assets/javascripts/custom.js b/app/assets/javascripts/custom.js index 8ce1eaf0..28d2047b 100644 --- a/app/assets/javascripts/custom.js +++ b/app/assets/javascripts/custom.js @@ -1,93 +1,81 @@ -function openNav() { - document.getElementById("mySidenav").style.visibility = "visible"; - document.getElementById("mySidenav").style.width = "250px"; - document.getElementById("main").style.marginLeft = "250px"; -} - -function closeNav() { - document.getElementById("mySidenav").style.visibility = "hidden"; - document.getElementById("mySidenav").style.width = "0"; - document.getElementById("main").style.marginLeft = "0"; -} +window.onload = function() { + window.counts = { -var dropdown = document.getElementsByClassName("dropdown-btn"); -var i; -for (i = 0; i < dropdown.length; i++) { - dropdown[i].addEventListener("click", function() { - this.classList.toggle("active"); - var dropdownContent = this.nextElementSibling; - if (dropdownContent.style.display === "block") { - dropdownContent.style.display = "none"; - } else { - dropdownContent.style.display = "block"; - } - }); -} + developers: window.counts?.developers || 1, + tech_leads: window.counts?.tech_leads || 1, + departments: window.counts?.departments || 1, + product_owners: window.counts?.product_owners || 1, + admin_users: window.counts?.admin_users || 1 -window.onload = function() { - window.count_developers = 2; - window.count_tech_leads = 2; - window.count_departments = 2; - window.count_product_owners = 2; - window.count_admin_users = 2; -} + }; +}; function add(name, value) { + var count = window.counts[name]++; + var elementId = name + count; + var inputId = "software_record_" + name + "_" + count; + var element = document.createElement("div"); - var inputelement = document.createElement("input"); - var inputgroupappend = document.createElement("div"); - var spanelement = document.createElement("span"); - var removebutton = document.createElement("i"); element.className = "input-group mt-2"; - if(name == "departments") { - element.id = name + window.count_departments; - } - else if(name == "product_owners") { - element.id = name + window.count_product_owners; - } - else if(name == "admin_users") { - element.id = name + window.count_admin_users; - } - inputelement.type = "text"; - inputelement.required = true; - if(value != "") { - inputelement.innerHTML = value; + element.id = elementId; + + var inputElement = document.createElement("input"); + inputElement.type = "text"; + inputElement.required = true; + inputElement.name = "software_record[" + name + "][]"; + inputElement.id = inputId; // Ensure unique ID for each input element + inputElement.className = "form-control"; + if (value != "") { + inputElement.value = value; } - inputelement.name = "software_record[" + name + "][]"; - inputelement.id = "software_record_"+ name + "_" ; - inputelement.className = "form-control"; - element.appendChild(inputelement); - inputgroupappend.className = "input-group-append btnRemove"; - element.appendChild(inputgroupappend); - spanelement.className = "input-group-text"; - inputgroupappend.appendChild(spanelement); - removebutton.className = "fas fa-minus remove"; - removebutton.innerHTML = " Delete"; - spanelement.appendChild(removebutton); - inputgroupappend.onclick = function() { - document.getElementById(element.id).remove(); + element.appendChild(inputElement); + + var inputGroupAppend = document.createElement("div"); + inputGroupAppend.className = "input-group-append btnRemove"; + element.appendChild(inputGroupAppend); + + var spanElement = document.createElement("span"); + spanElement.className = "input-group-text"; + inputGroupAppend.appendChild(spanElement); + + var removeButton = document.createElement("i"); + removeButton.className = "fas fa-minus remove"; + removeButton.innerHTML = " Delete"; + spanElement.appendChild(removeButton); + + // Update the onclick handler to directly remove the parent element + inputGroupAppend.onclick = function() { + element.remove(); }; - var valued = "multiple_"+name; - var multi_valued = document.getElementById(valued); - multi_valued.appendChild(element); + + var valued = "multiple_" + name; + var multiValued = document.getElementById(valued); + multiValued.appendChild(element); + + console.log("Added element with ID: " + element.id + " and input ID: " + inputId); } document.getElementById("btnAddProductOwners").onclick = function() { add("product_owners", ""); - window.count_product_owners++; }; document.getElementById("btnAddAdminUsers").onclick = function() { add("admin_users", ""); - window.count_admin_users++; }; document.getElementById("btnAddDepartments").onclick = function() { add("departments", ""); - window.count_departments++; }; -function remove(id){ +document.getElementById("btnAddDevelopers").onclick = function() { + add("developers", ""); +}; + +document.getElementById("btnAddTechLeads").onclick = function() { + add("tech_leads", ""); +}; + +function remove(id) { document.getElementById(id).remove(); } @@ -114,13 +102,3 @@ function handleRadio(myRadio) { } } -document.getElementById("btnAddDevelopers").onclick = function() { - add("developers", ""); - window.count_developers++; -}; - -document.getElementById("btnAddTechLeads").onclick = function() { - add("tech_leads", ""); - window.count_tech_leads++; -}; - diff --git a/app/views/software_records/_form_general.html.erb b/app/views/software_records/_form_general.html.erb index d4a2f793..f6572d57 100644 --- a/app/views/software_records/_form_general.html.erb +++ b/app/views/software_records/_form_general.html.erb @@ -48,304 +48,184 @@ - <% if current_user.role.to_s == "root_admin" %> - <% if component.to_s == "new" %> -
- <%= form.label :departments %> + add more -
- <%= text_field_tag "software_record[departments][]", nil, required: true, class: "form-control" %> -
- Delete -
-
-
- <% else %> - <% if @software_record.departments.count != 0 %> -
- <%= form.label :departments %> + add more - <% @software_record.departments.each do |department| %> - <% if @count_departments == 2 %> -
- <%= text_field_tag "software_record[departments][]", department, required: true, class: "form-control" %> -
- Delete -
-
- <% @count_departments += 1 %> - <% else %> - <% @id = "software_record_departments_" + @count_departments.to_s %> -
- <%= text_field_tag "software_record[departments][]", department, id: "software_record_departments_", required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- <% else %> -
- <%= form.label :departments %> + add more -
- <% end %> - <% end %> - <% else %> - <% if @software_record.departments.count != 0 %> -
- <% @software_record.departments.each do |department| %> - <% if @count_departments == 2 %> - - <% @count_departments += 1 %> - <% else %> - <% @id = "software_record_departments_" + @count_departments.to_s %> - - <% end %> - <% end %> -
- <% end %> - <% end %> +<% if current_user.role.to_s == "root_admin" %> +
+ <%= form.label :departments %> + + add more - + <% if component.to_s == "new" || @software_record.departments.empty? %> +
+ <%= text_field_tag "software_record[departments][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.departments.each_with_index do |department, index| %> + <% @id = "departments#{index + 1}" %> +
+ <%= text_field_tag "software_record[departments][]", department, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+<% else %> + <% if @software_record.departments.any? %> +
+ <% @software_record.departments.each_with_index do |department, index| %> + <% @id = "departments#{index + 1}" %> + + <% end %> +
+ <% end %> +<% end %> + - - <% if current_user.role.to_s != "owner" %> - <% if component.to_s == "new" %> -
- <%= form.label :developers %> + add more -
- <%= text_field_tag "software_record[developers][]", nil, required: true, class: "form-control" %> -
- Delete -
-
-
- <% else %> - <% if @software_record.developers.count != 0 %> -
- <%= form.label :developers %> + add more - <% @software_record.developers.each do |developer| %> - <% if @count_developers == 2 %> -
- <%= text_field_tag "software_record[developers][]", developer, required: true, class: "form-control" %> -
- Delete -
-
- <% @count_developers += 1 %> - <% else %> - <% @id = "software_record_developers_" + @count_developers.to_s %> -
- <%= text_field_tag "software_record[developers][]", developer, id: "software_record_developers_", required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- <% else %> -
- <%= form.label :developers %> + add more -
- <% end %> - <% end %> - <% else %> - <% if @software_record.developers.count != 0 %> -
- <% @software_record.developers.each do |developer| %> - <% if @count_developers == 2 %> - - <% @count_developers += 1 %> - <% else %> - <% @id = "software_record_developers_" + @count_developers.to_s %> - - <% end %> - <% end %> -
- <% end %> - <% end %> + +<% if current_user.role.to_s != "owner" %> +
+ <%= form.label :developers %> + + add more + + <% if component.to_s == "new" || @software_record.developers.empty? %> +
+ <%= text_field_tag "software_record[developers][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.developers.each_with_index do |developer, index| %> + <% @id = "developers#{index + 1}" %> +
+ <%= text_field_tag "software_record[developers][]", developer, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+<% else %> + <% if @software_record.developers.any? %> +
+ <% @software_record.developers.each_with_index do |developer, index| %> + <% @id = "developers#{index + 1}" %> + + <% end %> +
+ <% end %> +<% end %> + - + +<% if current_user.role.to_s != "owner" %> +
+ <%= form.label :tech_leads %> + + add more + + <% if component.to_s == "new" || @software_record.tech_leads.empty? %> +
+ <%= text_field_tag "software_record[tech_leads][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.tech_leads.each_with_index do |tech_lead, index| %> + <% @id = "tech_leads#{index + 1}" %> +
+ <%= text_field_tag "software_record[tech_leads][]", tech_lead, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+<% else %> + <% if @software_record.tech_leads.any? %> +
+ <% @software_record.tech_leads.each_with_index do |tech_lead, index| %> + <% @id = "tech_leads#{index + 1}" %> + + <% end %> +
+ <% end %> +<% end %> + - - <% if current_user.role.to_s != "owner" %> - <% if component.to_s == "new" %> -
- <%= form.label :tech_leads %> + add more -
- <%= text_field_tag "software_record[tech_leads][]", nil, required: true, class: "form-control" %> -
- Delete -
-
-
- <% else %> - <% if @software_record.tech_leads.count != 0 %> -
- <%= form.label :tech_leads %> + add more - <% @software_record.tech_leads.each do |tech_lead| %> - <% if @count_tech_leads == 2 %> -
- <%= text_field_tag "software_record[tech_leads][]", tech_lead, required: true, class: "form-control" %> -
- Delete -
-
- <% @count_tech_leads += 1 %> - <% else %> - <% @id = "software_record_tech_leads_" + @count_tech_leads.to_s %> -
- <%= text_field_tag "software_record[tech_leads][]", tech_lead, id: "software_record_tech_leads_", required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- <% else %> -
- <%= form.label :tech_leads %> + add more -
- <% end %> - <% end %> - <% else %> - <% if @software_record.tech_leads.count != 0 %> -
- <% @software_record.tech_leads.each do |tech_lead| %> - <% if @count_tech_leads == 2 %> - - <% @count_tech_leads += 1 %> - <% else %> - <% @id = "software_record_tech_leads_" + @count_tech_leads.to_s %> - - <% end %> - <% end %> -
- <% end %> - <% end %> - - + +
+ <%= form.label "Product Lead/Contact" %> + + add more + + <% if component.to_s == "new" || @software_record.product_owners.empty? %> +
+ <%= text_field_tag "software_record[product_owners][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.product_owners.each_with_index do |product_owner, index| %> + <% @id = "product_owners#{index + 1}" %> +
+ <%= text_field_tag "software_record[product_owners][]", product_owner, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+ - + +
+ <%= form.label "Admin Users" %> + + add more + + <% if component.to_s == "new" || @software_record.admin_users.empty? %> +
+ <%= text_field_tag "software_record[admin_users][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.admin_users.each_with_index do |admin_user, index| %> + <% @id = "admin_users#{index + 1}" %> +
+ <%= text_field_tag "software_record[admin_users][]", admin_user, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+ - <% if component.to_s == "new" %> -
- <%= form.label "Product Lead/Contact" %> + add more -
- <%= text_field_tag "software_record[product_owners][]", nil, required: true, class: "form-control" %> -
- Delete -
-
-
- <% else %> - <% if @software_record.product_owners.count != 0 %> -
- <%= form.label :product_owners %> + add more - <% @software_record.product_owners.each do |product_owner| %> - <% if @count_product_owners == 2 %> -
- <%= text_field_tag "software_record[product_owners][]", product_owner, required: true, class: "form-control" %> -
- Delete -
-
- <% @count_product_owners += 1 %> - <% else %> - <% @id = "software_record_tech_leads_" + @count_product_owners.to_s %> -
- <%= text_field_tag "software_record[product_owners][]", product_owner, id: "software_record_product_owners_", required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- <% else %> -
- <%= form.label :product_owners %> + add more -
- <% end %> - <% end %> - - - - - - <% if component.to_s == "new" %> -
- <%= form.label "Admin Users" %> + add more -
- <%= text_field_tag "software_record[admin_users][]", nil, required: true, class: "form-control" %> -
- Delete -
-
-
- <% else %> - <% if @software_record.admin_users.count != 0 %> -
- <%= form.label :admin_users %> + add more - <% @software_record.admin_users.each do |admin_user| %> - <% if @count_admin_users == 2 %> -
- <%= text_field_tag "software_record[admin_users][]", admin_user, required: true, class: "form-control" %> -
- Delete -
-
- <% @count_admin_users += 1 %> - <% else %> - <% @id = "software_record_admin_users" + @count_admin_users.to_s %> -
- <%= text_field_tag "software_record[admin_users][]", admin_user, id: "software_record_admin_users", required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- <% else %> -
- <%= form.label :admin_users %> + add more -
- <% end %> - <% end %> - <% if current_user.role.to_s != "owner" %>
From 49eb8eec4aac7653aff002ad22c40f7971a32ca0 Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Mon, 15 Jul 2024 13:35:23 -0400 Subject: [PATCH 3/8] Fixes rubocop errors in config initializers. --- app/assets/javascripts/custom.js | 13 +++++++++++++ config/initializers/assets.rb | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/custom.js b/app/assets/javascripts/custom.js index 28d2047b..60a7a869 100644 --- a/app/assets/javascripts/custom.js +++ b/app/assets/javascripts/custom.js @@ -1,3 +1,16 @@ +function openNav() { + document.getElementById("mySidenav").style.visibility = "visible"; + document.getElementById("mySidenav").style.width = "250px"; + document.getElementById("main").style.marginLeft = "250px"; +} + +function closeNav() { + document.getElementById("mySidenav").style.visibility = "hidden"; + document.getElementById("mySidenav").style.width = "0"; + document.getElementById("main").style.marginLeft = "0"; +} + + window.onload = function() { window.counts = { diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index dc49f927..881741de 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -14,4 +14,4 @@ # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w( admin.js admin.css ) -Rails.application.config.assets.precompile += %w( custom.js ) +Rails.application.config.assets.precompile += %w[custom.js] From 39084425f126f2d7157ab25d4c111da8271d635f Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Mon, 15 Jul 2024 16:16:11 -0400 Subject: [PATCH 4/8] Adds spec test for mutli-value --- .../software_records/multi_value_spec.rb | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 spec/features/software_records/multi_value_spec.rb diff --git a/spec/features/software_records/multi_value_spec.rb b/spec/features/software_records/multi_value_spec.rb new file mode 100644 index 00000000..ba0bbf5b --- /dev/null +++ b/spec/features/software_records/multi_value_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.feature 'MultiValueFields', type: :feature, js: true do + let(:user) { FactoryBot.create(:admin) } + let(:software_record) { FactoryBot.create(:software_record) } + + before do + visit new_user_session_path + fill_in 'Email', with: user.email + fill_in 'Password', with: 'random1234' + click_button 'Login' + visit edit_software_record_path(software_record) + end + + scenario 'User can add and remove multiple developers' do + within('#multiple_developers') do + expect(page).to have_selector('.input-group', count: 1) + find('a', text: '+ add more').click + expect(page).to have_selector('.input-group', count: 2) + all('.input-group-append').last.click + expect(page).to have_selector('.input-group', count: 1) + end + end + + scenario 'User can add and remove multiple tech leads' do + within('#multiple_tech_leads') do + expect(page).to have_selector('.input-group', count: 1) + find('a', text: '+ add more').click + expect(page).to have_selector('.input-group', count: 2) + all('.input-group-append').last.click + expect(page).to have_selector('.input-group', count: 1) + end + end + + scenario 'User can add and remove multiple departments' do + within('#multiple_departments') do + expect(page).to have_selector('.input-group', count: 1) + find('a', text: '+ add more').click + expect(page).to have_selector('.input-group', count: 2) + all('.input-group-append').last.click + expect(page).to have_selector('.input-group', count: 1) + end + end + + scenario 'User can add and remove multiple product owners' do + within('#multiple_product_owners') do + expect(page).to have_selector('.input-group', count: 1) + find('a', text: '+ add more').click + + expect(page).to have_selector('.input-group', count: 2) + + all('.input-group-append').last.click + expect(page).to have_selector('.input-group', count: 1) + end + end + + scenario 'User can add and remove multiple admin users' do + within('#multiple_admin_users') do + expect(page).to have_selector('.input-group', count: 1) + find('a', text: '+ add more').click + + expect(page).to have_selector('.input-group', count: 2) + + all('.input-group-append').last.click + expect(page).to have_selector('.input-group', count: 1) + end + end +end From 88dfcbe7eaf8027e52390ebe65061c55d50c88aa Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Mon, 15 Jul 2024 16:27:16 -0400 Subject: [PATCH 5/8] Updates Github Actions for Selenium. --- .github/workflows/main.yml | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 02d21c10..3a6f708f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,28 +1,49 @@ name: CI GitHub Action -on: "push" -#permissions: -# contents: read +on: push jobs: test: runs-on: ubuntu-latest + services: + selenium: + image: selenium/standalone-chrome + ports: + - 4444:4444 + steps: - uses: actions/checkout@v3 + - name: Set up Ruby - # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, - # change this to (see https://github.com/ruby/setup-ruby#versioning): uses: ruby/setup-ruby@v1 with: - bundler-cache: true # runs 'bundle install' and caches installed gems automatically + ruby-version: '3.3.3' # or your preferred Ruby version + bundler-cache: true + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y xvfb libnss3-dev + gem install bundler + bundle install + - name: Run rubocop run: | bundle exec rubocop + - name: Run tests - run: bundle exec rake + env: + DISPLAY: :99.0 + run: | + Xvfb :99 -ac & + bundle exec rspec + - name: Coveralls uses: coverallsapp/github-action@v2 + - name: Brakeman linter run: bundle exec brakeman --no-exit-on-warn --no-exit-on-error + - name: 'Run Bundler Audit' run: bundle exec bundler-audit + From e36075bd68c224efedc331ca93131f5b25b0ae60 Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Wed, 17 Jul 2024 15:30:54 -0400 Subject: [PATCH 6/8] Refactors javascript assets. --- app/assets/javascripts/filtermanagement.js | 17 +++++ app/assets/javascripts/inputsanitization.js | 4 ++ .../{custom.js => multivalueinputs.js} | 71 +++++-------------- app/assets/javascripts/navigation.js | 11 +++ app/views/layouts/application.html.erb | 5 +- app/views/layouts/software_records.html.erb | 5 +- config/initializers/assets.rb | 5 +- 7 files changed, 60 insertions(+), 58 deletions(-) create mode 100644 app/assets/javascripts/filtermanagement.js create mode 100644 app/assets/javascripts/inputsanitization.js rename app/assets/javascripts/{custom.js => multivalueinputs.js} (60%) create mode 100644 app/assets/javascripts/navigation.js diff --git a/app/assets/javascripts/filtermanagement.js b/app/assets/javascripts/filtermanagement.js new file mode 100644 index 00000000..fa499f03 --- /dev/null +++ b/app/assets/javascripts/filtermanagement.js @@ -0,0 +1,17 @@ +// Specific to software_records.html.erb +function clearFilters() { + document.getElementById("vendor-record-filter").style.display = "none"; + document.getElementById("software-type-filter").style.display = "none"; + var loaded = window.location.host; + window.location = "software_records"; +} + +function handleRadio(myRadio) { + if(myRadio.value === "vendor_records") { + document.getElementById("vendor-record-filter").style.display = "block"; + document.getElementById("software-type-filter").style.display = "none"; + } else { + document.getElementById("vendor-record-filter").style.display = "none"; + document.getElementById("software-type-filter").style.display = "block"; + } +} diff --git a/app/assets/javascripts/inputsanitization.js b/app/assets/javascripts/inputsanitization.js new file mode 100644 index 00000000..3cb7bc43 --- /dev/null +++ b/app/assets/javascripts/inputsanitization.js @@ -0,0 +1,4 @@ +var createdbyfield = document.getElementsByClassName('regex-createdby')[0]; +createdbyfield.onkeyup = function() { + createdbyfield.value = createdbyfield.value.replace(/[^a-zA-Z0-9 ]/, ''); +} diff --git a/app/assets/javascripts/custom.js b/app/assets/javascripts/multivalueinputs.js similarity index 60% rename from app/assets/javascripts/custom.js rename to app/assets/javascripts/multivalueinputs.js index 60a7a869..7a671b29 100644 --- a/app/assets/javascripts/custom.js +++ b/app/assets/javascripts/multivalueinputs.js @@ -1,25 +1,12 @@ -function openNav() { - document.getElementById("mySidenav").style.visibility = "visible"; - document.getElementById("mySidenav").style.width = "250px"; - document.getElementById("main").style.marginLeft = "250px"; -} - -function closeNav() { - document.getElementById("mySidenav").style.visibility = "hidden"; - document.getElementById("mySidenav").style.width = "0"; - document.getElementById("main").style.marginLeft = "0"; -} - - window.onload = function() { window.counts = { - + developers: window.counts?.developers || 1, tech_leads: window.counts?.tech_leads || 1, departments: window.counts?.departments || 1, product_owners: window.counts?.product_owners || 1, admin_users: window.counts?.admin_users || 1 - + }; }; @@ -27,11 +14,11 @@ function add(name, value) { var count = window.counts[name]++; var elementId = name + count; var inputId = "software_record_" + name + "_" + count; - + var element = document.createElement("div"); element.className = "input-group mt-2"; element.id = elementId; - + var inputElement = document.createElement("input"); inputElement.type = "text"; inputElement.required = true; @@ -42,76 +29,50 @@ function add(name, value) { inputElement.value = value; } element.appendChild(inputElement); - + var inputGroupAppend = document.createElement("div"); inputGroupAppend.className = "input-group-append btnRemove"; element.appendChild(inputGroupAppend); - + var spanElement = document.createElement("span"); spanElement.className = "input-group-text"; - inputGroupAppend.appendChild(spanElement); - + inputGroupAppend.appendChild(spanElement); + var removeButton = document.createElement("i"); removeButton.className = "fas fa-minus remove"; removeButton.innerHTML = " Delete"; spanElement.appendChild(removeButton); - + // Update the onclick handler to directly remove the parent element inputGroupAppend.onclick = function() { element.remove(); }; - + var valued = "multiple_" + name; var multiValued = document.getElementById(valued); multiValued.appendChild(element); - - console.log("Added element with ID: " + element.id + " and input ID: " + inputId); } - + document.getElementById("btnAddProductOwners").onclick = function() { add("product_owners", ""); }; - + document.getElementById("btnAddAdminUsers").onclick = function() { add("admin_users", ""); }; - + document.getElementById("btnAddDepartments").onclick = function() { add("departments", ""); }; - + document.getElementById("btnAddDevelopers").onclick = function() { add("developers", ""); }; - + document.getElementById("btnAddTechLeads").onclick = function() { add("tech_leads", ""); }; - + function remove(id) { document.getElementById(id).remove(); } - -var createdbyfield = document.getElementsByClassName('regex-createdby')[0]; -createdbyfield.onkeyup = function() { - createdbyfield.value = createdbyfield.value.replace(/[^a-zA-Z0-9 ]/, ''); -} - -// Specific to software_records.html.erb -function clearFilters() { - document.getElementById("vendor-record-filter").style.display = "none"; - document.getElementById("software-type-filter").style.display = "none"; - var loaded = window.location.host; - window.location = "software_records"; -} - -function handleRadio(myRadio) { - if(myRadio.value === "vendor_records") { - document.getElementById("vendor-record-filter").style.display = "block"; - document.getElementById("software-type-filter").style.display = "none"; - } else { - document.getElementById("vendor-record-filter").style.display = "none"; - document.getElementById("software-type-filter").style.display = "block"; - } -} - diff --git a/app/assets/javascripts/navigation.js b/app/assets/javascripts/navigation.js new file mode 100644 index 00000000..777f8df1 --- /dev/null +++ b/app/assets/javascripts/navigation.js @@ -0,0 +1,11 @@ +function openNav() { + document.getElementById("mySidenav").style.visibility = "visible"; + document.getElementById("mySidenav").style.width = "250px"; + document.getElementById("main").style.marginLeft = "250px"; +} + +function closeNav() { + document.getElementById("mySidenav").style.visibility = "hidden"; + document.getElementById("mySidenav").style.width = "0"; + document.getElementById("main").style.marginLeft = "0"; +} diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index db4bc2c0..dbc2b4cb 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -29,7 +29,10 @@ crossorigin="anonymous"> <%= render 'shared/application_footer' %> <% end %>
- <%= javascript_include_tag 'custom' %> + <%= javascript_include_tag 'navigation' %> + <%= javascript_include_tag 'filtermanagement' %> + <%= javascript_include_tag 'inputsanitization' %> + <%= javascript_include_tag 'multivalueinputs' %> diff --git a/app/views/layouts/software_records.html.erb b/app/views/layouts/software_records.html.erb index 4369ba19..4b338990 100644 --- a/app/views/layouts/software_records.html.erb +++ b/app/views/layouts/software_records.html.erb @@ -25,7 +25,10 @@ crossorigin="anonymous"> <%= alerts %> <%= render 'shared/dashboard_footer' %> - <%= javascript_include_tag 'custom' %> + <%= javascript_include_tag 'navigation' %> + <%= javascript_include_tag 'filtermanagement' %> + <%= javascript_include_tag 'inputsanitization' %> + <%= javascript_include_tag 'multivalueinputs' %> diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 881741de..ad2ab731 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -14,4 +14,7 @@ # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w( admin.js admin.css ) -Rails.application.config.assets.precompile += %w[custom.js] +Rails.application.config.assets.precompile += %w( navigation.js ) +Rails.application.config.assets.precompile += %w( filtermanagement.js ) +Rails.application.config.assets.precompile += %w( inputsanitization.js ) +Rails.application.config.assets.precompile += %w( multivalueinputs.js ) From af65d4cfd86103a4de395e6e60d74a48546cd845 Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Tue, 23 Jul 2024 12:48:06 -0400 Subject: [PATCH 7/8] Refactors multi_value partials and javascript. --- .../software_records/_form_general.html.erb | 184 +----------------- .../_form_multi_admin_users.html.erb | 29 +++ .../_form_multi_departments.html.erb | 44 +++++ .../_form_multi_developers.html.erb | 43 ++++ .../_form_multi_product_owners.html.erb | 29 +++ .../_form_multi_tech_leads.html.erb | 41 ++++ config/initializers/assets.rb | 8 +- 7 files changed, 196 insertions(+), 182 deletions(-) create mode 100644 app/views/software_records/_form_multi_admin_users.html.erb create mode 100644 app/views/software_records/_form_multi_departments.html.erb create mode 100644 app/views/software_records/_form_multi_developers.html.erb create mode 100644 app/views/software_records/_form_multi_product_owners.html.erb create mode 100644 app/views/software_records/_form_multi_tech_leads.html.erb diff --git a/app/views/software_records/_form_general.html.erb b/app/views/software_records/_form_general.html.erb index f6572d57..14a55089 100644 --- a/app/views/software_records/_form_general.html.erb +++ b/app/views/software_records/_form_general.html.erb @@ -47,184 +47,12 @@ <%= form.select(:authentication_type, t('authentication_types'), {}, { :class => 'form-control' }) %> - -<% if current_user.role.to_s == "root_admin" %> -
- <%= form.label :departments %> - + add more - - <% if component.to_s == "new" || @software_record.departments.empty? %> -
- <%= text_field_tag "software_record[departments][]", nil, required: true, class: "form-control" %> -
- Delete -
-
- <% else %> - <% @software_record.departments.each_with_index do |department, index| %> - <% @id = "departments#{index + 1}" %> -
- <%= text_field_tag "software_record[departments][]", department, required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
-<% else %> - <% if @software_record.departments.any? %> -
- <% @software_record.departments.each_with_index do |department, index| %> - <% @id = "departments#{index + 1}" %> - - <% end %> -
- <% end %> -<% end %> - - - -<% if current_user.role.to_s != "owner" %> -
- <%= form.label :developers %> - + add more - - <% if component.to_s == "new" || @software_record.developers.empty? %> -
- <%= text_field_tag "software_record[developers][]", nil, required: true, class: "form-control" %> -
- Delete -
-
- <% else %> - <% @software_record.developers.each_with_index do |developer, index| %> - <% @id = "developers#{index + 1}" %> -
- <%= text_field_tag "software_record[developers][]", developer, required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
-<% else %> - <% if @software_record.developers.any? %> -
- <% @software_record.developers.each_with_index do |developer, index| %> - <% @id = "developers#{index + 1}" %> - - <% end %> -
- <% end %> -<% end %> - - - -<% if current_user.role.to_s != "owner" %> -
- <%= form.label :tech_leads %> - + add more - - <% if component.to_s == "new" || @software_record.tech_leads.empty? %> -
- <%= text_field_tag "software_record[tech_leads][]", nil, required: true, class: "form-control" %> -
- Delete -
-
- <% else %> - <% @software_record.tech_leads.each_with_index do |tech_lead, index| %> - <% @id = "tech_leads#{index + 1}" %> -
- <%= text_field_tag "software_record[tech_leads][]", tech_lead, required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
-<% else %> - <% if @software_record.tech_leads.any? %> -
- <% @software_record.tech_leads.each_with_index do |tech_lead, index| %> - <% @id = "tech_leads#{index + 1}" %> - - <% end %> -
- <% end %> -<% end %> - - - -
- <%= form.label "Product Lead/Contact" %> - + add more - - <% if component.to_s == "new" || @software_record.product_owners.empty? %> -
- <%= text_field_tag "software_record[product_owners][]", nil, required: true, class: "form-control" %> -
- Delete -
-
- <% else %> - <% @software_record.product_owners.each_with_index do |product_owner, index| %> - <% @id = "product_owners#{index + 1}" %> -
- <%= text_field_tag "software_record[product_owners][]", product_owner, required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- - - -
- <%= form.label "Admin Users" %> - + add more - - <% if component.to_s == "new" || @software_record.admin_users.empty? %> -
- <%= text_field_tag "software_record[admin_users][]", nil, required: true, class: "form-control" %> -
- Delete -
-
- <% else %> - <% @software_record.admin_users.each_with_index do |admin_user, index| %> - <% @id = "admin_users#{index + 1}" %> -
- <%= text_field_tag "software_record[admin_users][]", admin_user, required: true, class: "form-control" %> -
- Delete -
-
- <% end %> - <% end %> -
- - + + <%= render 'form_multi_departments', software_record: @software_record, component: component, form: form %> + <%= render 'form_multi_developers', software_record: @software_record, component: component, form: form %> + <%= render 'form_multi_tech_leads', software_record: @software_record, component: component, form: form %> + <%= render 'form_multi_product_owners', software_record: @software_record, component: component, form: form %> + <%= render 'form_multi_admin_users', software_record: @software_record, component: component, form: form %> <% if current_user.role.to_s != "owner" %> diff --git a/app/views/software_records/_form_multi_admin_users.html.erb b/app/views/software_records/_form_multi_admin_users.html.erb new file mode 100644 index 00000000..ebaff8bd --- /dev/null +++ b/app/views/software_records/_form_multi_admin_users.html.erb @@ -0,0 +1,29 @@ + +
+ <%= form.label "Admin Users" %> + + add more + + <% if component.to_s == "new" || @software_record.admin_users.empty? %> +
+ <%= text_field_tag "software_record[admin_users][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.admin_users.each_with_index do |admin_user, index| %> + <% @id = "admin_users#{index + 1}" %> +
+ <%= text_field_tag "software_record[admin_users][]", admin_user, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+ + + + + diff --git a/app/views/software_records/_form_multi_departments.html.erb b/app/views/software_records/_form_multi_departments.html.erb new file mode 100644 index 00000000..a2912545 --- /dev/null +++ b/app/views/software_records/_form_multi_departments.html.erb @@ -0,0 +1,44 @@ + +<% if current_user.role.to_s == "root_admin" %> +
+ <%= form.label :departments %> + + add more + + <% if component.to_s == "new" || @software_record.departments.empty? %> +
+ <%= text_field_tag "software_record[departments][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.departments.each_with_index do |department, index| %> + <% @id = "departments#{index + 1}" %> +
+ <%= text_field_tag "software_record[departments][]", department, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+<% else %> + <% if @software_record.departments.any? %> +
+ <% @software_record.departments.each_with_index do |department, index| %> + <% @id = "departments#{index + 1}" %> + + <% end %> +
+ <% end %> +<% end %> + + + + diff --git a/app/views/software_records/_form_multi_developers.html.erb b/app/views/software_records/_form_multi_developers.html.erb new file mode 100644 index 00000000..6bb8f308 --- /dev/null +++ b/app/views/software_records/_form_multi_developers.html.erb @@ -0,0 +1,43 @@ + +<% if current_user.role.to_s != "owner" %> +
+ <%= form.label :developers %> + + add more + + <% if component.to_s == "new" || @software_record.developers.empty? %> +
+ <%= text_field_tag "software_record[developers][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.developers.each_with_index do |developer, index| %> + <% @id = "developers#{index + 1}" %> +
+ <%= text_field_tag "software_record[developers][]", developer, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+<% else %> + <% if @software_record.developers.any? %> +
+ <% @software_record.developers.each_with_index do |developer, index| %> + <% @id = "developers#{index + 1}" %> + + <% end %> +
+ <% end %> +<% end %> + + + diff --git a/app/views/software_records/_form_multi_product_owners.html.erb b/app/views/software_records/_form_multi_product_owners.html.erb new file mode 100644 index 00000000..7bfec3c0 --- /dev/null +++ b/app/views/software_records/_form_multi_product_owners.html.erb @@ -0,0 +1,29 @@ + +
+ <%= form.label "Product Lead/Contact" %> + + add more + + <% if component.to_s == "new" || @software_record.product_owners.empty? %> +
+ <%= text_field_tag "software_record[product_owners][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.product_owners.each_with_index do |product_owner, index| %> + <% @id = "product_owners#{index + 1}" %> +
+ <%= text_field_tag "software_record[product_owners][]", product_owner, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+ + + + + diff --git a/app/views/software_records/_form_multi_tech_leads.html.erb b/app/views/software_records/_form_multi_tech_leads.html.erb new file mode 100644 index 00000000..09b7c0bc --- /dev/null +++ b/app/views/software_records/_form_multi_tech_leads.html.erb @@ -0,0 +1,41 @@ + +<% if current_user.role.to_s != "owner" %> +
+ <%= form.label :tech_leads %> + + add more + + <% if component.to_s == "new" || @software_record.tech_leads.empty? %> +
+ <%= text_field_tag "software_record[tech_leads][]", nil, required: true, class: "form-control" %> +
+ Delete +
+
+ <% else %> + <% @software_record.tech_leads.each_with_index do |tech_lead, index| %> + <% @id = "tech_leads#{index + 1}" %> +
+ <%= text_field_tag "software_record[tech_leads][]", tech_lead, required: true, class: "form-control" %> +
+ Delete +
+
+ <% end %> + <% end %> +
+<% else %> + <% if @software_record.tech_leads.any? %> +
+ <% @software_record.tech_leads.each_with_index do |tech_lead, index| %> + <% @id = "tech_leads#{index + 1}" %> + + <% end %> +
+ <% end %> +<% end %> + diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index ad2ab731..fc33fc35 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -14,7 +14,7 @@ # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w( admin.js admin.css ) -Rails.application.config.assets.precompile += %w( navigation.js ) -Rails.application.config.assets.precompile += %w( filtermanagement.js ) -Rails.application.config.assets.precompile += %w( inputsanitization.js ) -Rails.application.config.assets.precompile += %w( multivalueinputs.js ) +Rails.application.config.assets.precompile += %w[navigation.js] +Rails.application.config.assets.precompile += %w[filtermanagement.js] +Rails.application.config.assets.precompile += %w[inputsanitization.js] +Rails.application.config.assets.precompile += %w[multivalueinputs.js] From cf24615fed1076052f035fa0d285108bf93c1539 Mon Sep 17 00:00:00 2001 From: Thomas Scherz Date: Tue, 23 Jul 2024 13:11:39 -0400 Subject: [PATCH 8/8] Refactors multi_value spec to test. --- .../software_records/multi_value_spec.rb | 80 ++++++++++++++++--- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/spec/features/software_records/multi_value_spec.rb b/spec/features/software_records/multi_value_spec.rb index ba0bbf5b..283ed91a 100644 --- a/spec/features/software_records/multi_value_spec.rb +++ b/spec/features/software_records/multi_value_spec.rb @@ -18,9 +18,21 @@ within('#multiple_developers') do expect(page).to have_selector('.input-group', count: 1) find('a', text: '+ add more').click + find('a', text: '+ add more').click + + # Fill in fields with identifiable values + all('.input-group input').each_with_index do |input, index| + input.set("Developer #{index + 1}") + end + + expect(page).to have_selector('.input-group', count: 3) + + # Delete 'Developer 2' + all('.input-group-append')[1].click expect(page).to have_selector('.input-group', count: 2) - all('.input-group-append').last.click - expect(page).to have_selector('.input-group', count: 1) + expect(page).not_to have_field(with: 'Developer 2') + expect(page).to have_field(with: 'Developer 1') + expect(page).to have_field(with: 'Developer 3') end end @@ -28,9 +40,21 @@ within('#multiple_tech_leads') do expect(page).to have_selector('.input-group', count: 1) find('a', text: '+ add more').click + find('a', text: '+ add more').click + + # Fill in fields with identifiable values + all('.input-group input').each_with_index do |input, index| + input.set("Tech Lead #{index + 1}") + end + + expect(page).to have_selector('.input-group', count: 3) + + # Delete 'Tech Lead 2' + all('.input-group-append')[1].click expect(page).to have_selector('.input-group', count: 2) - all('.input-group-append').last.click - expect(page).to have_selector('.input-group', count: 1) + expect(page).not_to have_field(with: 'Tech Lead 2') + expect(page).to have_field(with: 'Tech Lead 1') + expect(page).to have_field(with: 'Tech Lead 3') end end @@ -38,9 +62,21 @@ within('#multiple_departments') do expect(page).to have_selector('.input-group', count: 1) find('a', text: '+ add more').click + find('a', text: '+ add more').click + + # Fill in fields with identifiable values + all('.input-group input').each_with_index do |input, index| + input.set("Department #{index + 1}") + end + + expect(page).to have_selector('.input-group', count: 3) + + # Delete 'Department 2' + all('.input-group-append')[1].click expect(page).to have_selector('.input-group', count: 2) - all('.input-group-append').last.click - expect(page).to have_selector('.input-group', count: 1) + expect(page).not_to have_field(with: 'Department 2') + expect(page).to have_field(with: 'Department 1') + expect(page).to have_field(with: 'Department 3') end end @@ -48,11 +84,21 @@ within('#multiple_product_owners') do expect(page).to have_selector('.input-group', count: 1) find('a', text: '+ add more').click + find('a', text: '+ add more').click - expect(page).to have_selector('.input-group', count: 2) + # Fill in fields with identifiable values + all('.input-group input').each_with_index do |input, index| + input.set("Product Owner #{index + 1}") + end - all('.input-group-append').last.click - expect(page).to have_selector('.input-group', count: 1) + expect(page).to have_selector('.input-group', count: 3) + + # Delete 'Product Owner 2' + all('.input-group-append')[1].click + expect(page).to have_selector('.input-group', count: 2) + expect(page).not_to have_field(with: 'Product Owner 2') + expect(page).to have_field(with: 'Product Owner 1') + expect(page).to have_field(with: 'Product Owner 3') end end @@ -60,11 +106,21 @@ within('#multiple_admin_users') do expect(page).to have_selector('.input-group', count: 1) find('a', text: '+ add more').click + find('a', text: '+ add more').click - expect(page).to have_selector('.input-group', count: 2) + # Fill in fields with identifiable values + all('.input-group input').each_with_index do |input, index| + input.set("Admin User #{index + 1}") + end - all('.input-group-append').last.click - expect(page).to have_selector('.input-group', count: 1) + expect(page).to have_selector('.input-group', count: 3) + + # Delete 'Admin User 2' + all('.input-group-append')[1].click + expect(page).to have_selector('.input-group', count: 2) + expect(page).not_to have_field(with: 'Admin User 2') + expect(page).to have_field(with: 'Admin User 1') + expect(page).to have_field(with: 'Admin User 3') end end end