From 79f4804e9c33404199f63d887df0fb443b24b45b Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 17:06:18 -0500 Subject: [PATCH 1/8] :white_check_mark: Add resources tests from @rmarren1 --- tests/test_resources.py | 221 +++++++++++----------------------------- 1 file changed, 61 insertions(+), 160 deletions(-) diff --git a/tests/test_resources.py b/tests/test_resources.py index f0214f45b2..55b8163a87 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -1,164 +1,65 @@ import unittest -import warnings -from dash.resources import Scripts, Css -from dash.development._py_components_generation import generate_class - - -def generate_components(): - Div = generate_class('Div', ('children', 'id',), 'dash_html_components') - Span = generate_class('Span', ('children', 'id',), 'dash_html_components') - Input = generate_class( - 'Input', ('children', 'id',), - 'dash_core_components') - return Div, Span, Input - - -def external_url(package_name): - return ( - '//unpkg.com/{}@0.2.9' - '/{}/bundle.js'.format( - package_name.replace('_', '-'), - package_name - ) - ) - - -def rel_path(package_name): - return '{}/bundle.js'.format(package_name) - - -def abs_path(package_name): - return '/Users/chriddyp/{}/bundle.js'.format(package_name) - - -class TestResources(unittest.TestCase): - - def resource_test(self, css_or_js): - Div, Span, Input = generate_components() - - if css_or_js == 'css': - # The CSS URLs and paths will look a little bit differently - # than the JS urls but that doesn't matter for the purposes - # of the test - Div._css_dist = Span._css_dist = [{ - 'external_url': external_url('dash_html_components'), - 'relative_package_path': rel_path('dash_html_components') - }] - - Input._css_dist = [{ - 'external_url': external_url('dash_core_components'), - 'relative_package_path': rel_path('dash_core_components') - }] - - else: - Div._js_dist = Span._js_dist = [{ - 'external_url': external_url('dash_html_components'), - 'relative_package_path': rel_path('dash_html_components') - }] - - Input._js_dist = [{ - 'external_url': external_url('dash_core_components'), - 'relative_package_path': rel_path('dash_core_components') - }] - - layout = Div([None, 'string', Span(), Div(Input())]) - - if css_or_js == 'css': - resources = Css(layout) - else: - resources = Scripts(layout) - - resources._update_layout(layout) - - expected_filtered_external_resources = [ - { - 'external_url': external_url('dash_html_components'), - 'namespace': 'dash_html_components' - }, - { - 'external_url': external_url('dash_core_components'), - 'namespace': 'dash_core_components' - } - ] - expected_filtered_relative_resources = [ - { - 'relative_package_path': rel_path('dash_html_components'), - 'namespace': 'dash_html_components' - }, - { - 'relative_package_path': rel_path('dash_core_components'), - 'namespace': 'dash_core_components' - } +import dash +import mock +import dash_core_components as dcc + +_monkey_patched_js_dist = [ + { + 'external_url': 'https://external_javascript.js', + 'relative_package_path': 'external_javascript.js', + 'namespace': 'dash_core_components' + }, + { + 'external_url': 'https://external_css.css', + 'relative_package_path': 'external_css.css', + 'namespace': 'dash_core_components' + }, + { + 'relative_package_path': 'fake_dcc.js', + 'dev_package_path': 'fake_dcc.dev.js', + 'external_url': 'https://component_library.bundle.js', + 'namespace': 'dash_core_components' + }, + { + 'relative_package_path': 'fake_dcc.min.js.map', + 'dev_package_path': 'fake_dcc.dev.js.map', + 'external_url': 'https://component_library.bundle.js.map', + 'namespace': 'dash_core_components', + 'dynamic': True + } +] + +dcc._js_dist = _monkey_patched_js_dist +dcc.__version__ = 1 + + +class StatMock(object): + st_mtime = 1 + + +class Tests(unittest.TestCase): + + def test_external(self): + app = dash.Dash(__name__, assets_folder='tests/assets', assets_ignore='load_after.+.js') + app.layout = dcc.Markdown() + app.scripts.config.serve_locally = False + with mock.patch('dash.dash.os.stat', return_value=StatMock()): + resource = app._collect_and_register_resources(app.scripts.get_all_scripts()) + assert resource == [ + 'https://external_javascript.js', + 'https://external_css.css', + 'https://component_library.bundle.js' ] - if css_or_js == 'css': - self.assertEqual( - resources.get_all_css(), - expected_filtered_external_resources - ) - else: - self.assertEqual( - resources.get_all_scripts(), - expected_filtered_external_resources - ) - - resources.config.serve_locally = True - if css_or_js == 'css': - self.assertEqual( - resources.get_all_css(), - expected_filtered_relative_resources - ) - else: - self.assertEqual( - resources.get_all_scripts(), - expected_filtered_relative_resources - ) - - resources.config.serve_locally = False - extra_resource = {'external_url': '//cdn.bootstrap.com/min.css'} - expected_resources = expected_filtered_external_resources + [ - extra_resource + def test_internal(self): + app = dash.Dash(__name__, assets_folder='tests/assets', assets_ignore='load_after.+.js') + app.layout = dcc.Markdown() + app.scripts.config.serve_locally = True + with mock.patch('dash.dash.os.stat', return_value=StatMock()): + with mock.patch('dash.dash.importlib.import_module', return_value=dcc): + resource = app._collect_and_register_resources(app.scripts.get_all_scripts()) + assert resource == [ + '/_dash-component-suites/dash_core_components/external_javascript.js?v=1&m=1', + '/_dash-component-suites/dash_core_components/external_css.css?v=1&m=1', + '/_dash-component-suites/dash_core_components/fake_dcc.js?v=1&m=1' ] - if css_or_js == 'css': - resources.append_css(extra_resource) - self.assertEqual( - resources.get_all_css(), - expected_resources - ) - else: - resources.append_script(extra_resource) - self.assertEqual( - resources.get_all_scripts(), - expected_resources - ) - - resources.config.serve_locally = True - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter('always') - if css_or_js == 'css': - self.assertEqual( - resources.get_all_css(), - expected_filtered_relative_resources - ) - assert len(w) == 1 - assert 'A local version of {} is not available'.format( - extra_resource['external_url'] - ) in str(w[-1].message) - - else: - self.assertEqual( - resources.get_all_scripts(), - expected_filtered_relative_resources - ) - assert len(w) == 1 - assert 'A local version of {} is not available'.format( - extra_resource['external_url'] - ) in str(w[-1].message) - - def test_js_resources(self): - # self.resource_test('js') - pass - - def test_css_resources(self): - # self.resource_test('css') - pass From d9e7c6d058c8a9aac54adcb49f78fd1610ba925b Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 17:08:24 -0500 Subject: [PATCH 2/8] :shirt: Fix (wrong-import-order) --- tests/test_resources.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_resources.py b/tests/test_resources.py index 55b8163a87..196ae5b6aa 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -1,8 +1,9 @@ import unittest -import dash import mock import dash_core_components as dcc +import dash + _monkey_patched_js_dist = [ { 'external_url': 'https://external_javascript.js', From 87d681f0c7c17ea2397c5228c4aa2c4aa6b33f7a Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 17:31:22 -0500 Subject: [PATCH 3/8] :lipstick: Pretty up resources test. --- tests/test_resources.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/test_resources.py b/tests/test_resources.py index 196ae5b6aa..2405fcb15b 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -41,11 +41,19 @@ class StatMock(object): class Tests(unittest.TestCase): def test_external(self): - app = dash.Dash(__name__, assets_folder='tests/assets', assets_ignore='load_after.+.js') + app = dash.Dash( + __name__, + assets_folder='tests/assets', + assets_ignore='load_after.+.js' + ) app.layout = dcc.Markdown() app.scripts.config.serve_locally = False + with mock.patch('dash.dash.os.stat', return_value=StatMock()): - resource = app._collect_and_register_resources(app.scripts.get_all_scripts()) + resource = app._collect_and_register_resources( + app.scripts.get_all_scripts() + ) + assert resource == [ 'https://external_javascript.js', 'https://external_css.css', @@ -53,14 +61,26 @@ def test_external(self): ] def test_internal(self): - app = dash.Dash(__name__, assets_folder='tests/assets', assets_ignore='load_after.+.js') + app = dash.Dash( + __name__, + assets_folder='tests/assets', + assets_ignore='load_after.+.js' + ) app.layout = dcc.Markdown() app.scripts.config.serve_locally = True + with mock.patch('dash.dash.os.stat', return_value=StatMock()): - with mock.patch('dash.dash.importlib.import_module', return_value=dcc): - resource = app._collect_and_register_resources(app.scripts.get_all_scripts()) + with mock.patch('dash.dash.importlib.import_module', + return_value=dcc): + resource = app._collect_and_register_resources( + app.scripts.get_all_scripts() + ) + assert resource == [ - '/_dash-component-suites/dash_core_components/external_javascript.js?v=1&m=1', - '/_dash-component-suites/dash_core_components/external_css.css?v=1&m=1', - '/_dash-component-suites/dash_core_components/fake_dcc.js?v=1&m=1' + '/_dash-component-suites/' + 'dash_core_components/external_javascript.js?v=1&m=1', + '/_dash-component-suites/' + 'dash_core_components/external_css.css?v=1&m=1', + '/_dash-component-suites/' + 'dash_core_components/fake_dcc.js?v=1&m=1', ] From d5eb00f9b86db5c79c4293129993a63ca9485f79 Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 19:01:05 -0500 Subject: [PATCH 4/8] :rotating_light: Assert dynamic resources in registered path. --- tests/test_resources.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_resources.py b/tests/test_resources.py index 2405fcb15b..767d92ef07 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -84,3 +84,11 @@ def test_internal(self): '/_dash-component-suites/' 'dash_core_components/fake_dcc.js?v=1&m=1', ] + + self.assertTrue( + 'fake_dcc.min.js.map' + in app.registered_paths['dash_core_components'], + 'Dynamic resource not available in registered path {}'.format( + app.registered_paths['dash_core_components'] + ) + ) From cb99f4cf268f7b4806b498d2decba6bd57af7a80 Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 16:18:56 -0500 Subject: [PATCH 5/8] :pencil: Update changelog. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3114d8e1f4..6c07b43e92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.35.1 - 2018-12-27 +### Fixed +- Always skip `dynamic` resources from index resources collection. [#518](https://github.com/plotly/dash/pull/518) + ## 0.35.0 - 2018-12-18 ## Added - Experimental `--r-prefix` option to `dash-generate-components`, optionally generates R version of components and corresponding R package. [#483](https://github.com/plotly/dash/pull/483) From b122ba55698bcf6b0ae373631cf1e2896602b38a Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 16:19:39 -0500 Subject: [PATCH 6/8] :bookmark: Version 0.35.1 --- dash/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dash/version.py b/dash/version.py index 2670d05237..288ed76e57 100644 --- a/dash/version.py +++ b/dash/version.py @@ -1 +1 @@ -__version__ = '0.35.0' +__version__ = '0.35.1' From cbfa3f5b0907404c8739efe48c5b99784eb6cc5c Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 19:10:02 -0500 Subject: [PATCH 7/8] :ambulance: Skip dynamic external_url --- dash/dash.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 5133b32adc..b13ee0f050 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -391,11 +391,12 @@ def _relative_url_path(relative_package_path='', namespace=''): namespace=resource['namespace'] )) elif 'external_url' in resource: - if isinstance(resource['external_url'], str): - srcs.append(resource['external_url']) - else: - for url in resource['external_url']: - srcs.append(url) + if not is_dynamic_resource: + if isinstance(resource['external_url'], str): + srcs.append(resource['external_url']) + else: + for url in resource['external_url']: + srcs.append(url) elif 'absolute_path' in resource: raise Exception( 'Serving files from absolute_path isn\'t supported yet' From 13f3ad370d121aa967f7aa6589e4c321d9f60b28 Mon Sep 17 00:00:00 2001 From: t4rk1n Date: Thu, 27 Dec 2018 19:20:59 -0500 Subject: [PATCH 8/8] :lipstick: Use assertEqual --- tests/test_resources.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_resources.py b/tests/test_resources.py index 767d92ef07..38b4351f2f 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -54,11 +54,11 @@ def test_external(self): app.scripts.get_all_scripts() ) - assert resource == [ + self.assertEqual(resource, [ 'https://external_javascript.js', 'https://external_css.css', 'https://component_library.bundle.js' - ] + ]) def test_internal(self): app = dash.Dash( @@ -76,14 +76,14 @@ def test_internal(self): app.scripts.get_all_scripts() ) - assert resource == [ + self.assertEqual(resource, [ '/_dash-component-suites/' 'dash_core_components/external_javascript.js?v=1&m=1', '/_dash-component-suites/' 'dash_core_components/external_css.css?v=1&m=1', '/_dash-component-suites/' 'dash_core_components/fake_dcc.js?v=1&m=1', - ] + ]) self.assertTrue( 'fake_dcc.min.js.map'