Skip to content

Commit

Permalink
Merge pull request #469 from kevin-lee/task/445/add-toSnakeCase
Browse files Browse the repository at this point in the history
Close #445 - [`extras-string`] Add case conversion - `string.toSnakeCase`
  • Loading branch information
kevin-lee authored Oct 25, 2023
2 parents 695dce0 + 735d584 commit fc43323
Show file tree
Hide file tree
Showing 3 changed files with 273 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ object cases extends cases {
head + tail
}

def toSnakeCase: String =
s.split("[\\s_-]+")
.flatMap(_.splitByCase)
.mkString("_")

@SuppressWarnings(Array("org.wartremover.warts.Equals"))
def splitByCase: Vector[String] = {
@scala.annotation.tailrec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object Gens {
tail <- Gen.string(Gen.lower, Range.linear(min - 1, max - 1))
} yield head +: tail

def genFirstLowerCasesThenAllPascalCases(maxLength: Int)(min: Int, max: Int): Gen[List[String]] = {
def genFirstLowerCasesThenAllPascalCases(maxLength: Int)(min: Int, max: Int): Gen[List[String]] =
if (maxLength < 2) {
sys.error(show"maxLength should not be less than 2. maxLength=$maxLength")
} else if (min > max) {
Expand All @@ -31,6 +31,5 @@ object Gens {
} yield first :: rest

}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,34 @@ object StringCaseOpsSpec extends Properties {
testToCamelCaseWithUpperSpaceSeparatedStringValues,
),

// String.toSnakeCase
property(
"test String.toCamelCase with already snake_case",
testToSnakeCaseWithAlreadySnakeCase,
),
property("test String.toSnakeCase with PascalCases", testToSnakeCaseWithPascalCases),
property("test String.toSnakeCase with camelCases", testToSnakeCaseWithCamelCases),
property("test String.toSnakeCase with all UPPERCASE", testToSnakeCaseWithUpperCase),
property("test String.toSnakeCase with all lowercase", testToSnakeCaseWithLowerCase),
property("test String.toSnakeCase with all Snake_Cases", testToSnakeCaseWithSnakeCases),
property("test String.toSnakeCase with all lower_snake_cases", testToSnakeCaseWithLowerSnakeCases),
property("test String.toSnakeCase with all UPPER_SNAKE_CASES", testToSnakeCaseWithUpperSnakeCases),
property("test String.toSnakeCase with all Kebab-Cases", testToSnakeCaseWithKebabCases),
property("test String.toSnakeCase with all lower-kebab-cases", testToSnakeCaseWithLowerKebabCases),
property("test String.toSnakeCase with all UPPER-KEBAB-CASES", testToSnakeCaseWithUpperKebabCases),
property(
"test String.toSnakeCase with all space separated String values",
testToSnakeCaseWithSpaceSeparatedStringValues,
),
property(
"test String.toSnakeCase with all lower space separated String values",
testToSnakeCaseWithLowerSpaceSeparatedStringValues,
),
property(
"test String.toSnakeCase with all UPPER SPACE SEPARATED STRING VALUES",
testToSnakeCaseWithUpperSpaceSeparatedStringValues,
),

// String.SplitByCase
property("test String.SplitByCase with PascalCase", testSplitByCaseWithPascalCase),
property("test String.SplitByCase with PascalCases", testSplitByCaseWithPascalCases),
Expand Down Expand Up @@ -475,6 +503,8 @@ object StringCaseOpsSpec extends Properties {
(actual ==== expected).log(info)
}

///

def testToCamelCaseWithAlreadyCamelCase: Property = for {
expected <- Gen.string(Gen.lower, Range.linear(1, 10)).log("expected")
input <- Gen.constant(expected).log("input")
Expand Down Expand Up @@ -725,4 +755,241 @@ object StringCaseOpsSpec extends Properties {

///

def testToSnakeCaseWithAlreadySnakeCase: Property = for {
expected <- Gen
.string(Gen.lower, Range.linear(1, 10))
.list(Range.linear(1, 10))
.map(_.mkString("_"))
.log("expected")
input <- Gen.constant(expected).log("input")
} yield {
val actual = input.toSnakeCase
actual ==== expected
}

def testToSnakeCaseWithPascalCases: Property = for {
ss <- Gens.genPascalCase(2, 10).list(Range.linear(1, 4)).log("ss")
input <- Gen.constant(ss.mkString).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithCamelCases: Property = for {
s <- Gen.string(Gen.lower, Range.linear(1, 10)).log("s")
ss <- Gens.genPascalCase(2, 10).list(Range.linear(1, 4)).log("ss")
input <- Gen.constant(s + ss.mkString).log("input")
} yield {
val expected = (s :: ss).mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithUpperCase: Property = for {
expected <- Gen.string(Gen.upper, Range.linear(1, 10)).log("expected")
input <- Gen.constant(expected).log("input")
} yield {
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithLowerCase: Property = for {
expected <- Gen.string(Gen.lower, Range.linear(1, 10)).log("expected")
input <- Gen.constant(expected).log("input")
} yield {
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithSnakeCases: Property = for {
ss <- Gens.genPascalCase(1, 10).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant(ss.mkString("_")).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithLowerSnakeCases: Property = for {
ss <- Gen.string(Gen.lower, Range.linear(1, 10)).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant(ss.mkString("_")).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithUpperSnakeCases: Property = for {
ss <- Gen.string(Gen.upper, Range.linear(1, 10)).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant(ss.mkString("_")).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithKebabCases: Property = for {
ss <- Gens.genPascalCase(1, 10).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant(ss.mkString("-")).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithLowerKebabCases: Property = for {
ss <- Gen.string(Gen.lower, Range.linear(1, 10)).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant(ss.mkString("-")).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithUpperKebabCases: Property = for {
ss <- Gen.string(Gen.upper, Range.linear(1, 10)).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant(ss.mkString("-")).log("input")
} yield {
val expected = ss.mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithSpaceSeparatedStringValues: Property = for {
s <- Gens.genPascalCase(1, 10).log("ss")
ss <- Gens.genPascalCase(2, 10).list(Range.linear(1, 4)).log("ss")
input <- Gen.constant((s :: ss).mkString(" ")).log("input")
} yield {
val expected = (s :: ss).mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithLowerSpaceSeparatedStringValues: Property = for {
s <- Gen.string(Gen.lower, Range.linear(1, 10)).log("s")
ss <- Gen.string(Gen.lower, Range.linear(2, 10)).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant((s :: ss).mkString(" ")).log("input")
} yield {
val expected = (s :: ss).mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

def testToSnakeCaseWithUpperSpaceSeparatedStringValues: Property = for {
s <- Gen.string(Gen.upper, Range.linear(1, 10)).log("s")
ss <- Gen.string(Gen.upper, Range.linear(2, 10)).list(Range.linear(1, 5)).log("ss")
input <- Gen.constant((s :: ss).mkString(" ")).log("input")
} yield {
val expected = (s :: ss).mkString("_")
val actual = input.toSnakeCase

val info =
s"""
|> input: $input
|> actual: $actual
|> expected: $expected
|""".stripMargin

(actual ==== expected).log(info)
}

///

}

0 comments on commit fc43323

Please sign in to comment.