package org.jrebirth.af.core.application;

import java.lang.reflect.Field;

import javafx.scene.Node;

import org.jrebirth.af.api.exception.CoreException;
import org.jrebirth.af.api.ui.Model;
import org.jrebirth.af.api.wave.Wave;
import org.jrebirth.af.core.concurrent.JRebirth;
import org.jrebirth.af.core.concurrent.JRebirthThread;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.testfx.api.FxRobot;
import org.testfx.api.FxToolkit;

public class JRebirthApplicationTest<A extends DefaultApplication<?>> extends FxRobot {

    protected A application;

    @SuppressWarnings("unchecked")
    @Before
    public void setUp() throws Exception {
        if (this.application == null) {
            // ApplicationTest.launch(this.appClass);

            this.application = (A) JRebirthThread.getThread().getApplication();
        }
    }

    @After
    public void cleanup() throws Exception {
        FxToolkit.cleanupStages();
    }

    @AfterClass
    public static void close() throws InterruptedException {

        JRebirth.runIntoJAT(() -> {
            try {
                JRebirthThread.getThread().getApplication().stop();
            } catch (final CoreException e) {
                e.printStackTrace();
            }
        });

        while (JRebirthThread.getThread() != null && JRebirthThread.getThread().isAlive()) {
            Thread.sleep(250);
        }
    }

    protected void hold(final long... time) {
        try {
            Thread.sleep(time.length > 0 ? time[0] : 100);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param wave
     */
    protected void waitWave(final Wave wave) {
        while (wave.status() != Wave.Status.Handled) {
            try {
                Thread.sleep(10);
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @param model
     * @throws IllegalAccessException
     */
    protected Node grabInternalNode(final Model model, final String nodeName) {
        try {
            final Field f = model.view().getClass().getDeclaredField(nodeName);
            f.setAccessible(true);
            return (Node) f.get(model.view());

        } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

}

@@ -127,31 +127,119 @@
 api.
-exception.CoreException
+command.Command;%0Aimport org.jrebirth.af.api.exception.CoreException;%0Aimport org.jrebirth.af.api.service.Service
 ;%0Aim
@@ -2554,10 +2554,599 @@
 %0A    %7D%0A%0A
+    /**%0A     * @param model%0A     * @throws IllegalAccessException%0A     */%0A    protected %3CM extends Model%3E M model(final Class%3CM%3E modelClass) %7B%0A        return JRebirthThread.getThread().getFacade().uiFacade().retrieve(modelClass);%0A    %7D%0A%0A    protected %3CS extends Service%3E S service(final Class%3CS%3E serviceClass) %7B%0A        return JRebirthThread.getThread().getFacade().serviceFacade().retrieve(serviceClass);%0A    %7D%0A%0A    protected %3CC extends Command%3E C command(final Class%3CC%3E commandClass) %7B%0A        return JRebirthThread.getThread().getFacade().commandFacade().retrieve(commandClass);%0A    %7D%0A%0A
 %7D%0A

Add convenient method to retrieve components