beforeRouteLeave and mixin - vue.js

I am using Vue.js for a CRUD system, tracking a number of different domain classes, such as Customer, Product, etc. I have a validation mixin which I use in each editor component (e.g, CustomerDetail, ProductDetail). Because I would like common behaviour when a user moves away from the page without saving, I'd like to be able to have a method in my validation mixin which I can call in 'beforeRouteLeave'. The method I have come up with is this:
checkOnLeave(obj,message,confirmText="Leave",cancelText="Continue Editing",next){
if (this.isDirty(obj)) { //isDirty checks whether object has been changed
bootbox.confirm({
message: message,
buttons: {
confirm: {
label: confirmText,
},
cancel: {
label: cancelText,
}
},
callback: function (result) {
if (result) {
next();
} else {
next(false);
}
}
});
} else {
next();
}
}
When I try to use this, though, it doesn't have any idea what to do with 'next'. Clearly this is something from vue-router which it is unaware of. So how can I make my mixin vue-router aware so that I can use this?

Red herring alert. It actually works fine as is - it must have been a delay in compiling which caused the problem before (it happens from time to time with 'npm run dev', the compile occasionally doesn't kick in).

Related

Is there a way to show a bootstrap-vue $toast feedback in beforeRouteEnter?

I have a component which loads a single user, so I use a vue-router guard to load data and in case of error redirect back to the users list component.
Is there a way to show a vue-bootstrap $toast? Usually I access $toast from this component, but obviously this does not exists yet in beforeRouteEnter.
I know I could manage in other ways (show the error in the page and use created(), or use vuex to keep the error and show it in the next page), but since I am using $toast everywhere I would like to keep consistency.
I have no ideas... if only I could access the root component I would have access to $toast but I can't see a way.
// userComponent
// ...
beforeRouteEnter(to, from, next) {
Promise.all([store.dispatch("users/fetchOne", { id: to.params.id } )])
.then(next)
.catch(() => {
// this.$root.$bvToast.toast("ERROR!!!", { variant: "danger" }); // can't do this :(
next("/users");
});
},
//...
You don't have access to this inside beforeRouteEnter. So you can do below :
next(vm => {
vm.$root.$bvToast.toast(...)
})

How to perfectly isolate and clear environments between each test?

I'm trying to connect to SoundCloud using CasperJS. What is interesting is once you signed in and rerun the login feature later, the previous login is still active. Before going any further, here is the code:
casper.thenOpen('https://soundcloud.com/', function() {
casper.click('.header__login');
popup = /soundcloud\.com\/connect/;
casper.waitForPopup(popup, function() {
casper.withPopup(popup, function() {
selectors = {
'#username': username,
'#password': password
};
casper.fillSelectors('form.log-in', selectors, false);
casper.click('#authorize');
});
});
});
If you run this code at least twice, you should see the following error appears:
CasperError: Cannot dispatch mousedown event on nonexistent selector: .header__login
If you analyse the logs you will see that the second time, you were redirected to https://soundcloud.com/stream meaning that you were already logged in.
I did some research to clear environments between each test but it seems that the following lines don't solve the problem.
phantom.clearCookies()
casper.clear()
localStorage.clear()
sessionStorage.clear()
Technically, I'm really interested about understanding what is happening here. Maybe SoundCloud built a system to also store some variables server-side. In this case, I would have to log out before login. But my question is how can I perfectly isolate and clear everything between each test? Does someone know how to make the environment unsigned between each test?
To clear server-side session cache, calling: phantom.clearCookies(); did the trick for me. This cleared my session between test files.
Example here:
casper.test.begin("Test", {
test: function(test) {
casper.start(
"http://example.com",
function() {
... //Some testing here
}
);
casper.run(function() {
test.done();
});
},
tearDown: function(test) {
phantom.clearCookies();
}
});
If you're still having issues, check the way you are executing your tests.
Where did you call casper.clear() ?
I think you have to call it immediately after you have opened a page like:
casper.start('http://www.google.fr/', function() {
this.clear(); // javascript execution in this page has been stopped
//rest of code
});
From the doc: Clears the current page execution environment context. Useful to avoid having previously loaded DOM contents being still active.

Testing ember nested routes fails

I'm using karma with qUnit (after following this tutorial) to test my Ember application. It's mostly going well, however I've run into a problem that doesn't make sense.
Given the 2 following tests:
test('can get to products', function() {
visit('/products/')
.then(function() {
ok(find('*'));
});
});
test('can get to catalogues', function() {
visit('/products/catalogues')
.then(function() {
ok(find('*'));
});
});
The first will run fine. The test runner gets to /products and finds something.
However, the second test returns an error in the console:
Error: Assertion Failed: You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run
I turned on transition logs, and the test runner is visiting products.catalogues.index before throwing the error.
Any ideas with this? Or is it simply a bug inside ember's testing tools?
Both are valid routes defined inside the router...
The last part of the error holds the key to how to fix this problem. You have to make sure that any code that make async calls is wrapped in Ember.run. This includes things as simple as the create and set methods.
If you have something like
App.ProductsRoute = Ember.Route.extend({
model: function() {
return [
Ember.Object.create({title: "product1"}),
Ember.Object.create({title: "product2"})
]
}
});
refactor it to
App.ProductsRoute = Ember.Route.extend({
model: function() {
return [
Ember.run( Ember.Object, "create", {title: "product1"} ),
Ember.run( Ember.Object, "create", {title: "product2"} )
]
}
});
or
App.ProductsRoute = Ember.Route.extend({
model: function() {
return Ember.run(function() {
return [
Ember.Object.create({title: "product1"}),
Ember.Object.create({title: "product2"})
]
});
}
});
If you posted your /products code it would be easier to give a more specific answer.

Dojo aspect not working for ready

I want to have an aspect which does some task after dojo ready is called. The code is given below,
aspect.after(dojo, "ready", function(deferred) {
loader.hide();
});
The loader.hide() is not called after the page ready function is called. But the above code is working good with xhr instead of ready. Will aspects work for dojo/ready ? Am I missing something here?
Thanks in advance for your help
===============================================
After few trial and errors, got this working by using
dojo.ready(function() {
});
Wanted to know why the aspect is not working with
require(["dojo/ready"], function(ready) {
ready(function() {
});
});
Try using dojo/domReady too. You are not allowed to map domReady to any variable, so that is why it has to appear at the end:
require(["dojo/ready","dojo/domReady!"],function(ready) {
ready(function() {
// Your code
});
});

ExtJS4 MVC Architecture walkthrough on sencha doc giving me errors

I'm following the ExtJS4.0 MVC Application Architecture walk through and modifying it to my own project as I go to make sure I get things right. So far it's working perfectly. I've just completed the 'Defining a View' section and I'm about to start the 'Controlling the grid' section. Before I do, I want to remove the console.log code as I don't want or need it for my own project. I find I can replace it with an alert message but can't remove it all together without generating an error against ext-all-debug.js.
Here's my functioning code on the controller and the error it's generating after I remove the consol.log function. In the example doc, it's AM.controllers.list.
Ext.define('ChatAgent.controller.queues', {
extend: 'Ext.app.Controller'
, views: [
'queue.list'
]
, init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});
}
, onPanelRendered: function() {
console.log('The panel was rendered');
}
});
The error it generates is:
'fireFn' is null or not an object
All I've removed is:
onPanelRendered: function() {
console.log('The panel was rendered');
}
So why the error???
You need to get rid of the event listener as well. When the render event fires it is trying to call onPanelRendered which doesn't exist anymore.
If you aren't listening for any events, you don't even need to have that entire this.control block. Comment this out and see what happens.
this.control({
'viewport > panel': {
render: this.onPanelRendered
}
});