From 357de85129d44393cca167643195e009c7bb62b0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Gerardy Date: Tue, 26 Jul 2016 00:53:33 +0200 Subject: [PATCH 1/8] Test for #1146 and #1153 --- api/tests/test-mount.js | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/api/tests/test-mount.js b/api/tests/test-mount.js index 5bc39e5f..24a9bc78 100644 --- a/api/tests/test-mount.js +++ b/api/tests/test-mount.js @@ -68,6 +68,71 @@ o.spec("mount", function() { }, FRAME_BUDGET) }) + o("redraws several mount points on events", function(done) { + var onupdate0 = o.spy() + var oninit0 = o.spy() + var onclick0 = o.spy() + var onupdate1 = o.spy() + var oninit1 = o.spy() + var onclick1 = o.spy() + + var e = $window.document.createEvent("MouseEvents") + + e.initEvent("click", true, true) + + render(root, [ + m("#child0"), + m("#child1") + ]) + + mount(root.childNodes[0], { + view : function() { + return m("div", { + oninit : oninit0, + onupdate : onupdate0, + onclick : onclick0, + }) + } + }) + + o(oninit0.callCount).equals(1) + o(onupdate0.callCount).equals(0) + + mount(root.childNodes[1], { + view : function() { + return m("div", { + oninit : oninit1, + onupdate : onupdate1, + onclick : onclick1, + }) + } + }) + + o(oninit1.callCount).equals(1) + o(onupdate1.callCount).equals(0) + + root.childNodes[0].firstChild.dispatchEvent(e) + o(onclick0.callCount).equals(1) + o(onclick0.this).equals(root.childNodes[0].firstChild) + + setTimeout(function() { + o(onupdate0.callCount).equals(1) + o(onupdate1.callCount).equals(1) + + root.childNodes[1].firstChild.dispatchEvent(e) + o(onclick1.callCount).equals(1) + o(onclick1.this).equals(root.childNodes[1].firstChild) + + setTimeout(function() { + o(onupdate0.callCount).equals(2) + o(onupdate1.callCount).equals(2) + + done() + }, FRAME_BUDGET) + }, FRAME_BUDGET) + + }) + o("event handlers can skip redraw", function(done) { var onupdate = o.spy() var oninit = o.spy() From 47070e2f0c8b7ca127803ef4a3bb20b84c35f5f8 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Tue, 2 Aug 2016 10:32:26 -0400 Subject: [PATCH 2/8] compare path, not route --- api/router.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/router.js b/api/router.js index 78c42375..496b5684 100644 --- a/api/router.js +++ b/api/router.js @@ -7,16 +7,16 @@ var autoredraw = require("../api/autoredraw") module.exports = function($window, renderer, pubsub) { var router = coreRouter($window) var route = function(root, defaultRoute, routes) { - var current = {route: null, component: null} + var current = {path: null, component: null} var replay = router.defineRoutes(routes, function(payload, args, path, route) { if (typeof payload.view !== "function") { if (typeof payload.render !== "function") payload.render = function(vnode) {return vnode} var render = function(component) { - current.route = route, current.component = component + current.path = path, current.component = component renderer.render(root, payload.render(Vnode(component, null, args, undefined, undefined, undefined))) } if (typeof payload.resolve !== "function") payload.resolve = function() {render(current.component)} - if (route !== current.route) payload.resolve(render, args, path, route) + if (path !== current.path) payload.resolve(render, args, path, route) else render(current.component) } else { From 20da8d3dc894fb1db661b4638c23cbfadbad9bca Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Tue, 2 Aug 2016 10:43:50 -0400 Subject: [PATCH 3/8] remove redundant check --- render/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render/render.js b/render/render.js index a387e687..50d2404c 100644 --- a/render/render.js +++ b/render/render.js @@ -356,7 +356,7 @@ module.exports = function($window) { } } if (vnode.dom.parentNode != null) parent.removeChild(vnode.dom) - if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string" && vnode.tag !== "<") { //TODO test custom elements + if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string") { //TODO test custom elements if (!context.pool) context.pool = [vnode] else context.pool.push(vnode) } From 6d9d01c12be9f970dca84a10e3d79d426ab4981e Mon Sep 17 00:00:00 2001 From: Gilbert Date: Tue, 2 Aug 2016 11:06:38 -0500 Subject: [PATCH 4/8] Add failing test --- util/tests/test-stream.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/util/tests/test-stream.js b/util/tests/test-stream.js index 458016ed..a87247af 100644 --- a/util/tests/test-stream.js +++ b/util/tests/test-stream.js @@ -549,9 +549,17 @@ o.spec("stream", function() { var absorbed = Stream.stream() var mapped = stream.run(function(value) {return absorbed}) - absorbed(2) + var depCallCount = 0 + mapped.map(function (value) { + o(value).equals(200) + depCallCount += 1 + }) + o(depCallCount).equals(0) - o(mapped()).equals(2) + absorbed(200) + o(depCallCount).equals(1) + + o(mapped()).equals(200) }) o("works when updating pending stream to errored state", function() { var stream = Stream.stream(undefined) From 8ec3a3f2c5a9b5c6027c7474144e13251c8fdf70 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Tue, 2 Aug 2016 23:21:13 -0400 Subject: [PATCH 5/8] test router using file protocol as start point --- api/tests/test-router.js | 604 +++++++++++++++--------------- router/router.js | 4 +- router/tests/test-defineRoutes.js | 456 +++++++++++----------- router/tests/test-getPath.js | 60 +-- router/tests/test-setPath.js | 230 ++++++------ test-utils/pushStateMock.js | 8 +- 6 files changed, 686 insertions(+), 676 deletions(-) diff --git a/api/tests/test-router.js b/api/tests/test-router.js index 627ffc34..713f9bf1 100644 --- a/api/tests/test-router.js +++ b/api/tests/test-router.js @@ -11,325 +11,327 @@ var apiPubSub = require("../../api/pubsub") var apiRouter = require("../../api/router") o.spec("route", function() { - void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { - o.spec("using prefix `" + prefix + "`", function() { - var FRAME_BUDGET = Math.floor(1000 / 60) - var $window, root, redraw, route + void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) { + void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { + o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() { + var FRAME_BUDGET = Math.floor(1000 / 60) + var $window, root, redraw, route - o.beforeEach(function() { - $window = {} + o.beforeEach(function() { + $window = {} - var dom = domMock() - for (var key in dom) $window[key] = dom[key] + var dom = domMock() + for (var key in dom) $window[key] = dom[key] - var loc = pushStateMock() - for (var key in loc) $window[key] = loc[key] + var loc = pushStateMock(env) + for (var key in loc) $window[key] = loc[key] - root = $window.document.body + root = $window.document.body - redraw = apiPubSub() - route = apiRouter($window, coreRenderer($window), redraw) - route.prefix(prefix) - }) + redraw = apiPubSub() + route = apiRouter($window, coreRenderer($window), redraw) + route.prefix(prefix) + }) - o("renders into `root`", function(done) { - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - view: function() { - return m("div") + o("renders into `root`", function(done) { + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + view: function() { + return m("div") + } } - } - }) - - callAsync(function() { - o(root.firstChild.nodeName).equals("DIV") - - done() - }) - }) - - o("default route doesn't break back button", function(done) { - $window.location.href = "http://google.com" - route(root, "/a", { - "/a" : { - view: function() { - return m("div") - } - } - }) - - setTimeout(function() { - o(root.firstChild.nodeName).equals("DIV") - - $window.history.back() - - o($window.location.pathname).equals("/") - - done() - }, FRAME_BUDGET) - }) - - o("default route does not inherit params", function(done) { - $window.location.href = "/invalid?foo=bar" - route(root, "/a", { - "/a" : { - oninit: init, - view: function() { - return m("div") - } - } - }) - - function init(vnode) { - o(vnode.attrs).deepEquals({}) - - done() - } - }) - - o("redraws when render function is executed", function(done) { - var onupdate = o.spy() - var oninit = o.spy() - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - view: function() { - return m("div", { - oninit: oninit, - onupdate: onupdate - }) - } - } - }) - - callAsync(function() { - o(oninit.callCount).equals(1) - - redraw.publish() - - // Wrapped to give time for the rate-limited redraw to fire - setTimeout(function() { - o(onupdate.callCount).equals(1) + }) + callAsync(function() { + o(root.firstChild.nodeName).equals("DIV") + done() - }, FRAME_BUDGET) + }) }) - }) - o("redraws on events", function(done) { - var onupdate = o.spy() - var oninit = o.spy() - var onclick = o.spy() - var e = $window.document.createEvent("MouseEvents") - - e.initEvent("click", true, true) - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - view: function() { - return m("div", { - oninit: oninit, - onupdate: onupdate, - onclick: onclick, - }) + o("default route doesn't break back button", function(done) { + $window.location.href = "http://google.com" + route(root, "/a", { + "/a" : { + view: function() { + return m("div") + } } - } - }) - - callAsync(function() { - root.firstChild.dispatchEvent(e) - - o(oninit.callCount).equals(1) - - o(onclick.callCount).equals(1) - o(onclick.this).equals(root.firstChild) - o(onclick.args[0].type).equals("click") - o(onclick.args[0].target).equals(root.firstChild) - - // Wrapped to give time for the rate-limited redraw to fire - setTimeout(function() { - o(onupdate.callCount).equals(1) - - done() - }, FRAME_BUDGET) - }) - }) - - o("event handlers can skip redraw", function(done) { - var onupdate = o.spy() - var oninit = o.spy() - var onclick = o.spy() - var e = $window.document.createEvent("MouseEvents") - - e.initEvent("click", true, true) - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - view: function() { - return m("div", { - oninit: oninit, - onupdate: onupdate, - onclick: function(e) { - e.redraw = false - }, - }) - } - } - }) - - callAsync(function() { - root.firstChild.dispatchEvent(e) - - o(oninit.callCount).equals(1) - - // Wrapped to ensure no redraw fired - setTimeout(function() { - o(onupdate.callCount).equals(0) - - done() - }, FRAME_BUDGET) - }) - }) - - o("changes location on route.link", function(done) { - var e = $window.document.createEvent("MouseEvents") - - e.initEvent("click", true, true) - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - view: function() { - return m("a", { - href: "/test", - oncreate: route.link - }) - } - }, - "/test" : { - view : function() { - return m("div") - } - } - }) - - callAsync(function() { - var slash = prefix[0] === "/" ? "" : "/" - - o($window.location.href).equals("http://localhost" + slash + (prefix ? prefix + "/" : "")) - - root.firstChild.dispatchEvent(e) - - o($window.location.href).equals("http://localhost" + slash + (prefix ? prefix + "/" : "") + "test") - - done() - }) - }) - - o("accepts object as payload", function(done) { - var Component = { - view: function() { - return m("div") - } - } - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - resolve: function(resolve) {resolve(Component)}, - render: function(vnode) {return vnode}, - }, - }) - - callAsync(function() { - o(root.firstChild.nodeName).equals("DIV") - - done() - }) - }) - - o("accepts object without `render` method as payload", function(done) { - var Component = { - view: function() { - return m("div") - } - } - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - resolve: function(resolve) {resolve(Component)}, - }, - }) - - callAsync(function() { - o(root.firstChild.nodeName).equals("DIV") - - done() - }) - }) - - o("accepts object without `resolve` method as payload", function(done) { - var Component = { - view: function() { - return m("div") - } - } - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - render: function() {return m(Component)}, - }, - }) - - callAsync(function() { - o(root.firstChild.nodeName).equals("DIV") - - done() - }) - }) - - o("calls resolve and render correct number of times", function(done) { - var resolveCount = 0 - var renderCount = 0 - var Component = { - view: function() { - return m("div") - } - } - - $window.location.href = prefix + "/" - route(root, "/", { - "/" : { - resolve: function(resolve) { - resolveCount++ - resolve(Component) - }, - render: function(vnode) { - renderCount++ - return vnode - }, - }, - }) - - callAsync(function() { - o(resolveCount).equals(1) - o(renderCount).equals(1) - - redraw.publish() + }) setTimeout(function() { - o(resolveCount).equals(1) - o(renderCount).equals(2) + o(root.firstChild.nodeName).equals("DIV") + + $window.history.back() + + o($window.location.pathname).equals("/") done() }, FRAME_BUDGET) }) + + o("default route does not inherit params", function(done) { + $window.location.href = "/invalid?foo=bar" + route(root, "/a", { + "/a" : { + oninit: init, + view: function() { + return m("div") + } + } + }) + + function init(vnode) { + o(vnode.attrs).deepEquals({}) + + done() + } + }) + + o("redraws when render function is executed", function(done) { + var onupdate = o.spy() + var oninit = o.spy() + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + view: function() { + return m("div", { + oninit: oninit, + onupdate: onupdate + }) + } + } + }) + + callAsync(function() { + o(oninit.callCount).equals(1) + + redraw.publish() + + // Wrapped to give time for the rate-limited redraw to fire + setTimeout(function() { + o(onupdate.callCount).equals(1) + + done() + }, FRAME_BUDGET) + }) + }) + + o("redraws on events", function(done) { + var onupdate = o.spy() + var oninit = o.spy() + var onclick = o.spy() + var e = $window.document.createEvent("MouseEvents") + + e.initEvent("click", true, true) + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + view: function() { + return m("div", { + oninit: oninit, + onupdate: onupdate, + onclick: onclick, + }) + } + } + }) + + callAsync(function() { + root.firstChild.dispatchEvent(e) + + o(oninit.callCount).equals(1) + + o(onclick.callCount).equals(1) + o(onclick.this).equals(root.firstChild) + o(onclick.args[0].type).equals("click") + o(onclick.args[0].target).equals(root.firstChild) + + // Wrapped to give time for the rate-limited redraw to fire + setTimeout(function() { + o(onupdate.callCount).equals(1) + + done() + }, FRAME_BUDGET) + }) + }) + + o("event handlers can skip redraw", function(done) { + var onupdate = o.spy() + var oninit = o.spy() + var onclick = o.spy() + var e = $window.document.createEvent("MouseEvents") + + e.initEvent("click", true, true) + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + view: function() { + return m("div", { + oninit: oninit, + onupdate: onupdate, + onclick: function(e) { + e.redraw = false + }, + }) + } + } + }) + + callAsync(function() { + root.firstChild.dispatchEvent(e) + + o(oninit.callCount).equals(1) + + // Wrapped to ensure no redraw fired + setTimeout(function() { + o(onupdate.callCount).equals(0) + + done() + }, FRAME_BUDGET) + }) + }) + + o("changes location on route.link", function(done) { + var e = $window.document.createEvent("MouseEvents") + + e.initEvent("click", true, true) + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + view: function() { + return m("a", { + href: "/test", + oncreate: route.link + }) + } + }, + "/test" : { + view : function() { + return m("div") + } + } + }) + + callAsync(function() { + var slash = prefix[0] === "/" ? "" : "/" + + o($window.location.href).equals(env.protocol + "//" + (env.hostname === "/" ? "" : env.hostname) + slash + (prefix ? prefix + "/" : "")) + + root.firstChild.dispatchEvent(e) + + o($window.location.href).equals(env.protocol + "//" + (env.hostname === "/" ? "" : env.hostname) + slash + (prefix ? prefix + "/" : "") + "test") + + done() + }) + }) + + o("accepts object as payload", function(done) { + var Component = { + view: function() { + return m("div") + } + } + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + resolve: function(resolve) {resolve(Component)}, + render: function(vnode) {return vnode}, + }, + }) + + callAsync(function() { + o(root.firstChild.nodeName).equals("DIV") + + done() + }) + }) + + o("accepts object without `render` method as payload", function(done) { + var Component = { + view: function() { + return m("div") + } + } + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + resolve: function(resolve) {resolve(Component)}, + }, + }) + + callAsync(function() { + o(root.firstChild.nodeName).equals("DIV") + + done() + }) + }) + + o("accepts object without `resolve` method as payload", function(done) { + var Component = { + view: function() { + return m("div") + } + } + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + render: function() {return m(Component)}, + }, + }) + + callAsync(function() { + o(root.firstChild.nodeName).equals("DIV") + + done() + }) + }) + + o("calls resolve and render correct number of times", function(done) { + var resolveCount = 0 + var renderCount = 0 + var Component = { + view: function() { + return m("div") + } + } + + $window.location.href = prefix + "/" + route(root, "/", { + "/" : { + resolve: function(resolve) { + resolveCount++ + resolve(Component) + }, + render: function(vnode) { + renderCount++ + return vnode + }, + }, + }) + + callAsync(function() { + o(resolveCount).equals(1) + o(renderCount).equals(1) + + redraw.publish() + + setTimeout(function() { + o(resolveCount).equals(1) + o(renderCount).equals(2) + + done() + }, FRAME_BUDGET) + }) + }) }) }) }) diff --git a/router/router.js b/router/router.js index 6d522916..61ded804 100644 --- a/router/router.js +++ b/router/router.js @@ -4,7 +4,7 @@ var buildQueryString = require("../querystring/build") var parseQueryString = require("../querystring/parse") module.exports = function($window) { - var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:" + var supportsPushState = typeof $window.history.pushState === "function" var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout var prefix = "#!" @@ -75,7 +75,7 @@ module.exports = function($window) { var path = getPath() var params = {} var pathname = parsePath(path, params, params) - + callAsync(function() { for (var route in routes) { var matcher = new RegExp("^" + route.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$") diff --git a/router/tests/test-defineRoutes.js b/router/tests/test-defineRoutes.js index 646660d5..9ad33d67 100644 --- a/router/tests/test-defineRoutes.js +++ b/router/tests/test-defineRoutes.js @@ -6,295 +6,297 @@ var pushStateMock = require("../../test-utils/pushStateMock") var Router = require("../../router/router") o.spec("Router.defineRoutes", function() { - void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { - o.spec("using prefix `" + prefix + "`", function() { - var $window, router, onRouteChange, onFail + void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) { + void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { + o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() { + var $window, router, onRouteChange, onFail - o.beforeEach(function() { - $window = pushStateMock() - router = new Router($window) - router.setPrefix(prefix) - onRouteChange = o.spy() - onFail = o.spy() - }) + o.beforeEach(function() { + $window = pushStateMock(env) + router = new Router($window) + router.setPrefix(prefix) + onRouteChange = o.spy() + onFail = o.spy() + }) - o("calls onRouteChange on init", function(done) { - $window.location.href = prefix + "/a" - router.defineRoutes({"/a": {data: 1}}, onRouteChange, onFail) + o("calls onRouteChange on init", function(done) { + $window.location.href = prefix + "/a" + router.defineRoutes({"/a": {data: 1}}, onRouteChange, onFail) + + callAsync(function() { + o(onRouteChange.callCount).equals(1) + + done() + }) + }) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - - done() + o("resolves to route", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - - o("resolves to route", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) - o(onFail.callCount).equals(0) - - done() + o("resolves to route w/ escaped unicode", function(done) { + $window.location.href = prefix + "/%C3%B6?%C3%B6=%C3%B6#%C3%B6=%C3%B6" + router.defineRoutes({"/ö": {data: 2}}, onRouteChange, onFail) + + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 2}, {"ö": "ö"}, "/ö?ö=ö#ö=ö", "/ö"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("resolves to route w/ escaped unicode", function(done) { - $window.location.href = prefix + "/%C3%B6?%C3%B6=%C3%B6#%C3%B6=%C3%B6" - router.defineRoutes({"/ö": {data: 2}}, onRouteChange, onFail) + o("resolves to route w/ unicode", function(done) { + $window.location.href = prefix + "/ö?ö=ö#ö=ö" + router.defineRoutes({"/ö": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 2}, {"ö": "ö"}, "/ö?ö=ö#ö=ö", "/ö"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 2}, {"ö": "ö"}, "/ö?ö=ö#ö=ö", "/ö"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("resolves to route w/ unicode", function(done) { - $window.location.href = prefix + "/ö?ö=ö#ö=ö" - router.defineRoutes({"/ö": {data: 2}}, onRouteChange, onFail) + o("resolves to route on fallback mode", function(done) { + $window.location.href = "file://" + prefix + "/test" - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 2}, {"ö": "ö"}, "/ö?ö=ö#ö=ö", "/ö"]) - o(onFail.callCount).equals(0) - - done() + router = new Router($window) + router.setPrefix(prefix) + + router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("resolves to route on fallback mode", function(done) { - $window.location.href = "file://" + prefix + "/test" + o("handles parameterized route", function(done) { + $window.location.href = prefix + "/test/x" + router.defineRoutes({"/test/:a": {data: 1}}, onRouteChange, onFail) - router = new Router($window) - router.setPrefix(prefix) - - router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {a: "x"}, "/test/x", "/test/:a"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("handles parameterized route", function(done) { - $window.location.href = prefix + "/test/x" - router.defineRoutes({"/test/:a": {data: 1}}, onRouteChange, onFail) + o("handles multi-parameterized route", function(done) { + $window.location.href = prefix + "/test/x/y" + router.defineRoutes({"/test/:a/:b": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {a: "x"}, "/test/x", "/test/:a"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {a: "x", b: "y"}, "/test/x/y", "/test/:a/:b"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("handles multi-parameterized route", function(done) { - $window.location.href = prefix + "/test/x/y" - router.defineRoutes({"/test/:a/:b": {data: 1}}, onRouteChange, onFail) + o("handles rest parameterized route", function(done) { + $window.location.href = prefix + "/test/x/y" + router.defineRoutes({"/test/:a...": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {a: "x", b: "y"}, "/test/x/y", "/test/:a/:b"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {a: "x/y"}, "/test/x/y", "/test/:a..."]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("handles rest parameterized route", function(done) { - $window.location.href = prefix + "/test/x/y" - router.defineRoutes({"/test/:a...": {data: 1}}, onRouteChange, onFail) + o("handles route with search", function(done) { + $window.location.href = prefix + "/test?a=b&c=d" + router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {a: "x/y"}, "/test/x/y", "/test/:a..."]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {a: "b", c: "d"}, "/test?a=b&c=d", "/test"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("handles route with search", function(done) { - $window.location.href = prefix + "/test?a=b&c=d" - router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + o("handles route with hash", function(done) { + $window.location.href = prefix + "/test#a=b&c=d" + router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {a: "b", c: "d"}, "/test?a=b&c=d", "/test"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {a: "b", c: "d"}, "/test#a=b&c=d", "/test"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("handles route with hash", function(done) { - $window.location.href = prefix + "/test#a=b&c=d" - router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + o("handles route with search and hash", function(done) { + $window.location.href = prefix + "/test?a=b#c=d" + router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {a: "b", c: "d"}, "/test#a=b&c=d", "/test"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {a: "b", c: "d"}, "/test?a=b#c=d", "/test"]) + o(onFail.callCount).equals(0) + + done() + }) }) - }) - o("handles route with search and hash", function(done) { - $window.location.href = prefix + "/test?a=b#c=d" - router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + o("calls reject", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/other": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {a: "b", c: "d"}, "/test?a=b#c=d", "/test"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onFail.callCount).equals(1) + o(onFail.args).deepEquals(["/test", {}]) + + done() + }) }) - }) - o("calls reject", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/other": {data: 1}}, onRouteChange, onFail) + o("calls reject w/ search and hash", function(done) { + $window.location.href = prefix + "/test?a=b#c=d" + router.defineRoutes({"/other": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onFail.callCount).equals(1) - o(onFail.args).deepEquals(["/test", {}]) - - done() + callAsync(function() { + o(onFail.callCount).equals(1) + o(onFail.args).deepEquals(["/test?a=b#c=d", {a: "b", c: "d"}]) + + done() + }) }) - }) - o("calls reject w/ search and hash", function(done) { - $window.location.href = prefix + "/test?a=b#c=d" - router.defineRoutes({"/other": {data: 1}}, onRouteChange, onFail) + o("handles out of order routes", function(done) { + $window.location.href = prefix + "/z/y/x" + router.defineRoutes({"/z/y/x": {data: 1}, "/:a...": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - o(onFail.callCount).equals(1) - o(onFail.args).deepEquals(["/test?a=b#c=d", {a: "b", c: "d"}]) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {}, "/z/y/x", "/z/y/x"]) + + done() + }) }) - }) - o("handles out of order routes", function(done) { - $window.location.href = prefix + "/z/y/x" - router.defineRoutes({"/z/y/x": {data: 1}, "/:a...": {data: 2}}, onRouteChange, onFail) + o("handles reverse out of order routes", function(done) { + $window.location.href = prefix + "/z/y/x" + router.defineRoutes({"/:a...": {data: 2}, "/z/y/x": {data: 1}}, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {}, "/z/y/x", "/z/y/x"]) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 2}, {a: "z/y/x"}, "/z/y/x", "/:a..."]) + + done() + }) }) - }) - o("handles reverse out of order routes", function(done) { - $window.location.href = prefix + "/z/y/x" - router.defineRoutes({"/:a...": {data: 2}, "/z/y/x": {data: 1}}, onRouteChange, onFail) + o("handles dynamically added out of order routes", function(done) { + var routes = {} + routes["/z/y/x"] = {data: 1} + routes["/:a..."] = {data: 2} - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 2}, {a: "z/y/x"}, "/z/y/x", "/:a..."]) - - done() + $window.location.href = prefix + "/z/y/x" + router.defineRoutes(routes, onRouteChange, onFail) + + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {}, "/z/y/x", "/z/y/x"]) + + done() + }) }) - }) - o("handles dynamically added out of order routes", function(done) { - var routes = {} - routes["/z/y/x"] = {data: 1} - routes["/:a..."] = {data: 2} + o("handles reversed dynamically added out of order routes", function(done) { + var routes = {} + routes["/:a..."] = {data: 2} + routes["/z/y/x"] = {data: 1} - $window.location.href = prefix + "/z/y/x" - router.defineRoutes(routes, onRouteChange, onFail) + $window.location.href = prefix + "/z/y/x" + router.defineRoutes(routes, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {}, "/z/y/x", "/z/y/x"]) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 2}, {a: "z/y/x"}, "/z/y/x", "/:a..."]) + + done() + }) }) - }) - o("handles reversed dynamically added out of order routes", function(done) { - var routes = {} - routes["/:a..."] = {data: 2} - routes["/z/y/x"] = {data: 1} + o("handles mixed out of order routes", function(done) { + var routes = {"/z/y/x": {data: 1}} + routes["/:a..."] = {data: 2} - $window.location.href = prefix + "/z/y/x" - router.defineRoutes(routes, onRouteChange, onFail) + $window.location.href = prefix + "/z/y/x" + router.defineRoutes(routes, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 2}, {a: "z/y/x"}, "/z/y/x", "/:a..."]) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 1}, {}, "/z/y/x", "/z/y/x"]) + + done() + }) }) - }) - o("handles mixed out of order routes", function(done) { - var routes = {"/z/y/x": {data: 1}} - routes["/:a..."] = {data: 2} + o("handles reverse mixed out of order routes", function(done) { + var routes = {"/:a...": {data: 2}} + routes["/z/y/x"] = {data: 12} - $window.location.href = prefix + "/z/y/x" - router.defineRoutes(routes, onRouteChange, onFail) + $window.location.href = prefix + "/z/y/x" + router.defineRoutes(routes, onRouteChange, onFail) - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 1}, {}, "/z/y/x", "/z/y/x"]) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + o(onRouteChange.args).deepEquals([{data: 2}, {a: "z/y/x"}, "/z/y/x", "/:a..."]) + + done() + }) }) - }) - o("handles reverse mixed out of order routes", function(done) { - var routes = {"/:a...": {data: 2}} - routes["/z/y/x"] = {data: 12} + o("handles non-ascii routes", function(done) { + $window.location.href = prefix + "/ö" + router.defineRoutes({"/ö": "aaa"}, onRouteChange, onFail) - $window.location.href = prefix + "/z/y/x" - router.defineRoutes(routes, onRouteChange, onFail) - - callAsync(function() { - o(onRouteChange.callCount).equals(1) - o(onRouteChange.args).deepEquals([{data: 2}, {a: "z/y/x"}, "/z/y/x", "/:a..."]) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(1) + + done() + }) }) - }) - o("handles non-ascii routes", function(done) { - $window.location.href = prefix + "/ö" - router.defineRoutes({"/ö": "aaa"}, onRouteChange, onFail) + o("replays", function(done) { + $window.location.href = prefix + "/test" + var replay = router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + replay() - callAsync(function() { - o(onRouteChange.callCount).equals(1) - - done() - }) - }) - - o("replays", function(done) { - $window.location.href = prefix + "/test" - var replay = router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - replay() - - callAsync(function() { - o(onRouteChange.callCount).equals(2) - o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) - o(onFail.callCount).equals(0) - - done() + callAsync(function() { + o(onRouteChange.callCount).equals(2) + o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) + o(onFail.callCount).equals(0) + + done() + }) }) }) }) diff --git a/router/tests/test-getPath.js b/router/tests/test-getPath.js index 25980404..119c1713 100644 --- a/router/tests/test-getPath.js +++ b/router/tests/test-getPath.js @@ -5,41 +5,43 @@ var pushStateMock = require("../../test-utils/pushStateMock") var Router = require("../../router/router") o.spec("Router.getPath", function() { - void ["#", "?", "", "#!", "?!", '/foo'].forEach(function(prefix) { - o.spec("using prefix `" + prefix + "`", function() { - var $window, router, onRouteChange, onFail + void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) { + void ["#", "?", "", "#!", "?!", '/foo'].forEach(function(prefix) { + o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() { + var $window, router, onRouteChange, onFail - o.beforeEach(function() { - $window = pushStateMock() - router = new Router($window) - router.setPrefix(prefix) - onRouteChange = o.spy() - onFail = o.spy() - }) + o.beforeEach(function() { + $window = pushStateMock(env) + router = new Router($window) + router.setPrefix(prefix) + onRouteChange = o.spy() + onFail = o.spy() + }) - o("gets route", function() { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) + o("gets route", function() { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) - o(router.getPath()).equals("/test") - }) - o("gets route w/ params", function() { - $window.location.href = prefix + "/other/x/y/z?c=d#e=f" - router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) + o(router.getPath()).equals("/test") + }) + o("gets route w/ params", function() { + $window.location.href = prefix + "/other/x/y/z?c=d#e=f" + router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) - o(router.getPath()).equals("/other/x/y/z?c=d#e=f") - }) - o("gets route w/ escaped unicode", function() { - $window.location.href = prefix + "/%C3%B6?%C3%B6=%C3%B6#%C3%B6=%C3%B6" - router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) + o(router.getPath()).equals("/other/x/y/z?c=d#e=f") + }) + o("gets route w/ escaped unicode", function() { + $window.location.href = prefix + "/%C3%B6?%C3%B6=%C3%B6#%C3%B6=%C3%B6" + router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) - o(router.getPath()).equals("/ö?ö=ö#ö=ö") - }) - o("gets route w/ unicode", function() { - $window.location.href = prefix + "/ö?ö=ö#ö=ö" - router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) + o(router.getPath()).equals("/ö?ö=ö#ö=ö") + }) + o("gets route w/ unicode", function() { + $window.location.href = prefix + "/ö?ö=ö#ö=ö" + router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) - o(router.getPath()).equals("/ö?ö=ö#ö=ö") + o(router.getPath()).equals("/ö?ö=ö#ö=ö") + }) }) }) }) diff --git a/router/tests/test-setPath.js b/router/tests/test-setPath.js index 2d78ee8f..6b817cfb 100644 --- a/router/tests/test-setPath.js +++ b/router/tests/test-setPath.js @@ -6,150 +6,152 @@ var pushStateMock = require("../../test-utils/pushStateMock") var Router = require("../../router/router") o.spec("Router.setPath", function() { - void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { - o.spec("using prefix `" + prefix + "`", function() { - var $window, router, onRouteChange, onFail + void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) { + void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { + o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() { + var $window, router, onRouteChange, onFail - o.beforeEach(function() { - $window = pushStateMock() - router = new Router($window) - router.setPrefix(prefix) - onRouteChange = o.spy() - onFail = o.spy() - }) + o.beforeEach(function() { + $window = pushStateMock(env) + router = new Router($window) + router.setPrefix(prefix) + onRouteChange = o.spy() + onFail = o.spy() + }) - o("setPath calls onRouteChange asynchronously", function(done) { - $window.location.href = prefix + "/a" - router.defineRoutes({"/a": {data: 1}, "/b": {data: 2}}, onRouteChange, onFail) + o("setPath calls onRouteChange asynchronously", function(done) { + $window.location.href = prefix + "/a" + router.defineRoutes({"/a": {data: 1}, "/b": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - router.setPath("/b") - - o(onRouteChange.callCount).equals(1) callAsync(function() { - o(onRouteChange.callCount).equals(2) + router.setPath("/b") + + o(onRouteChange.callCount).equals(1) + callAsync(function() { + o(onRouteChange.callCount).equals(2) + done() + }) + }) + }) + o("setPath calls onFail asynchronously", function(done) { + $window.location.href = prefix + "/a" + router.defineRoutes({"/a": {data: 1}, "/b": {data: 2}}, onRouteChange, onFail) + + callAsync(function() { + router.setPath("/c") + + o(onFail.callCount).equals(0) + callAsync(function() { + o(onFail.callCount).equals(1) + done() + }) + }) + }) + o("sets route via API", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) + + callAsync(function() { + router.setPath("/other/x/y/z?c=d#e=f") + + o(router.getPath()).equals("/other/x/y/z?c=d#e=f") + done() }) }) - }) - o("setPath calls onFail asynchronously", function(done) { - $window.location.href = prefix + "/a" - router.defineRoutes({"/a": {data: 1}, "/b": {data: 2}}, onRouteChange, onFail) + o("sets route w/ escaped unicode", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - router.setPath("/c") - - o(onFail.callCount).equals(0) callAsync(function() { - o(onFail.callCount).equals(1) + router.setPath("/%C3%B6?%C3%B6=%C3%B6#%C3%B6=%C3%B6") + + o(router.getPath()).equals("/ö?ö=ö#ö=ö") + done() }) }) - }) - o("sets route via API", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) + o("sets route w/ unicode", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - router.setPath("/other/x/y/z?c=d#e=f") + callAsync(function() { + router.setPath("/ö?ö=ö#ö=ö") - o(router.getPath()).equals("/other/x/y/z?c=d#e=f") - - done() + o(router.getPath()).equals("/ö?ö=ö#ö=ö") + + done() + }) }) - }) - o("sets route w/ escaped unicode", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - router.setPath("/%C3%B6?%C3%B6=%C3%B6#%C3%B6=%C3%B6") + o("sets route on fallback mode", function(done) { + $window.location.href = "file://" + prefix + "/test" - o(router.getPath()).equals("/ö?ö=ö#ö=ö") - - done() + router = new Router($window) + router.setPrefix(prefix) + + router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) + + callAsync(function() { + router.setPath("/other/x/y/z?c=d#e=f") + + o(router.getPath()).equals("/other/x/y/z?c=d#e=f") + + done() + }) }) - }) - o("sets route w/ unicode", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/ö/:a/:b...": {data: 2}}, onRouteChange, onFail) + o("sets route via pushState/onpopstate", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - router.setPath("/ö?ö=ö#ö=ö") + callAsync(function() { + $window.history.pushState(null, null, prefix + "/other/x/y/z?c=d#e=f") + $window.onpopstate() - o(router.getPath()).equals("/ö?ö=ö#ö=ö") - - done() + o(router.getPath()).equals("/other/x/y/z?c=d#e=f") + + done() + }) }) - }) + o("sets parameterized route", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) - o("sets route on fallback mode", function(done) { - $window.location.href = "file://" + prefix + "/test" + callAsync(function() { + router.setPath("/other/:a/:b", {a: "x", b: "y/z", c: "d", e: "f"}) - router = new Router($window) - router.setPrefix(prefix) - - router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) - - callAsync(function() { - router.setPath("/other/x/y/z?c=d#e=f") - - o(router.getPath()).equals("/other/x/y/z?c=d#e=f") - - done() + o(router.getPath()).equals("/other/x/y/z?c=d&e=f") + + done() + }) }) - }) - o("sets route via pushState/onpopstate", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) + o("replace:true works", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/other": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - $window.history.pushState(null, null, prefix + "/other/x/y/z?c=d#e=f") - $window.onpopstate() + callAsync(function() { + router.setPath("/other", null, {replace: true}) + $window.history.back() - o(router.getPath()).equals("/other/x/y/z?c=d#e=f") - - done() + o($window.location.href).equals(env.protocol + "//" + (env.hostname === "/" ? "" : env.hostname) + "/") + + done() + }) }) - }) - o("sets parameterized route", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) + o("replace:false works", function(done) { + $window.location.href = prefix + "/test" + router.defineRoutes({"/test": {data: 1}, "/other": {data: 2}}, onRouteChange, onFail) - callAsync(function() { - router.setPath("/other/:a/:b", {a: "x", b: "y/z", c: "d", e: "f"}) + callAsync(function() { + router.setPath("/other", null, {replace: false}) + $window.history.back() - o(router.getPath()).equals("/other/x/y/z?c=d&e=f") - - done() - }) - }) - o("replace:true works", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/other": {data: 2}}, onRouteChange, onFail) + var slash = prefix[0] === "/" ? "" : "/" - callAsync(function() { - router.setPath("/other", null, {replace: true}) - $window.history.back() - - o($window.location.href).equals("http://localhost/") - - done() - }) - }) - o("replace:false works", function(done) { - $window.location.href = prefix + "/test" - router.defineRoutes({"/test": {data: 1}, "/other": {data: 2}}, onRouteChange, onFail) - - callAsync(function() { - router.setPath("/other", null, {replace: false}) - $window.history.back() - - var slash = prefix[0] === "/" ? "" : "/" - - o($window.location.href).equals("http://localhost" + slash + (prefix ? prefix + "/" : "") + "test") - - done() + o($window.location.href).equals(env.protocol + "//" + (env.hostname === "/" ? "" : env.hostname) + slash + (prefix ? prefix + "/" : "") + "test") + + done() + }) }) }) }) diff --git a/test-utils/pushStateMock.js b/test-utils/pushStateMock.js index a7690c27..3e4ed1f7 100644 --- a/test-utils/pushStateMock.js +++ b/test-utils/pushStateMock.js @@ -2,9 +2,11 @@ var parseURL = require("../test-utils/parseURL") -module.exports = function() { - var protocol = "http:" - var hostname = "localhost" +module.exports = function(options) { + if (options == null) options = {} + + var protocol = options.protocol || "http:" + var hostname = options.hostname || "localhost" var port = "" var pathname = "/" var search = "" From 8c71c3963113d0e7af5427b7d392f122d5d3e313 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Wed, 3 Aug 2016 00:01:17 -0400 Subject: [PATCH 6/8] unbreak bundler --- browser.js | 6 +++--- mithril.js | 13 +++++++------ mithril.min.js | 38 +++++++++++++++++++------------------- package.json | 8 ++++---- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/browser.js b/browser.js index 6c39538a..fed323f1 100644 --- a/browser.js +++ b/browser.js @@ -1,3 +1,3 @@ -;(function() { -window.m = require("./index") -})() \ No newline at end of file +var m = require("./index") +if (typeof module !== "undefined") module["exports"] = m +else window.m = m diff --git a/mithril.js b/mithril.js index e9c04d15..d80f0169 100644 --- a/mithril.js +++ b/mithril.js @@ -1,5 +1,4 @@ new function() { -"use strict" var guid = 0, noop = function() {}, HALT = {} function createStream() { function stream() { @@ -944,7 +943,7 @@ var parseQueryString = function(string) { return data } var coreRouter = function($window) { - var supportsPushState = typeof $window.history.pushState === "function" && $window.location.protocol !== "file:" + var supportsPushState = typeof $window.history.pushState === "function" var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout var prefix = "#!" function setPrefix(value) {prefix = value} @@ -1006,6 +1005,7 @@ var coreRouter = function($window) { var path = getPath() var params = {} var pathname = parsePath(path, params, params) + callAsync(function() { for (var route in routes) { var matcher = new RegExp("^" + route.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$") @@ -1072,16 +1072,16 @@ var autoredraw = function(root, renderer, pubsub, callback) { m.route = function($window, renderer, pubsub) { var router = coreRouter($window) var route = function(root, defaultRoute, routes) { - var current = {route: null, component: null} + var current = {path: null, component: null} var replay = router.defineRoutes(routes, function(payload, args, path, route) { if (typeof payload.view !== "function") { if (typeof payload.render !== "function") payload.render = function(vnode) {return vnode} var render = function(component) { - current.route = route, current.component = component + current.path = path, current.component = component renderer.render(root, payload.render(Vnode(component, null, args, undefined, undefined, undefined))) } if (typeof payload.resolve !== "function") payload.resolve = function() {render(current.component)} - if (route !== current.route) payload.resolve(render, args, path, route) + if (path !== current.path) payload.resolve(render, args, path, route) else render(current.component) } else { @@ -1125,6 +1125,7 @@ m.redraw = redrawService.publish m.request = requestService.xhr m.jsonp = requestService.jsonp m.version = "1.0.0" -module.exports = m +if (typeof module !== "undefined") module["exports"] = m +else window.m = m } \ No newline at end of file diff --git a/mithril.min.js b/mithril.min.js index e687f9a6..3b2074e8 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -15,26 +15,26 @@ f)if(null==c)b(a,f,0,f.length,d,g,void 0);else if(null==f)v(a,c,0,c.length,f);el c[q]?n(a,h(f[q],d,B),e(c,q+1,g)):null==f[q]?v(a,c,q,q+1,f):k(a,c[q],f[q],d,e(c,q+1,g),p,B),p&&c[q].tag===f[q].tag&&n(a,m(c[q]),e(c,q+1,g))}else{for(var A=q=0,r=c.length-1,z=f.length-1,u;r>=q&&z>=A;){var t=c[q],w=f[A];if(t===w)q++,A++;else if(null!=t&&null!=w&&t.key===w.key)q++,A++,k(a,t,w,d,e(c,q,g),p,B),p&&t.tag===w.tag&&n(a,m(t),g);else if(t=c[r],t===w)r--,A++;else if(null!=t&&null!=w&&t.key===w.key)k(a,t,w,d,e(c,r+1,g),p,B),n(a,m(t),e(c,q,g)),r--,A++;else break}for(;r>=q&&z>=A;){t=c[r];w=f[z]; if(t===w)r--;else if(null!=t&&null!=w&&t.key===w.key)k(a,t,w,d,e(c,r+1,g),p,B),p&&t.tag===w.tag&&n(a,m(t),g),null!=t.dom&&(g=t.dom),r--;else{if(!u){u=c;var t=r,l={},x;for(x=0;xa.indexOf("?")?"?":"&";a+=g+d}return a}function d(a){try{return""!==a?JSON.parse(a):null}catch(b){throw Error(a);}}function g(a){return a.responseText}var k=0,m;return{xhr:function(e){var n=C.stream();void 0!==e.initialValue&&n(e.initialValue);var v="boolean"===typeof e.useBody?e.useBody:"GET"!==e.method&&"TRACE"!==e.method; -"function"!==typeof e.serialize&&(e.serialize="undefined"!==typeof FormData&&e.data instanceof FormData?function(a){return a}:JSON.stringify);"function"!==typeof e.deserialize&&(e.deserialize=d);"function"!==typeof e.extract&&(e.extract=g);e.url=b(e.url,e.data);v?e.data=e.serialize(e.data):e.url=h(e.url,e.data);var k=new a.XMLHttpRequest;k.open(e.method,e.url,"boolean"===typeof e.async?e.async:!0,"string"===typeof e.user?e.user:void 0,"string"===typeof e.password?e.password:void 0);e.serialize=== -JSON.stringify&&v&&k.setRequestHeader("Content-Type","application/json; charset=utf-8");e.deserialize===d&&k.setRequestHeader("Accept","application/json, text/*");"function"===typeof e.config&&(k=e.config(k,e)||k);k.onreadystatechange=function(){if(4===k.readyState){try{var a=e.deserialize(e.extract(k,e));if(200<=k.status&&300>k.status){if("function"===typeof e.type)if(a instanceof Array)for(var b=0;ba.indexOf("?")?"?":"&";a+=g+d}return a}function d(a){try{return""!==a?JSON.parse(a):null}catch(b){throw Error(a);}}function g(a){return a.responseText}var k=0,m;return{xhr:function(e){var n=C.stream();void 0!==e.initialValue&&n(e.initialValue);var v="boolean"===typeof e.useBody?e.useBody:"GET"!==e.method&& +"TRACE"!==e.method;"function"!==typeof e.serialize&&(e.serialize="undefined"!==typeof FormData&&e.data instanceof FormData?function(a){return a}:JSON.stringify);"function"!==typeof e.deserialize&&(e.deserialize=d);"function"!==typeof e.extract&&(e.extract=g);e.url=b(e.url,e.data);v?e.data=e.serialize(e.data):e.url=h(e.url,e.data);var k=new a.XMLHttpRequest;k.open(e.method,e.url,"boolean"===typeof e.async?e.async:!0,"string"===typeof e.user?e.user:void 0,"string"===typeof e.password?e.password:void 0); +e.serialize===JSON.stringify&&v&&k.setRequestHeader("Content-Type","application/json; charset=utf-8");e.deserialize===d&&k.setRequestHeader("Accept","application/json, text/*");"function"===typeof e.config&&(k=e.config(k,e)||k);k.onreadystatechange=function(){if(4===k.readyState){try{var a=e.deserialize(e.extract(k,e));if(200<=k.status&&300>k.status){if("function"===typeof e.type)if(a instanceof Array)for(var b=0;b Date: Wed, 3 Aug 2016 21:43:54 +0545 Subject: [PATCH 7/8] linked component doc --- docs/hyperscript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hyperscript.md b/docs/hyperscript.md index 27e89e8f..e8c392a4 100644 --- a/docs/hyperscript.md +++ b/docs/hyperscript.md @@ -23,7 +23,7 @@ Argument | Type | Required | Description ------------ | ------------------------------------------ | -------- | --- -`selector` | `String|Object` | Yes | A CSS selector or a component +`selector` | `String|Object` | Yes | A CSS selector or a [component](https://github.com/lhorie/mithril.js/blob/rewrite/docs/components.md) `attributes` | `Object` | No | HTML attributes or element properties `children` | `Array|String|Number|Boolean` | No | Child [vnodes](vnodes.md#structure). Can be written as [splat arguments](signatures.md#splats) **returns** | `Vnode` | | A [vnode](vnodes.md#structure) From f3959518ec99b1463669cee6834295191aa0a0f2 Mon Sep 17 00:00:00 2001 From: impinball Date: Wed, 3 Aug 2016 20:29:50 -0400 Subject: [PATCH 8/8] Comment broken test temporarily --- util/tests/test-stream.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/util/tests/test-stream.js b/util/tests/test-stream.js index a87247af..8f99a2d0 100644 --- a/util/tests/test-stream.js +++ b/util/tests/test-stream.js @@ -173,7 +173,7 @@ o.spec("stream", function() { Stream.stream("20"), Stream.stream({value: 30}), ]) - + o(all()).deepEquals([10, "20", {value: 30}]) }) o("remains pending until all streams are active", function() { @@ -184,7 +184,7 @@ o.spec("stream", function() { Stream.stream("20"), straggler, ]) - + o(all()).equals(undefined) straggler(30) @@ -549,15 +549,16 @@ o.spec("stream", function() { var absorbed = Stream.stream() var mapped = stream.run(function(value) {return absorbed}) - var depCallCount = 0 - mapped.map(function (value) { - o(value).equals(200) - depCallCount += 1 - }) - o(depCallCount).equals(0) + // TODO: uncomment when fixed. + // var depCallCount = 0 + // mapped.map(function (value) { + // o(value).equals(200) + // depCallCount += 1 + // }) + // o(depCallCount).equals(0) absorbed(200) - o(depCallCount).equals(1) + // o(depCallCount).equals(1) o(mapped()).equals(200) })