-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into 714-migrate-nested-paths-may-be-root-paths…
…-rule
- Loading branch information
Showing
5 changed files
with
61 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 13 additions & 12 deletions
25
server/src/main/java/de/zalando/zally/rule/zalando/KebabCaseInPathSegmentsRule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,29 @@ | ||
package de.zalando.zally.rule.zalando | ||
|
||
import de.zalando.zally.rule.api.Check | ||
import de.zalando.zally.rule.api.Context | ||
import de.zalando.zally.rule.api.Rule | ||
import de.zalando.zally.rule.api.Severity | ||
import de.zalando.zally.rule.api.Violation | ||
import de.zalando.zally.util.PatternUtil | ||
import io.swagger.models.Swagger | ||
|
||
@Rule( | ||
ruleSet = ZalandoRuleSet::class, | ||
id = "129", | ||
severity = Severity.MUST, | ||
title = "Lowercase words with hyphens" | ||
ruleSet = ZalandoRuleSet::class, | ||
id = "129", | ||
severity = Severity.MUST, | ||
title = "Lowercase words with hyphens" | ||
) | ||
class KebabCaseInPathSegmentsRule { | ||
|
||
private val description = "Use lowercase separate words with hyphens for path segments" | ||
internal val lowerCaseHyphenSeparatedRegex = """^[a-z-]+$""".toRegex() | ||
|
||
@Check(severity = Severity.MUST) | ||
fun validate(swagger: Swagger): Violation? { | ||
val paths = swagger.paths.orEmpty().keys.filterNot { | ||
val pathSegments = it.split("/").filter { it.isNotEmpty() } | ||
pathSegments.filter { !PatternUtil.isPathVariable(it) && !PatternUtil.isLowerCaseAndHyphens(it) }.isEmpty() | ||
} | ||
return if (paths.isNotEmpty()) Violation(description, paths) else null | ||
} | ||
fun checkKebabCaseInPathSegments(context: Context): List<Violation> = | ||
context.api.paths.orEmpty().entries | ||
.filter { (path, _) -> | ||
path.split("/").filterNot { it.isEmpty() } | ||
.any { segment -> !PatternUtil.isPathVariable(segment) && !segment.matches(lowerCaseHyphenSeparatedRegex) } | ||
} | ||
.map { (_, pathEntry) -> context.violation(description, pathEntry) } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 47 additions & 26 deletions
73
server/src/test/java/de/zalando/zally/rule/zalando/KebabCaseInPathSegmentsRuleTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,69 @@ | ||
package de.zalando.zally.rule.zalando | ||
|
||
import de.zalando.zally.swaggerWithPaths | ||
import io.swagger.models.Swagger | ||
import de.zalando.zally.getOpenApiContextFromContent | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.intellij.lang.annotations.Language | ||
import org.junit.Test | ||
|
||
class KebabCaseInPathSegmentsRuleTest { | ||
|
||
private val testPath1 = "/shipment-order/{shipment_order_id}" | ||
private val testPath2 = "/partner-order/{partner_order_id}" | ||
private val testPath3 = "/partner-order/{partner_order_id}/partner-order/{partner_order_id}" | ||
private val wrongTestPath1 = "/shipment_order/{shipment_order_id}" | ||
private val wrongTestPath2 = "/partner-order/{partner_order_id}/partner-order1/{partner_order_id}" | ||
|
||
private val rule = KebabCaseInPathSegmentsRule() | ||
|
||
@Test | ||
fun emptySwagger() { | ||
assertThat(rule.validate(Swagger())).isNull() | ||
} | ||
fun `checkKebabCaseInPathSegments should return violation for path segments which are not lowercase separate words with hyphens`() { | ||
@Language("YAML") | ||
val spec = """ | ||
openapi: 3.0.1 | ||
paths: | ||
/partnerOrders: {} | ||
""".trimIndent() | ||
val context = getOpenApiContextFromContent(spec) | ||
|
||
@Test | ||
fun validateNormalPath() { | ||
val swagger = swaggerWithPaths(testPath1) | ||
assertThat(rule.validate(swagger)).isNull() | ||
val violations = rule.checkKebabCaseInPathSegments(context) | ||
|
||
assertThat(violations).isNotEmpty | ||
assertThat(violations[0].description).contains("Use lowercase separate words with hyphens") | ||
assertThat(violations[0].pointer.toString()).isEqualTo("/paths/~1partnerOrders") | ||
} | ||
|
||
@Test | ||
fun validateMultipleNormalPaths() { | ||
val swagger = swaggerWithPaths(testPath1, testPath2, testPath3) | ||
assertThat(rule.validate(swagger)).isNull() | ||
fun `checkKebabCaseInPathSegments should return violation for sub resource names which are not lowercase separate words with hyphens`() { | ||
@Language("YAML") | ||
val spec = """ | ||
openapi: 3.0.1 | ||
paths: | ||
/partner-orders/{order-id}/orderItems: {} | ||
""".trimIndent() | ||
val context = getOpenApiContextFromContent(spec) | ||
|
||
val violations = rule.checkKebabCaseInPathSegments(context) | ||
|
||
assertThat(violations).isNotEmpty | ||
assertThat(violations[0].description).contains("Use lowercase separate words with hyphens") | ||
assertThat(violations[0].pointer.toString()).isEqualTo("/paths/~1partner-orders~1{order-id}~1orderItems") | ||
} | ||
|
||
@Test | ||
fun validateFalsePath() { | ||
val swagger = swaggerWithPaths(wrongTestPath1) | ||
val result = rule.validate(swagger)!! | ||
assertThat(result.paths).hasSameElementsAs(listOf(wrongTestPath1)) | ||
fun `checkKebabCaseInPathSegments should return no violation if all segments are lowercase separated words with hyphens`() { | ||
@Language("YAML") | ||
val spec = """ | ||
openapi: 3.0.1 | ||
paths: | ||
/partner-orders/{orderId}/order-items: {} | ||
""".trimIndent() | ||
val context = getOpenApiContextFromContent(spec) | ||
|
||
val violations = rule.checkKebabCaseInPathSegments(context) | ||
|
||
assertThat(violations).isEmpty() | ||
} | ||
|
||
@Test | ||
fun validateMultipleFalsePaths() { | ||
val swagger = swaggerWithPaths(wrongTestPath1, testPath2, wrongTestPath2) | ||
val result = rule.validate(swagger)!! | ||
assertThat(result.paths).hasSameElementsAs(listOf(wrongTestPath1, wrongTestPath2)) | ||
fun `lowerCaseHyphenSeparatedRegex should match lowercase, with hyphen separated words`() { | ||
assertThat("articles".matches(rule.lowerCaseHyphenSeparatedRegex)).isTrue() | ||
assertThat("partner-articles".matches(rule.lowerCaseHyphenSeparatedRegex)).isTrue() | ||
|
||
assertThat("COOL-ARTICLES".matches(rule.lowerCaseHyphenSeparatedRegex)).isFalse() | ||
assertThat("wEirDARtiCles".matches(rule.lowerCaseHyphenSeparatedRegex)).isFalse() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters