jest/Vitest: is it possible to fetch nodes branches from virtual DOM without mounting the component first? - dom

When testing with Vitest/Jest:
I'm wrapping my JSX with the Vuetify <v-dialog> component,
<v-dialog>
<div id="test">
Hello world!!
</div>
</v-dialog>
which seemingly teleports the node's content outside of the virtual-DOMs "reach", so when we try to console.log the wrapper.html() (the mounted custom component), instead of it console logging the DOM structure, it returns this:
<!---->
<!--teleport start-->
<!--teleport end-->
<!---->
This is not very helpful when trying to test the component.
Is it possible to get and mount segments of the virtual-DOM only? I mean I only wish to mount this node:
<div id="test">
Hello world!!
</div>

Related

Conditional processing within a Sightly/HTL component dependent upon position within a page

I've recently begun as an Ops dev on an AEM project, and we have a component (a table, that has a title, some copy and a field where the author can author some HTML to represent the contents of a table, with and elements. This, for whatever reason, has to sit within a component, called ArticleContainer. The title should have an H1 tag if the table is at the top of the page, and an H2 tag if it's anywhere lower down. I've tried using data-sly-test thus:
<sly data-sly-test.topOfPage="${table.firstPosition==true}">
<h1 data-sly-test="${table.headerCopy}" class="heading fontH2 headingLinear headingThick">
<span class="tableHeadingWrapper">${table.headerCopy # context='html'}</span>
</h1>
</sly>
<sly data-sly-test="${!topOfPage}">
<h2 data-sly-test="${table.headerCopy}" class="heading fontH2 headingLinear headingThick">
<span class="tableHeadingWrapper">${table.headerCopy # context='html'}</span>
</h2>
</sly>
Now, this kind of processing has worked elsewhere where the component doesn't sit within a container, but it seems that if it's in a container it always picks up the non-topOfPage condition. I assume there might be a way to maybe do the test within the container component & pass it down into the table component? How would one go about this, or if it's not possible, is there another method by which one might achieve this?
There are two things here:
What does table.firstPosition return? You should be able to debug this in your Sling Model or POJO and probably need to adjust the logic to account for intermediary containers.
HTL/Sightly has a data-sly-element that allows you to change the HTML element based on an expression, you could make your code shorter (and easier to maintain):
<h1 data-sly-test="${table.headerCopy}" data-sly-element="${table.firstPosition ? 'h1' : 'h2'}" class="heading fontH2 headingLinear headingThick">
<span class="tableHeadingWrapper">${table.headerCopy # context='html'}</span>
</h1>

How to check if child component resource exist or not using Sightly in AEM?

my component has an embedded image component inside of it, i need to show image only if image component is authored,
Component Code:
<div class="col-md-4">
<sly data-sly-resource="${'image' # resourceType='test/components/content/image'}"></sly>
</div>
So i need to check resource of embedded image component authored or not
i know we can do this in Java, but how to do this in Sightly?
This can be doable ,using ${resource['image/jcr:primaryType']},
here image is child component
<sly data-sly-test="${resource['image/jcr:primaryType']}">
<div class="col-xs-5 col-md-4">
<sly data-sly-resource="${'image' # resourceType='test/components/content/image'}"></sly>
</div>
</sly>

in Adobe CQ (AEM) how to iterate through a list of resources using `data-sly-list` and `data-sly-resource` in sightly?

In AEM 6.1, with a structure like this:
- Page
- form node
- parsys
- node 1
- node 2
- ...
- node n
The original form has the following code which works
<div data-sly-resource="${ 'parsys' # resourceType='foundation/components/parsys' }" data-sly-unwrap>
I'm trying to update the form component that injects something before the last node n. On the form node, I have the following code:
<div data-sly-list.children="${resource.listChildren}">
<div data-sly-list.fields="${children.listChildren}">
<div data-sly-test=${fieldsList.last}> DO SOMETHING BEFORE LAST NODE</div>
<div data-sly-resource="${fields}"></div>
</div>
</div>
The data-sly-resource seems to cause the server to hang, with very high cpu usage while the browser is waiting for response. I have to terminate the server process and restart it.
I have tried <div data-sly-resource="${fields # resourceType = fields.resourceType}"></div> but it doesn't seem to render the fields as expected.
Is this the right way of iterating through nodes?
Update: Looked in the massive error.log file, and it seems the CPU spike was caused by infinite loop of RecursionTooDeepException - which I don't see where the recursion is.
According to the Sightly documentation on the Resource block statement, you need to pass in a path to the resource, either relative or absolute. I was able to make your code work by changing <div data-sly-resource="${fields}"></div> to <div data-sly-resource="${fields.path}"></div>.
<div data-sly-list.children="${resource.listChildren}">
<div data-sly-list.fields="${children.listChildren}">
<div data-sly-test=${fieldsList.last}> DO SOMETHING BEFORE LAST NODE</div>
<div data-sly-resource="${fields.path}"></div>
</div>
</div>
If you haven't already downloaded the Sightly REPL, I would highly suggest it to test and debug scenarios such as this one.
I would create a Sling Model and return the data from child nodes as a list from it.
See this link for reference https://sling.apache.org/documentation/bundles/models.html#collections

CQ5 Sightly Accordion component

Hi am trying to design an accordion component using sightly in AEM where instead of jsp we write html code along with different file for css and js under client libs.
I simply coded the below written part and wrote js for the same but am not able to see any changes ... Could someone please provide me a solution to implement the same.. ->when i click on show a parsys section opens up and when show converts to hide and when i click on hide the parsys section closes and hide converts to show.
<div data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap>
<css data-sly-call="${clientLib.css # categories=['sd-singtel.accordion_2']}" data-sly-unwrap/>
<js data-sly-call="${clientLib.js # categories=['sd-singtel.accordion_2']}" data-sly-unwrap/>
</div>
<div data-sly-test="${wcmmode.edit}">Accordion_2 component</div>
<div class="about-contentcontainer">
<div class="about-content">
<div class="awards">
<h4> <span class="more">Show</span></h4>
<h4> <span class="more expanded">Hide</span></h4>
</div>
</div>
</div>
<script>// <![CDATA[
$(document).ready(function() {
alert("Hello");
$(".awards h4 a").click(function() {
enter code here
$(this).parent().next().slideToggle("slow");
var htmlStr = $(this).find(".more").html();
if (htmlStr == "Show") {
$(this).find(".more").html("Hide");
$(this).find(".more").addClass("expanded");
} else {
$(this).find(".more").html("Show");
$(this).find(".more").removeClass("expanded");
}
});
});
// ]]></script>
Looking at it, I think that this has little to do with Sightly or even with AEM. Also, I'm not sure which content you want to toggle.
Below's a working HTML fragment for toggling content (independent from AEM):
<style>
.toggle-content {
display: block;
}
.toggle-content-hide,
.toggle-content-hidden .toggle-content-show {
display: inline;
}
.toggle-content-show,
.toggle-content-hidden .toggle-content-hide {
display: none;
}
</style>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>Sample content 1</div>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>Sample content 2</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
jQuery(function($) {
$('.toggle-content').click(function () {
$(this).toggleClass('toggle-content-hidden').next().toggle('slow');
return false;
})
});
</script>
To implement this in AEM, you should place the inline CSS into a CSS file of a client library, and the inline JS into a JS file of a client lib. I usually recommend to place them in the same client library within the component itself, so that everything that relates to that component is in the same folder. But when doing so, it is important to keep in mind that on a publish server, all /apps requests are forbidden by the dispatcher for security reasons, so all client libraries located under /apps should be merged and minified as one file that is typically located somewhere under /etc. To do so, you can use following repository node structure:
/apps/
mysite/
components/
mycomponent/
mycomponent.html Sightly template
clientlib/
jcr:primaryType = cq:ClientLibraryFolder
categories = [mysite.mycomponent]
css.txt contains just a reference to style.css
style.css contains the style snippet
js.txt contains just a reference to script.css
script.js contains the script snippet
/etc/
designs/
mysite/
clientlib/
jcr:primaryType = cq:ClientLibraryFolder
categories = [mysite.publish]
embed = [mysite.mycomponent, ...]
dependencies = [mysite.jquery]
The embed property of the /etc clientlib will make that it embeds and merges within the same file all clientlibs that are listed there. As opposed to the client libraries listed under the dependencies property, which will not get merged and will be served as a separate file. You can play with these properties to build the structure you need to optimize your site. There are also settings to automatically minify or not these files.
On the page, you then include the mysite.publish master clientlib located under /etc. So your page <head> element, would contain something like following Sightly template:
<head data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientLib.all # categories='sd-singtel.accordion_2'}" data-sly-unwrap/>
</head>
If you're using AEM 6.1, you can even drop the data-sly-unwrap, because the <sly> tag has the same effect.
After that, the Sightly template of your component located under a path like /apps/mysite/components/mycomponent/mycomponent.html would look as follows:
<div data-sly-test="${wcmmode.edit}">mycomponent name</div>
<a href="#" class="toggle-content">
<span class="toggle-content-show">Show</span>
<span class="toggle-content-hide">Hide</span>
</a>
<div>${properties.myContentProperty}</div>

Does wicket lose hold of the HTML components after a rearrangement through JavaScript?

I have a repeating component in wicked which needs to be added and deleted as per the user requirement. The maximum number of component is predefined. So I am adding the components at start up and hiding and showing based on need. I am required to change the arrangement of the components in the HTML markup when there is any deletion of the component. I use JavaScript for this. I want to know if wicket would lose hold of the components if I do this.
<div wicket:id="borrowerTabs" id="borrowerTabs">
<span wicket:id="borrowerTab1" id="borrowerTab1" ></span>
<span wicket:id="borrowerTab2" id="borrowerTab2" ></span>
<span wicket:id="borrowerTab3" id="borrowerTab3" ></span>
<span wicket:id="borrowerTab4" id="borrowerTab4" ></span>
<button wicket:id="addBorrower" id="addBorrower" type="button"></button>
<button wicket:id="deleteBorrower" id="deleteBorrower" onclick="updateUIForDeleteBorrower()" type="button"></button>
</div>
If delete the borrowerTab3, contents inside borrowerTab4 will be replacing the contents inside borrowerTab3 and the model objects too will be swapped though I do not do a target.add(borrowerTab3). Now while form submission, I am not getting the values of the fields inside borrowerTab3.
I'm not sure if it helps but try component.setVisible(false) in your java code to hide it.