mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Add more type definitions (#882)
* More typing to base.ts * Add more types * More types
This commit is contained in:
37
pyscriptjs/package-lock.json
generated
37
pyscriptjs/package-lock.json
generated
@@ -22,6 +22,7 @@
|
|||||||
"@rollup/plugin-legacy": "2.2.0",
|
"@rollup/plugin-legacy": "2.2.0",
|
||||||
"@rollup/plugin-node-resolve": "14.1.0",
|
"@rollup/plugin-node-resolve": "14.1.0",
|
||||||
"@rollup/plugin-typescript": "8.5.0",
|
"@rollup/plugin-typescript": "8.5.0",
|
||||||
|
"@types/codemirror": "^5.60.5",
|
||||||
"@types/jest": "29.1.2",
|
"@types/jest": "29.1.2",
|
||||||
"@types/node": "18.8.3",
|
"@types/node": "18.8.3",
|
||||||
"@typescript-eslint/eslint-plugin": "5.39.0",
|
"@typescript-eslint/eslint-plugin": "5.39.0",
|
||||||
@@ -1510,6 +1511,15 @@
|
|||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/codemirror": {
|
||||||
|
"version": "5.60.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||||
|
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/tern": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "0.0.39",
|
"version": "0.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
||||||
@@ -1628,6 +1638,15 @@
|
|||||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/tern": {
|
||||||
|
"version": "0.23.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||||
|
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/tough-cookie": {
|
"node_modules/@types/tough-cookie": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
|
||||||
@@ -7364,6 +7383,15 @@
|
|||||||
"@babel/types": "^7.3.0"
|
"@babel/types": "^7.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/codemirror": {
|
||||||
|
"version": "5.60.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||||
|
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/tern": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/estree": {
|
"@types/estree": {
|
||||||
"version": "0.0.39",
|
"version": "0.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
|
||||||
@@ -7482,6 +7510,15 @@
|
|||||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/tern": {
|
||||||
|
"version": "0.23.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||||
|
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/estree": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/tough-cookie": {
|
"@types/tough-cookie": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"@rollup/plugin-legacy": "2.2.0",
|
"@rollup/plugin-legacy": "2.2.0",
|
||||||
"@rollup/plugin-node-resolve": "14.1.0",
|
"@rollup/plugin-node-resolve": "14.1.0",
|
||||||
"@rollup/plugin-typescript": "8.5.0",
|
"@rollup/plugin-typescript": "8.5.0",
|
||||||
|
"@types/codemirror": "^5.60.5",
|
||||||
"@types/jest": "29.1.2",
|
"@types/jest": "29.1.2",
|
||||||
"@types/node": "18.8.3",
|
"@types/node": "18.8.3",
|
||||||
"@typescript-eslint/eslint-plugin": "5.39.0",
|
"@typescript-eslint/eslint-plugin": "5.39.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { basicSetup, EditorView } from 'codemirror';
|
import { basicSetup, EditorView } from 'codemirror';
|
||||||
import { python } from '@codemirror/lang-python';
|
import { python } from '@codemirror/lang-python';
|
||||||
import { indentUnit } from '@codemirror/language'
|
import { indentUnit } from '@codemirror/language'
|
||||||
import { Compartment, StateCommand } from '@codemirror/state';
|
import { Compartment } from '@codemirror/state';
|
||||||
import { keymap } from '@codemirror/view';
|
import { keymap } from '@codemirror/view';
|
||||||
import { defaultKeymap } from '@codemirror/commands';
|
import { defaultKeymap } from '@codemirror/commands';
|
||||||
import { oneDarkTheme } from '@codemirror/theme-one-dark';
|
import { oneDarkTheme } from '@codemirror/theme-one-dark';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { addClasses, htmlDecode, ensureUniqueId } from '../utils';
|
import { addClasses, htmlDecode } from '../utils';
|
||||||
|
|
||||||
export class PyTitle extends HTMLElement {
|
export class PyTitle extends HTMLElement {
|
||||||
widths: string[];
|
widths: string[];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Runtime } from '../runtime';
|
import type { Runtime } from '../runtime';
|
||||||
|
import type {PyProxy} from "pyodide"
|
||||||
import { getLogger } from '../logger';
|
import { getLogger } from '../logger';
|
||||||
|
|
||||||
const logger = getLogger('py-register-widget');
|
const logger = getLogger('py-register-widget');
|
||||||
@@ -12,7 +13,7 @@ function createWidget(runtime: Runtime, name: string, code: string, klass: strin
|
|||||||
name: string = name;
|
name: string = name;
|
||||||
klass: string = klass;
|
klass: string = klass;
|
||||||
code: string = code;
|
code: string = code;
|
||||||
proxy: any;
|
proxy: PyProxy;
|
||||||
proxyClass: any;
|
proxyClass: any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -38,7 +39,9 @@ function createWidget(runtime: Runtime, name: string, code: string, klass: strin
|
|||||||
runtime.globals.set(this.id, this.proxy);
|
runtime.globals.set(this.id, this.proxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
const xPyWidget = customElements.define(name, CustomWidget);
|
const xPyWidget = customElements.define(name, CustomWidget);
|
||||||
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||||
}
|
}
|
||||||
|
|
||||||
export function make_PyWidget(runtime: Runtime) {
|
export function make_PyWidget(runtime: Runtime) {
|
||||||
|
|||||||
@@ -24,10 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
interface Logger {
|
interface Logger {
|
||||||
debug(message: string, ...args: any[]): void;
|
debug(message: string, ...args: unknown[]): void;
|
||||||
info(message: string, ...args: any[]): void;
|
info(message: string, ...args: unknown[]): void;
|
||||||
warn(message: string, ...args: any[]): void;
|
warn(message: string, ...args: unknown[]): void;
|
||||||
error(message: string, ...args: any[]): void;
|
error(message: string, ...args: unknown[]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _cache = new Map<string, Logger>();
|
const _cache = new Map<string, Logger>();
|
||||||
@@ -46,7 +46,7 @@ function _makeLogger(prefix: string): Logger {
|
|||||||
|
|
||||||
function make(level: string) {
|
function make(level: string) {
|
||||||
const out_fn = console[level].bind(console);
|
const out_fn = console[level].bind(console);
|
||||||
function fn(fmt: string, ...args: any[]) {
|
function fn(fmt: string, ...args: unknown[]) {
|
||||||
out_fn(prefix + fmt, ...args);
|
out_fn(prefix + fmt, ...args);
|
||||||
}
|
}
|
||||||
return fn
|
return fn
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ import { getLogger } from './logger';
|
|||||||
import { handleFetchError, showError, globalExport } from './utils'
|
import { handleFetchError, showError, globalExport } from './utils'
|
||||||
import { createCustomElements } from './components/elements';
|
import { createCustomElements } from './components/elements';
|
||||||
|
|
||||||
|
type ImportType = { [key: string]: unknown }
|
||||||
|
type ImportMapType = {
|
||||||
|
imports: ImportType | null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const logger = getLogger('pyscript/main');
|
const logger = getLogger('pyscript/main');
|
||||||
|
|
||||||
@@ -69,7 +74,7 @@ class PyScriptApp {
|
|||||||
// and show a big error. PRs welcome :)
|
// and show a big error. PRs welcome :)
|
||||||
logger.info('searching for <py-config>');
|
logger.info('searching for <py-config>');
|
||||||
const elements = document.getElementsByTagName('py-config');
|
const elements = document.getElementsByTagName('py-config');
|
||||||
let el = null;
|
let el: Element | null = null;
|
||||||
if (elements.length > 0)
|
if (elements.length > 0)
|
||||||
el = elements[0];
|
el = elements[0];
|
||||||
if (elements.length >= 2) {
|
if (elements.length >= 2) {
|
||||||
@@ -188,7 +193,7 @@ class PyScriptApp {
|
|||||||
|
|
||||||
// lifecycle (7)
|
// lifecycle (7)
|
||||||
executeScripts(runtime: Runtime) {
|
executeScripts(runtime: Runtime) {
|
||||||
this.register_importmap(runtime);
|
void this.register_importmap(runtime);
|
||||||
this.PyScript = make_PyScript(runtime);
|
this.PyScript = make_PyScript(runtime);
|
||||||
customElements.define('py-script', this.PyScript);
|
customElements.define('py-script', this.PyScript);
|
||||||
}
|
}
|
||||||
@@ -207,9 +212,9 @@ class PyScriptApp {
|
|||||||
// inside py-script. It's also unclear whether we want to wait or not
|
// inside py-script. It's also unclear whether we want to wait or not
|
||||||
// (or maybe only wait only if we do an actual 'import'?)
|
// (or maybe only wait only if we do an actual 'import'?)
|
||||||
for (const node of document.querySelectorAll("script[type='importmap']")) {
|
for (const node of document.querySelectorAll("script[type='importmap']")) {
|
||||||
const importmap = (() => {
|
const importmap: ImportMapType = (() => {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(node.textContent);
|
return JSON.parse(node.textContent) as ImportMapType;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -224,7 +229,7 @@ class PyScriptApp {
|
|||||||
try {
|
try {
|
||||||
// XXX: pyodide doesn't like Module(), failing with
|
// XXX: pyodide doesn't like Module(), failing with
|
||||||
// "can't read 'name' of undefined" at import time
|
// "can't read 'name' of undefined" at import time
|
||||||
exports = { ...(await import(url)) };
|
exports = { ...(await import(url)) } as object;
|
||||||
} catch {
|
} catch {
|
||||||
logger.warn(`failed to fetch '${url}' for '${name}'`);
|
logger.warn(`failed to fetch '${url}' for '${name}'`);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ export const defaultConfig: AppConfig = {
|
|||||||
|
|
||||||
|
|
||||||
export function loadConfigFromElement(el: Element): AppConfig {
|
export function loadConfigFromElement(el: Element): AppConfig {
|
||||||
let srcConfig;
|
let srcConfig: AppConfig;
|
||||||
let inlineConfig;
|
let inlineConfig: AppConfig;
|
||||||
if (el === null) {
|
if (el === null) {
|
||||||
srcConfig = {};
|
srcConfig = {};
|
||||||
inlineConfig = {};
|
inlineConfig = {};
|
||||||
@@ -127,7 +127,7 @@ function mergeConfig(inlineConfig: AppConfig, externalConfig: AppConfig): AppCon
|
|||||||
|
|
||||||
for (const keyType in allKeys)
|
for (const keyType in allKeys)
|
||||||
{
|
{
|
||||||
const keys = allKeys[keyType];
|
const keys: string[] = allKeys[keyType];
|
||||||
keys.forEach(function(item: string){
|
keys.forEach(function(item: string){
|
||||||
if (keyType === "boolean")
|
if (keyType === "boolean")
|
||||||
{
|
{
|
||||||
@@ -199,14 +199,14 @@ function validateConfig(configText: string, configType = "toml") {
|
|||||||
|
|
||||||
for (const keyType in allKeys)
|
for (const keyType in allKeys)
|
||||||
{
|
{
|
||||||
const keys = allKeys[keyType];
|
const keys: string[] = allKeys[keyType];
|
||||||
keys.forEach(function(item: string){
|
keys.forEach(function(item: string){
|
||||||
if (validateParamInConfig(item, keyType, config))
|
if (validateParamInConfig(item, keyType, config))
|
||||||
{
|
{
|
||||||
if (item === "runtimes")
|
if (item === "runtimes")
|
||||||
{
|
{
|
||||||
finalConfig[item] = [];
|
finalConfig[item] = [];
|
||||||
const runtimes = config[item];
|
const runtimes = config[item] as object[];
|
||||||
runtimes.forEach(function(eachRuntime: object){
|
runtimes.forEach(function(eachRuntime: object){
|
||||||
const runtimeConfig: object = {};
|
const runtimeConfig: object = {};
|
||||||
for (const eachRuntimeParam in eachRuntime)
|
for (const eachRuntimeParam in eachRuntime)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getLogger } from './logger';
|
import { getLogger } from './logger';
|
||||||
import { ensureUniqueId, addClasses } from './utils';
|
import { ensureUniqueId } from './utils';
|
||||||
import type { Runtime } from './runtime';
|
import type { Runtime } from './runtime';
|
||||||
|
|
||||||
const logger = getLogger('pyexec');
|
const logger = getLogger('pyexec');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Runtime } from './runtime';
|
import { Runtime } from './runtime';
|
||||||
import { getLogger } from './logger';
|
import { getLogger } from './logger';
|
||||||
import type { loadPyodide as loadPyodideDeclaration, PyodideInterface } from 'pyodide';
|
import type { loadPyodide as loadPyodideDeclaration, PyodideInterface, PyProxy } from 'pyodide';
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import pyscript from './python/pyscript.py';
|
import pyscript from './python/pyscript.py';
|
||||||
@@ -10,12 +10,17 @@ declare const loadPyodide: typeof loadPyodideDeclaration;
|
|||||||
|
|
||||||
const logger = getLogger('pyscript/pyodide');
|
const logger = getLogger('pyscript/pyodide');
|
||||||
|
|
||||||
|
interface Micropip {
|
||||||
|
install: (packageName: string | string[]) => Promise<void>;
|
||||||
|
destroy: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
export class PyodideRuntime extends Runtime {
|
export class PyodideRuntime extends Runtime {
|
||||||
src: string;
|
src: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
lang?: string;
|
lang?: string;
|
||||||
interpreter: PyodideInterface;
|
interpreter: PyodideInterface;
|
||||||
globals: any;
|
globals: PyProxy;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
config: AppConfig,
|
config: AppConfig,
|
||||||
@@ -83,7 +88,7 @@ export class PyodideRuntime extends Runtime {
|
|||||||
async installPackage(package_name: string | string[]): Promise<void> {
|
async installPackage(package_name: string | string[]): Promise<void> {
|
||||||
if (package_name.length > 0) {
|
if (package_name.length > 0) {
|
||||||
logger.info(`micropip install ${package_name.toString()}`);
|
logger.info(`micropip install ${package_name.toString()}`);
|
||||||
const micropip = this.globals.get('micropip');
|
const micropip = this.globals.get('micropip') as Micropip;
|
||||||
await micropip.install(package_name);
|
await micropip.install(package_name);
|
||||||
micropip.destroy();
|
micropip.destroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { AppConfig } from './pyconfig';
|
import type { AppConfig } from './pyconfig';
|
||||||
import type { PyodideInterface } from 'pyodide';
|
import type { PyodideInterface, PyProxy } from 'pyodide';
|
||||||
import { getLogger } from './logger';
|
import { getLogger } from './logger';
|
||||||
|
|
||||||
const logger = getLogger('pyscript/runtime');
|
const logger = getLogger('pyscript/runtime');
|
||||||
@@ -35,7 +35,7 @@ export abstract class Runtime extends Object {
|
|||||||
/**
|
/**
|
||||||
* global symbols table for the underlying interpreter.
|
* global symbols table for the underlying interpreter.
|
||||||
* */
|
* */
|
||||||
abstract globals: any;
|
abstract globals: PyProxy;
|
||||||
|
|
||||||
constructor(config: AppConfig) {
|
constructor(config: AppConfig) {
|
||||||
super();
|
super();
|
||||||
@@ -54,7 +54,7 @@ export abstract class Runtime extends Object {
|
|||||||
* (asynchronously) which can call its own API behind the scenes.
|
* (asynchronously) which can call its own API behind the scenes.
|
||||||
* Python exceptions are turned into JS exceptions.
|
* Python exceptions are turned into JS exceptions.
|
||||||
* */
|
* */
|
||||||
abstract run(code: string): Promise<any>;
|
abstract run(code: string): Promise<unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as run, but Python exceptions are not propagated: instead, they
|
* Same as run, but Python exceptions are not propagated: instead, they
|
||||||
@@ -63,9 +63,10 @@ export abstract class Runtime extends Object {
|
|||||||
* This is a bad API and should be killed/refactored/changed eventually,
|
* This is a bad API and should be killed/refactored/changed eventually,
|
||||||
* but for now we have code which relies on it.
|
* but for now we have code which relies on it.
|
||||||
* */
|
* */
|
||||||
async runButDontRaise(code: string): Promise<any> {
|
async runButDontRaise(code: string): Promise<unknown> {
|
||||||
return this.run(code).catch(err => {
|
return this.run(code).catch(err => {
|
||||||
logger.error(err);
|
const error = err as Error
|
||||||
|
logger.error("Error:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export function ltrim(code: string): string {
|
|||||||
let _uniqueIdCounter = 0;
|
let _uniqueIdCounter = 0;
|
||||||
export function ensureUniqueId(el: HTMLElement) {
|
export function ensureUniqueId(el: HTMLElement) {
|
||||||
if (el.id === "")
|
if (el.id === "")
|
||||||
el.id = "py-internal-" + _uniqueIdCounter++;
|
el.id = `py-internal-${_uniqueIdCounter++}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -94,7 +94,7 @@ export function inJest(): boolean {
|
|||||||
return typeof process === 'object' && process.env.JEST_WORKER_ID !== undefined;
|
return typeof process === 'object' && process.env.JEST_WORKER_ID !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function globalExport(name: string, obj: any) {
|
export function globalExport(name: string, obj: object) {
|
||||||
// attach the given object to the global object, so that it is globally
|
// attach the given object to the global object, so that it is globally
|
||||||
// visible everywhere. Should be used very sparingly!
|
// visible everywhere. Should be used very sparingly!
|
||||||
|
|
||||||
|
|||||||
34
pyscriptjs/tests/unit/utils.test.ts
Normal file
34
pyscriptjs/tests/unit/utils.test.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { jest } from "@jest/globals"
|
||||||
|
import { ensureUniqueId } from "../../src/utils"
|
||||||
|
|
||||||
|
describe("Utils", () => {
|
||||||
|
|
||||||
|
let element: HTMLElement;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
element = document.createElement("div");
|
||||||
|
})
|
||||||
|
|
||||||
|
it("ensureUniqueId sets unique id on element", async () => {
|
||||||
|
expect(element.id).toBe("")
|
||||||
|
|
||||||
|
ensureUniqueId(element)
|
||||||
|
|
||||||
|
expect(element.id).toBe("py-internal-0")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("ensureUniqueId sets unique id with increasing counter", async () => {
|
||||||
|
const secondElement = document.createElement("div")
|
||||||
|
|
||||||
|
expect(element.id).toBe("")
|
||||||
|
expect(secondElement.id).toBe("")
|
||||||
|
|
||||||
|
ensureUniqueId(element)
|
||||||
|
ensureUniqueId(secondElement)
|
||||||
|
|
||||||
|
// The counter will have been incremented on
|
||||||
|
// the previous test, make sure it keeps increasing
|
||||||
|
expect(element.id).toBe("py-internal-1")
|
||||||
|
expect(secondElement.id).toBe("py-internal-2")
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user