Package com.google.javascript.refactoring

Source Code of com.google.javascript.refactoring.RefasterJsScannerTest

/*
* Copyright 2014 The Closure Compiler Authors.
*
* 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.javascript.refactoring;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.rhino.Node;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
* Unit tests for {RefasterJsScanner}.
*
* The RefasterJsScanner must be initialized with the compiler used to compile the
* test code so that the types from the template and the test code match.
* Therefore, it is important to compile the test code first before creating the
* scanner, and to reuse the same compiler object for both the test code and the
* scanner.
*
* @author mknichel@google.com (Mark Knichel)
*/
// TODO(mknichel): Make this a SmallTest by disabling threads in the JS Compiler.

@RunWith(JUnit4.class)
public class RefasterJsScannerTest {

  @Test
  public void testInitialize_missingTemplates() throws Exception {
    try {
      Compiler compiler = createCompiler();
      compileTestCode(compiler, "", "");
      createScanner(compiler, "");
      fail("An exception should have been thrown for missing templates.");
    } catch (IllegalStateException expected) {}

    try {
      Compiler compiler = createCompiler();
      compileTestCode(compiler, "", "");
      createScanner(compiler, "function notATemplate() {}");
      fail("An exception should have been thrown for missing templates.");
    } catch (IllegalStateException expected) {}

    try {
      Compiler compiler = createCompiler();
      compileTestCode(compiler, "", "");
      createScanner(compiler, "function after_foo() {}");
      fail("An exception should have been thrown for missing templates.");
    } catch (IllegalStateException expected) {}
  }

  @Test
  public void testInitialize_missingAfterTemplate() throws Exception {
    try {
      Compiler compiler = createCompiler();
      compileTestCode(compiler, "", "");
      createScanner(compiler, "function before_foo() {'bar'};");
      fail("An exception should have been thrown for missing the after template.");
    } catch (IllegalStateException expected) {}
  }

  @Test
  public void testInitialize_duplicateTemplateName() throws Exception {
    try {
      Compiler compiler = createCompiler();
      compileTestCode(compiler, "", "");
      createScanner(compiler, "function before_foo() {}; function before_foo() {};");
      fail("RefasterJS templates are not allowed to have the same name.");
    } catch (IllegalStateException expected) {}
  }

  @Test
  public void testInitialize_emptyBeforeTemplates() throws Exception {
    try {
      Compiler compiler = createCompiler();
      compileTestCode(compiler, "", "");
      createScanner(compiler, "function before_foo() {}; function after_foo() {};");
      fail("RefasterJS templates are not allowed to be empty!.");
    } catch (IllegalStateException expected) {}
  }

  @Test
  public void testInitialize_success() throws Exception {
    Compiler compiler = createCompiler();
    compileTestCode(compiler, "", "");
    createScanner(compiler, "function before_foo() {'str';}; function after_foo() {};");
  }

  @Test
  public void test_simple() throws Exception {
    String template = ""
        + "function before_foo() {\n"
        + "  var a = 'str';\n"
        + "};\n"
        + "function after_foo() {\n"
        + "  'bar';\n"
        + "}\n";
    Compiler compiler = createCompiler();
    String testCode = "var loc = 'str';";
    compileTestCode(compiler, testCode, "");
    Node root = getScriptRoot(compiler);
    RefasterJsScanner scanner = createScanner(compiler, template);
    Match match = new Match(root.getFirstChild(), new NodeMetadata(compiler));
    assertTrue(scanner.matches(match.getNode(), match.getMetadata()));

    List<SuggestedFix> fixes = scanner.processMatch(match);
    assertEquals(1, fixes.size());
    Set<CodeReplacement> replacements = fixes.get(0).getReplacements().get("test");
    assertEquals(1, replacements.size());
    assertEquals(
        new CodeReplacement(0, "var loc = 'str';".length(), "'bar';\n"),
        replacements.iterator().next());
  }

  @Test
  public void test_semicolonCorrect() throws Exception {
    String externs = ""
        + "/** @constructor */\n"
        + "function Location() {};\n"
        + "/** @type {string} */\n"
        + "Location.prototype.href;\n"
        + "function foo() {}";
    String template = ""
        + "/** @param {Location} loc */"
        + "function before_foo(loc) {\n"
        + "  loc.href = 'str';\n"
        + "};\n"
        + "function after_foo() {\n"
        + "  foo();\n"
        + "}\n";
    Compiler compiler = createCompiler();
    String preamble = "var loc = new Location();";
    String testCode = "loc.href = 'str';";
    compileTestCode(compiler, preamble + testCode, externs);
    Node root = getScriptRoot(compiler);
    RefasterJsScanner scanner = createScanner(compiler, template);
    Match match = new Match(
        root.getFirstChild().getNext().getFirstChild(), new NodeMetadata(compiler));
    assertTrue(scanner.matches(match.getNode(), match.getMetadata()));

    List<SuggestedFix> fixes = scanner.processMatch(match);
    assertEquals(1, fixes.size());
    Set<CodeReplacement> replacements = fixes.get(0).getReplacements().get("test");
    assertEquals(1, replacements.size());
    assertEquals(
        new CodeReplacement(preamble.length(), testCode.length(), "foo();\n"),
        replacements.iterator().next());
  }

  @Test
  public void test_withTypes() throws Exception {
    String externs = ""
        + "/** @constructor */\n"
        + "function FooType() {}\n"
        + "FooType.prototype.bar = function() {};";
    String template = externs
        + "/**\n"
        + " * @param {FooType} foo\n"
        + " */\n"
        + "function before_foo(foo) {\n"
        + "  foo.bar();\n"
        + "};\n"
        + "/**\n"
        + " * @param {FooType} foo\n"
        + " */\n"
        + "function after_foo(foo) {\n"
        + "  foo.baz();\n"
        + "}\n";
    Compiler compiler = createCompiler();
    String preamble = "var obj = new FooType();\n";
    String testCode = preamble + "obj.bar();";
    compileTestCode(compiler, testCode, externs);
    Node root = getScriptRoot(compiler);
    RefasterJsScanner scanner = createScanner(compiler, template);
    Match match = new Match(root.getLastChild().getFirstChild(), new NodeMetadata(compiler));
    assertTrue(scanner.matches(match.getNode(), match.getMetadata()));

    List<SuggestedFix> fixes = scanner.processMatch(match);
    assertEquals(1, fixes.size());
    Set<CodeReplacement> replacements = fixes.get(0).getReplacements().get("test");
    assertEquals(1, replacements.size());
    assertEquals(
        new CodeReplacement(preamble.length(), "obj.bar();".length(), "obj.baz();\n"),
        replacements.iterator().next());
  }


  @Test
  public void test_multiLines() throws Exception {
    String externs = ""
        + "/** @constructor */\n"
        + "function FooType() {}\n"
        + "FooType.prototype.bar = function() {};"
        + "FooType.prototype.baz = function() {};";
    String template = externs
        + "/**\n"
        + " * @param {FooType} foo\n"
        + " */\n"
        + "function before_foo(foo) {\n"
        + "  foo.bar();\n"
        + "  foo.baz();\n"
        + "};\n"
        + "function after_foo() {\n"
        + "}\n";
    Compiler compiler = createCompiler();
    String preamble = "var obj = new FooType();\n";
    String postamble = "var someOtherCode = 3;\n";
    String testCode = ""
        + preamble
        + "obj.bar();\n"
        + "obj.baz();\n"
        + postamble;
    compileTestCode(compiler, testCode, externs);
    Node root = getScriptRoot(compiler);
    RefasterJsScanner scanner = createScanner(compiler, template);
    Match match = new Match(root.getFirstChild().getNext(), new NodeMetadata(compiler));
    assertTrue(scanner.matches(match.getNode(), match.getMetadata()));

    List<SuggestedFix> fixes = scanner.processMatch(match);
    assertEquals(1, fixes.size());
    Set<CodeReplacement> replacements = fixes.get(0).getReplacements().get("test");
    assertEquals(2, replacements.size());
    Iterator<CodeReplacement> iterator = replacements.iterator();
    assertEquals(
        new CodeReplacement(preamble.length(), "obj.bar();".length(), ""),
        iterator.next());
    assertEquals(
        new CodeReplacement(preamble.length() + "obj.bar();\n".length(), "obj.baz();".length(), ""),
        iterator.next());
  }

  private Compiler createCompiler() {
    return new Compiler();
  }

  private RefasterJsScanner createScanner(Compiler compiler, String template) throws Exception {
    RefasterJsScanner scanner = new RefasterJsScanner();
    scanner.loadRefasterJsTemplateFromCode(template);
    scanner.initialize(compiler);
    return scanner;
  }

  private void compileTestCode(Compiler compiler, String testCode, String externs) {
    CompilerOptions options = RefactoringDriver.getCompilerOptions();
    compiler.compile(
        ImmutableList.of(SourceFile.fromCode("externs", externs)),
        ImmutableList.of(SourceFile.fromCode("test", testCode)),
        options);
  }

  private Node getScriptRoot(Compiler compiler) {
    Node root = compiler.getRoot();
    // The last child of the compiler root is a Block node, and the first child
    // of that is the Script node.
    return root.getLastChild().getFirstChild();
  }
}
TOP

Related Classes of com.google.javascript.refactoring.RefasterJsScannerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.