Versie 0.2.0
This commit is contained in:
commit
e77d8fd373
495 files changed
+81026
No files matched your search
@@ -0,0 +1,65 @@
|
||||
// Generated, do not edit. sha256:c59345089e27fb5a471d676d1783b760f5131e156f381aef6e04e76979a27c21
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
const { alertHtml } = await import('../../client/ui/alert.js');
|
||||
|
||||
describe('alertHtml: the four kinds', () => {
|
||||
it('renders kind, icon, title and body in the shape the stylesheet expects', () => {
|
||||
const html = alertHtml({ kind: 'error', title: 'Mislukt', body: 'Bestand onleesbaar.' });
|
||||
assert.match(html, /^<div class="alert alert-error"><span class="alert-icon">⚠️<\/span>/);
|
||||
assert.match(html, /<div class="alert-content"><div class="alert-title">Mislukt<\/div>/);
|
||||
assert.match(html, /<div class="alert-body">Bestand onleesbaar\.<\/div><\/div><\/div>$/);
|
||||
});
|
||||
|
||||
it('gives each kind its own icon, and neutral none', () => {
|
||||
assert.match(alertHtml({ kind: 'info', body: 'x' }), /alert-icon">ℹ️</);
|
||||
assert.match(alertHtml({ kind: 'success', body: 'x' }), /alert-icon">✓</);
|
||||
assert.match(alertHtml({ kind: 'error', body: 'x' }), /alert-icon">⚠️</);
|
||||
assert.doesNotMatch(alertHtml({ kind: 'neutral', body: 'x' }), /alert-icon/);
|
||||
});
|
||||
|
||||
it('lets a caller override the icon, and suppress it with null', () => {
|
||||
assert.match(alertHtml({ kind: 'info', icon: '✨', body: 'x' }), /alert-icon">✨</);
|
||||
assert.doesNotMatch(alertHtml({ kind: 'error', icon: null, body: 'x' }), /alert-icon/);
|
||||
});
|
||||
|
||||
it('REFUSES a kind that does not exist', () => {
|
||||
assert.throws(() => alertHtml({ kind: 'warning', body: 'x' }), /Unknown alert kind/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('alertHtml: what is left out leaves nothing behind', () => {
|
||||
it('writes no title element without a title', () => {
|
||||
assert.doesNotMatch(alertHtml({ kind: 'error', body: 'x' }), /alert-title/);
|
||||
});
|
||||
|
||||
it('writes no body element without a body', () => {
|
||||
assert.doesNotMatch(alertHtml({ kind: 'error', title: 'x' }), /alert-body/);
|
||||
});
|
||||
|
||||
it('still renders the content wrapper, because the flex layout needs it', () => {
|
||||
assert.match(alertHtml({ kind: 'neutral', body: 'x' }), /<div class="alert-content">/);
|
||||
});
|
||||
|
||||
it('adds an extra class only when asked', () => {
|
||||
assert.match(alertHtml({ kind: 'info', className: 'mt-lg', body: 'x' }), /"alert alert-info mt-lg"/);
|
||||
assert.match(alertHtml({ kind: 'info', body: 'x' }), /"alert alert-info"/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('alertHtml: title and body are text, extra is markup', () => {
|
||||
it('escapes the title and the body', () => {
|
||||
const html = alertHtml({ kind: 'error', title: '<b>t</b>', body: '<img src=x onerror=alert(1)>' });
|
||||
assert.doesNotMatch(html, /<b>|<img/);
|
||||
});
|
||||
|
||||
it('escapes a database message put in the body', () => {
|
||||
assert.doesNotMatch(alertHtml({ kind: 'error', body: 'no such column: <script>' }), /<script>/);
|
||||
});
|
||||
|
||||
it('does NOT escape extra', () => {
|
||||
assert.match(alertHtml({ kind: 'info', body: 'x', extra: '<button id="go">Go</button>' }),
|
||||
/<button id="go">Go<\/button>/);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user