mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Remove deprecated elements and adds deprecation banner to pys-on (#1084)
* Show deprecation banner * Add test for deprecation warning * Remove deprecated elements * Add entry in changelog * Update test_style * Remove random color rule * Add PR link to changelog
This commit is contained in:
@@ -1,24 +1,14 @@
|
||||
import type { Runtime } from '../runtime';
|
||||
import { make_PyRepl } from './pyrepl';
|
||||
import { PyBox } from './pybox';
|
||||
import { make_PyButton } from './pybutton';
|
||||
import { PyTitle } from './pytitle';
|
||||
import { make_PyInputBox } from './pyinputbox';
|
||||
import { make_PyWidget } from './pywidget';
|
||||
|
||||
function createCustomElements(runtime: Runtime) {
|
||||
const PyInputBox = make_PyInputBox(runtime);
|
||||
const PyButton = make_PyButton(runtime);
|
||||
const PyWidget = make_PyWidget(runtime);
|
||||
const PyRepl = make_PyRepl(runtime);
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
const xPyRepl = customElements.define('py-repl', PyRepl);
|
||||
const xPyBox = customElements.define('py-box', PyBox);
|
||||
const xPyTitle = customElements.define('py-title', PyTitle);
|
||||
const xPyWidget = customElements.define('py-register-widget', PyWidget);
|
||||
const xPyInputBox = customElements.define('py-inputbox', PyInputBox);
|
||||
const xPyButton = customElements.define('py-button', PyButton);
|
||||
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||
}
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import { getAttribute, addClasses, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
|
||||
const logger = getLogger('py-box');
|
||||
|
||||
export class PyBox extends HTMLElement {
|
||||
shadow: ShadowRoot;
|
||||
wrapper: HTMLElement;
|
||||
theme: string;
|
||||
widths: string[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// attach shadow so we can preserve the element original innerHtml content
|
||||
this.shadow = this.attachShadow({ mode: 'open' });
|
||||
|
||||
this.wrapper = document.createElement('slot');
|
||||
this.shadow.appendChild(this.wrapper);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage =
|
||||
'The element <py-box> is deprecated, you should create a ' +
|
||||
'div with "py-box" class name instead. For example: <div class="py-box">';
|
||||
createDeprecationWarning(deprecationMessage, 'py-box');
|
||||
const mainDiv = document.createElement('div');
|
||||
addClasses(mainDiv, ['py-box']);
|
||||
|
||||
// Hack: for some reason when moving children, the editor box duplicates children
|
||||
// meaning that we end up with 2 editors, if there's a <py-repl> inside the <py-box>
|
||||
// so, if we have more than 2 children with the cm-editor class, we remove one of them
|
||||
while (this.childNodes.length > 0) {
|
||||
if (this.firstChild.nodeName == 'PY-REPL') {
|
||||
// in this case we need to remove the child and create a new one from scratch
|
||||
const replDiv = document.createElement('div');
|
||||
// we need to put the new repl inside a div so that if the repl has auto-generate true
|
||||
// it can replicate itself inside that constrained div
|
||||
replDiv.appendChild(this.firstChild.cloneNode());
|
||||
mainDiv.appendChild(replDiv);
|
||||
this.firstChild.remove();
|
||||
} else {
|
||||
if (this.firstChild.nodeName != '#text') {
|
||||
mainDiv.appendChild(this.firstChild);
|
||||
} else {
|
||||
this.firstChild.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we need to set widths
|
||||
this.widths = [];
|
||||
|
||||
const widthsAttr = getAttribute(this, 'widths');
|
||||
if (widthsAttr) {
|
||||
for (const w of widthsAttr.split(';')) {
|
||||
if (w.includes('/')) {
|
||||
this.widths.push(w.split('/')[0]);
|
||||
} else {
|
||||
this.widths.push(w);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.widths = Array<string>(mainDiv.children.length).fill('1 1 0');
|
||||
}
|
||||
|
||||
this.widths.forEach((width, index) => {
|
||||
const node: ChildNode = mainDiv.childNodes[index];
|
||||
(<HTMLElement>node).style.flex = width;
|
||||
addClasses(<HTMLElement>node, ['py-box-child']);
|
||||
});
|
||||
|
||||
this.appendChild(mainDiv);
|
||||
logger.info('py-box connected');
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import type { Runtime } from '../runtime';
|
||||
|
||||
const logger = getLogger('py-button');
|
||||
|
||||
export function make_PyButton(runtime: Runtime) {
|
||||
class PyButton extends HTMLElement {
|
||||
widths: string[] = [];
|
||||
label: string | undefined = undefined;
|
||||
class: string[];
|
||||
defaultClass: string[];
|
||||
mount_name: string | undefined = undefined;
|
||||
code: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.defaultClass = ['py-button'];
|
||||
|
||||
const label = getAttribute(this, 'label');
|
||||
if (label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
// Styling does the same thing as class in normal HTML. Using the name "class" makes the style to malfunction
|
||||
const styling = getAttribute(this, 'styling');
|
||||
if (styling) {
|
||||
const klass = styling.trim();
|
||||
if (klass === '') {
|
||||
this.class = this.defaultClass;
|
||||
} else {
|
||||
// trim each element to remove unnecessary spaces which makes the button style to malfunction
|
||||
this.class = klass
|
||||
.split(' ')
|
||||
.map(x => x.trim())
|
||||
.filter(x => x !== '');
|
||||
}
|
||||
} else {
|
||||
this.class = this.defaultClass;
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage =
|
||||
'The element <py-button> is deprecated, create a function with your ' +
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.';
|
||||
createDeprecationWarning(deprecationMessage, 'py-button');
|
||||
|
||||
ensureUniqueId(this);
|
||||
this.code = htmlDecode(this.innerHTML) || '';
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
const mainDiv = document.createElement('button');
|
||||
mainDiv.innerHTML = this.label;
|
||||
addClasses(mainDiv, this.class);
|
||||
|
||||
mainDiv.id = this.id;
|
||||
this.id = `${this.id}-container`;
|
||||
|
||||
this.appendChild(mainDiv);
|
||||
this.code = this.code.split('self').join(this.mount_name);
|
||||
let registrationCode = `from pyodide.ffi import create_proxy`;
|
||||
registrationCode += `\n${this.mount_name} = Element("${mainDiv.id}")`;
|
||||
if (this.code.includes('def on_focus')) {
|
||||
this.code = this.code.replace('def on_focus', `def on_focus_${this.mount_name}`);
|
||||
registrationCode += `\n${this.mount_name}.element.addEventListener('focus', create_proxy(on_focus_${this.mount_name}))`;
|
||||
}
|
||||
|
||||
if (this.code.includes('def on_click')) {
|
||||
this.code = this.code.replace('def on_click', `def on_click_${this.mount_name}`);
|
||||
registrationCode += `\n${this.mount_name}.element.addEventListener('click', create_proxy(on_click_${this.mount_name}))`;
|
||||
}
|
||||
|
||||
// now that we appended and the element is attached, lets connect with the event handlers
|
||||
// defined for this widget
|
||||
runtime.runButDontRaise(this.code);
|
||||
runtime.runButDontRaise(registrationCode);
|
||||
logger.debug('py-button connected');
|
||||
}
|
||||
}
|
||||
|
||||
return PyButton;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { getAttribute, addClasses, htmlDecode, ensureUniqueId, createDeprecationWarning } from '../utils';
|
||||
import { getLogger } from '../logger';
|
||||
import type { Runtime } from '../runtime';
|
||||
|
||||
const logger = getLogger('py-inputbox');
|
||||
|
||||
export function make_PyInputBox(runtime: Runtime) {
|
||||
class PyInputBox extends HTMLElement {
|
||||
widths: string[] = [];
|
||||
label: string | undefined = undefined;
|
||||
mount_name: string | undefined = undefined;
|
||||
code: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const label = getAttribute(this, 'label');
|
||||
if (label) {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage =
|
||||
'The element <py-input> is deprecated, ' + 'use <input class="py-input"> instead.';
|
||||
createDeprecationWarning(deprecationMessage, 'py-input');
|
||||
ensureUniqueId(this);
|
||||
this.code = htmlDecode(this.innerHTML);
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
const mainDiv = document.createElement('input');
|
||||
mainDiv.type = 'text';
|
||||
addClasses(mainDiv, ['py-input']);
|
||||
|
||||
mainDiv.id = this.id;
|
||||
this.id = `${this.id}-container`;
|
||||
this.appendChild(mainDiv);
|
||||
|
||||
// now that we appended and the element is attached, lets connect with the event handlers
|
||||
// defined for this widget
|
||||
this.appendChild(mainDiv);
|
||||
this.code = this.code.split('self').join(this.mount_name);
|
||||
let registrationCode = `from pyodide.ffi import create_proxy`;
|
||||
registrationCode += `\n${this.mount_name} = Element("${mainDiv.id}")`;
|
||||
if (this.code.includes('def on_keypress')) {
|
||||
this.code = this.code.replace('def on_keypress', `def on_keypress_${this.mount_name}`);
|
||||
registrationCode += `\n${this.mount_name}.element.addEventListener('keypress', create_proxy(on_keypress_${this.mount_name}))`;
|
||||
}
|
||||
|
||||
runtime.runButDontRaise(this.code);
|
||||
runtime.runButDontRaise(registrationCode);
|
||||
logger.debug('py-inputbox connected');
|
||||
}
|
||||
}
|
||||
|
||||
return PyInputBox;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { htmlDecode, ensureUniqueId, showWarning } from '../utils';
|
||||
import { htmlDecode, ensureUniqueId, showWarning, createDeprecationWarning } from '../utils';
|
||||
import type { Runtime } from '../runtime';
|
||||
import { getLogger } from '../logger';
|
||||
import { pyExec } from '../pyexec';
|
||||
@@ -165,9 +165,10 @@ function createElementsWithEventListeners(runtime: Runtime, pyAttribute: string)
|
||||
const event = pyAttributeToEvent.get(pyAttribute);
|
||||
|
||||
if (pyAttribute === 'pys-onClick' || pyAttribute === 'pys-onKeyDown') {
|
||||
console.warn(
|
||||
'Use of pys-onClick and pys-onKeyDown attributes is deprecated in favor of py-onClick() and py-onKeyDown(). pys-on* attributes will be deprecated in a future version of PyScript.',
|
||||
);
|
||||
const msg =
|
||||
`The attribute 'pys-onClick' and 'pys-onKeyDown' are deprecated. Please 'py-click="myFunction()"' ` +
|
||||
` or 'py-keydown="myFunction()"' instead.`;
|
||||
createDeprecationWarning(msg, msg);
|
||||
const source = `
|
||||
from pyodide.ffi import create_proxy
|
||||
Element("${el.id}").element.addEventListener("${event}", create_proxy(${handlerCode}))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { addClasses, htmlDecode, createDeprecationWarning } from '../utils';
|
||||
|
||||
export class PyTitle extends HTMLElement {
|
||||
widths: string[];
|
||||
label: string;
|
||||
mount_name: string;
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const deprecationMessage = 'The element <py-title> is deprecated, please use an <h1> tag instead.';
|
||||
createDeprecationWarning(deprecationMessage, 'py-title');
|
||||
this.label = htmlDecode(this.innerHTML);
|
||||
this.mount_name = this.id.split('-').join('_');
|
||||
this.innerHTML = '';
|
||||
|
||||
const mainDiv = document.createElement('div');
|
||||
const divContent = document.createElement('h1');
|
||||
|
||||
addClasses(mainDiv, ['py-title']);
|
||||
divContent.innerHTML = this.label;
|
||||
|
||||
mainDiv.id = this.id;
|
||||
this.id = `${this.id}-container`;
|
||||
mainDiv.appendChild(divContent);
|
||||
this.appendChild(mainDiv);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,6 @@ html {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
color: #0f172a;
|
||||
.py-pop-up {
|
||||
text-align: center;
|
||||
width: 600px;
|
||||
|
||||
@@ -292,3 +292,22 @@ class TestBasic(PyScriptTest):
|
||||
pyscript_tag.evaluate("node => node.getPySrc()")
|
||||
== 'print("hello world!")\n'
|
||||
)
|
||||
|
||||
def test_pys_onClick_shows_deprecation_warning(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<button id="1" pys-onClick="myfunc()">Click me</button>
|
||||
<py-script>
|
||||
def myfunc():
|
||||
print("hello world")
|
||||
|
||||
</py-script>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".alert-banner")
|
||||
expected_message = (
|
||||
"The attribute 'pys-onClick' and 'pys-onKeyDown' are "
|
||||
"deprecated. Please 'py-click=\"myFunction()\"' or "
|
||||
"'py-keydown=\"myFunction()\"' instead."
|
||||
)
|
||||
assert banner.inner_text() == expected_message
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
from .support import PyScriptTest
|
||||
|
||||
|
||||
class TestPyButton(PyScriptTest):
|
||||
def test_box(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-box>
|
||||
<py-box>
|
||||
</py-box>
|
||||
</py-box>
|
||||
"""
|
||||
)
|
||||
|
||||
pybox_element = self.page.query_selector_all("py-box")
|
||||
|
||||
assert len(pybox_element) == 2
|
||||
assert pybox_element[1].get_attribute("class") == "py-box-child"
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-box>
|
||||
</py-box>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-box> is deprecated, you should create a div "
|
||||
'with "py-box" class name instead. For example: <div class="py-box">'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
@@ -1,60 +0,0 @@
|
||||
from .support import PyScriptTest
|
||||
|
||||
|
||||
class TestPyButton(PyScriptTest):
|
||||
def test_on_click(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-button label="my button">
|
||||
import js
|
||||
def on_click(evt):
|
||||
js.console.log('clicked!')
|
||||
</py-button>
|
||||
"""
|
||||
)
|
||||
assert self.console.log.lines[0] == self.PY_COMPLETE
|
||||
self.page.locator("text=my button").click()
|
||||
self.page.locator("text=my button").click()
|
||||
|
||||
assert self.console.log.lines[-2:] == ["clicked!", "clicked!"]
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-button label="my button">
|
||||
import js
|
||||
def on_click(evt):
|
||||
js.console.log('clicked!')
|
||||
</py-button>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-button> is deprecated, create a function with your "
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
|
||||
def test_creates_single_deprecation_banner(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-button label="my button">
|
||||
import js
|
||||
def on_click(evt):
|
||||
js.console.log('clicked!')
|
||||
</py-button>
|
||||
<py-button label="another button!">
|
||||
</py-button>
|
||||
"""
|
||||
)
|
||||
banner = self.page.query_selector_all(".py-warning")
|
||||
assert len(banner) == 1
|
||||
banner_content = banner[0].inner_text()
|
||||
expected = (
|
||||
"The element <py-button> is deprecated, create a function with your "
|
||||
'inline code and use <button py-click="function()" class="py-button"> instead.'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
@@ -1,42 +0,0 @@
|
||||
from .support import PyScriptTest
|
||||
|
||||
|
||||
class TestPyInputBox(PyScriptTest):
|
||||
def test_input_box_typing(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-inputbox label="my input">
|
||||
import js
|
||||
def on_keypress(evt):
|
||||
if evt.key == "Enter":
|
||||
js.console.log(evt.target.value)
|
||||
</py-inputbox>
|
||||
"""
|
||||
)
|
||||
assert self.console.log.lines[0] == self.PY_COMPLETE
|
||||
input = self.page.locator("input")
|
||||
|
||||
input.type("Hello")
|
||||
input.press("Enter")
|
||||
|
||||
assert self.console.log.lines[-1] == "Hello"
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-inputbox label="my input">
|
||||
import js
|
||||
def on_keypress(evt):
|
||||
if evt.key == "Enter":
|
||||
js.console.log(evt.target.value)
|
||||
</py-inputbox>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-input> is deprecated, "
|
||||
'use <input class="py-input"> instead.'
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
@@ -1,30 +0,0 @@
|
||||
from .support import PyScriptTest
|
||||
|
||||
|
||||
class TestPyTitle(PyScriptTest):
|
||||
def test_title_shows_on_page(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-title>Hello, World!</py-title>
|
||||
"""
|
||||
)
|
||||
|
||||
py_title = self.page.query_selector("py-title")
|
||||
# check that we do have py-title in the page, if not
|
||||
# py_title will be none
|
||||
assert py_title
|
||||
assert py_title.text_content() == "Hello, World!"
|
||||
|
||||
def test_deprecated_element(self):
|
||||
self.pyscript_run(
|
||||
"""
|
||||
<py-title>Hello, world!</py-title>
|
||||
"""
|
||||
)
|
||||
banner = self.page.locator(".py-warning")
|
||||
banner_content = banner.inner_text()
|
||||
expected = (
|
||||
"The element <py-title> is deprecated, please use an <h1> tag instead."
|
||||
)
|
||||
|
||||
assert banner_content == expected
|
||||
@@ -15,10 +15,6 @@ class TestStyle(PyScriptTest):
|
||||
<py-config>hello</py-config>
|
||||
<py-script>hello</py-script>
|
||||
<py-repl>hello</py-repl>
|
||||
<py-title>hello</py-title>
|
||||
<py-inputbox>hello</py-inputbox>
|
||||
<py-button>hello</py-button>
|
||||
<py-box>hello</py-box>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
@@ -27,10 +23,6 @@ class TestStyle(PyScriptTest):
|
||||
expect(self.page.locator("py-config")).to_be_hidden()
|
||||
expect(self.page.locator("py-script")).to_be_hidden()
|
||||
expect(self.page.locator("py-repl")).to_be_hidden()
|
||||
expect(self.page.locator("py-title")).to_be_hidden()
|
||||
expect(self.page.locator("py-inputbox")).to_be_hidden()
|
||||
expect(self.page.locator("py-button")).to_be_hidden()
|
||||
expect(self.page.locator("py-box")).to_be_hidden()
|
||||
|
||||
def test_pyscript_defined(self):
|
||||
"""Test elements have visibility that should"""
|
||||
@@ -41,26 +33,8 @@ class TestStyle(PyScriptTest):
|
||||
</py-config>
|
||||
<py-script>display("hello")</py-script>
|
||||
<py-repl>display("hello")</py-repl>
|
||||
<py-title>hello</py-title>
|
||||
<py-inputbox label="my input">
|
||||
import js
|
||||
def on_keypress(evt):
|
||||
if evt.key == "Enter":
|
||||
js.console.log(evt.target.value)
|
||||
</py-inputbox>
|
||||
<py-box>
|
||||
<py-button label="my button">
|
||||
import js
|
||||
def on_click(evt):
|
||||
js.console.log('clicked!')
|
||||
</py-button>
|
||||
</py-box>
|
||||
"""
|
||||
)
|
||||
expect(self.page.locator("py-config")).to_be_hidden()
|
||||
expect(self.page.locator("py-script")).to_be_visible()
|
||||
expect(self.page.locator("py-repl")).to_be_visible()
|
||||
expect(self.page.locator("py-title")).to_be_visible()
|
||||
expect(self.page.locator("py-inputbox")).to_be_visible()
|
||||
expect(self.page.locator("py-button")).to_be_visible()
|
||||
expect(self.page.locator("py-box")).to_be_visible()
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { PyBox } from "../../src/components/pybox"
|
||||
|
||||
customElements.define('py-box', PyBox)
|
||||
|
||||
describe('PyBox', () => {
|
||||
let instance: PyBox;
|
||||
|
||||
beforeEach(() => {
|
||||
instance = new PyBox();
|
||||
})
|
||||
|
||||
it('PyBox instantiates correctly', async () => {
|
||||
expect(instance).toBeInstanceOf(PyBox)
|
||||
})
|
||||
|
||||
it("test connectedCallback creates pybox div", async () => {
|
||||
expect(instance.innerHTML).toBe("")
|
||||
instance.connectedCallback()
|
||||
|
||||
expect(instance.innerHTML).toBe('<div class=\"py-box\"></div>')
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,88 +0,0 @@
|
||||
import type { Runtime } from "../../src/runtime"
|
||||
import { FakeRuntime } from "./fakeruntime"
|
||||
import { make_PyButton } from '../../src/components/pybutton';
|
||||
import { ensureUniqueId } from '../../src/utils';
|
||||
|
||||
const runtime: Runtime = new FakeRuntime();
|
||||
const PyButton = make_PyButton(runtime);
|
||||
customElements.define('py-button', PyButton);
|
||||
|
||||
describe('PyButton', () => {
|
||||
let instance;
|
||||
beforeEach(() => {
|
||||
instance = new PyButton();
|
||||
// Remove all the alert banners created when calling `connectedCallback`
|
||||
const banners = document.getElementsByClassName("alert-banner")
|
||||
for (const banner of banners) {
|
||||
banner.remove()
|
||||
}
|
||||
});
|
||||
|
||||
it('should get the Button to just instantiate', async () => {
|
||||
expect(instance).toBeInstanceOf(PyButton);
|
||||
});
|
||||
|
||||
it('onCallback gets or sets a new id', async () => {
|
||||
expect(instance.id).toBe('');
|
||||
|
||||
instance.connectedCallback();
|
||||
const instanceId = instance.id;
|
||||
// id should be similar to py-4850c8c3-d70d-d9e0-03c1-3cfeb0bcec0d-container
|
||||
expect(instanceId).toMatch(/py-(\w+-){1,5}container/);
|
||||
|
||||
// ensureUniqueId doesn't change the ID
|
||||
ensureUniqueId(instance);
|
||||
expect(instance.id).toEqual(instanceId);
|
||||
});
|
||||
|
||||
it('onCallback updates on_click code and function name ', async () => {
|
||||
expect(instance.code).toBe(undefined);
|
||||
expect(instance.innerHTML).toBe('');
|
||||
|
||||
instance.innerHTML = '\ndef on_click(e):\n';
|
||||
|
||||
instance.connectedCallback();
|
||||
|
||||
expect(instance.code).toMatch(/def\son_click_py_(\w+)\(e\)/);
|
||||
expect(instance.innerHTML).toContain('<button class="py-button"');
|
||||
});
|
||||
|
||||
it('onCallback updates on_focus code and function name', async () => {
|
||||
expect(instance.code).toBe(undefined);
|
||||
expect(instance.innerHTML).toBe('');
|
||||
|
||||
instance.innerHTML = '\ndef on_focus(e):\n';
|
||||
|
||||
instance.connectedCallback();
|
||||
|
||||
expect(instance.code).toMatch(/def\son_focus_py_(\w+)\(e\)/);
|
||||
expect(instance.innerHTML).toContain('<button class="py-button"');
|
||||
});
|
||||
|
||||
it('onCallback sets mount_name based on id', async () => {
|
||||
expect(instance.id).toBe('');
|
||||
expect(instance.mount_name).toBe(undefined);
|
||||
|
||||
instance.connectedCallback();
|
||||
|
||||
const instanceId = instance.id;
|
||||
|
||||
expect(instanceId).toMatch(/py-(\w+-){1,5}container/);
|
||||
expect(instance.mount_name).toBe(instanceId.replace('-container', '').split('-').join('_'));
|
||||
});
|
||||
|
||||
it('should create a single deprecation banner', async () => {
|
||||
document.body.innerHTML = ""
|
||||
let alertBanners = document.getElementsByClassName('alert-banner');
|
||||
expect(alertBanners.length).toBe(0);
|
||||
|
||||
instance.connectedCallback();
|
||||
expect(alertBanners.length).toBe(1);
|
||||
expect(alertBanners[0].innerHTML).toContain("<py-button> is deprecated");
|
||||
|
||||
// Calling `connectedCallback` again should not create a new banner
|
||||
instance.connectedCallback();
|
||||
alertBanners = document.getElementsByClassName('alert-banner');
|
||||
expect(alertBanners.length).toBe(1);
|
||||
})
|
||||
});
|
||||
@@ -1,62 +0,0 @@
|
||||
import { jest } from "@jest/globals"
|
||||
import type { Runtime } from "../../src/runtime"
|
||||
import { FakeRuntime } from "./fakeruntime"
|
||||
import { make_PyInputBox } from "../../src/components/pyinputbox"
|
||||
import { ensureUniqueId } from '../../src/utils';
|
||||
|
||||
const runtime: Runtime = new FakeRuntime();
|
||||
const PyInputBox = make_PyInputBox(runtime);
|
||||
|
||||
customElements.define('py-inputbox', PyInputBox)
|
||||
|
||||
describe("PyInputBox", () => {
|
||||
|
||||
let instance;
|
||||
|
||||
beforeEach(() => {
|
||||
instance = new PyInputBox()
|
||||
instance.runAfterRuntimeInitialized = jest.fn();
|
||||
})
|
||||
|
||||
it("PyInputBox instantiates correctly", async () => {
|
||||
expect(instance).toBeInstanceOf(PyInputBox)
|
||||
})
|
||||
|
||||
it('connectedCallback gets or sets a new id', async () => {
|
||||
expect(instance.id).toBe('');
|
||||
|
||||
instance.connectedCallback();
|
||||
const instanceId = instance.id;
|
||||
// id should be similar to py-4850c8c3-d70d-d9e0-03c1-3cfeb0bcec0d-container
|
||||
expect(instanceId).toMatch(/py-(\w+-){1,5}container/);
|
||||
|
||||
// ensureUniqueId doesn't change the ID
|
||||
ensureUniqueId(instance);
|
||||
expect(instance.id).toEqual(instanceId);
|
||||
});
|
||||
|
||||
it('onCallback sets mount_name based on id', async () => {
|
||||
expect(instance.id).toBe('');
|
||||
expect(instance.mount_name).toBe(undefined);
|
||||
|
||||
instance.connectedCallback();
|
||||
|
||||
const instanceId = instance.id;
|
||||
|
||||
expect(instanceId).toMatch(/py-(\w+-){1,5}container/);
|
||||
expect(instance.mount_name).toBe(instanceId.replace('-container', '').split('-').join('_'));
|
||||
});
|
||||
|
||||
it('onCallback updates on_keypress code and function name ', async () => {
|
||||
expect(instance.code).toBe(undefined);
|
||||
expect(instance.innerHTML).toBe('');
|
||||
|
||||
instance.innerHTML = '\ndef on_keypress(e):\n';
|
||||
|
||||
instance.connectedCallback();
|
||||
|
||||
expect(instance.code).toMatch(/def\son_keypress_py_(\w+)\(e\)/);
|
||||
expect(instance.innerHTML).toContain('<input type="text" class="py-input"');
|
||||
});
|
||||
|
||||
})
|
||||
@@ -1,35 +0,0 @@
|
||||
import { PyTitle } from "../../src/components/pytitle"
|
||||
|
||||
|
||||
customElements.define("py-title", PyTitle);
|
||||
|
||||
|
||||
describe("PyTitle", () => {
|
||||
let instance: PyTitle;
|
||||
|
||||
beforeEach(() => {
|
||||
instance = new PyTitle();
|
||||
})
|
||||
|
||||
it("PyTitle instantiates correctly", async () => {
|
||||
expect(instance).toBeInstanceOf(PyTitle);
|
||||
})
|
||||
|
||||
it("test connectedCallback defaults", async () => {
|
||||
instance.connectedCallback();
|
||||
expect(instance.label).toBe("")
|
||||
expect(instance.mount_name).toBe("")
|
||||
expect(instance.innerHTML).toBe(`<div class=\"py-title\" id=\"\"><h1></h1></div>`)
|
||||
})
|
||||
|
||||
it("label renders correctly on the page and updates id", async () => {
|
||||
instance.innerHTML = "Hello, world!";
|
||||
instance.id = "my-fancy-title";
|
||||
|
||||
instance.connectedCallback();
|
||||
|
||||
expect(instance.label).toBe("Hello, world!")
|
||||
expect(instance.mount_name).toMatch("my_fancy_title");
|
||||
expect(instance.innerHTML).toContain("<h1>Hello, world!</h1>")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user