Skip to content

Commit

Permalink
CircleCI Tests (plotly#59)
Browse files Browse the repository at this point in the history
* bump archetype version

* install eslint globally, fix tabs

* install requirements

* clean up tests

* unittest instead of implicit nosetest, all versions of python

* rm 36 for now

* just python 2 for now

* typo

* increase length of timeout

* log the layout

* remove duplicate visit
  • Loading branch information
chriddyp committed Aug 18, 2017
1 parent 3d00e17 commit 4d0545a
Show file tree
Hide file tree
Showing 9 changed files with 317 additions and 79 deletions.
23 changes: 18 additions & 5 deletions packages/dash-core-components/circle.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
machine:
node:
version: 4.4.7
node:
version: 6.9.2
post:
- pyenv global 2.7.10
environment:
TOX_PYTHON_27: python2.7

dependencies:
pre:
- npm install -g eslint
- pip install tox
- pip install -r dev-requirements.txt
- npm install
- node_modules/.bin/builder run build-dist
- node_modules/.bin/builder run copy-lib

test:
post:
# Ensure steps leading up to publishing work.
- node_modules/.bin/builder run build-dist
override:
- tox
- npm run test
12 changes: 12 additions & 0 deletions packages/dash-core-components/dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
dash_html_components
dash_renderer
dash
percy
selenium
mock
tox
tox-pyenv
six
plotly>=2.0.8
requests[security]
ipdb
4 changes: 2 additions & 2 deletions packages/dash-core-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"license": "MIT",
"dependencies": {
"builder": "2.10.1",
"dash-components-archetype": "^0.2.4",
"dash-components-archetype": "^0.2.11",
"moment": "^2.18.1",
"radium": "^0.17.1",
"ramda": "^0.23.0",
Expand All @@ -43,7 +43,7 @@
},
"devDependencies": {
"component-playground": "^1.3.2",
"dash-components-archetype-dev": "^0.2.4",
"dash-components-archetype-dev": "^0.2.11",
"enzyme": "^2.4.1"
}
}
82 changes: 82 additions & 0 deletions packages/dash-core-components/test/IntegrationTests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from __future__ import absolute_import
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import importlib
import multiprocessing
import percy
import time
import unittest


class IntegrationTests(unittest.TestCase):

@classmethod
def setUpClass(cls):
super(IntegrationTests, cls).setUpClass()
cls.driver = webdriver.Chrome()

loader = percy.ResourceLoader(webdriver=cls.driver)
cls.percy_runner = percy.Runner(loader=loader)
cls.percy_runner.initialize_build()

@classmethod
def tearDownClass(cls):
super(IntegrationTests, cls).tearDownClass()
cls.driver.quit()
cls.percy_runner.finalize_build()

def setUp(self):
pass

def tearDown(self):
time.sleep(3)
self.server_process.terminate()
time.sleep(3)

if hasattr(self, 'driver'):
self.driver.quit()


def startServer(self, app):
def run():
app.scripts.config.serve_locally = True
app.run_server(
port=8050,
debug=False,
processes=4
)

# Run on a separate process so that it doesn't block
self.server_process = multiprocessing.Process(target=run)
self.server_process.start()
time.sleep(0.5)

# Visit the dash page
self.driver.get('http://localhost:8050')
time.sleep(0.5)

# Inject an error and warning logger
logger = '''
window.tests = {};
window.tests.console = {error: [], warn: [], log: []};
var _log = console.log;
var _warn = console.warn;
var _error = console.error;
console.log = function() {
window.tests.console.log.push({method: 'log', arguments: arguments});
return _log.apply(console, arguments);
};
console.warn = function() {
window.tests.console.warn.push({method: 'warn', arguments: arguments});
return _warn.apply(console, arguments);
};
console.error = function() {
window.tests.console.error.push({method: 'error', arguments: arguments});
return _error.apply(console, arguments);
};
'''
self.driver.execute_script(logger)
5 changes: 0 additions & 5 deletions packages/dash-core-components/test/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
from os.path import dirname, basename, isfile
import glob
modules = glob.glob(dirname(__file__)+"/*.py")
__all__ = [basename(f)[:-3] for f in modules if isfile(f)]

11 changes: 0 additions & 11 deletions packages/dash-core-components/test/main.js
Original file line number Diff line number Diff line change
@@ -1,11 +0,0 @@
/* eslint-disable import/default */
/* global require:false */
import karmaRunner from 'dash-components-archetype-dev/karma-runner';

karmaRunner.setupEnvironment();

// Use webpack to infer and `require` tests automatically.
var testsReq = require.context('../src', true, /\.test.js$/);
testsReq.keys().map(testsReq);

karmaRunner.startKarma();
159 changes: 103 additions & 56 deletions packages/dash-core-components/test/test_integration.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import dash_core_components
from dash.react import Dash
# -*- coding: utf-8 -*-
import dash_core_components as dcc
import dash_html_components as html
import dash
import importlib
import percy
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
import multiprocessing
import unittest
import os

from .IntegrationTests import IntegrationTests
from .utils import assert_clean_console, invincible, wait_for

# Download geckodriver: https://github.com/mozilla/geckodriver/releases
# And add to path:
Expand All @@ -17,59 +23,100 @@
# export PERCY_TOKEN=...


class IntegrationTests(unittest.TestCase):

@classmethod
def setUpClass(cls):
super(IntegrationTests, cls).setUpClass()
cls.driver = webdriver.Firefox()

loader = percy.ResourceLoader(
webdriver=cls.driver
)
cls.percy_runner = percy.Runner(loader=loader)

cls.percy_runner.initialize_build()

@classmethod
def tearDownClass(cls):
super(IntegrationTests, cls).tearDownClass()
cls.driver.quit()
cls.percy_runner.finalize_build()

def setUp(s):
pass

def tearDown(s):
s.server_process.terminate()

def startServer(s, dash):
def run():
dash.run_server(
port=8050,
debug=False,
component_suites=[
'dash_core_components'
class Tests(IntegrationTests):
def setUp(self):
self.driver = webdriver.Chrome()
def wait_for_element_by_id(id):
wait_for(lambda: None is not invincible(
lambda: self.driver.find_element_by_id(id)
))
return self.driver.find_element_by_id(id)
self.wait_for_element_by_id = wait_for_element_by_id

def wait_for_element_by_css_selector(css_selector):
wait_for(lambda: None is not invincible(
lambda: self.driver.find_element_by_css_selector(css_selector)
))
return self.driver.find_element_by_css_selector(css_selector)
self.wait_for_element_by_css_selector = wait_for_element_by_css_selector


def test_integration(self):
app = dash.Dash(__name__)

app.layout = html.Div([
html.Div(id='waitfor'),
html.Label('Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
value='MTL'
),

html.Label('Multi-Select Dropdown'),
dcc.Dropdown(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
threaded=True
value=['MTL', 'SF'],
multi=True
),

html.Label('Radio Items'),
dcc.RadioItems(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
value='MTL'
),

html.Label('Checkboxes'),
dcc.Checklist(
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': u'Montréal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
values=['MTL', 'SF']
),

html.Label('Text Input'),
dcc.Input(value='MTL', type='text'),

html.Label('Slider'),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)},
value=5,
),

html.Label('Graph'),
dcc.Graph(
id='graph',
figure={
'data': [{
'x': [1, 2, 3],
'y': [4, 1, 4]
}]
}
)

# Run on a separate process so that it doesn't block
s.server_process = multiprocessing.Process(target=run)
s.server_process.start()
time.sleep(0.5)

def test_integration(s):
dash = Dash(__name__)

dash.layout = dash_core_components.Input(
id='hello-world'
)

s.startServer(dash)
s.driver.get('http://localhost:8050')

el = s.driver.find_element_by_id('hello-world')

# Take a screenshot with percy
s.percy_runner.snapshot(name='dash_core_components')
])
self.startServer(app)

try:
self.wait_for_element_by_id('waitfor')
except Exception as e:
print(self.wait_for_element_by_id(
'_dash-app-content').get_attribute('innerHTML'))
raise e

if 'PERCY_PROJECT' in os.environ and 'PERCY_TOKEN' in os.environ:
self.percy_runner.snapshot(name='dash_core_components')
Loading

0 comments on commit 4d0545a

Please sign in to comment.