Repository: spacetelescope/jwql

Issue:
Write tests for bokeh templating software
With the merge of #459, bokeh templating will be implemented for `jwql`.  We should address the test coverage for this software. 


Discussion:

Resolving patch:
diff --git a/jwql/bokeh_templating/example/main.py b/jwql/bokeh_templating/example/main.py
--- a/jwql/bokeh_templating/example/main.py
+++ b/jwql/bokeh_templating/example/main.py
@@ -24,6 +24,8 @@
 
 class TestBokehApp(BokehTemplate):
     """This is a minimal ``BokehTemplate`` app."""
+    
+    _embed = True
 
     def pre_init(self):
         """Before creating the Bokeh interface (by parsing the interface


Test patch:
diff --git a/jwql/tests/test_bokeh_templating.py b/jwql/tests/test_bokeh_templating.py
new file mode 100644
--- /dev/null
+++ b/jwql/tests/test_bokeh_templating.py
@@ -0,0 +1,62 @@
+"""Tests for the ``bokeh_templating`` module.
+Authors
+-------
+    - Graham Kanarek
+Use
+---
+    These tests can be run via the command line (omit the -s to
+    suppress verbose output to stdout):
+    ::
+        pytest -s test_bokeh_templating.py
+"""
+
+import os
+import numpy as np
+from jwql.bokeh_templating import BokehTemplate
+file_dir = os.path.dirname(os.path.realpath(__file__))
+
+
+class TestTemplate(BokehTemplate):
+    """
+    A minimal BokehTemplate app for testing purposes. This is adapted from
+    the example included in the ``bokeh_template`` package.
+    """
+    
+    _embed = True
+
+    def pre_init(self):
+        """
+        Before creating the Bokeh interface (by parsing the interface
+        file), we must initialize our ``a`` and ``b`` variables, and set
+        the path to the interface file.
+        """
+
+        self.a, self.b = 4, 2
+
+        self.format_string = None
+        self.interface_file = os.path.join(file_dir, "test_bokeh_tempating_interface.yaml")
+
+    # No post-initialization tasks are required.
+    post_init = None
+
+    @property
+    def x(self):
+        """The x-value of the Lissajous curves."""
+        return 4. * np.sin(self.a * np.linspace(0, 2 * np.pi, 500))
+
+    @property
+    def y(self):
+        """The y-value of the Lissajous curves."""
+        return 3. * np.sin(self.b * np.linspace(0, 2 * np.pi, 500))
+
+    def controller(self, attr, old, new):
+        """
+        This is the controller function which is used to update the
+        curves when the sliders are adjusted. Note the use of the
+        ``self.refs`` dictionary for accessing the Bokeh object
+        attributes.
+        """
+        self.a = self.refs["a_slider"].value
+        self.b = self.refs["b_slider"].value
+
+        self.refs["figure_source"].data = {'x': self.x, 'y': self.y}
diff --git a/jwql/tests/test_bokeh_templating_interface.yaml b/jwql/tests/test_bokeh_templating_interface.yaml
new file mode 100644
--- /dev/null
+++ b/jwql/tests/test_bokeh_templating_interface.yaml
@@ -0,0 +1,26 @@
+- !Slider: &a_slider # a slider for the a value
+    ref: "a_slider"
+    title: "A"
+    value: 4
+    range: !!python/tuple [1, 20, 0.1]
+    on_change: ['value', !self.controller ]
+- !Slider: &b_slider # a slider for the b value
+    ref: "b_slider"
+    title: "B"
+    value: 2
+    range: !!python/tuple [1, 20, 0.1]
+    on_change: ['value', !self.controller ]
+- !ColumnDataSource: &figure_source # the ColumnDataSource for the figure
+    ref: "figure_source"
+    data:
+        x: !self.x
+        y: !self.y
+- !Figure: &the_figure # the Figure itself, which includes a single line element.
+    ref: 'the_figure'
+    elements:
+        - {'kind': 'line', 'source': *figure_source, 'line_color': 'orange', 'line_width': 2}
+- !Document: # the Bokeh document layout: a single column with the figure and two sliders
+    - !column:
+        - *the_figure # note the use of YAML anchors to add the Bokeh objects to the Document layout directly.
+        - *a_slider
+        - *b_slider
\ No newline at end of file