Skip to content

Commit bce392a

Browse files
committed
Release 0.4.0
1 parent 7fd5c79 commit bce392a

File tree

8 files changed

+251
-118
lines changed

8 files changed

+251
-118
lines changed

docs/core.html

+12
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ <h1 class="title">Module <code>h2o_q.core</code></h1>
9292
import logging
9393
import os
9494
import os.path
95+
import sys
9596
from typing import List, Dict, Union, Tuple, Any, Optional
9697

9798
import requests
@@ -333,7 +334,18 @@ <h1 class="title">Module <code>h2o_q.core</code></h1>
333334
return hasattr(x, &#39;dump&#39;) and callable(x.dump)
334335

335336

337+
def _is_numpy_obj(x: Any) -&gt; bool:
338+
if &#39;numpy&#39; in sys.modules:
339+
np = sys.modules[&#39;numpy&#39;]
340+
if isinstance(x, (np.ndarray, np.dtype, np.integer, np.floating)):
341+
return True
342+
return False
343+
344+
336345
def _dump(xs: Any):
346+
if _is_numpy_obj(xs):
347+
raise ValueError(&#39;NumPy objects are not serializable by Q&#39;)
348+
337349
if isinstance(xs, (list, tuple)):
338350
return [_dump(x) for x in xs]
339351
elif isinstance(xs, dict):

docs/index.html

+91-60
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,29 @@ <h1 class="title">Package <code>h2o_q</code></h1>
9595
realtime state synchronization between Python and web browsers.</p>
9696
<h1 id="change-log">Change Log</h1>
9797
<ul>
98+
<li><a href="https://github.com/h2oai/qd/releases/tag/v0.4.0">v0.4.0</a> - Sep 16, 2020<ul>
99+
<li>Added<ul>
100+
<li>Trigger attribute to checklist component.</li>
101+
</ul>
102+
</li>
103+
<li>Changed<ul>
104+
<li>Allow same min and max values for the range slider component.</li>
105+
<li>App tests are now automatically and directly translated to Cypress tests when loaded.</li>
106+
</ul>
107+
</li>
108+
<li>Fixed<ul>
109+
<li>Allow removing selected options from the picker component.</li>
110+
<li>Render axis title properly when specified.</li>
111+
<li>Raise informative error message if attempting to use Numpy objects in components.</li>
112+
</ul>
113+
</li>
114+
<li>Removed<ul>
115+
<li>Cypress test bridge removed from server.</li>
116+
<li><code>run_tests</code> API.</li>
117+
</ul>
118+
</li>
119+
</ul>
120+
</li>
98121
<li><a href="https://github.com/h2oai/qd/releases/tag/v0.3.1">v0.3.1</a> - Sep 8, 2020<ul>
99122
<li>Fixed<ul>
100123
<li>Multiselect dropdown checkboxes do not respond when clicked.</li>
@@ -454,51 +477,42 @@ <h3 id="step-2-set-up-cypress">Step 2: Set up Cypress</h3>
454477
$ npm install
455478
</code></pre>
456479
<h2 id="writing-a-test">Writing a test</h2>
457-
<p>See the <a href="#wizard">Wizard</a> example to understand how to author tests for your interactive app. Specifically, note how the <code>@test</code> attribute and
458-
the <code>run_tests()</code> function is used.</p>
459-
<pre><code class="py">
460-
@test
461-
def test_wizard(t):
462-
t.visit('/demo')
463-
t.locate('step1').click()
464-
t.locate('text').should('have.text', 'What is your name?')
465-
t.locate('nickname').clear().type('Fred')
466-
t.locate('step2').click()
467-
t.locate('text').should('have.text', 'Hi Fred! How do you feel right now?')
468-
t.locate('feeling').clear().type('quirky')
469-
t.locate('step3').click()
470-
t.locate('text').should('have.text', 'What a coincidence, Fred! I feel quirky too!')
471-
472-
473-
if len(sys.argv) &gt; 1 and sys.argv[1] == 'test':
474-
run_tests()
475-
else:
476-
listen('/demo', main)
480+
<p>See the <a href="#wizard">Wizard</a> example to understand how to author tests for your interactive app. Specifically, note how the <code>@cypress</code> attribute is used. Refer to the <a href="https://docs.cypress.io/api/api/table-of-contents.html">Cypress API</a> to learn how to author assertions.</p>
481+
<pre><code class="py">from h2o_q import cypress
482+
483+
@cypress('Walk through the wizard')
484+
def test_wizard(cy):
485+
cy.visit('/demo')
486+
cy.locate('step1').click()
487+
cy.locate('text').should('have.text', 'What is your name?')
488+
cy.locate('nickname').clear().type('Fred')
489+
cy.locate('step2').click()
490+
cy.locate('text').should('have.text', 'Hi Fred! How do you feel right now?')
491+
cy.locate('feeling').clear().type('quirky')
492+
cy.locate('step3').click()
493+
cy.locate('text').should('have.text', 'What a coincidence, Fred! I feel quirky too!')
477494

478495
</code></pre>
479-
<p>See <a href="https://docs.cypress.io/guides/references/assertions.html#Common-Assertions">Assertions</a> to understand how the Cypress API works.</p>
480496
<h2 id="running-your-test">Running your test</h2>
481-
<h3 id="step-1-start-the-q-server-as-usual">Step 1: Start the Q server as usual</h3>
482-
<pre><code>$ q
483-
</code></pre>
484-
<h3 id="step-2-start-the-q-test-bridge">Step 2: Start the Q test bridge</h3>
485-
<p>The Q test bridge is built into your Q server executable, and helps run your Python tests on Cypress.</p>
486-
<p>In a new terminal window, run the Q executable with the <code>-cypress</code> command line argument.</p>
487-
<pre><code>$ qd -cypress
488-
</code></pre>
489-
<p>Optionally, use the <code>-cypress-dir</code> and <code>-cypress-bridge-address</code> command line arguments if you need additional control over the test bridge (run <code>qd -help</code> for details).</p>
490-
<h3 id="step-3-run-your-test">Step 3: Run your test</h3>
491-
<p>From your app's <code>venv</code>, run:</p>
492-
<pre><code>$ python examples/wizard.py test
493-
</code></pre>
494-
<p>Running the above command translates your Python test to Javascript and sends it to the Q test bridge. You should now see your test executing in the terminal window that belongs your test bridge.</p>
495-
<h3 id="step-4-optional-explore-your-executed-tests">Step 4: (Optional) Explore your executed tests</h3>
496-
<p>All your executed tests are stored in your <code>test/cypress/integration</code> directory. To view past results and re-run tests, simply launch Cypress like this:</p>
497+
<h3 id="step-1-start-the-cypress-test-runner">Step 1: Start the Cypress test runner</h3>
497498
<pre><code>$ cd path/to/q
498499
$ cd test
499500
$ ./node_modules/.bin/cypress open
500501
</code></pre>
501-
<p>You can then use the Cypres user interface to browse and execute individual tests interactively.</p>
502+
<h3 id="step-2-start-the-q-server-as-usual">Step 2: Start the Q server as usual</h3>
503+
<pre><code>$ ./qd
504+
</code></pre>
505+
<h3 id="step-3-translate-your-python-tests-to-javascript">Step 3: Translate your Python tests to Javascript</h3>
506+
<p>To translate your Python tests to Javascript, execute the Python module or file containing your tests like this:</p>
507+
<pre><code>$ CYPRESS_INTEGRATION_TEST_DIR=path/to/q/test/cypress/integration ./venv/bin/python examples/wizard.py
508+
</code></pre>
509+
<p>The <code>CYPRESS_INTEGRATION_TEST_DIR</code> environment variable indicates where the Q SDK should write translated files to. This must be set to the <code>cypress/integration</code> directory.</p>
510+
<p>Alternatively, you can set the <code>CYPRESS_INTEGRATION_TEST_DIR</code> environment variable in your shell (or IDE) to simplify running your test file:</p>
511+
<pre><code>$ export CYPRESS_INTEGRATION_TEST_DIR=path/to/q/test/cypress/integration
512+
$ ./venv/bin/python examples/wizard.py
513+
</code></pre>
514+
<h3 id="step-4-run-your-tests">Step 4: Run your tests</h3>
515+
<p>At this point, you should find all your tests displayed in the Cypress UI. Simply click on a test to run it. Happy testing!</p>
502516
<h1 id="examples">Examples</h1>
503517
<h2 id="hello-world">Hello World!</h2>
504518
<p>A simple example to get you started with Q.</p>
@@ -623,8 +637,7 @@ <h2 id="breadcrumbs">Breadcrumbs</h2>
623637
</code></pre>
624638
<h2 id="wizard">Wizard</h2>
625639
<p>Create a multi-step wizard using form cards.</p>
626-
<pre><code class="py">import sys
627-
from h2o_q import Q, ui, listen, test, run_tests
640+
<pre><code class="py">from h2o_q import Q, ui, listen, cypress, Cypress
628641

629642

630643
async def main(q: Q):
@@ -664,23 +677,20 @@ <h2 id="wizard">Wizard</h2>
664677
await q.page.save()
665678

666679

667-
@test
668-
def test_wizard(t):
669-
t.visit('/demo')
670-
t.locate('step1').click()
671-
t.locate('text').should('have.text', 'What is your name?')
672-
t.locate('nickname').clear().type('Fred')
673-
t.locate('step2').click()
674-
t.locate('text').should('have.text', 'Hi Fred! How do you feel right now?')
675-
t.locate('feeling').clear().type('quirky')
676-
t.locate('step3').click()
677-
t.locate('text').should('have.text', 'What a coincidence, Fred! I feel quirky too!')
680+
@cypress('Walk through the wizard')
681+
def try_walk_through(cy: Cypress):
682+
cy.visit('/demo')
683+
cy.locate('step1').click()
684+
cy.locate('text').should('have.text', 'What is your name?')
685+
cy.locate('nickname').clear().type('Fred')
686+
cy.locate('step2').click()
687+
cy.locate('text').should('have.text', 'Hi Fred! How do you feel right now?')
688+
cy.locate('feeling').clear().type('quirky')
689+
cy.locate('step3').click()
690+
cy.locate('text').should('have.text', 'What a coincidence, Fred! I feel quirky too!')
678691

679692

680-
if len(sys.argv) &gt; 1 and sys.argv[1] == 'test':
681-
run_tests()
682-
else:
683-
listen('/demo', main)
693+
listen('/demo', main)
684694
</code></pre>
685695
<h2 id="stepper">Stepper</h2>
686696
<p>Use Stepper to show progress through numbered steps.</p>
@@ -4126,6 +4136,26 @@ <h2 id="plot-histogram">Plot / Histogram</h2>
41264136
))
41274137
v.data = [(i * 10, i * 10 + 10, x) for i, (c, x, dx) in enumerate([f.next() for _ in range(n)])]
41284138

4139+
page.save()
4140+
</code></pre>
4141+
<h2 id="plot-axis-titles">Plot / Axis Titles</h2>
4142+
<p>Display custom axis titles on a plot.</p>
4143+
<pre><code class="py">from synth import FakeTimeSeries
4144+
from h2o_q import site, data, ui
4145+
4146+
page = site['/demo']
4147+
4148+
n = 50
4149+
f = FakeTimeSeries()
4150+
v = page.add('example', ui.plot_card(
4151+
box='1 1 4 5',
4152+
title='Line',
4153+
data=data('date price', n),
4154+
plot=ui.plot(
4155+
[ui.mark(type='line', x_scale='time', x='=date', y='=price', y_min=0, x_title='Date', y_title='Price')])
4156+
))
4157+
v.data = [(t, x) for t, x, dx in [f.next() for _ in range(n)]]
4158+
41294159
page.save()
41304160
</code></pre>
41314161
<h2 id="plot-form">Plot / Form</h2>
@@ -5140,7 +5170,7 @@ <h2 id="graphics-hilbert">Graphics / Hilbert</h2>
51405170
from .server import listen, Q
51415171
from .db import TeleDBError, TeleDB
51425172
from .types import *
5143-
from .test import test, run_tests</code></pre>
5173+
from .test import cypress, Cypress</code></pre>
51445174
</details>
51455175
</section>
51465176
<section>
@@ -5206,10 +5236,10 @@ <h1>Index</h1>
52065236
</li>
52075237
<li><a href="#writing-a-test">Writing a test</a></li>
52085238
<li><a href="#running-your-test">Running your test</a><ul>
5209-
<li><a href="#step-1-start-the-q-server-as-usual">Step 1: Start the Q server as usual</a></li>
5210-
<li><a href="#step-2-start-the-q-test-bridge">Step 2: Start the Q test bridge</a></li>
5211-
<li><a href="#step-3-run-your-test">Step 3: Run your test</a></li>
5212-
<li><a href="#step-4-optional-explore-your-executed-tests">Step 4: (Optional) Explore your executed tests</a></li>
5239+
<li><a href="#step-1-start-the-cypress-test-runner">Step 1: Start the Cypress test runner</a></li>
5240+
<li><a href="#step-2-start-the-q-server-as-usual">Step 2: Start the Q server as usual</a></li>
5241+
<li><a href="#step-3-translate-your-python-tests-to-javascript">Step 3: Translate your Python tests to Javascript</a></li>
5242+
<li><a href="#step-4-run-your-tests">Step 4: Run your tests</a></li>
52135243
</ul>
52145244
</li>
52155245
</ul>
@@ -5335,6 +5365,7 @@ <h1>Index</h1>
53355365
<li><a href="#plot-area-line-groups">Plot / Area + Line / Groups</a></li>
53365366
<li><a href="#plot-polygon">Plot / Polygon</a></li>
53375367
<li><a href="#plot-histogram">Plot / Histogram</a></li>
5368+
<li><a href="#plot-axis-titles">Plot / Axis Titles</a></li>
53385369
<li><a href="#plot-form">Plot / Form</a></li>
53395370
<li><a href="#plot-vega-lite">Plot / Vega-lite</a></li>
53405371
<li><a href="#plot-vega-lite-update">Plot / Vega-lite / Update</a></li>

0 commit comments

Comments
 (0)