-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d00a5fb
commit 898c4e3
Showing
4 changed files
with
196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* eslint-disable @typescript-eslint/no-unused-expressions */ | ||
import { expect } from "@open-wc/testing"; | ||
|
||
import { Insert, Remove, Update } from "./editv1.js"; | ||
|
||
import { convertEdit } from "./convertEdit.js"; | ||
import { SetAttributes } from "./editv2.js"; | ||
|
||
const doc = new DOMParser().parseFromString( | ||
'<SCL><Substation name="AA1"></Substation></SCL>', | ||
"application/xml", | ||
); | ||
|
||
const subSt = doc.querySelector("Substation")!; | ||
|
||
const removeV1: Remove = { node: subSt }; | ||
|
||
const insertV1: Insert = { | ||
parent: subSt, | ||
node: doc.createAttribute("VoltageLevel"), | ||
reference: null, | ||
}; | ||
|
||
const update: Update = { | ||
element: subSt, | ||
attributes: { | ||
name: "A2", | ||
desc: null, | ||
["__proto__"]: "a string", | ||
"myns:attr": { | ||
value: "value1", | ||
namespaceURI: "http://example.org/myns", | ||
}, | ||
"myns:attr2": { | ||
value: "value1", | ||
namespaceURI: "http://example.org/myns", | ||
}, | ||
attr: { | ||
value: "value2", | ||
namespaceURI: "http://example.org/myns2", | ||
}, | ||
attr2: { | ||
value: "value2", | ||
namespaceURI: "http://example.org/myns2", | ||
}, | ||
attr3: { | ||
value: "value3", | ||
namespaceURI: null, | ||
}, | ||
}, | ||
}; | ||
|
||
const setAttributes: SetAttributes = { | ||
element: subSt, | ||
attributes: { | ||
name: "A2", | ||
desc: null, | ||
}, | ||
attributesNS: { | ||
"http://example.org/myns": { | ||
"myns:attr": "value1", | ||
"myns:attr2": "value1", | ||
}, | ||
"http://example.org/myns2": { | ||
attr: "value2", | ||
attr2: "value2", | ||
}, | ||
}, | ||
}; | ||
|
||
const invalidEdit = { someWrongKey: "someValue" } as unknown as Update; | ||
|
||
describe("convertEditToEditV2", () => { | ||
it("passes through a Remove edit", () => | ||
expect(convertEdit(removeV1)).to.deep.equal(removeV1)); | ||
|
||
it("passes through a Insert edit", () => | ||
expect(convertEdit(insertV1)).to.deep.equal(insertV1)); | ||
|
||
it("converts Update to SetAttributes", () => | ||
expect(convertEdit(update)).to.deep.equal(setAttributes)); | ||
|
||
it("converts complex edits", () => { | ||
const editsV1 = [removeV1, insertV1, update]; | ||
|
||
const editsV2 = convertEdit(editsV1); | ||
|
||
const [removeV2, insertV2, updateV2] = Array.from( | ||
editsV2 as Array<Remove | Insert | SetAttributes>, | ||
); | ||
|
||
expect(removeV1).to.deep.equal(removeV2); | ||
expect(insertV1).to.deep.equal(insertV2); | ||
expect(updateV2).to.deep.equal(setAttributes); | ||
}); | ||
|
||
it("return empty array for invalid edit", () => { | ||
expect(convertEdit(invalidEdit)).to.be.an("array").that.is.empty; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { | ||
Edit, | ||
isComplex, | ||
isInsert, | ||
isNamespaced, | ||
isUpdate, | ||
isRemove, | ||
Update, | ||
} from "./editv1.js"; | ||
|
||
import { EditV2 } from "./editv2.js"; | ||
|
||
function convertUpdate(edit: Update): EditV2 { | ||
const attributes: Partial<Record<string, string | null>> = {}; | ||
const attributesNS: Partial< | ||
Record<string, Partial<Record<string, string | null>>> | ||
> = {}; | ||
|
||
Object.entries(edit.attributes).forEach(([key, value]) => { | ||
if (isNamespaced(value!)) { | ||
const ns = value.namespaceURI; | ||
if (!ns) return; | ||
|
||
if (!attributesNS[ns]) { | ||
attributesNS[ns] = {}; | ||
} | ||
attributesNS[ns][key] = value.value; | ||
} else attributes[key] = value; | ||
}); | ||
|
||
return { element: edit.element, attributes, attributesNS }; | ||
} | ||
|
||
export function convertEdit(edit: Edit): EditV2 { | ||
if (isRemove(edit)) return edit as EditV2; | ||
if (isInsert(edit)) return edit as EditV2; | ||
if (isUpdate(edit)) return convertUpdate(edit); | ||
if (isComplex(edit)) return edit.map(convertEdit); | ||
|
||
return []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** Intent to `parent.insertBefore(node, reference)` */ | ||
export type Insert = { | ||
parent: Node; | ||
node: Node; | ||
reference: Node | null; | ||
}; | ||
|
||
export type NamespacedAttributeValue = { | ||
value: string | null; | ||
namespaceURI: string | null; | ||
}; | ||
export type AttributeValue = string | null | NamespacedAttributeValue; | ||
/** Intent to set or remove (if null) attributes on element */ | ||
export type Update = { | ||
element: Element; | ||
attributes: Partial<Record<string, AttributeValue>>; | ||
}; | ||
|
||
/** Intent to remove a node from its ownerDocument */ | ||
export type Remove = { | ||
node: Node; | ||
}; | ||
|
||
/** Represents the user's intent to change an XMLDocument */ | ||
export type Edit = Insert | Update | Remove | Edit[]; | ||
|
||
export function isComplex(edit: Edit): edit is Edit[] { | ||
return edit instanceof Array; | ||
} | ||
|
||
export function isInsert(edit: Edit): edit is Insert { | ||
return (edit as Insert).parent !== undefined; | ||
} | ||
|
||
export function isNamespaced( | ||
value: AttributeValue, | ||
): value is NamespacedAttributeValue { | ||
return value !== null && typeof value !== "string"; | ||
} | ||
|
||
export function isUpdate(edit: Edit): edit is Update { | ||
return (edit as Update).element !== undefined; | ||
} | ||
|
||
export function isRemove(edit: Edit): edit is Remove { | ||
return ( | ||
(edit as Insert).parent === undefined && (edit as Remove).node !== undefined | ||
); | ||
} | ||
|
||
export type EditEvent<E extends Edit = Edit> = CustomEvent<E>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters