/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2010 Oracle and/or its affiliates. All rights reserved.
*
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*
* Contributor(s):
*
* Portions Copyrighted 2009 Sun Microsystems, Inc.
*/
package org.netbeans.modules.ruby.qaf;
import java.awt.Component;
import java.io.File;
import java.io.IOException;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JLabel;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.jellytools.Bundle;
import org.netbeans.jellytools.JellyTestCase;
import org.netbeans.jellytools.NbDialogOperator;
import org.netbeans.jellytools.NewFileWizardOperator;
import org.netbeans.jellytools.NewProjectWizardOperator;
import org.netbeans.jellytools.NewRubyProjectNameLocationStepOperator;
import org.netbeans.jellytools.OutputOperator;
import org.netbeans.jellytools.ProjectsTabOperator;
import org.netbeans.jellytools.actions.BuildGemAction;
import org.netbeans.jellytools.nodes.Node;
import org.netbeans.jemmy.ComponentChooser;
import org.netbeans.jemmy.EventTool;
import org.netbeans.jemmy.JemmyProperties;
import org.netbeans.jemmy.TimeoutExpiredException;
import org.netbeans.jemmy.operators.Operator;
import org.netbeans.modules.project.ui.test.ProjectSupport;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
/**
*
* @author lukas
*/
public abstract class RubyTestCase extends JellyTestCase {
private static final Logger LOGGER = Logger.getLogger(RubyTestCase.class.getName());
private Project project;
private String projectName;
private ProjectType projectType;
/**
* Enum type to hold project specific settings (like ie. project category
* label, project template name, etc.)
*/
protected enum ProjectType {
RUBY,
RAILS,
RR_SAMPLE;
/**
* Get project template category name
*
* @return category name
*/
public String getCategory() {
switch (this) {
case RUBY:
case RAILS:
//Ruby
return Bundle.getStringTrimmed("org.netbeans.modules.ruby.rubyproject.ui.wizards.Bundle", "Templates/Project/Ruby");
case RR_SAMPLE:
//Samples
return Bundle.getStringTrimmed("org.netbeans.modules.project.ui.Bundle", "Templates/Project/Samples");
}
throw new AssertionError("Unknown type: " + this); //NOI18N
}
/**
* Get project template project type name
*
* @return project type name
*/
public String getProjectTypeName() {
switch (this) {
case RUBY:
//Ruby Application
return Bundle.getStringTrimmed("org.netbeans.modules.ruby.rubyproject.ui.wizards.Bundle", "Templates/Project/Ruby/emptyRuby.xml");
case RAILS:
//Ruby on Rails Application
return Bundle.getStringTrimmed("org.netbeans.modules.ruby.railsprojects.ui.wizards.Bundle", "Templates/Project/Ruby/railsApp.xml");
}
throw new AssertionError("Unknown type: " + this); //NOI18N
}
}
public RubyTestCase(String name) {
super(name);
setProjectName(getProjectName());
setProjectType(getProjectType());
}
/**
* Method responsible for checking and setting up environment for particular
* test case, mainly for setting up project to be used by test case.<br/>
*
* Following logic is used for setting up a project (Note that
* <code>getProjectName()</code> method is used for getting correct project
* name):<br/>
* <ol>
* <li>look for a project in <i>projects</i> directory in data directory
* and if project is found there then open it in the IDE
* </li>
* <li>look for a project in <code>getWorkDir().getParentFile().getParentFile()</code>
* or in <code>System.getProperty("java.io.tmpdir")</code> directory
* (if some parent file does not exist), if project is found then open it
* in the IDE</li>
* <li>if project is not found then it will be created from scratch</li>
* </ol>
*
* @throws java.lang.Exception
*/
@Override
public void setUp() throws Exception {
super.setUp();
if (!ProjectType.RR_SAMPLE.equals(getProjectType())) {
System.out.println("######## TestCase: " + getName() + " #######"); //NOI18N
File projectRoot = new File(getDataDir(), "projects/" + getProjectName()); //NOI18N
if (projectRoot.exists()) {
project = (Project) ProjectSupport.openProject(new File(getDataDir(), "projects/" + getProjectName()));
} else {
projectRoot = new File(getProjectsRootDir(), projectName);
LOGGER.info("Using project in: " + projectRoot.getAbsolutePath()); //NOI18N
if (!projectRoot.exists()) {
project = createProject(projectName);
org.netbeans.junit.ide.ProjectSupport.waitScanFinished();
} else {
ProjectSupport.openProject(projectRoot);
FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(projectRoot));
assertNotNull("FO cannot be null", fo); //NOI18N
project = ProjectManager.getDefault().findProject(fo);
}
}
assertNotNull("Project cannot be null!", project); //NOI18N
}
}
@Override
public void tearDown() throws Exception {
super.tearDown();
project = null;
projectName = null;
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
//ignore
}
}
/**
* Get the name of the project to be used by test case
*
* @return name of the project
*/
protected abstract String getProjectName();
/**
* Get a Project instance used by test case
*
* @return a Project instance
*/
protected Project getProject() {
return project;
}
/**
* Get <code>Node</code> for the project used by test case
*
* @return an instance of <code>ProjectRootNode</code>
*/
protected Node getProjectRootNode() {
return new Node(ProjectsTabOperator.invoke().tree(), getProjectName());
}
/**
* Project type set for test case, ProjectType.RUBY is used by default
* Override this method to use different ProjectType
*
* @return ProjectType set for test case
*/
protected ProjectType getProjectType() {
return ProjectType.RUBY;
}
/**
* Get the name of the sample project's category (ie. Ruby)
*
* @return name of the project
*/
protected String getSamplesCategoryName() {
return ""; //NOI18N
}
/**
* Helper method to be used by subclasses to create new project according
* to given parameters. Default server registered in the IDE will be used.
*
* @param name project or sample name
* @param type project type
* @param javaeeVersion server type, can be null
* @return created project
* @throws java.io.IOException
*/
protected Project createProject(String name) throws IOException {
// project category & type selection step
NewProjectWizardOperator npwo = NewProjectWizardOperator.invoke();
npwo.treeCategories().setComparator(new Operator.DefaultStringComparator(true, true));
npwo.lstProjects().setComparator(new Operator.DefaultStringComparator(true, true));
if (ProjectType.RR_SAMPLE.equals(getProjectType())) {
npwo.selectCategory(getProjectType().getCategory() + "|" + getSamplesCategoryName()); //NOI18N
npwo.selectProject(name);
name = getProjectName();
} else {
npwo.selectCategory(getProjectType().getCategory());
npwo.selectProject(getProjectType().getProjectTypeName());
}
npwo.next();
// project name & location selection step
NewRubyProjectNameLocationStepOperator op = new NewRubyProjectNameLocationStepOperator();
op.txtProjectName().setText(name);
if (ProjectType.RR_SAMPLE.equals(getProjectType())) {
op.txtProjectLocation().setText(getWorkDirPath());
} else {
File projectLocation = null;
projectLocation = getProjectsRootDir();
op.txtProjectLocation().setText(projectLocation.getAbsolutePath());
}
LOGGER.info("Creating project in: " + op.txtProjectLocation().getText()); //NOI18N
op.finish();
// Opening Projects
String openingProjectsTitle = Bundle.getStringTrimmed("org.netbeans.modules.project.ui.Bundle", "LBL_Opening_Projects_Progress");
waitDialogClosed(openingProjectsTitle);
// wait project appear in projects view
Node prjNode = new Node(ProjectsTabOperator.invoke().tree(), name);
// wait classpath scanning finished
// org.netbeans.junit.ide.ProjectSupport.waitScanFinished();
// get a project instance to return
Project p = ((org.openide.nodes.Node) prjNode.getOpenideNode()).getLookup().lookup(Project.class);
assertNotNull("Project instance has not been found", p); //NOI18N
return p;
}
/**
* Helper method to be used by subclasses to create new file of given
* <code>fileType</code> from <i>Ruby</i> category
*
* @param p project where to create new file
* @param fileType file type name from ruby category
*/
protected void createNewRubyFile(Project p, String fileType) {
// Ruby
String rubyLabel = Bundle.getStringTrimmed("org.netbeans.modules.ruby.rubyproject.ui.wizards.Bundle", "Templates/Project/Ruby");
createNewFile(p, rubyLabel, fileType);
}
/**
* Helper method to be used by subclasses to create new file of given
* <code>fileType</code> from <code>fileCategory</code> category
*
* @param p project where to create new file
* @param fileType file type name from ruby category
*/
protected void createNewFile(Project p, String fileCategory, String fileType) {
// file category & filetype selection step
NewFileWizardOperator nfwo = NewFileWizardOperator.invoke();
new EventTool().waitNoEvent(500);
nfwo.treeCategories().setComparator(new Operator.DefaultStringComparator(true, true));
nfwo.lstFileTypes().setComparator(new Operator.DefaultStringComparator(true, true));
nfwo.cboProject().selectItem(p.toString());
nfwo.selectCategory(fileCategory);
nfwo.selectFileType(fileType);
nfwo.next();
}
/**
* Wait until dialog with title <code>dialogTitle</code> is closed
*
* @param dialogTitle title of the dialog to be closed
*/
protected void waitDialogClosed(String dialogTitle) {
try {
// wait at most 60 second until progress dialog dismiss
JemmyProperties.setCurrentTimeout("ComponentOperator.WaitStateTimeout", 60000); //NOI18N
new NbDialogOperator(dialogTitle).waitClosed();
} catch (TimeoutExpiredException e) {
// ignore when progress dialog was closed before we started to wait for it
}
}
protected File getProjectsRootDir() throws IOException {
File f = getWorkDir();
LOGGER.fine("Working directory is set to: " + f.getAbsolutePath()); //NOI18N
if (f != null) {
f = f.getParentFile();
if (f != null) {
f = f.getParentFile();
} else {
return new File(System.getProperty("java.io.tmpdir")); //NOI18N
}
} else {
return new File(System.getProperty("java.io.tmpdir")); //NOI18N
}
return f;
}
protected void buildProject() {
OutputOperator oo = OutputOperator.invoke();
new BuildGemAction().performPopup(getProjectRootNode());
oo.getOutputTab(getProjectName()).waitText("BUILD SUCCESSFUL"); //NOI18N
}
private void setProjectName(String projectName) {
this.projectName = projectName;
}
private void setProjectType(ProjectType projectType) {
this.projectType = projectType;
}
static class ModuleTFFinder extends JComponentByLabelFinder {
public ModuleTFFinder() {
// In Module:
super(Bundle.getStringTrimmed("org.netbeans.modules.ruby.rubyproject.templates.Bundle", "LBL_RubyTargetChooserPanelGUI_InModuleName_Label"));
}
}
static class TestedClassTFFinder extends JComponentByLabelFinder {
public TestedClassTFFinder() {
// Tested Class:
super(Bundle.getStringTrimmed("org.netbeans.modules.ruby.rubyproject.templates.Bundle", "LBL_RubyTargetChooserPanelGUI_Spec_Class"));
}
}
static class LocationCBFinder extends JComponentByLabelFinder {
public LocationCBFinder() {
// Location:
super(Bundle.getStringTrimmed("org.netbeans.modules.ruby.rubyproject.templates.Bundle", "LBL_RubyTargetChooserPanelGUI_jLabel1"));
}
}
static class JComponentByLabelFinder implements ComponentChooser {
private String label;
public JComponentByLabelFinder(String label) {
if (label == null || "".equals(label.trim())) {
throw new IllegalArgumentException(label + " is not valid label"); //NOI18N
}
this.label = label.trim();
}
public boolean checkComponent(Component c) {
if (c instanceof JComponent) {
JComponent jc = (JComponent) c;
Object o = jc.getClientProperty("labeledBy"); //NOI18N
if (o != null && o instanceof JLabel) {
JLabel lbl = (JLabel) o;
return label.equalsIgnoreCase(lbl.getText().trim());
}
}
return false;
}
public String getDescription() {
return "Find JComponent labeled by given label"; //NOI18N
}
}
}