QML: Signal isn't being called in a unit test

574 views Asked by At

I'm writing a C++ class ScriptProcess, meant to be used in QML, that acts as an interface to a child process. Said child process loads a script, then executes functions on demand. When you call a function, the result (be it a value or an exception) is returned asynchronously through signals.

import QtQuick 2.5
import QtTest 1.0
import dungeon 1.0

TestCase {
    id: test
    name: "ScriptProcessTest"

    property ScriptProcess session: null

    signal exceptionWhenLoadingCode(string type, int line, string message)

    SignalSpy {
        id: exceptionSpy
        target: test
        signalName: "exceptionWhenLoadingCode"
    }

    Component {
        id: process

        ScriptProcess {
            id: script

            onExceptionWhenLoadingCode: test.exceptionWhenLoadingCode(type, line, message)
        }
    }

    function startScript(scriptUrl) {
        var request = new XMLHttpRequest()
        request.open("GET", "data/%1.js".arg(scriptUrl), false)
        request.send(null)

        return process.createObject(test, {code: request.responseText})
    }

    function cleanup() {
        if (session) {
          session.stop()
        }

        delete session
        session = null
    }

    function test_syntaxErrorInGlobalContextIsReported() {
        var count = exceptionSpy.count
        session = startScript("syntax-error-in-global-context")

        compare(exceptionSpy.count, count + 1)
    }

    function test_errorThrownInGlobalContextIsReported() {
        var count = exceptionSpy.count
        session = startScript("error-in-global-context")

        compare(exceptionSpy.count, count + 1)
    }
}

In a nutshell, I do the following:

  1. For each test, open the auxillary process and load a script from a file. This is done by instantiating a Component, with the script given via the ScriptProcess.code property.
  2. Run the test.
  3. When the test finishes, kill the process and delete the object that manages it.

My problem is that the SignalSpy called exceptionSpy is not being triggered; exceptionSpy.count is always zero, and I have no idea why. Why is this the case? Am I misusing SignalSpy or Component?

1

There are 1 answers

0
jpnurmi On BEST ANSWER

XMLHttpRequest is asynchronous, so you should probably change startScript() to something like:

function startScript(scriptUrl) {
    var object = process.createObject(test)

    var request = new XMLHttpRequest()
    request.onreadystatechange = function() {
        if (request.readyState === XMLHttpRequest.DONE)
            object.code = request.responseText
    }
    request.open("GET", "data/%1.js".arg(scriptUrl), false)
    request.send(null)

    return object
}

And since the signal is not going to be emitted right away, you'll have to wait for it instead of comparing the count immediately after creating the object:

function test_foo() {
    var count = exceptionSpy.count
    session = startScript("...")

    tryCompare(exceptionSpy, "count", count + 1)
}