rendermime.spec.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Copyright (c) Jupyter Development Team.
  2. // Distributed under the terms of the Modified BSD License.
  3. import expect = require('expect.js');
  4. import {
  5. toArray
  6. } from 'phosphor/lib/algorithm/iteration';
  7. import {
  8. JSONObject
  9. } from 'phosphor/lib/algorithm/json';
  10. import {
  11. Widget
  12. } from 'phosphor/lib/ui/widget';
  13. import {
  14. TextRenderer
  15. } from '../../../lib/renderers';
  16. import {
  17. RenderMime
  18. } from '../../../lib/rendermime';
  19. import {
  20. defaultRenderMime
  21. } from '../utils';
  22. describe('rendermime/index', () => {
  23. describe('RenderMime', () => {
  24. describe('#constructor()', () => {
  25. it('should accept a mapping and a default order', () => {
  26. let r = defaultRenderMime();
  27. expect(r instanceof RenderMime).to.be(true);
  28. });
  29. });
  30. describe('#render()', () => {
  31. it('should render a mimebundle', () => {
  32. let r = defaultRenderMime();
  33. let w = r.render({ bundle: { 'text/plain': 'foo' } });
  34. expect(w instanceof Widget).to.be(true);
  35. });
  36. it('should return `undefined` for an unregistered mime type', () => {
  37. let r = defaultRenderMime();
  38. let value = r.render({ bundle: { 'text/fizz': 'buzz' } });
  39. expect(value).to.be(void 0);
  40. });
  41. it('should render with the mimetype of highest precidence', () => {
  42. let bundle: RenderMime.MimeMap<string> = {
  43. 'text/plain': 'foo',
  44. 'text/html': '<h1>foo</h1>'
  45. };
  46. let r = defaultRenderMime();
  47. let w = r.render({ bundle, trusted: true });
  48. let el = w.node.firstChild as HTMLElement;
  49. expect(el.localName).to.be('h1');
  50. });
  51. it('should render the mimetype that is safe', () => {
  52. let bundle: RenderMime.MimeMap<string> = {
  53. 'text/plain': 'foo',
  54. 'text/javascript': 'window.x = 1',
  55. 'image/png': 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
  56. };
  57. let r = defaultRenderMime();
  58. let w = r.render({ bundle, trusted: false });
  59. let el = w.node.firstChild as HTMLElement;
  60. expect(el.localName).to.be('img');
  61. });
  62. it('should render the mimetype that is sanitizable', () => {
  63. let bundle: RenderMime.MimeMap<string> = {
  64. 'text/plain': 'foo',
  65. 'text/html': '<h1>foo</h1>'
  66. };
  67. let r = defaultRenderMime();
  68. let w = r.render({ bundle, trusted: false });
  69. let el = w.node.firstChild as HTMLElement;
  70. expect(el.localName).to.be('h1');
  71. });
  72. it('should sanitize html', () => {
  73. let bundle: RenderMime.MimeMap<string> = {
  74. 'text/html': '<h1>foo <script>window.x=1></scrip></h1>'
  75. };
  76. let r = defaultRenderMime();
  77. let widget = r.render({ bundle });
  78. expect(widget.node.innerHTML).to.be('<h1>foo </h1>');
  79. });
  80. it('should render json data', () => {
  81. let bundle: RenderMime.MimeMap<JSONObject> = {
  82. 'application/json': { 'foo': 1 }
  83. };
  84. let r = defaultRenderMime();
  85. let widget = r.render({ bundle });
  86. expect(widget.node.textContent).to.be('{\n "foo": 1\n}');
  87. });
  88. it('should accept an injector', () => {
  89. let called = 0;
  90. let injector = (mimetype: string, value: string | JSONObject) => {
  91. if (mimetype === 'text/plain') {
  92. expect(value as string).to.be('foo');
  93. called++;
  94. } else if (mimetype === 'application/json') {
  95. expect((value as JSONObject)['foo']).to.be(1);
  96. called++;
  97. }
  98. };
  99. let bundle: RenderMime.MimeMap<string> = {
  100. 'foo/bar': '1'
  101. };
  102. let r = defaultRenderMime();
  103. r.render({ bundle, injector });
  104. expect(called).to.be(2);
  105. });
  106. });
  107. describe('#preferredMimetype()', () => {
  108. it('should find the preferred mimetype in a bundle', () => {
  109. let bundle: RenderMime.MimeMap<string> = {
  110. 'text/plain': 'foo',
  111. 'text/html': '<h1>foo</h1>'
  112. };
  113. let r = defaultRenderMime();
  114. expect(r.preferredMimetype(bundle)).to.be('text/html');
  115. });
  116. it('should return `undefined` if there are no registered mimetypes', () => {
  117. let r = defaultRenderMime();
  118. expect(r.preferredMimetype({ 'text/fizz': 'buzz' })).to.be(void 0);
  119. });
  120. it('should select the mimetype that is safe', () => {
  121. let bundle: RenderMime.MimeMap<string> = {
  122. 'text/plain': 'foo',
  123. 'text/javascript': 'window.x = 1',
  124. 'image/png': 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
  125. };
  126. let r = defaultRenderMime();
  127. expect(r.preferredMimetype(bundle)).to.be('image/png');
  128. });
  129. it('should render the mimetype that is sanitizable', () => {
  130. let bundle: RenderMime.MimeMap<string> = {
  131. 'text/plain': 'foo',
  132. 'text/html': '<h1>foo</h1>'
  133. };
  134. let r = defaultRenderMime();
  135. expect(r.preferredMimetype(bundle)).to.be('text/html');
  136. });
  137. });
  138. describe('#clone()', () => {
  139. it('should clone the rendermime instance with shallow copies of data', () => {
  140. let r = defaultRenderMime();
  141. let c = r.clone();
  142. expect(toArray(c.mimetypes())).to.eql(toArray(r.mimetypes()));
  143. let t = new TextRenderer();
  144. c.addRenderer('text/foo', t);
  145. expect(r).to.not.be(c);
  146. });
  147. });
  148. describe('#addRenderer()', () => {
  149. it('should add a renderer by mimetype', () => {
  150. let r = defaultRenderMime();
  151. let t = new TextRenderer();
  152. r.addRenderer('text/foo', t);
  153. let index = toArray(r.mimetypes()).indexOf('text/foo');
  154. expect(index).to.be(0);
  155. });
  156. it('should take an optional order index', () => {
  157. let r = defaultRenderMime();
  158. let t = new TextRenderer();
  159. let len = toArray(r.mimetypes()).length;
  160. r.addRenderer('text/foo', t, 0);
  161. let index = toArray(r.mimetypes()).indexOf('text/foo');
  162. expect(index).to.be(0);
  163. expect(toArray(r.mimetypes()).length).to.be(len + 1);
  164. });
  165. });
  166. describe('#removeRenderer()', () => {
  167. it('should remove a renderer by mimetype', () => {
  168. let r = defaultRenderMime();
  169. r.removeRenderer('text/html');
  170. let bundle: RenderMime.MimeMap<string> = {
  171. 'text/html': '<h1>foo</h1>'
  172. };
  173. expect(r.preferredMimetype(bundle)).to.be(void 0);
  174. });
  175. it('should be a no-op if the mimetype is not registered', () => {
  176. let r = defaultRenderMime();
  177. r.removeRenderer('text/foo');
  178. });
  179. });
  180. describe('#getRenderer()', () => {
  181. it('should get a renderer by mimetype', () => {
  182. let r = defaultRenderMime();
  183. expect(r.getRenderer('text/plain')).to.be.a(TextRenderer);
  184. });
  185. it('should return undefined for missing mimetype', () => {
  186. let r = defaultRenderMime();
  187. expect(r.getRenderer('foo/bar')).to.be(undefined);
  188. });
  189. });
  190. describe('#mimetypes()', () => {
  191. it('should get the ordered list of mimetypes', () => {
  192. let r = defaultRenderMime();
  193. expect(toArray(r.mimetypes()).indexOf('text/html')).to.not.be(-1);
  194. });
  195. });
  196. });
  197. });