diff --git a/front/static/js/viewHistory.js b/front/static/js/viewHistory.js index 97b4884..055011d 100644 --- a/front/static/js/viewHistory.js +++ b/front/static/js/viewHistory.js @@ -86,7 +86,7 @@ function updateSection(parsedData, saveButton) { saveButton.innerHTML = "Save"; saveButton.disabled = false; - + } // Wraps a Bootstrap form group around a field @@ -214,7 +214,7 @@ function createCollapsibleCard(sectionIdStr, sectionTitle, sectionCompleted, rul sectionState.classList.add("fas", "fa-exclamation-triangle"); } } - + // Create h2, button. Append button to h2, h2 to header, and header to card const h2 = document.createElement("h2"); h2.classList.add("mb-0"); @@ -232,7 +232,7 @@ function createCollapsibleCard(sectionIdStr, sectionTitle, sectionCompleted, rul return card; } -function createCollapsibleCardBody(form, type, sectionIdStr, sectionDescription, sectionCompleted, ruleViolations) { +function createCollapsibleCardBody(form, sectionIdStr, sectionDescription, sectionCompleted, ruleViolations) { // Create wrapper div const collapseDiv = document.createElement("div"); collapseDiv.id = sectionIdStr + "collapse"; @@ -284,7 +284,7 @@ function createCardFooter(ruleViolations) { violation.appendChild(ruleBreakText); violationMessage.appendChild(violation); } - + cardFooter.appendChild(violationMessage); return cardFooter; } @@ -295,12 +295,6 @@ function createReportForm(parsedData, type) { const accordion = document.createElement("div"); accordion.classList.add("accordion"); - //submit button - const submitButton = document.querySelector(".submit-report-button"); - if (submitButton) { - submitButton.setAttribute("data-rid", parsedData.report_pk); - } - if (type === reportType.EDIT) { modalBody = document.querySelector("#editReportModalBody"); modalLabel = document.querySelector("#editReportModalLabel"); @@ -317,6 +311,11 @@ function createReportForm(parsedData, type) { return; } + const submitButton = document.querySelector(".submit-report-button"); + if (submitButton) { + submitButton.setAttribute("data-rid", parsedData.report_pk); + } + while (modalBody.firstChild) { modalBody.removeChild(modalBody.firstChild); } @@ -339,13 +338,6 @@ function createReportForm(parsedData, type) { // Traverse the fields of this section let fields = sections[i].fields; for (let j = 0; j < fields.length; j++) { - - /* - console.log("Field label: " + fields[j].label); - console.log("Field type: " + fields[j].field_type); - console.log("Field value: " + fields[j].value); - */ - // Create a form group for each field and add it to the form form.appendChild(createFormGroup(sectionIdStr, fields[j])); } @@ -358,7 +350,7 @@ function createReportForm(parsedData, type) { form.appendChild(saveButton); // Create collapsible card body, append form to it, append card to accordion - let cardBody = createCollapsibleCardBody(form, type, sectionIdStr, + let cardBody = createCollapsibleCardBody(form, sectionIdStr, sections[i].html_description, sections[i].completed, sections[i].rule_violations); let cardFooter = createCardFooter(sections[i].rule_violations); if (cardFooter) { diff --git a/front/static/tests/qunit_tests.html b/front/static/tests/qunit_tests.html deleted file mode 100644 index b751c4a..0000000 --- a/front/static/tests/qunit_tests.html +++ /dev/null @@ -1,233 +0,0 @@ -<html> -<head> - <meta charset="utf-8"> - <title>QUnit Tests</title> - <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.9.2.css"> - <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> - <script src="../js/viewHistory.js"></script> -</head> -<body> - <div id="qunit"></div> - <div id="qunit-fixture"></div> - <script src="https://code.jquery.com/qunit/qunit-2.9.2.js"></script> - <script> - - // BEGIN createFormGroup unit tests - QUnit.module("createFormGroup"); - - // BEGIN: Test rendering of fields with type boolean - QUnit.test("boolean input group false renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "Have you taken this trip already?", - "field_name": "after_trip", - "field_type": "boolean", - "value": false - }; - - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-after_trip">Have you taken this trip already?: </label><div class="col-sm-6"><select name="after_trip" id="section-1-after_trip" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "boolean false renders as no option selected"); - - }); - - QUnit.test("boolean input group true renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "Have you taken this trip already?", - "field_name": "after_trip", - "field_type": "boolean", - "value": true - }; - - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-after_trip">Have you taken this trip already?: </label><div class="col-sm-6"><select name="after_trip" id="section-1-after_trip" class="form-control"><option value="true" selected="selected">Yes</option><option value="false">No</option></select></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "boolean true renders as yes option selected"); - }); - - // END: Test rendering of fields with type boolean - - - // BEGIN: Test rendering of fields with type date - QUnit.test("date input group renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "Departure date", - "field_name": "departure_date", - "field_type": "date", - "value": "None" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-departure_date">Departure date: </label><div class="col-sm-6"><input name="departure_date" id="section-1-departure_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); - }); - - QUnit.test("date value None", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "Departure date", - "field_name": "departure_date", - "field_type": "date", - "value": "None" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-departure_date").value; - assert.deepEqual(value, "", "date initialized to None has null value"); - }); - - QUnit.test("date value assignment", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "Departure date", - "field_name": "departure_date", - "field_type": "date", - "value": "2019-02-28" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-departure_date").value; - assert.deepEqual(value, field.value, "date input initialized to a value is rendered with that value"); - }); - // END: Test rendering of fields with type date - - // BEGIN: Test rendering of fields with type string - QUnit.test("string input group renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "City", - "field_name": "city", - "field_type": "string", - "value": "Portland" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-city">City: </label><div class="col-sm-6"><input name="city" id="section-1-city" type="text" class="form-control"></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); - }); - - QUnit.test("string value assignment", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "label": "City", - "field_name": "city", - "field_type": "string", - "value": "Portland" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-city").value; - assert.deepEqual(value, field.value, "text input initialized to a value is rendered with that value"); - }); - // END: Test rendering of fields with type date - - // BEGIN: Test rendering of fields with type decimal - QUnit.test("decimal input group renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": "0.00", - "field_type": "decimal", - "label": "Lowest fare", - "field_name": "lowest_fare" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-lowest_fare">Lowest fare: </label><div class="col-sm-6"><input name="lowest_fare" id="section-1-lowest_fare" type="number" class="form-control" step="0.01" min="0"></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); - }); - - QUnit.test("decimal input group initialized to default", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": "0.00", - "field_type": "decimal", - "label": "Lowest fare", - "field_name": "lowest_fare" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-lowest_fare").value; - assert.deepEqual(value, "", "decimal input initialized to 0.00 has null value"); - }); - - QUnit.test("decimal input group initialized to value", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": "1337", - "field_type": "decimal", - "label": "Lowest fare", - "field_name": "lowest_fare" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-lowest_fare").value; - assert.deepEqual(value, field.value, "decimal input initialized to 1337 has value 1337"); - }); - // END: Test rendering of fields with type decimal - - // BEGIN: Test rendering of fields with type integer - QUnit.test("integer input group renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": 0, - "field_type": "integer", - "label": "Number of full days of travel", - "field_name": "full_days" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-full_days">Number of full days of travel: </label><div class="col-sm-6"><input name="full_days" id="section-1-full_days" type="number" class="form-control" step="1" min="0"></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); - }); - - QUnit.test("integer input group initialized to default", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": 0, - "field_type": "integer", - "label": "Number of full days of travel", - "field_name": "full_days" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-full_days").value; - assert.deepEqual(value, "", "integer input initialized to 0 has null value"); - }); - - QUnit.test("integer input group initialized to value", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": 1234, - "field_type": "integer", - "label": "Number of full days of travel", - "field_name": "full_days" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector("#section-1-full_days").value; - assert.deepEqual(value, field.value.toString(), "integer input initialized to 1234 has string value 1234"); - }); - // END: Test rendering of fields with type integer - - - // BEGIN: Test rendering of fields with type file - QUnit.test("file input group renders", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": "", - "field_type": "file", - "label": "Screenshot of invoice", - "field_name": "invoice_screenshot" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-invoice_screenshot">Screenshot of invoice: </label><div class="col-sm-6"><input name="invoice_screenshot" id="section-1-invoice_screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div>` - assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); - }); - - QUnit.test("file input group form text assignment", function(assert) { - let sectionIdStr = "section-1-"; - let field = { - "value": "screenshot.jpg", - "field_type": "file", - "label": "Screenshot of invoice", - "field_name": "invoice_screenshot" - }; - let formGroup = createFormGroup(sectionIdStr, field); - let value = formGroup.querySelector(".form-text").innerHTML; - assert.deepEqual(value, field.value, "file input initialized to screenshot.jpg has string value screenshot.jpg"); - }); - // END: Test rendering of fields with type file - - </script> -</body> -</html> diff --git a/front/tests/qunit_tests.html b/front/tests/qunit_tests.html new file mode 100644 index 0000000..6636874 --- /dev/null +++ b/front/tests/qunit_tests.html @@ -0,0 +1,451 @@ +<html> +<head> + <meta charset="utf-8"> + <title>QUnit Tests</title> + <link rel="stylesheet" href="https://code.jquery.com/qunit/qunit-2.9.2.css"> + <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> + <script src="../static/js/viewHistory.js"></script> + <script src="testObjects.js"></script> +</head> +<body> + <div id="qunit"></div> + <div id="qunit-fixture"> + <div class="card-body"> + <div class="text-center"> + <i class="fas fa-spinner fa-3x fa-spin"></i> + </div> + <table class="table table-striped table-responsive-sm" style="visibility:hidden"> + <thead> + <tr> + <th>Title</th> + <th>Date Created</th> + <th class="d-none d-md-table-cell">Date Submitted</th> + <th>Action</th> + </tr> + </thead> + <tbody> + </tbody> + </table> + </div> + <div class="modal fade" id="newReportModal" tabindex="-1" role="dialog"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="newReportModalLabel"></h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body" id="newReportModalBody"> + <div class="text-center"> + <i class="fas fa-spinner fa-3x fa-spin"></i> + <br> + <br> + <h5>Creating Report ...</h5> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary submit-report-button">Submit Report</button> + </div> + </div> + </div> + </div> + <div class="modal fade" id="editReportModal" tabindex="-1" role="dialog"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="editReportModalLabel"></h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body" id="editReportModalBody"> + <div class="text-center"> + <i class="fas fa-spinner fa-3x fa-spin"></i> + <br> + <br> + <h5>Loading Report ...</h5> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-danger delete-report">Delete Report</button> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary submit-report-button">Submit Report</button> + </div> + </div> + </div> + </div> + </div> + <script src="https://code.jquery.com/qunit/qunit-2.9.2.js"></script> + <script> + + // BEGIN createFormGroup unit tests + QUnit.module("createFormGroup"); + + // BEGIN: Test rendering of fields with type boolean + QUnit.test("boolean input group false renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "Have you taken this trip already?", + "field_name": "after_trip", + "field_type": "boolean", + "value": false + }; + + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-after_trip">Have you taken this trip already?: </label><div class="col-sm-6"><select name="after_trip" id="section-1-after_trip" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "boolean false renders as no option selected"); + + }); + + QUnit.test("boolean input group true renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "Have you taken this trip already?", + "field_name": "after_trip", + "field_type": "boolean", + "value": true + }; + + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-after_trip">Have you taken this trip already?: </label><div class="col-sm-6"><select name="after_trip" id="section-1-after_trip" class="form-control"><option value="true" selected="selected">Yes</option><option value="false">No</option></select></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "boolean true renders as yes option selected"); + }); + + // BEGIN: Test rendering of fields with type date + QUnit.test("date input group renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "Departure date", + "field_name": "departure_date", + "field_type": "date", + "value": "None" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-departure_date">Departure date: </label><div class="col-sm-6"><input name="departure_date" id="section-1-departure_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); + }); + + QUnit.test("date value None", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "Departure date", + "field_name": "departure_date", + "field_type": "date", + "value": "None" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-departure_date").value; + assert.deepEqual(value, "", "date initialized to None has null value"); + }); + + QUnit.test("date value assignment", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "Departure date", + "field_name": "departure_date", + "field_type": "date", + "value": "2019-02-28" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-departure_date").value; + assert.deepEqual(value, field.value, "date input initialized to a value is rendered with that value"); + }); + + // BEGIN: Test rendering of fields with type string + QUnit.test("string input group renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "City", + "field_name": "city", + "field_type": "string", + "value": "Portland" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-city">City: </label><div class="col-sm-6"><input name="city" id="section-1-city" type="text" class="form-control"></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); + }); + + QUnit.test("string value assignment", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "label": "City", + "field_name": "city", + "field_type": "string", + "value": "Portland" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-city").value; + assert.deepEqual(value, field.value, "text input initialized to a value is rendered with that value"); + }); + + // BEGIN: Test rendering of fields with type decimal + QUnit.test("decimal input group renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": "0.00", + "field_type": "decimal", + "label": "Lowest fare", + "field_name": "lowest_fare" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-lowest_fare">Lowest fare: </label><div class="col-sm-6"><input name="lowest_fare" id="section-1-lowest_fare" type="number" class="form-control" step="0.01" min="0"></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); + }); + + QUnit.test("decimal input group initialized to default", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": "0.00", + "field_type": "decimal", + "label": "Lowest fare", + "field_name": "lowest_fare" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-lowest_fare").value; + assert.deepEqual(value, "", "decimal input initialized to 0.00 has null value"); + }); + + QUnit.test("decimal input group initialized to value", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": "1337", + "field_type": "decimal", + "label": "Lowest fare", + "field_name": "lowest_fare" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-lowest_fare").value; + assert.deepEqual(value, field.value, "decimal input initialized to 1337 has value 1337"); + }); + + // BEGIN: Test rendering of fields with type integer + QUnit.test("integer input group renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": 0, + "field_type": "integer", + "label": "Number of full days of travel", + "field_name": "full_days" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-full_days">Number of full days of travel: </label><div class="col-sm-6"><input name="full_days" id="section-1-full_days" type="number" class="form-control" step="1" min="0"></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); + }); + + QUnit.test("integer input group initialized to default", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": 0, + "field_type": "integer", + "label": "Number of full days of travel", + "field_name": "full_days" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-full_days").value; + assert.deepEqual(value, "", "integer input initialized to 0 has null value"); + }); + + QUnit.test("integer input group initialized to value", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": 1234, + "field_type": "integer", + "label": "Number of full days of travel", + "field_name": "full_days" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector("#section-1-full_days").value; + assert.deepEqual(value, field.value.toString(), "integer input initialized to 1234 has string value 1234"); + }); + + // BEGIN: Test rendering of fields with type file + QUnit.test("file input group renders", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": "", + "field_type": "file", + "label": "Screenshot of invoice", + "field_name": "invoice_screenshot" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let expectedHTML = `<div class="form-group row"><label class="col-sm-4 col-form" for="section-1-invoice_screenshot">Screenshot of invoice: </label><div class="col-sm-6"><input name="invoice_screenshot" id="section-1-invoice_screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div>` + assert.deepEqual(formGroup.outerHTML, expectedHTML, "formGroup string matches expectedHTML string"); + }); + + QUnit.test("file input group form text assignment", function(assert) { + let sectionIdStr = "section-1-"; + let field = { + "value": "screenshot.jpg", + "field_type": "file", + "label": "Screenshot of invoice", + "field_name": "invoice_screenshot" + }; + let formGroup = createFormGroup(sectionIdStr, field); + let value = formGroup.querySelector(".form-text").innerHTML; + assert.deepEqual(value, field.value, "file input initialized to screenshot.jpg has string value screenshot.jpg"); + }); + + + // BEGIN createCollapsibleCard unit tests + QUnit.module("createCollapsibleCard"); + + QUnit.test("incomplete section renders", function(assert) { + let sectionIdStr = "section-1-"; + let sectionTitle = "General Info"; + let sectionCompleted = false; + let ruleViolations = []; + + let card = createCollapsibleCard(sectionIdStr, sectionTitle, sectionCompleted, ruleViolations); + let expectedHTML = `<div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-1-collapse">General Info</button><i id="section-1-state"></i></h2></div></div>`; + assert.deepEqual(card.outerHTML, expectedHTML, "card html and expectedHTML are identical"); + }); + + QUnit.test("complete section with no rule violations renders", function(assert) { + let sectionIdStr = "section-1-"; + let sectionTitle = "General Info"; + let sectionCompleted = true; + let ruleViolations = []; + + let card = createCollapsibleCard(sectionIdStr, sectionTitle, sectionCompleted, ruleViolations); + let expectedHTML = `<div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-1-collapse">General Info</button><i id="section-1-state" class="fas fa-check-square"></i></h2></div></div>` + assert.deepEqual(card.outerHTML, expectedHTML, "card html and expectedHTML are identical"); + }); + + QUnit.test("complete section with a violation renders", function(assert) { + let sectionIdStr = "section-1-"; + let sectionTitle = "General Info"; + let sectionCompleted = true; + let ruleViolations = [{"label": "Fare limits", "rule_break_text": "You did a bad thing"}] + + let card = createCollapsibleCard(sectionIdStr, sectionTitle, sectionCompleted, ruleViolations); + let expectedHTML = `<div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-1-collapse">General Info</button><i id="section-1-state" class="fas fa-exclamation-triangle"></i></h2></div></div>` + assert.deepEqual(card.outerHTML, expectedHTML, "card html and expectedHTML are identical"); + }); + + + // BEGIN createCollapsibleCard unit tests + QUnit.module("createCollapsibleCardBody"); + + QUnit.test("incomplete section renders", function(assert) { + let form = document.createElement("form"); + let sectionIdStr = "section-1-"; + let sectionDescription = "<p>Section Description</p>"; + let sectionCompleted = false; + let ruleViolations = []; + let collapseDiv = createCollapsibleCardBody(form, sectionIdStr, sectionDescription, sectionCompleted, ruleViolations); + let expectedHTML = `<div id="section-1-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Section Description</p><form></form></div></div>`; + assert.deepEqual(collapseDiv.outerHTML, expectedHTML, "collapseDiv html and expectedHTML are identical"); + }); + + QUnit.test("complete section with no rule violations renders", function(assert) { + let form = document.createElement("form"); + let sectionIdStr = "section-1-"; + let sectionDescription = "<p>Section Description</p>"; + let sectionCompleted = true; + let ruleViolations = []; + let collapseDiv = createCollapsibleCardBody(form, sectionIdStr, sectionDescription, sectionCompleted, ruleViolations); + let expectedHTML = `<div id="section-1-collapse" class="collapse"><div class="card-body"><div></div><p>Section Description</p><form></form></div></div>`; + assert.deepEqual(collapseDiv.outerHTML, expectedHTML, "collapseDiv html and expectedHTML are identical"); + }); + + QUnit.test("complete section with rule violation renders", function(assert) { + let form = document.createElement("form"); + let sectionIdStr = "section-1-"; + let sectionDescription = "<p>Section Description</p>"; + let sectionCompleted = true; + let ruleViolations = [{"label": "Fare limits", "rule_break_text": "You did a bad thing"}] + let collapseDiv = createCollapsibleCardBody(form, sectionIdStr, sectionDescription, sectionCompleted, ruleViolations); + let expectedHTML = `<div id="section-1-collapse" class="collapse show"><div class="card-body"><div></div><p>Section Description</p><form></form></div></div>`; + assert.deepEqual(collapseDiv.outerHTML, expectedHTML, "collapseDiv html and expectedHTML are identical"); + }); + + + // BEGIN createCardFooter unit tests + QUnit.module("createCardFooter"); + + QUnit.test("card footer no rule violations does not render", function(assert) { + let ruleViolations = []; + let cardFooter = createCardFooter(ruleViolations); + assert.strictEqual(cardFooter, null, "cardFooter is null"); + }); + + QUnit.test("card footer with one rule violation renders", function(assert) { + let ruleViolations = [{"label": "Fare limits", "rule_break_text": "You did a bad thing"}]; + let cardFooter = createCardFooter(ruleViolations); + let expectedHTML = `<div class="card-footer"><div class="alert alert-danger"><div class="alert-heading">Rule Violations</div><hr><p><strong>Fare limits</strong><br>You did a bad thing</p></div></div>`; + assert.deepEqual(cardFooter.outerHTML, expectedHTML, "cardFooter html and expectedHTML are identical"); + }); + + QUnit.test("card footer with multiple rule violation renders", function(assert) { + let ruleViolations = [{"label": "Fare limits", "rule_break_text": "You did a bad thing"}, {"label": "Fare limits", "rule_break_text": "Now you've done it"}]; + let cardFooter = createCardFooter(ruleViolations); + let expectedHTML = `<div class="card-footer"><div class="alert alert-danger"><div class="alert-heading">Rule Violations</div><hr><p><strong>Fare limits</strong><br>You did a bad thing</p><p><strong>Fare limits</strong><br>Now you've done it</p></div></div>`; + assert.deepEqual(cardFooter.outerHTML, expectedHTML, "cardFooter html and expectedHTML are identical"); + }); + + + // BEGIN createReportForm unit tests + QUnit.module("createReportForm"); + + QUnit.test("new report renders", function(assert) { + createReportForm(testReport, reportType.NEW); + let newReportModal = document.getElementById("newReportModal"); + let expectedHTML = typeNewExpectedHTML; + assert.deepEqual(newReportModal.outerHTML, expectedHTML, "new report form and expectedHTML are identical") + }); + + QUnit.test("edit report renders", function(assert) { + createReportForm(testReport, reportType.EDIT); + let editReportModal = document.getElementById("editReportModal"); + let expectedHTML = typeEditExpectedHTML; + assert.deepEqual(editReportModal.outerHTML, expectedHTML, "edit report form and expectedHTML are identical") + }); + + QUnit.test("undefined report does not render", function(assert) { + let qunitFixture = document.getElementById("qunit-fixture"); + let expectedHTML = qunitFixture.outerHTML; + createReportForm(testReport, undefined); + assert.deepEqual(qunitFixture.outerHTML, expectedHTML, "report forms and expectedHTML are identical") + }); + + + // BEGIN displayListOfReports unit tests + QUnit.module("displayListOfReports"); + + QUnit.test("empty reports", function(assert) { + let expectedHTML = `<div class="card-body"><h5 class="text-center">No reports found.</h5></div>`; + let parsedData = {"reports": []}; + displayListOfReports(parsedData); + let cardBody = document.querySelector(".card-body"); + assert.deepEqual(cardBody.outerHTML.replace(/>\s+</g, "><"), expectedHTML, "card body and expectedHTML are identical"); + }); + + QUnit.test("one editable report", function(assert) { + let parsedData = {"reports": [{"date_created": "2019-03-05T08:00:00Z", "title": "TEST1", "reference_number": "1234", "date_submitted": "2019-03-05T08:00:00Z", "user_id": 2, "submitted": false, "report_pk": 4}]}; + let expectedHTML = displayReportsOneReportExpected; + displayListOfReports(parsedData); + let cardBody = document.querySelector(".card-body"); + assert.deepEqual(cardBody.outerHTML.replace(/>\s+</g, "><"), expectedHTML, "card body and expectedHTML are identical"); + }); + + + QUnit.test("two editable reports", function(assert) { + let parsedData = {"reports": [{"date_created": "2019-03-05T08:00:00Z", "title": "TEST1", "reference_number": "1234", "date_submitted": "2019-03-05T08:00:00Z", "user_id": 2, "submitted": false, "report_pk": 4}, {"date_created": "2019-03-05T08:00:00Z", "title": "TEST2", "reference_number": "12345", "date_submitted": "2019-03-05T08:00:00Z", "user_id": 2, "submitted": false, "report_pk": 5}]}; + let expectedHTML = displayReportsTwoReportsExpected; + displayListOfReports(parsedData); + let cardBody = document.querySelector(".card-body"); + assert.deepEqual(cardBody.outerHTML.replace(/>\s+</g, "><"), expectedHTML, "card body and expectedHTML are identical"); + }); + + QUnit.test("one viewable report", function(assert) { + let parsedData = {"reports": [{"date_created": "2019-03-05T08:00:00Z", "title": "TEST2", "reference_number": "12345", "date_submitted": "2019-03-05T08:00:00Z", "user_id": 2, "submitted": true, "report_pk": 5}]}; + let expectedHTML = displayReportsOneViewableExpected; + displayListOfReports(parsedData); + let cardBody = document.querySelector(".card-body"); + assert.deepEqual(cardBody.outerHTML.replace(/>\s+</g, "><"), expectedHTML, "card body and expectedHTML are identical"); + }); + </script> +</body> +</html> diff --git a/front/tests/testObjects.js b/front/tests/testObjects.js new file mode 100644 index 0000000..d9284d0 --- /dev/null +++ b/front/tests/testObjects.js @@ -0,0 +1,44 @@ +const testReport = {"title": "New Report 1", "report_pk": 2, "date_submitted": "2019-03-04T08:00:00Z", "sections": [{"title": "General Info", "rule_violations": [], "fields": [{"field_type": "boolean", "label": "Have you taken this trip already?", "field_name": "after_trip", "value": false}], "completed": false, "id": 10, "html_description": "<p>Each section of this report is designed to guide you through the reimbursement process. Please read through each and answer as many questions as you can that apply to you.</p><p>Be sure to click 'Save' after completing each section. Your entered data will be saved as you progress. You may also receive feedback from sections regarding policy restrictions and special requirements.</p>"}, {"title": "Pre-trip Planning", "rule_violations": [], "fields": [{"field_type": "date", "label": "Departure date", "field_name": "departure_date", "value": "None"}, {"field_type": "date", "label": "Return date", "field_name": "return_date", "value": "None"}, {"field_type": "file", "label": "Screenshot of least expensive ticket fare", "field_name": "screenshot", "value": ""}, {"field_type": "date", "label": "Date of screenshot", "field_name": "screenshot_date", "value": "None"}, {"field_type": "decimal", "label": "Lowest fare", "field_name": "lowest_fare", "value": "0.00"}, {"field_type": "decimal", "label": "Flight duration of lowest fare (hours)", "field_name": "lowest_fare_duration", "value": "0.00"}, {"field_type": "decimal", "label": "Fare of your preferred flight", "field_name": "preferred_flight_fare", "value": "0.00"}, {"field_type": "decimal", "label": "Flight duration of your preferred flight (hours)", "field_name": "preferred_flight_duration", "value": "0.00"}, {"field_type": "boolean", "label": "Is this an international flight?", "field_name": "international_flight", "value": false}], "completed": false, "id": 11, "html_description": "<p>At least 14 days before buying tickets for your trip, take a screenshot of a flight search showing the least expensive fare available for the dates you need to travel. Include fares from multiple airlines if possible. This information will be used to calculate reimbursable fare amounts.</p>"}, {"title": "Flight Info", "rule_violations": [], "fields": [{"field_type": "date", "label": "Actual departure date", "field_name": "departure_date", "value": "None"}, {"field_type": "date", "label": "Actual return date", "field_name": "return_date", "value": "None"}, {"field_type": "decimal", "label": "Ticket fare", "field_name": "fare", "value": "0.00"}, {"field_type": "file", "label": "Screenshot of confirmation of purchase", "field_name": "confirmation_screenshot", "value": ""}, {"field_type": "boolean", "label": "Was this an international flight?", "field_name": "international_flight", "value": false}], "completed": false, "id": 12, "html_description": "<p>Enter the details of your flight once you have made your purchase.</p>"}, {"title": "Hotel / Lodging", "rule_violations": [], "fields": [{"field_type": "decimal", "label": "USGSA Per diem rate", "field_name": "per_diem_rate", "value": "0.00"}, {"field_type": "decimal", "label": "Total cost for lodging", "field_name": "cost", "value": "0.00"}, {"field_type": "date", "label": "Check-in date", "field_name": "check_in_date", "value": "None"}, {"field_type": "date", "label": "Check-out date", "field_name": "check_out_date", "value": "None"}, {"field_type": "file", "label": "Screenshot of invoice", "field_name": "invoice_screenshot", "value": ""}], "completed": false, "id": 13, "html_description": "<p>Please submit a receipt from your hotel including both the total amount and the dates of your stay. Per diem rates can be found on <a href='https://www.gsa.gov/travel/plan-book/per-diem-rates' target='_blank'>the U.S. GSA website</a>.</p>"}, {"title": "Local Transportation", "rule_violations": [], "fields": [{"field_type": "decimal", "label": "Total cost of local transportation", "field_name": "cost", "value": "0.00"}], "completed": false, "id": 14, "html_description": "<p>This amount includes taxis, uber, and public transportation.</p>"}, {"title": "Per Diem and Other Expenses", "rule_violations": [], "fields": [{"field_type": "decimal", "label": "Per diem rate", "field_name": "rate", "value": "0.00"}, {"field_type": "integer", "label": "Number of full days of travel", "field_name": "full_days", "value": 0}, {"field_type": "integer", "label": "Number of partial days of travel", "field_name": "partial_days", "value": 0}, {"field_type": "decimal", "label": "Total Cost for meals and incidentals", "field_name": "cost", "value": "0.00"}], "completed": false, "id": 15, "html_description": "<p>Your per diem allowance is used to cover meals and incidental expenses. The rate for your travel destination can be found on the following websites:</p><ul><li><a href='https://www.gsa.gov/perdiem' target='_blank'>US General Serices Administration</a> for travel in the United States</li><li><a href='https://aoprals.state.gov/web920/per_diem.asp' target='_blank'>US Department of State</a> for travel outside the United States</li></ul><p>You may request up to 100% of the listed rate for a full day of travel, or 75% for a partial day of travel."}, {"title": "Payment Option - Paypal", "rule_violations": [], "fields": [{"field_type": "string", "label": "Email address used with Paypal", "field_name": "paypal_email", "value": ""}, {"field_type": "string", "label": "Preferred currency", "field_name": "preferred_currency", "value": ""}], "completed": false, "id": 16, "html_description": "<p>Complete this section if you wish to be reimbursed via Paypal. This is the preferred reimbursement method of Software Freedom Conservancy.</p>"}, {"title": "Payment Option - Check", "rule_violations": [], "fields": [{"field_type": "string", "label": "Street address", "field_name": "address_1", "value": ""}, {"field_type": "string", "label": "Street address 2", "field_name": "address_2", "value": ""}, {"field_type": "string", "label": "City", "field_name": "city", "value": ""}, {"field_type": "string", "label": "State", "field_name": "state", "value": ""}, {"field_type": "string", "label": "Zip code", "field_name": "zip", "value": ""}], "completed": false, "id": 17, "html_description": "<p>Complete this section if you wish to be reimbursed in USD via check sent by mail.</p>"}, {"title": "Payment Option - Bank Wire", "rule_violations": [], "fields": [{"field_type": "string", "label": "Full name of account holder", "field_name": "name", "value": ""}, {"field_type": "string", "label": "Street address", "field_name": "address_1", "value": ""}, {"field_type": "string", "label": "Street address 2", "field_name": "address_2", "value": ""}, {"field_type": "string", "label": "City", "field_name": "city", "value": ""}, {"field_type": "string", "label": "State", "field_name": "state", "value": ""}, {"field_type": "string", "label": "Zip code", "field_name": "zip", "value": ""}, {"field_type": "string", "label": "Account number", "field_name": "account", "value": ""}, {"field_type": "string", "label": "Preferred currency", "field_name": "currency", "value": ""}, {"field_type": "string", "label": "Bank name", "field_name": "bank_name", "value": ""}, {"field_type": "string", "label": "Bank address", "field_name": "bank_address", "value": ""}, {"field_type": "string", "label": "Bank ACH/ABA routing number (US) or SWIFT/BIC code (non-US)", "field_name": "routing_number", "value": ""}, {"field_type": "string", "label": "Additional information (see SFC policy)", "field_name": "additional_info", "value": ""}], "completed": false, "id": 18, "html_description": "<p>Complete this section if you wish to be wired the amount to your bank in your local currency. Please fill in as much of the following information as is possible. Please refer to the <a href='https://sfconservancy.org/projects/policies/conservancy-travel-policy.html' target='_blank'>SFC travel policy</a> for additional bank information required for certain countries.</p>"}], "submitted": false, "reference_number": "1234", "date_created": "2019-03-04T08:00:00Z"}; + +const typeNewExpectedHTML = `<div class="modal fade" id="newReportModal" tabindex="-1" role="dialog"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="newReportModalLabel">New Report 1</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body" id="newReportModalBody"><div class="accordion" id="newReportAccordion"><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-10-collapse">General Info</button><i id="section-10-state"></i></h2></div><div id="section-10-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Each section of this report is designed to guide you through the reimbursement process. Please read through each and answer as many questions as you can that apply to you.</p><p>Be sure to click 'Save' after completing each section. Your entered data will be saved as you progress. You may also receive feedback from sections regarding policy restrictions and special requirements.</p><form class="form section-form" id="section-10-form" data-rid="2" data-sid="10"><div class="form-group row"><label class="col-sm-4 col-form" for="section-10-after_trip">Have you taken this trip already?: </label><div class="col-sm-6"><select name="after_trip" id="section-10-after_trip" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-11-collapse">Pre-trip Planning</button><i id="section-11-state"></i></h2></div><div id="section-11-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>At least 14 days before buying tickets for your trip, take a screenshot of a flight search showing the least expensive fare available for the dates you need to travel. Include fares from multiple airlines if possible. This information will be used to calculate reimbursable fare amounts.</p><form class="form section-form" id="section-11-form" data-rid="2" data-sid="11"><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-departure_date">Departure date: </label><div class="col-sm-6"><input name="departure_date" id="section-11-departure_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-return_date">Return date: </label><div class="col-sm-6"><input name="return_date" id="section-11-return_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-screenshot">Screenshot of least expensive ticket fare: </label><div class="col-sm-6"><input name="screenshot" id="section-11-screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-screenshot_date">Date of screenshot: </label><div class="col-sm-6"><input name="screenshot_date" id="section-11-screenshot_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-lowest_fare">Lowest fare: </label><div class="col-sm-6"><input name="lowest_fare" id="section-11-lowest_fare" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-lowest_fare_duration">Flight duration of lowest fare (hours): </label><div class="col-sm-6"><input name="lowest_fare_duration" id="section-11-lowest_fare_duration" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-preferred_flight_fare">Fare of your preferred flight: </label><div class="col-sm-6"><input name="preferred_flight_fare" id="section-11-preferred_flight_fare" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-preferred_flight_duration">Flight duration of your preferred flight (hours): </label><div class="col-sm-6"><input name="preferred_flight_duration" id="section-11-preferred_flight_duration" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-international_flight">Is this an international flight?: </label><div class="col-sm-6"><select name="international_flight" id="section-11-international_flight" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-12-collapse">Flight Info</button><i id="section-12-state"></i></h2></div><div id="section-12-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Enter the details of your flight once you have made your purchase.</p><form class="form section-form" id="section-12-form" data-rid="2" data-sid="12"><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-departure_date">Actual departure date: </label><div class="col-sm-6"><input name="departure_date" id="section-12-departure_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-return_date">Actual return date: </label><div class="col-sm-6"><input name="return_date" id="section-12-return_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-fare">Ticket fare: </label><div class="col-sm-6"><input name="fare" id="section-12-fare" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-confirmation_screenshot">Screenshot of confirmation of purchase: </label><div class="col-sm-6"><input name="confirmation_screenshot" id="section-12-confirmation_screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-international_flight">Was this an international flight?: </label><div class="col-sm-6"><select name="international_flight" id="section-12-international_flight" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-13-collapse">Hotel / Lodging</button><i id="section-13-state"></i></h2></div><div id="section-13-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Please submit a receipt from your hotel including both the total amount and the dates of your stay. Per diem rates can be found on <a href="https://www.gsa.gov/travel/plan-book/per-diem-rates" target="_blank">the U.S. GSA website</a>.</p><form class="form section-form" id="section-13-form" data-rid="2" data-sid="13"><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-per_diem_rate">USGSA Per diem rate: </label><div class="col-sm-6"><input name="per_diem_rate" id="section-13-per_diem_rate" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-cost">Total cost for lodging: </label><div class="col-sm-6"><input name="cost" id="section-13-cost" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-check_in_date">Check-in date: </label><div class="col-sm-6"><input name="check_in_date" id="section-13-check_in_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-check_out_date">Check-out date: </label><div class="col-sm-6"><input name="check_out_date" id="section-13-check_out_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-invoice_screenshot">Screenshot of invoice: </label><div class="col-sm-6"><input name="invoice_screenshot" id="section-13-invoice_screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-14-collapse">Local Transportation</button><i id="section-14-state"></i></h2></div><div id="section-14-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>This amount includes taxis, uber, and public transportation.</p><form class="form section-form" id="section-14-form" data-rid="2" data-sid="14"><div class="form-group row"><label class="col-sm-4 col-form" for="section-14-cost">Total cost of local transportation: </label><div class="col-sm-6"><input name="cost" id="section-14-cost" type="number" class="form-control" step="0.01" min="0"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-15-collapse">Per Diem and Other Expenses</button><i id="section-15-state"></i></h2></div><div id="section-15-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Your per diem allowance is used to cover meals and incidental expenses. The rate for your travel destination can be found on the following websites:</p><ul><li><a href="https://www.gsa.gov/perdiem" target="_blank">US General Serices Administration</a> for travel in the United States</li><li><a href="https://aoprals.state.gov/web920/per_diem.asp" target="_blank">US Department of State</a> for travel outside the United States</li></ul><p>You may request up to 100% of the listed rate for a full day of travel, or 75% for a partial day of travel.</p><form class="form section-form" id="section-15-form" data-rid="2" data-sid="15"><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-rate">Per diem rate: </label><div class="col-sm-6"><input name="rate" id="section-15-rate" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-full_days">Number of full days of travel: </label><div class="col-sm-6"><input name="full_days" id="section-15-full_days" type="number" class="form-control" step="1" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-partial_days">Number of partial days of travel: </label><div class="col-sm-6"><input name="partial_days" id="section-15-partial_days" type="number" class="form-control" step="1" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-cost">Total Cost for meals and incidentals: </label><div class="col-sm-6"><input name="cost" id="section-15-cost" type="number" class="form-control" step="0.01" min="0"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-16-collapse">Payment Option - Paypal</button><i id="section-16-state"></i></h2></div><div id="section-16-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Complete this section if you wish to be reimbursed via Paypal. This is the preferred reimbursement method of Software Freedom Conservancy.</p><form class="form section-form" id="section-16-form" data-rid="2" data-sid="16"><div class="form-group row"><label class="col-sm-4 col-form" for="section-16-paypal_email">Email address used with Paypal: </label><div class="col-sm-6"><input name="paypal_email" id="section-16-paypal_email" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-16-preferred_currency">Preferred currency: </label><div class="col-sm-6"><input name="preferred_currency" id="section-16-preferred_currency" type="text" class="form-control"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-17-collapse">Payment Option - Check</button><i id="section-17-state"></i></h2></div><div id="section-17-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Complete this section if you wish to be reimbursed in USD via check sent by mail.</p><form class="form section-form" id="section-17-form" data-rid="2" data-sid="17"><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-address_1">Street address: </label><div class="col-sm-6"><input name="address_1" id="section-17-address_1" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-address_2">Street address 2: </label><div class="col-sm-6"><input name="address_2" id="section-17-address_2" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-city">City: </label><div class="col-sm-6"><input name="city" id="section-17-city" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-state">State: </label><div class="col-sm-6"><input name="state" id="section-17-state" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-zip">Zip code: </label><div class="col-sm-6"><input name="zip" id="section-17-zip" type="text" class="form-control"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-18-collapse">Payment Option - Bank Wire</button><i id="section-18-state"></i></h2></div><div id="section-18-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Complete this section if you wish to be wired the amount to your bank in your local currency. Please fill in as much of the following information as is possible. Please refer to the <a href="https://sfconservancy.org/projects/policies/conservancy-travel-policy.html" target="_blank">SFC travel policy</a> for additional bank information required for certain countries.</p><form class="form section-form" id="section-18-form" data-rid="2" data-sid="18"><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-name">Full name of account holder: </label><div class="col-sm-6"><input name="name" id="section-18-name" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-address_1">Street address: </label><div class="col-sm-6"><input name="address_1" id="section-18-address_1" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-address_2">Street address 2: </label><div class="col-sm-6"><input name="address_2" id="section-18-address_2" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-city">City: </label><div class="col-sm-6"><input name="city" id="section-18-city" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-state">State: </label><div class="col-sm-6"><input name="state" id="section-18-state" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-zip">Zip code: </label><div class="col-sm-6"><input name="zip" id="section-18-zip" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-account">Account number: </label><div class="col-sm-6"><input name="account" id="section-18-account" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-currency">Preferred currency: </label><div class="col-sm-6"><input name="currency" id="section-18-currency" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-bank_name">Bank name: </label><div class="col-sm-6"><input name="bank_name" id="section-18-bank_name" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-bank_address">Bank address: </label><div class="col-sm-6"><input name="bank_address" id="section-18-bank_address" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-routing_number">Bank ACH/ABA routing number (US) or SWIFT/BIC code (non-US): </label><div class="col-sm-6"><input name="routing_number" id="section-18-routing_number" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-additional_info">Additional information (see SFC policy): </label><div class="col-sm-6"><input name="additional_info" id="section-18-additional_info" type="text" class="form-control"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div></div></div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary submit-report-button" data-rid="2">Submit Report</button> + </div> + </div> + </div> + </div>`; + +const typeEditExpectedHTML = `<div class="modal fade" id="editReportModal" tabindex="-1" role="dialog"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="editReportModalLabel">New Report 1</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body" id="editReportModalBody"><div class="accordion" id="editReportAccordion"><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-10-collapse">General Info</button><i id="section-10-state"></i></h2></div><div id="section-10-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Each section of this report is designed to guide you through the reimbursement process. Please read through each and answer as many questions as you can that apply to you.</p><p>Be sure to click 'Save' after completing each section. Your entered data will be saved as you progress. You may also receive feedback from sections regarding policy restrictions and special requirements.</p><form class="form section-form" id="section-10-form" data-rid="2" data-sid="10"><div class="form-group row"><label class="col-sm-4 col-form" for="section-10-after_trip">Have you taken this trip already?: </label><div class="col-sm-6"><select name="after_trip" id="section-10-after_trip" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-11-collapse">Pre-trip Planning</button><i id="section-11-state"></i></h2></div><div id="section-11-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>At least 14 days before buying tickets for your trip, take a screenshot of a flight search showing the least expensive fare available for the dates you need to travel. Include fares from multiple airlines if possible. This information will be used to calculate reimbursable fare amounts.</p><form class="form section-form" id="section-11-form" data-rid="2" data-sid="11"><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-departure_date">Departure date: </label><div class="col-sm-6"><input name="departure_date" id="section-11-departure_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-return_date">Return date: </label><div class="col-sm-6"><input name="return_date" id="section-11-return_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-screenshot">Screenshot of least expensive ticket fare: </label><div class="col-sm-6"><input name="screenshot" id="section-11-screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-screenshot_date">Date of screenshot: </label><div class="col-sm-6"><input name="screenshot_date" id="section-11-screenshot_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-lowest_fare">Lowest fare: </label><div class="col-sm-6"><input name="lowest_fare" id="section-11-lowest_fare" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-lowest_fare_duration">Flight duration of lowest fare (hours): </label><div class="col-sm-6"><input name="lowest_fare_duration" id="section-11-lowest_fare_duration" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-preferred_flight_fare">Fare of your preferred flight: </label><div class="col-sm-6"><input name="preferred_flight_fare" id="section-11-preferred_flight_fare" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-preferred_flight_duration">Flight duration of your preferred flight (hours): </label><div class="col-sm-6"><input name="preferred_flight_duration" id="section-11-preferred_flight_duration" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-11-international_flight">Is this an international flight?: </label><div class="col-sm-6"><select name="international_flight" id="section-11-international_flight" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-12-collapse">Flight Info</button><i id="section-12-state"></i></h2></div><div id="section-12-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Enter the details of your flight once you have made your purchase.</p><form class="form section-form" id="section-12-form" data-rid="2" data-sid="12"><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-departure_date">Actual departure date: </label><div class="col-sm-6"><input name="departure_date" id="section-12-departure_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-return_date">Actual return date: </label><div class="col-sm-6"><input name="return_date" id="section-12-return_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-fare">Ticket fare: </label><div class="col-sm-6"><input name="fare" id="section-12-fare" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-confirmation_screenshot">Screenshot of confirmation of purchase: </label><div class="col-sm-6"><input name="confirmation_screenshot" id="section-12-confirmation_screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-12-international_flight">Was this an international flight?: </label><div class="col-sm-6"><select name="international_flight" id="section-12-international_flight" class="form-control"><option value="true">Yes</option><option value="false" selected="selected">No</option></select></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-13-collapse">Hotel / Lodging</button><i id="section-13-state"></i></h2></div><div id="section-13-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Please submit a receipt from your hotel including both the total amount and the dates of your stay. Per diem rates can be found on <a href="https://www.gsa.gov/travel/plan-book/per-diem-rates" target="_blank">the U.S. GSA website</a>.</p><form class="form section-form" id="section-13-form" data-rid="2" data-sid="13"><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-per_diem_rate">USGSA Per diem rate: </label><div class="col-sm-6"><input name="per_diem_rate" id="section-13-per_diem_rate" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-cost">Total cost for lodging: </label><div class="col-sm-6"><input name="cost" id="section-13-cost" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-check_in_date">Check-in date: </label><div class="col-sm-6"><input name="check_in_date" id="section-13-check_in_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-check_out_date">Check-out date: </label><div class="col-sm-6"><input name="check_out_date" id="section-13-check_out_date" type="date" placeholder="mm-dd-yyyy" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-13-invoice_screenshot">Screenshot of invoice: </label><div class="col-sm-6"><input name="invoice_screenshot" id="section-13-invoice_screenshot" type="file" class="form-control-file"><p class="form-text"></p></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-14-collapse">Local Transportation</button><i id="section-14-state"></i></h2></div><div id="section-14-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>This amount includes taxis, uber, and public transportation.</p><form class="form section-form" id="section-14-form" data-rid="2" data-sid="14"><div class="form-group row"><label class="col-sm-4 col-form" for="section-14-cost">Total cost of local transportation: </label><div class="col-sm-6"><input name="cost" id="section-14-cost" type="number" class="form-control" step="0.01" min="0"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-15-collapse">Per Diem and Other Expenses</button><i id="section-15-state"></i></h2></div><div id="section-15-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Your per diem allowance is used to cover meals and incidental expenses. The rate for your travel destination can be found on the following websites:</p><ul><li><a href="https://www.gsa.gov/perdiem" target="_blank">US General Serices Administration</a> for travel in the United States</li><li><a href="https://aoprals.state.gov/web920/per_diem.asp" target="_blank">US Department of State</a> for travel outside the United States</li></ul><p>You may request up to 100% of the listed rate for a full day of travel, or 75% for a partial day of travel.</p><form class="form section-form" id="section-15-form" data-rid="2" data-sid="15"><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-rate">Per diem rate: </label><div class="col-sm-6"><input name="rate" id="section-15-rate" type="number" class="form-control" step="0.01" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-full_days">Number of full days of travel: </label><div class="col-sm-6"><input name="full_days" id="section-15-full_days" type="number" class="form-control" step="1" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-partial_days">Number of partial days of travel: </label><div class="col-sm-6"><input name="partial_days" id="section-15-partial_days" type="number" class="form-control" step="1" min="0"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-15-cost">Total Cost for meals and incidentals: </label><div class="col-sm-6"><input name="cost" id="section-15-cost" type="number" class="form-control" step="0.01" min="0"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-16-collapse">Payment Option - Paypal</button><i id="section-16-state"></i></h2></div><div id="section-16-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Complete this section if you wish to be reimbursed via Paypal. This is the preferred reimbursement method of Software Freedom Conservancy.</p><form class="form section-form" id="section-16-form" data-rid="2" data-sid="16"><div class="form-group row"><label class="col-sm-4 col-form" for="section-16-paypal_email">Email address used with Paypal: </label><div class="col-sm-6"><input name="paypal_email" id="section-16-paypal_email" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-16-preferred_currency">Preferred currency: </label><div class="col-sm-6"><input name="preferred_currency" id="section-16-preferred_currency" type="text" class="form-control"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-17-collapse">Payment Option - Check</button><i id="section-17-state"></i></h2></div><div id="section-17-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Complete this section if you wish to be reimbursed in USD via check sent by mail.</p><form class="form section-form" id="section-17-form" data-rid="2" data-sid="17"><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-address_1">Street address: </label><div class="col-sm-6"><input name="address_1" id="section-17-address_1" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-address_2">Street address 2: </label><div class="col-sm-6"><input name="address_2" id="section-17-address_2" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-city">City: </label><div class="col-sm-6"><input name="city" id="section-17-city" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-state">State: </label><div class="col-sm-6"><input name="state" id="section-17-state" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-17-zip">Zip code: </label><div class="col-sm-6"><input name="zip" id="section-17-zip" type="text" class="form-control"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div><div class="card"><div class="card-header"><h2 class="mb-0"><button class="btn btn-link" type="button" data-toggle="collapse" data-target="#section-18-collapse">Payment Option - Bank Wire</button><i id="section-18-state"></i></h2></div><div id="section-18-collapse" class="collapse show"><div class="card-body"><div class="alert alert-danger section-alert">This section is not complete</div><p>Complete this section if you wish to be wired the amount to your bank in your local currency. Please fill in as much of the following information as is possible. Please refer to the <a href="https://sfconservancy.org/projects/policies/conservancy-travel-policy.html" target="_blank">SFC travel policy</a> for additional bank information required for certain countries.</p><form class="form section-form" id="section-18-form" data-rid="2" data-sid="18"><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-name">Full name of account holder: </label><div class="col-sm-6"><input name="name" id="section-18-name" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-address_1">Street address: </label><div class="col-sm-6"><input name="address_1" id="section-18-address_1" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-address_2">Street address 2: </label><div class="col-sm-6"><input name="address_2" id="section-18-address_2" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-city">City: </label><div class="col-sm-6"><input name="city" id="section-18-city" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-state">State: </label><div class="col-sm-6"><input name="state" id="section-18-state" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-zip">Zip code: </label><div class="col-sm-6"><input name="zip" id="section-18-zip" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-account">Account number: </label><div class="col-sm-6"><input name="account" id="section-18-account" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-currency">Preferred currency: </label><div class="col-sm-6"><input name="currency" id="section-18-currency" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-bank_name">Bank name: </label><div class="col-sm-6"><input name="bank_name" id="section-18-bank_name" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-bank_address">Bank address: </label><div class="col-sm-6"><input name="bank_address" id="section-18-bank_address" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-routing_number">Bank ACH/ABA routing number (US) or SWIFT/BIC code (non-US): </label><div class="col-sm-6"><input name="routing_number" id="section-18-routing_number" type="text" class="form-control"></div></div><div class="form-group row"><label class="col-sm-4 col-form" for="section-18-additional_info">Additional information (see SFC policy): </label><div class="col-sm-6"><input name="additional_info" id="section-18-additional_info" type="text" class="form-control"></div></div><button type="submit" class="btn btn-primary save-section">Save</button></form></div></div></div></div></div> + <div class="modal-footer"> + <button type="button" class="btn btn-danger delete-report" data-rid="2">Delete Report</button> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary submit-report-button">Submit Report</button> + </div> + </div> + </div> + </div>`; + +const displayReportsOneReportExpected = `<div class="card-body"><table class="table table-striped table-responsive-sm" style="visibility: visible;"><thead><tr><th>Title</th><th>Date Created</th><th class="d-none d-md-table-cell">Date Submitted</th><th>Action</th></tr></thead><tbody><tr><td>TEST1</td><td>3/5/2019</td><td class="d-none d-md-table-cell">TBD</td><td><button type="submit" data-rid="4" class="btn btn-primary edit-report-button" data-toggle="modal" data-target="#editReportModal">Edit</button></td></tr></tbody></table></div>`; + +const displayReportsTwoReportsExpected = `<div class="card-body"><table class="table table-striped table-responsive-sm" style="visibility: visible;"><thead><tr><th>Title</th><th>Date Created</th><th class="d-none d-md-table-cell">Date Submitted</th><th>Action</th></tr></thead><tbody><tr><td>TEST1</td><td>3/5/2019</td><td class="d-none d-md-table-cell">TBD</td><td><button type="submit" data-rid="4" class="btn btn-primary edit-report-button" data-toggle="modal" data-target="#editReportModal">Edit</button></td></tr><tr><td>TEST2</td><td>3/5/2019</td><td class="d-none d-md-table-cell">TBD</td><td><button type="submit" data-rid="5" class="btn btn-primary edit-report-button" data-toggle="modal" data-target="#editReportModal">Edit</button></td></tr></tbody></table></div>`; + +const displayReportsOneViewableExpected = `<div class="card-body"><table class="table table-striped table-responsive-sm" style="visibility: visible;"><thead><tr><th>Title</th><th>Date Created</th><th class="d-none d-md-table-cell">Date Submitted</th><th>Action</th></tr></thead><tbody><tr><td>TEST2</td><td>3/5/2019</td><td class="d-none d-md-table-cell">3/5/2019</td><td><button type="submit" data-rid="5" class="btn btn-success view-report-button" data-toggle="modal" data-target="#viewReportModal">View</button></td></tr></tbody></table></div>`;