Quellcode durchsuchen

Merge pull request #139 from blink1073/trust-test

Update notebook trust handler and tests
A. Darian vor 9 Jahren
Ursprung
Commit
631cfcfca8

+ 1 - 1
src/dialog/index.ts

@@ -199,7 +199,7 @@ function showDialog(options?: IDialogOptions): Promise<IButtonItem> {
       // Check for escape key
       if (evt.keyCode === 27) {
         host.removeChild(dialog);
-        resolve(null);
+        resolve(cancelButton);
       }
     }, true);
     dialog.addEventListener('contextmenu', evt => {

+ 1 - 1
src/notebook/notebook/trust.ts

@@ -29,7 +29,7 @@ const TRUST_MESSAGE = '<p>A trusted Jupyter notebook may execute hidden maliciou
 export
 function trustNotebook(model: INotebookModel, host?: HTMLElement): Promise<void> {
   if (!model) {
-    return;
+    return Promise.resolve(void 0);
   }
   // Do nothing if already trusted.
   let cells = model.cells;

+ 16 - 13
test/src/dialog/dialog.spec.ts

@@ -3,28 +3,31 @@
 
 import expect = require('expect.js');
 
+import {
+  simulate
+} from 'simulate-event';
+
 import {
   showDialog, okButton
 } from '../../../lib/dialog';
 
 import {
-  triggerMouseEvent, triggerKeyEvent, acceptDialog, dismissDialog
+  acceptDialog, dismissDialog
 } from '../utils';
 
 
-
-describe('jupyter-ui', () => {
+describe('dialog/index', () => {
 
   describe('showDialog()', () => {
 
     it('should accept zero arguments', (done) => {
       showDialog().then(result => {
-        expect(result).to.be(null);
+        expect(result.text).to.be('CANCEL');
         done();
       });
       Promise.resolve().then(() => {
         let node = document.body.getElementsByClassName('jp-Dialog')[0];
-        triggerKeyEvent(node as HTMLElement, 'keydown', { keyCode: 27 });
+        simulate(node as HTMLElement, 'keydown', { keyCode: 27 });
       });
     });
 
@@ -37,14 +40,14 @@ describe('jupyter-ui', () => {
         host: node,
         buttons: [okButton],
         okText: 'Yep'
-      }
+      };
       showDialog(options).then(result => {
-        expect(result).to.be(null);
+        expect(result.text).to.be('CANCEL');
         done();
       });
       Promise.resolve().then(() => {
         let target = document.body.getElementsByClassName('jp-Dialog')[0];
-        triggerKeyEvent(target as HTMLElement, 'keydown', { keyCode: 27 });
+        simulate(target as HTMLElement, 'keydown', { keyCode: 27 });
       });
     });
 
@@ -64,7 +67,7 @@ describe('jupyter-ui', () => {
     it('should accept an input body', (done) => {
       let body = document.createElement('input');
       showDialog({ body }).then(result => {
-        expect(result).to.be(null);
+        expect(result.text).to.be('CANCEL');
         done();
       });
       dismissDialog();
@@ -84,7 +87,7 @@ describe('jupyter-ui', () => {
         text: 'foo',
         className: 'bar',
         icon: 'baz'
-      }
+      };
       showDialog({ buttons: [button] }).then(result => {
         expect(result.text).to.be('foo');
         done();
@@ -98,13 +101,13 @@ describe('jupyter-ui', () => {
     it('should ignore context menu events', (done) => {
       let body = document.createElement('div');
       showDialog({ body }).then(result => {
-        expect(result).to.be(null);
+        expect(result.text).to.be('CANCEL');
         done();
       });
       Promise.resolve().then(() => {
         let node = document.body.getElementsByClassName('jp-Dialog')[0];
-        triggerMouseEvent(node as HTMLElement, 'contextmenu');
-        triggerKeyEvent(node as HTMLElement, 'keydown', { keyCode: 27 });
+        simulate(node as HTMLElement, 'contextmenu');
+        simulate(node as HTMLElement, 'keydown', { keyCode: 27 });
       });
     });
 

+ 1 - 0
test/src/index.ts

@@ -13,6 +13,7 @@ import './notebook/notebook/nbformat.spec';
 import './notebook/notebook/model.spec';
 import './notebook/notebook/modelfactory.spec';
 import './notebook/notebook/toolbar.spec';
+import './notebook/notebook/trust.spec';
 import './notebook/notebook/widget.spec';
 import './notebook/notebook/widgetfactory.spec';
 

+ 3 - 2
test/src/notebook/notebook/model.spec.ts

@@ -19,8 +19,9 @@ import {
   NotebookModel
 } from '../../../../lib/notebook/notebook/model';
 
-
-const DEFAULT_CONTENT: nbformat.INotebookContent = require('../../../../examples/notebook/test.ipynb') as nbformat.INotebookContent;
+import {
+  DEFAULT_CONTENT
+} from '../utils';
 
 
 describe('notebook/notebook', () => {

+ 70 - 0
test/src/notebook/notebook/trust.spec.ts

@@ -0,0 +1,70 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import expect = require('expect.js');
+
+import {
+ NotebookModel
+} from '../../../../lib/notebook/notebook/model';
+
+import {
+  trustNotebook
+} from '../../../../lib/notebook/notebook/trust';
+
+import {
+  acceptDialog, dismissDialog
+} from '../../utils';
+
+import {
+  DEFAULT_CONTENT
+} from '../utils';
+
+
+describe('notebook/notebook/trust', () => {
+
+  describe('#trustNotebook()', () => {
+
+    it('should trust the notebook cells if the user accepts', (done) => {
+      let model = new NotebookModel();
+      model.fromJSON(DEFAULT_CONTENT);
+      let cell = model.cells.get(0);
+      let cursor = cell.getMetadata('trusted');
+      expect(cursor.getValue()).to.not.be(true);
+      trustNotebook(model).then(() => {
+        expect(cursor.getValue()).to.be(true);
+        done();
+      });
+      acceptDialog();
+    });
+
+    it('should not trust the notebook cells if the user aborts', (done) => {
+      let model = new NotebookModel();
+      model.fromJSON(DEFAULT_CONTENT);
+      let cell = model.cells.get(0);
+      let cursor = cell.getMetadata('trusted');
+      expect(cursor.getValue()).to.not.be(true);
+      trustNotebook(model).then(() => {
+        expect(cursor.getValue()).to.not.be(true);
+        done();
+      });
+      dismissDialog();
+    });
+
+    it('should bail if the model is `null`', (done) => {
+      trustNotebook(null).then(() => { done(); });
+    });
+
+    it('should bail if all of the cells are trusted', (done) => {
+      let model = new NotebookModel();
+      model.fromJSON(DEFAULT_CONTENT);
+      for (let i = 0; i < model.cells.length; i++) {
+        let cell = model.cells.get(i);
+        let cursor = cell.getMetadata('trusted');
+        cursor.setValue(true);
+      }
+      trustNotebook(model).then(() => { done(); });
+    });
+
+  });
+
+});

+ 4 - 6
test/src/notebook/notebook/widget.spec.ts

@@ -32,18 +32,16 @@ import {
   Notebook, StaticNotebook
 } from '../../../../lib/notebook/notebook/widget';
 
-import {
-  nbformat
-} from '../../../../lib/notebook/notebook/nbformat';
-
 import {
   defaultRenderMime
 } from '../../rendermime/rendermime.spec';
 
+import {
+  DEFAULT_CONTENT
+} from '../utils';
 
-const rendermime = defaultRenderMime();
 
-const DEFAULT_CONTENT: nbformat.INotebookContent = require('../../../../examples/notebook/test.ipynb') as nbformat.INotebookContent;
+const rendermime = defaultRenderMime();
 
 
 function createWidget(): LogStaticNotebook {

+ 13 - 0
test/src/notebook/utils.ts

@@ -0,0 +1,13 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import {
+  nbformat
+} from '../../../lib/notebook/notebook/nbformat';
+
+
+/**
+ * The default notebook content.
+ */
+export
+const DEFAULT_CONTENT: nbformat.INotebookContent = require('../../../examples/notebook/test.ipynb') as nbformat.INotebookContent;

+ 19 - 21
test/src/utils.ts

@@ -1,24 +1,14 @@
 // Copyright (c) Jupyter Development Team.
 // Distributed under the terms of the Modified BSD License.
 
-export
-function triggerMouseEvent(node: HTMLElement, eventType: string, options: any = {}) {
-  let evt = new MouseEvent(eventType, options);
-  node.dispatchEvent(evt);
-}
-
-
-export
-function triggerKeyEvent(node: HTMLElement, eventType: string, options: any = {}) {
-  let evt = new KeyboardEvent(eventType, options);
-  // Work around bug in Chrome that zeros out the keyCode.
-  if ('keyCode' in options) {
-    Object.defineProperty(evt, 'keyCode', { value: options['keyCode'] });
-  }
-  node.dispatchEvent(evt);
-}
+import {
+  simulate
+} from 'simulate-event';
 
 
+/**
+ * Wait for a dialog to be attached to an element.
+ */
 export
 function waitForDialog(host: HTMLElement = document.body): Promise<void> {
   return new Promise<void>((resolve, reject) => {
@@ -29,27 +19,35 @@ function waitForDialog(host: HTMLElement = document.body): Promise<void> {
         return;
       }
       setTimeout(refresh, 10);
-    }
+    };
     refresh();
   });
 }
 
 
+/**
+ * Accept a dialog after it is attached if it has an OK button.
+ */
 export
 function acceptDialog(host: HTMLElement = document.body): Promise<void> {
-  return waitForDialog().then(() => {
+  return waitForDialog(host).then(() => {
     let node = host.getElementsByClassName('jp-Dialog-okButton')[0];
-    if (node) (node as HTMLElement).click();
+    if (node) {
+      (node as HTMLElement).click();
+    }
   });
 }
 
 
+/**
+ * Dismiss a dialog after it is attached.
+ */
 export
 function dismissDialog(host: HTMLElement = document.body): Promise<void> {
-  return waitForDialog().then(() => {
+  return waitForDialog(host).then(() => {
     let node = host.getElementsByClassName('jp-Dialog')[0];
     if (node) {
-      triggerKeyEvent(node as HTMLElement, 'keydown', { keyCode: 27 });
+      simulate(node as HTMLElement, 'keydown', { keyCode: 27 });
     }
   });
 }