Abort upload with UIkits Upload Component? - javascript

The title says it all. How can I abort the upload with UIKits Upload Component?
I'm trying to abort the upload in the beforeAll callback but I can't seem to get it to work.
UIkit.upload('.js-upload', {
url: '',
multiple: false,
mime: 'audio/*',
allow: '*.mp3',
beforeAll: function () {
return false; // <--- Why does it not return/abort?
});
}
});

Have a look at the source code. The return value from beforeAll isn't used.
The best option I see to abort the request is to get hang of the XMLHttpRequest object and call abort() on it:
UIkit.upload(".js-upload", {
// ...
loadStart: function (e) {
e.target.abort();
},
abort: function (e) {
// clean up after abort
}
// ...
});

Related

Jasmine AJAX spy failure

Ok these tests were passing a few bit ago. I have made no changes to which version of jasmine I'm using but... can anyone see obvious syntax errors here?
describe("ajax return", function() {
beforeEach(function() {
ajaxSpy = spyOn($, "ajax")
})
describe("on success", function() {
beforeEach(async function() {
ajaxSpy.and.callFake(function(e) {
e.success({"success":true, "remove":{1:"test"},"assign_prestock":"test2"})
})
await catalogDOM.syncAvailability(null)
})
it("should call", function() {
...
})
})
})
When running, I'm getting this error:
1_catalogDOM_spec.js:518 Uncaught (in promise) TypeError: e.success is not a function
UPDATE code for catalogDOM.syncAvailability
catalogDOM.syncAvailability: function(item_name_id) {
return new Promise(function(resolve, reject) {
$.ajax({
type:"POST",
url: "/retrieve-options-availability",
dataType:"json",
contentType:"application/json",
data: JSON.stringify(params)
})
.done(function(response, status_string, jqxhr) {
if (response["success"] == true) {
resolve()
} else {
reject(response["message"])
}
})
.fail(function(jqxhr, error_string, exception_object){
reject("Error loading availability. Refresh & try again or contact us if this persists.")
})
}
Try doing this to debug:
ajaxSpy.and.callFake(function(e) {
// add console.log here !!
console.log('e: ', e);
e.success({"success":true, "remove":{1:"test"},"assign_prestock":"test2"})
})
Apparently, .success is not a function anymore and you can look at the value of e there. I am thinking e is the argument for what's provided in $.ajax(/* e is here */);.
Looking at the documentation here: https://api.jquery.com/jquery.ajax/, I think we need to mock a done function.
Try this:
ajaxSpy.and.callFake(function (e) {
return {
done: function () {
return {
"success":true,
"remove":{1:"test"},
"assign_prestock":"test2",
// edit - create a fail function that's empty here
fail: function() {
// leave empty
}
};
}
};
});
Edit
Instead of doing a spy on ajaxSpy, try spying on catalogDOM directly. Something like this:
spyOn(catalogDOM, 'syncAvailability').and.resolveTo({/* Mock value here */ });
Or
spyOn(catalogDOM, 'syncAvailability').and.returnValue(Promise.resolve({ /* Mock value here */ });
And then you don't have to await it.

Electron js win.webContents.print callback function doesn't work?

I am working on an application with Electron js and Vue js. I need to print the Synchronous request sent by Renderer with the print function. According to the result, I have to transmit the result to the renderer over the backend. Therefore, I use the callback function of the print function. But when I use this function, the print method does not work. I shared the codes below. Could there be an error?
ipcMain.on("set-print", function(event, arg) {
let options = {
silent: true,
deviceName: arg,
};
win.webContents.print(options, function(success) {
event.returnValue = success;
});
});
Try Promise function
win.webContents.print(options)
.then((success)=>{
console.log(success);
})
.catch((err)=>{
console.log(err)
});
https://www.electronjs.org/docs/api/webview-tag#webviewprintoptions

Waiting for Several CSV files to load with Papaparse

I have been trying to load several CSV files before running the code on my page as it uses the data from the CSV files. I have used PAPAPARSE.js as a library to help me with this and I have come up with the following solution.
function loadData(){
console.log("Loading Data!")
loadNodeData();
loadEdgeData();
loadHeadendData();
setup();
}
function loadNodeData(){
Papa.parse("Data/CSV1.csv", {
download: true,
step: function(row) {
NodeData.push(row.data)
},
complete: function() {
console.log("Loaded Node Data!");
load1 = true;
}
});
}
function loadEdgeData(){
Papa.parse("Data/CSV2.csv", {
download: true,
step: function(row) {
EdgeData.push(row.data)
},
complete: function() {
console.log("Loaded Edge Data!");
load2 = true;
}
});
}
function loadHeadendData(){
Papa.parse("Data/CSV3.csv", {
download: true,
step: function(row) {
HeadendArr.push(row.data)
},
complete: function() {
console.log("Loaded Headend Data!");
load3=true;
}
});
}
function setup() {
intervalID = setInterval(isDataLoaded,100)
}
function isDataLoaded(){
//Attempt to setup the page, this will only work if the data iss loaded.
if(load1 && load2 && load3){
console.log("LOADED");
_setupSearchOptions();
}
}
I have this following setup, however i don't know if this is the best way to go about doing something like this. the loadData triggers on page load
<head onload="loadData()">
Is this the correct way to make the program flow?
A more modern approach is to use promises.
You can cut down the code repetition by creating one function that passes in the url and step array to push to and wrap the Papa.parse() call in a promise that gets resolved in the complete callback.
Then use Promise.all() to call _setupSearchOptions() after all three promises resolve
Something like:
function parseCsv(url, stepArr){
return new Promise(function(resolve, reject){
Papa.parse(url, {
download:true,
step: function(row){
stepArr.push(row.data)
},
complete: resolve
});
});
}
function loadData(){
const nodeReq = parseCsv("Data/CSV1.csv", NodeData);
const edgeReq = parseCsv("Data/CSV2.csv", EdgeData);
const headReq = parseCsv("Data/CSV3.csv", HeadendArr);
Promise.all([ nodeReq, edgeReq, headReq]).then(_setupSearchOptions);
}
Note that no error handling has been considered here. Presumably the Papa.parse api also has some fail or error callback that you would use to call the reject() and use a catch() with Promise.all() to handle that failure

Service Worker Detect Cache Completed

My PWA has a large data payload. I want to display a 'Please wait...' load page and wait until all caching is complete before launching the full app. Therefore, I need to detect when all caching has completed. The snippet of my service worker is:
let appCaches = [{
name: 'pageload-core-2018-02-14.002',
urls: [
'./',
'./index.html',
'./manifest.json',
'./sw.js',
'./sw-register.js'
]
},
{
name: 'pageload-icon-2018-02-14.002',
urls: [
'./icon-32.png',
'./icon-192.png',
'./icon-512.png'
]
},
{
name: 'pageload-data-2019-02-14.002',
urls: [
'./kjv.js'
]
}
];
let cacheNames = appCaches.map((cache) => cache.name);
self.addEventListener('install', function (event) {
console.log('install');
event.waitUntil(caches.keys().then(function (keys) {
return Promise.all(appCaches.map(function (appCache) {
if (keys.indexOf(appCache.name) === -1) {
caches.open(appCache.name).then(function (cache) {
return cache.addAll(appCache.urls).then(function () {
console.log(`Cached: ${appCache.name} # ${Math.floor(Date.now() / 1000)}`);
});
});
} else {
console.log(`Found: ${appCache.name}`);
return Promise.resolve(true);
}
})).then(function () {
// Happens first; expected last.
console.log(`Cache Complete # ${Math.floor(Date.now() / 1000)}`);
});
}));
self.skipWaiting();
});
When I test this with a simulated 3G network, the trace is:
I do not understand why the 'Cache Complete' message is logged before any of the individual 'Cached' messages are logged; I would expect it to be last. Is there something different about the way Promise.all behaves compared to other promises?
Oy! What a silly oversight. After breaking the promise chains into individual promises and stepping through the code, the problem became obvious.
self.addEventListener('install', function (event) {
console.log('install');
event.waitUntil(caches.keys().then(function (keys) {
return Promise.all(appCaches.map(function (appCache) {
if (keys.indexOf(appCache.name) === -1) {
// Never returned the promise chain to map!!!
return caches.open(appCache.name).then(function (cache) {
return cache.addAll(appCache.urls).then(function () {
console.log(`Cached: ${appCache.name} # ${Math.floor(Date.now() / 1000)}`);
});
});
} else {
console.log(`Found: ${appCache.name}`);
return Promise.resolve(true);
}
})).then(function () {
console.log(`Cache Complete # ${Math.floor(Date.now() / 1000)}`);
});
}));
self.skipWaiting();
});
I never returned the promise chain to the map function (no explicit return always returns undefined). So the array passed to Promise.all contained only undefined values. Therefore, it resolved immediately and hence logged its message before the others.
Live and learn...
#claytoncarney Do you know how to pass a callback.. or any way to listen to this event from my app?
I try to send a toast message to my user telling them that the data has been cached...
In this case, I send an alert (it's do not work)...

Jasmine, React & AJAX: Unit testing function within a function

Here's the code I would like to test. Specifically, I want to spy on a utility called Linkvalidation.validate to make sure that it is called when handleSave() is called.
This code lives in a component called the CondensedFormModal:
handleSave() {
LinkValidation.validate(this.state.url)
.then((response) => {
if (response.success) {
this.setState({
message: ''
});
}
})
.fail((error) => {
if (error && error.message && error.message.match(/invalid internal link/)) {
this.setState({
message: 'The URL is an internal link. Please use a public link.'
});
} else {
this.setState({
message: 'The URL is invalid.'
});
}
});
Here is the LinkValidation.validate utility I'm using in the handleSave function above:
define([
'module/api-call'
], function(
ApiCall
) {
'use strict';
// Calls validation API
function validate(link) {
var deferred = $.Deferred();
ApiCall.apiCall(
'/url/check',
{ link: link },
'POST',
function(data) {
if (data.success === true) {
deferred.resolve(data);
} else {
// This link is not valid
deferred.reject(data);
}
},
function() {
deferred.reject();
}
);
return deferred;
}
return {
validate: validate
};
});
Here is my test file--
Import statement:
import { validate } from 'modules/link-validation.js';
Test:
describe('when the URL is an internal link', () => {
it('displays a unique error message', (done) => {
let modal = shallowInstance(<CondensedFormModal />);
modal.setState({
url: 'https://internal.example.com'
});
let x = jasmine.createSpy('validate').and.returnValue({
message: "invalid internal link",
success: false,
url: 'https://example.com'
});
modal.handleSave();
_.defer(() => {
expect(x).toHaveBeenCalled();
done();
});
});
});
When I run this test, it consistently fails with the message "Expected spy validate to have been called."
After looking at the Jasmine docs (https://jasmine.github.io/2.1/introduction) and various other Stack Overflow questions (Unit test with spy is failing. Says spy was never called , Jasmine test case error 'Spy to have been called' , etc.) I'm unable to make this work. I've also tried callFake and callThrough instead of returnValue.
Any ideas on how to spy on LinkValidation.validate to assure that it was called?
This line:
let x = jasmine.createSpy('validate')
creates new spy function (it doesn't spy on existing validate function) and handleSave function is not aware of it. So it's not called at all.
You have to set spy on function that is actually called in your component. Since your CondensedFormModal uses LinkValidation module (which I assume is imported in component file) you have to set spy on validate function from imported module which is actually used by component. So I'd suggest something like this:
In CondensedFormModal constructor set LinkValidation as component property to make it easily accessible in tests:
this.LinkValidation = LinkValidation;
In handleSave use validate function like this:
this.LinkValidation.validate(this.state.url);
And finally in test set spy on component validate method:
describe('when the URL is an internal link', () => {
it('displays a unique error message', (done) => {
let modal = shallowInstance(<CondensedFormModal />);
...
spyOn(modal.LinkValidation, 'validate').and.returnValue({
message: "invalid internal link",
success: false,
url: 'https://dash.vagrant.local.rf29.net/shopping/new'
});
modal.handleSave();
_.defer(() => {
expect(modal.LinkValidation.validate).toHaveBeenCalled();
done();
});
});
});

Categories