diff --git a/spec/index.html b/spec/index.html
index a00433f3..7fb92d17 100644
--- a/spec/index.html
+++ b/spec/index.html
@@ -92,6 +92,7 @@
+
diff --git a/spec/suites/map/handler/Map.KeyboardSpec.js b/spec/suites/map/handler/Map.KeyboardSpec.js
new file mode 100644
index 00000000..13e626f1
--- /dev/null
+++ b/spec/suites/map/handler/Map.KeyboardSpec.js
@@ -0,0 +1,121 @@
+describe("Map.Keyboard", function () {
+
+ var map, container;
+
+ beforeEach(function () {
+ container = document.createElement('div');
+ container.style.width = container.style.height = '600px';
+ container.style.top = container.style.left = 0;
+ container.style.position = 'absolute';
+ document.body.appendChild(container);
+ map = L.map(container, {
+ zoomAnimation: false // If true, the test has to wait extra 250msec
+ });
+
+ map.setView([0, 0], 5);
+
+ // Keyboard functionality expects the map to be focused (clicked or cycle-tabbed)
+ // However this can only happen with trusted events (non-synthetic), so
+ // this bit has to be faked.
+ map.keyboard._onFocus();
+ });
+
+ afterEach(function () {
+ map.remove();
+ document.body.removeChild(container);
+ });
+
+ describe("cursor keys", function () {
+ it("move the map north", function (done) {
+
+ happen.keydown(document, {keyCode: 38}); // 38 = cursor up
+ happen.keypress(document, {keyCode: 38});
+ happen.keyup(document, {keyCode: 38});
+
+ setTimeout(function () {
+ expect(map.getCenter().lat).to.be.greaterThan(0);
+ done();
+ }, 300);
+ });
+
+ it("move the map south", function (done) {
+
+ happen.keydown(document, {keyCode: 40}); // 40 = cursor down
+ happen.keypress(document, {keyCode: 40});
+ happen.keyup(document, {keyCode: 40});
+
+ setTimeout(function () {
+ expect(map.getCenter().lat).to.be.lessThan(0);
+ done();
+ }, 300);
+ });
+
+ it("move the map west", function (done) {
+
+ happen.keydown(document, {keyCode: 37}); // 37 = cursor left
+ happen.keypress(document, {keyCode: 37});
+ happen.keyup(document, {keyCode: 37});
+
+ setTimeout(function () {
+ expect(map.getCenter().lng).to.be.lessThan(0);
+ done();
+ }, 300);
+ });
+
+ it("move the map east", function (done) {
+
+ happen.keydown(document, {keyCode: 39}); // 39 = cursor right
+ happen.keypress(document, {keyCode: 39});
+ happen.keyup(document, {keyCode: 39});
+
+ setTimeout(function () {
+ expect(map.getCenter().lng).to.be.greaterThan(0);
+ done();
+ }, 300);
+ });
+ });
+
+ describe("plus/minus keys", function () {
+ it("zoom in", function (done) {
+
+ happen.keydown(document, {keyCode: 171}); // 171 = +
+ happen.keypress(document, {keyCode: 171});
+ happen.keyup(document, {keyCode: 171});
+
+ setTimeout(function () {
+ expect(map.getZoom()).to.be.greaterThan(5);
+ done();
+ }, 300);
+ });
+
+ it("zoom out", function (done) {
+
+ happen.keydown(document, {keyCode: 173}); // 173 = - (in firefox)
+ happen.keypress(document, {keyCode: 173});
+ happen.keyup(document, {keyCode: 173});
+
+ setTimeout(function () {
+ expect(map.getZoom()).to.be.lessThan(5);
+ done();
+ }, 300);
+ });
+ });
+
+
+ describe("popup closing", function () {
+ it("closes a popup when pressing escape", function () {
+
+ var popup = L.popup().setLatLng([0, 0]).setContent('Null Island');
+ map.openPopup(popup);
+
+ expect(popup.isOpen()).to.be(true);
+
+ happen.keydown(document, {keyCode: 27}); // 27 = Esc
+// happen.keypress(document, {keyCode: 27});
+ happen.keyup(document, {keyCode: 27});
+
+ expect(popup.isOpen()).to.be(false);
+ });
+ });
+
+});
diff --git a/src/map/handler/Map.Keyboard.js b/src/map/handler/Map.Keyboard.js
index a0fd68d3..b0dfca85 100644
--- a/src/map/handler/Map.Keyboard.js
+++ b/src/map/handler/Map.Keyboard.js
@@ -162,7 +162,7 @@ export var Keyboard = Handler.extend({
} else if (key in this._zoomKeys) {
map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
- } else if (key === 27) {
+ } else if (key === 27 && map._popup) {
map.closePopup();
} else {