/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * 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 io.appium.uiautomator2.utils; import androidx.test.uiautomator.UiObjectNotFoundException; import androidx.test.uiautomator.UiSelector; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import io.appium.uiautomator2.common.exceptions.UiAutomator2Exception; import io.appium.uiautomator2.common.exceptions.UiSelectorSyntaxException; import static org.hamcrest.Matchers.containsString; @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) public class UiSelectorParserTests { @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void shouldBeAbleToParseSimpleUiSelector() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().className(android.widget.TextView.class).text("test") .clickable(false).selected(true).index(1); UiSelector actual = new UiSelectorParser("new UiSelector().className(android.widget" + ".TextView).text(\"test\").clickable(false).selected(true).index(1)").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseUiSelectorWithSpaces() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text("test").clickable(false); UiSelector actual = new UiSelectorParser( " new UiSelector() . text ( \"test\" ) . clickable ( false ) ").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseUiSelectorWithoutNewKeyword() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text("test"); UiSelector actual = new UiSelectorParser("UiSelector().text(\"test\")").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseUiSelectorWithoutConstructor() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text("test"); UiSelector actual = new UiSelectorParser("text(\"test\")").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseLiteralsWithParentheses() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text(")test(test)("); UiSelector actual = new UiSelectorParser("new UiSelector().text(\")test(test)(\")").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseLiteralsWithBrakes() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text("te\nst"); UiSelector actual = new UiSelectorParser("new UiSelector().text(\"te\nst\")").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseLiteralsWithQuotes() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text("\"\"tes\\t(\"test)("); UiSelector actual = new UiSelectorParser( "new UiSelector().text(\"\\\"\\\"tes\\t(\\\"test)(\")").parse(); assertSame(expected, actual); } @Test public void shouldBeAbleToParseNestedUiSelector() throws UiSelectorSyntaxException, UiObjectNotFoundException { UiSelector expected = new UiSelector().text("test").childSelector(new UiSelector() .checkable(true)); UiSelector actual = new UiSelectorParser( "new UiSelector().text(\"test\").childSelector(new UiSelector()" + ".checkable(true))").parse(); assertSame(expected, actual); } @Test() public void shouldThrowExceptionOnUnclosedParenthesis() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Unclosed paren in expression"); new UiSelectorParser("new UiSelector().text(\"test\"()").parse(); } @Test() public void shouldThrowExceptionIfNoPeriodAfterConstructor() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Expected \".\" at position 16"); new UiSelectorParser("new UiSelector()text(\"test\")").parse(); } @Test() public void shouldThrowExceptionIfNoSuitableConstructor() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("UiSelector has no suitable constructor"); new UiSelectorParser("new UiSelector(1, true).text(\"test\")").parse(); } @Test() public void shouldThrowExceptionIfNoOpeningParenthesisAfterMethodName() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("No opening parenthesis after method name at position 17"); new UiSelectorParser("new UiSelector().text)\"test\")").parse(); } @Test() public void shouldThrowExceptionOnMethodWithInvalidArgsCount() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage( "`UiSelector` doesn't have suitable method `text` with arguments [\"test1\", 5]"); new UiSelectorParser("new UiSelector().text(\"test1\", 5)").parse(); } @Test() public void shouldThrowExceptionOnInvalidMethod() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("UiSelector has no `test` method"); new UiSelectorParser("new UiSelector().test(5)").parse(); } @Test() public void shouldThrowExceptionIfBooleanArgHasInvalidType() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("invalidArg is not a boolean"); new UiSelectorParser("new UiSelector().checkable(invalidArg)").parse(); } @Test() public void shouldThrowExceptionIfStringArgHasInvalidType() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("invalidArg is not a string"); new UiSelectorParser("new UiSelector().text(invalidArg)").parse(); } @Test() public void shouldThrowExceptionIfIntegerArgHasInvalidType() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("invalidArg is not a integer"); new UiSelectorParser("new UiSelector().index(invalidArg)").parse(); } @Test() public void shouldThrowExceptionIfArgTypeIsNotSupported() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Could not parse"); new UiSelectorParser("new UiSelector().equals(test)").parse(); } @Test() public void shouldThrowExceptionIfClassNotFound() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage(containsString("com.fake.class")); new UiSelectorParser("new UiSelector().className(com.fake.class)").parse(); } @Test() public void shouldThrowExceptionIfMethodIsNotAccessible() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Problem using reflection to call `getInt` method"); new UiSelectorParser("new UiSelector().getInt(5)").parse(); } @Test() public void shouldThrowExceptionIfMethodDoesNotReturnUiSelector() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Unsupported return value type:`String`."); new UiSelectorParser("new UiSelector().index(0).toString()").parse(); } @Test() public void shouldThrowExceptionIfMethodThrowsException() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiAutomator2Exception.class); expectedException.expectMessage("java.util.regex.PatternSyntaxException: " + "Unclosed character class near index 0"); new UiSelectorParser("new UiSelector().resourceIdMatches(\"[\")").parse(); } @Test() public void shouldThrowExceptionIfMethodNameIsMissing() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Missing method name at position 17"); new UiSelectorParser("new UiSelector().(0)").parse(); } @Test() public void shouldThrowExceptionIfArgumentIsMissing() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Missing argument at position 22"); new UiSelectorParser("new UiSelector().index(,1)").parse(); } @Test() public void shouldThrowExceptionIfLastArgumentIsMissing() throws UiSelectorSyntaxException, UiObjectNotFoundException { expectedException.expect(UiSelectorSyntaxException.class); expectedException.expectMessage("Missing argument at position 24"); new UiSelectorParser("new UiSelector().index(0,)").parse(); } private void assertSame(UiSelector expected, UiSelector actual) { Assert.assertEquals(expected.toString(), actual.toString()); } }