blob: 001d37ed7c9d8a31a608f205a8e2b31152c95ea5 [file] [log] [blame]
/*
* Copyright 2008 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 com.google.gwt.resources.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.resources.client.CssResource.Import;
import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
import com.google.gwt.resources.client.CssResource.Shared;
/**
* Contains various full-stack tests of the CssResource system.
*/
public class CSSResourceTest extends GWTTestCase {
interface ChildResources extends Resources {
ChildResources INSTANCE = GWT.create(ChildResources.class);
@Override
@Source("16x16.png")
ImageResource spriteMethod();
}
interface ConcatenatedResources extends ClientBundle {
@Source(value = {"concatenatedA.css", "concatenatedB.css"})
CssResource css();
}
interface CssWithDefines extends CssResource {
String colorString();
double lengthFloat();
int lengthInt();
String lengthString();
int overrideInt();
@ClassName("overrideInt")
String overrideIntClass();
double percentFloat();
int percentInt();
double rawDouble();
float rawFloat();
int rawInt();
String multiValueBorderDef();
}
/**
* Regenerate this interface by running InterfaceGenerator over test.css.
*/
interface FullTestCss extends CssResource {
String affectedBySprite();
String blahA();
String css3Color();
String externalA();
String externalB();
String externalC();
String extraSpriteClass();
@ClassName("FAIL")
String fAIL();
@ClassName("may-combine")
String mayCombine();
@ClassName("may-combine2")
String mayCombine2();
@ClassName("may-merge")
String mayMerge();
@ClassName("may-not-combine")
String mayNotCombine();
@ClassName("may-not-combine2")
String mayNotCombine2();
@ClassName("may-not-merge")
String mayNotMerge();
@ClassName("may-not-merge-or-combine-because-of-this")
String mayNotMergeOrCombineBecauseOfThis();
String multiClassA();
String multiClassB();
String nestedSprite();
String replacement();
@ClassName("replacement-not-java-ident")
String replacementNotJavaIdent();
String spriteClass();
@ClassName("this-does-not-matter")
String thisDoesNotMatter();
}
interface HasDescendants extends CssResource {
String foo();
}
interface MyCssResource extends CssResource, MyNonCssResource {
@Override
@ClassName("replacement-not-java-ident")
String nameOverride();
}
interface MyCssResourceA extends MyCssResource, SharedClasses {
String local();
// This shouldn't make a difference
@Override
String replacement();
}
@ImportedWithPrefix("gwt-MyCssResourceB")
interface MyCssResourceB extends MyCssResource, SharedClasses {
String local();
@Override
String sharedOverrideClass();
}
/*
* Check type inheritance.
*/
interface MyCssResourceWithSprite extends MyCssResource {
String externalA();
String extraSpriteClass();
String multiClassA();
String multiClassB();
}
interface MyNonCssResource {
String nameOverride();
String replacement();
}
/**
* CssResource used to test that the compiler will pick up the right resource (.css or .gss)
* according to the module configuration.
*/
interface ResourceFileChooser extends CssResource {
String myClass();
}
interface NestedResources extends ClientBundle {
@Source("32x32.png")
DataResource dataMethod();
@Source("16x16.png")
ImageResource spriteMethod();
}
interface Resources extends ClientBundle {
Resources INSTANCE = GWT.create(Resources.class);
@Source("siblingTestA.css")
MyCssResourceA a();
@Source("siblingTestB.css")
MyCssResourceB b();
@Source("test.css")
FullTestCss css();
@Source("32x32.png")
CustomDataResource customDataMethod();
@Source("16x16.png")
CustomImageResource customSpriteMethod();
@Source("32x32.png")
DataResource dataMethod();
// Test default extensions
CssWithDefines deftest();
@Source("unrelatedDescendants.css")
@Import(value = {MyCssResourceA.class, MyCssResourceB.class})
HasDescendants descendants();
// Make sure an empty, no-op CssResource works
CssResource empty();
// Test nested ClientBundles
NestedResources nested();
@Source("16x16.png")
ImageResource spriteMethod();
ResourceFileChooser resourceFileChooser();
@Source("resourceFileChooser.css")
ResourceFileChooser resourceFileChooserWithSourceTargetingOneCssFile();
@Source("resourceFileChooser.gss")
ResourceFileChooser resourceFileChooserWithSourceTargetingOneGssFile();
@Source({"resourceFileChooser.css", "resourceFileChooser2.css"})
ResourceFileChooser resourceFileChooserWithSourceTargetingCssFiles();
@Source({"resourceFileChooser.gss", "resourceFileChooser2.gss"})
ResourceFileChooser resourceFileChooserWithSourceTargetingGssFiles();
@Source({"resourceFileChooser.css", "resourceFileChooser2.css", "resourceFileChooser3.css"})
ResourceFileChooser resourceFileChooserWithSourceTargetingCssFilesWithoutGssFile();
}
interface SharedBase extends CssResource {
String unsharedClass();
}
@ImportedWithPrefix("gwt-Shared")
@Shared
interface SharedClasses extends SharedBase {
String sharedClass();
String sharedOverrideClass();
}
interface SiblingResources extends ClientBundle {
@Source("siblingTestA.css")
MyCssResourceA a();
@Source("siblingTestB.css")
MyCssResourceB b();
}
public static String red() {
return "orange";
}
@Override
public String getModuleName() {
return "com.google.gwt.resources.ResourcesCssTest";
}
public void report(String s) {
// Can be filled in if debugging.
System.out.println(s);
}
public void testChildResources() {
Resources parentResource = GWT.create(Resources.class);
ChildResources childResource = GWT.create(ChildResources.class);
assertEquals(parentResource.dataMethod().getName(),
childResource.dataMethod().getName());
}
public void testConcatenatedResource() {
ConcatenatedResources r = GWT.create(ConcatenatedResources.class);
String text = r.css().getText();
assertTrue(text.contains(".partA"));
assertTrue(text.contains(".partB"));
}
public void testCss() {
FullTestCss css = Resources.INSTANCE.css();
String text = css.getText();
report(text);
// Check the sprite
assertTrue(text.contains("height:16px"));
assertTrue(text.contains("width:16px"));
// Check the value() expansion
assertTrue(text.contains("offset-left:\"guard\" 16px !important;"));
assertTrue(text.contains("offset:16px 16px;"));
// Make sure renaming works
assertFalse("replacement".equals(css.replacement()));
assertTrue(text.contains("." + css.replacement()));
assertTrue(text.contains("." + css.replacement() + ":after"));
assertTrue(text.contains("." + css.replacementNotJavaIdent()));
// Make sure renaming for multi-class selectors (.foo.bar) works
assertFalse("multiClassA".equals(css.multiClassA()));
assertFalse("multiClassB".equals(css.multiClassB()));
assertTrue(text.contains("." + css.multiClassA() + "." + css.multiClassB()));
// Check static if evaluation
assertTrue(text.contains("static:PASSED;"));
assertFalse(text.contains("FAIL"));
// Check runtime if evaluation
assertTrue(text.contains("runtime:PASSED;"));
// Check interestingly-named idents
assertTrue(text.contains("-some-wacky-extension"));
assertTrue(text.contains("another-extension:-bar"));
assertTrue(text.contains("-unescaped-hyphen:-is-better"));
assertTrue(text.contains("with_underscore:_is_better"));
assertTrue(text.contains("ns\\:tag"));
assertTrue(text.contains("ns\\:tag:pseudo"));
assertTrue(text.contains("ns\\:tag::double-pseudo"));
assertTrue(text.contains("ns\\:tag::-webkit-scrollbar"));
// Check escaped string values
assertTrue(text.contains("\"Hello\\\\\\\" world\""));
// Check values
assertFalse(text.contains("0.0;"));
assertFalse(text.contains("0.0px;"));
assertFalse(text.contains("0px;"));
assertTrue(text.contains("background-color:#fff;"));
assertTrue(text.contains("content:\"bar\";"));
// Check invalid CSS values
assertTrue(text.contains("top:expression(document.compatMode==\"CSS1Compat\" ? documentElement.scrollTop:document.body.scrollTop \\ 2);"));
// Check data URL expansion
assertTrue(text.contains("backgroundTopLevel:url('"
+ Resources.INSTANCE.dataMethod().getSafeUri().asString() + "')"));
assertTrue(text.contains("backgroundNested:url('"
+ Resources.INSTANCE.nested().dataMethod().getSafeUri().asString() + "')"));
assertTrue(text.contains("backgroundCustom:url('"
+ Resources.INSTANCE.customDataMethod().getSafeUri().asString() + "')"));
assertTrue(text.contains("backgroundImage:url('"
+ Resources.INSTANCE.spriteMethod().getSafeUri().asString() + "')"));
assertTrue(text.contains("backgroundImageNested:url('"
+ Resources.INSTANCE.nested().spriteMethod().getSafeUri().asString() + "')"));
assertTrue(text.contains("backgroundImageCustom:url('"
+ Resources.INSTANCE.customSpriteMethod().getSafeUri().asString() + "')"));
// Check @eval expansion
assertTrue(text.contains(red() + ";"));
// Check @def substitution
assertTrue(text.contains("50px"));
// Check @def substitution into function arguments
// Note that GWT transforms rgb(R, G, B) into #rrggbb form.
assertTrue(text.contains("-moz-linear-gradient(left, #007f00, #00007f 50%);"));
assertTrue(text.contains("-webkit-linear-gradient(left, #007f00, #00007f 50%);"));
assertTrue(text.contains("linear-gradient(to right, #007f00, #00007f 50%);"));
// Check merging semantics
assertTrue(text.indexOf("static:PASSED") < text.indexOf("runtime:PASSED"));
assertTrue(text.indexOf("before:merge") != -1);
assertTrue(text.indexOf("before:merge") < text.indexOf("after:merge"));
assertTrue(text.indexOf("." + css.mayCombine() + ",." + css.mayCombine2()) != -1);
assertTrue(text.indexOf("merge:merge") != -1);
assertTrue(text.indexOf("merge:merge") < text.indexOf("."
+ css.mayNotCombine()));
assertTrue(text.indexOf("may-not-combine") < text.indexOf("prevent:true"));
assertTrue(text.indexOf("prevent:true") < text.indexOf("prevent-merge:true"));
assertTrue(text.indexOf("prevent:true") < text.indexOf("."
+ css.mayNotCombine2()));
// Check commonly-used CSS3 constructs
assertTrue(text.contains("background-color:rgba(0, 0, 0, 0.5);"));
// Check external references
assertEquals("externalA", css.externalA());
assertTrue(text.contains(".externalA ." + css.replacement()));
assertTrue(text.contains(".externalB"));
assertTrue(text.contains(".externalC"));
// Test font-face contents
assertTrue(text.contains("url(Foo.otf) format(\"opentype\");"));
}
public void testDefines() {
Resources r = GWT.create(Resources.class);
CssWithDefines defines = r.deftest();
assertEquals(1, defines.rawInt());
assertEquals(1.5F, defines.rawFloat());
assertEquals(1.5, defines.rawDouble());
assertEquals(50, defines.lengthInt());
assertEquals(1.5, defines.lengthFloat());
assertEquals(50, defines.percentInt());
assertEquals(50.5, defines.percentFloat());
assertEquals("100px", defines.lengthString());
assertEquals("#f00", defines.colorString());
assertEquals(10, defines.overrideInt());
assertNotNull(defines.overrideIntClass());
assertFalse("10px".equals(defines.overrideIntClass()));
assertFalse("10".equals(defines.overrideIntClass()));
assertTrue(
// css
"1px solid rgba(0, 0, 0, 0.2)".equals(defines.multiValueBorderDef()) ||
// gss
"1px solid rgba(0,0,0,0.2)".equals(defines.multiValueBorderDef())
);
}
public void testEnsureInjected() {
Resources r = GWT.create(Resources.class);
assertTrue(r.empty().ensureInjected());
r = GWT.create(Resources.class);
assertFalse(r.empty().ensureInjected());
r = GWT.create(ChildResources.class);
assertTrue(r.empty().ensureInjected());
}
public void testFileChoice() {
// resource without @Source annotation
ResourceFileChooser css = Resources.INSTANCE.resourceFileChooser();
// should use the css file.
String expectedCss = "." + css.myClass() + "{width:5px;}";
assertEquals(expectedCss, css.getText());
// resource with @Source annotation targeting one .css file
css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneCssFile();
// should use the css file.
assertEquals(expectedCss, css.getText());
// resource with @Source annotation targeting one .gss file
css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneGssFile();
// should use the css file instead of the gss file
assertEquals(expectedCss, css.getText());
// resource with @Source annotation targeting several .css files
css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingCssFiles();
// should use the css files.
expectedCss = "." + css.myClass() + "{width:5px;padding:5px;}";
assertEquals(expectedCss, css.getText());
// resource with @Source annotation targeting several .gss files
css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingGssFiles();
// should use the css files instead of the gss files
assertEquals(expectedCss, css.getText());
}
public void testMultipleBundles() {
Resources r1 = GWT.create(Resources.class);
SiblingResources r2 = GWT.create(SiblingResources.class);
assertEquals(r1.a().replacement(), r2.a().replacement());
assertEquals(r1.b().replacement(), r2.b().replacement());
assertEquals(r1.a().sharedClass(), r2.b().sharedClass());
assertFalse(r1.a().sharedOverrideClass().equals(
r2.b().sharedOverrideClass()));
assertFalse(r1.a().unsharedClass().equals(r2.b().unsharedClass()));
String text = r1.descendants().getText();
report(text);
assertEquals("foo", r1.descendants().foo());
assertTrue(text.contains("." + r1.a().local() + " ." + r1.b().local()));
assertTrue(text.contains("." + r1.descendants().foo()));
assertTrue(text.contains(".bar"));
}
public void testSiblingCSS() {
SiblingResources r = GWT.create(SiblingResources.class);
assertFalse(r.a().replacement().equals(r.b().replacement()));
assertFalse(r.a().local().equals(r.b().local()));
String a = r.a().getText();
String b = r.b().getText();
report(a);
report(b);
assertTrue(a.contains(".other"));
assertTrue(b.contains(".other"));
assertTrue(a.contains(r.a().local()));
assertTrue(b.contains(r.b().local()));
assertFalse(a.contains(r.b().local()));
assertFalse(b.contains(r.a().local()));
}
}