Apply prettier to css, html, js, md, ts, and yml (#1249)

* Apply prettier to css, js, html, md, ts, and yml

As a followup I will add prettier to the .pre-commit config.
This patch is 100% generated by prettier.
I used a forked version of prettier that understands the
py-script tag.
See https://github.com/hoodmane/pyscript-prettier-precommit
for more info.

* Apply old pre-commit

* Revert some problems

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Revert some changes

* More changes

* Fix pre-commit

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Hood Chatham
2023-03-06 15:20:21 +01:00
committed by GitHub
parent 7ffe6a598e
commit 08f34f748b
108 changed files with 4571 additions and 3802 deletions

View File

@@ -1,127 +1,123 @@
import { expect, it, jest, describe, afterEach } from "@jest/globals"
import { _createAlertBanner, UserError, FetchError, ErrorCode } from "../../src/exceptions"
import { expect, it, jest, describe, afterEach } from '@jest/globals';
import { _createAlertBanner, UserError, FetchError, ErrorCode } from '../../src/exceptions';
describe("Test _createAlertBanner", () => {
afterEach(() => {
// Ensure we always have a clean body
document.body.innerHTML = `<div>Hello World</div>`;
})
describe('Test _createAlertBanner', () => {
afterEach(() => {
// Ensure we always have a clean body
document.body.innerHTML = `<div>Hello World</div>`;
});
it("error level shouldn't contain close button", async () => {
_createAlertBanner('Something went wrong!', 'error');
it("error level shouldn't contain close button", async () => {
_createAlertBanner("Something went wrong!", "error");
const banner = document.getElementsByClassName('alert-banner');
const closeButton = document.getElementById('alert-close-button');
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toBe('Something went wrong!');
expect(closeButton).toBeNull();
});
const banner = document.getElementsByClassName("alert-banner");
const closeButton = document.getElementById("alert-close-button");
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toBe("Something went wrong!");
expect(closeButton).toBeNull();
})
it('warning level should contain close button', async () => {
_createAlertBanner('This is a warning', 'warning');
it("warning level should contain close button", async () => {
_createAlertBanner("This is a warning", "warning");
const banner = document.getElementsByClassName('alert-banner');
const closeButton = document.getElementById('alert-close-button');
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toContain('This is a warning');
expect(closeButton).not.toBeNull();
});
const banner = document.getElementsByClassName("alert-banner");
const closeButton = document.getElementById("alert-close-button");
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toContain("This is a warning");
expect(closeButton).not.toBeNull();
})
it('error level banner should log to console', async () => {
const logSpy = jest.spyOn(console, 'error');
it("error level banner should log to console", async () => {
const logSpy = jest.spyOn(console, "error");
_createAlertBanner('Something went wrong!');
_createAlertBanner("Something went wrong!");
expect(logSpy).toHaveBeenCalledWith('Something went wrong!');
});
expect(logSpy).toHaveBeenCalledWith("Something went wrong!");
it('warning level banner should log to console', async () => {
const logSpy = jest.spyOn(console, 'warn');
})
_createAlertBanner('This warning', 'warning');
it("warning level banner should log to console", async () => {
const logSpy = jest.spyOn(console, "warn");
expect(logSpy).toHaveBeenCalledWith('This warning');
});
_createAlertBanner("This warning", "warning");
it('close button should remove element from page', async () => {
let banner = document.getElementsByClassName('alert-banner');
expect(banner.length).toBe(0);
expect(logSpy).toHaveBeenCalledWith("This warning");
})
_createAlertBanner('Warning!', 'warning');
it("close button should remove element from page", async () => {
let banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(0);
// Just a sanity check
banner = document.getElementsByClassName('alert-banner');
expect(banner.length).toBe(1);
_createAlertBanner("Warning!", "warning");
const closeButton = document.getElementById('alert-close-button');
if (closeButton) {
closeButton.click();
// Confirm that clicking the close button, removes the element
banner = document.getElementsByClassName('alert-banner');
expect(banner.length).toBe(0);
} else {
fail('Unable to find close button on the page, but should exist');
}
});
// Just a sanity check
banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(1);
it("toggling logging off on error alert shouldn't log to console", async () => {
const errorLogSpy = jest.spyOn(console, 'error');
const closeButton = document.getElementById("alert-close-button");
if(closeButton) {
closeButton.click();
// Confirm that clicking the close button, removes the element
banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(0);
} else {
fail("Unable to find close button on the page, but should exist");
}
_createAlertBanner('Test error', 'error', 'text', false);
expect(errorLogSpy).not.toHaveBeenCalledWith('Test error');
});
})
it("toggling logging off on warning alert shouldn't log to console", async () => {
const warnLogSpy = jest.spyOn(console, 'warn');
_createAlertBanner('Test warning', 'warning', 'text', false);
expect(warnLogSpy).not.toHaveBeenCalledWith('Test warning');
});
it("toggling logging off on error alert shouldn't log to console", async () => {
const errorLogSpy = jest.spyOn(console, "error");
it('_createAlertbanner messageType text writes message to content', async () => {
let banner = document.getElementsByClassName('alert-banner');
expect(banner.length).toBe(0);
_createAlertBanner("Test error", "error", "text", false);
expect(errorLogSpy).not.toHaveBeenCalledWith("Test error");
})
const message = '<p>Test message</p>';
_createAlertBanner(message, 'error', 'text');
banner = document.getElementsByClassName('alert-banner');
it("toggling logging off on warning alert shouldn't log to console", async () => {
const warnLogSpy = jest.spyOn(console, "warn");
_createAlertBanner("Test warning", "warning", "text", false);
expect(warnLogSpy).not.toHaveBeenCalledWith("Test warning");
})
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toBe('&lt;p&gt;Test message&lt;/p&gt;');
expect(banner[0].textContent).toBe(message);
});
it('_createAlertbanner messageType html writes message to innerHTML', async () => {
let banner = document.getElementsByClassName('alert-banner');
expect(banner.length).toBe(0);
it('_createAlertbanner messageType text writes message to content', async () => {
let banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(0);
const message = '<p>Test message</p>';
_createAlertBanner(message, 'error', 'html');
banner = document.getElementsByClassName('alert-banner');
const message = '<p>Test message</p>'
_createAlertBanner(message, 'error', 'text');
banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toBe(message);
expect(banner[0].textContent).toBe('Test message');
});
});
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toBe("&lt;p&gt;Test message&lt;/p&gt;");
expect(banner[0].textContent).toBe(message);
})
describe('Test Exceptions', () => {
it('UserError contains errorCode and shows in message', async () => {
const errorCode = ErrorCode.BAD_CONFIG;
const message = 'Test error';
const userError = new UserError(ErrorCode.BAD_CONFIG, message);
expect(userError.errorCode).toBe(errorCode);
expect(userError.message).toBe(`(${errorCode}): ${message}`);
});
it('_createAlertbanner messageType html writes message to innerHTML', async () => {
let banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(0);
const message = '<p>Test message</p>';
_createAlertBanner(message, 'error', 'html');
banner = document.getElementsByClassName("alert-banner");
expect(banner.length).toBe(1);
expect(banner[0].innerHTML).toBe(message);
expect(banner[0].textContent).toBe("Test message");
})
})
describe("Test Exceptions", () => {
it('UserError contains errorCode and shows in message', async() => {
const errorCode = ErrorCode.BAD_CONFIG;
const message = 'Test error';
const userError = new UserError(ErrorCode.BAD_CONFIG, message);
expect(userError.errorCode).toBe(errorCode);
expect(userError.message).toBe(`(${errorCode}): ${message}`);
})
it('FetchError contains errorCode and shows in message', async() => {
const errorCode = ErrorCode.FETCH_NOT_FOUND_ERROR;
const message = 'Test error';
const fetchError = new FetchError(errorCode, message);
expect(fetchError.errorCode).toBe(errorCode);
expect(fetchError.message).toBe(`(${errorCode}): ${message}`);
})
})
it('FetchError contains errorCode and shows in message', async () => {
const errorCode = ErrorCode.FETCH_NOT_FOUND_ERROR;
const message = 'Test error';
const fetchError = new FetchError(errorCode, message);
expect(fetchError.errorCode).toBe(errorCode);
expect(fetchError.message).toBe(`(${errorCode}): ${message}`);
});
});

View File

@@ -1,111 +1,107 @@
import { describe, it, expect, jest } from '@jest/globals'
import { FetchError, ErrorCode } from "../../src/exceptions"
import { robustFetch } from "../../src/fetch"
import { describe, it, expect, jest } from '@jest/globals';
import { FetchError, ErrorCode } from '../../src/exceptions';
import { robustFetch } from '../../src/fetch';
import { Response } from 'node-fetch';
describe("robustFetch", () => {
describe('robustFetch', () => {
it('should return a response object', async () => {
global.fetch = jest.fn(() => Promise.resolve(new Response((status = '200'), 'Hello World')));
it("should return a response object", async () => {
global.fetch = jest.fn(() => (Promise.resolve(new Response(status="200", "Hello World"))));
const response = await robustFetch('https://pyscript.net');
expect(response).toBeInstanceOf(Response);
expect(response.status).toBe(200);
});
const response = await robustFetch("https://pyscript.net");
expect(response).toBeInstanceOf(Response);
expect(response.status).toBe(200);
})
it('receiving a 404 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => Promise.resolve(new Response('Not Found', { status: 404 })));
it('receiving a 404 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => (Promise.resolve(new Response("Not Found", {status: 404}))));
const url = 'https://pyscript.net/non-existent-page';
const expectedError = new FetchError(
ErrorCode.FETCH_NOT_FOUND_ERROR,
`Fetching from URL ${url} failed with error 404 (Not Found). ` + `Are your filename and path correct?`,
);
const url = "https://pyscript.net/non-existent-page"
const expectedError = new FetchError(
ErrorCode.FETCH_NOT_FOUND_ERROR,
`Fetching from URL ${url} failed with error 404 (Not Found). ` +
`Are your filename and path correct?`
)
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
it('receiving a 401 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => Promise.resolve(new Response('', { status: 401 })));
it('receiving a 401 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => (Promise.resolve(new Response("", {status: 401}))));
const url = 'https://pyscript.net/protected-page';
const expectedError = new FetchError(
ErrorCode.FETCH_UNAUTHORIZED_ERROR,
`Fetching from URL ${url} failed with error 401 (Unauthorized). ` + `Are your filename and path correct?`,
);
const url = "https://pyscript.net/protected-page"
const expectedError = new FetchError(
ErrorCode.FETCH_UNAUTHORIZED_ERROR,
`Fetching from URL ${url} failed with error 401 (Unauthorized). ` +
`Are your filename and path correct?`
)
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
it('receiving a 403 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => Promise.resolve(new Response('', { status: 403 })));
it('receiving a 403 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => (Promise.resolve(new Response("", {status: 403}))));
const url = 'https://pyscript.net/secret-page';
const expectedError = new FetchError(
ErrorCode.FETCH_FORBIDDEN_ERROR,
`Fetching from URL ${url} failed with error 403 (Forbidden). ` + `Are your filename and path correct?`,
);
const url = "https://pyscript.net/secret-page"
const expectedError = new FetchError(
ErrorCode.FETCH_FORBIDDEN_ERROR,
`Fetching from URL ${url} failed with error 403 (Forbidden). ` +
`Are your filename and path correct?`
)
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
it('receiving a 500 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => Promise.resolve(new Response('Not Found', { status: 500 })));
it('receiving a 500 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => (Promise.resolve(new Response("Not Found", {status: 500}))));
const url = 'https://pyscript.net/protected-page';
const expectedError = new FetchError(
ErrorCode.FETCH_SERVER_ERROR,
`Fetching from URL ${url} failed with error 500 (Internal Server Error). ` +
`Are your filename and path correct?`,
);
const url = "https://pyscript.net/protected-page"
const expectedError = new FetchError(
ErrorCode.FETCH_SERVER_ERROR,
`Fetching from URL ${url} failed with error 500 (Internal Server Error). ` +
`Are your filename and path correct?`
)
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
it('receiving a 503 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => Promise.resolve(new Response('Not Found', { status: 503 })));
it('receiving a 503 when fetching should throw FetchError with the right errorCode', async () => {
global.fetch = jest.fn(() => (Promise.resolve(new Response("Not Found", {status: 503}))));
const url = 'https://pyscript.net/protected-page';
const expectedError = new FetchError(
ErrorCode.FETCH_UNAVAILABLE_ERROR,
`Fetching from URL ${url} failed with error 503 (Service Unavailable). ` +
`Are your filename and path correct?`,
);
const url = "https://pyscript.net/protected-page"
const expectedError = new FetchError(
ErrorCode.FETCH_UNAVAILABLE_ERROR,
`Fetching from URL ${url} failed with error 503 (Service Unavailable). ` +
`Are your filename and path correct?`
)
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
it('handle TypeError when using a bad url', async () => {
global.fetch = jest.fn(() => Promise.reject(new TypeError('Failed to fetch')));
it('handle TypeError when using a bad url', async () => {
global.fetch = jest.fn(() => (Promise.reject(new TypeError("Failed to fetch"))));
const url = 'https://pyscript.net/protected-page';
const expectedError = new FetchError(
ErrorCode.FETCH_ERROR,
`Fetching from URL ${url} failed with error 'Failed to fetch'. Are your filename and path correct?`,
);
const url = "https://pyscript.net/protected-page"
const expectedError = new FetchError(
ErrorCode.FETCH_ERROR,
`Fetching from URL ${url} failed with error 'Failed to fetch'. Are your filename and path correct?`
)
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
it('handle failed to fetch when using local file', async () => {
global.fetch = jest.fn(() => Promise.reject(new TypeError('Failed to fetch')));
it('handle failed to fetch when using local file', async () => {
global.fetch = jest.fn(() => (Promise.reject(new TypeError("Failed to fetch"))));
const url = './my-awesome-pyscript.py';
const url = "./my-awesome-pyscript.py"
const expectedError = new FetchError(
ErrorCode.FETCH_ERROR,
`PyScript: Access to local files
const expectedError = new FetchError(
ErrorCode.FETCH_ERROR,
`PyScript: Access to local files
(using "Paths:" in &lt;py-config&gt;)
is not available when directly opening a HTML file;
you must use a webserver to serve the additional files.
See <a style="text-decoration: underline;" href="https://github.com/pyscript/pyscript/issues/257#issuecomment-1119595062">this reference</a>
on starting a simple webserver with Python.
`
)
`,
);
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
})
expect(() => robustFetch(url)).rejects.toThrow(expectedError);
});
});

View File

@@ -1,49 +1,55 @@
import { calculatePaths } from "../../src/plugins/fetch";
import { FetchConfig } from "../../src/pyconfig";
import { calculatePaths } from '../../src/plugins/fetch';
import { FetchConfig } from '../../src/pyconfig';
describe("CalculateFetchPaths", () => {
it("should calculate paths when only from is provided", () => {
const fetch_cfg: FetchConfig[] = [{from: "http://a.com/data.csv" }];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(["./data.csv"]);
expect(fetchPaths).toStrictEqual(["http://a.com/data.csv"]);
})
describe('CalculateFetchPaths', () => {
it('should calculate paths when only from is provided', () => {
const fetch_cfg: FetchConfig[] = [{ from: 'http://a.com/data.csv' }];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(['./data.csv']);
expect(fetchPaths).toStrictEqual(['http://a.com/data.csv']);
});
it("should calculate paths when only files is provided", () => {
const fetch_cfg: FetchConfig[] = [{files: ["foo/__init__.py", "foo/mod.py"] }];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(["./foo/__init__.py", "./foo/mod.py"]);
expect(fetchPaths).toStrictEqual(["foo/__init__.py", "foo/mod.py"]);
})
it('should calculate paths when only files is provided', () => {
const fetch_cfg: FetchConfig[] = [{ files: ['foo/__init__.py', 'foo/mod.py'] }];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(['./foo/__init__.py', './foo/mod.py']);
expect(fetchPaths).toStrictEqual(['foo/__init__.py', 'foo/mod.py']);
});
it("should calculate paths when files and to_folder is provided", () => {
const fetch_cfg: FetchConfig[] = [{files: ["foo/__init__.py", "foo/mod.py"], to_folder: "/my/lib/"}];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(["/my/lib/foo/__init__.py", "/my/lib/foo/mod.py"]);
expect(fetchPaths).toStrictEqual(["foo/__init__.py", "foo/mod.py"]);
})
it('should calculate paths when files and to_folder is provided', () => {
const fetch_cfg: FetchConfig[] = [{ files: ['foo/__init__.py', 'foo/mod.py'], to_folder: '/my/lib/' }];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(['/my/lib/foo/__init__.py', '/my/lib/foo/mod.py']);
expect(fetchPaths).toStrictEqual(['foo/__init__.py', 'foo/mod.py']);
});
it("should calculate paths when from and files and to_folder is provided", () => {
const fetch_cfg: FetchConfig[] = [{from: "http://a.com/download/", files: ["foo/__init__.py", "foo/mod.py"], to_folder: "/my/lib/"}];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(["/my/lib/foo/__init__.py", "/my/lib/foo/mod.py"]);
expect(fetchPaths).toStrictEqual(["http://a.com/download/foo/__init__.py", "http://a.com/download/foo/mod.py"]);
})
it('should calculate paths when from and files and to_folder is provided', () => {
const fetch_cfg: FetchConfig[] = [
{ from: 'http://a.com/download/', files: ['foo/__init__.py', 'foo/mod.py'], to_folder: '/my/lib/' },
];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(['/my/lib/foo/__init__.py', '/my/lib/foo/mod.py']);
expect(fetchPaths).toStrictEqual(['http://a.com/download/foo/__init__.py', 'http://a.com/download/foo/mod.py']);
});
it("should error out while calculating paths when filename cannot be determined from 'from'", () => {
const fetch_cfg: FetchConfig[] = [{from: "http://google.com/", to_folder: "/tmp"}];
expect(()=>calculatePaths(fetch_cfg)).toThrowError("Couldn't determine the filename from the path http://google.com/");
})
const fetch_cfg: FetchConfig[] = [{ from: 'http://google.com/', to_folder: '/tmp' }];
expect(() => calculatePaths(fetch_cfg)).toThrowError(
"Couldn't determine the filename from the path http://google.com/",
);
});
it("should calculate paths when to_file is explicitly supplied", () => {
const fetch_cfg: FetchConfig[] = [{from: "http://a.com/data.csv?version=1", to_file: "pkg/tmp/data.csv"}];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(["./pkg/tmp/data.csv"]);
expect(fetchPaths).toStrictEqual(["http://a.com/data.csv?version=1"]);
})
it('should calculate paths when to_file is explicitly supplied', () => {
const fetch_cfg: FetchConfig[] = [{ from: 'http://a.com/data.csv?version=1', to_file: 'pkg/tmp/data.csv' }];
const [paths, fetchPaths] = calculatePaths(fetch_cfg);
expect(paths).toStrictEqual(['./pkg/tmp/data.csv']);
expect(fetchPaths).toStrictEqual(['http://a.com/data.csv?version=1']);
});
it("should error out when both to_file and files parameters are provided", () => {
const fetch_cfg: FetchConfig[] = [{from: "http://a.com/data.csv?version=1", to_file: "pkg/tmp/data.csv", files: ["a.py", "b.py"]}];
expect(()=>calculatePaths(fetch_cfg)).toThrowError("Cannot use 'to_file' and 'files' parameters together!");
})
})
it('should error out when both to_file and files parameters are provided', () => {
const fetch_cfg: FetchConfig[] = [
{ from: 'http://a.com/data.csv?version=1', to_file: 'pkg/tmp/data.csv', files: ['a.py', 'b.py'] },
];
expect(() => calculatePaths(fetch_cfg)).toThrowError("Cannot use 'to_file' and 'files' parameters together!");
});
});

View File

@@ -15,20 +15,16 @@ describe('getLogger', () => {
console.info = jest.fn();
const logger = getLogger('prefix1');
logger.info('hello world')
expect(console.info).toHaveBeenCalledWith(
'[prefix1] hello world'
)
logger.info('hello world');
expect(console.info).toHaveBeenCalledWith('[prefix1] hello world');
});
it('logger.info handles multiple args', () => {
console.info = jest.fn();
const logger = getLogger('prefix2');
logger.info('hello', 'world', 1, 2, 3)
expect(console.info).toHaveBeenCalledWith(
'[prefix2] hello', 'world', 1, 2, 3
)
logger.info('hello', 'world', 1, 2, 3);
expect(console.info).toHaveBeenCalledWith('[prefix2] hello', 'world', 1, 2, 3);
});
it('logger.{debug,warn,error} also works', () => {
@@ -43,15 +39,8 @@ describe('getLogger', () => {
logger.error('this is an error');
expect(console.info).not.toHaveBeenCalled();
expect(console.debug).toHaveBeenCalledWith(
'[prefix3] this is a debug'
)
expect(console.warn).toHaveBeenCalledWith(
'[prefix3] this is a warning'
)
expect(console.error).toHaveBeenCalledWith(
'[prefix3] this is an error'
)
expect(console.debug).toHaveBeenCalledWith('[prefix3] this is a debug');
expect(console.warn).toHaveBeenCalledWith('[prefix3] this is a warning');
expect(console.error).toHaveBeenCalledWith('[prefix3] this is an error');
});
});

View File

@@ -1,9 +1,8 @@
import { describe, it, beforeEach, expect } from "@jest/globals"
import { UserError, ErrorCode } from "../../src/exceptions"
import { PyScriptApp } from "../../src/main"
describe("Test withUserErrorHandler", () => {
import { describe, it, beforeEach, expect } from '@jest/globals';
import { UserError, ErrorCode } from '../../src/exceptions';
import { PyScriptApp } from '../../src/main';
describe('Test withUserErrorHandler', () => {
class MyApp extends PyScriptApp {
myRealMain: any;
@@ -24,46 +23,46 @@ describe("Test withUserErrorHandler", () => {
it("userError doesn't stop execution", () => {
function myRealMain() {
throw new UserError(ErrorCode.GENERIC, "Computer says no");
throw new UserError(ErrorCode.GENERIC, 'Computer says no');
}
const app = new MyApp(myRealMain);
app.main();
const banners = document.getElementsByClassName("alert-banner");
const banners = document.getElementsByClassName('alert-banner');
expect(banners.length).toBe(1);
expect(banners[0].innerHTML).toBe("(PY0000): Computer says no");
expect(banners[0].innerHTML).toBe('(PY0000): Computer says no');
});
it("userError escapes by default", () => {
it('userError escapes by default', () => {
function myRealMain() {
throw new UserError(ErrorCode.GENERIC, "hello <br>");
throw new UserError(ErrorCode.GENERIC, 'hello <br>');
}
const app = new MyApp(myRealMain);
app.main();
const banners = document.getElementsByClassName("alert-banner");
const banners = document.getElementsByClassName('alert-banner');
expect(banners.length).toBe(1);
expect(banners[0].innerHTML).toBe("(PY0000): hello &lt;br&gt;");
expect(banners[0].innerHTML).toBe('(PY0000): hello &lt;br&gt;');
});
it("userError messageType=html don't escape", () => {
function myRealMain() {
throw new UserError(ErrorCode.GENERIC, "hello <br>", "html");
throw new UserError(ErrorCode.GENERIC, 'hello <br>', 'html');
}
const app = new MyApp(myRealMain);
app.main();
const banners = document.getElementsByClassName("alert-banner");
const banners = document.getElementsByClassName('alert-banner');
expect(banners.length).toBe(1);
expect(banners[0].innerHTML).toBe("(PY0000): hello <br>");
expect(banners[0].innerHTML).toBe('(PY0000): hello <br>');
});
it("any other exception should stop execution and raise", () => {
it('any other exception should stop execution and raise', () => {
function myRealMain() {
throw new Error("Explosions!");
throw new Error('Explosions!');
}
const app = new MyApp(myRealMain);
expect(() => app.main()).toThrow(new Error("Explosions!"))
expect(() => app.main()).toThrow(new Error('Explosions!'));
});
});

View File

@@ -11,7 +11,7 @@ describe('RemoteInterpreter', () => {
let interpreter: InterpreterClient;
let stdio: CaptureStdio = new CaptureStdio();
beforeAll(async () => {
const config: AppConfig = {interpreters: [{src: "../pyscriptjs/node_modules/pyodide/pyodide.js"}]};
const config: AppConfig = { interpreters: [{ src: '../pyscriptjs/node_modules/pyodide/pyodide.js' }] };
interpreter = new InterpreterClient(config, stdio);
/**

View File

@@ -4,31 +4,29 @@ import { type Stdio, CaptureStdio, StdioMultiplexer, TargetedStdio } from '../..
describe('CaptureStdio', () => {
it('captured streams are initialized to empty string', () => {
let stdio = new CaptureStdio();
expect(stdio.captured_stdout).toBe("");
expect(stdio.captured_stderr).toBe("");
expect(stdio.captured_stdout).toBe('');
expect(stdio.captured_stderr).toBe('');
});
it('stdout() and stderr() captures', () => {
let stdio = new CaptureStdio();
stdio.stdout_writeline("hello");
stdio.stdout_writeline("world");
stdio.stderr_writeline("this is an error");
expect(stdio.captured_stdout).toBe("hello\nworld\n");
expect(stdio.captured_stderr).toBe("this is an error\n");
stdio.stdout_writeline('hello');
stdio.stdout_writeline('world');
stdio.stderr_writeline('this is an error');
expect(stdio.captured_stdout).toBe('hello\nworld\n');
expect(stdio.captured_stderr).toBe('this is an error\n');
});
it('reset() works', () => {
let stdio = new CaptureStdio();
stdio.stdout_writeline("aaa");
stdio.stderr_writeline("bbb");
stdio.stdout_writeline('aaa');
stdio.stderr_writeline('bbb');
stdio.reset();
expect(stdio.captured_stdout).toBe("");
expect(stdio.captured_stderr).toBe("");
expect(stdio.captured_stdout).toBe('');
expect(stdio.captured_stderr).toBe('');
});
});
describe('StdioMultiplexer', () => {
let a: CaptureStdio;
let b: CaptureStdio;
@@ -44,10 +42,10 @@ describe('StdioMultiplexer', () => {
// no listeners, messages are ignored
multi.stdout_writeline('out 1');
multi.stderr_writeline('err 1');
expect(a.captured_stdout).toBe("");
expect(a.captured_stderr).toBe("");
expect(b.captured_stdout).toBe("");
expect(b.captured_stderr).toBe("");
expect(a.captured_stdout).toBe('');
expect(a.captured_stderr).toBe('');
expect(b.captured_stdout).toBe('');
expect(b.captured_stderr).toBe('');
});
it('redirects to multiple listeners', () => {
@@ -59,11 +57,11 @@ describe('StdioMultiplexer', () => {
multi.stdout_writeline('out 2');
multi.stderr_writeline('err 2');
expect(a.captured_stdout).toBe("out 1\nout 2\n");
expect(a.captured_stderr).toBe("err 1\nerr 2\n");
expect(a.captured_stdout).toBe('out 1\nout 2\n');
expect(a.captured_stderr).toBe('err 1\nerr 2\n');
expect(b.captured_stdout).toBe("out 2\n");
expect(b.captured_stderr).toBe("err 2\n");
expect(b.captured_stdout).toBe('out 2\n');
expect(b.captured_stderr).toBe('err 2\n');
});
});
@@ -75,32 +73,30 @@ describe('TargetedStdio', () => {
beforeEach(() => {
//DOM element to capture stdout and stderr
let target_div = document.getElementById("output-id");
let target_div = document.getElementById('output-id');
if (target_div=== null){
if (target_div === null) {
target_div = document.createElement('div');
target_div.id = "output-id";
target_div.id = 'output-id';
document.body.appendChild(target_div);
}
else {
target_div.innerHTML = "";
} else {
target_div.innerHTML = '';
}
//DOM element to capture stderr
let error_div = document.getElementById("error-id");
let error_div = document.getElementById('error-id');
if (error_div=== null){
if (error_div === null) {
error_div = document.createElement('div');
error_div.id = "error-id";
error_div.id = 'error-id';
document.body.appendChild(error_div);
}
else {
error_div.innerHTML = "";
} else {
error_div.innerHTML = '';
}
const tag = document.createElement('div');
tag.setAttribute("output", "output-id");
tag.setAttribute("stderr", "error-id");
tag.setAttribute('output', 'output-id');
tag.setAttribute('stderr', 'error-id');
capture = new CaptureStdio();
targeted = new TargetedStdio(tag, 'output', true, true);
@@ -112,29 +108,29 @@ describe('TargetedStdio', () => {
multi.addListener(error_targeted);
});
it('targeted id is set by constructor', () =>{
expect(targeted.source_attribute).toBe("output");
it('targeted id is set by constructor', () => {
expect(targeted.source_attribute).toBe('output');
});
it('targeted stdio/stderr also goes to multiplexer', () =>{
multi.stdout_writeline("out 1");
multi.stderr_writeline("out 2");
expect(capture.captured_stdout).toBe("out 1\n");
expect(capture.captured_stderr).toBe("out 2\n");
expect(document.getElementById("output-id")?.innerHTML).toBe("out 1<br>out 2<br>");
expect(document.getElementById("error-id")?.innerHTML).toBe("out 2<br>");
it('targeted stdio/stderr also goes to multiplexer', () => {
multi.stdout_writeline('out 1');
multi.stderr_writeline('out 2');
expect(capture.captured_stdout).toBe('out 1\n');
expect(capture.captured_stderr).toBe('out 2\n');
expect(document.getElementById('output-id')?.innerHTML).toBe('out 1<br>out 2<br>');
expect(document.getElementById('error-id')?.innerHTML).toBe('out 2<br>');
});
it('Add and remove targeted listener', () => {
multi.stdout_writeline("out 1");
multi.stdout_writeline('out 1');
multi.removeListener(targeted);
multi.stdout_writeline("out 2");
multi.stdout_writeline('out 2');
multi.addListener(targeted);
multi.stdout_writeline("out 3");
multi.stdout_writeline('out 3');
//all three should be captured by multiplexer
expect(capture.captured_stdout).toBe("out 1\nout 2\nout 3\n");
expect(capture.captured_stdout).toBe('out 1\nout 2\nout 3\n');
//out 2 should not be present in the DOM element
expect(document.getElementById("output-id")?.innerHTML).toBe("out 1<br>out 3<br>");
expect(document.getElementById('output-id')?.innerHTML).toBe('out 1<br>out 3<br>');
});
});

View File

@@ -1,73 +1,78 @@
import { beforeEach, expect, describe, it } from "@jest/globals"
import { ensureUniqueId, joinPaths, createSingularWarning} from "../../src/utils"
import { beforeEach, expect, describe, it } from '@jest/globals';
import { ensureUniqueId, joinPaths, createSingularWarning } from '../../src/utils';
describe("Utils", () => {
describe('Utils', () => {
let element: HTMLElement;
let element: HTMLElement;
beforeEach(() => {
element = document.createElement('div');
});
beforeEach(() => {
element = document.createElement("div");
})
it('ensureUniqueId sets unique id on element', async () => {
expect(element.id).toBe('');
it("ensureUniqueId sets unique id on element", async () => {
expect(element.id).toBe("")
ensureUniqueId(element);
ensureUniqueId(element)
expect(element.id).toBe('py-internal-0');
});
expect(element.id).toBe("py-internal-0")
})
it('ensureUniqueId sets unique id with increasing counter', async () => {
const secondElement = document.createElement('div');
it("ensureUniqueId sets unique id with increasing counter", async () => {
const secondElement = document.createElement("div")
expect(element.id).toBe('');
expect(secondElement.id).toBe('');
expect(element.id).toBe("")
expect(secondElement.id).toBe("")
ensureUniqueId(element);
ensureUniqueId(secondElement);
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');
});
});
// 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")
})
})
describe('JoinPaths', () => {
it('should remove trailing slashes from the beginning and the end', () => {
const paths: string[] = ['///abc/d/e///'];
const joinedPath = joinPaths(paths);
expect(joinedPath).toStrictEqual('/abc/d/e');
});
describe("JoinPaths", () => {
it("should remove trailing slashes from the beginning and the end", () => {
const paths: string[] = ['///abc/d/e///'];
const joinedPath = joinPaths(paths);
expect(joinedPath).toStrictEqual('/abc/d/e');
})
it('should not remove slashes from the middle to preserve protocols such as http', () => {
const paths: string[] = ['http://google.com', '///data.txt'];
const joinedPath = joinPaths(paths);
expect(joinedPath).toStrictEqual('http://google.com/data.txt');
});
it("should not remove slashes from the middle to preserve protocols such as http", () => {
const paths: string[] = ['http://google.com', '///data.txt'];
const joinedPath = joinPaths(paths);
expect(joinedPath).toStrictEqual('http://google.com/data.txt');
})
it('should not join paths when they are empty strings', () => {
const paths: string[] = ['', '///hhh/ll/pp///', '', 'kkk'];
const joinedPath = joinPaths(paths);
expect(joinedPath).toStrictEqual('hhh/ll/pp/kkk');
});
it("should not join paths when they are empty strings", () => {
const paths: string[] = ['', '///hhh/ll/pp///', '', 'kkk'];
const joinedPath = joinPaths(paths);
expect(joinedPath).toStrictEqual('hhh/ll/pp/kkk');
})
describe('createSingularBanner', () => {
it('should create one and new banner containing the sentinel text, and not duplicate it', () => {
//One warning banner with the desired text should be created
createSingularWarning('A unique error message', 'unique');
expect(document.getElementsByClassName('alert-banner')?.length).toEqual(1);
expect(document.getElementsByClassName('alert-banner')[0].textContent).toEqual(
expect.stringContaining('A unique error message'),
);
describe("createSingularBanner", () => {
it("should create one and new banner containing the sentinel text, and not duplicate it", () => {
//One warning banner with the desired text should be created
createSingularWarning("A unique error message", "unique")
expect(document.getElementsByClassName("alert-banner")?.length).toEqual(1)
expect(document.getElementsByClassName("alert-banner")[0].textContent).toEqual(expect.stringContaining("A unique error message"))
//Should still only be one banner, since the second uses the existing sentinel value "unique"
createSingularWarning('This banner should not appear', 'unique');
expect(document.getElementsByClassName('alert-banner')?.length).toEqual(1);
expect(document.getElementsByClassName('alert-banner')[0].textContent).toEqual(
expect.stringContaining('A unique error message'),
);
//Should still only be one banner, since the second uses the existing sentinel value "unique"
createSingularWarning("This banner should not appear", "unique")
expect(document.getElementsByClassName("alert-banner")?.length).toEqual(1)
expect(document.getElementsByClassName("alert-banner")[0].textContent).toEqual(expect.stringContaining("A unique error message"))
//If the sentinel value is not provided, the entire msg is used as the sentinel
createSingularWarning("A unique error message", null)
expect(document.getElementsByClassName("alert-banner")?.length).toEqual(1)
expect(document.getElementsByClassName("alert-banner")[0].textContent).toEqual(expect.stringContaining("A unique error message"))
})
})
})
//If the sentinel value is not provided, the entire msg is used as the sentinel
createSingularWarning('A unique error message', null);
expect(document.getElementsByClassName('alert-banner')?.length).toEqual(1);
expect(document.getElementsByClassName('alert-banner')[0].textContent).toEqual(
expect.stringContaining('A unique error message'),
);
});
});
});