Nativescript imagepicker .getImage() is not a function error - nativescript

I have been trying to implement the answer to this question but keep getting the error "selected.getImage is not a function".
I have tried multiple different code examples at this point and I'm stumped. It seems like this is a type error, but I'm not sure where I can correct this.
I am looking to select a single image and return the path to that image in order to upload to the server. I don't need to display it on the device, though that is an option I suppose. Seems easy enough, but apparently I'm missing something.
I'm using v. 6.0.1 or the imagepicker plugin. I'd quote the code, but at this point I am using the exact example provided by Shiva Prasad in the above question.
Adding code per Max Vollmer:
var context = imagepickerModule.create({
mode: "single" // allow choosing single image
});
context
.authorize()
.then(function () {
return context.present();
})
.then(function (selection) {
console.log("Selection done:");
setTimeout(() => {
selection.forEach(function (selected) {
selected.getImage().then((source) => {
console.log(selected.fileUri); // this is the uri you need
});
});
}, 1000);
}).catch(function (e) {
console.log(e);
});

I was facing the exact same error yesterday.
I use the fromAsset function directly on the "selected" because apparently with the new version of this plugin, "selected" is an Asset. So you got an imageSource and you can use the "saveToFile" function that will copy the Asset into a new location (get this location using fileSystemModule from TNS). Use the path of this new location for your UI, and the image will appear. You can also create a file object from this location fileSystemModule.File.fromPath(path);, I use for upload.
context
.authorize()
.then(function () {
return context.present();
})
.then(function (selection) {
selection.forEach(function (selected) {
let file;
if (selected._android) {
file = fileSystemModule.File.fromPath(selected._android);
//viewModel.uploadFile(file);
}else{
imageSourceModule.fromAsset(selected).then((imageSource) => {
const folder = fileSystemModule.knownFolders.documents().path;
const fileName = "Photo.png";
const path = fileSystemModule.path.join(folder, fileName);
const saved = imageSource.saveToFile(path, "png");
if (saved) {
console.log("Image saved successfully!");
file = fileSystemModule.File.fromPath(path);
//viewModel.uploadFile(file);
}else{
console.log("Error! - image couldnt save.");
}
});
}
});
}).catch(function (e) {
console.log(e);
// process error
});
Explanation
The uncommented snippet (//viewModel.uploadFile(file);), viewModel reference (will be different on your app) and the function: uploadFile for example is where you would pass the file to upload it or set it to the image.src etc
Make sure to declare imageSourceModule at the top.
const imageSourceModule = require("tns-core-modules/image-source");

Related

Download link excel in vuejs

In controller laravel: I use box/spout , I save the excel file in a separate folder, and i create a variable that points to the folder where the file is saved, and i return the vuejs view to download that file
$path = '/files/'.$name;
$urlFile = url('/files/'.$name);
var_dump($urlFile);
// Result:
http://localhost.loca/file/data.xlsx
I return view vuejs:
return response()->json($urlFile);
View vuejs :
methods: {
// event button click
clickButton() {
axios
.get("/api/export")
.then((res) => {
console.log(res.data) // http://localhost.loca/file/data.xlsx
// I want to download this link !
})
.catch((error) => {
console.log(error);
});
}
}
Please give me idea download link ? Thanks
Update: I use window.open(res.data) but it doesn't work
Try to create an anchor and click on it programmatically to download the file :
.then((res) => {
console.log(res.data) // http://localhost.loca/file/data.xlsx
//create and append anchor download to body
const downloadAnchor = document.createElement("a");
downloadAnchor.setAttribute("href", "http://localhost.loca/file/data.xlsx");
downloadAnchor.setAttribute("download", "data.xlsx");
document.body.appendChild(downloadAnchor);
downloadAnchor.click();
//remove anchor download
document.body.removeChild(downloadAnchor);
})
If window.open doesn't work you can try this:
function download(url) {
const a = document.createElement('a')
a.href = url
a.download = url.split('/').pop()
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
And then call the download function in your method:
methods: {
// event button click
clickButton() {
axios
.get("/api/export")
.then((res) => {
console.log(res.data) // http://localhost.loca/file/data.xlsx
download(res.data)
})
.catch((error) => {
console.log(error);
});
}
}

Cypress - How can I verify if the downloaded file contains name that is dynamic?

In cypress, the xlsx file I am downloading always starts with lets say "ABC" and then some dynamic IDs. How can I verify if the file is downloaded successfully and also contains that dynamic name?
Secondly, what if the downloaded file is like "69d644353f126777.xlsx" then how can i verify that the file is downloaded when everything in the name is dynamic.
Thanks in advance.
One way that suggests itself is to query the downloads folder with a task,
/cypress/plugins/index.js
const fs = require('fs');
on('task', {
downloads: (downloadspath) => {
return fs.readdirSync(downloadspath)
}
})
test
cy.task('downloads', 'my/downloads/folder').then(before => {
// do the download
cy.task('downloads', 'my/downloads/folder').then(after => {
expect(after.length).to.be.eq(before.length +1)
})
})
If you can't direct the downloads to a folder local to the project, provide a full path. Node.js (i.e Cypress tasks) has full access to the file system.
To get the name of the new file, use a filter and take the first (and only) item in the result.
const newFile = after.filter(file => !before.includes(file))[0]
Maybe this will works but this also requires a filename to be assert.Write this code in index.js
on('task', {
isExistPDF(PDFfilename, ms = 4000) {
console.log(
`looking for PDF file in ${downloadDirectory}`,
PDFfilename,
ms
);
return hasPDF(PDFfilename, ms);
},
});
Now add custom command in support/commands.js
Cypress.Commands.add('isDownloaded', (selectorXPATH, fileName) => {
//click on button
cy.xpath(selectorXPATH).should('be.visible').click()
//verify downloaded file
cy.task('isExistPDF', fileName).should('equal', true)
})
Lastly write this code in your logic area
verifyDownloadedFile(fileName) {
//Clear downloads folder
cy.exec('rm cypress/downloads/*', {
log: true,
failOnNonZeroExit: false,
})
cy.isDownloaded(this.objectFactory.exportToExcelButton, fileName)
}
and call this function in your testcase
I ended up using something similar to #user14783414.
However I keep getting that the downloads' folder length was 0. I then added an cy.wait() which solved the issue.
cy.task('downloads', 'my/downloads/folder').then(before => {
// do the download
}).then(() => {
cy.wait(500).then(() => {
cy.task('downloads', 'my/downloads/folder').then(after => {
expect(after.length).to.be.eq(before.length +1)
})
})
})
})
Another approach is to leverage Nodes fs.watch(...) API and to define a plugin task which waits for a new download to be available and returns the filename:
/cypress/plugins/index.js
const fs = require('fs');
module.exports = (on, config) => {
on('task', {
getDownload: () => {
const downloadsFolder = config['downloadsFolder'];
return new Promise((resolve, reject) => {
const watcher = fs.watch(downloadsFolder, (eventType, filename) => {
if (eventType === 'rename' && !filename.endsWith('.crdownload')) {
resolve(filename);
watcher.close();
}
});
setTimeout(reject, config.taskTimeout); // Or another timeout if desired
});
},
});
};
And then it is fairly easily used within a test spec as follows:
/sometest.spec.js
it('downloads a file', () => {
cy.get(downloadButtonSelector).click();
cy.task('getDownload').then(fileName => {
// do something with your newly downloaded file!
console.log('Downloaded file:', fileName);
});
});
Now technically there may be a bit of a race condition if the file is downloaded extremely quickly and the file exists on disk before the watcher begins, but in my testing - even with relatively small files and fast network speed - I have never observed this.
For the solution of Nicholas, in firefox, the '.crdownload' doesn't exist so we need to add a condition on the '.part' :
if (eventType === 'rename' && !filename.endsWith('.crdownload') && !filename.endsWith('.part'))

how to get the text of bootstrap alert message for testing with protractor

this is my spec
it('should save edited majorObject', function () {
var description = element(by.id('objectDescription'));
description.clear();
description.sendKeys('edited');
var add = element(by.id('saveObject'));
add.click().then(function () {
expect(element(by.css('.alert-success')).isDisplayed()).toBe(true);
expect(element(by.css('.alert-success')).toText()).toBe("Saved Successfully");
})
});
i used
expect(element(by.css('.alert-success')).toText()).toBe("Saved Successfully");
But it is showing undefined and is their any alternative way to do this?
You meant to use getText() instead of toText():
expect(element(by.css('.alert-success')).getText()).toBe("Saved Successfully");

Can't get meteor FileCollection package to work

I am (unfortunately) working on a Windows machine so I had to manually add the FileCollection package to my app, but when I run my app, I can access the file collection and file collection methods from the browser console. However, I can't seem to get the event listeners set up on an actual page. (FYI, I am using iron-router for my templating architecture.)
It seems like the code that needs to be called is just not coming in the right order, but I've experimented with where I place the code and nothing seems to make a difference.
The server side code:
// Create a file collection, and enable file upload and download using HTTP
Images = new fileCollection('images',
{ resumable: true, // Enable built-in resumable.js upload support
http: [
{ method: 'get',
path: '/:_id', // this will be at route "/gridfs/images/:_id"
lookup: function (params, query) { // uses express style url params
return { _id: params._id }; // a mongo query mapping url to myFiles
}
}
]
}
);
if (Meteor.isServer) {
// Only publish files owned by this userId, and ignore
// file chunks being used by Resumable.js for current uploads
Meteor.publish('myImages',
function () {
return Images.find({ 'metadata._Resumable': { $exists: false },
'metadata.owner': this.userId });
}
);
// Allow rules for security. Should look familiar!
// Without these, no file writes would be allowed
Images.allow({
remove: function (userId, file) {
// Only owners can delete
if (userId !== file.metadata.owner) {
return false;
} else {
return true;
}
},
// Client file document updates are all denied, implement Methods for that
// This rule secures the HTTP REST interfaces' PUT/POST
update: function (userId, file, fields) {
// Only owners can upload file data
if (userId !== file.metadata.owner) {
return false;
} else {
return true;
}
},
insert: function (userId, file) {
// Assign the proper owner when a file is created
file.metadata = file.metadata || {};
file.metadata.owner = userId;
return true;
}
});
}
The client side code (currently in main.js at the top level of the client dir):
if (Meteor.isClient) {
// This assigns a file upload drop zone to some DOM node
Images.resumable.assignDrop($(".fileDrop"));
// This assigns a browse action to a DOM node
Images.resumable.assignBrowse($(".fileBrowse"));
// When a file is added via drag and drop
Images.resumable.on('fileAdded', function(file) {
// Create a new file in the file collection to upload
Images.insert({
_id : file.uniqueIdentifier, // This is the ID resumable will use
filename : file.fileName,
contentType : file.file.type
}, function(err, _id) {// Callback to .insert
if (err) {throwError('Image upload failed');}
// Once the file exists on the server, start uploading
Images.resumable.upload();
});
});
Images.resumable.on('fileSuccess', function(file) {
var userId = Meteor.userId();
var url = '/gridfs/images/' + file._id;
Meteor.users.update(userId, {
$set : {
"profile.$.imageURL" : url
}
});
Session.set('uploading', false);
});
Images.resumable.on('fileProgress', function(file) {
Session.set('uploading', true);
});
}
I think the issue might be with using IronRouter. I'll assume you are using some layout.html via Iron router and inside it you've added your template for your file table to be shown. (I'm guessing your are following the sampleApp that came with fileCollection.). I had a problem when I did this and it had to do with where I had the code that attached the listeners. The problem is where you have the code "Images.resumable.assignDrop($(".fileDrop"));" in your client file. The way you have it now, that line of code is running before your template is rendered within the layout.html. So the code can not find the DOM element ".fileDrop". To fix this create a layout.js file and use the rendered method like this...
Template.layout.rendered = function(){
Images.resumable.assignDrop($(".fileDrop"));
}

Running into Error while waiting for Protractor to sync with the page with basic protractor test

describe('my homepage', function() {
var ptor = protractor.getInstance();
beforeEach(function(){
// ptor.ignoreSynchronization = true;
ptor.get('http://localhost/myApp/home.html');
// ptor.sleep(5000);
})
describe('login', function(){
var email = element.all(protractor.By.id('email'))
, pass = ptor.findElement(protractor.By.id('password'))
, loginBtn = ptor.findElement(protractor.By.css('#login button'))
;
it('should input and login', function(){
// email.then(function(obj){
// console.log('email', obj)
// })
email.sendKeys('josephine#hotmail.com');
pass.sendKeys('shakalakabam');
loginBtn.click();
})
})
});
the above code returns
Error: Error while waiting for Protractor to sync with the page: {}
and I have no idea why this is, ptor load the page correctly, it seem to be the selection of the elements that fails.
TO SSHMSH:
Thanks, your almost right, and gave me the right philosophy, so the key is to ptor.sleep(3000) to have each page wait til ptor is in sync with the project.
I got the same error message (Angular 1.2.13). My tests were kicked off too early and Protractor didn't seem to wait for Angular to load.
It appeared that I had misconfigured the protractor config file. When the ng-app directive is not defined on the BODY-element, but on a descendant, you have to adjust the rootElement property in your protractor config file to the selector that defines your angular root element, for example:
// protractor-conf.js
rootElement: '.my-app',
when your HTML is:
<div ng-app="myApp" class="my-app">
I'm using ChromeDriver and the above error usually occurs for the first test. I've managed to get around it like this:
ptor.ignoreSynchronization = true;
ptor.get(targetUrl);
ptor.wait(
function() {
return ptor.driver.getCurrentUrl().then(
function(url) {
return targetUrl == url;
});
}, 2000, 'It\'s taking too long to load ' + targetUrl + '!'
);
Essentially you are waiting for the current URL of the browser to become what you've asked for and allow 2s for this to happen.
You probably want to switch the ignoreSynchronization = false afterwards, possibly wrapping it in a ptor.wait(...). Just wondering, would uncommenting the ptor.sleep(5000); not help?
EDIT:
After some experience with Promise/Deferred I've realised the correct way of doing this would be:
loginBtn.click().then(function () {
ptor.getCurrentUrl(targetUrl).then(function (newURL){
expect(newURL).toBe(whatItShouldBe);
});
});
Please note that if you are changing the URL (that is, moving away from the current AngularJS activated page to another, implying the AngularJS library needs to reload and init) than, at least in my experience, there's no way of avoiding the ptor.sleep(...) call. The above will only work if you are staying on the same Angular page, but changing the part of URL after the hashtag.
In my case, I encountered the error with the following code:
describe("application", function() {
it("should set the title", function() {
browser.getTitle().then(function(title) {
expect(title).toEqual("Welcome");
});
});
});
Fixed it by doing this:
describe("application", function() {
it("should set the title", function() {
browser.get("#/home").then(function() {
return browser.getTitle();
}).then(function(title) {
expect(title).toEqual("Welcome");
});
});
});
In other words, I was forgetting to navigate to the page I wanted to test, so Protractor was having trouble finding Angular. D'oh!
The rootElement param of the exports.config object defined in your protractor configuration file must match the element containing your ng-app directive. This doesn't have to be uniquely identifying the element -- 'div' suffices if the directive is in a div, as in my case.
From referenceConf.js:
// Selector for the element housing the angular app - this defaults to
// body, but is necessary if ng-app is on a descendant of <body>
rootElement: 'div',
I got started with Protractor by watching the otherwise excellent egghead.io lecture, where he uses a condensed exports.config. Since rootElement defaults to body, there is no hint as to what is wrong with your configuration if you don't start with a copy of the provided reference configuration, and even then the
Error while waiting for Protractor to sync with the page: {}
message doesn't give much of a clue.
I had to switch from doing this:
describe('navigation', function(){
browser.get('');
var navbar = element(by.css('#nav'));
it('should have a link to home in the navbar', function(){
//validate
});
it('should have a link to search in the navbar', function(){
//validate
});
});
to doing this:
describe('navigation', function(){
beforeEach(function(){
browser.get('');
});
var navbar = element(by.css('#nav'));
it('should have a link to home in the navbar', function(){
//validate
});
it('should have a link to search in the navbar', function(){
//validate
});
});
the key diff being:
beforeEach(function(){
browser.get('');
});
hope this may help someone.
I was getting this error:
Failed: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
The solution was to call page.navigateTo() before page.getTitle().
Before:
import { AppPage } from './app.po';
describe('App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should have the correct title', () => {
expect(page.getTitle()).toEqual('...');
})
});
After:
import { AppPage } from './app.po';
describe('App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
page.navigateTo();
});
it('should have the correct title', () => {
expect(page.getTitle()).toEqual('...');
})
});
If you are using
browser.restart()
in your spec some times, it throws the same error.
Try to use
await browser.restart()

Resources