'How can I test a resizable circle SVG element?
Trying to figure out how to properly test a resizable <circle> svg element.
I am new to React Testing Library, so I'm unsure if this is possible with RTL (with the Mocha test framework) or if I should use Cypress.
Let's say I have a circle element:
<circle data-testid='circle-element' cx="100" cy="100" r="50"/>
NOTE: 0,0 origin is at the top left.
The center of the circle is located at x=100, y=100 with a radius of 50.
Located on the edge of the circle at x=150, y=100 is a Draghandle where a user can click and drag to resize the circle.
<DragHandle
data-testid='circle-draghandle'
x={handleX}
y={handleY}
dragMove={onHandleDrag}
/>
If a user clicks on the Draghandle at its original location of x=150, y=100 and drags to x=200, y=100, we expect the circle radius to now be 100.
NOTE: the center of the circle is unchanged; still at x=100, y=100.
How can I test this?
I did figure out how to test if the circle rendered properly using React Testing Library with given coordinates and radius:
it('should render a Circle with the coordinates provided', function () {
render(<Circle mark={{ cx: 100, cy: 100, r: 50}} />)
expect(screen.getByTestId('circle-element'))
.to.have.attr('r')
.to.equal('50')
})
NOTE: <Circle> is our component where the actual <circle> svg element lives.
Any help with testing the resizing part what be amazing!
Thank you.
Solution 1:[1]
OK - finally have a solution using React Testing Library and user-events@14!
Hopefully this will help someone else.
user-events must be 14.0 or higher.
import userEvent in testing file:
import userEvent from '@testing-library/user-event'
The test:
describe('Circle tool', function () {
let mark
beforeEach(function () {
mark = CircleMark.create({
id: 'circle1',
toolType: 'circle',
x_center: 200,
y_center: 200,
r: 50
})
})
it('should change the radius when drag handle is moved', async () => {
const user = userEvent.setup()
render(<Circle mark={mark} />)
expect(mark.x_center).to.equal(200)
expect(mark.y_center).to.equal(200)
expect(mark.r).to.equal(50)
// click on dragHandle
// move dragHandle
// release mouse button
const circleDragHandle = screen.getByTestId('draghandle')
await user.pointer([
{ keys: '[MouseLeft>]', target: circleDragHandle },
{ coords: { x: 300, y: 200 } },
{ keys: '[/MouseLeft]' }
])
expect(mark.x_center).to.equal(200)
expect(mark.y_center).to.equal(200)
expect(mark.r).to.equal(100)
})
})
Solution 2:[2]
Tests for dragging can be difficult to implement, if using Cypress I recommend adding cypress-real-events library.
cy.get('[data-testid="circle-draghandle"]')
.realClick()
.realMouseMove(200, 100) // drag 100 right
.realMouseUp()
cy.getByTestId('circle-element') // from cypress-testing-library add-on
.should('have.attr', 'r', '50')
The result may be close but not exact (say 49), in which case the test log will tell you.
If so you can use a closeTo assertion
cy.getByTestId('circle-element')
.should('have.attr', 'r')
.and(radius => {
expect(radius).to.be.closeTo(50, 1)
})
Note
The above would only work if your graphic is <svg>, but it can't be used for <canvas>.
Solution 3:[3]
Try below library-free solution to drag and drop:
cy.get('[data-testid="circle-draghandle"]')
.trigger('mousedown', { //simulating hold click
button: 0
}).wait(700)
.trigger('mousemove', { //simulating drag
pageX: 200,
pageY: 100,
force: true
}).wait(250)
.trigger('mouseup', { //simulating drop
force: true
});
Then you could use Fody's suggested closeTo solution to check the result
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Erik |
| Solution 2 | Fody |
| Solution 3 | Fseee |


