diff --git a/src/static/js/skiplist.js b/src/static/js/skiplist.js index 798991ad9..105f5902c 100644 --- a/src/static/js/skiplist.js +++ b/src/static/js/skiplist.js @@ -95,6 +95,11 @@ class Point { } insert(entry) { + if (entry.key == null) throw new Error('entry.key must not be null'); + if (this._skipList.containsKey(entry.key)) { + throw new Error(`an entry with key ${entry.key} already exists`); + } + const newNode = new Node(entry); const pNodes = this.nodes; const pIdxs = this.idxs; diff --git a/src/tests/frontend/index.html b/src/tests/frontend/index.html index 3b0f1c6e0..6e2f8ca77 100644 --- a/src/tests/frontend/index.html +++ b/src/tests/frontend/index.html @@ -9,6 +9,7 @@
+ diff --git a/src/tests/frontend/runner.js b/src/tests/frontend/runner.js index d9f37bcae..b119f2963 100644 --- a/src/tests/frontend/runner.js +++ b/src/tests/frontend/runner.js @@ -159,6 +159,11 @@ $(() => { // get the list of specs and filter it if requested const specs = specs_list.slice(); + const absUrl = (url) => new URL(url, window.location.href).href; + require.setRootURI(absUrl('../../javascripts/src')); + require.setLibraryURI(absUrl('../../javascripts/lib')); + require.setGlobalKeyPath('require'); + // inject spec scripts into the dom const $body = $('body'); $.each(specs, (i, spec) => { diff --git a/src/tests/frontend/specs/skiplist.js b/src/tests/frontend/specs/skiplist.js new file mode 100644 index 000000000..4b2ebd5aa --- /dev/null +++ b/src/tests/frontend/specs/skiplist.js @@ -0,0 +1,18 @@ +'use strict'; + +const SkipList = require('ep_etherpad-lite/static/js/skiplist'); + +describe('skiplist.js', function () { + it('rejects null keys', async function () { + const skiplist = new SkipList(); + for (const key of [undefined, null]) { + expect(() => skiplist.push({key})).to.throwError(); + } + }); + + it('rejects duplicate keys', async function () { + const skiplist = new SkipList(); + skiplist.push({key: 'foo'}); + expect(() => skiplist.push({key: 'foo'})).to.throwError(); + }); +});