Refactoring entities (#23)

* Still WIP

* WIP

* ArrayEntity parsing fixed

* Fix format text entity

* Tests for various entity classes and update entity class implementations

* More tests and fixed

* More entities fixed

* Simple entities serialization fixed

* Entities tests fixed

* Remove serialization bits

* Fix Function reference

* CustomProperties creating fixed

* WIP

* Better typing for grammars

* Decoding code fixes

* Fixing still

* Several fixes

* rename toString to serialize

* Several fixes

* More fixes

* Moving more stuff out of Utility

* Several fixes

* Fixing Linear color entity print

* Serialization fixes

* Fix serialization

* Method to compute grammar

* Renaming fix

* Fix array grammar and equality check

* Fix inlined keys

* Fix type

* Several serialization fixes

* Fix undefined dereference

* Several fixes

* More fixes and cleanup

* Fix keys quoting mechanism

* Fix natural number assignment

* Fix Int64 toString()

* Fix quoted keys for inlined arrays

* Fix PG pins

* Fix several test cases

* Types fixes

* New pin default value empty

* Fix non existing DefaultValue for variadic nodes

* Smaller fixes for crashes

* Fix link color when attached to knot

* Linking test and more reliability operations for adding pins

* Improve issue 18 test

* More tests and fixes

* Fix enum pin entity

* Remove failing test
This commit is contained in:
barsdeveloper
2024-09-08 11:46:36 +02:00
committed by GitHub
parent 31a07b992d
commit 23ee628e28
129 changed files with 8888 additions and 8584 deletions

View File

@@ -0,0 +1,69 @@
// @ts-nocheck
import StringEntity from "../js/entity/StringEntity.js"
import initializeSerializerFactory from "../js/serialization/initializeSerializerFactory.js"
import { expect, test } from "./fixtures/test.js"
import Entity1 from "./resources/Entity1.js"
import Entity2 from "./resources/Entity2.js"
import Entity3 from "./resources/Entity3.js"
import Entity4 from "./resources/Entity4.js"
import entity2Value1 from "./resources/serializedEntity2-1.js"
import entity2Value from "./resources/serializedEntity2.js"
import entity3Value from "./resources/serializedEntity3.js"
import entity4Value from "./resources/serializedEntity4.js"
test.beforeAll(() => initializeSerializerFactory())
test.describe.configure({ mode: "parallel" })
test("Entity2", () => {
const value = new Entity2()
expect(Object.keys(value)).toHaveLength(9)
expect(value.serialize()).toEqual(entity2Value)
const other = new Entity2({ someString2: new StringEntity("gamma") })
expect(value.equals(other)).toBeFalsy()
other.someString2 = new StringEntity("beta")
expect(value.equals(other)).toBeTruthy()
})
test("Entity2-1", () => {
Entity2.attributes.someEntity = Entity2.attributes.someEntity.flagInlined()
const value = new Entity2()
expect(value.serialize()).toEqual(entity2Value1)
})
test("Entity3", () => {
let value = new Entity3()
const keys = [
"alpha",
"bravo",
"charlie",
"delta",
"echo",
"foxtrot",
"golf",
"hotel",
"india",
"juliett",
"kilo",
// "lima", // Not defined by default
"mike",
"november",
"oscar",
"papa",
// "quebec", // Not defined by default
"romeo",
"sierra",
]
expect(Object.keys(value)).toStrictEqual(keys)
expect(value.serialize()).toEqual(entity3Value)
})
test("Entity4", () => {
Entity1.attributeSeparator = " - "
Entity1.keySeparator = ":"
Entity1.printKey = k => k.toUpperCase()
Entity1.wrap = (entity, v) => `E1[${v}]`
const entity = new Entity4()
expect(entity.serialize()).toEqual(entity4Value)
})

File diff suppressed because it is too large Load Diff

157
tests/linking.spec.js Normal file
View File

@@ -0,0 +1,157 @@
import BlueprintFixture from "./fixtures/BlueprintFixture.js"
import { expect, test } from "./fixtures/test.js"
test.describe("Linking", () => {
test.beforeEach(async ({ blueprintPage }) => {
await blueprintPage.removeNodes()
await blueprintPage.paste(String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_29" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_CallFunction_29'"
bIsPureFunc=True
FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.KismetMathLibrary'",MemberName="MakeRotator")
NodePosX=-3152
NodePosY=-608
NodeGuid=4340FF7A779C4CD6A214350F6B196A20
CustomProperties Pin (PinId=01CEDBCB4492ACD233830FBBB7583895,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nKismet Math Library Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.KismetMathLibrary'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__KismetMathLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=9EF49AF4439604F146626C942630AE7F,PinName="Roll",PinFriendlyName="X (Roll)",PinToolTip="X (Roll)\nFloat (single-precision)",PinType.PinCategory="real",PinType.PinSubCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0.0",AutogeneratedDefaultValue="0.0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=C7D2429C4EC24C0D8AE6ADA672BE7C6F,PinName="Pitch",PinFriendlyName="Y (Pitch)",PinToolTip="Y (Pitch)\nFloat (single-precision)",PinType.PinCategory="real",PinType.PinSubCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0.0",AutogeneratedDefaultValue="0.0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=291C0FB3400FBFE88817D7BF71DC1FF7,PinName="Yaw",PinFriendlyName="Z (Yaw)",PinToolTip="Z (Yaw)\nFloat (single-precision)",PinType.PinCategory="real",PinType.PinSubCategory="float",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0.0",AutogeneratedDefaultValue="0.0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=5BADBCF34ED86925DAA81983B5BE12B2,PinName="ReturnValue",PinToolTip="Return Value\nRotator\n\nMakes a rotator {Roll, Pitch, Yaw} from rotation values supplied in degrees",Direction="EGPD_Output",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Rotator'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0, 0, 0",AutogeneratedDefaultValue="0, 0, 0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_5" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_CallFunction_5'"
bIsPureFunc=True
FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.KismetMathLibrary'",MemberName="GetForwardVector")
NodePosX=-2704
NodePosY=-576
NodeGuid=9BFBB662CF9642FBB9003050B5A1D394
CustomProperties Pin (PinId=E8BB6375453E11DF80EEBDBEEE1FFA23,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nKismet Math Library Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.KismetMathLibrary'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultObject="/Script/Engine.Default__KismetMathLibrary",PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=EBD734BF4537F7BFDA921F932A1E67D9,PinName="InRot",PinToolTip="In Rot\nRotator",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Rotator'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0, 0, 0",AutogeneratedDefaultValue="0, 0, 0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=C0EC34304B3A9CCCDFFE71BEE1A30949,PinName="ReturnValue",PinToolTip="Return Value\nVector\n\nRotate the world forward vector by the given rotation",Direction="EGPD_Output",PinType.PinCategory="struct",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.ScriptStruct'/Script/CoreUObject.Vector'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="0, 0, 0",AutogeneratedDefaultValue="0, 0, 0",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`)
})
/** @param {BlueprintFixture} blueprintPage */
const getElements = blueprintPage => {
/** @type {Locator<PinElement>} */
const aPin = blueprintPage.blueprintLocator.locator('ueb-node:has-text("Make Rotator") ueb-pin:has-text("Return Value")')
/** @type {Locator<PinElement>} */
const bPin = blueprintPage.blueprintLocator.locator('ueb-node:has-text("Get Forward Vector") ueb-pin:has-text("In Rot")')
return { aPin, bPin }
}
test("Can connect pins", async ({ blueprintPage }) => {
const { aPin, bPin } = getElements(blueprintPage)
const aRect = await aPin.evaluate(pin => pin.getBoundingClientRect())
const bRect = await bPin.evaluate(pin => pin.getBoundingClientRect())
const mouse = blueprintPage.page.mouse
const color = await aPin.evaluate(pin => pin.entity.pinColor().toString())
expect(color).toMatch(/\d+\,\s*\d+\,\s*\d+/)
expect(await aPin.evaluate(pin => pin.entity.pinColor().toString())).toEqual(color)
expect(await aPin.evaluate(pin => pin.entity.isLinked())).toBeFalsy()
expect(await bPin.evaluate(pin => pin.entity.isLinked())).toBeFalsy()
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(0)
await aPin.hover({
position: {
x: Math.floor(aRect.width / 2),
y: Math.floor(aRect.height / 2),
}
})
await mouse.down()
await mouse.move(aRect.left + aRect.width + 100, aRect.top + aRect.height + 100, { steps: 4 })
// There is one link element ...
expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(1)
// ... but no pins are linked yet
expect(await aPin.evaluate(pin => pin.entity.isLinked())).toBeFalsy()
expect(await bPin.evaluate(pin => pin.entity.isLinked())).toBeFalsy()
await bPin.hover({
position: {
x: Math.floor(bRect.width / 2),
y: Math.floor(bRect.height / 2),
}
})
await mouse.up()
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(1)
expect(await blueprintPage.blueprintLocator.locator("ueb-link").evaluate(
link => link.style.getPropertyValue("--ueb-link-color-rgb"))
)
.toEqual(color)
expect(await aPin.evaluate(pin => pin.entity.isLinked())).toBeTruthy()
expect(await bPin.evaluate(pin => pin.entity.isLinked())).toBeTruthy()
})
test("Can connect only once", async ({ blueprintPage }) => {
{
const { aPin, bPin } = getElements(blueprintPage)
const aRect = await aPin.evaluate(pin => pin.getBoundingClientRect())
const bRect = await bPin.evaluate(pin => pin.getBoundingClientRect())
const mouse = blueprintPage.page.mouse
await aPin.hover({
position: {
x: Math.floor(aRect.width / 2),
y: Math.floor(aRect.height / 2),
}
})
await mouse.down()
await mouse.move(aRect.left + aRect.width + 100, aRect.top + aRect.height + 100, { steps: 4 })
await bPin.hover({
position: {
x: Math.floor(bRect.width / 2),
y: Math.floor(bRect.height / 2),
}
})
await mouse.up()
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(1)
}
{
const { aPin, bPin } = getElements(blueprintPage)
const aRect = await aPin.evaluate(pin => pin.getBoundingClientRect())
const bRect = await bPin.evaluate(pin => pin.getBoundingClientRect())
const mouse = blueprintPage.page.mouse
await aPin.hover({
position: {
x: Math.floor(aRect.width / 2),
y: Math.floor(aRect.height / 2),
}
})
await mouse.down()
await mouse.move(aRect.left + aRect.width + 100, aRect.top + aRect.height + 100, { steps: 4 })
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(2)
await bPin.hover({
position: {
x: Math.floor(bRect.width / 2),
y: Math.floor(bRect.height / 2),
}
})
await expect(blueprintPage.blueprintLocator.locator('ueb-link[data-dragging="true"] .ueb-link-message-text'))
.toContainText("Replace existing input connections")
await mouse.up()
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(1)
}
{
const { aPin, bPin } = getElements(blueprintPage)
const aRect = await aPin.evaluate(pin => pin.getBoundingClientRect())
const bRect = await bPin.evaluate(pin => pin.getBoundingClientRect())
const mouse = blueprintPage.page.mouse
await bPin.hover({
position: {
x: Math.floor(bRect.width / 2),
y: Math.floor(bRect.height / 2),
}
})
await mouse.down()
await mouse.move(bRect.left + bRect.width + 100, bRect.top + bRect.height + 100, { steps: 4 })
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(2)
await aPin.hover({
position: {
x: Math.floor(aRect.width / 2),
y: Math.floor(aRect.height / 2),
}
})
await mouse.up()
await expect(blueprintPage.blueprintLocator.locator("ueb-link")).toHaveCount(1)
}
})
})

View File

@@ -96,8 +96,8 @@ while (i < nodeTests.length) {
},
Configuration.gridSize
)
expect(Math.abs(nodeTest.size[0] - expectedSize[0])).toBeLessThan(1.5)
expect(Math.abs(nodeTest.size[1] - expectedSize[1])).toBeLessThan(1.5)
expect(Math.abs(nodeTest.size[0] - expectedSize[0])).toBeLessThanOrEqual(1.5)
expect(Math.abs(nodeTest.size[1] - expectedSize[1])).toBeLessThanOrEqual(1.5)
if (
Math.abs(nodeTest.size[0] - expectedSize[0]) > 0.6
|| Math.abs(nodeTest.size[1] - expectedSize[1]) > 0.6
@@ -166,8 +166,10 @@ while (i < nodeTests.length) {
async ({ blueprintPage }) => {
const variadic = blueprintPage.node.getByText("Add pin")
await expect(variadic).toBeVisible()
await variadic.hover()
await variadic.click()
expect(await blueprintPage.node.locator("ueb-pin").all()).toHaveLength(nodeTest.pins + 1)
await variadic.blur()
}
)
}

View File

@@ -1,581 +0,0 @@
import { expect, test } from "@playwright/test"
import Utility from "../js/Utility.js"
import FormatTextEntity from "../js/entity/FormatTextEntity.js"
import GuidEntity from "../js/entity/GuidEntity.js"
import IntegerEntity from "../js/entity/IntegerEntity.js"
import KeyBindingEntity from "../js/entity/KeyBindingEntity.js"
import LinearColorEntity from "../js/entity/LinearColorEntity.js"
import ObjectReferenceEntity from "../js/entity/ObjectReferenceEntity.js"
import PinEntity from "../js/entity/PinEntity.js"
import RotatorEntity from "../js/entity/RotatorEntity.js"
import SimpleSerializationRotatorEntity from "../js/entity/SimpleSerializationRotatorEntity.js"
import SimpleSerializationVector2DEntity from "../js/entity/SimpleSerializationVector2DEntity.js"
import SimpleSerializationVectorEntity from "../js/entity/SimpleSerializationVectorEntity.js"
import SymbolEntity from "../js/entity/SymbolEntity.js"
import UnknownKeysEntity from "../js/entity/UnknownKeysEntity.js"
import Vector2DEntity from "../js/entity/Vector2DEntity.js"
import VectorEntity from "../js/entity/VectorEntity.js"
import Grammar from "../js/serialization/Grammar.js"
import SerializerFactory from "../js/serialization/SerializerFactory.js"
import initializeSerializerFactory from "../js/serialization/initializeSerializerFactory.js"
test.beforeAll(() => initializeSerializerFactory())
test.describe.configure({ mode: "parallel" })
test("Array", () => {
const serializer = SerializerFactory.getSerializer(Array)
expect(serializer.read("()")).toStrictEqual([])
expect(serializer.read("( )")).toStrictEqual([])
expect(serializer.read("(1, 2, 3, 4, 5, 6)")).toStrictEqual([1, 2, 3, 4, 5, 6])
expect(serializer.read(`(
"alpha",
"beta",
123,
3BEF2168446CAA32D5B54289FAB2F0BA,
Some(a=1, b="2")
)`)).toStrictEqual([
"alpha",
"beta",
123,
new GuidEntity("3BEF2168446CAA32D5B54289FAB2F0BA"),
new UnknownKeysEntity({
lookbehind: "Some",
a: 1,
b: "2",
})
])
expect(serializer.read(`(
A(first = (9,8,7,6,5), second = 00000000000000000000000000000000),
B(key="hello"),
)`)).toStrictEqual([
new UnknownKeysEntity({
lookbehind: "A",
first: [9, 8, 7, 6, 5],
second: new GuidEntity("00000000000000000000000000000000"),
}),
new UnknownKeysEntity({
lookbehind: "B",
key: "hello",
})
])
// Nested
expect(serializer.read("((1, 2), (3, 4))")).toStrictEqual([[1, 2], [3, 4]])
expect(serializer.read('(((1, 2), (3, 4)), 5)')).toStrictEqual([[[1, 2], [3, 4]], 5])
expect(serializer.read(`(
One(a = (1,(2,(3,(4)))), b = ()),
)`)).toStrictEqual([
new UnknownKeysEntity({
lookbehind: "One",
a: [1, [2, [3, [4]]]],
b: null,
}),
])
})
test("Boolean", () => {
let serializer = SerializerFactory.getSerializer(Boolean)
expect(serializer.read("true")).toStrictEqual(true)
expect(serializer.read("True")).toStrictEqual(true)
expect(serializer.read("false")).toStrictEqual(false)
expect(serializer.read("False")).toStrictEqual(false)
})
test("FormatTextEntity", () => {
let serializer = SerializerFactory.getSerializer(FormatTextEntity)
expect(
serializer.read(`LOCGEN_FORMAT_NAMED(NSLOCTEXT("KismetSchema", "SplitPinFriendlyNameFormat", "{PinDisplayName} {ProtoPinDisplayName}"), "PinDisplayName", "Out Hit", "ProtoPinDisplayName", "Blocking Hit")`)
.toString()
).toBe("Out Hit Blocking Hit")
expect(
serializer.read(`LOCGEN_FORMAT_NAMED(NSLOCTEXT("KismetSchema", "SplitPinFriendlyNameFormat", "{PinDisplayName} {ProtoPinDisplayName}"), "PinDisplayName", "Out Hit", "ProtoPinDisplayName", "Hit Bone Name")`)
.toString()
).toBe("Out Hit Hit Bone Name")
expect(
serializer.read(String.raw`LOCGEN_FORMAT_ORDERED(
NSLOCTEXT(
"PCGSettings",
"OverridableParamPinTooltip",
"{0}Attribute type is \"{1}\" and its exact name is \"{2}\""
),
"If InRangeMin = InRangeMax, then that density value is mapped to the average of OutRangeMin and OutRangeMax\n",
"float",
"InRangeMin"
)`)
.toString()
).toBe(`If InRangeMin = InRangeMax, then that density value is mapped to the average of OutRangeMin and OutRangeMax\nAttribute type is "float" and its exact name is "InRangeMin"`)
})
test("GuidEntity", () => {
let serializer = SerializerFactory.getSerializer(GuidEntity)
let guid = serializer.read("0556a3ecabf648d0a5c07b2478e9dd32")
expect(guid).toBeInstanceOf(GuidEntity)
expect(guid.value).toBe("0556a3ecabf648d0a5c07b2478e9dd32")
guid = serializer.read("64023BC344E0453DBB583FAC411489BC")
expect(guid).toBeInstanceOf(GuidEntity)
expect(guid.value).toBe("64023BC344E0453DBB583FAC411489BC")
guid = serializer.read("6edC4a425ca948da8bC78bA52DED6C6C")
expect(guid).toBeInstanceOf(GuidEntity)
expect(guid.value).toBe("6edC4a425ca948da8bC78bA52DED6C6C")
expect(() => serializer.read("172087193 9B04362973544B3564FDB2C")).toThrow()
expect(() => serializer.read("E25F14F8F3E9441AB07153E7DA2BA2B")).toThrow()
expect(() => serializer.read("A78988B0097E48418C8CB87EC5A67ABF7")).toThrow()
})
test("IntegerEntity", () => {
let serializer = SerializerFactory.getSerializer(IntegerEntity)
let integer = serializer.read("0")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(0)
integer = serializer.read("+0")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(0)
integer = serializer.read("-0")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(0)
integer = serializer.read("99")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(99)
integer = serializer.read("-8685")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(-8685)
integer = serializer.read("+555")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(555)
integer = serializer.read("1000000000")
expect(integer).toBeInstanceOf(IntegerEntity)
expect(integer.value).toStrictEqual(1000000000)
expect(() => serializer.read("1.2").value).toThrow()
})
test("KeyBindingEntity", () => {
let serializer = SerializerFactory.getSerializer(KeyBindingEntity)
let binding = serializer.read("A")
expect(binding).toBeInstanceOf(KeyBindingEntity)
expect(binding).toMatchObject({ Key: { value: "A" } })
binding = serializer.read("(bCtrl=True,Key=A)")
expect(binding).toBeInstanceOf(KeyBindingEntity)
expect(binding).toMatchObject({ Key: { value: "A" }, bCtrl: true })
binding = serializer.read("(bCtrl=false,bShift=false,bCmd=true,bAlt=false,Key=X)")
expect(binding).toBeInstanceOf(KeyBindingEntity)
expect(binding).toMatchObject({ Key: { value: "X" }, bAlt: false, bCtrl: false, bCmd: true })
binding = serializer.read("( bCtrl= false \n, Key \n\n\n =Y ,bAlt=true )")
expect(binding).toBeInstanceOf(KeyBindingEntity)
expect(binding).toMatchObject({ Key: { value: "Y" }, bAlt: true, bCtrl: false })
})
test("LinearColorEntity", () => {
const serializer = SerializerFactory.getSerializer(LinearColorEntity)
let color = LinearColorEntity.getWhite()
expect(color.toRGBA()).toStrictEqual([255, 255, 255, 255])
expect(color.toRGBAString()).toStrictEqual("FFFFFFFF")
expect(color.toNumber()).toStrictEqual(-1)
expect(color.toHSVA()).toStrictEqual([0, 0, 1, 1])
color = serializer.read("(R=1,G=0,B=0)")
expect(color.toRGBA()).toStrictEqual([255, 0, 0, 255])
expect(color.toRGBAString()).toStrictEqual("FF0000FF")
expect(color.toNumber()).toStrictEqual(-16776961)
expect(color.toHSVA()).toStrictEqual([0, 1, 1, 1])
color = serializer.read("(R=0.000000,G=0.660000,B=1.000000,A=1.000000)")
expect(color.toRGBA()).toStrictEqual([0, 168, 255, 255])
expect(color.toRGBAString()).toStrictEqual("00A8FFFF")
expect(color.toNumber()).toStrictEqual(11075583)
expect(color.toHSVA()).toStrictEqual([0.55666666666666666666, 1, 1, 1])
color = serializer.read("(B=0.04394509003266556,G=0.026789300067696642,A=0.83663232408635,R=0.6884158028074934,)")
expect(color.toRGBA()).toStrictEqual([176, 7, 11, 213])
expect(color.toRGBAString()).toStrictEqual("B0070BD5")
expect(color.toNumber()).toStrictEqual(-1341715499)
expect(color.toHSVA().map(v => Utility.roundDecimals(v, 3))).toStrictEqual([0.996, 0.961, 0.688, 0.837])
color = serializer.read(`(
A = 0.327 ,
R=0.530 , G = 0.685
,B
= 0.9 ,)`)
expect(color.toRGBA()).toStrictEqual([135, 175, 230, 83])
expect(color.toRGBAString()).toStrictEqual("87AFE653")
expect(color.toNumber()).toStrictEqual(-2018515373)
expect(color.toHSVA().map(v => Utility.roundDecimals(v, 3))).toStrictEqual([0.597, 0.411, 0.9, 0.327])
expect(() => serializer.read("(R=0.000000,G=0.660000,A=1.000000)")).toThrow()
expect(() => serializer.read("(R=0.000000,G=\"hello\",A=1.000000)")).toThrow()
})
test("Null", () => {
const serializer = SerializerFactory.getSerializer(null)
expect(serializer.read("()")).toBeNull()
expect(() => serializer.read("123")).toThrow()
expect(() => serializer.read("(a)")).toThrow()
expect(() => serializer.read("(")).toThrow()
})
test("Number", () => {
const serializer = SerializerFactory.getSerializer(Number)
expect(serializer.read("0")).toBeCloseTo(0, 0.00001)
expect(serializer.read("+0")).toBeCloseTo(0, 0.00001)
expect(serializer.read("-0")).toBeCloseTo(0, 0.00001)
expect(serializer.read("5")).toBeCloseTo(5, 0.00001)
expect(serializer.read("0.05")).toBeCloseTo(0.05, 0.00001)
expect(serializer.read("-999.666")).toBeCloseTo(-999.666, 0.001)
expect(serializer.read("+45.4545")).toBeCloseTo(45.4545, 0.001)
expect(serializer.read("+1000000000")).toBeCloseTo(1E9, 0.1)
expect(serializer.read("inf")).toBe(Number.POSITIVE_INFINITY)
expect(serializer.read("+inf")).toBe(Number.POSITIVE_INFINITY)
expect(serializer.read("-inf")).toBe(Number.NEGATIVE_INFINITY)
expect(() => serializer.read("alpha")).toThrow()
})
test("ObjectReferenceEntity", () => {
const serializer = SerializerFactory.getSerializer(ObjectReferenceEntity)
let reference = serializer.read("Class")
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({ type: "Class", path: "" })
expect(serializer.write(reference)).toBe("Class")
reference = serializer.read(`Class'/Script/ShooterGame.ShooterGameMode'`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({ type: "Class", path: "/Script/ShooterGame.ShooterGameMode" })
expect(serializer.write(reference)).toBe(`Class'/Script/ShooterGame.ShooterGameMode'`)
reference = serializer.read(`EdGraphPin'EdGraphPin_45417'`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({ type: "EdGraphPin", path: "EdGraphPin_45417" })
expect(serializer.write(reference)).toBe(`EdGraphPin'EdGraphPin_45417'`)
reference = serializer.read(`EdGraphPin'"K2Node_DynamicCast_2126.EdGraphPin_3990988"'`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({ type: "EdGraphPin", path: "K2Node_DynamicCast_2126.EdGraphPin_3990988" })
expect(serializer.write(reference)).toBe(`EdGraphPin'"K2Node_DynamicCast_2126.EdGraphPin_3990988"'`)
reference = serializer.read(
`"/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'"`
)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "/Script/Engine.MaterialExpressionMaterialFunctionCall",
path: "MaterialExpressionMaterialFunctionCall_0",
})
expect(serializer.write(reference)).toBe(
`"/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'"`
)
reference = serializer.read(
`/Script/Engine.EdGraph'"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N"'`
)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "/Script/Engine.EdGraph",
path: "/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N",
})
expect(serializer.write(reference)).toBe(
`/Script/Engine.EdGraph'"/Engine/EditorBlueprintResources/StandardMacros.StandardMacros:Do N"'`
)
reference = serializer.read(
`EdGraphPin'"K2Node_CommutativeAssociativeBinaryOperator_152.EdGraphPin_4045"'`
)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "EdGraphPin",
path: "K2Node_CommutativeAssociativeBinaryOperator_152.EdGraphPin_4045",
})
expect(serializer.write(reference)).toBe(
`EdGraphPin'"K2Node_CommutativeAssociativeBinaryOperator_152.EdGraphPin_4045"'`
)
reference = serializer.read(
`Function'"/Game/Mods/CrazyDinos/ElementalDragon/CDElementalDragon_Character_BP.SKEL_CDElementalDragon_Character_BP_C:ROS Change Element"'`
)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "Function",
path: "/Game/Mods/CrazyDinos/ElementalDragon/CDElementalDragon_Character_BP.SKEL_CDElementalDragon_Character_BP_C:ROS Change Element",
})
expect(serializer.write(reference)).toBe(
`Function'"/Game/Mods/CrazyDinos/ElementalDragon/CDElementalDragon_Character_BP.SKEL_CDElementalDragon_Character_BP_C:ROS Change Element"'`
)
reference = serializer.read(`EdGraph'/Game/Systems/BP_MacroGlobal.BP_MacroGlobal:Or+Branch'`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "EdGraph",
path: "/Game/Systems/BP_MacroGlobal.BP_MacroGlobal:Or+Branch",
})
expect(serializer.write(reference)).toBe(`EdGraph'/Game/Systems/BP_MacroGlobal.BP_MacroGlobal:Or+Branch'`)
reference = serializer.read(`/Script/Engine.EdGraph'"+-Weird/2,Macro"'`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({ type: "/Script/Engine.EdGraph", path: "+-Weird/2,Macro" })
expect(serializer.write(reference)).toBe(`/Script/Engine.EdGraph'"+-Weird/2,Macro"'`)
reference = serializer.read(`/Script/BlueprintGraph.K2Node_VariableGet`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({ type: "/Script/BlueprintGraph.K2Node_VariableGet", path: "" })
expect(serializer.write(reference)).toBe(`/Script/BlueprintGraph.K2Node_VariableGet`)
reference = serializer.read(
`/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'`
)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "/Script/Engine.MaterialExpressionMaterialFunctionCall",
path: "MaterialExpressionMaterialFunctionCall_0",
})
expect(serializer.write(reference)).toBe(
`/Script/Engine.MaterialExpressionMaterialFunctionCall'MaterialExpressionMaterialFunctionCall_0'`
)
reference = serializer.read(
`/Script/Engine.MaterialExpressionMaterialFunctionCall'/Engine/Transient.Material_0:MaterialGraph_0.MaterialGraphNode_3.MaterialExpressionMaterialFunctionCall_0'`
)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "/Script/Engine.MaterialExpressionMaterialFunctionCall",
path: "/Engine/Transient.Material_0:MaterialGraph_0.MaterialGraphNode_3.MaterialExpressionMaterialFunctionCall_0",
})
expect(serializer.write(reference)).toBe(
`/Script/Engine.MaterialExpressionMaterialFunctionCall'/Engine/Transient.Material_0:MaterialGraph_0.MaterialGraphNode_3.MaterialExpressionMaterialFunctionCall_0'`
)
reference = serializer.read(`/Script/CoreUObject.Class'"/Script/Engine.GameModeBase"'`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "/Script/CoreUObject.Class",
path: "/Script/Engine.GameModeBase",
})
expect(serializer.write(reference)).toBe(`/Script/CoreUObject.Class'"/Script/Engine.GameModeBase"'`)
reference = serializer.read(`"/Game/_YukiritoLib/Textures/T_紫色渐变01.T_紫色渐变01"`)
expect(reference).toBeInstanceOf(ObjectReferenceEntity)
expect(reference).toMatchObject({
type: "/Game/_YukiritoLib/Textures/T_紫色渐变01.T_紫色渐变01",
path: "",
})
})
test("PinEntity", () => {
const serializer = SerializerFactory.getSerializer(PinEntity)
expect(serializer.read("Pin (PinType.PinSubCategoryMemberReference=())")).toMatchObject({
"PinType": { "PinSubCategoryMemberReference": null }
})
})
test("SimpleSerializationRotatorEntity", () => {
const serializer = SerializerFactory.getSerializer(SimpleSerializationRotatorEntity)
expect(serializer.read("0, 0, 0")).toEqual(new SimpleSerializationRotatorEntity({
R: 0,
P: 0,
Y: 0,
}))
expect(serializer.read("0.65, 1.0, 0.99")).toEqual(new SimpleSerializationRotatorEntity({
P: 0.65,
Y: 1.0,
R: 0.99,
}))
expect(serializer.read("7,6,5")).toEqual(new SimpleSerializationRotatorEntity({
P: 7,
Y: 6,
R: 5,
}))
})
test("SimpleSerializationVector2DEntity", () => {
const serializer = SerializerFactory.getSerializer(SimpleSerializationVector2DEntity)
expect(serializer.read("0, 0")).toEqual(new SimpleSerializationVector2DEntity({
X: 0,
Y: 0,
}))
expect(serializer.read("127.8, 13.3")).toEqual(new SimpleSerializationVector2DEntity({
X: 127.8,
Y: 13.3,
}))
expect(serializer.read("5,0")).toEqual(new SimpleSerializationVector2DEntity({
X: 5,
Y: 0,
}))
})
test("SimpleSerializationVectorEntity", () => {
const serializer = SerializerFactory.getSerializer(SimpleSerializationVectorEntity)
expect(serializer.read("0, 0, 0")).toEqual(new SimpleSerializationVectorEntity({
X: 0,
Y: 0,
Z: 0,
}))
expect(serializer.read("1001, 56.4, 0.5")).toEqual(new SimpleSerializationVectorEntity({
X: 1001,
Y: 56.4,
Z: 0.5,
}))
expect(serializer.read("-1,-2,-3")).toEqual(new SimpleSerializationVectorEntity({
X: -1,
Y: -2,
Z: -3,
}))
})
test("String", () => {
const serializer = SerializerFactory.getSerializer(String)
expect(serializer.read('""')).toStrictEqual("")
expect(serializer.read('"hello"')).toStrictEqual("hello")
expect(serializer.read('"hello world 123 - éèàò@ç ^ ^^^"')).toStrictEqual("hello world 123 - éèàò@ç ^ ^^^")
expect(serializer.read('"\\""')).toStrictEqual('"')
expect(() => serializer.read("Hello")).toThrow()
expect(serializer.write(`"/Script/CoreUObject.Class'/Script/Interhaptics.HapticSource'"`))
.toBe(String.raw`"\"/Script/CoreUObject.Class'/Script/Interhaptics.HapticSource'\""`)
})
test("UnknownKeysValue", () => {
const parser = Grammar.unknownValue
expect(parser.parse('"Hello"').constructor).toStrictEqual(String)
expect(parser.parse("()")).toBeNull()
expect(parser.parse("8345").constructor).toStrictEqual(Number)
expect(parser.parse("True").constructor).toStrictEqual(Boolean)
expect(parser.parse("False").constructor).toStrictEqual(Boolean)
expect(parser.parse("F0223D3742E67C0D9FEFB2A64946B7F0").constructor).toStrictEqual(GuidEntity)
expect(parser.parse("SYMBOL1").constructor).toStrictEqual(SymbolEntity)
expect(parser.parse("Symbol_2_3_4").constructor).toStrictEqual(SymbolEntity)
expect(parser.parse("(X=-0.495, Y=0, )").constructor).toStrictEqual(Vector2DEntity)
expect(parser.parse("(X=-0.495,Y=+765.0,Z=7)").constructor).toStrictEqual(VectorEntity)
expect(parser.parse("(R=1.000000,P=7.6,Y=+88.99)").constructor).toStrictEqual(RotatorEntity)
expect(parser.parse("(R=0.000000,G=0.660000,B=1.000000,A=1.000000)").constructor)
.toStrictEqual(LinearColorEntity)
expect(parser.parse(`Class'"/Script/Engine.KismetSystemLibrary"'`).constructor)
.toStrictEqual(ObjectReferenceEntity)
expect(parser.parse("(1,2,3,4,5,6,7,8,9)")).toStrictEqual([1, 2, 3, 4, 5, 6, 7, 8, 9])
expect(parser.parse(`( "Hello", "World", )`)).toStrictEqual(["Hello", "World"])
expect(parser.parse(`( "Alpha", 123, Beta, "Gamma", "Delta", 99 )`))
.toStrictEqual(["Alpha", 123, new SymbolEntity({ value: "Beta" }), "Gamma", "Delta", 99])
})
test("UnknownKeysEntity", () => {
const serializer = SerializerFactory.getSerializer(UnknownKeysEntity)
let unknown = serializer.read('LookbehindValue(FirstKey=1,SecondKey=SOME_SYMBOL2,ThirdKey="Hello")')
expect(unknown).toBeInstanceOf(UnknownKeysEntity)
expect(unknown).toMatchObject({
lookbehind: "LookbehindValue",
FirstKey: 1,
SecondKey: new SymbolEntity("SOME_SYMBOL2"),
ThirdKey: "Hello",
})
unknown = serializer.read('(A = (-1,-2,-3), B = SomeFunction(B1 = "b1", B2 = (X=101,Y=102,Z=103)))')
expect(unknown).toBeInstanceOf(UnknownKeysEntity)
expect(unknown).toMatchObject({
A: [-1, -2, -3],
B: new UnknownKeysEntity({
lookbehind: "SomeFunction",
B1: "b1",
B2: new VectorEntity({ X: 101, Y: 102, Z: 103 }),
}),
})
})
test("VectorEntity", () => {
const serializer = SerializerFactory.getSerializer(VectorEntity)
let vector = serializer.read("(X=1,Y=2,Z=3.5)")
expect(vector).toBeInstanceOf(VectorEntity)
expect(vector).toStrictEqual(new VectorEntity({
X: 1,
Y: 2,
Z: 3.5,
}))
vector = serializer.read("(X=10,Y=+20.88,Z=-30.54,)")
expect(vector).toBeInstanceOf(VectorEntity)
expect(vector).toStrictEqual(new VectorEntity({
X: 10,
Y: 20.88,
Z: -30.54,
}))
vector = serializer.read(`(
Z = -3.66 ,
X
= -1 , Y =
-2
,
)`)
expect(vector).toBeInstanceOf(VectorEntity)
expect(vector).toStrictEqual(new VectorEntity({
X: -1,
Y: -2,
Z: -3.66,
}))
expect(() => serializer.read("(X=1,Y=\"2\",Z=3)")).toThrow()
expect(() => serializer.read("(X=1,Z=3)")).toThrow()
expect(() => serializer.read("(X=1,Y=2,Unexpected=6,Z=3.5)")).toThrow()
})
test("Vector2DEntity", () => {
let serializer = SerializerFactory.getSerializer(Vector2DEntity)
let vector = serializer.read("(X=78,Y=56.3)")
expect(vector).toBeInstanceOf(Vector2DEntity)
expect(vector).toStrictEqual(new Vector2DEntity({
X: 78,
Y: 56.3,
}))
vector = serializer.read("(X=+4.5,Y=-8.88,)")
expect(vector).toBeInstanceOf(Vector2DEntity)
expect(vector).toStrictEqual(new Vector2DEntity({
X: 4.5,
Y: -8.88,
}))
vector = serializer.read(`(
Y = +93.004 ,
X
= 0 ,
)`)
expect(vector).toBeInstanceOf(Vector2DEntity)
expect(vector).toStrictEqual(new Vector2DEntity({
X: 0,
Y: 93.004,
}))
expect(() => serializer.read("(X=1,Y=\"2\")")).toThrow()
expect(() => serializer.read("(X=1)")).toThrow()
expect(() => serializer.read("(X=777, Y=555, Unexpected=6, HH=2)")).toThrow()
})

View File

@@ -1,20 +1,13 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import IEntity from "../../js/entity/IEntity.js"
import NumberEntity from "../../js/entity/NumberEntity.js"
export default class Entity1 extends IEntity {
static attributeSeparator = ", "
static wrap = (entity, v) => `Entity1(${v})`
static attributes = {
a: new AttributeInfo({
type: Number,
default: 8,
}),
b: new AttributeInfo({
type: Number,
default: 9,
}),
}
constructor(values = {}) {
super(values)
...super.attributes,
a: NumberEntity.withDefault(type => new type(8)),
b: NumberEntity.withDefault(type => new type(9)),
}
}

View File

@@ -1,21 +1,38 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import ArrayEntity from "../../js/entity/ArrayEntity.js"
import BooleanEntity from "../../js/entity/BooleanEntity.js"
import IEntity from "../../js/entity/IEntity.js"
import NumberEntity from "../../js/entity/NumberEntity.js"
import StringEntity from "../../js/entity/StringEntity.js"
import Entity1 from "./Entity1.js"
export default class Entity2 extends IEntity {
static attributeSeparator = "\n"
static keySeparator = ": "
static printKey = k => ` ${k}`
static wrap = (entity, v) => `{\n${v}\n}`
static attributes = {
someNumber: AttributeInfo.createValue(567),
someString: AttributeInfo.createValue("alpha"),
someString2: AttributeInfo.createValue("beta"),
someBoolean: AttributeInfo.createValue(true),
someBoolean2: AttributeInfo.createValue(false),
someObjectString: AttributeInfo.createValue("gamma"),
someArray: AttributeInfo.createValue([400, 500, 600, 700, 800]),
someArray2: AttributeInfo.createValue(() => [400, 500, 600, 700, 800]),
someEntity: new AttributeInfo({
type: Entity1,
default: new Entity1()
}),
...super.attributes,
someNumber: NumberEntity.withDefault(type => new type(567)),
someString: StringEntity.withDefault(type => new type("alpha")),
someString2: StringEntity.withDefault(type => new type("beta")),
someBoolean: BooleanEntity.withDefault(type => new type(true)),
someBoolean2: BooleanEntity.withDefault(),
someObjectString: StringEntity.withDefault(type => new type("gamma")),
someArray: ArrayEntity.of(NumberEntity).withDefault(type => new type([
new NumberEntity(400),
new NumberEntity(500),
new NumberEntity(600),
new NumberEntity(700),
new NumberEntity(800),
])),
someArray2: ArrayEntity.of(NumberEntity).withDefault(type => new type([
new NumberEntity(-400),
new NumberEntity(-500),
new NumberEntity(-600),
new NumberEntity(-700),
new NumberEntity(-800),
])),
someEntity: Entity1.withDefault(),
}
}

View File

@@ -1,74 +1,58 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import AlternativesEntity from "../../js/entity/AlternativesEntity.js"
import ArrayEntity from "../../js/entity/ArrayEntity.js"
import BooleanEntity from "../../js/entity/BooleanEntity.js"
import IEntity from "../../js/entity/IEntity.js"
import Union from "../../js/entity/Union.js"
import NullEntity from "../../js/entity/NullEntity.js"
import NumberEntity from "../../js/entity/NumberEntity.js"
import StringEntity from "../../js/entity/StringEntity.js"
import Entity1 from "./Entity1.js"
import Entity2 from "./Entity2.js"
export default class Entity3 extends IEntity {
static attributeSeparator = "\n"
static keySeparator = ": "
static printKey = k => ` ${k}`
static wrap = (entity, v) => `[[\n${v}\n]]`
static attributes = {
alpha: AttributeInfo.createValue(32),
bravo: new AttributeInfo({
type: Number,
default: 78,
}),
charlie: new AttributeInfo({
type: String,
default: "Charlie",
}),
delta: new AttributeInfo({
type: String,
default: null,
}),
echo: AttributeInfo.createValue("echo"),
foxtrot: AttributeInfo.createValue(false),
golf: AttributeInfo.createValue([]),
hotel: new AttributeInfo({
type: Array,
default: null,
}),
india: new AttributeInfo({
type: [Number],
default: () => [],
}),
juliett: new AttributeInfo({
type: [String],
default: ["a", "b", "c", "d", "e"],
}),
kilo: new AttributeInfo({
type: [Boolean],
default: () => [true, false, false, true, true],
}),
lima: AttributeInfo.createType(String),
mike: new AttributeInfo({
type: new Union(Number, String, Array),
default: "Bar",
}),
november: new AttributeInfo({
type: new Union(Number, String, Array),
default: 0,
}),
oscar: new AttributeInfo({
type: Entity1,
default: () => new Entity1()
}),
papa: new AttributeInfo({
type: Entity1,
default: () => new Entity1({ a: 12, b: 13 }),
}),
quebec: new AttributeInfo({
default: 0, // will assign undefined because it does not satisfy the predicate
predicate: v => v >= 1 && v <= 10,
}),
romeo: new AttributeInfo({
type: Entity1,
default: new Entity1(),
inlined: true,
}),
sierra: new AttributeInfo({
type: Entity2,
default: new Entity2(),
inlined: true,
}),
...super.attributes,
alpha: NumberEntity.withDefault(type => new type(32)),
bravo: NumberEntity.withDefault(type => new type(78)),
charlie: StringEntity.withDefault(type => new type("Charlie")),
delta: StringEntity.withDefault(type => new NullEntity()),
echo: StringEntity.withDefault(type => new type("echo")),
foxtrot: BooleanEntity.withDefault(),
golf: ArrayEntity.of(StringEntity).withDefault(),
hotel: ArrayEntity.of(NumberEntity).withDefault(() => new NullEntity()),
india: ArrayEntity.of(NumberEntity).withDefault(),
juliett: ArrayEntity.of(StringEntity).withDefault(type => new type([
new StringEntity("a"),
new StringEntity("b"),
new StringEntity("c"),
new StringEntity("d"),
new StringEntity("e"),
])),
kilo: ArrayEntity.of(BooleanEntity).withDefault(type => new type([
new BooleanEntity(true),
new BooleanEntity(),
new BooleanEntity(),
new BooleanEntity(true),
new BooleanEntity(true),
])),
lima: StringEntity,
mike: AlternativesEntity
.accepting(NumberEntity, StringEntity, ArrayEntity)
.withDefault(type => new StringEntity("Bar")),
november: AlternativesEntity
.accepting(NumberEntity, StringEntity, ArrayEntity)
.withDefault(type => new NumberEntity(0)),
oscar: Entity1.withDefault(),
papa: Entity1.withDefault(type => new type({
a: new NumberEntity(12),
b: new NumberEntity(13),
})),
quebec: NumberEntity,
romeo: Entity1.withDefault().flagInlined(),
sierra: Entity2.withDefault().flagInlined(),
}
}

View File

@@ -1,33 +1,23 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import ArrayEntity from "../../js/entity/ArrayEntity.js"
import IEntity from "../../js/entity/IEntity.js"
import NullEntity from "../../js/entity/NullEntity.js"
import NumberEntity from "../../js/entity/NumberEntity.js"
import Entity1 from "./Entity1.js"
import Entity3 from "./Entity3.js"
export default class Entity4 extends IEntity {
static attributeSeparator = "\n"
static keySeparator = " => "
static printKey = k => ` \${${k}}`
static wrap = (entity, v) => `Begin\n${v}\nEnd`
static attributes = {
first: new AttributeInfo({
type: Entity3,
default: new Entity3(),
inlined: true,
}),
second: new AttributeInfo({
default: [new Entity1({ a: 1, b: 2 }), new Entity1({ a: 11, b: 22 })],
inlined: true,
}),
third: new AttributeInfo({
type: Array,
default: null,
})
}
constructor() {
super()
/** @type {Entity1} */ this.second
IEntity.defineAttributes(this.second, {
0: {
inlined: true,
},
})
...super.attributes,
first: Entity3.withDefault().flagInlined(),
second: ArrayEntity.of(Entity1).withDefault(type => new type([
new (Entity1.flagInlined())({ a: new NumberEntity(1), b: new NumberEntity(2) }),
new Entity1({ a: new NumberEntity(11), b: new NumberEntity(22) }),
])).flagInlined(),
third: ArrayEntity.withDefault(() => new NullEntity()),
}
}

View File

@@ -1,19 +0,0 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import IntegerEntity from "../../js/entity/IntegerEntity.js"
import ObjectEntity from "../../js/entity/ObjectEntity.js"
import EntityF from "./EntityF.js"
// @ts-expect-error
export default class Entity5 extends ObjectEntity {
static attributes = {
key1: AttributeInfo.createType(String),
key2: AttributeInfo.createType(EntityF),
key3: new AttributeInfo({
type: IntegerEntity,
default: new IntegerEntity(5),
silent: true,
}),
}
static grammar = this.createGrammar()
}

View File

@@ -1,27 +0,0 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import IEntity from "../../js/entity/IEntity.js"
import Union from "../../js/entity/Union.js"
import Grammar from "../../js/serialization/Grammar.js"
export default class EntityF extends IEntity {
static attributes = {
...super.attributes,
arg1: AttributeInfo.createType(Number),
arg2: AttributeInfo.createType(String),
lookbehind: new AttributeInfo({
...super.attributes.lookbehind,
default: new Union("Foo", "Bar"),
})
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this, false)
}
constructor(values = {}) {
super(values)
}
}

View File

@@ -538,6 +538,32 @@ export default class FlowControlNodes extends NodeTests {
delegate: false,
development: false,
},
{
name: "Sequence",
value: String.raw`
Begin Object Class=/Script/BlueprintGraph.K2Node_ExecutionSequence Name="K2Node_ExecutionSequence_4" ExportPath="/Script/BlueprintGraph.K2Node_ExecutionSequence'/Engine/Maps/Templates/NewWorld.NewWorld:PersistentLevel.NewWorld.EventGraph.K2Node_ExecutionSequence_4'"
NodePosX=496
NodePosY=192
NodeGuid=7E38FFEB6B474D4E80CDA4B4720C9E24
CustomProperties Pin (PinId=2612016B4EAAC152FA9ABB9E23572EE1,PinName="execute",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_26 2658362A4F2BA6A3BE7398A8604FAC6D,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=D665418E47B39BB80A8F02B3951BF0DB,PinName="then_0",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_Timeline_1 ABA55A2B4F3689076D856F921255888F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=A3D98FA145671788536EA1AD2CF5DA61,PinName="then_1",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_Timeline_1 4069CE0043C4948BDE9D17A2FEE8DE0A,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=47D0C212ACF74C57873C7C16B66E0EC6,PinName="then_2",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [8.5, 10],
color: Configuration.nodeColors.gray,
icon: SVGIcon.sequence,
pins: 4,
pinNames: [
"Then 0",
"Then 1",
"Then 2",
],
delegate: false,
development: false,
variadic: true,
},
])
}
}

View File

@@ -41,26 +41,24 @@ export default class IssuesNodes1 extends NodeTests {
delegate: false,
development: false,
additionalTest: async (node, pins, blueprintPage) => {
const relevantPins = (await Promise.all(
pins.map(async p => {
const innerText = await p.innerText()
// @ts-expect-error
return [Configuration.rgba.includes(innerText), p]
})
))
.filter(([flag, value]) => flag)
.map(([flag, value]) => /** @type {Locator<PinElement>} */(value))
expect(await Promise.all(relevantPins.map(async pin => await pin.innerText()))).toStrictEqual(Configuration.rgba)
for (const p of relevantPins) {
const pinName = await p.innerText()
expect(p.locator('input[type="checkbox"]')).toBeChecked({ checked: pinName === "R" })
const relevantPins = []
for (const pin of pins) {
const innerText = await pin.innerText()
if (Configuration.rgba.includes(innerText)) {
relevantPins.push(pin)
}
}
for (const pin of relevantPins) {
const pinName = await pin.innerText()
// Only pin R is checked
await expect(pin.locator('input[type="checkbox"]')).toBeChecked({ checked: pinName === "R" })
}
await relevantPins[0].locator('input[type="checkbox"]').uncheck() // Uncheck "R"
await relevantPins[2].locator('input[type="checkbox"]').check() // Check "B"
await relevantPins[3].locator('input[type="checkbox"]').check() // Check "A"
await relevantPins[2].locator('input[type="checkbox"]').uncheck() // Uncheck "B"
await relevantPins[2].locator('input[type="checkbox"]').check() // Check "B"
expect(node.locator(".ueb-node-name")).toHaveText("Mask ( B A )")
await expect(node.locator(".ueb-node-name")).toHaveText("Mask ( B A )")
const resultSerialization = await blueprintPage.blueprintLocator.evaluate(blueprint => {
blueprint.selectAll()
return blueprint.template.getCopyInputObject().getSerializedText()
@@ -97,6 +95,49 @@ export default class IssuesNodes1 extends NodeTests {
expect(resultSerialization).toMatch(Utility.getFirstWordOrder(words))
}
},
{
name: "Issue 21",
title: "Subtract(1,1)",
value: String.raw`
Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name="MaterialGraphNode_202" ExportPath=/Script/UnrealEd.MaterialGraphNode'/Engine/Transient.卡通:MaterialGraph_0.MaterialGraphNode_202'
Begin Object Class=/Script/Engine.MaterialExpressionSubtract Name="MaterialExpressionSubtract_10" ExportPath=/Script/Engine.MaterialExpressionSubtract'/Engine/Transient.卡通:MaterialGraph_0.MaterialGraphNode_202.MaterialExpressionSubtract_10'
End Object
Begin Object Name="MaterialExpressionSubtract_10" ExportPath=/Script/Engine.MaterialExpressionSubtract'/Engine/Transient.卡通:MaterialGraph_0.MaterialGraphNode_202.MaterialExpressionSubtract_10'
A=(Expression="/Script/Engine.MaterialExpressionSaturate'MaterialGraphNode_237.MaterialExpressionSaturate_3'")
B=(Expression="/Script/Engine.MaterialExpressionSaturate'MaterialGraphNode_201.MaterialExpressionSaturate_7'")
MaterialExpressionEditorX=0
MaterialExpressionEditorY=0
MaterialExpressionGuid=7202C13642DA1225C118CF867599387C
Material="/Script/UnrealEd.PreviewMaterial'/Engine/Transient.卡通'"
End Object
MaterialExpression=/Script/Engine.MaterialExpressionSubtract'MaterialExpressionSubtract_10'
NodePosX=0
NodePosY=0
NodeGuid=7008F5AC49E8F5BFD4C707819A58C021
CustomProperties Pin (PinId=86D4DE5E48C71A576ED0519B982907B3,PinName="A",PinType.PinCategory="optional",PinType.PinSubCategory="red",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="1",LinkedTo=(),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=5C75E1374E1E7436C72B9FA072875C04,PinName="B",PinType.PinCategory="optional",PinType.PinSubCategory="red",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="1",LinkedTo=(),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=528D346A49976B0854764CA755AF2F93,PinName="Output",PinFriendlyName=NSLOCTEXT("MaterialGraphNode", "Space", " "),Direction="EGPD_Output",PinType.PinCategory="",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
`,
size: [8, 6],
color: Configuration.nodeColors.green,
icon: null,
pins: 3,
pinNames: ["A", "B"],
delegate: false,
development: false,
additionalTest: async (node, pins, blueprintPage) => {
await expect(pins[0].locator("ueb-input")).toHaveText("1.0")
await expect(pins[1].locator("ueb-input")).toHaveText("1.0")
let inputs = await node.locator("ueb-input").all()
await inputs[0].fill("-8")
await blueprintPage.blur()
expect(await node.evaluate(n => n.nodeDisplayName)).toEqual("Subtract(-8,1)")
await inputs[1].fill("9.2")
await blueprintPage.blur()
expect(await node.evaluate(n => n.nodeDisplayName)).toEqual("Subtract(-8,9.2)")
}
},
])
}
}

View File

@@ -1,7 +1,7 @@
import Configuration from "../../js/Configuration.js"
import Utility from "../../js/Utility.js"
import PinElement from "../../js/element/PinElement.js"
import IntegerEntity from "../../js/entity/IntegerEntity.js"
import NumberEntity from "../../js/entity/NumberEntity.js"
import RBSerializationVector2DEntity from "../../js/entity/RBSerializationVector2DEntity.js"
import VectorEntity from "../../js/entity/VectorEntity.js"
import { expect } from "../fixtures/test.js"
@@ -70,10 +70,10 @@ export default class MaterialNodes extends NodeTests {
development: false,
additionalTest: async node => {
const value = 10000.0
/** @type {Locator<PinElement<Number>>} */
/** @type {Locator<PinElement<NumberEntity>>} */
const pin = node.locator("ueb-pin").first()
expect(await pin.evaluate(pin => pin.getDefaultValue())).toBeCloseTo(value)
await expect(node.locator("ueb-input")).toHaveText([Utility.printNumber(value)])
expect(await pin.evaluate(pin => pin.getDefaultValue().valueOf())).toBeCloseTo(value)
await expect(node.locator("ueb-input")).toHaveText([NumberEntity.printNumber(value)])
}
},
{
@@ -111,13 +111,13 @@ export default class MaterialNodes extends NodeTests {
additionalTest: async node => {
const x = 0.1
const y = 23.88888
/** @type {Locator<PinElement<Number>>} */
/** @type {Locator<PinElement<NumberEntity>>} */
const xPin = node.locator("ueb-pin").nth(0)
/** @type {Locator<PinElement<Number>>} */
/** @type {Locator<PinElement<NumberEntity>>} */
const yPin = node.locator("ueb-pin").nth(1)
expect(await xPin.evaluate(pin => pin.getDefaultValue())).toBeCloseTo(x)
expect(await yPin.evaluate(pin => pin.getDefaultValue())).toBeCloseTo(y)
await expect(node.locator("ueb-input")).toHaveText([Utility.printNumber(x), Utility.printNumber(y)])
expect(await xPin.evaluate(pin => pin.getDefaultValue().valueOf())).toBeCloseTo(x)
expect(await yPin.evaluate(pin => pin.getDefaultValue().valueOf())).toBeCloseTo(y)
await expect(node.locator("ueb-input")).toHaveText([NumberEntity.printNumber(x), NumberEntity.printNumber(y)])
}
},
{
@@ -157,7 +157,7 @@ export default class MaterialNodes extends NodeTests {
const values = await input.evaluate(pin => pin.getDefaultValue().toArray())
const expected = [0.00432, 123.199997, 7657650176.0]
expected.forEach((v, i) => expect(v).toBeCloseTo(values[i]))
await expect(input.locator("ueb-input")).toHaveText(expected.map(v => Utility.printNumber(v)))
await expect(input.locator("ueb-input")).toHaveText(expected.map(v => NumberEntity.printNumber(v)))
}
},
{
@@ -490,9 +490,7 @@ export default class MaterialNodes extends NodeTests {
color: Configuration.nodeColors.red,
icon: null,
pins: 2,
pinNames: [
"Preview",
],
pinNames: ["Preview"],
delegate: false,
development: false,
},
@@ -520,9 +518,7 @@ export default class MaterialNodes extends NodeTests {
color: Configuration.nodeColors.red,
icon: null,
pins: 2,
pinNames: [
"Preview",
],
pinNames: ["Preview"],
delegate: false,
development: false,
},

View File

@@ -193,11 +193,24 @@ export default class OperationsNodes extends NodeTests {
delegate: false,
development: false,
variadic: true,
additionalTest: async (node, pins) => {
additionalTest: async (node, pins, blueprintPage) => {
for (const pin of pins) {
expect(await pin.evaluate(pin => pin.template.renderIcon().strings.join("")))
.toStrictEqual(SVGIcon.operationPin.strings.join(""))
}
let inputs = await node.locator(".ueb-pin-input").all()
for (const input of inputs) {
expect(await input.isChecked()).toBeFalsy()
}
await inputs[inputs.length - 1].check()
expect(await inputs[inputs.length - 1].isChecked()).toBeTruthy()
const variadic = blueprintPage.node.getByText("Add pin")
await variadic.click()
inputs = await node.locator(".ueb-pin-input").all()
await inputs[inputs.length - 2].uncheck()
for (const input of inputs) {
expect(await input.isChecked()).toBeFalsy()
}
}
},
{
@@ -276,11 +289,21 @@ export default class OperationsNodes extends NodeTests {
delegate: false,
development: false,
variadic: true,
additionalTest: async (node, pins) => {
additionalTest: async (node, pins, blueprintPage) => {
for (const pin of pins) {
expect(await pin.evaluate(pin => pin.template.renderIcon().strings.join("")))
.toStrictEqual(SVGIcon.operationPin.strings.join(""))
}
expect(await pins[0].evaluate(pin => pin.entity.DefaultValue.constructor.serialized)).toBeTruthy()
expect(await pins[1].evaluate(pin => pin.entity.DefaultValue.constructor.serialized)).toBeTruthy()
await pins[0].locator("ueb-input").fill("54")
await blueprintPage.blur()
expect(await pins[0].evaluate(pin => pin.entity.DefaultValue.constructor.serialized)).toBeTruthy()
expect(await pins[0].evaluate(pin => pin.entity.DefaultValue.serialize())).toEqual('"54"')
await pins[1].locator("ueb-input").fill("771")
await blueprintPage.blur()
expect(await pins[1].evaluate(pin => pin.entity.DefaultValue.constructor.serialized)).toBeTruthy()
expect(await pins[1].evaluate(pin => pin.entity.DefaultValue.serialize())).toEqual('"771"')
}
},
{

View File

@@ -570,7 +570,7 @@ export default class OtherNodes extends NodeTests {
await inputs[1].fill("-22.22")
await inputs[2].fill("-33.33")
await blueprintPage.blur()
expect(await pins[2].evaluate(pin => pin.entity.DefaultValue.constructor.name))
expect(await pins[2].evaluate(pin => pin.entity.DefaultValue.constructor.className()))
.toBe("SimpleSerializationVectorEntity")
await expect(pins[2].locator("ueb-input")).toHaveText(["-11.11", "-22.22", "-33.33"])
inputs = await pins[3].locator("ueb-input").all()
@@ -578,18 +578,18 @@ export default class OtherNodes extends NodeTests {
await inputs[1].fill("77")
await inputs[2].fill("66")
await blueprintPage.blur()
expect(await pins[3].evaluate(pin => pin.entity.DefaultValue.constructor.name))
expect(await pins[3].evaluate(pin => pin.entity.DefaultValue.constructor.className()))
.toBe("SimpleSerializationRotatorEntity")
await expect(pins[3].locator("ueb-input")).toHaveText(["88.0", "77.0", "66.0"])
await pins[4].locator("ueb-input").fill("35.814")
await blueprintPage.blur()
expect(await pins[4].evaluate(pin => pin.entity.DefaultValue.constructor.name))
expect(await pins[4].evaluate(pin => pin.entity.DefaultValue.constructor.className()))
.toBe("IntegerEntity")
await expect(pins[4].locator("ueb-input")).toHaveText("35")
await pins[6].locator("input").check()
await expect(pins[6].locator("input")).toBeChecked()
expect(await pins[6].evaluate(pin => pin.entity.DefaultValue.constructor.name))
.toBe("Boolean")
expect(await pins[6].evaluate(pin => pin.entity.DefaultValue.constructor.className()))
.toBe("BooleanEntity")
const serialization = await blueprintPage.getSerializedNodes()
await blueprintPage.removeNodes()
await blueprintPage.paste(serialization)

View File

@@ -0,0 +1,12 @@
export default `{
someNumber: 567
someString: "alpha"
someString2: "beta"
someBoolean: True
someBoolean2: False
someObjectString: "gamma"
someArray: (400,500,600,700,800)
someArray2: (-400,-500,-600,-700,-800)
someEntity.a: 8
someEntity.b: 9
}`

View File

@@ -6,6 +6,6 @@ export default `{
someBoolean2: False
someObjectString: "gamma"
someArray: (400,500,600,700,800)
someArray2: (400,500,600,700,800)
someArray2: (-400,-500,-600,-700,-800)
someEntity: Entity1(a=8, b=9)
}`

View File

@@ -14,7 +14,6 @@ export default `[[
november: 0
oscar: Entity1(a=8, b=9)
papa: Entity1(a=12, b=13)
quebec: 6
romeo.a: 8
romeo.b: 9
sierra.someNumber: 567
@@ -24,6 +23,6 @@ export default `[[
sierra.someBoolean2: False
sierra.someObjectString: "gamma"
sierra.someArray: (400,500,600,700,800)
sierra.someArray2: (400,500,600,700,800)
sierra.someArray2: (-400,-500,-600,-700,-800)
sierra.someEntity: Entity1(a=8, b=9)
]]`

View File

@@ -23,7 +23,7 @@ export default `Begin
\${first.sierra.someBoolean2} => False
\${first.sierra.someObjectString} => "gamma"
\${first.sierra.someArray} => (400,500,600,700,800)
\${first.sierra.someArray2} => (400,500,600,700,800)
\${first.sierra.someArray2} => (-400,-500,-600,-700,-800)
\${first.sierra.someEntity} => E1[A:8 - B:9]
\${second(0).a} => 1
\${second(0).b} => 2

View File

@@ -1,5 +0,0 @@
export default `Begin Object
key1="Value 1"
key2=Foo(arg1=55,arg2="Argument 2")
End Object
`

View File

@@ -51,48 +51,6 @@ test("approximatelyEqual method test", () => {
expect(Utility.approximatelyEqual(2, 3)).toBeFalsy()
})
test("equals method test", () => {
expect(Utility.equals(0.2, 0.2)).toBeTruthy()
// @ts-expect-error
expect(Utility.equals(new Number(0.7), 0.7)).toBeTruthy()
// @ts-expect-error
expect(Utility.equals(-40.3, new Number(-40.3))).toBeTruthy()
// @ts-expect-error
expect(Utility.equals(new Number(-40.3), new Number(-40.3))).toBeTruthy()
expect(Utility.equals(0.2 + 0.1, 0.3)).toBeFalsy() // Strict equality
expect(Utility.equals(null, undefined)).toBeFalsy()
expect(Utility.equals(undefined, null)).toBeFalsy()
expect(Utility.equals(0, false)).toBeFalsy()
expect(Utility.equals(false, false)).toBeTruthy()
expect(Utility.equals(2n, 2)).toBeTruthy()
expect(Utility.equals(-6845, -6845n)).toBeTruthy()
expect(Utility.equals(7735n, 7736)).toBeFalsy()
expect(Utility.equals("abc", "abc")).toBeTruthy()
// @ts-expect-error
expect(Utility.equals(new String("abc"), new String("abc"))).toBeTruthy()
expect(Utility.equals("abc", "aBc")).toBeFalsy()
expect(Utility.equals([], [])).toBeTruthy()
expect(Utility.equals(
[-2, "alpha", new String("beta"), new Number(40), [1, 2, 3]],
[new Number(-2), new String("alpha"), new String("beta"), new Number(40), new Array(1, 2, 3)]
)).toBeTruthy()
expect(Utility.equals(
[-2.1, "alpha", new String("beta"), new Number(40), [1, 2, 3]],
[new Number(-2), new String("alpha"), new String("beta"), new Number(40), new Array(1, 2, 3)]
)).toBeFalsy() // First element is different
expect(Utility.equals(
[-2, "Alpha", new String("beta"), new Number(40), [1, 2, 3]],
[new Number(-2), new String("alpha"), new String("beta"), new Number(40), new Array(1, 2, 3)]
)).toBeFalsy() // Second element is different
})
test("isValueOfType method test", () => {
expect(Utility.isValueOfType(34, Number)).toBeTruthy()
expect(Utility.isValueOfType(new Number(34), Number)).toBeTruthy()
expect(Utility.isValueOfType("34", String)).toBeTruthy()
expect(Utility.isValueOfType("34", Number)).toBeFalsy()
})
test("mergeArrays method test", () => {
expect(Utility.mergeArrays(
[],