diff --git a/.github/workflows/tethys.yml b/.github/workflows/tethys.yml index 984eb7c7a..3b4db6e6b 100644 --- a/.github/workflows/tethys.yml +++ b/.github/workflows/tethys.yml @@ -92,6 +92,42 @@ jobs: conda activate tethys coveralls --service=github + frontend-tests: + name: Frontend Tests + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Set Up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Set Up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install Tethys and Dependencies + run: | + + bash scripts/install_tethys.sh --partial-tethys-install meds -n tethys -s $PWD -x -d 5.1 --python-version 3.12 + . ~/miniconda/etc/profile.d/conda.sh + conda activate tethys + python -m pip install --upgrade pip + + - name: Install Dependencies + run: npm install + working-directory: tests/js_tests + + - name: Run Tests + run: | + . ~/miniconda/etc/profile.d/conda.sh + conda activate tethys + npm test + working-directory: tests/js_tests + docker-build: name: Docker Build (${{ matrix.platform }}, ${{ matrix.django-version }}, ${{ matrix.python-version }}) runs-on: ${{ matrix.platform }} diff --git a/.gitignore b/.gitignore index da65bfd81..697210fde 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,7 @@ tethys_portal/_version.py # Required for docs build git-lfs-*/* conda.recipe/meta.yaml + +jest_coverage/ +package-lock.json +tests/js_tests/rendered_templates \ No newline at end of file diff --git a/tests/js_tests/.babelrc b/tests/js_tests/.babelrc new file mode 100644 index 000000000..ff3059c3f --- /dev/null +++ b/tests/js_tests/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["@babel/preset-env"] +} \ No newline at end of file diff --git a/tests/js_tests/__mocks__/cesium.js b/tests/js_tests/__mocks__/cesium.js new file mode 100644 index 000000000..2b728ba32 --- /dev/null +++ b/tests/js_tests/__mocks__/cesium.js @@ -0,0 +1,46 @@ +module.exports = { + Viewer: jest.fn().mockImplementation(() => ({ + scene: { + globe: {}, + primitives: { add: jest.fn() }, + }, + camera: { + setView: jest.fn(), + flyTo: jest.fn(), + lookAt: jest.fn(), + lookAtTransform: jest.fn(), + viewBoundingSphere: jest.fn(), + }, + imageryLayers: { addImageryProvider: jest.fn() }, + terrainProvider: jest.fn(), + entities: { add: jest.fn() }, + clock: {}, + dataSources: { add: jest.fn() }, + trackedEntity: null, + })), + Ion: { defaultAccessToken: "mock_token" }, + ClockViewModel: jest.fn(), + WebMapServiceImageryProvider: jest.fn(), + JulianDate: { + fromIso8601: jest.fn(), + toIso8601: jest.fn(), + }, + GeoJsonDataSource: { + load: jest.fn(), + }, + CzmlDataSource: { + load: jest.fn(), + }, + TimeIntervalCollection: { + fromIso8601DateArray: jest.fn(), + }, + Cartesian3: jest.fn(), + Color: jest.fn(), + HorizontalOrigin: {}, + VerticalOrigin: {}, + PointGraphics: jest.fn(), + Material: { + fromType: jest.fn(), + }, + }; + \ No newline at end of file diff --git a/tests/js_tests/gizmos/datatable_view.test.js b/tests/js_tests/gizmos/datatable_view.test.js new file mode 100644 index 000000000..56778b3bd --- /dev/null +++ b/tests/js_tests/gizmos/datatable_view.test.js @@ -0,0 +1,63 @@ +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; +const { screen } = require("@testing-library/dom"); + +import $ from "jquery"; + +import DataTable from "datatables.net"; +$.fn.DataTable = DataTable; + +import TETHYS_DATATABLE_VIEW from "../../../tethys_gizmos/static/tethys_gizmos/js/datatable_view.js"; + +global.TETHYS_DATATABLE_VIEW = TETHYS_DATATABLE_VIEW; + +global.Node = window.Node; +global.Option = window.Option || function Option() {}; + +let renderedHtml = ''; + +const DATATABLE_VIEW_ID = "test_datatable_view_id"; + +beforeAll(() => { + const templateName = "tethys_gizmos/gizmos/datatable_view.html"; + const context = JSON.stringify({ + title: "Testing the datatable view gizmo", + id: DATATABLE_VIEW_ID, + + column_names: ["Column 1", "Column 2", "Column 3"], + rows: [ + ["Row 1 Column 1", "Row 1 Column 2", "Row 1 Column 3"], + ["Row 2 Column 1", "Row 2 Column 2", "Row 2 Column 3"], + ["Row 3 Column 1", "Row 3 Column 2", "Row 3 Column 3"], + ] + + }); + + execSync(`python render_template.py ${templateName} '${context}' `, { stdio: "inherit" }); + + const outputPath = path.resolve("./rendered_templates/test_datatable_view_output.html"); + renderedHtml = fs.readFileSync(outputPath, "utf8"); +}); + +beforeEach(() => { + document.body.innerHTML = renderedHtml; + + // Initialize datatable view + TETHYS_DATATABLE_VIEW.initTableView(".data_table_gizmo_view"); +}); + +test("Gizmo renders correctly", () => { + expect(screen.getByText("Column 1")).toBeInTheDocument(); + expect(screen.getByText("Column 2")).toBeInTheDocument(); + expect(screen.getByText("Column 3")).toBeInTheDocument(); + expect(screen.getByText("Row 1 Column 1")).toBeInTheDocument(); + expect(screen.getByText("Row 1 Column 2")).toBeInTheDocument(); + expect(screen.getByText("Row 1 Column 3")).toBeInTheDocument(); +}); + +test("Datatable is initialized", () => { + const dataTable = document.querySelector(".data_table_gizmo_view"); + expect(dataTable).toHaveClass("dataTable"); +}); + diff --git a/tests/js_tests/gizmos/range_slider.test.js b/tests/js_tests/gizmos/range_slider.test.js new file mode 100644 index 000000000..f689b01f7 --- /dev/null +++ b/tests/js_tests/gizmos/range_slider.test.js @@ -0,0 +1,57 @@ +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; +import { screen, fireEvent } from "@testing-library/dom"; +import "@testing-library/jest-dom"; +import $ from "jquery"; + +import TETHYS_RANGE_SLIDER from "../../../tethys_gizmos/static/tethys_gizmos/js/range_slider.js"; + +global.TETHYS_RANGE_SLIDER = TETHYS_RANGE_SLIDER; + +let renderedHtml = ""; +const RANGE_SLIDER_ID = "test-range-slider"; + +beforeAll(() => { + const templateName = "tethys_gizmos/gizmos/range_slider.html"; + const context = JSON.stringify({ + name: RANGE_SLIDER_ID, + display_text: "Select Range", + min: 0, + max: 100, + step: 5, + initial: 50, + }); + + // Render the template with the context + execSync(`python render_template.py ${templateName} '${context}' `, { stdio: "inherit" }); + + const outputPath = path.resolve("./rendered_templates/test_range_slider_output.html"); + + // Read the rendered HTML + renderedHtml = fs.readFileSync(outputPath, "utf8"); +}); + +beforeEach(() => { + document.body.innerHTML = renderedHtml; + + // Initialize range slider and add event listeners + TETHYS_RANGE_SLIDER.init_range_sliders(); +}); + +test("Gizmo renders correctly", () => { + expect(screen.getByLabelText("Select Range")).toBeInTheDocument(); + expect(screen.getByRole("slider")).toBeInTheDocument(); +}); + +test("Range slider updates display text", () => { + const rangeSliderInput = document.getElementById(RANGE_SLIDER_ID); + const rangeSliderDisplay = rangeSliderInput.nextElementSibling; + + // Test for initial value + expect(rangeSliderDisplay).toHaveTextContent("50"); + + // Test for updated value with input + fireEvent.input(rangeSliderInput, { target: { value: 75 } }); + expect(rangeSliderDisplay).toHaveTextContent("75"); +}); \ No newline at end of file diff --git a/tests/js_tests/gizmos/select_input.test.js b/tests/js_tests/gizmos/select_input.test.js new file mode 100644 index 000000000..4f85a8f8e --- /dev/null +++ b/tests/js_tests/gizmos/select_input.test.js @@ -0,0 +1,64 @@ +import { execSync } from "child_process"; +import path from "path"; +import fs from "fs"; + +const { screen } = require("@testing-library/dom"); +import userEvent from "@testing-library/user-event"; + +import TETHYS_SELECT_INPUT from "../../../tethys_gizmos/static/tethys_gizmos/js/select_input.js"; + +import $ from "jquery"; +global.$ = $; +global.jQuery = $; + +$.fn.select2 = jest.fn().mockImplementation(function () { + return this; +}); + +let renderedHtml = ""; + +beforeAll(() => { + const templateName = "tethys_gizmos/gizmos/select_input.html"; + const context = JSON.stringify({ + title: "Testing the select input gizmo", + id: "test_select_input_id", + options: [ + ["Option 1", "option1"], + ["Option 2", "option2"], + ["Option 3", "option3"], + ], + initial: "option2", + display_text: "Choose an Option", + name: "test_selector" + }); + + execSync(`python render_template.py ${templateName} '${context}'`, { stdio: "inherit" }); + const outputPath = path.resolve("./rendered_templates/test_select_input_output.html"); + renderedHtml = fs.readFileSync(outputPath, "utf8"); +}) + +beforeEach(() => { + document.body.innerHTML = renderedHtml; + TETHYS_SELECT_INPUT.initSelectInput(".tethys-select2"); +}); + +test("Gizmo renders correctly", () => { + expect(screen.getByText("Option 1")).toBeInTheDocument(); + expect(screen.getByText("Option 2")).toBeInTheDocument(); + expect(screen.getByText("Option 3")).toBeInTheDocument(); +}); + +test("The initially selected value is visible to the user", () => { + const select = screen.getByLabelText("Choose an Option"); + expect(select).toHaveDisplayValue("Option 2"); +}); + + +test("User can select a different option", async () => { + const user = userEvent.setup(); + const select = screen.getByLabelText("Choose an Option"); + + await user.selectOptions(select, "option3"); + + expect(select).toHaveDisplayValue("Option 3"); +}); \ No newline at end of file diff --git a/tests/js_tests/gizmos/slide_sheet.test.js b/tests/js_tests/gizmos/slide_sheet.test.js new file mode 100644 index 000000000..a38edb400 --- /dev/null +++ b/tests/js_tests/gizmos/slide_sheet.test.js @@ -0,0 +1,87 @@ +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; +const { screen, fireEvent } = require("@testing-library/dom"); + +import SLIDE_SHEET from "../../../tethys_gizmos/static/tethys_gizmos/js/slide_sheet.js" + +window.SLIDE_SHEET = SLIDE_SHEET; + +let renderedHtml = ''; + +const SLIDE_SHEET_ID = "test_slide_sheet_id" + +function simulateShowClassStyling() { + // Simulate the CSS class 'show' to display or hide the slide sheet + // To be used in the tests any time a slide sheet is opened or closed + // manually or with a simulated button press + document.querySelectorAll('.slide-sheet').forEach((element) => { + if (element.classList.contains('show')) { + element.style.display = 'block'; + } + else { + element.style.display = 'none'; + } + }); +} + +beforeAll(() => { + // Render the template using Python script with a provided context + const templateName = "tethys_gizmos/gizmos/slide_sheet.html"; + const context = JSON.stringify({ + title: "Testing the slide sheet gizmo", + id: SLIDE_SHEET_ID, + content_template: "test_template.html" + }); + execSync(`python render_template.py ${templateName} '${context}' `, { stdio: "inherit" }); + // Read the rendered HTML file + const outputPath = path.resolve("./rendered_templates/test_slide_sheet_output.html"); + renderedHtml = fs.readFileSync(outputPath, "utf8"); +}) + +beforeEach(() => { + // Set up the document body with the rendered HTML before each test runs + document.body.innerHTML = renderedHtml; +}); + +test("Gizmo renders correctly", () => { + const sheet = document.getElementById(SLIDE_SHEET_ID); + expect(sheet).toBeInTheDocument(); + expect(sheet).toHaveClass("slide-sheet"); +}); + +test("Clicking the open button should show the slide sheet", async () => { + const sheet = document.getElementById(SLIDE_SHEET_ID); + // Make sure the sheet is not visible to start off + expect(sheet).not.toBeVisible(); + // Add a button to open the slide sheet + const button = document.createElement("button"); + button.className = "btn-open"; + button.textContent = "Open Slide Sheet"; + document.body.appendChild(button); + // Add an event listener to the button to open the slide sheet + const openButton = screen.getByText("Open Slide Sheet"); + openButton.addEventListener("click", () => { + SLIDE_SHEET.open(SLIDE_SHEET_ID); + }); + fireEvent.click(openButton); + simulateShowClassStyling(); + // Check that the slide sheet is now visible + expect(sheet).toBeVisible(); +}); + + +test("Clicking the close button should hide the slide sheet", async () => { + // Open the slide sheet first + SLIDE_SHEET.open(SLIDE_SHEET_ID); + simulateShowClassStyling(); + const sheet = document.getElementById(SLIDE_SHEET_ID); + // Make sure the sheet is visible to start off + expect(sheet).toBeVisible(); + // Now close it + const closeButton = document.querySelector(".btn-close"); + fireEvent.click(closeButton); + simulateShowClassStyling(); + // Check that the sheet is no longer visible + expect(sheet).not.toBeVisible(); +}); \ No newline at end of file diff --git a/tests/js_tests/gizmos/toggle_switch.test.js b/tests/js_tests/gizmos/toggle_switch.test.js new file mode 100644 index 000000000..2214cfa9d --- /dev/null +++ b/tests/js_tests/gizmos/toggle_switch.test.js @@ -0,0 +1,68 @@ +import { execSync } from "child_process"; +import fs from "fs"; +import path from "path"; +const { screen, fireEvent } = require("@testing-library/dom"); + +import TOGGLE_SWITCH from "../../../tethys_gizmos/static/tethys_gizmos/js/toggle_switch.js" + +window.TOGGLE_SWITCH = TOGGLE_SWITCH; + +import $ from "jquery"; +global.$ = $; +global.jQuery = $; +$.fn.bootstrapSwitch = jest.fn(); + +let renderedHtml = ''; + +beforeAll(() => { + // Render the template using Python script with a provided context + const templateName = "tethys_gizmos/gizmos/toggle_switch.html"; + const context = JSON.stringify({ + name: "test_toggle_switch", + display_text: "Test Toggle Switch", + on_label: "On Label Text", + off_label: "Off Label Text", + initial: false + }); + execSync(`python render_template.py ${templateName} '${context}' `, { stdio: "inherit" }); + // Read the rendered HTML file + const outputPath = path.resolve("./rendered_templates/test_toggle_switch_output.html"); + renderedHtml = fs.readFileSync(outputPath, "utf8"); +}); + +beforeEach(() => { + // Set up the document body with the rendered HTML before each test runs + document.body.innerHTML = renderedHtml; + + // Initialize the toggle switch + TOGGLE_SWITCH.initToggleSwitch(".bootstrap-switch"); +}); + +test("Gizmo renders correctly", () => { + const toggleSwitch = screen.getByLabelText("Test Toggle Switch"); + expect(toggleSwitch).toBeInTheDocument(); +}); + +test("Toggle switch is unchecked by default", () => { + const toggleInput = screen.getByLabelText("Test Toggle Switch"); + expect(toggleInput).not.toBeChecked(); +}); + +test("Toggle switch initialization calls bootstrapSwitch", () => { + expect($.fn.bootstrapSwitch).toHaveBeenCalled(); +}); + +test("User can toggle the switch", () => { + const toggleInput = screen.getByLabelText("Test Toggle Switch"); + + // Check if the toggle switch is initially unchecked + expect(toggleInput).not.toBeChecked(); + + // Simulate click + fireEvent.click(toggleInput); + expect(toggleInput).toBeChecked(); + + // Simulate click again + fireEvent.click(toggleInput); + expect(toggleInput).not.toBeChecked(); +}); \ No newline at end of file diff --git a/tests/js_tests/jest.config.js b/tests/js_tests/jest.config.js new file mode 100644 index 000000000..ed031f960 --- /dev/null +++ b/tests/js_tests/jest.config.js @@ -0,0 +1,14 @@ +module.exports = { + testEnvironment: "jsdom", + roots: [""], + setupFiles: ["/jest.polyfills.js"], + setupFilesAfterEnv: ["/setup.js"], + collectCoverage: true, + coverageDirectory: "jest_coverage", + coverageReporters: ["text", "lcov"], + moduleFileExtensions: ["js", "jsx", "json", "node"], + moduleNameMapper: { + "^cesium$": "/__mocks__/cesium.js", + }, + transformIgnorePatterns: ["/node_modules/"], + }; \ No newline at end of file diff --git a/tests/js_tests/jest.polyfills.js b/tests/js_tests/jest.polyfills.js new file mode 100644 index 000000000..5e8b3c1af --- /dev/null +++ b/tests/js_tests/jest.polyfills.js @@ -0,0 +1,3 @@ +import { TextEncoder, TextDecoder } from "util"; +global.TextEncoder = TextEncoder; +global.TextDecoder = TextDecoder; \ No newline at end of file diff --git a/tests/js_tests/package.json b/tests/js_tests/package.json new file mode 100644 index 000000000..706d213ec --- /dev/null +++ b/tests/js_tests/package.json @@ -0,0 +1,20 @@ +{ + "devDependencies": { + "@babel/core": "^7.26.9", + "@babel/preset-env": "^7.26.9", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/user-event": "^14.6.1", + "babel-jest": "^29.7.0", + "datatables.net": "^2.2.2", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jquery": "^3.7.1", + "jsdom": "^26.0.0" + }, + "scripts": { + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage" + } +} diff --git a/tests/js_tests/render_template.py b/tests/js_tests/render_template.py new file mode 100644 index 000000000..65723411b --- /dev/null +++ b/tests/js_tests/render_template.py @@ -0,0 +1,70 @@ +import json +import os +import sys + +import django +from django.conf import settings +from django.template.loader import render_to_string, select_template + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tethys_portal.settings") + +# Add tests templates directory to settings so that django finds them +TEST_TEMPLATE_DIR = os.path.abspath( + os.path.join(os.path.dirname(__file__), "templates") +) +if TEST_TEMPLATE_DIR not in settings.TEMPLATES[0]["DIRS"]: + settings.TEMPLATES[0]["DIRS"].append(TEST_TEMPLATE_DIR) + +django.setup() + + +def confirm_template_path(template_name): + try: + select_template([template_name]) + + except Exception as e: + print(f"Error finding template: {e}") + + sys.exit(1) + + +def form_output_name(template_name): + template = template_name.removesuffix(".html") + return f"{template}_output.html" + + +def render_template(template_name, context): + try: + # Confirm the template path exists + confirm_template_path(template_name) + + # Render template using context + try: + rendered_html = render_to_string(template_name, context) + + except Exception as e: + print(f"Error: {e}") + sys.exit(1) + + output_path = f"./rendered_templates/test_{os.path.basename(form_output_name(template_name))}" + os.makedirs(os.path.dirname(output_path), exist_ok=True) + + # Write the rendered html into the result file + with open(output_path, "w") as file: + file.write(rendered_html) + + print(f"Template rendered to {output_path}") + except Exception as e: + print(f"Error rendering template: {e}") + sys.exit(1) + + +if __name__ == "__main__": + # breakpoint() + if len(sys.argv) < 3: + print("Usage: python render_template.py ''") + sys.exit(1) + + template_name = sys.argv[1] + context = json.loads(sys.argv[2]) + render_template(template_name, context) diff --git a/tests/js_tests/setup.js b/tests/js_tests/setup.js new file mode 100644 index 000000000..2ad57849e --- /dev/null +++ b/tests/js_tests/setup.js @@ -0,0 +1,23 @@ +try { + require("cesium"); + } catch (e) { + jest.mock("cesium", () => require("./__mocks__/cesium")); + } + +import { JSDOM } from "jsdom"; + +const dom = new JSDOM("", { + url: "http://localhost", +}); + +global.window = dom.window; +global.document = dom.window.document; + +const $ = require("jquery"); + +global.$ = $; +global.jQuery = $; + +global.$.fn = global.$.fn || {}; + +import "@testing-library/jest-dom"; \ No newline at end of file diff --git a/tests/js_tests/templates/test_template.html b/tests/js_tests/templates/test_template.html new file mode 100644 index 000000000..f66183eb0 --- /dev/null +++ b/tests/js_tests/templates/test_template.html @@ -0,0 +1 @@ +

This is a test template

\ No newline at end of file diff --git a/tethys_gizmos/static/tethys_gizmos/js/cesium_map_view.js b/tethys_gizmos/static/tethys_gizmos/js/cesium_map_view.js index 6baf5a513..f4460effa 100644 --- a/tethys_gizmos/static/tethys_gizmos/js/cesium_map_view.js +++ b/tethys_gizmos/static/tethys_gizmos/js/cesium_map_view.js @@ -896,8 +896,49 @@ var CESIUM_MAP_VIEW = (function() { cesium_initialize_all(); }); + // Expose private functions for testing + public_interface._testOnly = { + cesium_base_map_init, + cesium_globe_init, + cesium_map_view_init, + cesium_initialize_all, + cesium_widgets_init, + clock_options_init, + cesium_view, + cesium_terrain, + cesium_image_layers, + cesium_load_model, + cesium_load_entities, + cesium_load_primitives, + cesium_models, + update_field, + option_checker, + cesium_shadow_options, + textarea_string_dict, + cesium_logging, + is_defined, + is_empty_or_undefined, + in_array, + string_to_object, + string_to_function, + string_w_arg_to_function, + build_options, + build_options_string, + need_to_run, + cesium_options, + json_parser, + clear_data, + cesium_time_callback + }; + return public_interface; }()); // End of package wrapper // NOTE: that the call operator (open-closed parenthesis) is used to invoke the library wrapper // function immediately after being parsed. + +/* This statement for testing coverage purposes */ +/* istanbul ignore next */ +if (typeof module !== "undefined" && module.exports) { + module.exports = CESIUM_MAP_VIEW; +} diff --git a/tethys_gizmos/static/tethys_gizmos/js/datatable_view.js b/tethys_gizmos/static/tethys_gizmos/js/datatable_view.js index 07fc78d35..f3ba34e1e 100644 --- a/tethys_gizmos/static/tethys_gizmos/js/datatable_view.js +++ b/tethys_gizmos/static/tethys_gizmos/js/datatable_view.js @@ -51,3 +51,9 @@ var TETHYS_DATATABLE_VIEW = (function() { /***************************************************************************** * Public Functions *****************************************************************************/ + +/* This statement for testing coverage purposes */ +/* istanbul ignore next */ +if (typeof module !== "undefined" && module.exports) { + module.exports = { ...TETHYS_DATATABLE_VIEW} ; +} \ No newline at end of file diff --git a/tethys_gizmos/static/tethys_gizmos/js/range_slider.js b/tethys_gizmos/static/tethys_gizmos/js/range_slider.js index af38fd4c0..516c21cea 100644 --- a/tethys_gizmos/static/tethys_gizmos/js/range_slider.js +++ b/tethys_gizmos/static/tethys_gizmos/js/range_slider.js @@ -38,7 +38,10 @@ var TETHYS_RANGE_SLIDER = (function() { /* * Library object that contains public facing functions of the package. */ - public_interface = {}; + // TODO Make sure this is ok + public_interface = { + init_range_sliders: init_range_sliders, + }; // Initialization: jQuery function that gets called when // the DOM tree finishes loading @@ -49,3 +52,9 @@ var TETHYS_RANGE_SLIDER = (function() { return public_interface; }()); // End of package wrapper + +/* This statement for testing coverage purposes */ +/* istanbul ignore next */ +if (typeof module !== "undefined" && module.exports) { + module.exports = TETHYS_RANGE_SLIDER; +} \ No newline at end of file diff --git a/tethys_gizmos/static/tethys_gizmos/js/select_input.js b/tethys_gizmos/static/tethys_gizmos/js/select_input.js index 38005e595..444882f60 100644 --- a/tethys_gizmos/static/tethys_gizmos/js/select_input.js +++ b/tethys_gizmos/static/tethys_gizmos/js/select_input.js @@ -55,3 +55,9 @@ var TETHYS_SELECT_INPUT = (function() { /***************************************************************************** * Public Functions *****************************************************************************/ + +/* This statement for testing coverage purposes */ +/* istanbul ignore next */ +if (typeof module !== "undefined" && module.exports) { + module.exports = TETHYS_SELECT_INPUT; +} \ No newline at end of file diff --git a/tethys_gizmos/static/tethys_gizmos/js/slide_sheet.js b/tethys_gizmos/static/tethys_gizmos/js/slide_sheet.js index 0c2a4ccc2..b607884d5 100644 --- a/tethys_gizmos/static/tethys_gizmos/js/slide_sheet.js +++ b/tethys_gizmos/static/tethys_gizmos/js/slide_sheet.js @@ -21,6 +21,9 @@ var SLIDE_SHEET = (function() { // Slide sheet var open_slide_sheet, close_slide_sheet; + // Private functions + var open, close; + /************************************************************************ * PRIVATE FUNCTION IMPLEMENTATIONS *************************************************************************/ @@ -56,10 +59,17 @@ var SLIDE_SHEET = (function() { // Initialization: jQuery function that gets called when // the DOM tree finishes loading - $(document).ready(function(){}); + // Commented out because it is not needed for now + // $(document).ready(function(){}); return public_interface; }()); // End of package wrapper // NOTE: that the call operator (open-closed parenthesis) is used to invoke the library wrapper -// function immediately after being parsed. \ No newline at end of file +// function immediately after being parsed. + +/* This statement for testing coverage purposes */ +/* istanbul ignore next */ +if (typeof module !== "undefined" && module.exports) { + module.exports = SLIDE_SHEET; +} \ No newline at end of file diff --git a/tethys_gizmos/static/tethys_gizmos/js/toggle_switch.js b/tethys_gizmos/static/tethys_gizmos/js/toggle_switch.js index 109d9e785..e7d0dc7f6 100644 --- a/tethys_gizmos/static/tethys_gizmos/js/toggle_switch.js +++ b/tethys_gizmos/static/tethys_gizmos/js/toggle_switch.js @@ -54,3 +54,9 @@ var TETHYS_TOGGLE_SWITCH = (function() { /***************************************************************************** * Public Functions *****************************************************************************/ + +/* This statement for testing coverage purposes */ +/* istanbul ignore next */ +if (typeof module !== "undefined" && module.exports) { + module.exports = { ...TETHYS_TOGGLE_SWITCH} ; +} \ No newline at end of file