/*
 * Copyright 2015-2016 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.junit.gen5.engine;

import static java.util.function.Predicate.isEqual;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.data.Index.atIndex;
import static org.junit.gen5.commons.util.FunctionUtils.where;
import static org.junit.gen5.engine.ExecutionEvent.*;
import static org.junit.gen5.engine.ExecutionEvent.Type.*;
import static org.junit.gen5.engine.TestExecutionResult.Status.*;
import static org.junit.gen5.engine.TestExecutionResultConditions.*;

import java.util.List;

import org.assertj.core.api.Condition;
import org.junit.gen5.engine.ExecutionEvent.Type;
import org.junit.gen5.engine.TestExecutionResult.Status;

/**
 * Collection of AssertJ conditions for {@link ExecutionEvent}.
 */
public class ExecutionEventConditions {

	@SafeVarargs
	public static void assertRecordedExecutionEventsContainsExactly(List<ExecutionEvent> executionEvents,
			Condition<? super ExecutionEvent>... conditions) {
		assertThat(executionEvents).hasSize(conditions.length);
		for (int i = 0; i < conditions.length; i++) {
			assertThat(executionEvents).has(conditions[i], atIndex(i));
		}
	}

	@SafeVarargs
	public static Condition<ExecutionEvent> event(Condition<? super ExecutionEvent>... conditions) {
		return allOf(conditions);
	}

	public static Condition<ExecutionEvent> engine() {
		return new Condition<>(byTestDescriptor(EngineDescriptor.class::isInstance), "is an engine");
	}

	public static Condition<ExecutionEvent> test(String uniqueIdSubstring) {
		return allOf(test(), uniqueIdSubstring(uniqueIdSubstring));
	}

	public static Condition<ExecutionEvent> test() {
		return new Condition<>(byTestDescriptor(TestDescriptor::isTest), "is a test");
	}

	public static Condition<ExecutionEvent> container(Class<?> clazz) {
		return container(clazz.getName());
	}

	public static Condition<ExecutionEvent> container(String uniqueIdSubstring) {
		return allOf(container(), uniqueIdSubstring(uniqueIdSubstring));
	}

	public static Condition<ExecutionEvent> container() {
		return new Condition<>(byTestDescriptor(TestDescriptor::isContainer), "is a container");
	}

	public static Condition<ExecutionEvent> uniqueIdSubstring(String uniqueIdSubstring) {
		return new Condition<>(
			byTestDescriptor(where(TestDescriptor::getUniqueId, uniqueId -> uniqueId.contains(uniqueIdSubstring))),
			"has descriptor with uniqueId substring '%s'", uniqueIdSubstring);
	}

	public static Condition<ExecutionEvent> skippedWithReason(String expectedReason) {
		return allOf(type(SKIPPED), reason(expectedReason));
	}

	public static Condition<ExecutionEvent> started() {
		return type(STARTED);
	}

	public static Condition<ExecutionEvent> abortedWithReason(Condition<? super Throwable> causeCondition) {
		return finishedWithCause(ABORTED, causeCondition);
	}

	public static Condition<ExecutionEvent> finishedWithFailure(Condition<? super Throwable> causeCondition) {
		return finishedWithCause(FAILED, causeCondition);
	}

	private static Condition<ExecutionEvent> finishedWithCause(Status expectedStatus,
			Condition<? super Throwable> causeCondition) {
		return finished(allOf(status(expectedStatus), cause(causeCondition)));
	}

	public static Condition<ExecutionEvent> finishedWithFailure() {
		return finished(status(FAILED));
	}

	public static Condition<ExecutionEvent> finishedSuccessfully() {
		return finished(status(SUCCESSFUL));
	}

	public static Condition<ExecutionEvent> finished(Condition<TestExecutionResult> resultCondition) {
		return allOf(type(FINISHED), result(resultCondition));
	}

	public static Condition<ExecutionEvent> type(Type expectedType) {
		return new Condition<>(byType(expectedType), "type is %s", expectedType);
	}

	public static Condition<ExecutionEvent> result(Condition<TestExecutionResult> condition) {
		return new Condition<>(byPayload(TestExecutionResult.class, condition::matches), "event with result where %s",
			condition);
	}

	public static Condition<ExecutionEvent> reason(String expectedReason) {
		return new Condition<>(byPayload(String.class, isEqual(expectedReason)), "event with reason '%s'",
			expectedReason);
	}

}

@@ -437,17 +437,21 @@
 ertions.
-*
+allOf
 ;%0Aimport
@@ -870,16 +870,60 @@
 dition;%0A
+import org.assertj.core.api.SoftAssertions;%0A
 import o
@@ -1308,16 +1308,71 @@
 ns) %7B%0A%09%09
+SoftAssertions softly = new SoftAssertions();%0A%09%09softly.
 assertTh
@@ -1470,16 +1470,23 @@
 +) %7B%0A%09%09%09
+softly.
 assertTh
@@ -1541,16 +1541,38 @@
 ));%0A%09%09%7D%0A
+%09%09softly.assertAll();%0A
 %09%7D%0A%0A%09@Sa

Use SoftAssertions to see all failures in one go