package org.jetbrains.plugins.cucumber.psi; import com.intellij.lexer.Lexer; import com.intellij.psi.tree.IElementType; import junit.framework.TestCase; import org.jetbrains.plugins.cucumber.psi.GherkinLexer; import org.jetbrains.plugins.cucumber.psi.GherkinTokenTypes; import org.jetbrains.plugins.cucumber.psi.PlainGherkinKeywordProvider; import java.util.Arrays; import java.util.Collection; import java.util.List; /** * @author yole */ public class GherkinLexerTest extends TestCase { public void testComment() throws Exception { doTest("# foo", "COMMENT:0-5"); } public void testWhitespaceComment() throws Exception { doTest(" # foo", "WHITE_SPACE:0-3", "COMMENT:3-8"); } public void testKeyword() throws Exception { doTest("Feature", "FEATURE_KEYWORD:0-7"); } public void testTextAfterKeyword() throws Exception { doTest("Feature: Feature", "FEATURE_KEYWORD:0-7", "COLON:7-8", "WHITE_SPACE:8-9", "TEXT:9-16"); } public void testNoSpaceAfterKeyword() throws Exception { doTest("Featureee", "TEXT:0-9"); } public void testSpaceAfterKeyword() throws Exception { doTest("Given foo", "STEP_KEYWORD:0-5", "WHITE_SPACE:5-6", "TEXT:6-9"); } public void testSpaceAtEndOfLine() throws Exception { doTest("Given foo \n", "STEP_KEYWORD:0-5", "WHITE_SPACE:5-6", "TEXT:6-9", "WHITE_SPACE:9-13"); } public void testTag() throws Exception { doTest("@foo", "TAG:0-4"); } public void testPyString() throws Exception { doTest("\"\"\"\n bar \"\"\"", "PYSTRING_QUOTES:0-3", "PYSTRING_TEXT:3-9", "PYSTRING_QUOTES:9-12"); } public void testTable() throws Exception { doTest("|a|", "PIPE:0-1", "TABLE_CELL:1-2", "PIPE:2-3"); } public void testTable_EscapedBackslash() throws Exception { doTest("|a\\|a|", "PIPE:0-1", "TABLE_CELL:1-5", "PIPE:5-6"); } public void testTable_EscapedBar() throws Exception { doTest("|a\\\\|", "PIPE:0-1", "TABLE_CELL:1-4", "PIPE:4-5"); } public void testTableWhitespace() throws Exception { doTest("|a |", "PIPE:0-1", "TABLE_CELL:1-2", "WHITE_SPACE:2-4", "PIPE:4-5"); } public void testLongKeywordsFirst() throws Exception { doTest("Scenario Outline:", "SCENARIO_OUTLINE_KEYWORD:0-16", "COLON:16-17"); } public void testLanguage() throws Exception { doTest("# language: en-lol\nOH HAI: STUFFING", "COMMENT:0-18", "WHITE_SPACE:18-19", "FEATURE_KEYWORD:19-25", "COLON:25-26", "WHITE_SPACE:26-27", "TEXT:27-35"); } public void testKeywordAtEndOfLine() throws Exception { doTest("Feature:\n Background:\n When foo", "FEATURE_KEYWORD:0-7", "COLON:7-8", "WHITE_SPACE:8-11", "BACKGROUND_KEYWORD:11-21", "COLON:21-22", "WHITE_SPACE:22-27", "STEP_KEYWORD:27-31", "WHITE_SPACE:31-32", "TEXT:32-35"); } public void testAsteriskKeyword() throws Exception { doTest("*", "STEP_KEYWORD:0-1"); } public void testNewStyleSpaceAfterKeyword() throws Exception { doTest("Lorsqu'foo", "STEP_KEYWORD:0-7", "TEXT:7-10"); } public void testStepParameter() throws Exception { doTest("Given test step <param01>", "STEP_KEYWORD:0-5", "WHITE_SPACE:5-6", "TEXT:6-15", "WHITE_SPACE:15-16", "STEP_PARAMETER_BRACE:16-17", "STEP_PARAMETER_TEXT:17-24", "STEP_PARAMETER_BRACE:24-25"); } public void testStepParameterList() throws Exception { doTest("Given test step <param01> word <param02>", "STEP_KEYWORD:0-5", "WHITE_SPACE:5-6", "TEXT:6-15", "WHITE_SPACE:15-16", "STEP_PARAMETER_BRACE:16-17", "STEP_PARAMETER_TEXT:17-24", "STEP_PARAMETER_BRACE:24-25", "WHITE_SPACE:25-26", "TEXT:26-30", "WHITE_SPACE:30-31", "STEP_PARAMETER_BRACE:31-32", "STEP_PARAMETER_TEXT:32-39", "STEP_PARAMETER_BRACE:39-40"); } public void testStepParameterBeforeText() throws Exception { doTest("Given <param01> test <param02>", "STEP_KEYWORD:0-5", "WHITE_SPACE:5-6", "STEP_PARAMETER_BRACE:6-7", "STEP_PARAMETER_TEXT:7-14", "STEP_PARAMETER_BRACE:14-15", "WHITE_SPACE:15-16", "TEXT:16-20", "WHITE_SPACE:20-21", "STEP_PARAMETER_BRACE:21-22", "STEP_PARAMETER_TEXT:22-29", "STEP_PARAMETER_BRACE:29-30"); } public void testStepParameters() { doTest("Given test step <par01> <par01> test", "STEP_KEYWORD:0-5", "WHITE_SPACE:5-6", "TEXT:6-15", "WHITE_SPACE:15-18", "STEP_PARAMETER_BRACE:18-19", "STEP_PARAMETER_TEXT:19-24", "STEP_PARAMETER_BRACE:24-25", "WHITE_SPACE:25-27", "STEP_PARAMETER_BRACE:27-28", "STEP_PARAMETER_TEXT:28-33", "STEP_PARAMETER_BRACE:33-34", "WHITE_SPACE:34-35", "TEXT:35-39"); } public void testPyStringParameters() { doTest("\"\"\"text <param> text\"\"\"", "PYSTRING_QUOTES:0-3", "PYSTRING_TEXT:3-8", "STEP_PARAMETER_BRACE:8-9", "STEP_PARAMETER_TEXT:9-14", "STEP_PARAMETER_BRACE:14-15", "PYSTRING_TEXT:15-20", "PYSTRING_QUOTES:20-23"); } public void testPyStringParametersAndExample() { doTest("\"\"\"text\"\"\" Examples", "PYSTRING_QUOTES:0-3", "PYSTRING_TEXT:3-7", "PYSTRING_QUOTES:7-10", "WHITE_SPACE:10-11", "EXAMPLES_KEYWORD:11-19"); } public void testPyStringWithoutParameters() { doTest("\"\"\"\n" + "<\n" + "\"\"\"\n" + "And step", "PYSTRING_QUOTES:0-3", "PYSTRING_TEXT:3-6", "PYSTRING_QUOTES:6-9", "WHITE_SPACE:9-10", "STEP_KEYWORD:10-13", "WHITE_SPACE:13-14", "TEXT:14-18"); } public void testPyStringWithParameter() { doTest("\"\"\"<>|\"\"\"", "PYSTRING_QUOTES:0-3", "STEP_PARAMETER_BRACE:3-4", "STEP_PARAMETER_BRACE:4-5", "PYSTRING_TEXT:5-6", "PYSTRING_QUOTES:6-9"); } public void testScenarioWithParameter() { doTest( "Feature: test\n" + " Scenario Outline: Opening <scan> Scan Settings", "FEATURE_KEYWORD:0-7", "COLON:7-8", "WHITE_SPACE:8-9", "TEXT:9-13", "WHITE_SPACE:13-16", "SCENARIO_OUTLINE_KEYWORD:16-32", "COLON:32-33", "WHITE_SPACE:33-34", "TEXT:34-41", "WHITE_SPACE:41-42", "STEP_PARAMETER_BRACE:42-43", "STEP_PARAMETER_TEXT:43-47", "STEP_PARAMETER_BRACE:47-48", "WHITE_SPACE:48-49", "TEXT:49-62" ); } public void testUnicodeWhitespace() { doTest("|\u3000\n", "PIPE:0-1", "WHITE_SPACE:1-3"); } private static void doTest(String text, String... expectedTokens) { Lexer lexer = new GherkinLexer(new MockGherkinKeywordProvider()); lexer.start(text); int idx = 0; int tokenPos = 0; while (lexer.getTokenType() != null) { if (idx > expectedTokens.length) fail("Too many tokens"); assertEquals("Token offset mismatch at position " + idx, tokenPos, lexer.getTokenStart()); String tokenName = lexer.getTokenType().toString() + ":" + lexer.getTokenStart() + "-" + lexer.getTokenEnd(); assertEquals("Token mismatch at position " + idx, expectedTokens[idx], tokenName); idx++; tokenPos = lexer.getTokenEnd(); lexer.advance(); } if (idx < expectedTokens.length) fail("Not enough tokens"); } private static class MockGherkinKeywordProvider extends PlainGherkinKeywordProvider { private List<String> myLolcatKeywords = Arrays.asList("OH HAI", "I CAN HAZ", "MISHUN", "MISHUN SRSLY"); private MockGherkinKeywordProvider() { super(); //TODO add custom langs } public Collection<String> getAllKeywords(String language) { return language.equals("en-lol") ? myLolcatKeywords : super.getAllKeywords(language); } @Override public IElementType getTokenType(String language, String keyword) { return language.equals("en-lol") ? GherkinTokenTypes.FEATURE_KEYWORD : super.getTokenType(language, keyword); } public String getBaseKeyword(String language, String keyword) { return language.equals("en-lol") ? "Feature" : super.getBaseKeyword(language, keyword); } } }