Updating proxy events with arguments in RactiveJS 0.8 - events

I'm experimenting with some old code for a shopping cart that I've discovered online, to try to get it working with version 0.8 (I know 0.9 and 1.0 are available, but that comes later...!)
I've managed to update all except one line of code:
<span class="cart-list__item-discard discard-from-cart fa fa-lg fa-trash" on-click="discard:{{i}}"></span>
It's returning this message:
Proxy events with arguments are deprecated. You can fire events with arguments using "#this.fire('eventName', arg1, arg2, ...)". at line 14 character 105:
<span class="cart-list__item-discard discard-from-cart fa fa-lg fa-trash" on-click="discard:{{i}}"></span>
I've tried different changes to the code, such as removing the :{{i}} and rewriting it to use #this.fire as suggested, but the former removes the wrong item, and the latter results in no action! Clearly I'm missing something here. How should I rewrite this line of code to work with Ractive 0.8 and remove the deprecation warning?

on-* supports three forms of syntax
The proxy syntax (event name only, no arguments)
<button type="button" on-click="eventname">Push me!</button>
And the expression syntax (expression value)
<button type="button" on-click="#this.method('Hello, World!')">Push me!</button>
The third is a special form of the expression syntax where it's an array whose first value is the event name and the rest are its arguments. This one closely resembles the old proxy syntax with args.
<button type="button" on-click="['eventname', 'Hello, World!']">Push me!</button>
More on on-* in the documentation.

Related

Cypress-Xpath: Correct Xpath syntax for id? It can't find it

Tried cy.get(#Username) , doesn't work- cypress says it can't find it. could it be related to uppercase letter?
Installed Xpath plugin and used this
cy.xpath('//input[#id="Username"]') but it didn't work.
<input type="email" class="form-control" autocomplete="off" data-gd="identity-login-local-form-username" autofocus="" data-val="true" data-val-required="The Username field is required." id="Username" name="Username" value="">
Please before giving -1 , please explain what I need to improve. Thanks!
After downloading xpath plugin, did you add require('cypress-xpath') in your project's cypress/support/index.js file?
According to your example, code below should find the Username
cy.xpath('//input[#id="Username"]')
cy.get('#Username')
The capital letter may be causing the problem. Usually ids have a small letter.
Try using the data-gd attribute instead.
cy.get('[data-gy="identity-login-local-form-username"]')
If that does not work, you may have some shadow DOM before the <input> that blocks the search, in which case you can search inside the shadow like this
it('tests the input', {includeShadowDom:true}, () => {
cy.get('[data-gy="identity-login-local-form-username"]')
})
I tested with a capital letter cy.get('#Username') and cy.xpath('//input[#id="Username"]') - both worked for me, so likely there is shadow DOM or an <iframe> on your page.
Is it possible that the page has a default namespace? If the page is served as XHTML, it may have a default XML namespace, in which case the input's name is not simply input.
If that is the problem, then you could declare the http://www.w3.org/1999/xhtml namespace and associate it with a prefix, e.g. xhtml (I don't know cypress so not sure how you'd do that), and then query for //xhtml:input[#id="Username"]. An alternative is to query for an element whose local name is input in any namespace at all, e.g. //*[local-name()='input'][#id="Username"]
In case your username field is under a shadow DOM which means other fields will also be under the shadow Dom, it would be advisable to write includeShadowDom: true in your cypress config file to avoid repetition(cypress.json if cypress version < 10; cypress.config.js if cypress version > 10), then directly use the command:
cy.get('#Username').type('username-text')
In case your username field is under an iframe, you can get the cypress iframe plugin
To install npm install -D cypress-iframe
Go to cypress/support/commands.js file, add the following:
import 'cypress-iframe';
// or
require('cypress-iframe');
In your test write:
cy.iframe('#my-frame')
.find('#Username')
.should('be.visible')
.type('username-text')
I can also confirm the way you are selecting the Username input element is correct.
If you suspect shadow DOM is interfering with your test, the best way to debug IMO is to
inspect your DOM around the <input>
look for a parent element that has #shadow-root below it (in bold)
change the test to include this parent
add the .shadow() command after the parent to break through the barrier
cy.get('parent-with-shadow-root')
.shadow()
.find('#Username')
This debugs and confirms your issue. Everything else, e.g setting global config etc can be done after you know what you have to deal with.
After I tried suggestions and people's confirmation that my xpath was correct, I shifted my focus on the error I got while Cypress was trying to find the element. The error I got was uncaught exception.https://stackoverflow.com/questions/53845493/cypress-uncaught-assertion-error-despite-cy-onuncaughtexception
This error occurs when a module fails to load due to some exception. The error message above should provide additional context. A common reason why the module fails to load is that you've forgotten to include the file with the defined module or that the file couldn't be loaded.
Using ngRoute In AngularJS 1.2.0 and later, ngRoute has been moved to its own module. If you are getting this error after upgrading to 1.2.x or later, be sure that you've installed ngRoute.

ember-changeset-validations not working as expected with a boolean

I have an Ember object that has as attribute a boolean field that I want to validate with ember-changeset-validations.
It is the typical "Agree to terms" checkbox.
Here is the hbs code:
{{one-way-checkbox changeset.agree_terms
class="form-control"
update=(action (mut changeset.agree_terms))}}
{{#each changeset.error.agree_terms.validation as |error|}}
<span class="text-danger help-block m-l-3">{{t (concat 'bookings.error.' error)}}</span>
{{/each}}
I have a validations file, where the particular validation for this member of changeset is:
agree_terms: validateFormat({
regex: /^(true)$/,
message: 'You need to agree on Terms!'
})
Thing is, for some reason this never validates to TRUE correctly, I always get the error message...any ideas what I'm doing wrong here?
This is a bit tricky; but I figured that out. ember-change-set-validations do make use of ember-validators underneath. Since; you are using validateFormat; the following code is being run at the end. If you look at the link I have provided; there is a check !canInvoke(value, 'match') causes you the problem. Since the checked value of a checkbox is a boolean and you cannot invoke match on booleans you always end up having an invalid validation.
What can you do? Well; I am not an expert at ember-change-set-validations and ember-validators but it is pretty easy to write a custom validator. This is what I did in the following twiddle. It seems to be working pretty fine.
What I understood is; it is not a good idea to use boolean values with format type validator (it clearly does not work); I only wished it was documented. I hope this helps you.

Inserting a translation into a placeholder with Emblem.js

I'm trying to write a login form with ember.js/emblem.js. Everything works, unless I try I18ning the placeholders like so:
Em.TextField valueBinding="view.username" placeholder="#{t 'users.attributes.username}"
Em.TextField valueBinding="view.password" placeholder="#{t 'users.attributes.password'}" type="password"
I get the same response if I try:
= input value=view.username placeholder="#{t 'users.attributes.username}"
= input value=view.password placeholder="#{t 'users.attributes.password'}" type="password"
In both cases, I get this error message:
Pre compilation failed for: form
. . . .
Compiler said: Error: Emblem syntax error, line 2: Expected BeginStatement or DEDENT but "\uEFEF" found. Em.TextField valueBinding="view.username" placeholder="#{t 'users.attributes.username}"
I assume this is happening because I'm trying to compile something from within a statement that's already being compiled. In evidence of this, I don't get the runtime error if I change the code to:
input value=view.username placeholder="#{t 'users.attributes.username}"
input value=view.password placeholder="#{t 'users.attributes.password'}" type="password"
But the downside is that the value bindings no longer work, which still leaves the form nonoperational. Is there another way of approaching this problem that I haven't considered?
As Alexander pointed out, this is a limitation of Ember and Handlebars. The workaround that I've been using is to make the placeholder refer to a controller property which then returns the translated string. For example:
{{input
type="text"
value=controller.filterText
placeholder=controller.filterPlaceholder }}
And then in the controller:
filterPlaceholder: function () {
return i18n.t('players.filter');
}.property('model.name'),
This is beyond the scope of what Emblem can do because it's an inherent limitation of Ember+Handlebars. What you're trying to do is use the input helper and, inside the helper invocation, use another helper t to get the value for the placeholder option. You can't (presently) do this in Ember, so Emblem's not going to be able to do that for you.
edit: you should try the Ember i18n library. I haven't used it yet, but it seems like what you'll want to do is to mix in the TranslateableAttributes mixin into Ember.View, like:
Ember.View.reopen(Em.I18n.TranslateableAttributes)
and then in your emblem template you can do something like
= input placeholderTranslation="button.add_user.title"
I noticed a typo in the first placeholder="#{t 'users.attributes.username}". It's missing the closing single quote.
The Emblem syntax error, line 2: Expected BeginStatement or DEDENT but "\uEFEF" found. can be misleading. I've found that the error is somewhere else entirely to what was being reported. For instance, linkTo without a | for plain text reports a similar error.
You should use the views to format things and drop them into the template. Controllers are not meant to know what happens at the template.
You would also want that to be a property, so i18n will work just once and then you can use the cache version.
Templete:
{{input value=view.username placeholder=view.usernamePlaceholder}}
{{input value=view.password placeholder=view.passwordPlaceholder type="password"}}
View:
export default Ember.View.extend({
usernamePlaceholder: function() {
return Ember.I18n.t('users.attributes.username');
}.property(),
passwordPlaceholder: function() {
return Ember.I18n.t('users.attributes.password');
}.property()
});

xpath test element for class

I'm wondering if xpath has a way to test an element for a class. I currently have the ID, I would just like to be able to test to ensure JS added a class.
My element where I'm testing to see if id=foo contains class=red.
<span id="foo" class="red">test</span>
I'm assuming you would use xpathCount?
getXpathCount(("//a[#id='foo']") not sure what goes next).equals(1);
I've also tried this without success,
getXpathCount("//span[#id='foo'].span[contains(#class,'red')]").equals(1);
The xpath to use would be
//a[#id='foo' and #class='red']

are css class names with dashes supported in Markaby

Any idea if I can use classes with dashes in Markaby?
Doing div.label-center in mab file results in this HTML:
<div class="label -"><center>
Bonus question - is Markaby dead or alive?
If you want to do this you must send a message to class because - is an operator in Ruby. Write code that way:
div.send(:'label-center')

Resources