de.knowwe.uitest.DiaFluxUITest.java Source code

Java tutorial

Introduction

Here is the source code for de.knowwe.uitest.DiaFluxUITest.java

Source

/*
 * Copyright (C) 2015 denkbares GmbH, Germany
 *
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option) any
 * later version.
 *
 * This software is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */

package de.knowwe.uitest;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Rule;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.denkbares.strings.Strings;

import static junit.framework.TestCase.assertEquals;

/**
 * Created by Veronika Sehne, Albrecht Striffler (denkbares GmbH) on 28.01.15.
 * <p>
 * Test the Test Protocol for DiaFlux (System Test - Manual DiaFlux BMI)
 */
public abstract class DiaFluxUITest extends KnowWEUITest {

    public DiaFluxUITest() {
        super();
    }

    @Override
    public String getTestName() {
        return "DiaFlux";
    }

    @Rule
    public UITestUtils.RetryRule retry = new UITestUtils.RetryRule(2);

    @Test
    public void addTerminology() throws IOException {
        changeArticleText(readFile("Step1.txt"));

        checkNoErrorsExist();
    }

    @Test
    public void addFlowchartStumps() throws Exception {
        changeArticleText(readFile("Step2.txt"));

        String article = getDriver().getWindowHandle();

        // first DiaFlux panel
        createNextFlow();
        switchToEditor(article);

        getDriver().findElement(By.id("properties.autostart")).click();

        setFlowName("BMI-Main");
        addStartNode(-150, 300);
        addExitNode(250, 300);

        saveAndSwitchBack(article);

        // second DiaFlux panel
        createNextFlow();
        switchToEditor(article);

        setFlowName("BMI-Anamnesis");

        addStartNode(-150, 300);
        addExitNode(50, 450, "Illegal arguments");
        addExitNode(-100, 600, "Weight ok");
        addExitNode(150, 600, "Weight problem");

        saveAndSwitchBack(article);

        // third DiaFlux panel
        createNextFlow();
        switchToEditor(article);

        setFlowName("BMI-SelectTherapy");
        addStartNode(-150, 300, "Mild therapy");
        addStartNode(-150, 400, "Rigorous therapy");
        addExitNode(50, 350, "Done");

        saveAndSwitchBack(article);

        // third DiaFlux panel
        createNextFlow();
        switchToEditor(article);

        setFlowName("BMI-SelectMode");
        addStartNode(-150, 300);
        addExitNode(50, 450, "Pediatrics");
        addExitNode(150, 450, "Adult");

        saveAndSwitchBack(article);

    }

    @Test
    public void implementBMIMain() throws Exception {
        changeArticleText(readFile("Step3.txt"));

        String articleHandle = getDriver().getWindowHandle();

        openVisualEditor(1);

        switchToEditor(articleHandle);

        addActionNode(-150, 60, "BMI-SelectMode");

        connect(2, 4);
        connect(4, 3, "Pediatrics");

        addActionNode(50, 150, "BMI-Anamnesis"); // 7

        connect(4, 7, "Adult");
        connect(7, 3, "Illegal arguments");
        connect(7, 3, "Weight ok");

        addActionNode(0, 220, "bmi"); // 11

        connect(7, 11, "Weight problem");

        addActionNode(-350, 220, "BMI-SelectTherapy"); // 13
        addActionNode(-350, 320, "BMI-SelectTherapy", "Rigorous therapy"); // 14

        connect(11, 13, "Formula", "gradient(bmi[-7d, 0s]) >= 0 & gradient(bmi[-7d, 0s]) < 5");
        connect(11, 14, "Formula", "gradient(bmi[-7d, 0s]) >= 5");

        addActionNode(0, 280, "Continue selected therapy", "ask"); // 17

        connect(11, 17, "Formula", "gradient(bmi[-7d, 0s]) < 0");

        addSnapshotNode(-10, 340); // 19

        connect(13, 19, "Done");
        connect(14, 19, "Done");
        connect(17, 19);

        connect(19, 7);

        saveAndSwitchBack(articleHandle);

        checkNoErrorsExist();
    }

    @Test
    public void implementBMIAnamnesis() throws Exception {
        changeArticleText(readFile("Step4.txt"));

        String articleHandle = getDriver().getWindowHandle();

        openVisualEditor(2);

        switchToEditor(articleHandle);

        addActionNode(-150, 60, "Height", "ask"); // 6
        addActionNode(50, 60, "Weight", "always ask"); // 7

        connect(2, 6);
        connect(6, 7, "> ", "0");

        addActionNode(-150, 150, "Illegal arguments", "established"); // 10

        connect(6, 10, "= ", "0");
        connect(10, 3);

        addActionNode(50, 250, "bmi", "Formula", "Weight / (Height * Height)"); // 13

        connect(7, 13, "known");

        addActionNode(-350, 250, "Weight classification", "Normal weight"); // 15
        addActionNode(-50, 320, "Weight classification", "Overweight"); // 16
        addActionNode(150, 320, "Weight classification", "Severe overweight"); // 17

        connect(13, 15, "[  ..  [", "18.5", "25");
        connect(13, 16, "[  ..  [", "25", "30");
        connect(13, 17, " ", "30");

        connect(15, 4);
        connect(16, 5);
        connect(17, 5);

        saveAndSwitchBack(articleHandle);

        checkNoErrorsExist();
    }

    @Test
    public void implementBMISelectTherapy() throws Exception {
        changeArticleText(readFile("Step5.txt"));

        String articleHandle = getDriver().getWindowHandle();

        openVisualEditor(3);

        switchToEditor(articleHandle);

        // white spaces to give the auto complete some time
        addActionNode(-150, 60, "Therapy       " + Keys.ARROW_DOWN + Keys.ARROW_DOWN, "Mild therapy"); // 5
        addActionNode(-150, 120, "Therapy       " + Keys.ARROW_DOWN + Keys.ARROW_DOWN, "Rigorous therapy"); // 6

        connect(2, 5);
        connect(3, 6);
        connect(5, 4);
        connect(6, 4);

        saveAndSwitchBack(articleHandle);

        checkNoErrorsExist();
    }

    @Test
    public void implementBMISelectMode() throws Exception {
        changeArticleText(readFile("Step6.txt"));

        String articleHandle = getDriver().getWindowHandle();

        openVisualEditor(4);

        switchToEditor(articleHandle);

        addActionNode(-250, 60, "Age ", "ask"); // 5
        addActionNode(0, 60, "Age classification", "Adult"); // 6
        addActionNode(-250, 120, "Age classification", "Pediatrics"); // 7
        addActionNode(0, 120, "Age classification"); // 8

        connect(2, 5);
        connect(5, 6, "> ", "14");
        connect(5, 7, " ", "14");
        connect(6, 8);
        connect(7, 8);
        connect(8, 3, "Pediatrics");
        connect(8, 4, "Adult");

        saveAndSwitchBack(articleHandle);

        checkNoErrorsExist();
    }

    @Test
    public void testKB1() throws IOException {
        changeArticleText(readFile("Step7.txt"));

        reset();
        setAge("21");
        setHeight("1.9");
        setWeight("90");

        assertBMI("24.930747922437675");

        assertEquals("Adult", getDriver().findElements(By.className("answerClicked")).get(0).getText());
        assertEquals("Normal weight", getDriver().findElements(By.className("answerClicked")).get(1).getText());

        reset();
    }

    @Test
    public void testKB2() throws IOException {
        changeArticleText(readFile("Step7.txt"));

        reset();
        setAge("14");
        setHeight("1.9");
        setWeight("90");

        assertBMI("");
        assertEquals("Pediatrics", getDriver().findElements(By.className("answerClicked")).get(0).getText());
        assertEquals(1, getDriver().findElements(By.className("answerClicked")).size());

        reset();
    }

    @Test
    public void testKB3() throws IOException {
        changeArticleText(readFile("Step7.txt"));

        reset();
        setAge("15");
        setHeight("1.9");
        setWeight("200");

        assertBMI("55.4016620498615");

        assertEquals("Adult", getDriver().findElements(By.className("answerClicked")).get(0).getText());
        assertEquals("Severe overweight", getDriver().findElements(By.className("answerClicked")).get(1).getText());

        reset();
    }

    @Test
    public void testKB4() throws IOException {
        changeArticleText(readFile("Step7.txt"));

        reset();
        setAge("21");
        setHeight("0");

        assertBMI("");

        assertEquals("Adult", getDriver().findElements(By.className("answerClicked")).get(0).getText());
        assertEquals("Illegal arguments",
                getDriver().findElement(By.cssSelector(".SOLUTION-ESTABLISHED a")).getText());
        // solution highlighted
        assertEquals("color: rgb(150, 110, 120);",
                getDriver().findElement(By.cssSelector(".type_Solution .clickable-term")).getAttribute("style"));

        reset();
    }

    // TODO: FIX AND ENABLE AGAIN
    /*@Test
    public void testTraces() throws IOException, InterruptedException {
       changeArticleText(readFile("Step7.txt"));
        
       reset();
        
       showTraces();
        
       // just checking the amount of highlighted nodes and edges...
       assertActiveNodes("BMI-Main", 2, 0);
       assertActiveEdges("BMI-Main", 1, 0);
        
       reset();
       setAge("21");
       setHeight("1.9");
       setWeight("95");
        
       assertActiveNodes("BMI-Main", 2, 4);
       assertActiveEdges("BMI-Main", 1, 5);
        
       assertActiveNodes("BMI-Anamnesis", 3, 3);
       assertActiveEdges("BMI-Anamnesis", 2, 3);
        
       assertActiveNodes("BMI-SelectTherapy", 0, 3);
       assertActiveEdges("BMI-SelectTherapy", 0, 2);
        
       assertActiveNodes("BMI-SelectMode", 0, 5);
       assertActiveEdges("BMI-SelectMode", 0, 4);
    }*/

    @Test
    public void testSpecialChars() throws Exception {
        changeArticleText(readFile("Step8.txt"));

        checkErrorsExist();

        String articleHandle = getDriver().getWindowHandle();

        openVisualEditor(3);

        switchToEditor(articleHandle);

        editActionNode(5, "Therapy ", "" + Keys.ARROW_DOWN);
        editActionNode(6, "Therapy ", "" + Keys.ARROW_DOWN);
        //editActionNode(6, "Therapy       " + Keys.ARROW_DOWN + Keys.ARROW_DOWN, "" + Keys.ARROW_DOWN + Keys.ARROW_DOWN);

        saveAndSwitchBack(articleHandle);

        checkNoErrorsExist();

        openVisualEditor(3);

        switchToEditor(articleHandle);

        setFlowName("BMI-SelectTherapy $`/\\=,!{};:_-");

        editStartNode(2, "Mild therapy $`#/\\\\|=,!{};:_-");
        editStartNode(3, "Rigorous therapy $`#/\\\\|=,!{};:_-");

        addCommentNode(-400, 300, "Here we test a lot of special characters &%$`<#>/\\\\|=,!(){};:_-"); // 11

        new Actions(getDriver()).dragAndDropBy(getDriver().findElement(By.id("#node_3")), -100, 0).perform();
        connect(getDriver().findElement(By.id("#rule_8")).findElement(By.className("rule_selector")), 11);
        connect(11, 6);

        editExitNode(4, "Done $`#/\\|=,!{};:_-");

        saveAndSwitchBack(articleHandle);

        checkErrorsExist();

        openVisualEditor(1);

        switchToEditor(articleHandle);

        editActionNode(13, "BMI-SelectTh", "" + Keys.ARROW_DOWN);
        editActionNode(14, "BMI-SelectTh", "" + Keys.ARROW_DOWN + Keys.ARROW_DOWN);

        editEdge(20, "Done ");
        editEdge(21, "Done ");

        saveAndSwitchBack(articleHandle);

        checkNoErrorsExist();
    }

    // TODO: FIX AND ENABLE AGAIN
    /*
       @Test
       public void testSpecialCharTraces() throws IOException, InterruptedException {
          changeArticleText(readFile("Step9.txt"));
        
          reset();
        
          showTraces();
        
          // just checking the amount of highlighted nodes and edges...
          assertActiveNodes("BMI-Main", 2, 0);
          assertActiveEdges("BMI-Main", 1, 0);
        
          reset();
          setAge("21");
          setHeight("1.9");
          setWeight("95");
        
          assertBMI("26.315789473684212");
          assertEquals("Adult", getDriver().findElements(By.className("answerClicked")).get(0).getText());
          assertEquals("Overweight", getDriver().findElements(By.className("answerClicked")).get(1).getText());
        
          assertActiveNodes("BMI-Main", 2, 4);
          assertActiveEdges("BMI-Main", 1, 5);
        
          assertActiveNodes("BMI-Anamnesis", 3, 3);
          assertActiveEdges("BMI-Anamnesis", 2, 3);
        
          assertActiveNodes("flow_1c072bbf", 0, 4); // BMI-SelectTherapy
          assertActiveEdges("flow_1c072bbf", 0, 3); // BMI-SelectTherapy
        
          assertActiveNodes("BMI-SelectMode", 0, 5);
          assertActiveEdges("BMI-SelectMode", 0, 4);
       }
        
       private void showTraces() throws UnsupportedEncodingException {
          if (getDriver().findElements(By.className("traceActive")).isEmpty()) {
     clickTool("type_DiaFlux", 2, "highlights active nodes");
     new WebDriverWait(getDriver(), 10).until(ExpectedConditions.presenceOfElementLocated(By.className("traceActive")));
          }
       }*/

    private void editEdge(int edgeId, String text) {
        WebElement rule = getDriver().findElement(By.id("#rule_" + edgeId));
        rule.findElement(By.className("rule_selector")).click();
        Select ruleSelect = new Select(rule.findElement(By.tagName("select")));
        try {
            ruleSelect.selectByVisibleText(text);
        } catch (NoSuchElementException e) {
            // selecting by text fails with chrome and special chars... try to match as good as possible
            List<WebElement> options = ruleSelect.getOptions();
            for (WebElement option : options) {
                if (option.getText().startsWith(text)) {
                    String value = option.getAttribute("value");
                    ruleSelect.selectByValue(value);
                    break;
                }
            }
        }
    }

    private void assertActiveNodes(String flow, int expectedActive, int expectedSnap) {
        assertEquals(expectedActive,
                getDriver().findElements(By.cssSelector("#" + flow + " .Node.traceActive")).size());
        assertEquals(expectedSnap,
                getDriver().findElements(By.cssSelector("#" + flow + " .Node.traceSnap")).size());
    }

    private void assertActiveEdges(String flow, int expectedActive, int expectedSnap) {
        int actualActive = 0;
        int actualSnap = 0;
        for (WebElement rule : getDriver().findElements(By.cssSelector("#" + flow + " .Rule"))) {
            if (!rule.findElements(By.className("traceSnap")).isEmpty())
                actualSnap++;
            if (!rule.findElements(By.className("traceActive")).isEmpty())
                actualActive++;
        }
        assertEquals(expectedActive, actualActive);
        assertEquals(expectedSnap, actualSnap);
    }

    private void reset() {
        String currentStatus = UITestUtils.getCurrentStatus(getDriver());
        getDriver().findElement(By.className("reset")).click();
        UITestUtils.awaitStatusChange(getDriver(), currentStatus);
    }

    private void assertBMI(String expected) {
        assertEquals(expected, getDriver().findElements(By.className("numinput")).get(3).getAttribute("value"));
    }

    private void setWeight(String value) {
        setValue(value, 2);
    }

    private void setHeight(String value) {
        setValue(value, 1);
    }

    private void setAge(String value) {
        setValue(value, 0);
    }

    private void setValue(String value, int index) {
        String currentStatus = UITestUtils.getCurrentStatus(getDriver());
        getDriver().findElements(By.className("numinput")).get(index).sendKeys(value + Keys.ENTER);
        UITestUtils.awaitStatusChange(getDriver(), currentStatus);
    }

    private void connect(int sourceId, int targetId, String... text) throws InterruptedException {
        connect(getDriver().findElement(By.id("#node_" + sourceId)), targetId, text);
    }

    private void connect(WebElement source, int targetId, String... text) throws InterruptedException {
        source.click();
        WebElement arrowTool = getDriver().findElement(By.className("ArrowTool"));
        WebElement targetNode = getDriver().findElement(By.id("#node_" + targetId));
        (new Actions(getDriver())).dragAndDrop(arrowTool, targetNode).perform();
        if (text.length > 0) {
            Select select = new Select(getDriver().findElement(By.cssSelector(".selectedRule select")));
            if (text[0].equalsIgnoreCase("formula")) {
                select.selectByIndex(10);
                getDriver().findElement(By.cssSelector(".selectedRule textarea")).sendKeys(text[1] + Keys.ENTER);
            } else {
                switch (text[0]) {
                case "[  ..  ]":
                    select.selectByValue("8");
                    break;
                case "[  ..  [":
                    select.selectByValue("9");
                    break;
                default:
                    select.selectByVisibleText(text[0].trim());
                    break;
                }
                if (text.length > 1) {
                    List<WebElement> inputs = getDriver().findElements(By.cssSelector(".GuardEditor input"));
                    inputs.get(0).sendKeys(text[1]);
                    if (text.length > 2) {
                        inputs.get(1).sendKeys(text[2] + Keys.ENTER);
                    } else {
                        inputs.get(0).sendKeys(Keys.ENTER);
                    }
                }
            }
        }
    }

    private void openVisualEditor(int nth) throws Exception {
        int attempt = 0;
        while (attempt < 5 && getDriver().getWindowHandles().size() == 1) {
            try {
                clickTool("type_DiaFlux", nth, "visual editor");
                Thread.sleep(500);
                attempt++;
            } catch (Exception e) {
                if (attempt == 4) {
                    throw new Exception(e);
                }
            }
        }
    }

    protected void clickTool(String markupClass, int nth, String tooltipContains)
            throws UnsupportedEncodingException {
        WebElement markup = getDriver().findElements(By.className(markupClass)).get(nth - 1);
        WebElement toolMenu = markup.findElement(By.className("headerMenu"));
        WebElement editTool = markup.findElements(By.cssSelector(".markupMenu a.markupMenuItem")).stream()
                .filter(element -> Strings.containsIgnoreCase(element.getAttribute("title"), tooltipContains))
                .findFirst().get();
        if (getDriver() instanceof JavascriptExecutor) {
            List<WebElement> stickyRows = getDriver().findElements(By.className("sticky"));
            JavascriptExecutor jse = (JavascriptExecutor) getDriver();
            for (WebElement row : stickyRows) {
                jse.executeScript("arguments[0].style.display = 'none';", row);
            }
        }
        new Actions(getDriver()).moveToElement(toolMenu).moveToElement(editTool).click(editTool).perform();
    }

    private void createNextFlow() {
        new WebDriverWait(getDriver(), 5)
                .until(ExpectedConditions.presenceOfElementLocated(By.linkText("Click here to create one.")))
                .click();
    }

    private void saveAndSwitchBack(String winHandleBefore) {
        getDriver().findElement(By.id("saveClose")).click();
        getDriver().switchTo().window(winHandleBefore);
        String pageContentSelector = getTemplate() == WikiTemplate.haddock ? ".page-content" : "#pagecontent";
        UITestUtils.awaitRerender(getDriver(), By.cssSelector(pageContentSelector));
    }

    private void addActionNode(int xOffset, int yOffset, String... text) throws InterruptedException {
        addNode(xOffset, yOffset, By.id("decision_prototype"), By.cssSelector(".NodeEditor .ObjectSelect *"), text);
    }

    private void addStartNode(int xOffset, int yOffset, String... text) throws InterruptedException {
        addNode(xOffset, yOffset, By.id("start_prototype"), By.cssSelector(".NodeEditor .startPane input"), text);
    }

    private void addSnapshotNode(int xOffset, int yOffset, String... text) throws InterruptedException {
        addNode(xOffset, yOffset, By.id("snapshot_prototype"), By.cssSelector(".NodeEditor .snapshotPane input"),
                text);
    }

    private void addCommentNode(int xOffset, int yOffset, String... text) throws InterruptedException {
        addNode(xOffset, yOffset, By.id("comment_prototype"), By.cssSelector(".NodeEditor .commentPane textarea"),
                text);
    }

    private void addExitNode(int xOffset, int yOffset, String... text) throws InterruptedException {
        addNode(xOffset, yOffset, By.id("exit_prototype"), By.cssSelector(".NodeEditor .exitPane input"), text);
    }

    private void addNode(int xOffset, int yOffset, By prototypeSelector, By textSelector, String... text)
            throws InterruptedException {
        WebElement start = getDriver().findElement(prototypeSelector);
        new Actions(getDriver()).dragAndDropBy(start, xOffset, yOffset).perform();
        Thread.sleep(200);
        if (text.length > 0) {
            String selector = prototypeSelector.toString();
            if (selector.contains("start") || selector.contains("snapshot") || selector.contains("exit")) { // for decision nodes, editor opens automatically
                List<WebElement> nodes = getDriver().findElements(By.cssSelector(".Flowchart > .Node"));
                WebElement newNode = nodes.get(nodes.size() - 1);
                new Actions(getDriver()).doubleClick(newNode).perform();
            }
            setNodeAttributes(textSelector, text);
        }

    }

    private void editStartNode(int nodeId, String... text) throws InterruptedException {
        editNode(nodeId, By.cssSelector(".NodeEditor .startPane input"), text);
    }

    private void editExitNode(int nodeId, String... text) throws InterruptedException {
        editNode(nodeId, By.cssSelector(".NodeEditor .exitPane input"), text);
    }

    private void editActionNode(int nodeId, String... text) throws InterruptedException {
        editNode(nodeId, By.cssSelector(".NodeEditor .ObjectSelect *"), text);
    }

    private void editNode(int nodeId, By textSelector, String... text) throws InterruptedException {
        new Actions(getDriver()).doubleClick(getDriver().findElement(By.id("#node_" + nodeId))).perform();
        setNodeAttributes(textSelector, text);
    }

    private void setNodeAttributes(By textSelector, String... text) throws InterruptedException {
        getDriver().findElement(textSelector).click();
        getDriver().findElement(textSelector).clear();
        getDriver().findElement(textSelector).sendKeys(text[0]);
        Thread.sleep(200);
        getDriver().findElement(textSelector).sendKeys(Keys.ENTER);
        if (text.length > 1) {
            Select actionSelect = new Select(getDriver().findElement(By.cssSelector(".ActionEditor select")));
            if (text[1].equalsIgnoreCase("formula")) {
                actionSelect.selectByIndex(1);
                //actionSelect.findElement(By.xpath("//option[@value='" + 1 + "']")).click();
                //actionSelect.findElements(By.tagName("option")).get(1).click();
                getDriver().findElement(By.cssSelector(".ActionEditor textarea")).sendKeys(text[2] + Keys.ENTER);
            } else if (text[1].startsWith("" + Keys.ARROW_DOWN)) {
                actionSelect.selectByIndex(text[1].length() - 1);
                //actionSelect.sendKeys(text[1] + Keys.ENTER);
            } else {
                actionSelect.selectByVisibleText(text[1]);
                //actionSelect.findElement(By.xpath("//option[text()='" + text[1] + "']")).click();
            }
        }

        List<WebElement> okButtons = getDriver().findElements(By.cssSelector(".NodeEditor .ok"));
        if (okButtons.size() == 1)
            okButtons.get(0).click();
    }

    private void setFlowName(String flowName) {
        getDriver().findElement(By.id("properties.editName")).clear();
        getDriver().findElement(By.id("properties.editName")).sendKeys(flowName);
    }

    protected void switchToEditor(String articleHandle) throws InterruptedException {
        new WebDriverWait(getDriver(), 10).until((WebDriver driver) -> driver.getWindowHandles().size() == 2);
        Set<String> windowHandles = new HashSet<>(getDriver().getWindowHandles());
        windowHandles.remove(articleHandle);
        getDriver().switchTo().window(windowHandles.iterator().next());
        new WebDriverWait(getDriver(), 10)
                .until(ExpectedConditions.presenceOfElementLocated(By.id("start_prototype")));
    }

}