/* * Copyright 2009 Google Inc. * * 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.eclipse.javascript.jstestdriver.ui.view; import java.io.IOException; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleManager; import org.eclipse.ui.console.MessageConsole; import org.eclipse.ui.console.MessageConsoleStream; import com.google.common.collect.Lists; import com.google.eclipse.javascript.jstestdriver.core.ProjectHelper; import com.google.eclipse.javascript.jstestdriver.core.ServiceLocator; import com.google.eclipse.javascript.jstestdriver.core.model.EclipseJstdTestResult; import com.google.eclipse.javascript.jstestdriver.core.model.EclipseJstdTestRunResult; import com.google.eclipse.javascript.jstestdriver.core.model.LaunchConfigurationConstants; import com.google.eclipse.javascript.jstestdriver.core.model.LoadedSourceFileLibrary; import com.google.eclipse.javascript.jstestdriver.core.model.ResultModel; import com.google.jstestdriver.TestResult; /** * Show the test results. * * @author shyamseshadri@gmail.com (Shyam Seshadri) */ public class TestResultsPanel extends Composite { private static final Logger logger = Logger.getLogger(TestResultsPanel.class.getName()); private final EclipseJstdTestRunResult testRunResult; private final TreeViewer testResultsTree; private final TestResultProgressBar testProgressIndicator; private final Label failuresLabel; private final Label errorsLabel; private final Label totalRunLabel; private final Text testDetailsText; private final MessageConsoleStream messageConsoleStream; private final TestCaseOpener testCaseOpener; private int totalNumTests; private ILaunchConfiguration lastLaunchConfiguration; private Object currentSelection; public TestResultsPanel(final IWorkbenchPage workbenchPage, Composite parent, int style) { super(parent, style); testCaseOpener = new TestCaseOpener(ServiceLocator.getService(LoadedSourceFileLibrary.class)); IConsoleManager consoleManager = ConsolePlugin.getDefault().getConsoleManager(); MessageConsole messageConsole = new MessageConsole("JSTestDriver", null); messageConsole.activate(); messageConsoleStream = new MessageConsoleStream(messageConsole); consoleManager.addConsoles(new IConsole[] {messageConsole}); setLayout(new GridLayout(3, true)); GridData layoutData = new GridData(); layoutData.grabExcessHorizontalSpace = true; layoutData.grabExcessVerticalSpace = true; layoutData.verticalAlignment = SWT.FILL; layoutData.horizontalAlignment = SWT.FILL; setLayoutData(layoutData); testRunResult = new EclipseJstdTestRunResult(); GridData totalRunLabelData = new GridData(); totalRunLabelData.grabExcessHorizontalSpace = true; totalRunLabelData.horizontalAlignment = SWT.FILL; totalRunLabel = new Label(this, SWT.CENTER); totalRunLabel.setText("Run : 0 / 0"); totalRunLabel.setLayoutData(totalRunLabelData); GridData otherLabelData = new GridData(); otherLabelData.horizontalAlignment = SWT.FILL; errorsLabel = new Label(this, SWT.CENTER); errorsLabel.setText("Errors : 0"); errorsLabel.setLayoutData(otherLabelData); failuresLabel = new Label(this, SWT.CENTER); failuresLabel.setText("Failed : 0"); failuresLabel.setLayoutData(otherLabelData); GridData progressIndicatorData = new GridData(); progressIndicatorData.horizontalSpan = 4; progressIndicatorData.horizontalAlignment = SWT.FILL; progressIndicatorData.verticalAlignment = SWT.FILL; progressIndicatorData.heightHint = 20; progressIndicatorData.minimumWidth = 180; testProgressIndicator = new TestResultProgressBar(this, SWT.NONE); testProgressIndicator.setLayoutData(progressIndicatorData); SashForm resultsSashForm = new SashForm(this, SWT.VERTICAL); GridData sashFormData = new GridData(); sashFormData.horizontalSpan = 3; sashFormData.horizontalAlignment = SWT.FILL; sashFormData.grabExcessHorizontalSpace = true; sashFormData.grabExcessVerticalSpace = true; sashFormData.heightHint = 340; sashFormData.verticalAlignment = SWT.FILL; resultsSashForm.setLayoutData(sashFormData); testResultsTree = new TreeViewer(resultsSashForm, SWT.NONE); testResultsTree.getTree().setLayoutData(sashFormData); testResultsTree.setLabelProvider(new TestResultsTreeLabelProvider()); testResultsTree.setContentProvider(new TestResultsTreeContentProvider()); testResultsTree.setInput(testRunResult); testResultsTree.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { testDetailsText.setText(""); TreeSelection selection = (TreeSelection) event.getSelection(); currentSelection = selection.getFirstElement(); if (currentSelection instanceof EclipseJstdTestResult) { EclipseJstdTestResult result = (EclipseJstdTestResult) currentSelection; StringBuilder details = new StringBuilder(); result.writeDetails(details); testDetailsText.setText(details.toString()); } } }); testResultsTree.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { if (currentSelection instanceof EclipseJstdTestResult) { EclipseJstdTestResult selected = (EclipseJstdTestResult) currentSelection; IProject project = null; try { String projectName = lastLaunchConfiguration.getAttribute(LaunchConfigurationConstants.PROJECT_NAME, ""); project = new ProjectHelper().getProject(projectName); } catch (CoreException e) { logger.log(Level.WARNING, "Could not read project name from launch configuration.", e); } testCaseOpener.openTestSource(project, selected.getResult(), workbenchPage); return; } } }); GridData testDetailsData = new GridData(); testDetailsData.horizontalSpan = 3; testDetailsData.grabExcessHorizontalSpace = true; testDetailsData.heightHint = 100; testDetailsData.verticalAlignment = SWT.FILL; testDetailsData.horizontalAlignment = SWT.FILL; testDetailsText = new Text(resultsSashForm, SWT.MULTI | SWT.WRAP); testDetailsText.setLayoutData(testDetailsData); } /** * Gets the last launched configuration, for easy rerunning of tests. * * @return the last launch config, {@code null} if none were launched. */ public ILaunchConfiguration getLastLaunchConfiguration() { return lastLaunchConfiguration; } /** * Sets up the panel for the next test run, clearing all the fields, resetting * the progress bar and saving the launch config for rerunning. * * @param launchConfiguration the launch config used to launch the tests */ public void setupForNextTestRun(ILaunchConfiguration launchConfiguration) { synchronized (this) { totalNumTests = 0; totalRunLabel.setText("Run : 0 / 0"); errorsLabel.setText("Errors : 0"); failuresLabel.setText("Failed : 0"); try { //Save the copy of the original launch configuration. Therefore, //the changes on the original configuration will not influence //stored values. // //Rerun feature will be safe no matter what happens outside. Similarly, //outside word will be safe from changes done on the copy. lastLaunchConfiguration = launchConfiguration.copy("Safe Save Copy"); } catch (CoreException e) { //This really should not happen, highly unlikely. logger.log(Level.SEVERE, "Could not create copy the launch configuration", e); } testRunResult.clear(); testResultsTree.refresh(); testProgressIndicator.reset(); update(); } } /** * Increases the total number of expected tests by numTests. * * @param numTests The number of tests to increment by. */ public void addNumberOfTests(int numTests) { synchronized (this) { totalNumTests += numTests; testProgressIndicator.setMax(totalNumTests); totalRunLabel.setText("Run : " + testRunResult.getNumberOfTests() + " / " + totalNumTests); } } /** * Registers the test results and increments the progress bar and adds them to * the test results tree. * * @param testResults the test results from JS Test Driver. */ public void addTestResults(Collection<TestResult> testResults) { synchronized (this) { Collection<ResultModel> failedTests = Lists.newArrayList(); for (TestResult result : testResults) { ResultModel addedResult = testRunResult.addTestResult(result); messageConsoleStream.println(result.getLog()); if (!addedResult.passed()) { failedTests.add(addedResult); } } try { messageConsoleStream.flush(); } catch (IOException e) { } testProgressIndicator.step(testResults.size(), failedTests.size() == 0); testResultsTree.refresh(); boolean first = true; for (ResultModel resultModel : failedTests) { if (first) { first = false; testResultsTree.setSelection(new StructuredSelection(resultModel)); } testResultsTree.expandToLevel(resultModel, TreeViewer.ALL_LEVELS); } errorsLabel.setText("Errors : " + testRunResult.getNumberOfErrors()); failuresLabel.setText("Failed : " + testRunResult.getNumberOfFailures()); totalRunLabel.setText("Run : " + testRunResult.getNumberOfTests() + " / " + totalNumTests); } } /** * Sets the filter for the test results tree * * @param filter the filter */ public void setTreeFilter(ViewerFilter filter) { testResultsTree.setFilters(new ViewerFilter[] {filter}); } /** * Clears all filters on the test results tree. */ public void clearTreeFilter() { testResultsTree.setFilters(new ViewerFilter[0]); } }