/*******************************************************************************
* Copyright 2017 Ivan Shubin http://galenframework.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.galenframework.tests.speclang2.pagespec;
import com.galenframework.page.selenium.SeleniumPage;
import com.galenframework.parser.SyntaxException;
import com.galenframework.speclang2.pagespec.PageSpecReader;
import com.galenframework.specs.Place;
import com.galenframework.specs.page.CorrectionsRect;
import com.galenframework.specs.page.PageSection;
import com.galenframework.browser.SeleniumBrowser;
import com.galenframework.components.mocks.driver.MockedDriver;
import com.galenframework.components.validation.MockedPage;
import com.galenframework.page.PageElement;
import com.galenframework.specs.page.Locator;
import com.galenframework.specs.page.ObjectSpecs;
import com.galenframework.specs.page.PageSpec;
import com.galenframework.speclang2.pagespec.SectionFilter;
import org.testng.annotations.Test;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import static java.util.Arrays.asList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
public class PageSpecReaderTest extends PageSpecReaderTestBase {
@Test
public void shouldRead_objectDefinitions() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-definitions.gspec");
assertThat(pageSpec.getObjects(), is((Map<String, Locator>)new HashMap<String, Locator>(){{
put("header", new Locator("css", "#header"));
put("header-icon", new Locator("css", "#header img"));
put("button", new Locator("xpath", "//div[@id='button']"));
put("cancel-link", new Locator("id", "cancel"));
put("caption", new Locator("css", "#wrapper")
.withCorrections(new CorrectionsRect(
new CorrectionsRect.Correction(0, CorrectionsRect.Type.PLUS),
new CorrectionsRect.Correction(100, CorrectionsRect.Type.PLUS),
new CorrectionsRect.Correction(5, CorrectionsRect.Type.MINUS),
new CorrectionsRect.Correction(7, CorrectionsRect.Type.PLUS)
)));
}}));
}
@Test
public void shouldRead_objectDefinitions_withMultiObjects() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-definitions-multi-objects.gspec",
new SeleniumBrowser(new MockedDriver("/speclang2/mocks/menu-items.json")).getPage(), asList("mobile"), EMPTY_TAGS);
assertThat(pageSpec.getObjects(), is((Map<String, Locator>)new HashMap<String, Locator>(){{
put("menu-item-1", new Locator("css", "#menu li", 1));
put("menu-item-2", new Locator("css", "#menu li", 2));
put("menu-item-3", new Locator("css", "#menu li", 3));
put("menu-item-4", new Locator("css", "#menu li", 4));
}}));
}
@Test
public void shouldRead_objectDefinitions_withMultiLevelObjects() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-definitions-multi-level-objects.gspec",
new SeleniumBrowser(new MockedDriver("/speclang2/mocks/multi-level-objects.json")).getPage(), asList("mobile"), EMPTY_TAGS);
assertThat(pageSpec.getObjects(), is((Map<String, Locator>)new HashMap<String, Locator>(){{
put("header", new Locator("css", "#header"));
put("header.icon", new Locator("css", "img")
.withParent(new Locator("css", "#header")));
put("header.item-1", new Locator("css", "li", 1).withParent(new Locator("css", "#header")));
put("header.item-2", new Locator("css", "li", 2).withParent(new Locator("css", "#header")));
put("box-1", new Locator("css", ".box", 1));
put("box-1.caption", new Locator("css", ".caption")
.withParent(new Locator("css", ".box", 1)));
put("box-2", new Locator("css", ".box", 2));
put("box-2.caption", new Locator("css", ".caption")
.withParent(new Locator("css", ".box", 2)));
put("box-3", new Locator("css", ".box", 3));
put("box-3.caption", new Locator("css", ".caption")
.withParent(new Locator("css", ".box", 3)));
}}));
}
@Test
public void shouldRead_objectDefinitions_withJsBlocks() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/objects-with-js-blocks.gspec");
assertThat(pageSpec.getObjects(), is((Map<String, Locator>)new HashMap<String, Locator>(){{
put("header_caption", new Locator("css", ".some-header h1"));
}}));
}
@Test
public void shouldRead_sectionsWithObjectSpecs() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/sections-with-object-specs.gspec");
assertThat(pageSpec.getSections().size(), is(2));
PageSection section1 = pageSpec.getSections().get(0);
assertThat(section1.getObjects().size(), is(1));
assertThat(section1.getObjects().get(0).getObjectName(), is("header"));
assertThat(section1.getObjects().get(0).getSpecs().size(), is(1));
assertThat(section1.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("height 100px"));
assertThat(section1.getSections().size(), is(1));
PageSection subSection = section1.getSections().get(0);
assertThat(subSection.getObjects().size(), is(2));
assertThat(subSection.getObjects().get(0).getObjectName(), is("login-link"));
assertThat(subSection.getObjects().get(0).getSpecs().size(), is(1));
assertThat(subSection.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("height 30px"));
assertThat(subSection.getObjects().get(1).getObjectName(), is("register-link"));
assertThat(subSection.getObjects().get(1).getSpecs().size(), is(1));
assertThat(subSection.getObjects().get(1).getSpecs().get(0).getOriginalText(), is("right-of login-link 10 to 30px"));
PageSection section2 = pageSpec.getSections().get(1);
assertThat(section2.getName(), is("Main section"));
assertThat(section2.getObjects().size(), is(1));
assertThat(section2.getObjects().get(0).getObjectName(), is("main-section"));
assertThat(section2.getObjects().get(0).getSpecs().size(), is(2));
assertThat(section2.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("below header 0 to 5px"));
assertThat(section2.getObjects().get(0).getSpecs().get(1).getOriginalText(), is("inside screen 0px left right"));
}
@Test
public void shouldProcess_complexObjectExpressions_insideSections() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/complex-object-expressions.gspec");
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getName(), is("Main section"));
assertThat(section.getObjects().size(), is(6));
assertThat(section.getPlace(), is(new Place("speclang2/complex-object-expressions.gspec", 16)));
assertThat(section.getObjects().get(0).getObjectName(), is("header"));
assertThat(section.getObjects().get(0).getSpecs().size(), is(1));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("inside screen 0px left right"));
assertThat(section.getObjects().get(1).getObjectName(), is("menu"));
assertThat(section.getObjects().get(1).getSpecs().size(), is(1));
assertThat(section.getObjects().get(1).getSpecs().get(0).getOriginalText(), is("inside screen 0px left right"));
assertThat(section.getObjects().get(2).getObjectName(), is("main"));
assertThat(section.getObjects().get(2).getSpecs().size(), is(1));
assertThat(section.getObjects().get(2).getSpecs().get(0).getOriginalText(), is("inside screen 0px left right"));
assertThat(section.getObjects().get(3).getObjectName(), is("menu-item-1"));
assertThat(section.getObjects().get(3).getSpecs().size(), is(1));
assertThat(section.getObjects().get(3).getSpecs().get(0).getOriginalText(), is("height 30px"));
assertThat(section.getObjects().get(4).getObjectName(), is("menu-item-2"));
assertThat(section.getObjects().get(4).getSpecs().size(), is(1));
assertThat(section.getObjects().get(4).getSpecs().get(0).getOriginalText(), is("height 30px"));
assertThat(section.getObjects().get(5).getObjectName(), is("menu-item-3"));
assertThat(section.getObjects().get(5).getSpecs().size(), is(1));
assertThat(section.getObjects().get(5).getSpecs().get(0).getOriginalText(), is("height 30px"));
}
@Test
public void shouldProcess_hashInObjectPattern_asDigits() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/hash-in-object-name.gspec");
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(2));
assertThat(section.getObjects().get(0).getObjectName(), is("item-1"));
assertThat(section.getObjects().get(1).getObjectName(), is("item-342"));
}
/**
* Purpose of this test is to check that "${}" expressions could be processed everywhere
*/
@Test
public void shouldRead_variablesDefinition_andProcessThem() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/variables-and-processing.gspec");
assertThat(pageSpec.getSections().size(), is(1));
assertThat(pageSpec.getSections().get(0).getName(), is("Section for user Johny"));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getObjectName(), is("welcome-message"));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecs().get(0).getOriginalText(), is("text is \"Welcome, Johny\""));
}
@Test
public void shouldRead_simpleForLoop_andProcessIt() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/for-loop.gspec");
assertThat(pageSpec.getSections().size(), is(1));
assertThat(pageSpec.getSections().get(0).getName(), is("Main section"));
assertThat(pageSpec.getSections().get(0).getObjects().size(), is(13));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
int objectIndex = 0;
for (int i = 1; i <= 3; i++) {
for (Integer j : asList(5, 7, 9)) {
assertThat("Object #" + objectIndex + " name should be",
objects.get(objectIndex).getObjectName(),
is("box-" + i + "-" + j));
assertThat("Object #" + objectIndex + " spec should be",
objects.get(objectIndex).getSpecs().get(0).getOriginalText(),
is("text is \"" + i + " and " + j + "\""));
objectIndex++;
}
assertThat("Object #" + objectIndex + " name should be",
objects.get(objectIndex).getObjectName(),
is("label-" + i));
assertThat("Object #" + objectIndex + " spec should be",
objects.get(objectIndex).getSpecs().get(0).getOriginalText(),
is("height 10px"));
objectIndex++;
}
assertThat("Object #11 name should be",
objects.get(objectIndex).getObjectName(),
is("caption"));
assertThat("Object #11 spec should be",
objects.get(objectIndex).getSpecs().get(0).getOriginalText(),
is("width 50px"));
}
@Test
public void shouldRead_eachLoop_andProcessIt() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/foreach-loop.gspec");
assertThat(pageSpec.getSections().size(), is(3));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(4));
for (int i = 0; i < 4; i++) {
assertThat("Section 1. Object #" + i + " name should be", objects.get(i).getObjectName(),
is("menu-item-" + (i+1)));
assertThat("Section 1. Object #" + i + " spec should be", objects.get(i).getSpecs().get(0).getOriginalText(),
is("width 100px"));
}
List<ObjectSpecs> objects2 = pageSpec.getSections().get(1).getObjects();
assertThat(objects2.size(), is(3));
for (int i = 0; i < 3; i++) {
assertThat("Section 2. Object #" + i + " name should be", objects2.get(i).getObjectName(),
is("menu-item-" + (i+2)));
assertThat("Section 2. Object #" + i + " spec should be", objects2.get(i).getSpecs().get(0).getOriginalText(),
is("right-of menu-item-" + (i+1) + " 10px"));
}
List<ObjectSpecs> objects3 = pageSpec.getSections().get(2).getObjects();
assertThat(objects3.size(), is(3));
for (int i = 0; i < 3; i++) {
assertThat("Section 3. Object #" + i + " name should be", objects3.get(i).getObjectName(),
is("menu-item-" + (i+1)));
assertThat("Section 3. Object #" + i + " spec should be", objects3.get(i).getSpecs().get(0).getOriginalText(),
is("left-of menu-item-" + (i + 2) + " 10px"));
}
}
/**
* Comes from https://github.com/galenframework/galen/issues/303
*/
@Test
public void shouldRead_emptyLoops_withoutException() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/empty-for-loops.gspec", EMPTY_PAGE, EMPTY_TAGS, EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(0));
}
@Test
public void shouldLoopOver_existingAndNonExisting_objects() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/foreach-loop-with-nonexisting-objects.gspec");
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(6));
assertThat(objects.get(0).getObjectName(), is("menu-item-1"));
assertThat(objects.get(1).getObjectName(), is("menu-item-2"));
assertThat(objects.get(2).getObjectName(), is("menu-item-3"));
assertThat(objects.get(3).getObjectName(), is("header"));
assertThat(objects.get(4).getObjectName(), is("toolbar"));
assertThat(objects.get(5).getObjectName(), is("popup"));
}
@Test
public void shouldRead_taggedSections_andProcessOnlyThose_thatMatchGivenTags_1() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/tagged-sections.gspec", EMPTY_PAGE, asList("mobile"), EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("header"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("height 100px"));
assertThat(objects.get(1).getObjectName(), is("header-icon"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("inside header 5px top left"));
}
@Test
public void shouldRead_taggedSections_andProcessOnlyThose_thatMatchGivenTags_2() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/tagged-sections.gspec", EMPTY_PAGE, asList("tablet"), EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("header"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("height 100px"));
assertThat(objects.get(1).getObjectName(), is("header-icon"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("inside header 5px top left"));
}
@Test
public void shouldRead_taggedSections_andProcessOnlyThose_thatMatchGivenTags_3() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/tagged-sections.gspec", EMPTY_PAGE, asList("desktop"), EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("header"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("height 200px"));
assertThat(objects.get(1).getObjectName(), is("header-icon"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("inside header 5px top left"));
}
@Test
public void shouldRead_taggedSections_andExcludeTags() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/tagged-sections.gspec", EMPTY_PAGE, asList("mobile", "desktop"), asList("tablet"));
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("header"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("height 200px"));
assertThat(objects.get(1).getObjectName(), is("header-icon"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("inside header 5px top left"));
}
@Test
public void should_importOtherPageSpecs_onlyOnce_andMergeSectionsAndObjects() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/import-other-pagespecs.gspec");
assertThat(pageSpec.getObjects(), is((Map<String, Locator>) new HashMap<String, Locator>() {{
put("header", new Locator("css", "#header"));
put("main-container", new Locator("css", "#main"));
}}));
assertThat(pageSpec.getSections().size(), is(2));
assertThat(pageSpec.getSections().get(0).getName(), is("Header section"));
assertThat(pageSpec.getSections().get(0).getObjects().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getObjectName(), is("header"));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecs().size(), is(2));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecs().get(0).getOriginalText(), is("inside screen 0px top left right"));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecs().get(1).getOriginalText(), is("height 100px"));
assertThat(pageSpec.getSections().get(1).getName(), is("Main section"));
assertThat(pageSpec.getSections().get(1).getObjects().size(), is(1));
assertThat(pageSpec.getSections().get(1).getObjects().get(0).getObjectName(), is("main-container"));
assertThat(pageSpec.getSections().get(1).getObjects().get(0).getSpecs().size(), is(1));
assertThat(pageSpec.getSections().get(1).getObjects().get(0).getSpecs().get(0).getOriginalText(), is("below header 0px"));
}
@Test
public void shouldImportOtherSpecs_whenMainSpecIsLoaded_fromAbsolutePath() throws IOException {
PageSpec pageSpec = readPageSpec(new File(getClass().getResource("/speclang2/import-other-pagespecs.gspec").getFile()).getAbsolutePath());
assertThat(pageSpec.getObjects(), is((Map<String, Locator>) new HashMap<String, Locator>() {{
put("header", new Locator("css", "#header"));
put("main-container", new Locator("css", "#main"));
}}));
}
@Test
public void shouldExecute_customJavaScript_fromSeparateFile() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/script-importing.gspec");
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("caption"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("text is \"Awesome website!\""));
assertThat(objects.get(1).getObjectName(), is("caption-2"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("text is \"Welcome, Johny\""));
}
@Test
public void scriptsPath_shouldBeResolved_whenSpecIsLoaded_fromAbsolutePath() throws IOException {
String absolutePath = new File(getClass().getResource("/speclang2/script-importing.gspec").getFile()).getAbsolutePath();
PageSpec pageSpec = readPageSpec(absolutePath);
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("caption"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("text is \"Awesome website!\""));
assertThat(objects.get(1).getObjectName(), is("caption-2"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("text is \"Welcome, Johny\""));
}
@Test
public void shouldExecute_inPageJavaScript() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/script-inpage.gspec");
assertThat(pageSpec.getSections().size(), is(1));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("caption"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("text is \"Awesome website!\""));
assertThat(objects.get(1).getObjectName(), is("caption-2"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("text is \"Welcome, Johny\""));
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "JavaScript error inside statement\n in speclang2/error-in-js-block.gspec:8"
)
public void shouldFail_whenThereIsError_inJavaScriptBlock() throws IOException {
readPageSpec("speclang2/error-in-js-block.gspec",
new MockedPage(new HashMap<String, PageElement>()),
EMPTY_TAGS, EMPTY_TAGS);
}
@Test
public void shouldRead_conditionsWithMultipleElseBlocks() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/conditions.gspec",
new MockedPage(new HashMap<String, PageElement>() {{
put("header", element(0, 0, 100, 10));
}}),
EMPTY_TAGS, EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(1));
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(1));
assertThat(section.getObjects().get(0).getObjectName(), is("header-icon"));
assertThat(section.getObjects().get(0).getSpecs().size(), is(1));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("inside header 10px top left"));
}
@Test
public void shouldRead_conditionsWithMultipleElseBlocks_2() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/conditions.gspec",
new MockedPage(new HashMap<String, PageElement>(){{
put("header", invisibleElement(0, 0, 100, 10));
put("header2", element(0, 0, 100, 10));
}}),
EMPTY_TAGS, EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(1));
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(1));
assertThat(section.getObjects().get(0).getObjectName(), is("header2-icon"));
assertThat(section.getObjects().get(0).getSpecs().size(), is(1));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("inside header2 5px top left"));
}
@Test
public void shouldRead_conditionsWithMultipleElseBlocks_3() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/conditions.gspec",
new MockedPage(new HashMap<String, PageElement>(){{
put("header", invisibleElement(0, 0, 100, 10));
put("header2", invisibleElement(0, 0, 100, 10));
}}),
EMPTY_TAGS, EMPTY_TAGS);
assertThat(pageSpec.getSections().size(), is(1));
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(1));
assertThat(section.getObjects().get(0).getObjectName(), is("header3"));
assertThat(section.getObjects().get(0).getSpecs().size(), is(1));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("visible"));
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "JavaScript error inside statement\n in speclang2/condition-with-js-error.gspec:5"
)
public void shouldFail_whenThereIsAnError_insideIfStatement() throws IOException {
readPageSpec("speclang2/condition-with-js-error.gspec",
new MockedPage(new HashMap<String, PageElement>()),
EMPTY_TAGS, EMPTY_TAGS);
}
@Test
public void shouldAllow_toPassProperties() throws IOException {
Properties properties = new Properties();
properties.put("custom.user.name", "John");
PageSpec pageSpec = new PageSpecReader().read("speclang2/properties.gspec", EMPTY_PAGE, new SectionFilter(EMPTY_TAGS, EMPTY_TAGS), properties, NO_VARS, EMPTY_OBJECTS);
assertThat(pageSpec.getSections().get(0).getName(), is("Main section for user John"));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecs().get(0).getOriginalText(),
is("text is \"Welcome, John!\""));
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "\\QExpecting \"px\", \"to\" or \"%\", got \"\"\n in \\E.*speclang2/syntax-error.gspec:9")
public void shouldThrow_fileSyntaxException_ifThereIsAnErrorInSpec() throws IOException {
readPageSpec("speclang2/syntax-error.gspec");
}
@Test
public void shouldAllow_mathExpressions_onIntegerValues_onForLoopIndexes() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/for-loop-math-expression.gspec");
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(4));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(),
is("right-of menu-item-3"));
assertThat(section.getObjects().get(1).getSpecs().get(0).getOriginalText(),
is("right-of menu-item-5"));
assertThat(section.getObjects().get(2).getSpecs().get(0).getOriginalText(),
is("right-of menu-item-7"));
assertThat(section.getObjects().get(3).getSpecs().get(0).getOriginalText(),
is("right-of menu-item-9"));
}
@Test
public void shouldParse_forLoops_withIfStatements() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/for-with-if.gspec");
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(1));
assertThat(section.getObjects().get(0).getSpecs().size(), is(2));
assertThat(section.getObjects().get(0).getObjectName(),
is("button"));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(),
is("inside container1 10px top left"));
assertThat(section.getObjects().get(0).getSpecs().get(1).getOriginalText(),
is("inside container2 10px top left"));
}
@Test
public void shouldRead_specsWithWarningLevel() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/warning-level-in-specs.gspec");
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().get(0).getSpecs().get(0).isOnlyWarn(), is(false));
assertThat(section.getObjects().get(0).getSpecs().get(0).getOriginalText(), is("width 100px"));
assertThat(section.getObjects().get(0).getSpecs().get(1).isOnlyWarn(), is(true));
assertThat(section.getObjects().get(0).getSpecs().get(1).getOriginalText(), is("height 100px"));
}
@Test
public void shouldRead_specAliases_beforeActualSpecs() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/spec-notes.gspec");
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getObjects().size(), is(1));
ObjectSpecs object = section.getObjects().get(0);
assertThat(object.getSpecs().size(), is(3));
assertThat(object.getSpecs().get(0).getAlias(), is(nullValue()));
assertThat(object.getSpecs().get(0).getOriginalText(), is("height 100px"));
assertThat(object.getSpecs().get(1).getAlias(), is("should be visible"));
assertThat(object.getSpecs().get(1).getOriginalText(), is("visible"));
assertThat(object.getSpecs().get(2).getAlias(), is("should be on top"));
assertThat(object.getSpecs().get(2).getOriginalText(), is("inside screen 0px top"));
}
@Test
public void shouldAllow_toPassCustomJsObjects() throws IOException {
PageSpec pageSpec = new PageSpecReader().read(
"speclang2/custom-js-variables.gspec",
EMPTY_PAGE,
new SectionFilter(EMPTY_TAGS, EMPTY_TAGS),
NO_PROPERTIES,
new HashMap<String, Object>() {{
put("age", 29);
put("userName", "John");
}}, EMPTY_OBJECTS);
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecs().get(0).getOriginalText(),
is("text is \"Name: John, age: 29\""));
}
@Test
public void shouldClean_emptySetions() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/empty-sections.gspec");
assertThat(pageSpec.getSections().size(), is(1));
PageSection section = pageSpec.getSections().get(0);
assertThat(section.getSections().size(), is(0));
assertThat(section.getObjects().size(), is(1));
}
@Test
public void countFunction_shouldCountAllMatchingObjects() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/count.gspec");
assertThat(pageSpec.getSections().size(), is(2));
assertThat(pageSpec.getSections().get(0).getObjects().size(), is(6));
assertThat(pageSpec.getSections().get(1).getObjects().size(), is(3));
}
@Test
public void forEachLoop_shouldOrderCorrectly_objectsWithNumbers() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/foreach-sortorder.gspec");
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(4));
assertThat(objects.get(0).getObjectName(), is("menu-item-1"));
assertThat(objects.get(1).getObjectName(), is("menu-item-2"));
assertThat(objects.get(2).getObjectName(), is("menu-item-12"));
assertThat(objects.get(3).getObjectName(), is("menu-item-101"));
}
@Test
public void forEachLoop_shouldAllow_toUseIndex() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/forEach-loop-with-index.gspec");
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(3));
assertThat(objects.get(0).getObjectName(), is("item-1"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("inside screen 100px top"));
assertThat(objects.get(1).getObjectName(), is("item-2"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("inside screen 200px top"));
assertThat(objects.get(2).getObjectName(), is("item-3"));
assertThat(objects.get(2).getSpecs().get(0).getOriginalText(), is("inside screen 300px top"));
}
@Test
public void shouldAllow_toProvideObjects_toPageSpec() throws IOException {
Map<String, Locator> objects = new HashMap<>();
objects.put("header", new Locator("css", "#header"));
objects.put("menu", new Locator("id", "menu"));
PageSpec pageSpec = new PageSpecReader().read("speclang2/provide-objects.gspec", EMPTY_PAGE, new SectionFilter(EMPTY_TAGS, EMPTY_TAGS), NO_PROPERTIES, NO_VARS, objects);
assertThat(pageSpec.getObjects(), allOf(
hasEntry("header", new Locator("css", "#header")),
hasEntry("menu", new Locator("id", "menu")),
hasEntry("button", new Locator("css", "#button"))
));
}
@Test
public void customRules_shouldAllow_toUse_ruleBodies_inSpecs() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/custom-rules-using-rule-body.gspec",
new MockedPage(new HashMap<String, PageElement>(){{
put("banner-1", element(0, 0, 100, 10));
put("banner-2", invisibleElement(0, 0, 100, 10));
}}),
EMPTY_TAGS, EMPTY_TAGS);
assertThat(pageSpec.getSections().get(0).getObjects().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecGroups().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecGroups().get(0).getSpecs().get(0).getOriginalText(), is("height 90px"));
assertThat(pageSpec.getSections().get(0).getSections().size(), is(2));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getSections().get(0).getObjects();
assertThat(objects.size(), is(1));
assertThat(objects.get(0).getObjectName(), is("banner-1"));
assertThat(objects.get(0).getSpecs().size(), is(1));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("width 145px"));
objects = pageSpec.getSections().get(0).getSections().get(1).getObjects();
assertThat(objects.size(), is(1));
assertThat(objects.get(0).getObjectName(), is("banner-3"));
assertThat(objects.get(0).getSpecs().size(), is(1));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("visible"));
}
@Test
public void shouldRead_objectClasses_inObjectsSection() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-groups-definition.gspec");
assertThat(pageSpec.getObjectGroups(), hasEntry("image-validation", asList("menu.item-1", "button")));
assertThat(pageSpec.getObjectGroups(), hasEntry("menu-stuff", asList("menu.item-1")));
}
@Test
public void shouldApply_objectGroups_toAlreadyProcessedObjects() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-groups-added.gspec");
assertThat(pageSpec.getObjectGroups(), hasEntry("groupA", asList("obj1", "obj3")));
assertThat(pageSpec.getObjectGroups(), hasEntry("groupB", asList("obj1", "obj3")));
assertThat(pageSpec.getObjectGroups(), hasEntry("groupC", asList("obj1", "obj2", "obj3")));
}
@Test
public void countFunction_shouldWorkWithGroups() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/count-grouped-objects.gspec");
assertThat(firstAppearingSpecIn(pageSpec), is("text is \"count is 4\""));
}
@Test
public void findFunction_shouldWorkWithGroups() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/find-grouped-object.gspec");
assertThat(firstAppearingObjectIn(pageSpec).getObjectName(), is("menu_item-1"));
}
@Test
public void firstFunction_shouldWorkWithGroups() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/first-grouped-object.gspec");
assertThat(firstAppearingObjectIn(pageSpec).getObjectName(), is("menu_item-1"));
}
@Test
public void lastFunction_shouldWorkWithGroups() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/last-grouped-object.gspec");
assertThat(firstAppearingObjectIn(pageSpec).getObjectName(), is("menu_icon"));
}
@Test
public void shouldFind_allObjects_forSpecifiedGroups_inRegularObjectStatement() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-groups-search.gspec");
assertSearchAndForEachGroupsElements(pageSpec);
}
@Test
public void shouldFind_allObjects_forSpecifiedGroups_forEachLoop() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-groups-foreach.gspec");
assertSearchAndForEachGroupsElements(pageSpec);
}
private void assertSearchAndForEachGroupsElements(PageSpec pageSpec) {
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("cancel-button"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("height 30px"));
assertThat(objects.get(1).getObjectName(), is("login-button"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("height 30px"));
}
@Test
public void shouldFind_allObjects_forSpecifiedGroups_inJavaScriptFindAllFunction() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/object-groups-findAll.gspec",
new MockedPage(new HashMap<String, PageElement>()),
EMPTY_TAGS, EMPTY_TAGS);
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(2));
assertThat(objects.get(0).getObjectName(), is("cancel-button"));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is("height 30px"));
assertThat(objects.get(1).getObjectName(), is("login-button"));
assertThat(objects.get(1).getSpecs().get(0).getOriginalText(), is("height 30px"));
}
/**
* When nonexisting object is passed to findAll function - it should return an instance of JsPageElement that
* will give 0 for any location related values like width, height, right etc. Also it should return false for
* isVisible function.
* @throws IOException
*/
@Test
public void findAll_andFind_functions_shouldHave_strictObjectProcessing_likeForEachLoop() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/findAll-nonexisting-objects.gspec");
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(1));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is(
"text is \"header[0, 0, 0, 0, false], menu[0, 0, 0, 0, false]\""
));
assertThat(objects.get(0).getSpecs().get(1).getOriginalText(), is(
"text is \"header[0, 0, 0, 0, false]\""
));
}
@Test
public void screenAndViewportObjects_shouldBeAccessible_fromJavaScript_codeBlocks() throws IOException {
MockedDriver driver = new MockedDriver();
driver.setExpectedJavaScriptReturnValues(asList(
(Object)asList(1000L, 700L),
(Object)asList(900L, 700L)
));
PageSpec pageSpec = readPageSpec("speclang2/screen-and-viewport-from-js.gspec", new SeleniumPage(driver));
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(1));
assertThat(objects.get(0).getSpecs().get(0).getOriginalText(), is(
"width 120 px"
));
}
@Test
public void shouldAllowToInvoke_first_function() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/first-function.gspec");
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(1));
assertThat(objects.get(0).getObjectName(), is("menu_item-1"));
}
@Test
public void shouldAllowToInvoke_last_function() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/last-function.gspec");
List<ObjectSpecs> objects = pageSpec.getSections().get(0).getObjects();
assertThat(objects.size(), is(1));
assertThat(objects.get(0).getObjectName(), is("menu_item-3"));
}
@Test
public void ruleShouldAllows_toUseColon_atTheEnd() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/rule-colon-at-end.gspec");
assertThat(pageSpec.getSections().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().size(), is(0));
assertThat(pageSpec.getSections().get(0).getSections().size(), is(1));
assertThat(pageSpec.getSections().get(0).getSections().get(0).getObjects().size(), is(1));
ObjectSpecs object = pageSpec.getSections().get(0).getSections().get(0).getObjects().get(0);
assertThat(object.getObjectName(), is("menu_item-1"));
assertThat(object.getSpecs().size(), is(1));
assertThat(object.getSpecs().get(0).getOriginalText(), is("width 100px"));
}
@Test
public void ruleShouldHave_priorityOverRules_thatWereDeclaredFirst() throws IOException {
PageSpec pageSpec = readPageSpec("speclang2/rule-priority.gspec");
assertThat(pageSpec.getSections().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getObjectName(), is("cancel_button"));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecGroups().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecGroups().get(0).getSpecs().size(), is(1));
assertThat(pageSpec.getSections().get(0).getObjects().get(0).getSpecGroups().get(0).getSpecs().get(0).getOriginalText(), is("width 30px"));
assertThat(pageSpec.getSections().get(0).getSections().size(), is(1));
assertThat(pageSpec.getSections().get(0).getSections().get(0).getObjects().size(), is(1));
ObjectSpecs object = pageSpec.getSections().get(0).getSections().get(0).getObjects().get(0);
assertThat(object.getObjectName(), is("login_button"));
assertThat(object.getSpecs().size(), is(1));
assertThat(object.getSpecs().get(0).getOriginalText(), is("width 300px"));
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "\\QError processing rule: button is located at the left side inside main_container with 10px margin\\E\\s+\\Qin speclang2/rule-error.gspec:7\\E")
public void shouldThrownInformativeError_whenThereIsProblemParsingTheRule() throws IOException {
readPageSpec("speclang2/rule-error.gspec");
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "\\QError processing rule: is located at the left side inside main_container with 10px margin\\E\\s+\\Qin speclang2/rule-error-object-level.gspec:7\\E")
public void shouldThrownInformativeError_whenThereIsProblemParsingTheRule_inObjectLevel() throws IOException {
readPageSpec("speclang2/rule-error-object-level.gspec");
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "\\QSpecs cannot have inner blocks\\E\\s+\\Qin speclang2/incorrect/nested-spec.gspec:7\\E")
public void shouldGiveError_whenSpecIsNested_belowAnotherSpec() throws IOException {
readPageSpec("speclang2/incorrect/nested-spec.gspec");
}
@Test(expectedExceptions = SyntaxException.class,
expectedExceptionsMessageRegExp = "\\QNot enough menu items\\E\\s+\\Qin speclang2/die.gspec:6\\E")
public void shouldGiveError_whenUsingDieStatement() throws IOException {
readPageSpec("speclang2/die.gspec");
}
}