Using #key inside of a loop works fine in development but not production - node.js

The code below works fine in development. I get the number (#key) appended to my class 'step' to produce...'step0, step1, step2, ...) but it does not work in production. Any suggestions on how to get this to work in production?
{{#careers}}
<div class="col-sm-{{{../size}}} emp text-center"><span class="emp-role">{{this}}</span><span class="step{{#key}}"></span></div>
{{/careers}}
The overall goal was to produce numbered 'step' classes.
I then had some css to handle step0, step1, step2 and step3.
.step0 {
...
}
.step1 {
...
}
.step2 {
...
}
I tried to do this with an nth-child() but couldn't get it work work.

I was using {{#key}} when I should have been using {{#index}}.
Answer found here.

Related

Testcafe: using Test Controler in boundTestRun not working

I'm trying to work with shadow roots in my Testcafe project. It's a little bit complicated to deal with it. I create a custom function that behaves the same as Selector().find() but I struggle with this error :
The "boundTestRun" option value is expected to be a test controller.
when I'm doing as documented here :
import { Selector, t } from 'testcafe'
getInShadowRoot = Selector(
// More code here
)
const boundedGetInShadowRoot = this.getInShadowRoot.with({ boundTestRun: t })
I create a gist to illustrate my problem: https://gist.github.com/HugoDel/a600f3e120674e3f255884f3dc84fee3
Thanks for your help!
Edit:
I finally get rid of it since I don't need to add .with({ boundTestRun: t }) to make it work.

Including d3 graph in Angular 4 application

I am building an Angular application with typescript, where I would like to display the force directed network graph from Mike Boston build with d3 shown here.
I have copied and translated most of the code to type script without trouble but the line
. force("link", d3.forceLink().id(function(d) { return d.id; }))
fails with the error {} has no property id.
Only the following lines referring to d.source.x works fine?
I have installed d3 with npm and also types/d3 but still no luck, even though the typings.d.ts has an interface defining the id.
Thank you for your help!
Maybe that is something related to versioning, if you are using TypeScript 2.4.1, try to downgrade to 2.3.4 and give it a go.
As a workaround you could use any:
const forceLink: any = d3.forceLink();
. force("link", forceLink.id(function(d) { return d.id; }))
The example given at http://plnkr.co/edit/qcESHb3cCwD6NZL1yuhX?p=preview helped me, with focus on code shown here:
this.simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
this.render(miserables);
This is the best rendition I have seen. Works for me.

Android Studio - Gradle assemble task

I'm currently struggling with a build process in gradle. My goal is to not have a specific java class in the final .apk for a specific flavor.
The logic goes like this:
1.) before compiling my project delete MyClass.java and copy it to a temp folder
2.) after assembling the apk copy back MyClass.java to my original folder
3.) delete the temp folder
This happens only if I build a specific flavor, so it doesn't happen for all build variants. My code works perfectly when I build only one flavor and one build variant e.g. assembleFlavorRelease, but if I wan't to make my code work for multiple build types; if I run assembleFlavor it should build flavorDebug the same way it does flavorRelease.
However my logic goes trough only the first time and after that it stops, so flavorDebug is build with MyClass and it shouldn't be, while flavorRelease doesn't include MyClass in the .apk because my code runs the first time.
Here is what the code looks like:
task copyResource << {
copy {
from 'src/main/java/MyClass.java'
into 'src/temp'
}
}
task deleteResource << {
delete {
'src/main/java/MyClass.java'
}
}
task deleteTemp << {
delete {
'src/temp'
}
}
task copyBackToSource << {
copy {
from 'src/temp/MyClass.java'
into 'src/main/java'
}
deleteTemp.execute()
}
android.applicationVariants.all { variant ->
if (variant.name.contains('flavor')) {
deleteResource.dependsOn copyResource
variant.javaCompile.dependsOn deleteResource
variant.assemble.doLast {
copyBackToSource.execute()
}
}
}
I think that the directories which I use in my code are somehow locked when trying to execute the whole process the second time?
I feel that you are approaching the problem in the wrong way. Instead of thinking
Put the java file in src/main/java and remove it from flavorX
You should instead be approaching it as
Add an extra source directory to the source sets for flavorY and flavorZ
Once you approach the problem like this it becomes much easier
If you only want the file in one flavor, you can put the file in the flavor specific source folder using the built in conventions (ie src/flavorX/java)
If you want the file in more than one flavor you could put MyClass.java in src/common/java and do something like
android {
productFlavors {
flavor1 {
}
flavor2 {
}
flavor3 {
}
}
}
sourceSets {
flavor1.java = ['src/flavor1/java','src/common/java']
flavor2.java = ['src/flavor2/java','src/common/java']
}
Ok so I got the right solution from here: https://discuss.gradle.org/t/android-gradle-assemble-tasks/10711
If you want to avoid compiling a specific class then use this:
variant.javaCompile.exclude '**/SourceFileToExclude.java'

Geb picking a link from a list

I have recently been reading through the book of Geb and trying to get to grips with it as it seems like a great tool. I feel like I'm getting there but there's still some really core concepts that I can't seem to grasp.
As an example, take the website:-
http://www.escapistmagazine.com/videos/view/zero-punctuation
Now if I want to test that the first video listed links to the correct page my first thought was to do the following
class ZeroPunctuationIndexPage extends Page {
static url = "http://www.escapistmagazine.com/videos/view/zero-punctuation"
static at = {title == "Zero Punctuation Video Gallery | The Escapist"}
static content = {
selectFirstVideo {$("a", 0, class: "filmstrip_video")}
firstVideoTitle {$("i", 0, class: "filmstrip_video")}
}
}
class ZeroPunctuationIndexSpec extends GebReportingSpec {
def "Click the latest video and play it"(){
given:
to ZeroPunctuationIndexPage
when:
selectFirstVideo.click()
then:
title.endsWith(firstVideoTitle)
}
}
Essentially I thought if I pick the first class that contains the video (filmstrip_video) and then pick the link inside it then I could click that, and compare the video title from the link to the new page title.
Looking at it again I'm not surprised it didn't work, but I'm not sure what to do.
If anyone could give me a quick solution i'd appreciate it. I'm not doing anything in particular with the escapist page, I just picked somewhere with an index of videos to try out writing a test.
Thank you!
It was not getting the link and it was failing, so I fixed that and double checked. Now, it's working fine and it passes. Also, when you are selecting the first element, you don't need to write 0 explicitly as by default it will choose the 0th element.
class ZeroPunctuationIndexPage extends Page {
static url = "http://www.escapistmagazine.com/videos/view/zero-punctuation"
static at = {title == "Zero Punctuation Video Gallery | The Escapist"}
static content = {
selectFirstVideo {$("div.filmstrip_video").find('a')}
firstVideoTitle {$("div.filmstrip_video").find('i')}
}
}
class ZeroPunctuationIndexSpec extends GebReportingSpec {
def "Click the latest video and play it"(){
given:
to ZeroPunctuationIndexPage
when:
waitFor { selectFirstVideo.click() }
then:
title.endsWith(firstVideoTitle.text())
}
}
Cheers!
Try:
title.endsWith(firstVideoTitle.text())
I'm on my iPad, so I can't test it, but it should work.

General Problems With Geb (StaleElementReferenceException & Wait Timeouts)

According to the "Book of Geb" I started to map our portal's web pages. I prefer to use variables defined within static content closure block and accessing them afterwards in page methods:
static content = {
buttonSend { $("input", type: "submit", nicetitle: "Senden") }
}
def sendLetter() {
waitFor { buttonSend.isDisplayed() }
buttonSend.click()
}
Unfortunately, sometimes I get an Geb waiting timeout exception (after 60 secs) or even worse I receive the well known "StaleElementReferenceException".
I could avoid the wait timeout when using "isEnabled" instead of "isDisplayed" but for the "StaleElementReferenceException" I could only apply the below solution:
def sendLetter() {
waitFor { buttonSend.isEnabled() }
try {
buttonSend.click()
} catch (StaleElementReferenceException e) {
log.info(e.getMessage())
buttonSend.click()
}
}
I guess, this solution is not really nice but I could not apply an explicitly wait as described in another article. Thus, I have some general questions:
Should I avoid to use static content definitions when pages are dynamically?
At what time or event Geb is refreshing its DOM? How can I trigger the DOM refreshment?
Why I still get a "StaleElementReferenceException" when using CSS selectors?
I would appreciate every hint which helps to understand or to solve this issue. The best would be to have a simple code example since I'm still a beginner. Thank you!
If you defined an at check on your page class the page would first verify that condition and wait for the first n seconds. Which is assigned in your gebConfig file. The default is 30 seconds.
static at = {
waitFor { buttonSend.isDisplayed() }
}
Thus once you call your pages 'to' method with a test or whatever you are using it for the page will wait and then perform your page manipulations.
to MyPage
buttonSend.click()
Should I avoid to use static content definitions when pages are dynamically?
No. Actually, the static definitions are of closures. So what is
actually happening is each time you make use of that Pages static
components you are calling a closure which is run dynamically on the
current page(collection of webElements). Understanding this is key to
using Geb and discovering the problems you will run into.
At what time or event Geb is refreshing its DOM? How can I trigger the DOM refreshment?
When you call: to, go, at, click ,withFrame(frame, page), withWindow
and browser drive methods it will refresh the current set of
WebElements. Geb has a nice collection of utiliities to make switching
between pages and waiting for page manipulations easy. Note: Geb is
actually built on WebDriver WebElements.
Why I still get a "StaleElementReferenceException" when using CSS selectors?
It is possible the page hasn't finished loading, has been manipulated
with ajax calls or has been refreshed in some other way. Sometimes an
'at' PAGE method call can fix these issues. They are for me most
common when using frames as Geb seems to become confused between pages
and frames a little. There are workarounds.
In short if you use the page pattern you can easily switch expected pages using the Page class you have defined with a static content, at, and url closure using the below:
to(Page)
at(Page)
Navigator.click(Page)
withFrame(frame, Page) { }
In addition to twinj's answer, I would like to point out a couple of other workarounds in case you encounter a StaleElementReferenceException.
Often times I find it is better to write out your selector manually rather than rely on the contents as defined in the page. Even though your page contents should not be cached by default, they still manage to slip away from me at times. This is particularly prevalent when dealing with dynamic content or iterations.
Ex: Let's say we want to click an element from a dynamically created dropdown.
Typically you might want to do something like...
static content = {
dropdown { $("#parentDiv").find("ul") }
}
void clickDesiredElement(String elementName) {
dropdown.click()
def desiredElement = dropdown.find("li", text:elementName)
waitFor { desiredElement.displayed }
desiredElement.click()
}
If this doesn't work, try getting rid of the contents altogether, and writing out the selector manually...
void clickDesiredElement(String elementName) {
$("#parentDiv").find("ul").click()
def desiredElement = $("#parentDiv").find("ul").find("li", text:elementName)
waitFor { desiredElement.displayed }
desiredElement.click()
}
In really nasty cases, you may have to use a manual timer, as pointed out in this answer, and your code may look like this...
void clickDesiredElement(String elementName) {
$("#parentDiv").find("ul").click()
sleepForNSeconds(2)
def desiredElement = $("#parentDiv").find("ul").find("li", text:elementName)
waitFor { desiredElement.displayed }
desiredElement.click()
}
Keep in mind this is a workaround :)
For large iterations and convenient closure methods, such as each{} or collect{}, you may want to add a waitFor{} in each iteration.
Ex: Let's say we want to get all rows of a large table
Typically you might want to do something like...
def rows = $("#table1").find("tr").collect {
[
name: it.find("td",0),
email: it.find("td",1)
]
}
Sometimes I find myself having to do this iteratively, along with a waitFor{} between each iteration in order to avoid a StaleElementReferentException. It might look something like this...
def rows = []
int numRows = $("#table1").find("tr").size()
int i
for(i=0; i < numRows; i++) {
waitFor {
def row = $("#table1").find("tr",i)
rows << [
name: row.find("td",0),
email: row.find("td",1)
]
}
}
I have figured that it is the navigator which get lost when you load dynamically.
I've solve the issue locally by reinit the page or module with below code:
void waitForDynamically(Double timeout = 20, Closure closure) {
closure.resolveStrategy = Closure.DELEGATE_FIRST
switch (this) {
case Module:
init(browser, browser.navigatorFactory)
break
case Page:
init(browser)
break
default:
throw new UnsupportedOperationException()
}
waitFor {
closure()
}
}

Resources