Skip to content

Commit 92a7a30

Browse files
committed
Merge branch 'fix-4-anchor-link' into develop
2 parents 42391c1 + 2da40ad commit 92a7a30

File tree

9 files changed

+196
-15
lines changed

9 files changed

+196
-15
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ group :development, :test do
2626
gem 'puma'
2727
gem 'simplecov', require: false, group: :test
2828
gem 'byebug'
29-
# gem 'pry-byebug'
29+
gem 'pry-byebug'
3030
gem 'webmock'
3131
gem 'webdrivers', '~> 4.1'
3232
end

Gemfile.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ GEM
8080
cells (>= 4.1.6, < 5.0.0)
8181
childprocess (0.9.0)
8282
ffi (~> 1.0, >= 1.0.11)
83+
coderay (1.1.2)
8384
concurrent-ruby (1.1.5)
8485
crack (0.4.3)
8586
safe_yaml (~> 1.0.0)
@@ -125,6 +126,12 @@ GEM
125126
nokogiri (1.10.5)
126127
mini_portile2 (~> 2.4.0)
127128
pipetree (0.1.1)
129+
pry (0.12.2)
130+
coderay (~> 1.1.0)
131+
method_source (~> 0.9.0)
132+
pry-byebug (3.8.0)
133+
byebug (~> 11.0)
134+
pry (~> 0.10)
128135
public_suffix (3.0.3)
129136
puma (4.3.1)
130137
nio4r (~> 2.0)
@@ -253,6 +260,7 @@ DEPENDENCIES
253260
cells-rails
254261
generator_spec
255262
matestack-ui-core!
263+
pry-byebug
256264
puma
257265
rspec-rails (~> 3.8)
258266
selenium-webdriver

app/concepts/matestack/ui/core/app/app.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Vue from 'vue/dist/vue.esm'
2-
import axios from 'axios'
32
import VRuntimeTemplate from "v-runtime-template"
43
import Vuex from 'vuex'
4+
import isNavigatingToAnotherPage from "./location"
55

66
const componentDef = {
77
props: ['appConfig', 'params'],
@@ -12,9 +12,10 @@ const componentDef = {
1212
asyncTemplate: state => state.pageTemplate,
1313
}),
1414
mounted: function(){
15-
const self = this;
16-
window.onpopstate = function(event) {
17-
self.$store.dispatch("navigateTo", {url: document.location.pathname, backwards: true} );
15+
window.onpopstate = (event) => {
16+
if (isNavigatingToAnotherPage(document.location, event)) {
17+
this.$store.dispatch("navigateTo", {url: document.location.pathname, backwards: true} );
18+
};
1819
}
1920
},
2021
components: {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const isNavigatingToAnotherPage = function(currentLocation, popstateEvent) {
2+
const targetLocation = popstateEvent.target.location;
3+
4+
// omits hash by design
5+
return currentLocation.pathname !== targetLocation.pathname ||
6+
currentLocation.origin !== targetLocation.origin ||
7+
currentLocation.search !== targetLocation.search
8+
}
9+
10+
export default isNavigatingToAnotherPage

spec/spec_helper.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
Dir[File.join File.dirname(__FILE__), 'support', '**', '*.rb'].each { |f| require f }
3838

39+
require 'pry'
40+
3941
RSpec.configure do |config|
4042
# config.include Capybara::DSL
4143
# rspec-expectations config goes here. You can use an alternate

spec/usage/components/link_spec.rb

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,140 @@ def response
179179
expect(stripped(static_output)).to ( include(stripped(expected_static_output)) )
180180
end
181181

182+
it "behaves correctly with anchor links (no reload, retain anchor)" do
183+
class ExamplePage < Matestack::Ui::Page
184+
def response
185+
components {
186+
link path: "#someanchor", text: "go to anchor", id: "my-link"
187+
188+
br times: 200
189+
190+
div id: "someanchor" do
191+
plain "hello!"
192+
end
193+
194+
div id: "my-div" do
195+
plain "#{DateTime.now.strftime('%Q')}"
196+
end
197+
}
198+
end
199+
end
200+
201+
visit "/example"
202+
203+
element = page.find("#my-div")
204+
before_content = element.text
205+
206+
# don't you rerender on me!
207+
expect(ExamplePage).not_to receive(:new)
208+
209+
page.click_link("my-link")
210+
211+
# if the page reloaded we'd have different content here but as we don't want reloads
212+
# we want the same
213+
expect(page).to have_css("#my-div", text: before_content)
214+
expect(page.current_url).to end_with("#someanchor")
215+
end
216+
217+
describe "with an App" do
218+
219+
after :each do
220+
class ExamplePage < Matestack::Ui::Page
221+
# as the test suites work with redefining classes and this
222+
# hack here was used to set a specific app easily,
223+
# we need to "restore" previous state
224+
def set_app_class
225+
super
226+
end
227+
end
228+
end
229+
230+
it "behaves correctly with anchor links (no reload, retain anchor) even inside an app" do
231+
class Apps::MyTestApp < Matestack::Ui::App
232+
def response
233+
components {
234+
page_content
235+
}
236+
end
237+
end
238+
239+
class ExamplePage < Matestack::Ui::Page
240+
def response
241+
components {
242+
link path: "#someanchor", text: "go to anchor", id: "my-link"
243+
244+
br times: 200
245+
246+
div id: "someanchor" do
247+
plain "hello!"
248+
end
249+
250+
div id: "my-div" do
251+
plain "#{DateTime.now.strftime('%Q')}"
252+
end
253+
}
254+
end
255+
256+
# Hacky/instable but easy way to set my custom App for this page
257+
def set_app_class
258+
@app_class = Apps::MyTestApp
259+
end
260+
end
261+
262+
visit "/example"
263+
264+
element = page.find("#my-div")
265+
before_content = element.text
266+
267+
# don't you rerender on me!
268+
expect(ExamplePage).not_to receive(:new)
269+
270+
page.click_link("my-link")
271+
272+
# if the page reloaded we'd have different content here but as we don't want reloads
273+
# we want the same
274+
expect(page).to have_css("#my-div", text: before_content)
275+
expect(page.current_url).to end_with("#someanchor")
276+
end
277+
278+
it "just changing the search string will still reload the page" do
279+
class Apps::MyTestApp < Matestack::Ui::App
280+
def response
281+
components {
282+
page_content
283+
}
284+
end
285+
end
286+
287+
class ExamplePage < Matestack::Ui::Page
288+
def response
289+
components {
290+
link path: "?a=true", text: "go to anchor", id: "my-link"
291+
292+
br times: 200
293+
294+
div id: "my-div" do
295+
plain "#{DateTime.now.strftime('%Q')}"
296+
end
297+
}
298+
end
299+
300+
# Hacky/instable but easy way to set my custom App for this page
301+
def set_app_class
302+
@app_class = Apps::MyTestApp
303+
end
304+
end
305+
306+
visit "/example"
307+
308+
element = page.find("#my-div")
309+
before_content = element.text
310+
311+
page.click_link("my-link")
312+
313+
expect(page).to have_css("#my-div")
314+
expect(page).to have_no_css("#my-div", text: before_content)
315+
expect(page.current_url).to end_with("?a=true")
316+
end
317+
end
182318
end

vendor/assets/javascripts/dist/matestack-ui-core.js

Lines changed: 32 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/assets/javascripts/dist/matestack-ui-core.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/assets/javascripts/matestack-ui-core.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)