Get list of styles in React Testing Library - ecmascript-6

I want to check for styling of all selected span elements:
<div class='color selected'>
<span/>
</div>
I tried it like this:
const selectedColorNodes = document.querySelectorAll('.color.selected');
const selectedColors = Array.from(selectedColorNodes).map(
(item: HTMLElement) => item.firstElementChild.style.backgroundColor,
);
expect(selectedColors).toBe(['ffffff', '000000', '7d533f']);
But selectedColors always is ['','','']
style is highlighted as well with error: Property 'style' does not exist on type 'Element'
What am I doing wrong?

I am not sure because you didn't attach the classes css styling but I can see you are accessing firstElementChild which in the example you provided is a span with no classes. I assume that this span doesn't have any styling but on the page it looks like it has the background color you are trying to assert while in fact it's the parent element who is styled with that color so what you get is empty strings because there is no background color on the child element itself.
Generally it is not recommended to write tests for styling but if you find yourself doing that a lot, I would recommend adding jest-dom which has many useful assertions like toHaveClass or toHaveStyle which would make your tests more concise and more readable.

Related

How to make reset.css not apply inside 1 element?

I want to do this because I get stylized text from "Portable Text to React". However my index.css (global style)
which has a css reset, removes all the default styling from elements of the portable text.
How can I exclude the reset.css from this 1 react component (or solve this in another way you know) ? Adding .unset * {all: unset} or .unset * {all: unset} class does not create the behaviour I want. It removes all styling instead of re-giving the styling to h1s, spans, lists etc.
In here what you can do is, you need to separate your styles for different components. Normally don't use global css to add styles to jsx code.There are couple of ways to add separate css for your component. In here what it does is, these styles are targeting only for selected components.
Option one -use module.css file.
in here you can add css classes only inside the module.css file.(dont use id selectors inside here).Read this reference, you can get full idea about this.click here
option two -use third party library like styled component.
this doc explain clearly what need to do and have many examples to get idea.click here to navigate the doc
Solved: Give this class to the element. revert behaves exactly the way I want. Returns all elements inside this one element to browser default styling, while my css reset remains active on rest of the application. I don't know if there are any drawbacks.
.unset * {
all: revert;
}

How to change the styling of nested child element inside a shadow DOM using angular

I want to change the font style of a child element which is wrapped inside a parent element which is internally wrapped by others and finally it is enclosed inside a shadow root. Attaching the DOM tree structure -
DOM structure description here
I tried making changes by following code
let host = document.querySelector(".fs-timescale-dd");
// host.setAttribute('style','font-style:normal');
let child= host.querySelector('.select');
child.querySelector('.ng-select').querySelector('.ng-select-container')
.querySelector('ng-value-container').querySelector('ng-placeholder')
.setAttribute('style','font-style:normal');
But I'm getting TypeError: Cannot read properties of null (reading 'querySelector')
I'm new to Angular, can someone please help.
You have not clearly mentioned your goal. After reading your question what I can understand is you want to change the font style of the options of the dropdown. If so you can do this from the following example. You can directly select the class on which you want to apply the style.
::ng-deep .some-class {
font-style: normal;
}
Solved by referencing the shadow dom element by adding a class name to it.
Something like this -
document.querySelector(".fs-timescale-dd").className('someName').shadowRoot.setAttribute("font","arial")

Shadow Dom and CSS3 :target selector

I should start off by saying that I don't really have an issue that I'm trying to work through. I just had an interesting thought about how Shadow Dom and the CSS3 :target selector might / should / currently do work together.
I know that HTML specification says that there should only ever be one element with a particular ID value in a valid HTML document. But when we start using webcomponents with shadow dom we could very easily find ourselves using multiple elements with the same ID. This is especially true when we use the same component multiple times in the same page. So the question that I have is this: what should happen to an element inside a shadow dom region that has an ID value which matches the current hash and which is styled with a :target rule?
For example, if I wrote a webcomponent (my-element) that contained
<style>
#debug {display:none}
#debug:target { display:block; background-color:yellow; border 2px solid red; }
</style>
<div id="debug">some debug data</div>
What should happen to all the instance of my-element that I put on a page and navigated to #debug on? Should the debug element in each component show? Should none of them show? Should only the first element's debug div show (the same one I'd expect the browser to try and navigate to)?
My opinion is that if the page does not have an element with an ID=debug value that no scrolling navigation should appear on the page. As shadow dom is isolated from the rest of the page's styles the browser shouldn't try to navigate to such an element nested in shadow dom. Each my-element instance should be able to see the current page's URL though and should apply any matching :target rules, such that each my-elements' debug div should be visible.
If this were the case it would make for some interesting possibilities for sharing page state across all components, such as the debug example above. However, I doubt that is how Chrome is currently implementing things. And I'm pretty sure this Shadow Dom polyfill isn't going to handle things correctly as it basically shoehorns everything into the page's Dom tree and that would break the html specification.
Just curious if anyone has an answer for how this should work and how it works today...
(edited from my pc to add formatting... hard to do from my phone)
I think you can see the shadow DOM like a nested document. CSS can't address elements inside the shadow DOM from the outside (previously existing shadow piercing CSS selectors were deprecated).
This also encapsulates ids and therefore multiple components that contain elements with an id won't cause collisions or duplicates.
If you have the CSS with the :target selector inside a components style, it should be able to address the element with the matching id, otherwise it shouldn't.
So the question that I have is this: what should happen to an element
inside a shadow dom region that has an ID value which matches the
current hash and which is styled with a :target rule?
Adding to Günter Zöchbauer above answer an alternative is to use the Custom Element object when the style is encapsulated, if the style is global it will work just fine. Use the define method to create a custom component as shown in the the docs. This will not encapsulate your elements so be aware that your styles can be shared across files.
So instead of doing this:
const shadow = this.attachShadow({ mode: "open" });
shadow.appendChild(pTag)
Use this:
this.appendChild(pTag);
both previous examples suppose you're in a HTMLElement class or a class that inherits it.

CSS selector select by div class attributes

<div class="thumbnail-popular" style="background: url('http://images.gogoanime.tv/images/upload/Go!.Princess.Precure.full.1812487.jpg');"></div>
I am trying to get the url component of this div class but I seem to be unable to fetch that specific data in the div class.
I have looked into making use of attributes but my attempts have been unsuccessful so far.
Usage of this CSS selector is through Kimonolabs.
div.thumbnail-popular should get you the element you're looking for — unless there is more than one such element, in which case you will need to narrow down your selector.
For example you will need to find out if this particular element belongs to a specific parent, or is the first, second, ... nth child, or any other information about the surrounding elements in the page that you're working with.
The background URL is in a style attribute on this element, so you will need to extract that attribute as described here. However you will still need to parse the declarations inside the style value in order to get the URL; I am not sure if it is possible to do this through kimono as I am not familiar with it (I'm not sure what its advanced mode really does, and it's difficult to tell from the lone screenshot that is provided in that help article).

Is there a way to target an element depending on what is inside it?

On my page, I have custom styled hyperlinks, and I also have alot of hyperlinked images. I don't want these custom styles to appear on the hyperlinks that only contain images. Instead of adding a separate class (i.e "nostyle") to each hyperlinked image, can I somehow target the hyperlinked images from my stylesheet?
You cannot select the parent of a matched item in CSS directly. There are workarounds with js (e.g. Searching elements and applying class attributes to their parent nodes) but seems a bit clumsy. You would rather refactor your document structure to find out a slicker solution.
sure, just use
a img {
// your style here...
}
if you want to target only the images within a certain class of links, use
a.yourclass img {}
Based on what it sounds like you're asking for the answer is no. You can't go backwards in the CSS only forwards.
As Theo.T mentioned, you could have a JS work-around.
One idea is to do an element innerHTML check to see if the element has an <img> tag inside it and if it does, change the element.className = "nostyle"; but that's a messy workaround and by the time you get the syntax right in JS (and cross-browser) you could have re-factored your document.
no need for a anchor class.
a[rel="image"] img {}