refactor py-config to use json (#754)

* refactor py-config to use toml

* switch from toml to json and add unit tests

* fix test for py-config

* fix integration test

* use flat structure for JSON

* allow merging configs

* replace arrays instead of concatenating them

* remove extra keys from inline config of integration test

* simplify array replacement logic

* allow config from src to be partial as well

* add comments to unit tests

* add unit test for setting config from both inline and src

* handle parse errors + validate config supplied

* separate functions for src and inline

* suggested improvements

* show error message in red on parser error

* fix eslint

* use resolveJsonModule as true

* use default config defined as a variable without import

* remove disable eslint comment

* remove import for covfefe.json as well

* metadata injection

* add support for schema + extra keys

* use schema_version
This commit is contained in:
Madhur Tandon
2022-09-16 02:07:00 +05:30
committed by GitHub
parent 0b014eea56
commit 4841e29fc6
8 changed files with 330 additions and 46 deletions

View File

@@ -55,10 +55,13 @@ class TestRuntimeConfig(PyScriptTest):
""",
extra_head="""
<py-config>
runtimes:
- src: "/pyodide/pyodide.js"
name: pyodide-0.20.0
lang: python
{
"runtimes": [{
"src": "/pyodide/pyodide.js",
"name": "pyodide-0.20.0",
"lang": "python"
}]
}
</py-config>
""",
)

View File

@@ -1,15 +1,32 @@
import type { AppConfig, RuntimeConfig } from '../../src/runtime';
import { PyConfig } from '../../src/components/pyconfig';
// inspired by trump typos
const covfefeConfig = {
"name": "covfefe",
"runtimes": [{
"src": "/demo/covfefe.js",
"name": "covfefe",
"lang": "covfefe"
}],
"wonerful": "discgrace"
};
import {jest} from '@jest/globals';
customElements.define('py-config', PyConfig);
describe('PyConfig', () => {
let instance: PyConfig;
const xhrMockClass = () => ({
open : jest.fn(),
send : jest.fn(),
responseText : JSON.stringify(covfefeConfig)
});
// @ts-ignore
window.XMLHttpRequest = jest.fn().mockImplementation(xhrMockClass)
beforeEach(() => {
instance = new PyConfig();
let runtime_config: RuntimeConfig = {src: "/demo/covfefe.js", name: "covfefe", lang: "covfefe"};
let app_config: AppConfig = {autoclose_loader: true, runtimes: [runtime_config]};
instance.values = app_config;
});
it('should get the Config to just instantiate', async () => {
@@ -17,7 +34,55 @@ describe('PyConfig', () => {
});
it('should load runtime from config and set as script src', () => {
instance.values = covfefeConfig;
instance.loadRuntimes();
expect(document.scripts[0].src).toBe("http://localhost/demo/covfefe.js");
});
it('should load the default config', ()=> {
instance.connectedCallback();
expect(instance.values.name).toBe("pyscript");
expect(instance.values.author_email).toBe("foo@bar.com");
expect(instance.values.pyscript?.time).not.toBeNull();
// @ts-ignore
expect(instance.values.runtimes[0].lang).toBe("python");
});
it('should load the config from inline', ()=> {
instance.innerHTML = JSON.stringify(covfefeConfig);
instance.connectedCallback();
// @ts-ignore
expect(instance.values.runtimes[0].lang).toBe("covfefe");
expect(instance.values.pyscript?.time).not.toBeNull();
// version wasn't present in `inline config` but is still set due to merging with default
expect(instance.values.version).toBe("0.1");
});
it('should load the config from src attribute', ()=> {
instance.setAttribute("src", "/covfefe.json");
instance.connectedCallback();
// @ts-ignore
expect(instance.values.runtimes[0].lang).toBe("covfefe");
expect(instance.values.pyscript?.time).not.toBeNull();
// wonerful is an extra key supplied by the user and is unaffected by merging process
expect(instance.values.wonerful).toBe("discgrace");
// version wasn't present in `config from src` but is still set due to merging with default
expect(instance.values.version).toBe("0.1");
});
it('should load the config from both inline and src', ()=> {
instance.innerHTML = JSON.stringify({"version": "0.2a", "wonerful": "highjacked"});
instance.setAttribute("src", "/covfefe.json");
instance.connectedCallback();
// @ts-ignore
expect(instance.values.runtimes[0].lang).toBe("covfefe");
expect(instance.values.pyscript?.time).not.toBeNull();
// config from src had an extra key "wonerful" with value "discgrace"
// inline config had the same extra key "wonerful" with value "highjacked"
// the merge process works for extra keys that clash as well
// so the final value is "highjacked" since inline takes precedence over src
expect(instance.values.wonerful).toBe("highjacked");
// version wasn't present in `config from src` but is still set due to merging with default and inline
expect(instance.values.version).toBe("0.2a");
});
});