Check if object contains a link in React Testing Library - javascript

Having the following unit test:
const MY_URL = 'example.com'
it('should render MyComponent with url', () => {
const { getByTestId } = render(<MyComponent />);
const myLink = getByTestId(TestIds.LINK);
expect(loggingLink).toContain(MY_URL);
});
The test fails with the following message:
Expected value: "example.com"
Received object: <div class="m-3" data-testid="test-link">my-link</div>
So it seems that toContain doesn't check what is inside of that object. Is there a method to check that the URL is inside the object?

You can get the anchor element with ByRole query. Just search it with link and then check the attribute href:
// I used screen in this case, but you can get getByRole from render.
const anchorElement = screen.getByRole('link');
expect(anchorElement).toBeInTheDocument();
expect(anchorElement).toHaveAttribute('href', 'example.com');
Anchor elements have link role only when href attribute is present, otherwise no corresponding role. You can check more about it here.

There's a couple of things. First, toContain is for testing if an element exists in an array. https://jestjs.io/docs/expect#tocontainitem
Second, the point of RTL is not to test properties and such, but to test what users see on the screen. So I guess the "RTL way" of doing this would be to click the link and see what's displayed. Which admittedly is not always helpful in every situation!
If you are absolutely sure this url needs a test around it, then you do have an escape hatch via the underlying jest jsdom selectors. You can query an element using a bog standard querySelector and then test the href property directly.
In fact you don't even need querySelector. The getBy methods all return a jsdom object which you can then test with getAttribute('href')

Related

Vue3 web component set attribute

I created stand alone web component, with Vite and Vue3, to replace old jQuery libraries.
When rendered in html, it looks something like:
<custom-datepicker id="deliveryTime">
#shadow-root
<div>...actual component...</div>
</custom-datepicker>
When user select date it would be perfect if I can set attribute value to this element, like:
<custom-datepicker value="selected value HERE" ...
so the form can then use this value from the element by it's id.
Problem is that the only way I manage to achieve this is by emitting event (selected) from my web component and listening to that event, so the form can use value, like:
const datepicker = document.querySelector('#deliveryTime');
const dateSelected = (e) => {
datepicker.value = e.detail.val;
}
window.addEventListener('selected', dateSelected);
If I set value attribute within web component, rest of the app (Apache Velocity template) can't access it because it is in the shadow-root:
<custom-datepicker id="deliveryTime">
#shadow-root
<div value="selected value is sadly HERE">...actual component...</div>
</custom-datepicker>
Is it even possible to achieve this from inside the web component (so I can omit listener)?
I found solution, maybe not the cleanest one but it works :)
In my web-component, in mounted hook component is selected:
const dp = ref(null)
onMounted(() => {
dp.value = document.querySelector("#deliveryTime");
})
After date is selected, instead of emitting just set attribute:
dp.value.setAttribute('value', value)
What if you access the HTMLElement linked to your shadowhost and then use the "setAttribute" function on it ? Assuming you have access to the shadowRoot inside your component using 'this', I think something like that will do the trick (https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/host) :
const shadowHost = this.shadowRoot.host; // The HTMLElement linked to <custom-datepicker />
shadowHost.setAttribute("value", someValueOfYourChoice);

[vue-test-utils]: overwriting methods via the `methods` property or setMethods is deprecated

I am trying to test the methods of my Vue components; the test is seems working fine. But the problem is that it's giving a depreciation warning in the console.
I believe that the vue-test-utils teams would be removing the setMethods and methods property in their next major release.
My problem is that there are no alternative ways to achieve the same things provided for both setMethods and methods property.
Just they suggested a warning:
To stub a complex method extract it from the component and test it in isolation. Otherwise, the suggestion is to rethink those tests.
My Question: How can we extract the method and test the functionalities of the method clicked from the component level or not?
Below is my simple example where I mocked a method and checking if it gets called inside the component when triggered click.
const downloadStub = jest.fn()
const wrapper = mount(Documents, {
methods: { downloadNow: downloadStub },
})
it('check download button clicked and calling downloadNow method', () => {
wrapper.find('.download-button').trigger('click')
expect(downloadStub).toBeCalled()
})
Note: No issues in running the above code; I want to know the alternative ways to achieve the same result and avoid the warning?
After some research, I found one solution that works the way I expected. I am able to achieve this, without using any methods properties and setMethods.
This way, I got rid of the warning message methods property is deprecated and will be removed.
const wrapper = mount(Documents, {
})
it('check download button clicked and calling downloadNow method', () => {
const downloadSpy = jest.spyOn(wrapper.vm, 'downloadNow')
wrapper.find('.download-button').trigger('click')
expect(downloadSpy).toBeCalled()
})
I use the jest.spyOn method and pass the wrapper.vm and method name.
Other solutions are also welcome.

How to make queries in Jest test within context of particular element?

I'm writing tests in Jest for a React app. Let's say I have a web page that contains multiples of a certain element. In the below case, I have two buttons. I want to make queries in my test about the button that is inside of the div element with a test ID of 2.
Is there a way for me to query for that button within the context of that parent div? Something like:
const secondDiv = screen.getByTestId(2);
const buttonOfInterest = secondDiv.getByRole('button', {name: 'Button'});
I've tried the above before, but it doesn't work.
I know that I could assign test ID's to the buttons, but I think it'd be very helpful in other scenarios to be able to make queries within contexts of particular elements (instead of using screen, which refers to the entire document).
You can use “within” helper function:
import { screen, within } from '#testing-library/dom';
const someDiv = screen.getByTestId('some-id');
const childButton = within(someDiv).getByRole('button');
In addition to genechk's answer:
If you are writing tests for react app you better use
import { screen, within } from '#testing-library/react'
instead of
import { screen, within } from '#testing-library/dom';

testcafe - how to assert text contains in html body

I am using testcafe for api testing however our api requires login. Below is my code. I can see json response fine. But i am not sure how to assert on the page.
import { Selector } from 'testcafe';
import Page from './page';
// Page model
const page = new Page();
const url = 'https://myexample.com';
const elementWithIdOrClassName = Selector(value => {
return document.getElementById(value) || document.getElementsByTagName(value);
});
fixture `Test`
.page(url + '/talent/career')
.beforeEach( async t => {
await t
.typeText(page.username, 'gvp50')
.typeText(page.password, 'password')
.click(page.login_button)
});
// Tests
test('Text typing basics', async t => {
await t
.navigateTo(url+'/api/learner/learning_items')
.expect(Selector('html')).contains('learning_items');
});
Testcafe just hangs after i run this code. I tried Selector('body') as well but it doesn't work.
You need to specify what element property (state) you'd like to obtain (verify).
After you selected the entire 'html' element (Selector('html')), specify what property (state) you'd like to access (attributes, childNodes, style, size, etc.). See the DOM Node State topic to learn more.
It looks like you wanted to access the text content as follows:
.expect(Selector('html').textContent).contains('learning_items');
However, such selector usage is unlikely to be the cause of the hang as TestCafe will properly display a message about invalid selector usage. You might want to simplify your test and/or debug it to find what causes the hang.
const cellcomparedata =await Selector('[role="gridcell"]').textContent;
console.log("cellcomparedata is",cellcomparedata);
either you can use this.

How do I get an attribute of an element nested in a React component using Jest and/or Enzyme?

I want to test to see whether an image has properly loaded in a React app. I have decided to check the src attribute of the img element nested within the React component. I want to use the Jest testing framework and, if needed, the Enzyme testing utility.
By digging through the Object.keys of a shallow React test component, I was able to come up with the following solution. The line I'm uncertain about is indicated with the asterisks.
import React from 'react';
import {shallow} from 'enzyme';
import App from './App';
it('should have the logo image', () => {
const app = shallow(<App />);
const img = app.find('img');
const src = img.node.props.src; // ******
expect(src).toBe('logo.svg');
});
This solution does work but it seems a little convoluted (it requires a property of a property of a property of a wrapper) and seems somewhat obscure (I can't easily find clear instructions for this online). So, is this the correct/simplest way to do this?
If so, where is the documentation?
If not, how else should/could I be doing this? e.g. Is there some ready-made getAttribute or retrieveProp method, etc. in Enzyme? Is there a better way of doing this using something else instead of Enzyme, e.g. react-addons-test-utils?
This question about React element attributes doesn't seem to quite answer it for me even though the poster there also indicates having a hard time finding documentation about asserting a rendered attribute value. A number of other questions (e.g. here, here and here) deal with React/Jest/Enzyme but don't deal with retrieving attribute values.
After some digging, I found the following. The indicated line in the question:
const src = img.node.props.src;
can be simplified to the following:
const src = img.prop('src');
The documentation can be found here.
If someone knows of a non-Enzyme way of doing this, I'd still be interested in hearing about it.
For me, it worked as below
expect(companySelect.find('input').props()["disabled"]).toBe(true)
props() returns an object having all the attributes of the selector and then it can be browsed as an object.
Hope this helps too....
https://airbnb.io/enzyme/docs/api/ReactWrapper/props.html
The #testing-library/jest-dom library provides a custom matcher toHaveAttribute. After extending expect clause
import '#testing-library/jest-dom/extend-expect'
we can assert like
const rect = document.querySelector('[data-testid="my-rect"]')
expect(rect).toHaveAttribute('width', '256')
With React Test Utilities:
it('should have the logo image', () =>
const app = TestUtils.renderIntoDocument(<App/>);
var image = TestUtils.findRenderedDOMComponentWithTag(app, 'img');
expect(image.getDOMNode().getAttribute('src')).toEqual('logo.svg');
});
Enzyme tests looks much cleaner.
For me this worked
expect(component.find('button').props().disabled).toBeTruthy();
.node is not working After some hard work, I found the following is 100% related to answer for above question
const src = img.getElement().props.src;

Categories

Resources