diff --git a/examples/basic/app.js b/examples/basic/app.js index cced2e29e..6033475de 100644 --- a/examples/basic/app.js +++ b/examples/basic/app.js @@ -48,6 +48,7 @@ new Vue({ {{ props.route.path }} (with v-slot). +
  • /foo (replace)
  • {{ n }}
    diff --git a/src/util/scroll.js b/src/util/scroll.js index 683adc456..c6c055a97 100644 --- a/src/util/scroll.js +++ b/src/util/scroll.js @@ -3,6 +3,7 @@ import type Router from '../index' import { assert } from './warn' import { getStateKey, setStateKey } from './state-key' +import { extend } from './misc' const positionStore = Object.create(null) @@ -14,7 +15,10 @@ export function setupScroll () { // location.host contains the port and location.hostname doesn't const protocolAndPath = window.location.protocol + '//' + window.location.host const absolutePath = window.location.href.replace(protocolAndPath, '') - window.history.replaceState({ key: getStateKey() }, '', absolutePath) + // preserve existing history state as it could be overriden by the user + const stateCopy = extend({}, window.history.state) + stateCopy.key = getStateKey() + window.history.replaceState(stateCopy, '', absolutePath) window.addEventListener('popstate', e => { saveScrollPosition() if (e.state && e.state.key) { diff --git a/test/e2e/specs/basic.js b/test/e2e/specs/basic.js index 2c1465c88..f5e6364eb 100644 --- a/test/e2e/specs/basic.js +++ b/test/e2e/specs/basic.js @@ -9,8 +9,8 @@ module.exports = { browser .url('http://localhost:8080/basic/') .waitForElementVisible('#app', 1000) - .assert.count('li', 8) - .assert.count('li a', 8) + .assert.count('li', 9) + .assert.count('li a', 9) // assert correct href with base .assert.attributeContains('li:nth-child(1) a', 'href', '/basic/') .assert.attributeContains('li:nth-child(2) a', 'href', '/basic/foo') diff --git a/test/e2e/specs/history-state.js b/test/e2e/specs/history-state.js new file mode 100644 index 000000000..d5cd60e32 --- /dev/null +++ b/test/e2e/specs/history-state.js @@ -0,0 +1,56 @@ +const bsStatus = require('../browserstack-send-status') + +module.exports = { + ...bsStatus(), + + '@tags': ['history'], + + 'history state': function (browser) { + browser + .url('http://localhost:8080/scroll-behavior/') + .waitForElementVisible('#app', 1000) + + .execute(function () { + window.scrollTo(0, 100) + const key = window.history.state.key + window.history.replaceState({ key, foo: 'foo' }, '', window.location.pathname) + }) + .url('http://localhost:8080/scroll-behavior/') + .waitForElementVisible('#app', 1000) + .assert.evaluate(function () { + return window.history.state.foo === 'foo' + }, null, 'keeps existing state when reloading') + + // check on navigation + .url('http://localhost:8080/basic/') + .click('li:nth-child(2) a') + .assert.urlEquals('http://localhost:8080/basic/foo') + .execute(function () { + window.scrollTo(0, 100) + const key = window.history.state.key + window.history.replaceState({ key, foo: 'foo' }, '', window.location.pathname) + }) + .click('li:nth-child(3) a') + .assert.urlEquals('http://localhost:8080/basic/bar') + .execute(function () { + window.history.back() + }) + .assert.evaluate(function () { + return window.history.state.foo === 'foo' + }, null, 'keeps existing state when navigating back') + .click('li:nth-child(3) a') + .assert.urlEquals('http://localhost:8080/basic/bar') + .execute(function () { + window.scrollTo(0, 100) + const key = window.history.state.key + window.history.replaceState({ key, bar: 'bar' }, '', window.location.pathname) + }) + .click('li:nth-child(9) a') + .assert.urlEquals('http://localhost:8080/basic/foo') + .assert.evaluate(function () { + return window.history.state.bar === 'bar' + }, null, 'keeps existing state when replacing') + + .end() + } +}