The use of CSS selector

Time:2021-4-24

preface

I’ve been writing data verification this week. During the foreground unit test, sometimes layer V doesn’t render the data, so I need to let it render manually.

it('should create', () => 
    //The following assertion ensures that no exception occurs during the initialization of the component
    expect(component).toBeTruthy();

    //Simulation of production environment background asynchronous return data 
    getTestScheduler().flush();

    //Ensure that after receiving the simulation data, no exception occurs in the component re rendering
    fixture.detectChanges();
});

We can understand the specific meaning of the sentence from teacher Pan’s blog. But this is not enough, we finally confirm whether the v-layer data is rendered or not is judged by our naked eyes, which loses the significance of unit testing. In order to further improve, we also need to add assertions in the unit test, asserting that the current V layer successfully rendered the data.

css selector

To assert that an item of the current V layer has successfully rendered the data, the first step is to obtain the V layer element. There are also examples of assertions through the table element and input element in the tutorial. But what I get here is the value in a Div. Specific V layer code is as follows

<div class="row">
  <div class="col-md-2 text-right">
    < label > subject < / label >
  </div>
  <div class="col-md-8">
    {{subject.course?.name}}
  </div>
</div>

The use of CSS selector

We want to assert subject.course.name The value of. But it’s a normal div, with no special properties. At this time, I want to take this opportunity to learn about CSS selectors.
CSS selector can obtain a v-layer element in various forms. This paper introduces several common CSS selectors.
1、 Absolute positioning

const nameInput: HTMLInputElement = fixture.debugElement.query(By.css('html >  
body > div > div > form > input')).nativeElement;

This kind of positioning is to find an element through the parent-child relationship layer by layer. The advantage is that an element can be found accurately. However, as soon as the elements related to layer V change, they also change here.

2、 Relative positioning
If we understand absolute positioning, we can understand relative positioning.

const nameInput: HTMLInputElement = fixture.debugElement.query(By.css('div > table')).nativeElement;

It will match all the table elements under a Div.

3、 Attribute positioning

Attribute positioning can be divided into ID positioning, class positioning and (other) attribute positioning. We use attribute location in the example.

const nameInput: HTMLInputElement = fixture.debugElement.query(By.css('input[name="name"]')).nativeElement;

expect(nameInput.value).toEqual(student.name);

Here we are matching an input element, and the name attribute of this input is name.
See this article for detailsCSS selector

Using the console to get the CSS selector

We can also use the console to print the location of an element.
The use of CSS selector
Find this element, right-click copy, and have the copy selector option. Let’s see what’s printed

#root0 > div:nth-child(1) > div.col-md-8

Once the element position is found, the remaining assertions are easy to write.
But there was a problem.

I first used the code of the instance

const subjectCourseNameDiv: HTMLDivElement = fixture.debugElement.query(By.css('#root0 > div:nth-child(1) > div.col-md-8')).nativeElement;

expect( subjectCourseNameDiv.value ). tocontainin ('account name ');

But the assertion always goes wrong, saying that the value I assert is undefined. However, there is no problem in printing the elements obtained by subjectcoursenamediv.

At this time, I think of the use of input and Div. input is the value of the obtained attribute, for example, to write like this

< input type = "name =" value = "account name XXX" >

And that’s what div says

< div > subject name

One is the attribute and the other is the value in it. Then go to the Internet to check the writing method of div selector. It shouldn’t besubjectCourseNameDiv.valueInstead ofsubjectCourseNameDiv.innerText
The overall code is as follows.

fit('should create', () => {
    expect(component).toBeTruthy();

    const subjectCourseNameDiv: HTMLDivElement = fixture.debugElement.query(By.css('#root0 > div:nth-child(1) > div.col-md-8')).nativeElement;
    expect(subjectCourseNameDiv.innerText).toBe('');

    getTestScheduler().flush();
    fixture.autoDetectChanges();

    expect( subjectCourseNameDiv.innerText ). tocontainin ('account name ');
  });

Run a unit test and pass it. Happy to submit the code. But it’s not that simple.
The use of CSS selector
The robot test can’t pass. I ran the unit test as a whole, but I reported an error in the unit test I just wrote, saying that I didn’t find the corresponding element.
The use of CSS selector

I’ll run this unit test alone,

The use of CSS selector

The test passed…

After thinking about it, I guess that the element could not be found due to the change of the overall unit test V layer.
We need to know what’s changed.

The use of CSS selector

Print this selector

#root158 > div

The number is 158, which should represent the connection number of the test. In this way, what we write is definitely not right. At this time, we can use relative positioning. delete#root0 >.

const subjectCourseNameDiv: HTMLInputElement = fixture.debugElement.query(By.css('div:nth-child(1) > div.col-md-8')).nativeElement;

Unit test passed.

summary

CSS selector makes me feel the objectification of HTML. When I first learned, I always thought that HTML was completely different from the back-end language syntax. But the essence is the same. That’s why learning a language is all about it.