Estou enfrentando um problema ao tentar obter o tamanho do elemento de texto usando d3:
Eu tentei getComputedTextLength ou getBBox, minha biblioteca indo bem, mas quando o teste simulado com jsdom retornou o seguinte erro:
TypeError: text.node(...).getBBox não é uma função
Alguma ideia ?
jsdom não faz nenhum layout, então nenhum desses métodos retornaria nada sensato. Você pode apenas deslocá-los em seu retorno de chamada created
e retornar valores simulados.
@Sebmaster obrigado
Espero que o jsdom dê suporte ao layout em breve,
Mesmo problema aqui. Como você pode "shim" os métodos no retorno de chamada, você poderia dar um exemplo?
https://github.com/tmpvar/jsdom#intervening -before-parsing
Obrigado, eu tentei
const dom = new JSDOM('<!DOCTYPE html><body><p>Hello world</p></body></html>', {
beforeParse(window) {
HTMLUnknownElement.getComputedTextLength = (() => 200);
}
});
mas ainda recebo o erro TypeError: tspan.node(...).getComputedTextLength is not a function
. Qual é o elemento certo para simular? 😕
Não, você provavelmente quer window.HTMLElement. Mas eu não sei o que tspan.node(...) retorna, então talvez registre o que é isso.
Você também precisa anexá-lo ao protótipo, não como um método estático.
Para referência futura; a função de nó retorna um window.Element. Isto é o que funcionou para nós:
const dom = new JSDOM('<!DOCTYPE html><body><p>Hello world</p></body></html>', {
beforeParse(window) {
window.Element.prototype.getComputedTextLength = function() {
return 200
}
}
})
Aqui está uma função simples que você pode implementar para polyfill para getBBox
getBoundingBox(svg) {
if (svg.getBBox) {
return svg.getBBox()
} else if (svg.attributes.d) {
let xmin, xmax, ymin, ymax
let path = svg.attributes.d.value
path = path.replace(/[a-z].*/g," ").replace(/[\sA-Z]+/gi," ").trim()
const coordinate_list = path.split(" ")
for (var coordinate of coordinate_list) {
if (coordinate.length > 1) {
let initial_coordinate = coordinate.split(",")
xmin = xmax = initial_coordinate[0]
ymin = ymax = initial_coordinate[1]
break
}
}
for (var coordinate of coordinate_list) {
let xycoord = coordinate.split(",")
if (!xycoord[1]) {
// ignore relative movements
xycoord[0] = xmin
xycoord[1] = ymin
}
xmin = Math.min(xmin, xycoord[0])
xmax = Math.max(xmax, xycoord[0])
ymin = Math.min(ymin, xycoord[1])
ymax = Math.max(ymax, xycoord[1])
}
return [[xmin, ymax], [xmax, ymin]]
}
}
@jordancoil você usa esta função para estender SVGGraphicsElement?
@rssfrncs Ele apenas permite que você obtenha as coordenadas da caixa delimitadora em navegadores que não têm suporte para getBBox()
@jordancoil Polyfill interessante, você sabe se isso também leva em consideração os estilos aplicados ao elemento svg?
Parece que ele verifica apenas as coordenadas do caminho, portanto, se a largura do traçado do caminho for 20 px ou 1px, retornaremos a mesma bbox. Legal de qualquer maneira ter um polyfill simplificado assim
Para uma implementação rápida para testes no Jest:
beforeEach(() => {
window.SVGElement.prototype.getBBox = () => ({
x: 0,
y: 0,
// whatever other props you need
});
});
afterEach(() => {
delete window.SVGElement.prototype.getBBox;
});
Provavelmente uma solução melhor com mocks, mas precisa ser pragmático, então apenas faça o que funciona por enquanto.
beforeEach(() => {
window.SVGElement.prototype.getComputedTextLength = () => 200;
});
Graças a @larrybotha , isso funcionou para mim para getComputedTextLength.
@larrybotha @ronvenna ,
quando estou implementando a solução acima, estou recebendo o seguinte erro:
TypeError: Não é possível ler a propriedade 'protótipo' de indefinido
gentilmente me guie
@megha-ui não tenho certeza porque SVGElement
não estaria disponível em window
mas você _pode_ ser capaz de adicionar SVGElement
a window
:
beforeEach(() => {
// naive way to add SVGElement to window if it doesn't exist
if (!window.SVGElement) {
window.SVGElement = {};
}
window.SVGElement.prototype.getBBox = () => ({
x: 0,
y: 0,
// whatever other props you need
});
});
Isso não foi testado e provavelmente mascarará apenas um problema subjacente - se você receber outros erros depois de fazer isso, essa não é a abordagem correta e você precisará determinar qual é o problema subjacente.
Você pode começar inspecionando o objeto window
dentro beforeEach
para determinar se SVGElement
está lá ou não (veja as dicas de solução de problemas do Jest ), embora neste ponto o StackOverflow seja um lugar melhor para obter feedback.
Comentários muito úteis
Para uma implementação rápida para testes no Jest:
Provavelmente uma solução melhor com mocks, mas precisa ser pragmático, então apenas faça o que funciona por enquanto.