// Copyright (c) Jupyter Development Team. // Distributed under the terms of the Modified BSD License. import expect = require('expect.js'); import { Widget } from 'phosphor-widget'; import { LatexRenderer, PDFRenderer, JavascriptRenderer, SVGRenderer, MarkdownRenderer, TextRenderer, HTMLRenderer, ImageRenderer } from '../../../lib/renderers'; import { RenderMime } from '../../../lib/rendermime'; const TRANSFORMERS = [ new JavascriptRenderer(), new MarkdownRenderer(), new HTMLRenderer(), new PDFRenderer(), new ImageRenderer(), new SVGRenderer(), new LatexRenderer(), new TextRenderer() ]; export function defaultRenderMime(): RenderMime { let renderers: RenderMime.MimeMap> = {}; let order: string[] = []; for (let t of TRANSFORMERS) { for (let m of t.mimetypes) { renderers[m] = t; order.push(m); } } return new RenderMime({ renderers, order }); } describe('jupyter-ui', () => { describe('RenderMime', () => { describe('#constructor()', () => { it('should accept a mapping and a default order', () => { let r = defaultRenderMime(); expect(r instanceof RenderMime).to.be(true); }); }); describe('#render()', () => { it('should render a mimebundle', (done) => { let r = defaultRenderMime(); r.render({ 'text/plain': 'foo' }).then(w => { expect(w instanceof Widget).to.be(true); }).then(done, done); }); it('should return `undefined` for an unregistered mime type', (done) => { let r = defaultRenderMime(); r.render({ 'text/fizz': 'buzz' }).then(value => { expect(value).to.be(void 0); }).then(done, done); }); it('should render with the mimetype of highest precidence', (done) => { let bundle: RenderMime.MimeMap = { 'text/plain': 'foo', 'text/html': '

foo

' }; let r = defaultRenderMime(); r.render(bundle, true).then(w => { let el = w.node.firstChild as HTMLElement; expect(el.localName).to.be('h1'); }).then(done, done); }); it('should render the mimetype that is safe', (done) => { let bundle: RenderMime.MimeMap = { 'text/plain': 'foo', 'text/javascript': 'window.x = 1', 'image/png': 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' }; let r = defaultRenderMime(); r.render(bundle, false).then(w => { let el = w.node.firstChild as HTMLElement; expect(el.localName).to.be('img'); }).then(done, done); }); it('should render the mimetype that is sanitizable', (done) => { let bundle: RenderMime.MimeMap = { 'text/plain': 'foo', 'text/html': '

foo

' }; let r = defaultRenderMime(); r.render(bundle, false).then(w => { let el = w.node.firstChild as HTMLElement; expect(el.localName).to.be('h1'); }).then(done, done); }); it('should sanitize markdown', (done) => { let md = require('../../../examples/filebrowser/sample.md'); let r = defaultRenderMime(); r.render({ 'text/markdown': md as string }).then(widget => { expect(widget.node.innerHTML).to.be(`

Title first level

\n

Title second Level

\n

Title third level

\n

h4

\n
h5
\n
h6
\n

h1

\n

h2

\n

h3

\n

h4

\n
h6
\n

This is just a sample paragraph
You can look at different level of nested unorderd list ljbakjn arsvlasc asc asc awsc asc ascd ascd ascd asdc asc

\n
    \n
  • level 1
      \n
    • level 2
    • \n
    • level 2
    • \n
    • level 2
        \n
      • level 3
      • \n
      • level 3
          \n
        • level 4
            \n
          • level 5
              \n
            • level 6
            • \n
            \n
          • \n
          \n
        • \n
        \n
      • \n
      \n
    • \n
    • level 2
    • \n
    \n
  • \n
  • level 1
  • \n
  • level 1
  • \n
  • level 1
    Ordered list
  • \n
  • level 1
      \n
    1. level 1
    2. \n
    3. level 1
        \n
      1. level 1
      2. \n
      3. level 1
      4. \n
      5. level 1
          \n
        1. level 1
        2. \n
        3. level 1
            \n
          1. level 1
          2. \n
          3. level 1
          4. \n
          5. level 1
          6. \n
          \n
        4. \n
        \n
      6. \n
      \n
    4. \n
    \n
  • \n
  • level 1
  • \n
  • level 1
    some Horizontal line
  • \n
\n
\n

and another one

\n

Colons can be used to align columns.

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TablesAreCool
col 3 isright-aligned1600
col 2 iscentered12
zebra stripesare neat1
\n

There must be at least 3 dashes separating each header cell.
The outer pipes (|) are optional, and you don\'t need to make the
raw Markdown line up prettily. You can also use inline Markdown.

\n`); }).then(done, done); }); it('should sanitize html', (done) => { let bundle: RenderMime.MimeMap = { 'text/html': '

foo ' }; let r = defaultRenderMime(); r.render(bundle).then(widget => { expect(widget.node.innerHTML.indexOf('svg')).to.not.be(-1); expect(widget.node.innerHTML.indexOf('script')).to.be(-1); }).then(done, done); }); }); describe('#preferredMimetype()', () => { it('should find the preferred mimetype in a bundle', () => { let bundle: RenderMime.MimeMap = { 'text/plain': 'foo', 'text/html': '

foo

' }; let r = defaultRenderMime(); expect(r.preferredMimetype(bundle)).to.be('text/html'); }); it('should return `undefined` if there are no registered mimetypes', () => { let r = defaultRenderMime(); expect(r.preferredMimetype({ 'text/fizz': 'buzz' })).to.be(void 0); }); it('should select the mimetype that is safe', () => { let bundle: RenderMime.MimeMap = { 'text/plain': 'foo', 'text/javascript': 'window.x = 1', 'image/png': 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' }; let r = defaultRenderMime(); expect(r.preferredMimetype(bundle, false)).to.be('image/png'); }); it('should render the mimetype that is sanitizable', () => { let bundle: RenderMime.MimeMap = { 'text/plain': 'foo', 'text/html': '

foo

' }; let r = defaultRenderMime(); expect(r.preferredMimetype(bundle, false)).to.be('text/html'); }); }); describe('#clone()', () => { it('should clone the rendermime instance with shallow copies of data', () => { let r = defaultRenderMime(); let c = r.clone(); expect(c.order).to.eql(r.order); let t = new TextRenderer(); c.addRenderer('text/foo', t); expect(r).to.not.be(c); }); }); describe('#addRenderer()', () => { it('should add a renderer by mimetype', () => { let r = defaultRenderMime(); let t = new TextRenderer(); r.addRenderer('text/foo', t); let index = r.order.indexOf('text/foo'); expect(index).to.be(0); }); it('should take an optional order index', () => { let r = defaultRenderMime(); let t = new TextRenderer(); let len = r.order.length; r.addRenderer('text/foo', t, 0); let index = r.order.indexOf('text/foo'); expect(index).to.be(0); expect(r.order.length).to.be(len + 1); }); }); describe('#removeRenderer()', () => { it('should remove a renderer by mimetype', () => { let r = defaultRenderMime(); r.removeRenderer('text/html'); let bundle: RenderMime.MimeMap = { 'text/html': '

foo

' }; expect(r.preferredMimetype(bundle)).to.be(void 0); }); it('should be a no-op if the mimetype is not registered', () => { let r = defaultRenderMime(); r.removeRenderer('text/foo'); }); }); describe('#order', () => { it('should get the ordered list of mimetypes', () => { let r = defaultRenderMime(); expect(r.order.indexOf('text/html')).to.not.be(-1); }); it('should set the ordered list of mimetypes', () => { let r = defaultRenderMime(); let order = r.order.reverse(); r.order = order; expect(r.order).to.eql(order); }); }); }); });