javascalatestingapiclient

How do you iterate through each status in scala?


I'm trying to iterate through each status to check if the ArrayList has at least 1 ACTIVE and 1 INACTIVE status.

var active = false;
var inactive = false;
for (item <- reasons.items) {
  if(item.status == "ACTIVE")
    active = true
  if(item.status == "INACTIVE")
    }
active must be (true)
inactive must be (true)

Is there a cleaner way to do this? I've tried with streams like this but no luck

var active = false;      
var stream = reasons.items.toStream
        .forEach(item => if(item.status == "ACTIVE") {active = true})

Note: reasons holds items (There is 1 items). items holds individual items that can be called like reasons.items.get(x).


Solution

  • The other answers explain well how to achieve this using Scala collections. Since it looks like you're using ScalaTest, I wanted to add that you could also use ScalaTest to loop over the elements.

    Using the loop-style syntax from inspectors:

    forAtLeast(1, reasons.items) { item =>
      item.status must be ("ACTIVE")
    }
    
    forAtLeast(1, reasons.items) { item =>
      item.status must be ("INACTIVE")
    }
    

    Note that inspectors are defined separately from matchers, so you'll have to import org.scalatest.Inspectors._ or extends … with org.scalatest.Inspectors to get forAtLeast into scope.

    If you want to avoid the loop-style syntax from inspectors, you can use the inspector shorthand syntax together with the reflection-based have syntax:

    atLeast(1, reasons.items) must have ('status "ACTIVE")
    atLeast(1, reasons.items) must have ('status "INACTIVE")
    

    If you want to avoid the reflection-based syntax for have, you can extend the have syntax to support your status property directly:

    def status(expectedValue: String) =
      new HavePropertyMatcher[Item, String] {
        def apply(item: Item) =
          HavePropertyMatchResult(
            item.status == expectedValue,
            "status",
            expectedValue,
            item.title
          )
      }
    
    atLeast(1, reasons.items) must have (status "ACTIVE")
    atLeast(1, reasons.items) must have (status "INACTIVE")
    

    Or if you prefer be over have, you could extend the be syntax to add support for active and inactive:

    class StatusMatcher(expectedValue: String) extends BeMatcher[Item] {
      def apply(left: Item) =
        MatchResult(
          left.status == expectedValue,
          left.toString + " did not have status " + expectedValue,
          left.toString + " had status " + expectedValue,
        )
    }
    
    val active = new StatusMatcher("ACTIVE")
    val inactive = new statusMatcher("INACTIVE")
    
    atLeast(1, reasons.items) must be (active)
    atLeast(1, reasons.items) must be (inactive)
    

    In the examples here it looks a bit silly to define your own matchers just to save a couple of words in an assertion, but if you write hundreds of tests about the same properties, it can be really convenient to get your assertions down to one line and still be naturally readable. So in my experience, defining your own matchers like this can make sense if you reuse them in a lot of tests.