I haven't been able to figure out to get relative scope working for components. For example, given the following (apologies for the contrived example):
<div>
<div class="animal-component">
<h1>Zebra</h1>
</div>
<div>
<div class="animal-component">
<h1>Giraffe</h1>
</div>
</div>
</div>
let animalComponent = PO.component({
title: text('h1')
});
let page = PO.build({
zebraComponent: animalComponent,
giraffeComponent: animalComponent
});
How can I make sure that zebraComponent
points to the first component, and giraffeComponent
points to the second one? I understand I could define two different components:
let zebraComponent = PO.component({
scope: '.outer-component:nth-child(1)',
title: text('h1')
});
let giraffeComponent = PO.component({
scope: '.outer-component:nth-child(2)',
title: text('h1')
});
let page = PO.build({
zebraComponent: zebraComponent,
giraffeComponent: giraffeComponent
});
In this particular case I might also be able to swing it with a collection, but the real pain starts when you have a hierarchy of components:
<div id="your-parents">
<div class="person-entry mother">
<h2>Mother</h2>
<div class="text-field first-name">
<h3>First name</h3>
<input type="text" />
</div>
<div class="text-field last-name">
<h3>Last name</h3>
<input type="text" />
</div>
</div>
<div class="person-entry father">
<h2>Father</h2>
<div class="text-field first-name">
<h3>First name</h3>
<input type="text" />
</div>
<div class="text-field last-name">
<h3>Last name</h3>
<input type="text" />
</div>
</div>
</div>
let textField = PO.component({
fieldName: text('h3'),
inputValue: value('input')
});
let personEntry = PO.component({
title: text('h2'),
firstNameField: textField,
lastNameField: textField
});
let page = PO.build({
mother: personEntry,
father: personEntry
});
Given the above, splitting the components into MotherFirstName, MotherLastName, FatherFirstName, FatherLastName, is a huge waste of time, and not at all DRY.
I think the solution is to allow a component to declare the relative scope of its child components, in the same way that you can use a helper such as text
. Imagine something like:
let textField = PO.component({
fieldName: text('h3'),
inputValue: value('input')
});
let personEntry = PO.component({
title: text('h2'),
firstNameField: textField.relative('.first-name')
lastNameField: textField.relative('.last-name')
});
let page = PO.build({
scope: '#your-parents',
mother: personEntry.relative('.mother'),
father: personEntry.relative('.father')
});
So if I wanted to get the title of the mother's first name field, I could do page.mother().firstNameField().fieldName()
, which would run a selector of #your-parents .mother .first-name h3
.
Alternative syntax:
mother: relativeComponent(personEntry, '.mother'),
Please tell me if I'm missing something obvious. Otherwise if this sounds like something you guys are interested in I'll see if I can work up a PR.