package org.angularjs.codeInsight; import com.intellij.lang.javascript.JSTestUtils; import com.intellij.lang.javascript.dialects.JSLanguageLevel; import com.intellij.lang.javascript.psi.JSLiteralExpression; import com.intellij.lang.javascript.psi.JSProperty; import com.intellij.lang.javascript.psi.JSPsiNamedElementBase; import com.intellij.lang.javascript.psi.impl.JSOffsetBasedImplicitElement; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import org.angularjs.AngularTestUtil; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import java.util.List; /** * @author Irina.Chernushina on 2/12/2016. */ public class AngularUiRouterTest extends LightPlatformCodeInsightFixtureTestCase { @Override protected String getTestDataPath() { return AngularTestUtil.getBaseTestDataPath(getClass()) + "uiRouter"; } public void testSimpleViewCompletion() throws Exception { final List<String> variants = myFixture.getCompletionVariants("simpleView.completion.js", "one.html", "two.html", "angular.js"); Assert.assertEquals("menuTip", variants.get(0)); } public void testPartialTypedViewCompletion() throws Exception { final List<String> variants = myFixture.getCompletionVariants("partialTypedView.completion.js", "one.html", "two.html", "angular.js"); Assert.assertEquals("menuTip", variants.get(0)); } public void testPartialTypedViewNavigation() throws Exception { final PsiFile[] files = myFixture.configureByFiles("partialTypedView.navigation.js", "one.html", "two.html", "angular.js"); myFixture.doHighlighting(); testNavigationToMenuTip(files[0]); } public void testNoNavigationFromViews() throws Exception { //when there is not a views definition final PsiFile[] files = myFixture.configureByFiles("noNavigationFromViews.js", "angular.js"); myFixture.doHighlighting(); final PsiElement another = getReferenceByTextAround(files[0], "another").resolve(); Assert.assertTrue(another instanceof JSProperty); Assert.assertEquals("another", ((JSProperty) another).getName()); final PsiElement boring = getReferenceByTextAround(files[0], "boring").resolve(); Assert.assertTrue(boring instanceof JSProperty); Assert.assertEquals("boring", ((JSProperty) boring).getName()); } private void testNavigationToMenuTip(PsiFile file) { final String str = "'menuTip'"; final PsiReference reference = getReferenceByTextAround(file, str); Assert.assertEquals(StringUtil.unquoteString(str), reference.getCanonicalText()); final PsiElement resolve = reference.resolve(); Assert.assertNotNull(resolve); Assert.assertEquals("one.html", resolve.getContainingFile().getName()); Assert.assertEquals(StringUtil.unquoteString(str), ((JSPsiNamedElementBase) resolve).getName()); } public void testInnerPropertyControllerAs() throws Exception { final List<String> variants = myFixture.getCompletionVariants("innerPropertyControllerAs.completion.js", "one.html", "two.html", "angular.js"); Assert.assertEquals("testMe", variants.get(0)); } public void testControllerRedefinitionSyntaxOutside() throws Exception { final List<String> variants = myFixture.getCompletionVariants("controllerRedefinitionSyntaxOutside.completion.js", "one.html", "two.html", "angular.js"); Assert.assertTrue(variants.contains("testMe")); Assert.assertTrue(variants.contains("something")); } public void testControllerRedefinitionSyntaxNavigation() throws Exception { final String mainFile = "controllerRedefinitionSyntax.navigation.js"; final PsiFile[] files = myFixture.configureByFiles(mainFile, "one.html", "two.html", "angular.js"); myFixture.doHighlighting(); final String str = "'testMe as something'"; final PsiElement element = getElement(files[0], str); Assert.assertEquals(str, element.getText()); Assert.assertTrue(element.getParent() instanceof JSLiteralExpression); Assert.assertTrue(element.getParent().getParent() instanceof JSProperty); final PsiReference[] references = element.getParent().getReferences(); Assert.assertEquals(1, references.length); Assert.assertEquals("testMe", references[0].getCanonicalText()); final PsiElement resolve = references[0].resolve(); Assert.assertNotNull(resolve); Assert.assertEquals(mainFile, resolve.getContainingFile().getName()); Assert.assertEquals("testMe", ((JSPsiNamedElementBase) resolve).getName()); } public void testNavigationToNamedView() throws Exception { final PsiFile[] files = myFixture.configureByFiles("appWithViews.navigation.js", "one.html", "two.html", "angular.js"); myFixture.doHighlighting(); testNavigationToMenuTip(files[0]); } @NotNull private PsiReference getReferenceByTextAround(PsiFile file, String str) { final PsiElement element = getElement(file, str); Assert.assertTrue(element.getParent() instanceof JSProperty); PsiReference reference = element.getParent().getReference(); Assert.assertNotNull(reference); return reference; } @NotNull private PsiElement getElement(PsiFile file, String str) { final int idx = myFixture.getEditor().getDocument().getText().indexOf(str); Assert.assertTrue(idx > 0); final PsiElement element = file.findElementAt(idx); Assert.assertNotNull(element); return element; } public void testNavigationToDefaultView() throws Exception { final PsiFile[] files = myFixture.configureByFiles("appWithViews.navigation.js", "one.html", "two.html", "angular.js"); myFixture.doHighlighting(); emptyViewNavigatesToFilesDefaultView(files[0], "'one.html'"); emptyViewNavigatesToFilesDefaultView(files[0], "'two.html'"); } private void emptyViewNavigatesToFilesDefaultView(PsiFile file, String str) { final PsiElement inObj = getElement(file, str); Assert.assertTrue(inObj.getParent() instanceof JSLiteralExpression); Assert.assertTrue(inObj.getParent().getParent() instanceof JSProperty); final JSProperty templateUrl = (JSProperty)inObj.getParent().getParent(); Assert.assertEquals("templateUrl", templateUrl.getName()); final PsiElement parentProperty = templateUrl.getParent().getParent(); Assert.assertTrue(parentProperty instanceof JSProperty); final PsiReference reference = parentProperty.getReference(); Assert.assertNotNull(reference); Assert.assertEquals("", reference.getCanonicalText()); final PsiElement resolve = reference.resolve(); Assert.assertNotNull(resolve); Assert.assertEquals(StringUtil.unquoteString(str), resolve.getContainingFile().getName()); Assert.assertEquals("", ((JSPsiNamedElementBase) resolve).getName()); final PsiElement element = ((JSOffsetBasedImplicitElement)resolve).getElementAtOffset(); Assert.assertEquals("ui-view", element.getText()); } // states public void testStatesCompletion() throws Exception { final List<String> variants = myFixture.getCompletionVariants("stateReferences.completion.html", "appStates.js", "angular.js"); Assert.assertTrue(variants.contains("one")); Assert.assertTrue(variants.contains("two")); Assert.assertTrue(variants.contains("two.words")); } public void testStatesNavigation() throws Exception { final PsiFile[] files = myFixture.configureByFiles("stateReferences.navigation.html", "appStates.js", "angular.js"); myFixture.doHighlighting(); checkNavigation(files[0], "one", null, "appStates.js"); checkNavigation(files[0], "two", null, "appStates.js"); checkNavigation(files[0], "two.words", null, "appStates.js"); checkNavigation(files[0], ".words", "two.words", "appStates.js"); } public void testStatesNavigationForStatesWithNameInObject() throws Exception { final PsiFile[] files = myFixture.configureByFiles("stateReferences.navigation.html", "appStateWithNameInObject.js", "angular.js"); myFixture.doHighlighting(); checkNavigation(files[0], "one", null, "appStateWithNameInObject.js"); checkNavigation(files[0], "two", null, "appStateWithNameInObject.js"); checkNavigation(files[0], "two.words", null, "appStateWithNameInObject.js"); checkNavigation(files[0], ".words", "two.words", "appStateWithNameInObject.js"); } public void testGenericStatesAsArrayOfReferences() throws Exception { JSTestUtils.testWithinLanguageLevel(JSLanguageLevel.ES6, myFixture.getProject(), () -> { final PsiFile[] files = myFixture.configureByFiles("genericStateReferences.navigation.html", "appStatesGeneric.js", "homeState.js", "loginState.js", "angular.js"); myFixture.doHighlighting(); checkNavigation(files[0], "home", null, "homeState.js"); checkNavigation(files[0], "login", null, "loginState.js"); }); } public void testGenericStatesByVar() throws Exception { JSTestUtils.testWithinLanguageLevel(JSLanguageLevel.ES6, myFixture.getProject(), () -> { final PsiFile[] files = myFixture.configureByFiles("genericStateReferences.navigation.html", "appStatesGenericVar.js", "angular.js"); myFixture.doHighlighting(); checkNavigation(files[0], "home", null, "appStatesGenericVar.js"); checkNavigation(files[0], "login", null, "appStatesGenericVar.js"); }); } private void checkNavigation(PsiFile file, String state, String referencedTextExpected, String appStatesFileName) { referencedTextExpected = referencedTextExpected == null ? state : referencedTextExpected; final PsiElement inObj = getElement(file, "ui-sref=\"" + state + "\""); Assert.assertEquals("ui-sref", inObj.getText()); Assert.assertTrue(inObj.getParent() instanceof XmlAttribute); final XmlAttributeValue element = ((XmlAttribute)inObj.getParent()).getValueElement(); Assert.assertNotNull(element); final PsiReference reference = element.getReference(); Assert.assertEquals(state, reference.getCanonicalText()); final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false); if (results.length > 1) { for (ResolveResult result : results) { final PsiElement resolvedElement = result.getElement(); Assert.assertEquals(appStatesFileName, resolvedElement.getContainingFile().getName()); if (StringUtil.equals(referencedTextExpected, StringUtil.unquoteString(resolvedElement.getNavigationElement().getText()))) { return; } } Assert.assertTrue(false); } else { final PsiElement resolve = reference.resolve(); Assert.assertNotNull(state, resolve); Assert.assertEquals(appStatesFileName, resolve.getContainingFile().getName()); Assert.assertEquals(referencedTextExpected, StringUtil.unquoteString(resolve.getNavigationElement().getText())); } } }