Skip to content

Commit

Permalink
added tests for ScriptInjector and StyleInjector
Browse files Browse the repository at this point in the history
  • Loading branch information
treblereel committed Jun 14, 2023
1 parent 5c236aa commit fecceaa
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,72 +19,80 @@
import elemental2.dom.HTMLDocument;
import elemental2.dom.HTMLScriptElement;
import elemental2.dom.Window;

import java.util.function.Consumer;
import jsinterop.annotations.JsFunction;

public class ScriptInjector {

private Window window = DomGlobal.window;

private HTMLScriptElement style;

private ScriptInjector(HTMLScriptElement style) {
this.style = style;
}

public static ScriptInjector fromString(String contents) {
return fromString(contents, null, null);
}

public static ScriptInjector fromString(String contents, Consumer<HTMLScriptElement> onResolve) {
return fromString(contents, onResolve, null);

}

public static ScriptInjector fromString(String contents, Consumer<HTMLScriptElement> onResolve, Consumer<HTMLScriptElement> onReject) {
HTMLScriptElement element = createElement(onResolve, onReject);
element.text = contents;
return new ScriptInjector(element);
}

public static ScriptInjector fromUrl(String url) {
return fromUrl(url, null, null);
}

public static ScriptInjector fromUrl(String url, Consumer<HTMLScriptElement> onResolve) {
return fromUrl(url, onResolve, null);
}


public static ScriptInjector fromUrl(String url, Consumer<HTMLScriptElement> onResolve, Consumer<HTMLScriptElement> onReject) {
HTMLScriptElement element = createElement(onResolve, onReject);
element.src = url;
return new ScriptInjector(element);
}

private static HTMLScriptElement createElement(Consumer<HTMLScriptElement> onResolve, Consumer<HTMLScriptElement> onReject) {
HTMLScriptElement script = (HTMLScriptElement) DomGlobal.document.createElement("script");
if (onResolve != null) {
script.onreadystatechange = (e) -> {
onResolve.accept(script);
return null;
};
}
if (onReject != null) {
script.onerror = (e) -> {
onReject.accept(script);
return null;
};
}
return script;
}

public ScriptInjector setWindow(Window window) {
this.window = window;
return this;
}

public void inject() {
((HTMLDocument) Reflect.get(window, "document")).head.appendChild(style);
}
public static final Window TOP_WINDOW = DomGlobal.window;
public Window window;

private HTMLScriptElement scriptElement;

private ScriptInjector(HTMLScriptElement scriptElement) {
this.scriptElement = scriptElement;
}

public static ScriptInjector fromString(String contents) {
return fromString(contents, null, null);
}

public static ScriptInjector fromString(String contents, Callback onResolve) {
return fromString(contents, onResolve, null);
}

public static ScriptInjector fromString(String contents, Callback onResolve, Callback onReject) {
HTMLScriptElement element = createElement(onResolve, onReject);
element.text = contents;
return new ScriptInjector(element);
}

public static ScriptInjector fromUrl(String url) {
return fromUrl(url, null, null);
}

public static ScriptInjector fromUrl(String url, Callback onResolve) {
return fromUrl(url, onResolve, null);
}

public static ScriptInjector fromUrl(String url, Callback onResolve, Callback onReject) {
HTMLScriptElement element = createElement(onResolve, onReject);
element.src = url;
return new ScriptInjector(element);
}

private static HTMLScriptElement createElement(Callback onResolve, Callback onReject) {
HTMLScriptElement script = (HTMLScriptElement) DomGlobal.document.createElement("script");
script.addEventListener(
"load",
(e) -> {
if (onResolve != null) {
onResolve.accept(script);
}
});

script.addEventListener(
"error",
(e) -> {
if (onReject != null) {
onReject.accept(script);
}
});
script.type = "text/javascript";
return script;
}

public ScriptInjector setWindow(Window window) {
this.window = window;
return this;
}

public void inject() {
((HTMLDocument) Reflect.get(window, "document")).head.appendChild(scriptElement);
}

@JsFunction
@FunctionalInterface
public interface Callback {
void accept(HTMLScriptElement script);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,32 @@

public class StyleInjector {

private final String styleBody;

public static StyleInjector injectStyleSheet(String contents) {
return new StyleInjector(contents);
}

private StyleInjector(String styleBody) {
this.styleBody = styleBody;
}

private HTMLStyleElement createElement(String contents) {
HTMLStyleElement style = (HTMLStyleElement) DomGlobal.document.createElement("style");
style.setAttribute("language", "text/css");
style.innerHTML = contents;
return style;
}

public HTMLStyleElement injectStyleSheet() {
HTMLStyleElement style = createElement(styleBody);
DomGlobal.document.head.appendChild(style);
return style;
}

public HTMLStyleElement injectStyleSheetAtStart() {
HTMLStyleElement style = createElement(styleBody);
DomGlobal.document.head.insertBefore(style, DomGlobal.document.head.firstChild);
return style;
}

}
private final String styleBody;

public static StyleInjector injectStyleSheet(String contents) {
return new StyleInjector(contents);
}

private StyleInjector(String styleBody) {
this.styleBody = styleBody;
}

private HTMLStyleElement createElement(String contents) {
HTMLStyleElement style = (HTMLStyleElement) DomGlobal.document.createElement("style");
style.setAttribute("language", "text/css");
style.innerHTML = contents;
return style;
}

public HTMLStyleElement injectStyleSheet() {
HTMLStyleElement style = createElement(styleBody);
DomGlobal.document.head.appendChild(style);
return style;
}

public HTMLStyleElement injectStyleSheetAtStart() {
HTMLStyleElement style = createElement(styleBody);
DomGlobal.document.head.insertBefore(style, DomGlobal.document.head.firstChild);
return style;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2010 Google Inc.
*
* 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 org.treblereel.j2cl.commons;

import static org.junit.Assert.assertEquals;

import com.google.j2cl.junit.apt.J2clTestInput;
import elemental2.dom.DomGlobal;
import elemental2.dom.HTMLScriptElement;
import jsinterop.base.Js;
import org.junit.Test;
import org.treblereel.j2cl.processors.common.injectors.ScriptInjector;

@J2clTestInput(ScriptInjectorTest.class)
public class ScriptInjectorTest {

@Test
public void testInjectScript() {
String jsCode = "function myFunction() { return 'Hello, world!'; }";
ScriptInjector.fromString(jsCode).setWindow(ScriptInjector.TOP_WINDOW).inject();
String result = ((Window) Js.uncheckedCast(DomGlobal.window)).myFunction();
assertEquals("Hello, world!", result);
}

@Test
public void testInjectScriptUrl() {
ScriptInjector.fromUrl(
"test_function.js",
new ScriptInjector.Callback() {
@Override
public void accept(HTMLScriptElement htmlScriptElement) {
String result = ((Window) Js.uncheckedCast(DomGlobal.window)).myFunction2();
assertEquals("TEST2", result);
}
},
new ScriptInjector.Callback() {
@Override
public void accept(HTMLScriptElement htmlScriptElement) {
DomGlobal.console.error("Error loading script");
}
})
.setWindow(ScriptInjector.TOP_WINDOW)
.inject();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2010 Google Inc.
*
* 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 org.treblereel.j2cl.commons;

import static org.junit.Assert.assertEquals;

import com.google.j2cl.junit.apt.J2clTestInput;
import elemental2.dom.DomGlobal;
import elemental2.dom.HTMLDivElement;
import jsinterop.base.Js;
import org.junit.Test;
import org.treblereel.j2cl.processors.common.injectors.StyleInjector;

@J2clTestInput(StyleInjectorTest.class)
public class StyleInjectorTest {

@Test
public void testStyleInjection() {
String css = ".myText { font-weight: bold; }";

StyleInjector.injectStyleSheet(css).injectStyleSheet();

HTMLDivElement testElement = (HTMLDivElement) DomGlobal.document.createElement("div");
testElement.id = "testElement";
testElement.className = "myText";
testElement.textContent = "Hello, world!";
DomGlobal.document.body.append(testElement);

HTMLDivElement tested = (HTMLDivElement) DomGlobal.document.getElementById("testElement");

assertEquals("myText", tested.className);
Window window = Js.uncheckedCast(DomGlobal.window);

assertEquals("700", window.getComputedStyle(tested).fontWeight); // alias for bold
}

@Test
public void testStyleInjectionAtStart() {
String css = ".myText { background-color: yellow; }";

StyleInjector.injectStyleSheet(css).injectStyleSheetAtStart();

HTMLDivElement tested = (HTMLDivElement) DomGlobal.document.getElementById("testElement");
assertEquals("myText", tested.className);

Window window = Js.uncheckedCast(DomGlobal.window);

assertEquals("700", window.getComputedStyle(tested).fontWeight); // alias for bold
assertEquals(
"rgb(255, 255, 0)", window.getComputedStyle(tested).backgroundColor); // code for yellow
assertEquals(css, DomGlobal.document.head.firstChild.textContent);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2010 Google Inc.
*
* 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 org.treblereel.j2cl.commons;

import elemental2.core.Function;
import elemental2.core.Reflect;
import elemental2.dom.CSSStyleDeclaration;
import elemental2.dom.Element;
import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsOverlay;
import jsinterop.annotations.JsType;

@JsType(isNative = true, namespace = "<global>")
public class Window {

@JsMethod
public native CSSStyleDeclaration getComputedStyle(Element elt);

@JsOverlay
public final String myFunction() {
Function f = (Function) Reflect.get(this, "myFunction");
Object result = f.bind(this).apply();
return (String) result;
}

@JsOverlay
public final String myFunction2() {
Function f = (Function) Reflect.get(this, "myFunction2");
Object result = f.bind(this).apply();
return (String) result;
}
}
1 change: 1 addition & 0 deletions tests/commons/src/test/resources/public/test_function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
function myFunction2() { return 'TEST2'; }

0 comments on commit fecceaa

Please sign in to comment.