From bbecb9132ef98bd619525a4a81cf4d44425cc76f Mon Sep 17 00:00:00 2001 From: Kazik Pogoda Date: Mon, 14 Aug 2017 22:49:01 +0200 Subject: [PATCH 1/4] guava, junit and mockito dependencies added to the project --- github-users-web-client/pom.xml | 39 +++++++++++++++++++++++++++++++++ pom.xml | 23 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/github-users-web-client/pom.xml b/github-users-web-client/pom.xml index 2913271..72f9802 100644 --- a/github-users-web-client/pom.xml +++ b/github-users-web-client/pom.xml @@ -70,6 +70,16 @@ dagger-gwt + + + com.google.guava + guava + + + com.google.guava + guava-gwt + + com.intendia.gwt.autorest @@ -83,6 +93,18 @@ com.intendia.gwt.rxgwt rxgwt + + + + junit + junit + test + + + org.mockito + mockito-core + test + @@ -119,6 +141,23 @@ gwt-maven-plugin ${gwt.version} + + org.apache.maven.plugins + maven-surefire-plugin + + + + + test + + test + + + diff --git a/pom.xml b/pom.xml index 9a11d07..5979cb4 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ 1.0.0-SNAPSHOT 2.8.1 2.11 + 23.0 v8.1.2 @@ -153,6 +154,16 @@ elemental2-dom 1.0.0-beta-1 + + com.google.guava + guava + ${guava.version} + + + com.google.guava + guava-gwt + ${guava.version} + com.google.dagger dagger-gwt @@ -203,6 +214,18 @@ closure-compiler-unshaded v20170626 + + + + junit + junit + 4.12 + + + org.mockito + mockito-core + 2.8.47 + From 388774af50a65bcd76554d759ab90c69209df44f Mon Sep 17 00:00:00 2001 From: Kazik Pogoda Date: Tue, 28 Nov 2017 20:53:10 +0100 Subject: [PATCH 2/4] ankh library update with Image preloaded and MdcElevator --- .../com/xemantic/ankh/{ => web}/Ankh.gwt.xml | 2 + .../com/xemantic/ankh/{ => web}/Elements.java | 2 +- .../java/com/xemantic/ankh/web/Images.java | 55 +++ .../ankh/{ => web}/IncrementalDom.java | 6 +- .../web/driver/WebUrlOpener.java | 2 +- .../xemantic/ankh/web/mdc/MdcElevator.java | 110 ++++++ .../com/xemantic/ankh/web/ImagesTest.java | 60 ++++ .../ankh/web/mdc/MdcElevatorTest.java | 337 ++++++++++++++++++ 8 files changed, 569 insertions(+), 5 deletions(-) rename github-users-web-client/src/main/java/com/xemantic/ankh/{ => web}/Ankh.gwt.xml (92%) rename github-users-web-client/src/main/java/com/xemantic/ankh/{ => web}/Elements.java (98%) create mode 100644 github-users-web-client/src/main/java/com/xemantic/ankh/web/Images.java rename github-users-web-client/src/main/java/com/xemantic/ankh/{ => web}/IncrementalDom.java (90%) rename github-users-web-client/src/main/java/com/xemantic/{githubusers => ankh}/web/driver/WebUrlOpener.java (96%) create mode 100644 github-users-web-client/src/main/java/com/xemantic/ankh/web/mdc/MdcElevator.java create mode 100644 github-users-web-client/src/test/java/com/xemantic/ankh/web/ImagesTest.java create mode 100644 github-users-web-client/src/test/java/com/xemantic/ankh/web/mdc/MdcElevatorTest.java diff --git a/github-users-web-client/src/main/java/com/xemantic/ankh/Ankh.gwt.xml b/github-users-web-client/src/main/java/com/xemantic/ankh/web/Ankh.gwt.xml similarity index 92% rename from github-users-web-client/src/main/java/com/xemantic/ankh/Ankh.gwt.xml rename to github-users-web-client/src/main/java/com/xemantic/ankh/web/Ankh.gwt.xml index e70ee79..f263b97 100644 --- a/github-users-web-client/src/main/java/com/xemantic/ankh/Ankh.gwt.xml +++ b/github-users-web-client/src/main/java/com/xemantic/ankh/web/Ankh.gwt.xml @@ -27,6 +27,8 @@ + + diff --git a/github-users-web-client/src/main/java/com/xemantic/ankh/Elements.java b/github-users-web-client/src/main/java/com/xemantic/ankh/web/Elements.java similarity index 98% rename from github-users-web-client/src/main/java/com/xemantic/ankh/Elements.java rename to github-users-web-client/src/main/java/com/xemantic/ankh/web/Elements.java index de09fff..ed61365 100644 --- a/github-users-web-client/src/main/java/com/xemantic/ankh/Elements.java +++ b/github-users-web-client/src/main/java/com/xemantic/ankh/web/Elements.java @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -package com.xemantic.ankh; +package com.xemantic.ankh.web; import com.intendia.rxgwt.elemental2.RxElemental2; import com.xemantic.githubusers.logic.event.Trigger; diff --git a/github-users-web-client/src/main/java/com/xemantic/ankh/web/Images.java b/github-users-web-client/src/main/java/com/xemantic/ankh/web/Images.java new file mode 100644 index 0000000..0a16e98 --- /dev/null +++ b/github-users-web-client/src/main/java/com/xemantic/ankh/web/Images.java @@ -0,0 +1,55 @@ +/* + * github-users-web - lists GitHub users. Minimal app demonstrating + * cross-platform app development (Web, Android, iOS) where core + * logic is shared and transpiled from Java to JavaScript and + * Objective-C. This project delivers Web version. + * + * Copyright (C) 2017 Kazimierz Pogoda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.xemantic.ankh.web; + +import elemental2.dom.Image; +import rx.Single; + +import java.util.Objects; + +/** + * Image utilities. + * + * @author morisil + */ +public final class Images { + + private Images() { /* util class, non-instantiable */ } + + public static Single preload(String url) { + Objects.requireNonNull(url); + return Single.create(subscriber -> { + Image image = new Image(); + image.src = url; + image.onload = p0 -> { + subscriber.onSuccess(image); + return null; + }; + image.onerror = p0 -> { + subscriber.onError(new RuntimeException("Could not load image: " + url)); + return null; + }; + }); + } + +} diff --git a/github-users-web-client/src/main/java/com/xemantic/ankh/IncrementalDom.java b/github-users-web-client/src/main/java/com/xemantic/ankh/web/IncrementalDom.java similarity index 90% rename from github-users-web-client/src/main/java/com/xemantic/ankh/IncrementalDom.java rename to github-users-web-client/src/main/java/com/xemantic/ankh/web/IncrementalDom.java index afa0925..05f1a97 100644 --- a/github-users-web-client/src/main/java/com/xemantic/ankh/IncrementalDom.java +++ b/github-users-web-client/src/main/java/com/xemantic/ankh/web/IncrementalDom.java @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -package com.xemantic.ankh; +package com.xemantic.ankh.web; import elemental2.dom.DocumentFragment; import elemental2.dom.DomGlobal; @@ -47,10 +47,10 @@ public static E create(Patcher patcher) { return (E) fragment.firstChild; } - @JsMethod(namespace = "com.xemantic.ankh.incrementaldom", name = "patch") + @JsMethod(namespace = "com.xemantic.ankh.web.incrementaldom", name = "patch") public static native void patch(Node element, Patcher patcher); - @JsMethod(namespace = "com.xemantic.ankh.incrementaldom", name = "patchOuter") + @JsMethod(namespace = "com.xemantic.ankh.web.incrementaldom", name = "patchOuter") public static native void patchOuter(Node element, Patcher patcher); @JsFunction diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/driver/WebUrlOpener.java b/github-users-web-client/src/main/java/com/xemantic/ankh/web/driver/WebUrlOpener.java similarity index 96% rename from github-users-web-client/src/main/java/com/xemantic/githubusers/web/driver/WebUrlOpener.java rename to github-users-web-client/src/main/java/com/xemantic/ankh/web/driver/WebUrlOpener.java index db5a36e..be56ccb 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/driver/WebUrlOpener.java +++ b/github-users-web-client/src/main/java/com/xemantic/ankh/web/driver/WebUrlOpener.java @@ -20,7 +20,7 @@ * along with this program. If not, see . */ -package com.xemantic.githubusers.web.driver; +package com.xemantic.ankh.web.driver; import com.xemantic.githubusers.logic.driver.UrlOpener; import elemental2.dom.DomGlobal; diff --git a/github-users-web-client/src/main/java/com/xemantic/ankh/web/mdc/MdcElevator.java b/github-users-web-client/src/main/java/com/xemantic/ankh/web/mdc/MdcElevator.java new file mode 100644 index 0000000..322c2b7 --- /dev/null +++ b/github-users-web-client/src/main/java/com/xemantic/ankh/web/mdc/MdcElevator.java @@ -0,0 +1,110 @@ +/* + * github-users-web - lists GitHub users. Minimal app demonstrating + * cross-platform app development (Web, Android, iOS) where core + * logic is shared and transpiled from Java to JavaScript and + * Objective-C. This project delivers Web version. + * + * Copyright (C) 2017 Kazimierz Pogoda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.xemantic.ankh.web.mdc; + +import com.google.common.base.Preconditions; +import com.google.gwt.regexp.shared.MatchResult; +import com.google.gwt.regexp.shared.RegExp; +import elemental2.dom.Element; + +import java.util.Objects; + +/** + * Controls {@code mdc-elevation} class. + * + * @author morisil + */ +public class MdcElevator { + + private final static RegExp ELEVATION_CLASS_REG_EXP = RegExp.compile("^mdc-elevation--z([0-9][0-9]?)$"); + + private final Element element; + + private final int initialLevel; + + private int currentLevel; + + public MdcElevator(Element element) { + this.element = Objects.requireNonNull(element); + initialLevel = getLevel(element); + currentLevel = initialLevel; + } + + public static int getLevel(Element element) { + int level = 0; + for (int i = 0, length = element.classList.getLength(); i < length; i++) { + String klass = element.classList.getAt(i); + level += getLevel(klass); + if (level > 0) { + break; + } + } + return level; + } + + public void liftTo(int level) { + Preconditions.checkArgument((level >= 0) && (level <= 24), "level range: 0..24"); + if (currentLevel == level) { + return; + } + if (currentLevel > 0) { + element.classList.remove("mdc-elevation--z" + currentLevel); + } + if (level > 0) { + element.classList.add("mdc-elevation--z" + level); + } + currentLevel = level; + } + + public void liftToInitialLevel() { + liftTo(initialLevel); + } + + private static int getLevel(String klass) { + MatchResult result = ELEVATION_CLASS_REG_EXP.exec(klass); + return result != null + ? Integer.parseInt(result.getGroup(1)) + : 0; + } + + public static OverBuilder whenOver(Element element) { + return new OverBuilder(element); + } + + public static class OverBuilder { + + private final Element element; + + private OverBuilder(Element element) { + this.element = element; + } + + public void liftTo(int level) { + MdcElevator elevator = new MdcElevator(element); + element.addEventListener("mouseenter", e -> elevator.liftTo(level)); + element.addEventListener("mouseleave", e -> elevator.liftToInitialLevel()); + } + + } + +} diff --git a/github-users-web-client/src/test/java/com/xemantic/ankh/web/ImagesTest.java b/github-users-web-client/src/test/java/com/xemantic/ankh/web/ImagesTest.java new file mode 100644 index 0000000..f476beb --- /dev/null +++ b/github-users-web-client/src/test/java/com/xemantic/ankh/web/ImagesTest.java @@ -0,0 +1,60 @@ +/* + * github-users-web - lists GitHub users. Minimal app demonstrating + * cross-platform app development (Web, Android, iOS) where core + * logic is shared and transpiled from Java to JavaScript and + * Objective-C. This project delivers Web version. + * + * Copyright (C) 2017 Kazimierz Pogoda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.xemantic.ankh.web; + +import elemental2.dom.Image; +import org.hamcrest.CoreMatchers; +import org.junit.Test; +import rx.Single; + +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; + +/** + * Test of the {@link Images}. + * + * @author morisil + */ +public class ImagesTest { + + @Test(expected = NullPointerException.class) + public void preload_nullUrl_shouldThrowException() { + // when + Images.preload(null); + + // then should fail + } + + @Test + public void preload_properUrl_shouldReturnSingle() { + // given + String url = "http://foo.com/image.png"; + + // when + Single single = Images.preload(url); + + // then + assertThat(single, notNullValue()); + } + +} diff --git a/github-users-web-client/src/test/java/com/xemantic/ankh/web/mdc/MdcElevatorTest.java b/github-users-web-client/src/test/java/com/xemantic/ankh/web/mdc/MdcElevatorTest.java new file mode 100644 index 0000000..1243c79 --- /dev/null +++ b/github-users-web-client/src/test/java/com/xemantic/ankh/web/mdc/MdcElevatorTest.java @@ -0,0 +1,337 @@ +/* + * github-users-web - lists GitHub users. Minimal app demonstrating + * cross-platform app development (Web, Android, iOS) where core + * logic is shared and transpiled from Java to JavaScript and + * Objective-C. This project delivers Web version. + * + * Copyright (C) 2017 Kazimierz Pogoda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.xemantic.ankh.web.mdc; + +import elemental2.dom.DOMTokenList; +import elemental2.dom.Element; +import elemental2.dom.EventListener; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.*; + +/** + * Test of the {@link MdcElevator}. + * + * @author morisil + */ +public class MdcElevatorTest { + + @SuppressWarnings("ConstantConditions") + @Test(expected = NullPointerException.class) + public void new_nullElement_shouldThrowException() { + // given + Element element = null; + + // when + new MdcElevator(element); + + // then exception should be thrown + } + + @Test + public void new_noInteraction_shouldNotChangeCssClasses() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + + // when + new MdcElevator(element); // and no interaction + + // then + verify(element.classList).getLength(); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void getLevel_noCssClasses_shouldReturnLevel0() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + + // when + int level = MdcElevator.getLevel(element); + + // then + verify(element.classList).getLength(); + verifyNoMoreInteractions(element, element.classList); + assertThat(level, is(0)); + } + + @Test + public void getLevel_1NonElevationCssClass_shouldReturnLevel0() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("foo"); + + // when + int level = MdcElevator.getLevel(element); + + // then + verify(element.classList).getLength(); + verify(element.classList).getAt(0); + verifyNoMoreInteractions(element, element.classList); + assertThat(level, is(0)); + } + + @Test + public void getLevel_1ElevationCssClass_shouldReturnDefinedElevation() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("mdc-elevation--z12"); + + // when + int level = MdcElevator.getLevel(element); + + // then + verify(element.classList).getLength(); + verify(element.classList).getAt(0); + verifyNoMoreInteractions(element, element.classList); + assertThat(level, is(12)); + } + + @Test + public void liftTo_fromLevel0_shouldAddElevationClassName() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftTo(8); + + // then + InOrder inOrder = inOrder(element.classList); + inOrder.verify(element.classList).getLength(); + inOrder.verify(element.classList).add("mdc-elevation--z8"); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void liftTo_fromNon0Level_shouldReplaceElevationClassNames() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("mdc-elevation--z2"); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftTo(8); + + // then + InOrder inOrder = inOrder(element.classList); + inOrder.verify(element.classList).getLength(); + inOrder.verify(element.classList).getAt(0); + inOrder.verify(element.classList).remove("mdc-elevation--z2"); + inOrder.verify(element.classList).add("mdc-elevation--z8"); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void liftTo_sameLevel_shouldDoNothing() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("mdc-elevation--z2"); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftTo(2); + + // then + verify(element.classList).getLength(); + verify(element.classList).getAt(0); + verifyNoMoreInteractions(element, element.classList); + } + + @Test(expected = IllegalArgumentException.class) + public void liftTo_negativeLevel_shouldThrowException() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftTo(-1); + + // then exception should be thrown + } + + @Test(expected = IllegalArgumentException.class) + public void liftTo_levelAboveLimit_shouldThrowException() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftTo(25); + + // then exception should be thrown + } + + @Test + public void liftToInitialLevel_alreadyOnInitialLevel0_shouldNotChangeCssClasses() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftToInitialLevel(); + + // then + verify(element.classList).getLength(); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void liftToInitialLevel_alreadyOnInitialLevelNon0_shouldNotChangeCssClasses() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("mdc-elevation--z1"); + MdcElevator elevator = new MdcElevator(element); + + // when + elevator.liftToInitialLevel(); + + // then + verify(element.classList).getLength(); + verify(element.classList).getAt(0); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void liftToInitialLevel_whereInitialLevel0_shouldRemoveElevationCssClass() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + MdcElevator elevator = new MdcElevator(element); + elevator.liftTo(1); + + // when + elevator.liftToInitialLevel(); + + // then + InOrder inOrder = inOrder(element.classList); + inOrder.verify(element.classList).getLength(); + inOrder.verify(element.classList).add("mdc-elevation--z1"); + inOrder.verify(element.classList).remove("mdc-elevation--z1"); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void liftToInitialLevel_whereInitialLevelNon0_shouldReplaceElevationCssClass() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("mdc-elevation--z1"); + MdcElevator elevator = new MdcElevator(element); + elevator.liftTo(2); + + // when + elevator.liftToInitialLevel(); + + // then + InOrder inOrder = inOrder(element.classList); + inOrder.verify(element.classList).getLength(); + inOrder.verify(element.classList).getAt(0); + inOrder.verify(element.classList).remove("mdc-elevation--z1"); + inOrder.verify(element.classList).add("mdc-elevation--z2"); + inOrder.verify(element.classList).remove("mdc-elevation--z2"); + inOrder.verify(element.classList).add("mdc-elevation--z1"); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void whenOver_noInitialCssElevationSpecified_shouldAddAndRemoveElevation() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(0); + MdcElevator.whenOver(element).liftTo(8); + ArgumentCaptor enterCaptor = ArgumentCaptor.forClass(EventListener.class); + ArgumentCaptor leaveCaptor = ArgumentCaptor.forClass(EventListener.class); + verify(element).addEventListener(eq("mouseenter"), enterCaptor.capture()); + verify(element).addEventListener(eq("mouseleave"), leaveCaptor.capture()); + + // when + enterCaptor.getValue().handleEvent(null); // event payload doesn't matter + leaveCaptor.getValue().handleEvent(null); + + // then + InOrder inOrder = inOrder(element.classList); + inOrder.verify(element.classList).getLength(); + inOrder.verify(element.classList).add("mdc-elevation--z8"); + inOrder.verify(element.classList).remove("mdc-elevation--z8"); + verifyNoMoreInteractions(element, element.classList); + } + + @Test + public void whenOver_initialCssElevationSpecified_shouldReplaceAndRestoreElevation() { + // given + Element element = mock(Element.class); + element.classList = mock(DOMTokenList.class); + given(element.classList.getLength()).willReturn(1); + given(element.classList.getAt(0)).willReturn("mdc-elevation--z2"); + MdcElevator.whenOver(element).liftTo(8); + ArgumentCaptor enterCaptor = ArgumentCaptor.forClass(EventListener.class); + ArgumentCaptor leaveCaptor = ArgumentCaptor.forClass(EventListener.class); + verify(element).addEventListener(eq("mouseenter"), enterCaptor.capture()); + verify(element).addEventListener(eq("mouseleave"), leaveCaptor.capture()); + + // when + enterCaptor.getValue().handleEvent(null); // event payload doesn't matter + leaveCaptor.getValue().handleEvent(null); + + // then + InOrder inOrder = inOrder(element.classList); + inOrder.verify(element.classList).getLength(); + inOrder.verify(element.classList).getAt(0); + inOrder.verify(element.classList).remove("mdc-elevation--z2"); + inOrder.verify(element.classList).add("mdc-elevation--z8"); + inOrder.verify(element.classList).remove("mdc-elevation--z8"); + inOrder.verify(element.classList).add("mdc-elevation--z2"); + verifyNoMoreInteractions(element, element.classList); + } + +} From 69907152c15d4e1fae3ba984e5c49de4394bdca4 Mon Sep 17 00:00:00 2001 From: Kazik Pogoda Date: Tue, 28 Nov 2017 20:58:03 +0100 Subject: [PATCH 3/4] code adjusted for new package structure of ankh library --- .../java/com/xemantic/githubusers/GitHubUsersWeb.gwt.xml | 2 +- .../com/xemantic/githubusers/web/GitHubUsersModule.java | 2 +- .../com/xemantic/githubusers/web/view/WebDrawerView.java | 4 ++-- .../java/com/xemantic/githubusers/web/view/WebScreen.java | 2 +- .../com/xemantic/githubusers/web/view/WebSnackbarView.java | 2 +- github-users-web-server/src/main/webapp/js/deps.js | 4 ++-- .../modules/com/xemantic/ankh/{ => web}/incrementaldom.js | 6 +++--- .../webapp/js/modules/com/xemantic/githubusers/web/app.js | 2 +- .../com/xemantic/githubusers/web/tool/PrepareGwtJs.java | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) rename github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/{ => web}/incrementaldom.js (85%) diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/GitHubUsersWeb.gwt.xml b/github-users-web-client/src/main/java/com/xemantic/githubusers/GitHubUsersWeb.gwt.xml index b5248fb..bfff65a 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/GitHubUsersWeb.gwt.xml +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/GitHubUsersWeb.gwt.xml @@ -29,7 +29,7 @@ - + diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/GitHubUsersModule.java b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/GitHubUsersModule.java index 81600f0..7047b51 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/GitHubUsersModule.java +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/GitHubUsersModule.java @@ -31,7 +31,7 @@ import com.xemantic.githubusers.logic.event.UserSelectedEvent; import com.xemantic.githubusers.logic.service.UserService; import com.xemantic.githubusers.logic.view.*; -import com.xemantic.githubusers.web.driver.WebUrlOpener; +import com.xemantic.ankh.web.driver.WebUrlOpener; import com.xemantic.githubusers.web.error.DefaultErrorAnalyzer; import com.xemantic.githubusers.web.view.*; import com.xemantic.githubusers.web.service.WebUserService; diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebDrawerView.java b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebDrawerView.java index edbefd6..aa941c1 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebDrawerView.java +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebDrawerView.java @@ -22,8 +22,8 @@ package com.xemantic.githubusers.web.view; -import com.xemantic.ankh.Elements; -import com.xemantic.ankh.IncrementalDom; +import com.xemantic.ankh.web.Elements; +import com.xemantic.ankh.web.IncrementalDom; import com.xemantic.githubusers.logic.event.Trigger; import com.xemantic.githubusers.logic.view.DrawerView; import elemental2.dom.Element; diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebScreen.java b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebScreen.java index 28b3f0e..d2d68ec 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebScreen.java +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebScreen.java @@ -22,7 +22,7 @@ package com.xemantic.githubusers.web.view; -import com.xemantic.ankh.IncrementalDom; +import com.xemantic.ankh.web.IncrementalDom; import elemental2.dom.DomGlobal; import elemental2.dom.Element; import elemental2.dom.HTMLInputElement; diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebSnackbarView.java b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebSnackbarView.java index ad72fb1..4710ae0 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebSnackbarView.java +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebSnackbarView.java @@ -22,7 +22,7 @@ package com.xemantic.githubusers.web.view; -import com.xemantic.ankh.IncrementalDom; +import com.xemantic.ankh.web.IncrementalDom; import com.xemantic.githubusers.logic.view.SnackbarView; import elemental2.dom.Element; import mdc.snackbar.MDCSnackbar; diff --git a/github-users-web-server/src/main/webapp/js/deps.js b/github-users-web-server/src/main/webapp/js/deps.js index b8ea12a..107dcf7 100644 --- a/github-users-web-server/src/main/webapp/js/deps.js +++ b/github-users-web-server/src/main/webapp/js/deps.js @@ -27,6 +27,6 @@ goog.addDependency("../../../../js/lib/incemental-dom/incremental-dom-closure.js", ['incrementaldom'], [], true); goog.addDependency("../../../../js/lib/closure-templates/soyutils_idom.js", ['soy.idom'], ['goog.soy.data.SanitizedHtml', 'incrementaldom', 'goog.soy'], true); goog.addDependency("../../../../js/generated/templates.js", ['com.xemantic.githubusers.web.view.template.incrementaldom'], ['incrementaldom', 'soy.idom'], true); -goog.addDependency("../../../../js/modules/com/xemantic/ankh/incrementaldom.js", ['com.xemantic.ankh.incrementaldom'], ['incrementaldom'], true); +goog.addDependency("../../../../js/modules/com/xemantic/ankh/web/incrementaldom.js", ['com.xemantic.ankh.web.incrementaldom'], ['incrementaldom'], true); goog.addDependency("../../../../js/modules/com/xemantic/githubusers/web/view/template.js", ['com.xemantic.githubusers.web.view.template'], ['com.xemantic.githubusers.web.view.template.incrementaldom'], true); -goog.addDependency("../../../../js/modules/com/xemantic/githubusers/web/app.js", ['com.xemantic.githubusers.web.app'], ['com.xemantic.githubusers.web.view.template', 'com.xemantic.ankh.incrementaldom'], true); +goog.addDependency("../../../../js/modules/com/xemantic/githubusers/web/app.js", ['com.xemantic.githubusers.web.app'], ['com.xemantic.githubusers.web.view.template', 'com.xemantic.ankh.web.incrementaldom'], true); diff --git a/github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/incrementaldom.js b/github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/web/incrementaldom.js similarity index 85% rename from github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/incrementaldom.js rename to github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/web/incrementaldom.js index 85a03fd..4c1bcbb 100644 --- a/github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/incrementaldom.js +++ b/github-users-web-server/src/main/webapp/js/modules/com/xemantic/ankh/web/incrementaldom.js @@ -25,7 +25,7 @@ In the GWT code it is represented as IncrementalDom util class. */ -goog.module("com.xemantic.ankh.incrementaldom"); +goog.module("com.xemantic.ankh.web.incrementaldom"); goog.module.declareLegacyNamespace(); const _mod = goog.require("incrementaldom"); @@ -33,5 +33,5 @@ const _mod = goog.require("incrementaldom"); exports.patch = _mod.patch; exports.patchOuter = _mod.patchOuter; -goog.exportSymbol("com.xemantic.ankh.incrementaldom.patch", _mod.patch); -goog.exportSymbol("com.xemantic.ankh.incrementaldom.patchOuter", _mod.patchOuter); +goog.exportSymbol("com.xemantic.ankh.web.incrementaldom.patch", _mod.patch); +goog.exportSymbol("com.xemantic.ankh.web.incrementaldom.patchOuter", _mod.patchOuter); diff --git a/github-users-web-server/src/main/webapp/js/modules/com/xemantic/githubusers/web/app.js b/github-users-web-server/src/main/webapp/js/modules/com/xemantic/githubusers/web/app.js index a2839c0..40a460c 100644 --- a/github-users-web-server/src/main/webapp/js/modules/com/xemantic/githubusers/web/app.js +++ b/github-users-web-server/src/main/webapp/js/modules/com/xemantic/githubusers/web/app.js @@ -36,7 +36,7 @@ goog.module.declareLegacyNamespace(); This module is used as an entry point in the index-dev.html and when referenced it will cause all the dependant modules to be loaded as well. */ -goog.require("com.xemantic.ankh.incrementaldom"); +goog.require("com.xemantic.ankh.web.incrementaldom"); goog.require("com.xemantic.githubusers.web.view.template"); function start() { diff --git a/github-users-web-tools/src/main/java/com/xemantic/githubusers/web/tool/PrepareGwtJs.java b/github-users-web-tools/src/main/java/com/xemantic/githubusers/web/tool/PrepareGwtJs.java index 066d539..e40de67 100644 --- a/github-users-web-tools/src/main/java/com/xemantic/githubusers/web/tool/PrepareGwtJs.java +++ b/github-users-web-tools/src/main/java/com/xemantic/githubusers/web/tool/PrepareGwtJs.java @@ -83,7 +83,7 @@ private void writeHeader(BufferedWriter out) throws IOException { out.write(" */\n"); out.write("goog.module('app');\n"); out.write("goog.require('com.xemantic.githubusers.web.app');\n"); - out.write("goog.require('com.xemantic.ankh.incrementaldom');\n\n"); + out.write("goog.require('com.xemantic.ankh.web.incrementaldom');\n\n"); } private boolean shouldSkip(String line) { From 101d86495791ad07cff54ed8678eb1a6d05f5c35 Mon Sep 17 00:00:00 2001 From: Kazik Pogoda Date: Tue, 28 Nov 2017 21:04:06 +0100 Subject: [PATCH 4/4] new layout with cards instead of tiles --- .../githubusers/web/view/WebUserListView.java | 7 +- .../githubusers/web/view/WebUserView.java | 22 ++++- .../githubusers/web/view/templates.soy | 42 ++++++---- .../src/main/webapp/assets/person.png | Bin 0 -> 7203 bytes .../src/main/webapp/index-dev.html | 3 - .../src/main/webapp/main.css | 78 ++++++++++++++++-- 6 files changed, 114 insertions(+), 38 deletions(-) create mode 100644 github-users-web-server/src/main/webapp/assets/person.png diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserListView.java b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserListView.java index 10a70e4..bb8a9a1 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserListView.java +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserListView.java @@ -22,15 +22,14 @@ package com.xemantic.githubusers.web.view; -import com.xemantic.ankh.Elements; -import com.xemantic.ankh.IncrementalDom; +import com.xemantic.ankh.web.Elements; +import com.xemantic.ankh.web.IncrementalDom; import com.xemantic.githubusers.logic.event.Trigger; import com.xemantic.githubusers.logic.view.UserListView; import com.xemantic.githubusers.logic.view.UserView; import elemental2.dom.Element; import elemental2.dom.HTMLButtonElement; import elemental2.dom.HTMLElement; -import mdc.gridList.MDCGridList; import rx.Observable; import javax.inject.Inject; @@ -54,8 +53,6 @@ public class WebUserListView implements UserListView, WebView { public WebUserListView() { element = IncrementalDom.create(Templates::userList); Elements elements = new Elements(element); - /* it will center the grid and make it react to window resizing */ - MDCGridList.attachTo(elements.get(".mdc-grid-list")); userTiles = elements.get(".user-tiles"); loadMoreButton = elements.getButton(".load-more-action"); loadMore$ = Elements.observeClicksOf(loadMoreButton); diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserView.java b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserView.java index e7d8262..99afa2c 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserView.java +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/WebUserView.java @@ -21,12 +21,15 @@ */ package com.xemantic.githubusers.web.view; -import com.xemantic.ankh.Elements; +import com.xemantic.ankh.web.Elements; +import com.xemantic.ankh.web.Images; +import com.xemantic.ankh.web.mdc.MdcElevator; import com.xemantic.githubusers.logic.event.Trigger; import com.xemantic.githubusers.logic.model.User; import com.xemantic.githubusers.logic.view.UserView; -import com.xemantic.ankh.IncrementalDom; +import com.xemantic.ankh.web.IncrementalDom; import elemental2.dom.Element; +import mdc.ripple.MDCRipple; import rx.Observable; /** @@ -43,14 +46,21 @@ public class WebUserView implements UserView, WebView { public WebUserView() { element = IncrementalDom.create(() -> Templates.user(new Templates.UserParams())); userClicks$ = Elements.observeClicksOf(element); + Element userCard = element.querySelector(".user-card"); + MDCRipple.attachTo(userCard); + MdcElevator.whenOver(userCard).liftTo(8); } @Override public void displayUser(User user) { Templates.UserParams params = new Templates.UserParams(); params.login = user.getLogin(); - params.avatarUrl = user.getAvatarUrl() + "&s=200"; // we can rescale server side here - IncrementalDom.patchOuter(element, () -> Templates.user(params)); + patchUser(params); + Images.preload(user.getAvatarUrl()) + .subscribe(image -> { + params.avatarUrl = image.src; + patchUser(params); + }); } @Override @@ -63,4 +73,8 @@ public Element asElement() { return element; } + private void patchUser(Templates.UserParams params) { + IncrementalDom.patchOuter(element, () -> Templates.user(params)); + } + } diff --git a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/templates.soy b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/templates.soy index 5630a69..a7826e4 100644 --- a/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/templates.soy +++ b/github-users-web-client/src/main/java/com/xemantic/githubusers/web/view/templates.soy @@ -51,27 +51,35 @@ {/template} -{template .user} - {@param login: any} - {@param avatarUrl: any} -
  • -
    - -
    -
    - star_border -
    {$login}
    -
    -
  • -{/template} - {template .userList}
    -
    -
      +
      +
      +
      - + +
      +
      +{/template} + +{template .user} + {@param login: any} + {@param avatarUrl: any} +
      +
      +
      +
      + {if $avatarUrl != null} + {$login} avatar + {/if} +
      +
      +
      +

      {$login}

      +
      {/template} diff --git a/github-users-web-server/src/main/webapp/assets/person.png b/github-users-web-server/src/main/webapp/assets/person.png new file mode 100644 index 0000000000000000000000000000000000000000..72e81164b726c9f8be05da5fbec642ec06be4e83 GIT binary patch literal 7203 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 literal 0 HcmV?d00001 diff --git a/github-users-web-server/src/main/webapp/index-dev.html b/github-users-web-server/src/main/webapp/index-dev.html index 74babfc..144891e 100644 --- a/github-users-web-server/src/main/webapp/index-dev.html +++ b/github-users-web-server/src/main/webapp/index-dev.html @@ -43,14 +43,11 @@
      -
      - - diff --git a/github-users-web-server/src/main/webapp/main.css b/github-users-web-server/src/main/webapp/main.css index 93a302a..9a7564c 100644 --- a/github-users-web-server/src/main/webapp/main.css +++ b/github-users-web-server/src/main/webapp/main.css @@ -27,6 +27,17 @@ body { font-family: Roboto, Helvetica, Arial, sans-serif; + background: #e8e8e8; +} + +/* preload images */ +body::after { + position: absolute; + width: 0; + height: 0; + overflow: hidden; + z-index: -1; + content: url("assets/person.png"); } .mdc-toolbar a, .mdc-toolbar a:visited { @@ -64,28 +75,77 @@ body { padding-top: 8px; } -.user-list .user-tiles > li { - cursor: pointer; +.user-list .mdc-layout-grid { + max-width: 1280px; +} + +.user-card { + background: white; } -.user-list .user-tiles .mdc-grid-tile__secondary { - background: rgba(0, 0, 0, 0.3); +.user-card .mdc-card__media { + padding: 0; +} + +.image-placeholder-1x1 img { + /*width: 460px; + height: auto; + display: block;*/ + animation: material-design__image 3s; + animation-fill-mode: forward; +} + +.user-card .mdc-card__primary h1 { + text-align: center; } .user-list .user-list-actions { padding-top: 20px; text-align: center; - margin-bottom: 20px; + margin-bottom: 40px; } .user-list .user-list-actions .load-more-action { margin: auto; } -/* FIXES */ +.image-placeholder-person { + background-image: url("assets/person.png"); + background-size: 100% 100%; +} + +.image-progressive-fade-in { + animation: material-design__image 3s; + animation-fill-mode: forwards; +} + +.image-wrapper-1x1 { + padding-bottom: 100%; +} -/* temporary drawers should cover header, should be fixed in 0.16.0 */ +.image-wrapper-1x1 img { + background: white; + width: 100%; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; +} -.mdc-temporary-drawer { - z-index: 5; +/* Approximation of Material Design specifications */ +@keyframes material-design__image { + 0% { + opacity: 0; + filter: saturate(20%) brightness(125%); + } + 66.7% { + opacity: 1; + } + 83.3% { + filter: saturate(87%) brightness(100%); + } + 100% { + filter: saturate(100%) brightness(100%); + } }