Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Unit tests with Jest + Enzyme and updates to Tabs component by valentijnnieman · Pull Request #315 · plotly/dash-core-components · GitHub
Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .babelrc
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
{
"presets": ["env", "react"],
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
}
"env": {
"production": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"development": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel"]
},
"test": {
"plugins": ["transform-object-rest-spread", "styled-jsx/babel-test"]

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we use (a brand new) plugin babel-test, so that Jest will use Babel and styled-jsx, but won't parse the classes to jsx-1324 or whatever, so that we can make assertions on them!

}
}
}
134 changes: 67 additions & 67 deletions .circleci/config.yml
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,84 @@
version: 2

jobs:
"python-2.7": &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27
'python-2.7': &test-template
docker:
- image: circleci/python:2.7-stretch-node-browsers
environment:
PYTHON_VERSION: py27

steps:
- checkout
steps:
- checkout

- run:
name: Create virtual env
command: python -m venv || virtualenv venv
- run:
name: Create virtual env
command: python -m venv || virtualenv venv

- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt
- run:
name: Write job name
command: echo $CIRCLE_JOB > circlejob.txt

- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}

- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts
- run:
name: Install dependencies
command: |
sudo pip install virtualenv --upgrade
. venv/bin/activate
pip install -r requirements-dev.txt
npm install --ignore-scripts

- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- "venv"
- "node_modules"
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }}-{{ checksum ".circleci/config.yml" }}-{{ checksum "circlejob.txt" }}
paths:
- 'venv'
- 'node_modules'

- run:
name: prettier --list-different
command: npm run format:test
- run:
name: prettier --list-different
command: npm run format:test

- run:
name: npm run lint
command: npm run lint
- run:
name: npm run lint
command: npm run lint

- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py
- run:
name: Build
command: |
. venv/bin/activate
npm run build:js
npm run build:py

- run:
name: Run tests
command: |
. venv/bin/activate
python --version
python -m unittest test.test_integration
python -m unittest test.test_dash_import
- run:
name: Run tests
command: |
. venv/bin/activate
python --version
npm run test-unit

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real difference apart from formatting - running the new unit tests in CircleCI.

python -m unittest test.test_integration
python -m unittest test.test_dash_import

"python-3.6":
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

"python-3.7":
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0
'python-3.6':
<<: *test-template
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
PYTHON_VERSION: py36
PERCY_ENABLE: 0

'python-3.7':
<<: *test-template
docker:
- image: circleci/python:3.7-stretch-node-browsers
environment:
PYTHON_VERSION: py37
PERCY_ENABLE: 0

workflows:
version: 2
build:
jobs:
- "python-2.7"
- "python-3.6"
- "python-3.7"
version: 2
build:
jobs:
- 'python-2.7'
- 'python-3.6'
- 'python-3.7'
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
# Change Log for dash-core-components
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [0.34.0] - 2018-10-17
### Added
- `npm run test-unit` will run new Jest+Enzyme unit tests
- Unit tests for Tabs component
### Fixed
- Fixed bug in Tabs component where value was resetting if using callback-less mode [#331](https://github.com/plotly/dash-core-components/issues/331)
- Fixed bug with default Tabs value not being set to children's Tab value (if it's set)
- Fixed bug where Tabs.children.props wheren't being selected properly, related to [#84](https://github.com/plotly/dash-renderer/issues/84)

## [0.33.1] -- 2018-10-17
### Fixed
Expand Down
134 changes: 67 additions & 67 deletions dash_core_components/Store.py
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,67 @@
# AUTO GENERATED FILE - DO NOT EDIT
from dash.development.base_component import Component, _explicitize_args
class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.
Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.
memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.
Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []
_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}
for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)
def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
# AUTO GENERATED FILE - DO NOT EDIT

from dash.development.base_component import Component, _explicitize_args


class Store(Component):
"""A Store component.
Easily keep data on the client side with this component.
The data is not inserted in the DOM.
Data can be in memory, localStorage or sessionStorage.
The data will be kept with the id as key.

Keyword arguments:
- id (string; required): The key of the storage.
- storage_type (a value equal to: 'local', 'session', 'memory'; optional): The type of the web storage.

memory: only kept in memory, reset on page refresh.
local: window.localStorage, data is kept after the browser quit.
session: window.sessionStorage, data is cleared once the browser quit.
- data (dict | list | number | string; optional): The stored data for the id.
- clear_data (boolean; optional): Set to true to remove the data contained in `data_key`.
- modified_timestamp (number; optional): The last time the storage was modified.

Available events: """
@_explicitize_args
def __init__(self, id=Component.REQUIRED, storage_type=Component.UNDEFINED, data=Component.UNDEFINED, clear_data=Component.UNDEFINED, modified_timestamp=Component.UNDEFINED, **kwargs):
self._prop_names = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self._type = 'Store'
self._namespace = 'dash_core_components'
self._valid_wildcard_attributes = []
self.available_events = []
self.available_properties = ['id', 'storage_type', 'data', 'clear_data', 'modified_timestamp']
self.available_wildcard_properties = []

_explicit_args = kwargs.pop('_explicit_args')
_locals = locals()
_locals.update(kwargs) # For wildcard attrs
args = {k: _locals[k] for k in _explicit_args if k != 'children'}

for k in ['id']:
if k not in args:
raise TypeError(
'Required argument `' + k + '` was not specified.')
super(Store, self).__init__(**args)

def __repr__(self):
if(any(getattr(self, c, None) is not None
for c in self._prop_names
if c is not self._prop_names[0])
or any(getattr(self, c, None) is not None
for c in self.__dict__.keys()
if any(c.startswith(wc_attr)
for wc_attr in self._valid_wildcard_attributes))):
props_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self._prop_names
if getattr(self, c, None) is not None])
wilds_string = ', '.join([c+'='+repr(getattr(self, c, None))
for c in self.__dict__.keys()
if any([c.startswith(wc_attr)
for wc_attr in
self._valid_wildcard_attributes])])
return ('Store(' + props_string +
(', ' + wilds_string if wilds_string != '' else '') + ')')
else:
return (
'Store(' +
repr(getattr(self, self._prop_names[0], None)) + ')')
2 changes: 1 addition & 1 deletion dash_core_components/Tab.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ class Tab(Component):
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- label (optional): The tab's label
- label (string; optional): The tab's label
- value (string; optional): Value for determining which Tab is currently selected
- disabled (boolean; optional): Determines if tab is disabled or not - defaults to false
- disabled_style (dict; optional): Overrides the default (inline) styles when disabled
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/Tabs.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ class Tabs(Component):
children components that will be that tab's content.

Keyword arguments:
- children (a list of or a singular dash component, string or number; optional): Array that holds Tab components
- children (list | a list of or a singular dash component, string or number; optional): Array that holds Tab components
- id (string; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
Expand Down
Loading