From d3b93c15902215e550f01f8beadbd4b1a40d6244 Mon Sep 17 00:00:00 2001
From: Marlon Harrison <92547717+marlon-ionic@users.noreply.github.com>
Date: Mon, 13 Jun 2022 16:55:41 -0500
Subject: [PATCH] feat(mock-doc): add matrix and tspan props for svgelement
(#3408)
this pr adds the following members per request from
ZenDesk ticket 41657:
- Added following members were added to MockDoc: createSVGPoint(),
getBBox(), getComputedTextLength(), getCTM(), getScreenCTM()
- add focus() and blur() to `MockElement`, removing them from
`MockSVGElement` (which inherits from the former)
---
src/mock-doc/element.ts | 141 ++++++++++++++++++++-
src/mock-doc/node.ts | 6 +
src/mock-doc/test/html-parse.spec.ts | 35 +++++
src/testing/puppeteer/puppeteer-element.ts | 2 +-
4 files changed, 177 insertions(+), 7 deletions(-)
diff --git a/src/mock-doc/element.ts b/src/mock-doc/element.ts
index 3a9a0317702..da2ca330214 100644
--- a/src/mock-doc/element.ts
+++ b/src/mock-doc/element.ts
@@ -65,7 +65,28 @@ export function createElementNS(ownerDocument: any, namespaceURI: string, tagNam
if (namespaceURI === 'http://www.w3.org/1999/xhtml') {
return createElement(ownerDocument, tagName);
} else if (namespaceURI === 'http://www.w3.org/2000/svg') {
- return new MockSVGElement(ownerDocument, tagName);
+ switch (tagName.toLowerCase()) {
+ case 'text':
+ case 'tspan':
+ case 'tref':
+ case 'altglyph':
+ case 'textpath':
+ return new MockSVGTextContentElement(ownerDocument, tagName);
+ case 'circle':
+ case 'ellipse':
+ case 'image':
+ case 'line':
+ case 'path':
+ case 'polygon':
+ case 'polyline':
+ case 'rect':
+ case 'use':
+ return new MockSVGGraphicsElement(ownerDocument, tagName);
+ case 'svg':
+ return new MockSVGSVGElement(ownerDocument, tagName);
+ default:
+ return new MockSVGElement(ownerDocument, tagName);
+ }
} else {
return new MockElement(ownerDocument, tagName);
}
@@ -237,6 +258,95 @@ patchPropAttributes(MockScriptElement.prototype, {
type: String,
});
+export class MockDOMMatrix {
+ static fromMatrix() {
+ return new MockDOMMatrix();
+ }
+ a: number = 1;
+ b: number = 0;
+ c: number = 0;
+ d: number = 1;
+ e: number = 0;
+ f: number = 0;
+ m11: number = 1;
+ m12: number = 0;
+ m13: number = 0;
+ m14: number = 0;
+ m21: number = 0;
+ m22: number = 1;
+ m23: number = 0;
+ m24: number = 0;
+ m31: number = 0;
+ m32: number = 0;
+ m33: number = 1;
+ m34: number = 0;
+ m41: number = 0;
+ m42: number = 0;
+ m43: number = 0;
+ m44: number = 1;
+ is2D: boolean = true;
+ isIdentity: boolean = true;
+ inverse() {
+ return new MockDOMMatrix();
+ }
+ flipX() {
+ return new MockDOMMatrix();
+ }
+ flipY() {
+ return new MockDOMMatrix();
+ }
+ multiply() {
+ return new MockDOMMatrix();
+ }
+ rotate() {
+ return new MockDOMMatrix();
+ }
+ rotateAxisAngle() {
+ return new MockDOMMatrix();
+ }
+ rotateFromVector() {
+ return new MockDOMMatrix();
+ }
+ scale() {
+ return new MockDOMMatrix();
+ }
+ scaleNonUniform() {
+ return new MockDOMMatrix();
+ }
+ skewX() {
+ return new MockDOMMatrix();
+ }
+ skewY() {
+ return new MockDOMMatrix();
+ }
+ toJSON() {}
+ toString() {}
+ transformPoint() {
+ return new MockDOMPoint();
+ }
+ translate() {
+ return new MockDOMMatrix();
+ }
+}
+
+export class MockDOMPoint {
+ w: number = 1;
+ x: number = 0;
+ y: number = 0;
+ z: number = 0;
+ toJSON() {}
+ matrixTransform() {
+ return new MockDOMMatrix();
+ }
+}
+
+export class MockSVGRect {
+ height: number = 10;
+ width: number = 10;
+ x: number = 0;
+ y: number = 0;
+}
+
export class MockStyleElement extends MockHTMLElement {
sheet: MockCSSStyleSheet;
@@ -266,7 +376,6 @@ export class MockStyleElement extends MockHTMLElement {
setStyleElementText(this, value);
}
}
-
export class MockSVGElement extends MockElement {
// SVGElement properties and methods
get ownerSVGElement(): SVGSVGElement {
@@ -275,10 +384,6 @@ export class MockSVGElement extends MockElement {
get viewportElement(): SVGElement {
return null;
}
-
- focus() {
- /**/
- }
onunload() {
/**/
}
@@ -299,6 +404,30 @@ export class MockSVGElement extends MockElement {
}
}
+export class MockSVGGraphicsElement extends MockSVGElement {
+ getBBox(_options?: { clipped: boolean; fill: boolean; markers: boolean; stroke: boolean }): MockSVGRect {
+ return new MockSVGRect();
+ }
+ getCTM(): MockDOMMatrix {
+ return new MockDOMMatrix();
+ }
+ getScreenCTM(): MockDOMMatrix {
+ return new MockDOMMatrix();
+ }
+}
+
+export class MockSVGSVGElement extends MockSVGGraphicsElement {
+ createSVGPoint(): MockDOMPoint {
+ return new MockDOMPoint();
+ }
+}
+
+export class MockSVGTextContentElement extends MockSVGGraphicsElement {
+ getComputedTextLength(): number {
+ return 0;
+ }
+}
+
export class MockBaseElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'base');
diff --git a/src/mock-doc/node.ts b/src/mock-doc/node.ts
index 393deda66cd..f49d4b006c6 100644
--- a/src/mock-doc/node.ts
+++ b/src/mock-doc/node.ts
@@ -235,6 +235,10 @@ export class MockElement extends MockNode {
return shadowRoot;
}
+ blur() {
+ /**/
+ }
+
get shadowRoot() {
return this.__shadowRoot || null;
}
@@ -316,6 +320,8 @@ export class MockElement extends MockNode {
return this.children[0] || null;
}
+ focus(_options?: { preventScroll?: boolean }) {}
+
getAttribute(attrName: string) {
if (attrName === 'style') {
if (this.__style != null && this.__style.length > 0) {
diff --git a/src/mock-doc/test/html-parse.spec.ts b/src/mock-doc/test/html-parse.spec.ts
index 17d29264e77..eb3286ae924 100644
--- a/src/mock-doc/test/html-parse.spec.ts
+++ b/src/mock-doc/test/html-parse.spec.ts
@@ -2,6 +2,7 @@ import { createFragment } from '../document';
import { MockDocument } from '../document';
import { NODE_TYPES } from '../constants';
import { parseHtmlToDocument, parseHtmlToFragment } from '../parse-html';
+import { MockDOMMatrix, MockDOMPoint, MockSVGRect, MockSVGSVGElement, MockSVGTextContentElement } from '../element';
describe('parseHtml', () => {
let doc: MockDocument;
@@ -87,6 +88,40 @@ describe('parseHtml', () => {
expect(doc.body.firstElementChild.attributes.item(0).name).toEqual('viewBox');
});
+ it('svg matrix members', () => {
+ doc = new MockDocument(`
+
+ `);
+ const svgElem: MockSVGSVGElement = doc.body.firstElementChild?.firstElementChild as MockSVGSVGElement;
+ expect(svgElem).toBeDefined();
+ expect(svgElem.getBBox()).toEqual(new MockSVGRect());
+ expect(svgElem.createSVGPoint()).toEqual(new MockDOMPoint());
+ expect(svgElem.getScreenCTM()).toEqual(new MockDOMMatrix());
+ expect(svgElem.getCTM()).toEqual(new MockDOMMatrix());
+ });
+
+ it('svg text members', () => {
+ doc = new MockDocument(`
+
+
+ Hello
+ world
+
+
+ `);
+ const text: MockSVGTextContentElement = doc.body.firstElementChild?.firstElementChild as MockSVGTextContentElement;
+ expect(text).toBeDefined();
+ expect(text.tagName).toEqual('text');
+
+ const tspan: MockSVGTextContentElement = text.firstElementChild as MockSVGTextContentElement;
+ expect(tspan).toBeDefined();
+ expect(tspan.getComputedTextLength()).toEqual(0);
+ });
+
it('template', () => {
doc = new MockDocument(`
text
diff --git a/src/testing/puppeteer/puppeteer-element.ts b/src/testing/puppeteer/puppeteer-element.ts
index 7582376396e..1c9db5f9742 100644
--- a/src/testing/puppeteer/puppeteer-element.ts
+++ b/src/testing/puppeteer/puppeteer-element.ts
@@ -55,7 +55,7 @@ export class E2EElement extends MockHTMLElement implements pd.E2EElementInternal
await this._page.waitForChanges();
}
- async focus() {
+ override async focus() {
await this._elmHandle.focus();
await this._page.waitForChanges();
}