diff --git a/morphir/src/org/finos/morphir/ir/gen1/naming.scala b/morphir/src/org/finos/morphir/ir/gen1/naming.scala new file mode 100644 index 000000000..aa3e62aa0 --- /dev/null +++ b/morphir/src/org/finos/morphir/ir/gen1/naming.scala @@ -0,0 +1,55 @@ +package org.finos.morphir.ir.gen1 + +object naming extends Names { + + final implicit class PackageNameSyntax(val self: PackageName) extends AnyVal { + def /(moduleName: ModuleName): QualifiedModuleName = QualifiedModuleName(self, moduleName) + } + + final implicit class QualifiedModuleNameSyntax(val self: QualifiedModuleName) extends AnyVal { + def %(localName: String): FQName = FQName(self.packageName, self.modulePath, Name.fromString(localName)) + def %(name: Name): FQName = FQName(self.packageName, self.modulePath, name) + } + + final implicit class NamingHelper(val sc: StringContext) extends AnyVal { + + def fqn(args: Any*): FQName = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + FQName.fromString(interlaced.mkString) + } + + def mod(args: Any*): ModuleName = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + ModuleName.fromString(interlaced.mkString) + } + + def n(args: Any*): Name = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + Name.fromString(interlaced.mkString) + } + + def qmn(args: Any*): QualifiedModuleName = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + QualifiedModuleName.fromString(interlaced.mkString) + } + + def name(args: Any*): Name = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + Name.fromString(interlaced.mkString) + } + + def pkg(args: Any*): PackageName = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + PackageName.fromString(interlaced.mkString) + } + + def path(args: Any*): Path = { + val interlaced = interlace(sc.parts, args.map(_.toString)) + Path.fromString(interlaced.mkString) + } + } + + private[morphir] def interlace[T](a: Iterable[T], b: Iterable[T]): List[T] = + if (a.isEmpty) b.toList + else a.head +: interlace(b, a.tail) +} diff --git a/morphir/test/src/org/finos/morphir/ir/gen1/FQNameSpec.scala b/morphir/test/src/org/finos/morphir/ir/gen1/FQNameSpec.scala index 3f8acf386..caaf43fb6 100644 --- a/morphir/test/src/org/finos/morphir/ir/gen1/FQNameSpec.scala +++ b/morphir/test/src/org/finos/morphir/ir/gen1/FQNameSpec.scala @@ -1,191 +1,23 @@ package org.finos.morphir.ir.gen1 -//import zio.test.Assertion.* -//import zio.test.* -// -//object FQNameSpec extends MorphirSpecDefault { -// def spec = suite("FQNameSpec")( -// suite("Create a FQName:")( -// test("By using a string") { -// assertTrue( -// FQName.fromString("moduleName/packageName/localName", "/") == -// FQName( -// PackageName(Path.fromString("moduleName")), -// ModuleName(Path.fromString("packageName")), -// Name.fromString("localName") -// ) -// ) -// }, -// test("By using a QName with package name") { -// implicit val packageName = PackageName.fromString("package Name") -// val qName = QName(Path.fromString("qualified.Name.Path"), Name.fromString("localName")) -// assertTrue(FQName.fromQName(qName) == FQName(packageName, qName.moduleName, qName.localName)) -// }, -// test("By using a QName without package name using implicit defaults") { -// val pkg = PackageName(Path.fromString("package Name")) -// implicit val default: FQNamingOptions = FQNamingOptions(pkg, ModuleName(Path.fromString("MyModule")), ":") -// val qName = QName(Path.fromString("qualified.Name.Path"), Name.fromString("localName")) -// assertTrue(FQName.fromQName(qName) == FQName(pkg, ModuleName(qName.modulePath), qName.localName)) -// } -// ), -// suite("Retrieving variables should work")( -// test("Get PackagePath") { -// val fqName = FQName.fromString("moduleName/packageName/localName", "/") -// assertTrue(FQName.getPackagePath(fqName) == Path.fromString("moduleName")) -// }, -// test("Get ModulePath") { -// val fqName = FQName.fromString("moduleName/packageName/localName", "/") -// assertTrue(FQName.getModulePath(fqName) == Path.fromString("packageName")) -// }, -// test("Get localName") { -// val fqName = FQName.fromString("moduleName/packageName/localName", "/") -// assertTrue(FQName.getLocalName(fqName) == Name.fromString("localName")) -// } -// ), -// suite("Creating a string from FQName") { -// test("should work") { -// assertTrue( -// FQName.toString( -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("java home")), -// Name.fromString("morphir") -// ) -// ) == "Com.Example:JavaHome:morphir" -// ) -// } -// }, -// suite("Creating FQName from a string")( -// test("3 parameters")( -// assertTrue( -// FQName.fromString("Com.Example:JavaHome:morphir", ":") == -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("3 parameters - different splitter")( -// assertTrue( -// FQName.fromString("Com.Example;JavaHome;morphir", ";") == -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("3 parameters - with implicit FQNamingOptions") { -// implicit val default: FQNamingOptions = FQNamingOptions(PackageName(Path.empty), ModuleName(Path.empty), ";") -// -// assertTrue( -// FQName.fromString("Com.Example;JavaHome;morphir") == -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// }, -// test("2 parameters")( -// assertTrue( -// FQName.fromString("scalaHome:morphir") == -// FQName( -// PackageName(Path.empty), -// ModuleName(Path.fromString("scalaHome")), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("2 parameters - with implicit FQNamingOptions") { -// implicit val default: FQNamingOptions = -// FQNamingOptions(PackageName(Path.fromString("zio.test")), ModuleName(Path.fromString("MyModule")), ";") -// -// assertTrue( -// FQName.fromString("JavaHome;morphir") == -// FQName( -// PackageName(Path.fromString("zio.test")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// }, -// test("1 parameter")( -// assertTrue( -// FQName.fromString("morphir") == FQName( -// PackageName(Path.empty), -// ModuleName(Path.empty), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("1 parameters - with implicit FQNamingOptions") { -// implicit val default: FQNamingOptions = -// FQNamingOptions(PackageName(Path.fromString("zio.test")), ModuleName(Path.fromString("MyModule")), ";") -// -// assertTrue( -// FQName.fromString("morphir") == -// FQName( -// PackageName(Path.fromString("zio.test")), -// ModuleName(Path.fromString("MyModule")), -// Name.fromString("morphir") -// ) -// ) -// }, -// test("empty string - empty path")( -// assertTrue( -// FQName.fromString("") == -// FQName( -// PackageName(Path.empty), -// ModuleName(Path.empty), -// Name.fromString("") -// ) -// ) -// ), -// test("4 or more parameters - throws ParserError")( -// assert(FQName.fromString("abc:bcd:cde:def", ":"))(throwsA[ParserError]) && -// assert(FQName.fromString("abc:bcd:cde:def:efg", ":"))(throwsA[ParserError]) -// ), -// test("other variations for throwing ParserError")( -// assert(FQName.fromString(":", ":"))(throwsA[ParserError]) && -// assert(FQName.fromString(":"))(throwsA[ParserError]) && -// assert(FQName.fromString("-", "-"))(throwsA[ParserError]) && -// assert(FQName.fromString("::", ":"))(throwsA[ParserError]) && -// assert(FQName.fromString("::"))(throwsA[ParserError]) && -// assert(FQName.fromString(";;", ";"))(throwsA[ParserError]) -// ) -// ), -// suite("getModuleName")( -// test("When Path and LocalName are compound") { -// val sut = FQName.fromString(":morphir.sdk:local.date") -// assertTrue( -// sut.getModuleName == QualifiedModuleName(Path.fromString("morphir.sdk"), Name.fromString("LocalDate")) -// ) -// } -// ) -// ) -//} -//package org.finos.morphir.ir -//import org.finos.morphir.naming.* -//import org.finos.morphir.datamodel.namespacing.{PackageName => Pack, *} -//import org.finos.morphir.testing.MorphirSpecDefault -//import zio.test.Assertion.* -//import zio.test.* -// -//object FQNameSpec extends MorphirSpecDefault { -// def spec = suite("FQNameSpec")( -// suite("Create a FQName:")( -// test("By using a string") { -// assertTrue( -// FQName.fromString("moduleName/packageName/localName", "/") == -// FQName( -// PackageName(Path.fromString("moduleName")), -// ModuleName(Path.fromString("packageName")), -// Name.fromString("localName") -// ) -// ) -// }, +import org.finos.morphir.ir.gen1.naming.* +import org.finos.morphir.testing.MorphirSpecDefault +import zio.test.Assertion.* +import zio.test.* + +object FQNameSpec extends MorphirSpecDefault { + def spec = suite("FQNameSpec")( + suite("Create a FQName:")( + test("By using a string") { + assertTrue( + FQName.fromString("moduleName/packageName/localName", "/") == + FQName( + PackageName(Path.fromString("moduleName")), + ModuleName(Path.fromString("packageName")), + Name.fromString("localName") + ) + ) + } // test("By using a QName with package name") { // implicit val packageName = PackageName.fromString("package Name") // val qName = QName(Path.fromString("qualified.Name.Path"), Name.fromString("localName")) @@ -197,135 +29,135 @@ package org.finos.morphir.ir.gen1 // val qName = QName(Path.fromString("qualified.Name.Path"), Name.fromString("localName")) // assertTrue(FQName.fromQName(qName) == FQName(pkg, ModuleName(qName.modulePath), qName.localName)) // } -// ), -// suite("Retrieving variables should work")( -// test("Get PackagePath") { -// val fqName = FQName.fromString("moduleName/packageName/localName", "/") -// assertTrue(FQName.getPackagePath(fqName) == Path.fromString("moduleName")) -// }, -// test("Get ModulePath") { -// val fqName = FQName.fromString("moduleName/packageName/localName", "/") -// assertTrue(FQName.getModulePath(fqName) == Path.fromString("packageName")) -// }, -// test("Get localName") { -// val fqName = FQName.fromString("moduleName/packageName/localName", "/") -// assertTrue(FQName.getLocalName(fqName) == Name.fromString("localName")) -// } -// ), -// suite("Creating a string from FQName") { -// test("should work") { -// assertTrue( -// FQName.toString( -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("java home")), -// Name.fromString("morphir") -// ) -// ) == "Com.Example:JavaHome:morphir" -// ) -// } -// }, -// suite("Creating FQName from a string")( -// test("3 parameters")( -// assertTrue( -// FQName.fromString("Com.Example:JavaHome:morphir", ":") == -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("3 parameters - different splitter")( -// assertTrue( -// FQName.fromString("Com.Example;JavaHome;morphir", ";") == -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("3 parameters - with implicit FQNamingOptions") { -// implicit val default: FQNamingOptions = FQNamingOptions(PackageName(Path.empty), ModuleName(Path.empty), ";") -// -// assertTrue( -// FQName.fromString("Com.Example;JavaHome;morphir") == -// FQName( -// PackageName(Path.fromString("com.example")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// }, -// test("2 parameters")( -// assertTrue( -// FQName.fromString("scalaHome:morphir") == -// FQName( -// PackageName(Path.empty), -// ModuleName(Path.fromString("scalaHome")), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("2 parameters - with implicit FQNamingOptions") { -// implicit val default: FQNamingOptions = -// FQNamingOptions(PackageName(Path.fromString("zio.test")), ModuleName(Path.fromString("MyModule")), ";") -// -// assertTrue( -// FQName.fromString("JavaHome;morphir") == -// FQName( -// PackageName(Path.fromString("zio.test")), -// ModuleName(Path.fromString("JavaHome")), -// Name.fromString("morphir") -// ) -// ) -// }, -// test("1 parameter")( -// assertTrue( -// FQName.fromString("morphir") == FQName( -// PackageName(Path.empty), -// ModuleName(Path.empty), -// Name.fromString("morphir") -// ) -// ) -// ), -// test("1 parameters - with implicit FQNamingOptions") { -// implicit val default: FQNamingOptions = -// FQNamingOptions(PackageName(Path.fromString("zio.test")), ModuleName(Path.fromString("MyModule")), ";") -// -// assertTrue( -// FQName.fromString("morphir") == -// FQName( -// PackageName(Path.fromString("zio.test")), -// ModuleName(Path.fromString("MyModule")), -// Name.fromString("morphir") -// ) -// ) -// }, -// test("empty string - empty path")( -// assertTrue( -// FQName.fromString("") == -// FQName( -// PackageName(Path.empty), -// ModuleName(Path.empty), -// Name.fromString("") -// ) -// ) -// ), + ), + suite("Retrieving variables should work")( + test("Get PackagePath") { + val fqName = FQName.fromString("moduleName/packageName/localName", "/") + assertTrue(FQName.getPackagePath(fqName) == Path.fromString("moduleName")) + }, + test("Get ModulePath") { + val fqName = FQName.fromString("moduleName/packageName/localName", "/") + assertTrue(FQName.getModulePath(fqName) == Path.fromString("packageName")) + }, + test("Get localName") { + val fqName = FQName.fromString("moduleName/packageName/localName", "/") + assertTrue(FQName.getLocalName(fqName) == Name.fromString("localName")) + } + ), + suite("Creating a string from FQName") { + test("should work") { + assertTrue( + FQName.toString( + FQName( + PackageName(Path.fromString("com.example")), + ModuleName(Path.fromString("java home")), + Name.fromString("morphir") + ) + ) == "Com.Example:JavaHome:morphir" + ) + } + }, + suite("Creating FQName from a string")( + test("3 parameters")( + assertTrue( + FQName.fromString("Com.Example:JavaHome:morphir", ":") == + FQName( + PackageName(Path.fromString("com.example")), + ModuleName(Path.fromString("JavaHome")), + Name.fromString("morphir") + ) + ) + ), + test("3 parameters - different splitter")( + assertTrue( + FQName.fromString("Com.Example;JavaHome;morphir", ";") == + FQName( + PackageName(Path.fromString("com.example")), + ModuleName(Path.fromString("JavaHome")), + Name.fromString("morphir") + ) + ) + ), + test("3 parameters - with implicit FQNamingOptions") { + implicit val default: FQNamingOptions = FQNamingOptions(PackageName(Path.empty), ModuleName(Path.empty), ";") + + assertTrue( + FQName.fromString("Com.Example;JavaHome;morphir") == + FQName( + PackageName(Path.fromString("com.example")), + ModuleName(Path.fromString("JavaHome")), + Name.fromString("morphir") + ) + ) + }, + test("2 parameters")( + assertTrue( + FQName.fromString("scalaHome:morphir") == + FQName( + PackageName(Path.empty), + ModuleName(Path.fromString("scalaHome")), + Name.fromString("morphir") + ) + ) + ), + test("2 parameters - with implicit FQNamingOptions") { + implicit val default: FQNamingOptions = + FQNamingOptions(PackageName(Path.fromString("zio.test")), ModuleName(Path.fromString("MyModule")), ";") + + assertTrue( + FQName.fromString("JavaHome;morphir") == + FQName( + PackageName(Path.fromString("zio.test")), + ModuleName(Path.fromString("JavaHome")), + Name.fromString("morphir") + ) + ) + }, + test("1 parameter")( + assertTrue( + FQName.fromString("morphir") == FQName( + PackageName(Path.empty), + ModuleName(Path.empty), + Name.fromString("morphir") + ) + ) + ), + test("1 parameters - with implicit FQNamingOptions") { + implicit val default: FQNamingOptions = + FQNamingOptions(PackageName(Path.fromString("zio.test")), ModuleName(Path.fromString("MyModule")), ";") + + assertTrue( + FQName.fromString("morphir") == + FQName( + PackageName(Path.fromString("zio.test")), + ModuleName(Path.fromString("MyModule")), + Name.fromString("morphir") + ) + ) + }, + test("empty string - empty path")( + assertTrue( + FQName.fromString("") == + FQName( + PackageName(Path.empty), + ModuleName(Path.empty), + Name.fromString("") + ) + ) + ) // test("4 or more parameters - throws ParserError")( // assert(FQName.fromString("abc:bcd:cde:def", ":"))(throwsA[ParserError]) && -// assert(FQName.fromString("abc:bcd:cde:def:efg", ":"))(throwsA[ParserError]) +// assert(FQName.fromString("abc:bcd:cde:def:efg", ":"))(throwsA[ParserError]) // ), // test("other variations for throwing ParserError")( // assert(FQName.fromString(":", ":"))(throwsA[ParserError]) && -// assert(FQName.fromString(":"))(throwsA[ParserError]) && -// assert(FQName.fromString("-", "-"))(throwsA[ParserError]) && -// assert(FQName.fromString("::", ":"))(throwsA[ParserError]) && -// assert(FQName.fromString("::"))(throwsA[ParserError]) && -// assert(FQName.fromString(";;", ";"))(throwsA[ParserError]) +// assert(FQName.fromString(":"))(throwsA[ParserError]) && +// assert(FQName.fromString("-", "-"))(throwsA[ParserError]) && +// assert(FQName.fromString("::", ":"))(throwsA[ParserError]) && +// assert(FQName.fromString("::"))(throwsA[ParserError]) && +// assert(FQName.fromString(";;", ";"))(throwsA[ParserError]) // ) -// ), + ) // suite("getModuleName")( // test("When Path and LocalName are compound") { // val sut = FQName.fromString(":morphir.sdk:local.date") @@ -334,5 +166,5 @@ package org.finos.morphir.ir.gen1 // ) // } // ) -// ) -//} + ) +} diff --git a/morphir/test/src/org/finos/morphir/ir/gen1/NameSpec.scala b/morphir/test/src/org/finos/morphir/ir/gen1/NameSpec.scala index 68c42d9ff..c788d3693 100644 --- a/morphir/test/src/org/finos/morphir/ir/gen1/NameSpec.scala +++ b/morphir/test/src/org/finos/morphir/ir/gen1/NameSpec.scala @@ -1,143 +1,143 @@ package org.finos.morphir.ir.gen1 -import org.finos.morphir.ir.gen1.* +import org.finos.morphir.ir.gen1.naming.* import org.finos.morphir.testing.MorphirSpecDefault import zio.test.* -//object NameSpec extends MorphirSpecDefault { -// def spec = suite("Name")( -// suite("Create a Name from a string and check that:")( -// suite("Name should be creatable from a single word that:")( -// test("Starts with a capital letter") { -// assertTrue(Name.fromString("Marco") == Name("marco")) -// }, -// test("Is all lowercase") { -// assertTrue(Name.fromString("polo") == Name("polo")) -// } -// ), -// suite("Name should be creatable from compound words that:")( -// test("Are formed from a snake case word") { -// assertTrue(Name.fromString("super_mario_world") == Name("super", "mario", "world")) -// }, -// test("Contain many kinds of word delimiters") { -// assertTrue(Name.fromString("fooBar_baz 123") == Name("foo", "bar", "baz", "123")) -// }, -// test("Are formed from a camel-cased string") { -// assertTrue(Name.fromString("valueInUSD") == Name("value", "in", "u", "s", "d")) -// }, -// test("Are formed from a title-cased string") { -// assertTrue( -// Name.fromString("ValueInUSD") == Name("value", "in", "u", "s", "d"), -// Name.fromString("ValueInJPY") == Name("value", "in", "j", "p", "y") -// ) -// }, -// test("Have a number in the middle") { -// assertTrue(Name.fromString("Nintendo64VideoGameSystem") == Name("nintendo", "64", "video", "game", "system")) -// }, -// test("Are complete and utter nonsense") { -// assertTrue(Name.fromString("_-%") == Name.empty) -// } -// ), -// test("It splits the name as expected") { -// // "fooBar","blahBlah" => ["foo","bar","blah","blah"] -// // "fooBar","blahBlah" => ["fooBar","blahBlah"] -// assertTrue( -// Name.fromString("fooBar").toList == List("foo", "bar") -// ) -// } -// ), -// suite("Name should be convertible to a title-case string:")( -// test("When the name was originally constructed from a snake-case string") { -// val sut = Name.fromString("snake_case_input") -// assertTrue(Name.toTitleCase(sut) == "SnakeCaseInput") -// }, -// test( -// "When the name was originally constructed from a camel-case string" -// ) { -// val sut = Name.fromString("camelCaseInput") -// assertTrue(Name.toTitleCase(sut) == "CamelCaseInput") -// } -// ), -// suite("Name should be convertible to a camel-case string:")( -// test( -// "When the name was originally constructed from a snake-case string" -// ) { -// val sut = Name.fromString("snake_case_input") -// assertTrue(Name.toCamelCase(sut) == "snakeCaseInput") -// }, -// test( -// "When the name was originally constructed from a camel-case string" -// ) { -// val sut = Name.fromString("camelCaseInput") -// assertTrue(Name.toCamelCase(sut) == "camelCaseInput") -// } -// ), -// suite("Name should be convertible to snake-case")( -// test("When given a name constructed from a list of words") { -// val input = Name.fromList(List("foo", "bar", "baz", "123")) -// assertTrue(Name.toSnakeCase(input) == "foo_bar_baz_123") -// }, -// test("When the name has parts of an abbreviation") { -// val name = Name.fromList(List("value", "in", "u", "s", "d")) -// assertTrue(Name.toSnakeCase(name) == "value_in_USD") -// } -// ), -// suite("Name should be convertible to kebab-case")( -// test("When given a name constructed from a list of words") { -// val input = Name.fromList(List("foo", "bar", "baz", "123")) -// assertTrue(Name.toKebabCase(input) == "foo-bar-baz-123") -// }, -// test("When the name has parts of an abbreviation") { -// val name = Name.fromList(List("value", "in", "u", "s", "d")) -// assertTrue(Name.toKebabCase(name) == "value-in-USD") -// } -// ), -// suite("Name toHumanWords should provide a list of words from a Name")( -// test("When the name is from a camelCase string") { -// val sut = Name.fromString("ValueInUSD") -// assertTrue(Name.toHumanWords(sut) == List("value", "in", "USD")) -// } -// ), -// suite("fromIterable")( -// test("Splits provided names as expected") { -// assertTrue(Name.fromIterable(List("fooBar", "fizzBuzz")) == Name("foo", "bar", "fizz", "buzz")) -// } -// ), -// suite("Misc")( -// test("Name.toString") { -// assertTrue(Name.fromString("fooBar").toString == "[foo,bar]", Name.fromString("a").toString == "[a]") -// } -// ), -// suite("VariableName")( -// test("When calling VariableName.unapply") { -// val sut = Name.fromString("InspectorGadget") -// val variableName = Name.VariableName.unapply(sut) -// assertTrue(variableName == Some("inspectorGadget")) -// }, -// test("When using as an extractor") { -// val sut = Name.fromString("IronMan") -// val actual = sut match { -// case Name.VariableName(variableName) => variableName -// case _ => "not a variable name" -// } -// assertTrue(actual == "ironMan") -// } -// ), -// suite("String Interpolation")( -// test("When using the n interpolator on a plain string") { -// assertTrue(n"Foo" == Name.fromString("Foo"), n"Foo" == Name.fromList(List("foo"))) -// }, -// test("When using the n interpolator with an int value") { -// val n = 42 -// assertTrue(n"Foo$n" == Name.fromString("Foo42"), n"Foo$n" == Name.fromList(List("foo", "42"))) -// } -// ), -// suite("Operators")( -// suite("+")( -// test("It should support adding a String to a Name") { -// assertTrue(Name.fromString("Foo") + "bar" == Name.fromString("FooBar")) -// } -// ) -// ) -// ) -//} +object NameSpec extends MorphirSpecDefault { + def spec = suite("Name")( + suite("Create a Name from a string and check that:")( + suite("Name should be creatable from a single word that:")( + test("Starts with a capital letter") { + assertTrue(Name.fromString("Marco") == Name("marco")) + }, + test("Is all lowercase") { + assertTrue(Name.fromString("polo") == Name("polo")) + } + ), + suite("Name should be creatable from compound words that:")( + test("Are formed from a snake case word") { + assertTrue(Name.fromString("super_mario_world") == Name("super", "mario", "world")) + }, + test("Contain many kinds of word delimiters") { + assertTrue(Name.fromString("fooBar_baz 123") == Name("foo", "bar", "baz", "123")) + }, + test("Are formed from a camel-cased string") { + assertTrue(Name.fromString("valueInUSD") == Name("value", "in", "u", "s", "d")) + }, + test("Are formed from a title-cased string") { + assertTrue( + Name.fromString("ValueInUSD") == Name("value", "in", "u", "s", "d"), + Name.fromString("ValueInJPY") == Name("value", "in", "j", "p", "y") + ) + }, + test("Have a number in the middle") { + assertTrue(Name.fromString("Nintendo64VideoGameSystem") == Name("nintendo", "64", "video", "game", "system")) + }, + test("Are complete and utter nonsense") { + assertTrue(Name.fromString("_-%") == Name.empty) + } + ), + test("It splits the name as expected") { + // "fooBar","blahBlah" => ["foo","bar","blah","blah"] + // "fooBar","blahBlah" => ["fooBar","blahBlah"] + assertTrue( + Name.fromString("fooBar").toList == List("foo", "bar") + ) + } + ), + suite("Name should be convertible to a title-case string:")( + test("When the name was originally constructed from a snake-case string") { + val sut = Name.fromString("snake_case_input") + assertTrue(Name.toTitleCase(sut) == "SnakeCaseInput") + }, + test( + "When the name was originally constructed from a camel-case string" + ) { + val sut = Name.fromString("camelCaseInput") + assertTrue(Name.toTitleCase(sut) == "CamelCaseInput") + } + ), + suite("Name should be convertible to a camel-case string:")( + test( + "When the name was originally constructed from a snake-case string" + ) { + val sut = Name.fromString("snake_case_input") + assertTrue(Name.toCamelCase(sut) == "snakeCaseInput") + }, + test( + "When the name was originally constructed from a camel-case string" + ) { + val sut = Name.fromString("camelCaseInput") + assertTrue(Name.toCamelCase(sut) == "camelCaseInput") + } + ), + suite("Name should be convertible to snake-case")( + test("When given a name constructed from a list of words") { + val input = Name.fromList(List("foo", "bar", "baz", "123")) + assertTrue(Name.toSnakeCase(input) == "foo_bar_baz_123") + }, + test("When the name has parts of an abbreviation") { + val name = Name.fromList(List("value", "in", "u", "s", "d")) + assertTrue(Name.toSnakeCase(name) == "value_in_USD") + } + ), + suite("Name should be convertible to kebab-case")( + test("When given a name constructed from a list of words") { + val input = Name.fromList(List("foo", "bar", "baz", "123")) + assertTrue(Name.toKebabCase(input) == "foo-bar-baz-123") + }, + test("When the name has parts of an abbreviation") { + val name = Name.fromList(List("value", "in", "u", "s", "d")) + assertTrue(Name.toKebabCase(name) == "value-in-USD") + } + ), + suite("Name toHumanWords should provide a list of words from a Name")( + test("When the name is from a camelCase string") { + val sut = Name.fromString("ValueInUSD") + assertTrue(Name.toHumanWords(sut) == List("value", "in", "USD")) + } + ), + suite("fromIterable")( + test("Splits provided names as expected") { + assertTrue(Name.fromIterable(List("fooBar", "fizzBuzz")) == Name("foo", "bar", "fizz", "buzz")) + } + ), + suite("Misc")( + test("Name.toString") { + assertTrue(Name.fromString("fooBar").toString == "[foo,bar]", Name.fromString("a").toString == "[a]") + } + ), + suite("VariableName")( + test("When calling VariableName.unapply") { + val sut = Name.fromString("InspectorGadget") + val variableName = Name.VariableName.unapply(sut) + assertTrue(variableName == Some("inspectorGadget")) + }, + test("When using as an extractor") { + val sut = Name.fromString("IronMan") + val actual = sut match { + case Name.VariableName(variableName) => variableName + case _ => "not a variable name" + } + assertTrue(actual == "ironMan") + } + ), + suite("String Interpolation")( + test("When using the n interpolator on a plain string") { + assertTrue(n"Foo" == Name.fromString("Foo"), n"Foo" == Name.fromList(List("foo"))) + }, + test("When using the n interpolator with an int value") { + val n = 42 + assertTrue(n"Foo$n" == Name.fromString("Foo42"), n"Foo$n" == Name.fromList(List("foo", "42"))) + } + ), + suite("Operators")( + suite("+")( + test("It should support adding a String to a Name") { + assertTrue(Name.fromString("Foo") + "bar" == Name.fromString("FooBar")) + } + ) + ) + ) +} diff --git a/morphir/test/src/org/finos/morphir/ir/gen1/PathSpec.scala b/morphir/test/src/org/finos/morphir/ir/gen1/PathSpec.scala index 5abc98a66..963b844fa 100644 --- a/morphir/test/src/org/finos/morphir/ir/gen1/PathSpec.scala +++ b/morphir/test/src/org/finos/morphir/ir/gen1/PathSpec.scala @@ -1,114 +1,115 @@ package org.finos.morphir.ir.gen1 +import org.finos.morphir.ir.gen1.naming.* import org.finos.morphir.testing.MorphirSpecDefault import zio.test.* -//object PathSpec extends MorphirSpecDefault { -// def spec = suite("Path")( -// suite("Creating a Path from a String")( -// test("It can be constructed from a simple string") { -// assertTrue(Path.fromString("Person") == Path(n"person")) -// }, -// test("It can be constructed from a long string") { -// assertTrue(Path.fromString("She Sells Seashells") == Path(n"she sells seashells")) -// }, -// test("It can be constructed when given a dotted string") { -// assertTrue(Path.fromString("blog.Author") == Path(n"blog", n"author")) -// }, -// test("It can be constructed when given a '-' separated string") { -// assertTrue(Path.fromString("blog-Author") == Path(n"blog", Name.fromList(List("author")))) -// }, -// test("It can be constructed when given a '/' separated string") { -// assertTrue(Path.fromString("blog/Author") == Path(Name.fromList("blog"), Name.fromList("author"))) -// }, -// test("It can be constructed when given a '\' separated string") { -// assertTrue(Path.fromString("blog\\Author") == Path(n"blog", n"author")) -// }, -// test("It can be constructed when given a ':' separated string") { -// assertTrue(Path.fromString("Morphir:SDK") == Path(n"Morphir", n"SDK")) -// }, -// test("It can be constructed when given a ';' separated string") { -// assertTrue(Path.fromString("Blog ; Author") == Path(n"blog", n"author")) -// }, -// test("It can be constructed from Name arguments") { -// assertTrue( -// Path(Name.fromString("projectfiles"), Name.fromString("filePath")) == Path.fromList( -// List(Name.fromList(List("projectfiles")), Name.fromList(List("file", "path"))) -// ) -// ) -// }, -// test("It can be constructed from string arguments") { -// assertTrue( -// Path("myCompany", "some Type") == Path.fromList( -// Name.fromList("my", "company"), -// Name.fromList("some", "type") -// ) -// ) -// } -// ), -// suite("Transforming a Path into a String")( -// test("Paths with period and TitleCase") { -// val input = Path( -// Name("foo", "bar"), -// Name("baz") -// ) -// assertTrue(Path.toString(Name.toTitleCase, ".", input) == "FooBar.Baz") -// }, -// test("Paths with slash and Snake_Case") { -// val input = Path( -// Name("foo", "bar"), -// Name("baz") -// ) -// assertTrue(Path.toString(Name.toSnakeCase, "/", input) == "foo_bar/baz") -// } -// ), -// suite("Transforming a Path into list of Names")( -// test("It can be constructed using toList") { -// assertTrue( -// Path.toList(Path(Name("Com", "Example"), Name("Hello", "World"))) == List( -// Name("Com", "Example"), -// Name("Hello", "World") -// ) -// ) -// } -// ), -// suite("Creating a Path from a Name")( -// test("It can be constructed from names")( -// assertTrue( -// Path.root / Name("Org") / Name("Finos") == Path(Vector(Name("Org"), Name("Finos"))), -// Path.root / Name("Alpha") / Name("Beta") / Name("Gamma") == Path(Vector( -// Name("Alpha"), -// Name("Beta"), -// Name("Gamma") -// )) -// ) -// ) -// ), -// suite("Checking if one Path is a prefix of another should:")( -// test("""Return true: Given path is "foo/bar" and prefix is "foo" """) { -// val sut = Path.fromString("foo/bar") -// val prefix = Path.fromString("foo") -// -// assertTrue(Path.isPrefixOf(prefix = prefix, path = sut)) -// }, -// test("""Return false: Given path is "foo/foo" and prefix is "bar" """) { -// val sut = Path.fromString("foo/foo") -// val prefix = Path.fromString("bar") -// -// assertTrue(!Path.isPrefixOf(prefix = prefix, path = sut)) -// }, -// test("""Return true: Given equal paths""") { -// val sut = Path.fromString("foo/bar/baz") -// val prefix = sut -// assertTrue(Path.isPrefixOf(prefix = prefix, path = sut)) -// } -// ), -// suite("ToString")( -// test("The standard to String should return a String representation of the path using the default PathRenderer")( -// assertTrue( -// Path.fromString("foo/bar/baz").toString == "Foo.Bar.Baz" -// ) -// ) -// ) -// ) -//} +object PathSpec extends MorphirSpecDefault { + def spec = suite("Path")( + suite("Creating a Path from a String")( + test("It can be constructed from a simple string") { + assertTrue(Path.fromString("Person") == Path(n"person")) + }, + test("It can be constructed from a long string") { + assertTrue(Path.fromString("She Sells Seashells") == Path(n"she sells seashells")) + }, + test("It can be constructed when given a dotted string") { + assertTrue(Path.fromString("blog.Author") == Path(n"blog", n"author")) + }, + test("It can be constructed when given a '-' separated string") { + assertTrue(Path.fromString("blog-Author") == Path(n"blog", Name.fromList(List("author")))) + }, + test("It can be constructed when given a '/' separated string") { + assertTrue(Path.fromString("blog/Author") == Path(Name.fromList("blog"), Name.fromList("author"))) + }, + test("It can be constructed when given a '\' separated string") { + assertTrue(Path.fromString("blog\\Author") == Path(n"blog", n"author")) + }, + test("It can be constructed when given a ':' separated string") { + assertTrue(Path.fromString("Morphir:SDK") == Path(n"Morphir", n"SDK")) + }, + test("It can be constructed when given a ';' separated string") { + assertTrue(Path.fromString("Blog ; Author") == Path(n"blog", n"author")) + }, + test("It can be constructed from Name arguments") { + assertTrue( + Path(Name.fromString("projectfiles"), Name.fromString("filePath")) == Path.fromList( + List(Name.fromList(List("projectfiles")), Name.fromList(List("file", "path"))) + ) + ) + }, + test("It can be constructed from string arguments") { + assertTrue( + Path("myCompany", "some Type") == Path.fromList( + Name.fromList("my", "company"), + Name.fromList("some", "type") + ) + ) + } + ), + suite("Transforming a Path into a String")( + test("Paths with period and TitleCase") { + val input = Path( + Name("foo", "bar"), + Name("baz") + ) + assertTrue(Path.toString(Name.toTitleCase, ".", input) == "FooBar.Baz") + }, + test("Paths with slash and Snake_Case") { + val input = Path( + Name("foo", "bar"), + Name("baz") + ) + assertTrue(Path.toString(Name.toSnakeCase, "/", input) == "foo_bar/baz") + } + ), + suite("Transforming a Path into list of Names")( + test("It can be constructed using toList") { + assertTrue( + Path.toList(Path(Name("Com", "Example"), Name("Hello", "World"))) == List( + Name("Com", "Example"), + Name("Hello", "World") + ) + ) + } + ), + suite("Creating a Path from a Name")( + test("It can be constructed from names")( + assertTrue( + Path.root / Name("Org") / Name("Finos") == Path(Vector(Name("Org"), Name("Finos"))), + Path.root / Name("Alpha") / Name("Beta") / Name("Gamma") == Path(Vector( + Name("Alpha"), + Name("Beta"), + Name("Gamma") + )) + ) + ) + ), + suite("Checking if one Path is a prefix of another should:")( + test("""Return true: Given path is "foo/bar" and prefix is "foo" """) { + val sut = Path.fromString("foo/bar") + val prefix = Path.fromString("foo") + + assertTrue(Path.isPrefixOf(prefix = prefix, path = sut)) + }, + test("""Return false: Given path is "foo/foo" and prefix is "bar" """) { + val sut = Path.fromString("foo/foo") + val prefix = Path.fromString("bar") + + assertTrue(!Path.isPrefixOf(prefix = prefix, path = sut)) + }, + test("""Return true: Given equal paths""") { + val sut = Path.fromString("foo/bar/baz") + val prefix = sut + assertTrue(Path.isPrefixOf(prefix = prefix, path = sut)) + } + ), + suite("ToString")( + test("The standard to String should return a String representation of the path using the default PathRenderer")( + assertTrue( + Path.fromString("foo/bar/baz").toString == "Foo.Bar.Baz" + ) + ) + ) + ) +} diff --git a/morphir/test/src/org/finos/morphir/ir/gen1/QNameSpec.scala b/morphir/test/src/org/finos/morphir/ir/gen1/QNameSpec.scala index e60d96b4e..7ab1a96ed 100644 --- a/morphir/test/src/org/finos/morphir/ir/gen1/QNameSpec.scala +++ b/morphir/test/src/org/finos/morphir/ir/gen1/QNameSpec.scala @@ -1,54 +1,55 @@ package org.finos.morphir.ir.gen1 +import org.finos.morphir.ir.gen1.naming.* import org.finos.morphir.testing.MorphirSpecDefault import zio.test.* -//object QNameSpec extends MorphirSpecDefault { -// def spec = suite("QName")( -// suite("Creating a tuple from QName")( -// test("toTuple should provide the Path and Name as a tuple") { -// val path = Path.fromString("ice.cream") -// val name = Name.fromString("float") -// val expected = (path, name) -// assertTrue(QName(path, name).toTuple == expected) -// } -// ), -// suite("Creating a QName")( -// test("Creating a QName with a tuple") { -// val path = Path.fromString("friday") -// val name = Name.fromString("night") -// assertTrue(QName.fromTuple((path, name)) == QName(path, name)) -// }, -// test("Creating a QName from a name") { -// val path = Path.fromString("blog.Author") -// val name = Name.fromString("book") -// assertTrue(QName.fromName(path, name) == QName(path, name)) -// } -// ), -// suite("Fetching values from QName")( -// test("localName and path") { -// val path = Path.fromString("path") -// val name = Name.fromString("name") -// assertTrue( -// QName.getLocalName(QName(path, name)) == name, -// QName.getModulePath(QName(path, name)) == path -// ) -// } -// ), -// suite("QName and Strings")( -// test("Create String from QName") { -// val path = Path.fromString("front.page") -// val name = Name.fromString("dictionary words") -// assertTrue(QName(path, name).toString == "Front.Page:dictionaryWords") -// }, -// test("Create QName from String") { -// val str = "Proper.Path:name" -// assertTrue(QName.fromString(str) == Some(QName(Path.fromString("Proper.Path"), Name.fromString("name")))) -// }, -// test("Provide an invalid String") { -// val str2 = "invalidpathname" -// assertTrue(QName.fromString(str2) == None) -// } -// ) -// ) -//} +object QNameSpec extends MorphirSpecDefault { + def spec = suite("QName")( + suite("Creating a tuple from QName")( + test("toTuple should provide the Path and Name as a tuple") { + val path = Path.fromString("ice.cream") + val name = Name.fromString("float") + val expected = (path, name) + assertTrue(QName(path, name).toTuple == expected) + } + ), + suite("Creating a QName")( + test("Creating a QName with a tuple") { + val path = Path.fromString("friday") + val name = Name.fromString("night") + assertTrue(QName.fromTuple((path, name)) == QName(path, name)) + }, + test("Creating a QName from a name") { + val path = Path.fromString("blog.Author") + val name = Name.fromString("book") + assertTrue(QName.fromName(path, name) == QName(path, name)) + } + ), + suite("Fetching values from QName")( + test("localName and path") { + val path = Path.fromString("path") + val name = Name.fromString("name") + assertTrue( + QName.getLocalName(QName(path, name)) == name, + QName.getModulePath(QName(path, name)) == path + ) + } + ), + suite("QName and Strings")( + test("Create String from QName") { + val path = Path.fromString("front.page") + val name = Name.fromString("dictionary words") + assertTrue(QName(path, name).toString == "Front.Page:dictionaryWords") + }, + test("Create QName from String") { + val str = "Proper.Path:name" + assertTrue(QName.fromString(str) == Some(QName(Path.fromString("Proper.Path"), Name.fromString("name")))) + }, + test("Provide an invalid String") { + val str2 = "invalidpathname" + assertTrue(QName.fromString(str2) == None) + } + ) + ) +}