Skip to content

Commit

Permalink
Common testing error types
Browse files Browse the repository at this point in the history
  • Loading branch information
jedrz committed Feb 25, 2025
1 parent 8401e27 commit fb01ffb
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 114 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package pl.touk.nussknacker.ui.api

import pl.touk.nussknacker.engine.definition.test.TestInfoProvider.TestDataPreparationError
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError.TooManyCharactersGenerated

object TestingApiErrorMessages {

val noSourcesWithTestDataGeneration = "No sources with test data generation available"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import pl.touk.nussknacker.restmodel.BaseEndpointDefinitions
import pl.touk.nussknacker.ui.api.BaseHttpService.CustomAuthorizationError
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError._
import pl.touk.nussknacker.ui.api.description.NodesApiEndpoints.Dtos.ParametersValidationResultDto
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError.NotFoundTestingError._
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError.BadRequestTestingError._
import pl.touk.nussknacker.ui.api.description.NodesApiEndpoints.Dtos.{NodesError, ParametersValidationResultDto}
import pl.touk.nussknacker.ui.api.description.TestingApiEndpoints
import pl.touk.nussknacker.ui.api.utils.ScenarioHttpServiceExtensions
import pl.touk.nussknacker.ui.process.ProcessService
Expand All @@ -20,7 +22,7 @@ import pl.touk.nussknacker.ui.security.api.AuthManager
import pl.touk.nussknacker.ui.validation.ParametersValidator
import sttp.model.StatusCode.{BadRequest, NotFound}
import sttp.tapir.EndpointIO.Example
import sttp.tapir.{Codec, CodecFormat, EndpointOutput, oneOfVariantFromMatchType, plainBody}
import sttp.tapir.{Codec, CodecFormat, EndpointOutput, oneOfVariant, oneOfVariantFromMatchType, plainBody}

import scala.concurrent.{ExecutionContext, Future}

Expand Down Expand Up @@ -157,106 +159,61 @@ object TestingApiHttpService {

object TestingError {

final case class NoScenario(scenarioName: ProcessName) extends TestingError
final case object NoPermission extends TestingError with CustomAuthorizationError
final case object NoDataGenerated extends TestingError
final case object NoSourcesWithTestDataGeneration extends TestingError
final case class TooManyCharactersGenerated(length: Int, limit: Int) extends TestingError
final case class TooManySamplesRequested(maxSamples: Int) extends TestingError
final case object NoPermission extends TestingError with CustomAuthorizationError

implicit val noScenarioCodec: Codec[String, NoScenario, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[NoScenario](e => s"No scenario ${e.scenarioName} found")
}
sealed trait BadRequestTestingError extends TestingError

implicit val noDataGeneratedCodec: Codec[String, NoDataGenerated.type, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[NoDataGenerated.type](_ =>
TestingApiErrorMessages.noDataGenerated
)
}
object BadRequestTestingError {
final case class TooManyCharactersGenerated(length: Int, limit: Int) extends BadRequestTestingError
final case class TooManySamplesRequested(maxSamples: Int) extends BadRequestTestingError

implicit val badRequestTestingErrorCodec: Codec[String, BadRequestTestingError, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[BadRequestTestingError] {
case TooManyCharactersGenerated(length, limit) =>
TestingApiErrorMessages.tooManyCharactersGenerated(length, limit)
case TooManySamplesRequested(maxSamples) =>
TestingApiErrorMessages.requestedTooManySamplesToGenerate(maxSamples)
}
}

implicit val noSourcesWithTestDataGenerationCodec
: Codec[String, NoSourcesWithTestDataGeneration.type, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[NoSourcesWithTestDataGeneration.type](_ =>
TestingApiErrorMessages.noSourcesWithTestDataGeneration
)
}

implicit val tooManyCharactersGeneratedCodec: Codec[String, TooManyCharactersGenerated, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[TooManyCharactersGenerated] {
case TooManyCharactersGenerated(length, limit) =>
TestingApiErrorMessages.tooManyCharactersGenerated(length, limit)
sealed trait NotFoundTestingError extends TestingError

object NotFoundTestingError {
final case class NoScenario(scenarioName: ProcessName) extends NotFoundTestingError
final case object NoDataGenerated extends NotFoundTestingError
final case object NoSourcesWithTestDataGeneration extends NotFoundTestingError

implicit val notFoundTestingErrorCodec: Codec[String, NotFoundTestingError, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[NotFoundTestingError] {
case NoScenario(scenarioName) => s"No scenario ${scenarioName.value} found"
case NoDataGenerated => TestingApiErrorMessages.noDataGenerated
case NoSourcesWithTestDataGeneration => TestingApiErrorMessages.noSourcesWithTestDataGeneration
}
}
}

implicit val tooManySamplesRequestedCodec: Codec[String, TooManySamplesRequested, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[TooManySamplesRequested] {
case TooManySamplesRequested(maxSamples) =>
TestingApiErrorMessages.requestedTooManySamplesToGenerate(maxSamples)
implicit val noScenarioCodec: Codec[String, NoScenario, CodecFormat.TextPlain] = {
BaseEndpointDefinitions.toTextPlainCodecSerializationOnly[NoScenario](e =>
s"No scenario ${e.scenarioName} found"
)
}

}

}

object Examples {

val noScenarioExample: EndpointOutput.OneOfVariant[NoScenario] =
oneOfVariantFromMatchType(
NotFound,
plainBody[NoScenario]
.example(
Example.of(
summary = Some("No scenario {scenarioName} found"),
value = NoScenario(ProcessName("'example scenario'"))
)
)
)

val noDataGeneratedExample: EndpointOutput.OneOfVariant[NoDataGenerated.type] =
oneOfVariantFromMatchType(
NotFound,
plainBody[NoDataGenerated.type]
.example(
Example.of(
summary = Some("No data was generated"),
value = NoDataGenerated
)
)
)
val noScenarioExample: Example[NoScenario] = Example.of(
summary = Some("No scenario {scenarioName} found"),
value = NoScenario(ProcessName("'example scenario'"))
)

val noSourcesWithTestDataGenerationExample: EndpointOutput.OneOfVariant[NoSourcesWithTestDataGeneration.type] =
oneOfVariantFromMatchType(
val noScenarioErrorOutput: EndpointOutput.OneOfVariant[NoScenario] =
oneOfVariant(
NotFound,
plainBody[NoSourcesWithTestDataGeneration.type]
.example(
Example.of(
summary = Some("No sources with test data generation available"),
value = NoSourcesWithTestDataGeneration
)
)
)

val tooManyCharactersGeneratedExample: EndpointOutput.OneOfVariant[TooManyCharactersGenerated] =
oneOfVariantFromMatchType(
BadRequest,
plainBody[TooManyCharactersGenerated]
.example(
Example.of(
summary = Some("Too many characters were generated"),
value = TooManyCharactersGenerated(length = 5000, limit = 2000)
)
)
)

val tooManySamplesRequestedExample: EndpointOutput.OneOfVariant[TooManySamplesRequested] =
oneOfVariantFromMatchType(
BadRequest,
plainBody[TooManySamplesRequested]
.example(
Example.of(
summary = Some("Too many samples requested"),
value = TooManySamplesRequested(maxSamples = 1000)
)
)
plainBody[NoScenario].example(noScenarioExample)
)

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ import pl.touk.nussknacker.security.AuthCredentials
import pl.touk.nussknacker.ui.api.TapirCodecs.ScenarioGraphCodec._
import pl.touk.nussknacker.ui.api.TapirCodecs.ScenarioNameCodec._
import pl.touk.nussknacker.ui.api.TapirCodecs.ScenarioTestingCodecs._
import pl.touk.nussknacker.ui.api.TestingApiHttpService.Examples.{
noDataGeneratedExample,
noScenarioExample,
noSourcesWithTestDataGenerationExample,
tooManyCharactersGeneratedExample,
tooManySamplesRequestedExample
}
import pl.touk.nussknacker.ui.api.TestingApiHttpService.Examples.{noScenarioErrorOutput, noScenarioExample}
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError.BadRequestTestingError.{
TooManyCharactersGenerated,
TooManySamplesRequested
}
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError.{BadRequestTestingError, NotFoundTestingError}
import pl.touk.nussknacker.ui.api.TestingApiHttpService.TestingError.NotFoundTestingError.{
NoDataGenerated,
NoSourcesWithTestDataGeneration
}
import pl.touk.nussknacker.ui.definition.DefinitionsService
import sttp.model.StatusCode.Ok
import sttp.model.StatusCode.{BadRequest, NotFound, Ok}
import sttp.tapir.EndpointIO.Example
import sttp.tapir._
import sttp.tapir.json.circe.jsonBody
Expand Down Expand Up @@ -97,7 +100,7 @@ class TestingApiEndpoints(auth: EndpointInput[AuthCredentials]) extends BaseEndp
)
.errorOut(
oneOf[TestingError](
noScenarioExample,
noScenarioErrorOutput,
)
)
.withSecurity(auth)
Expand Down Expand Up @@ -133,7 +136,7 @@ class TestingApiEndpoints(auth: EndpointInput[AuthCredentials]) extends BaseEndp
)
.errorOut(
oneOf[TestingError](
noScenarioExample
noScenarioErrorOutput
)
)
.withSecurity(auth)
Expand Down Expand Up @@ -172,7 +175,7 @@ class TestingApiEndpoints(auth: EndpointInput[AuthCredentials]) extends BaseEndp
)
.errorOut(
oneOf[TestingError](
noScenarioExample
noScenarioErrorOutput
)
)
.withSecurity(auth)
Expand Down Expand Up @@ -204,11 +207,39 @@ class TestingApiEndpoints(auth: EndpointInput[AuthCredentials]) extends BaseEndp
)
.errorOut(
oneOf[TestingError](
noScenarioExample,
noDataGeneratedExample,
noSourcesWithTestDataGenerationExample,
tooManyCharactersGeneratedExample,
tooManySamplesRequestedExample,
oneOfVariantFromMatchType[NotFoundTestingError](
NotFound,
plainBody[NotFoundTestingError]
.examples(
List(
noScenarioExample,
Example.of(
summary = Some("No data was generated"),
value = NoDataGenerated
),
Example.of(
summary = Some("No sources with test data generation available"),
value = NoSourcesWithTestDataGeneration
)
)
)
),
oneOfVariantFromMatchType[BadRequestTestingError](
BadRequest,
plainBody[BadRequestTestingError]
.examples(
List(
Example.of(
summary = Some("Too many characters were generated"),
value = TooManyCharactersGenerated(length = 5000, limit = 2000)
),
Example.of(
summary = Some("Too many samples requested"),
value = TooManySamplesRequested(maxSamples = 1000)
)
)
)
)
)
)
.withSecurity(auth)
Expand Down
23 changes: 14 additions & 9 deletions docs-internal/api/nu-designer-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3441,11 +3441,13 @@ paths:
content:
text/plain:
schema:
anyOf:
- type: string
- type: string
type: string
examples:
Example:
Example0:
summary: Too many characters were generated
value: 5000 characters were generated, limit is 2000. Please configure
'testDataSettings.testDataMaxLength' to increase the limit
Example1:
summary: Too many samples requested
value: Too many samples requested, limit is 1000. Please configure
'testDataSettings.maxSamplesCount' to increase the limit
Expand Down Expand Up @@ -3477,12 +3479,15 @@ paths:
content:
text/plain:
schema:
anyOf:
- type: string
- type: string
- type: string
type: string
examples:
Example:
Example0:
summary: No scenario {scenarioName} found
value: No scenario 'example scenario' found
Example1:
summary: No data was generated
value: No data was generated
Example2:
summary: No sources with test data generation available
value: No sources with test data generation available
'501':
Expand Down

0 comments on commit fb01ffb

Please sign in to comment.