0

I'm trying to write automated tests for a gui application written in scala with swing. I'm adapting the code from this article which leverages getName() to find the right ui element in the tree.

This is a self-contained version of my code. It's incomplete, untested, and probably broken and/or non-idiomatic and/or suboptimal in various ways, but my question is regarding the compiler error listed below.

import scala.swing._
import java.awt._
import ListView._

import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith
import org.scalatest.FunSpec
import org.scalatest.matchers.ShouldMatchers

object MyGui extends SimpleSwingApplication {
  def top = new MainFrame {
    title = "MyGui"

    val t = new Table(3, 3)
    t.peer.setName("my-table")
    contents = t
  }
}

object TestUtils {
  def getChildNamed(parent: UIElement, name: String): UIElement = {
    // Debug line
    println("Class: " + parent.peer.getClass() +
            " Name: " + parent.peer.getName())

    if (name == parent.peer.getName()) { return parent }

    if (parent.peer.isInstanceOf[java.awt.Container]) {

      val children = parent.peer.getComponents()
      /// COMPILER ERROR HERE   ^^^

      for (child <- children) {
        val matching_child = getChildNamed(child, name)
        if (matching_child != null) { return matching_child }
      }
    }

    return null
  }
}

@RunWith(classOf[JUnitRunner])
class MyGuiSpec extends FunSpec {
  describe("My gui window") {
    it("should have a table") {
      TestUtils.getChildNamed(MyGui.top, "my-table")
    }
  }
}

When I compile this file I get:

29: error: value getComponents is not a member of java.awt.Component
      val children = parent.peer.getComponents()
                                 ^
one error found

As far as I can tell, getComponents is in fact a member of java.awt.Component. I used the code in this answer to dump the methods on parent.peer, and I can see that getComponents is in the list.

Answers that provide another approach to the problem (automated gui testing in a similar manner) are welcome, but I'd really like to understand why I can't access getComponents.

Community
  • 1
  • 1
bstpierre
  • 30,042
  • 15
  • 70
  • 103

1 Answers1

1

The issue is that you're looking at two different classes. Your javadoc link points to java.awt.Container, which indeed has getComponents method. On the other hand, the compiler is looking for getComponents on java.awt.Component (the parent class), which is returned by parent.peer, and can't find it.

Instead of if (parent.peer.isInstanceOf[java.awt.Container]) ..., you can verify the type of parent.peer and cast it like this:

parent.peer match {
      case container: java.awt.Container =>
         // the following works because container isA Container
         val children = container.getComponents
        // ...
      case _ => // ...
}
Alex Yarmula
  • 10,477
  • 5
  • 33
  • 32