how to test ajax request in custom component made by polymer - polymer

component html file part where request is being send
<paper-button class="indigo" style="margin-top:1em; width:15%"
on-tap="sendLoginRequest">Login</paper-button>
<iron-ajax id="loginAjaxRequest" handle-as="json" on-
response="loginResponse" on-error="showToast"></iron-ajax>
sendloginRequest function part where request is fired
sendLoginRequest() {
//some code
this.$.loginAjaxRequest.url = "http://localhost:8080/api/login"
this.$.loginAjaxRequest.body = JSON.stringify(loginJson)
this.$.loginAjaxRequest.method = "POST"
this.$.loginAjaxRequest.generateRequest()
}
how to write test cases for it

Related

Polymer.js iron-ajax headers basic authorization not working

I'm doing a cross origin request to fetch a json response from the url which has a Basic authentication. So on tap of the button, am setting the headers for basic authentication. When I print out the values before the request has been sent I see them. But when i check the chrome dev tool for request I don't see the headers been set. Also the request turns to be an "Options" request from "GET" request and the response comes as 401 unauthorized. Is there anything am missing?
<paper-input type="search" value="{{imageUrl}}" placeholder="Enter Image URL"></paper-input>
<div class="buttons">
<paper-button on-tap="getData" autofocus>Search</paper-button>
</div>
<iron-ajax
id="xhr"
url="https://api.com/v1"
params='{"url":"some query value"}'
handle-as="json"
method="GET"
last-response="{{ajaxResponse}}"></iron-ajax>
getData: function(){
this.$.xhr.headers['X-Requested-With'] = "XMLHttpRequest";
this.$.xhr.headers['Authorization'] = this.makeHeaders(this.user, this.password);
this.$.xhr.generateRequest();
}
By default iron-ajax does not send the credentials by default for cross-site requests
You can change this by setting the withCredentials property on the iron-ajax:
<iron-ajax
id="xhr"
url="https://api.com/v1"
params='{"url":"some query value"}'
handle-as="json"
with-credentials="true"
method="GET"
last-response="{{ajaxResponse}}"></iron-ajax>
or
this.$.xhr.withCredentials = true;

Polymer Starter Kit: how to work with the backend API?

I use Polymer Starter Kit 1.0.3.
My application have different types of pages. Some of them should render data received from request to backend API.
But when the application starts, all requests from all pages immediately start.
The question is how to do the right job with the backend?
I had the same problem as you, the solution I found was to use methods in my elements to call a function that it request information to the backend when I really need it. Sorry for my English.
There is iron-ajax,this is the mainly element polymer work with backend.
Here is an example in my project
<iron-ajax auto
verbose="true"
url="[[apiCategories]]"
handle-as="json"
on-response="_onCategoriesLoadComplete"></iron-ajax>
<iron-ajax auto
id="ajaxWeapons"
verbose="true"
url="[[apiWeapons]]"
params="[[apiWeaponsParams]]"
debounce-duration="300"
handle-as="json"
last-response="{{page}}"></iron-ajax>
<iron-ajax auto
verbose="true"
url="{{apiCountries}}"
handle-as="json"
last-response="{{countries}}"></iron-ajax>
This is very useful, when param change or id change, the whole page's data will reload, the simplest way to work with backend.
Maybe you don't want to auto request, example in my code
<iron-ajax id="ajaxUserRegister"
verbose="true"
url="{{apiUsers}}"
method="PUT"
on-response="_onUserRegisterComplete"
content-type="application/json"
handle-as="json"></iron-ajax>
<iron-ajax id="ajaxUserLogin"
verbose="true"
url="{{apiUsers}}"
method="POST"
on-response="_onUserLoginComplete"
content-type="application/json"
handle-as="json"></iron-ajax>
<iron-ajax id="ajaxUserGet"
verbose="true"
url="{{apiUsers}}"
method="GET"
headers="[[user.headers]]"
on-response="_onUserGetComplete"
content-type="application/json"
handle-as="json"></iron-ajax>
You can also use backend source when you needed
com._userLogin = function () {
var {inputAccount:account,inputPassword:pwd} = this;
if (!(account && account.length >= 4)) {
this.showToast('Wrong account');
return
}
if (!(pwd && pwd.length >= 4)) {
this.showToast('Wrong password');
return
}
this.$.ajaxUserLogin.body = {name: account, password: pwd};
this.$.ajaxUserLogin.generateRequest();
};
com._onUserLoginComplete = function (e, ajax) {
if (ajax.response.error) {
this.showToast('Login faield:' + ajax.response.error);
return
}
this.user = ajax.response;
};
In conclusion,define you backend resource as a iron-ajax, this is how polymer work with backend.

Polymer element content not showing up after core-ajax runs

I am trying call a polymer page from router.go method of another polymer page.
It reaches the polymer element page and runs the core-ajax that i have defined there.
But after running the core-ajax part it never displays the page i.e. it never displays the content of the page.
page from which i m calling the page not getting loaded ...
///////////////////////////////////////////////////////
<polymer-element name="create-client" attributes="router" >
<template>
<app-router id="router" mode="auto|pushstate|hash">
<app-route path="/create-project/:clientName" import="/elements/create-project/create-project.html" on-before-data-binding="{{bindToken}}" bindRouter></app-route>
</app-router>
.
.
.
.<script>
(function() {
Polymer('create-client', {
createProject: function() {
this.$.router.bind('token', this.token, 10);
this.$.router.go('/create-project/' + this.savedClientName);
},
bindToken: function(event) {
debugger;
// update the route's model before it's bound to the home-page or login-page
event.detail.model.token = this.token;
}
}
//////////////////////////////////////////////////////////
Page where it goes and runs the core-ajax but does not reurn the page html.
////////////////////////////////////////////////////////////
<polymer-element name="create-project" attributes="clientName router" >
<template bind "{{clientName}}">
<app-router id="router" mode="auto|pushstate|hash">
<!-- <app-route path="/create-project/:clientName" import="/elements/create-project/create-project.html" on-before-data-binding="{{bindToken}}"></app-route> -->
</app-router>
.
.
.
<core-ajax
auto
url="{{globals.url}}listClients"
headers='{"Authorization": "{{token}}"}'
params=''
handleAs='json'
on-core-response="{{handleClientsResponse}}">
</core-ajax>
</template>
<script>
(function() {
Polymer('create-project', {
handleClientsResponse : function(e) {
this.listClients = e.detail.response;
console.log(e.detail.response);
}
I could debug and see that core-ajax is run , but my front end never displays the content of this page.
Can anyone let me know what's wrong here?
According to Polymer's documentation, you must write the handle-as params in double quotes.
https://elements.polymer-project.org/elements/iron-ajax

Remove child element's attribute from Polymer js

I've a custom element which, among other things, has a core-input and a paper button in it.
When the element is created, the input is disabled, and I want to enable it when I tap the button.
I've tried several ways and can't access the input's attribute.
<paper-input-decorator label="Nombre de usuario" floatingLabel>
<input id="usernameinput" value="{{UserName}}" is="core-input" disabled />
</paper-input-decorator>
<paper-button raised id="edprobutton" on-tap="{{edbutTapped}}">EDITAR</paper-button>
What should I write in
edbutTapped: function () {
},
EDIT
So, I've learned that the problem was that my username input element was inside a repeat template, and that's bad for what I was trying to do. Now I'm trying to bind a single json object to my element, with no luck so far.
What I have right now:
In my Index page:
<profile-page id="profpage" isProfile="true" entity="{{profEntity}}"></profile-page>
<script>
$(document).ready(function () {
var maintemplate = document.querySelector('#fulltemplate');
$.getJSON('api/userProfile.json', function (data) {
var jsonString = JSON.stringify(data);
alert(jsonString);
maintemplate.profEntity = jsonString;
});
}
</script>
In my element's page:
<polymer-element name="profile-page" attributes="isprofile entity">
<template>
<style>
[...]
</style>
<div flex vertical layout>
<core-label class="namepro">{{entity.Name}}</core-label>
<core-label class="subpro">{{entity.CompanyPosition}}</core-label>
<core-label class="subpro">{{entity.OrgUnitName}}</core-label>
</div>
</template>
</polymer-element>
And my JSON looks like this:
{"Name": "Sara Alvarez","CompanyPosition": "Desarrollo","OrgUnitName": "N-Adviser"}
I'm asuming I need to "update" my element somehow after changing its entity attribute?
Try the following
<script>
Polymer({
edbutTapped: function () {
this.$.usernameinput.disabled = false;
}
});
</script>
The this.$ allows you to access controls defined in an elements and the usernameinput is the id you assigned to the input.
This can go below the closing tag of the element you are defining.
'disabled' is conditional-attribute.
So this will be the correct use of it:
<input id="usernameinput" value="{{UserName}}" is="core-input" disabled?="{{isDisabled}}" />
In the prototype:
//first disable the field, can be done in ready callback:
ready: function () {
this.isDisabled = 'true';
}
//set idDisabled to 'false' i.e. enable the input
edbutTapped: function () {
this.isDisabled = 'false';
},
OK this is going to be a long answer (hence why I am not entering this as an edit of my original answer). I've just done something which is functionally the same.
The first thing is this code;
$.getJSON('api/userProfile.json', function (data) {
var jsonString = JSON.stringify(data);
alert(jsonString);
maintemplate.profEntity = jsonString;
});
Polymer has a control called core-ajax - this as it's name suggests makes an ajax call. The other really nice thing is that it can be made to execute when the URL changes. This is the code from the project I've got.
<core-ajax id="ajax"
auto=true
method="POST"
url="/RoutingMapHandler.php?Command=retrieve&Id=all"
response="{{response}}"
handleas="json"
on-core-error="{{handleError}}"
on-core-response="{{handleResponse}}">
</core-ajax>
The auto is the bit which tells it to fire when the URL changes. The description of auto from the polymer documentation is as follows;
With auto set to true, the element performs a request whenever its
url, params or body properties are changed.
you don't need the on-core-response but the on-core-error might be more useful. For my code response contains the JSON returned.
So for your code - it would be something like this
<core-ajax id="ajax"
auto=true
method="POST"
url="/api/userProfile.json"
response="{{jsonString}}"
handleas="json"
on-core-error="{{handleError}}" >
</core-ajax>
Now we have the data coming into your project we need to handle this. This is done by making use of Polymer's data-binding.
Lets detour to the element you are creating. Cannot see anything wrong with the following line.
<polymer-element name="profile-page" attributes="isprofile entity">
We have an element called 'profile-page' with two properties 'isprofile' and 'entity'.
Only because my Javascript leaves a bit to be desired I would pass each property as a seperate entity making that line
<polymer-element name="profile-page" attributes="isprofile name companyposition OrgUnitName">
Then at the bottom of your element define a script tag
<script>
Polymer({
name: "",
companyposition: "",
OrgUnitName: ""
});
</script>
Now back to the calling (profile-page). The following code (from my project) has the following;
<template repeat="{{m in response.data}}">
<map-list-element mapname="{{m.mapName}}" recordid="{{m.Id}}" on-show-settings="{{showSettings}}">
</map-list-element>
</template>
Here we repeat the following each element. In your case you only have one entry and it is stored in jsonString so your template is something like this
<template repeat="{{u in jsonString}}">
<profile-page name="{{u.name}} companyposition="{{u.companyposition}}" OrgUnitName="{{u.OrgUnitName}}">
</profile-page>
</template>
Now we get to the issue you have. Return to your profie-page element. Nothing wrong with the line
on-tap="{{edbutTapped}}"
This calls a function called edbutTapped. Taking the code I gave you earlier
<script>
Polymer({
edbutTapped: function () {
this.$.usernameinput.disabled = false;
}
});
</script>
The only thing to change here is add the following code
created: function() {
this.$.usernameinput.disabled = true;
},
This is inserted after the Polymer({ line. I cannot see in your revised code where the usernameinput is defined but I am assuming you have not posted it and it is defined in the element.
And you should be working, but remember to keep your case consistent and to be honest I've not been - certain parts of Polymer are case sensitive - that catches me out all the time :)

Is there a way to swap one polymer component for another?

I'm stuck a bit conceptually. I've created a builder component for managing the input of data via an AJAX post. On return, I'll have a JSON object that I can render to the client. Optimally, I'd like to instantiate a new render component, pass the JSON object to it, and then destroy the builder component (door number two is a simple page reload, but that seems like a very 1990s hammer for a 21st century nail).
Representative (simplified) builder component:
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/core-ajax/core-ajax.html">
<polymer-element name="post-builder" attributes="accesstoken">
<template>
<core-ajax id="poster" url="api_call" handleAs="json"></core-ajax>
<textarea class="form-control" rows="4" placeholder="Enter text here." value="{{ body }}"></textarea>
<div class="postControls">
<div class="sendLink">
Post
</div>
</div>
</template>
<script>
created: function(){
this.body = '';
},
ready: function(){
},
postAndReplaceTile: function(){
data = {body : this.body, publish : true};
var ajax = this.$.poster;
ajax.removeEventListener('core-response');
ajax.method = 'POST';
ajax.contentType = 'application/json';
ajax.params = { access_token: this.accesstoken };
ajax.body = JSON.stringify(data);
ajax.addEventListener('core-response', function(){
if(this.response.hasOwnProperty('post')){
if(this.response.post.hasOwnProperty('id')){
// valid JSON object of the new post
}
}
});
ajax.go();
}
});
</script>
</polymer-element>
At the stage of the valid JSON object, I'm looking for a moral equivalent of jQuery's replaceWith()...recognizing that the JSON object is in the component that's being replaced so I need to sequence these events carefully. Is there a way to cleanly reach up to the parent DOM and do these types of transformations?
You could use parentNode.host (see here) to access the container element and use DOM methods to replace the element but that's somehow an anti-pattern and breaks encapsulation (see here and here).
It's proably better to use events and let the container element take care of swaping the elements.