├── .gitignore
├── pom.xml
└── src
└── test
├── java
└── com
│ └── galenframework
│ └── java
│ └── sample
│ ├── components
│ └── GalenTestBase.java
│ └── tests
│ └── WelcomePageTest.java
└── resources
└── specs
├── addNotePage.spec
├── common.spec
├── loginPage-withErrorMessage.spec
├── loginPage.spec
├── menuHighlight.spec
├── myNotesPage.spec
└── welcomePage.spec
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | *.iml
3 | .idea/
4 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | com.galenframework
5 | galen-java-sample-tests
6 | 0.1-SNAPSHOT
7 | Galen Framework Sample Java Test Project
8 | jar
9 | A test project for testing Galen using Java-based tests
10 |
11 |
12 |
13 | org.hamcrest
14 | hamcrest-all
15 | 1.3
16 | test
17 |
18 |
19 | org.testng
20 | testng
21 | 6.7
22 | test
23 |
24 |
25 | com.galenframework
26 | galen-java-support
27 | 2.3.0
28 |
29 |
30 |
31 |
32 |
33 | org.apache.maven.plugins
34 | maven-compiler-plugin
35 | 2.3.2
36 |
37 | 1.8
38 | 1.8
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-surefire-plugin
44 | 2.17
45 |
46 |
47 | usedefaultlistenersfalse
48 |
49 | listener
50 | com.galenframework.testng.GalenTestNgReportsListener
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | The Apache Software License, Version 2.0
61 | http://www.apache.org/licenses/LICENSE-2.0.txt
62 | manual
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/src/test/java/com/galenframework/java/sample/components/GalenTestBase.java:
--------------------------------------------------------------------------------
1 | package com.galenframework.java.sample.components;
2 |
3 | import com.galenframework.testng.GalenTestNgTestBase;
4 | import org.openqa.selenium.Dimension;
5 | import org.openqa.selenium.WebDriver;
6 | import org.openqa.selenium.firefox.FirefoxDriver;
7 | import org.testng.annotations.DataProvider;
8 |
9 | import java.util.List;
10 |
11 | import static java.util.Arrays.asList;
12 |
13 | public abstract class GalenTestBase extends GalenTestNgTestBase {
14 |
15 | private static final String ENV_URL = "http://testapp.galenframework.com";
16 |
17 | @Override
18 | public WebDriver createDriver(Object[] args) {
19 | WebDriver driver = new FirefoxDriver();
20 | if (args.length > 0) {
21 | if (args[0] != null && args[0] instanceof TestDevice) {
22 | TestDevice device = (TestDevice)args[0];
23 | if (device.getScreenSize() != null) {
24 | driver.manage().window().setSize(device.getScreenSize());
25 | }
26 | }
27 | }
28 | return driver;
29 | }
30 |
31 | public void load(String uri) {
32 | getDriver().get(ENV_URL + uri);
33 | }
34 |
35 | @DataProvider(name = "devices")
36 | public Object [][] devices () {
37 | return new Object[][] {
38 | {new TestDevice("mobile", new Dimension(450, 800), asList("mobile"))},
39 | {new TestDevice("tablet", new Dimension(750, 800), asList("tablet"))},
40 | {new TestDevice("desktop", new Dimension(1024, 800), asList("desktop"))}
41 | };
42 | }
43 |
44 | public static class TestDevice {
45 | private final String name;
46 | private final Dimension screenSize;
47 | private final List tags;
48 |
49 | public TestDevice(String name, Dimension screenSize, List tags) {
50 | this.name = name;
51 | this.screenSize = screenSize;
52 | this.tags = tags;
53 | }
54 |
55 | public String getName() {
56 | return name;
57 | }
58 |
59 | public Dimension getScreenSize() {
60 | return screenSize;
61 | }
62 |
63 | public List getTags() {
64 | return tags;
65 | }
66 |
67 | @Override
68 | public String toString() {
69 | return String.format("%s %dx%d", name, screenSize.width, screenSize.height);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/com/galenframework/java/sample/tests/WelcomePageTest.java:
--------------------------------------------------------------------------------
1 | package com.galenframework.java.sample.tests;
2 |
3 | import com.galenframework.java.sample.components.GalenTestBase;
4 | import com.galenframework.java.sample.components.GalenTestBase;
5 | import org.openqa.selenium.By;
6 | import org.testng.annotations.Test;
7 |
8 | import java.io.IOException;
9 |
10 |
11 | public class WelcomePageTest extends GalenTestBase {
12 |
13 | @Test(dataProvider = "devices")
14 | public void welcomePage_shouldLookGood_onDevice(TestDevice device) throws IOException {
15 | load("/");
16 | checkLayout("/specs/welcomePage.spec", device.getTags());
17 | }
18 |
19 | @Test(dataProvider = "devices")
20 | public void loginPage_shouldLookGood_onDevice(TestDevice device) throws IOException {
21 | load("/");
22 | getDriver().findElement(By.xpath("//button[.='Login']")).click();
23 | checkLayout("/specs/loginPage.spec", device.getTags());
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/resources/specs/addNotePage.spec:
--------------------------------------------------------------------------------
1 | @import common.spec
2 |
3 | @objects
4 | caption css #content h2
5 | title-textfield css input[name='note.title']
6 | description-textfield css textarea
7 | button-add css button.btn-primary
8 | button-cancel css button.btn-default
9 |
10 |
11 | = Add note page =
12 | @on *
13 | caption:
14 | below menu 20 to 45 px
15 | inside content ~ 20px left right
16 | height 20 to 40px
17 | above title-textfield 10 to 20px
18 | aligned vertically all title-textfield
19 |
20 | title-textfield:
21 | inside content ~ 20px left right
22 | below caption 10 to 20px
23 | inside content ~ 20px left right
24 | height 25 to 40px
25 | above description-textfield 10 to 20px
26 |
27 | description-textfield:
28 | aligned vertically all title-textfield
29 | height 150 to 350px
30 |
31 |
32 | button-add, button-cancel:
33 | height 40 to 50px
34 |
35 |
36 | @on desktop, tablet
37 | button-add:
38 | width 80 to 140px
39 | aligned horizontally all button-cancel
40 | below description-textfield 10 to 20px
41 | aligned vertically left description-textfield
42 |
43 | button-cancel:
44 | near button-add 0 to 10px right
45 | width 80 to 140px
46 |
47 |
48 |
49 | @on mobile
50 | button-add, button-cancel:
51 | aligned vertically all description-textfield
52 |
53 | button-cancel:
54 | below button-add 10 to 20px
--------------------------------------------------------------------------------
/src/test/resources/specs/common.spec:
--------------------------------------------------------------------------------
1 |
2 | @objects
3 | header css #header .middle-wrapper
4 | header-logo id header-logo
5 | header-text css #header h1
6 | menu css #menu ul
7 | menu-item-* css #menu li a
8 | content css #content
9 | footer id footer
10 |
11 |
12 | = Header =
13 | @on *
14 | header:
15 | inside screen 0px top
16 | centered horizontally inside screen 1px
17 | height ~ 70px
18 |
19 | header-logo:
20 | inside header 5 to 15px top, 0 to 10px left
21 | near header-text 5 to 30px left
22 |
23 | header-text:
24 | inside header 10 to 25px top
25 |
26 | @on desktop
27 | header:
28 | width 900px
29 |
30 | header-text:
31 | text is "Sample Website for Galen Framework"
32 |
33 |
34 | @on mobile, tablet
35 | header-text:
36 | text is "Sample Website"
37 |
38 |
39 |
40 |
41 | = Menu =
42 | menu:
43 | centered horizontally inside screen 1px
44 | below header ~ 0px
45 |
46 |
47 | @on desktop
48 | menu:
49 | width 900px
50 |
51 |
52 | @on desktop, tablet
53 | menu-item-1:
54 | inside menu ~ 0px top left bottom
55 |
56 | menu-item-*:
57 | width 90 to 130px
58 | height ~ 64px
59 | inside menu ~ 0px top
60 |
61 | @forEach [menu-item-*] as menuItem, prev as previousMenuItem
62 | ${menuItem}:
63 | right-of ${previousMenuItem} 0 to 5px
64 | aligned horizontally all ${previousMenuItem}
65 |
66 |
67 | @on mobile
68 | menu-item-* :
69 | width 48 to 50% of screen/width
70 |
71 | @for [ 1, 2 ] as index
72 | menu-item-${index}:
73 | above menu-item-${index + 2} 0 to 5px
74 |
75 | @for [ 1, 3 ] as index
76 | menu-item-${index}:
77 | near menu-item-${index + 1} 0 to 5 px left
78 |
79 |
80 | = Content =
81 | @on *
82 | content:
83 | below menu ~ 0px
84 | centered horizontally inside screen 1px
85 |
86 |
87 | @on desktop
88 | content:
89 | width 900px
90 |
91 |
92 | = Footer =
93 | footer:
94 | height ~ 200px
95 | below content 0px
96 |
--------------------------------------------------------------------------------
/src/test/resources/specs/loginPage-withErrorMessage.spec:
--------------------------------------------------------------------------------
1 |
2 |
3 | @objects
4 | password-textfield css input[name='login.password']
5 | login-button css .button-login
6 | error-message id login-error-message
7 |
8 |
9 | = Error message =
10 | @on *
11 | error-message:
12 | below password-textfield 5 to 15px
13 | height ~ 52px
14 | aligned vertically all password-textfield
15 | above login-button 10 to 30px
16 |
17 |
18 | @on mobile
19 | error-message:
20 | aligned vertically all login-button
21 |
--------------------------------------------------------------------------------
/src/test/resources/specs/loginPage.spec:
--------------------------------------------------------------------------------
1 | @import common.spec
2 |
3 | @objects
4 | login-box id login-page
5 | login-caption css #login-page h2
6 |
7 | username-textfield css input[name='login.username']
8 | password-textfield css input[name='login.password']
9 |
10 | login-button css .button-login
11 | cancel-button css .button-cancel
12 |
13 |
14 | = Login box =
15 | @on *
16 | login-box:
17 | centered horizontally inside content 1px
18 | below menu 20 to 45px
19 |
20 | login-caption:
21 | height 20 to 35px
22 | text is "Login"
23 |
24 | username-textfield, password-textfield:
25 | height 25 to 35 px
26 |
27 | username-textfield:
28 | below login-caption 5 to 15px
29 | aligned vertically all password-textfield
30 |
31 | password-textfield:
32 | below username-textfield 5 to 15px
33 | aligned vertically left login-button
34 |
35 | login-button, cancel-button:
36 | height 40 to 50 px
37 |
38 | login-button:
39 | text is "Login"
40 |
41 | cancel-button:
42 | text is "Cancel"
43 |
44 |
45 | @on desktop, tablet
46 | login-box:
47 | width 400px
48 |
49 | login-caption:
50 | inside login-box ~ 40px top, ~ 20px left
51 |
52 | username-textfield, password-textfield:
53 | inside login-box ~ 20px left right
54 |
55 | login-button:
56 | below password-textfield 5 to 15px
57 | width 70 to 90 px
58 | aligned horizontally all cancel-button
59 |
60 | cancel-button:
61 | width 80 to 100 px
62 | near login-button 3 to 8px right
63 |
64 |
65 | @on mobile
66 | login-box:
67 | inside screen ~ 20px left right
68 |
69 | username-textfield, password-textfield:
70 | inside login-box 0px left right
71 |
72 | login-caption:
73 | inside login-box 0px top, 0px left
74 |
75 | login-button:
76 | inside login-box 0px left right
77 | above cancel-button 4 to 10px
78 | aligned vertically all cancel-button
79 |
--------------------------------------------------------------------------------
/src/test/resources/specs/menuHighlight.spec:
--------------------------------------------------------------------------------
1 |
2 | @objects
3 | menu-item-* css #menu li a
4 |
5 | = Menu highlight =
6 | @on usual
7 | menu-item-1:
8 | color-scheme 90 to 96 % #2d6ca2, 1 to 4 % white
9 |
10 |
11 |
12 | @on hovered
13 | menu-item-1:
14 | color-scheme 90 to 96 % #205380, 1 to 4 % white
15 |
--------------------------------------------------------------------------------
/src/test/resources/specs/myNotesPage.spec:
--------------------------------------------------------------------------------
1 | @import common.spec
2 |
3 | @objects
4 | caption css #my-notes-page h2
5 |
6 | note-* css .list-group a
7 | title css h4
8 | description css p
9 |
10 | button-addnote css button
11 |
12 |
13 | = Content =
14 | @on *
15 | caption:
16 | below menu 20 to 45 px
17 | inside content ~ 20px left right
18 | height 20 to 40px
19 | above note-1 10 to 20px
20 | aligned vertically all note-1
21 |
22 |
23 | note-1:
24 | above note-2 ~ 0px
25 | aligned vertically all note-2
26 |
27 | @for [ 1 - 2 ] as i
28 | note-${i}:
29 | height ~ 64px
30 | inside content ~ 20px left right
31 |
32 | note-${i}.title:
33 | inside note-${i} ~ 11 px top, ~ 16px left
34 |
35 | note-${i}.description:
36 | below note-${i}.title ~ 5 px
37 | inside note-${i} ~ 11 px bottom
38 | aligned vertically all note-${i}.title
39 |
40 |
41 | button-addnote:
42 | height ~ 45px
43 | below note-2 20 to 45 px
44 |
45 | @on desktop, tablet
46 | button-addnote:
47 | width 90 to 120px
48 | inside content ~ 20 px left
49 | aligned vertically left note-1
50 |
51 | @on mobile
52 | button-addnote:
53 | inside content ~ 20px left right
54 |
--------------------------------------------------------------------------------
/src/test/resources/specs/welcomePage.spec:
--------------------------------------------------------------------------------
1 | @import common.spec
2 |
3 | @objects
4 | welcome-block css .jumbotron
5 | greeting css #welcome-page h1
6 | text-block-* css #welcome-page p
7 | login-button css #welcome-page .button-login
8 |
9 |
10 |
11 | = Content =
12 | @on *
13 | text-block-1, login-button, text-block-3:
14 | inside welcome-block ~30px left
15 |
16 | greeting:
17 | above text-block-1 10 to 50 px
18 | inside welcome-block ~ 30px left
19 |
20 | text-block-1:
21 | height > 20px
22 | above login-button 10 to 50 px
23 |
24 | login-button:
25 | height ~ 45px
26 | text is "Login"
27 | above text-block-3 10 to 50px
28 |
29 |
30 | @on desktop
31 | greeting:
32 | height ~ 69px
33 | inside welcome-block ~ 68 px top
34 |
35 | login-button:
36 | width ~ 78px
37 |
38 |
39 | @on tablet
40 | greeting:
41 | height ~ 39px
42 | inside welcome-block ~ 50 px top
43 |
44 | login-button:
45 | width ~ 78px
46 |
47 | @on mobile
48 | greeting:
49 | height ~ 78px
50 | inside welcome-block ~ 50 px top
51 |
52 | login-button:
53 | inside welcome-block ~ 30px left right
54 |
--------------------------------------------------------------------------------