diff --git a/test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js b/test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js
new file mode 100644
index 0000000000000000000000000000000000000000..00d6aeff0442eb98ef5fa4f6dca043ca7344d1d3
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next-abrupt.js
@@ -0,0 +1,44 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Abrupt completions should not preclude additional jobs
+es6id: 25.4.2.1
+info: >
+    [...]
+    7. If handlerResult is an abrupt completion, then
+       a. Let status be Call(promiseCapability.[[Reject]], undefined,
+          «handlerResult.[[value]]»).
+       b. NextJob Completion(status).
+    8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+       «handlerResult.[[value]]»).
+    9. NextJob Completion(status).
+---*/
+
+var promise = new Promise(function(resolve) {
+  resolve();
+});
+var fulfilledCallCount = 0;
+var rejectedCallCount = 0;
+
+promise.then(function() {
+    fulfilledCallCount += 1;
+    throw new Error();
+  }, function() {
+    rejectedCallCount += 1;
+  });
+
+promise.then(function() {
+    if (fulfilledCallCount !== 1) {
+      $DONE('Expected "onFulfilled" handler to be invoked exactly once.');
+      return;
+    }
+
+    if (rejectedCallCount !== 0) {
+      $DONE('Expected "onRejected" handler to not be invoked.');
+      return;
+    }
+
+    $DONE();
+  }, function() {
+    $DONE('This promise should not be rejected.');
+  });
diff --git a/test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js b/test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js
new file mode 100644
index 0000000000000000000000000000000000000000..1443459a1643d10e7ce7c1aae58f1c55af77ae52
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/rxn-handler-fulfilled-next.js
@@ -0,0 +1,52 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: All queued jobs should be executed in series
+es6id: 25.4.2.1
+info: >
+    [...]
+    7. If handlerResult is an abrupt completion, then
+       a. Let status be Call(promiseCapability.[[Reject]], undefined,
+          «handlerResult.[[value]]»).
+       b. NextJob Completion(status).
+    8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+       «handlerResult.[[value]]»).
+    9. NextJob Completion(status).
+---*/
+
+var promise = new Promise(function(resolve) {
+  resolve();
+});
+var log = '';
+
+promise.then(function() {
+    log += 'a';
+  }, function() {
+    log += 'A';
+  });
+
+promise.then(function() {
+    log += 'b';
+  }, function() {
+    log += 'B';
+  });
+
+promise.then(function() {
+    log += 'c';
+  }, function() {
+    log += 'C';
+  });
+
+promise.then(function() {
+    if (log !== 'abc') {
+      $DONE(
+        'Expected each "onFulfilled" handler to be invoked exactly once in series. ' +
+        'Expected: abc. Actual: ' + log
+      );
+      return;
+    }
+
+    $DONE();
+  }, function() {
+    $DONE('This promise should not be rejected.');
+  });
diff --git a/test/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js b/test/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c3d18b40d9795583debf3ed8b4b7822e3324620
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/rxn-handler-rejected-next-abrupt.js
@@ -0,0 +1,44 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: Abrupt completions should not preclude additional jobs
+es6id: 25.4.2.1
+info: >
+    [...]
+    7. If handlerResult is an abrupt completion, then
+       a. Let status be Call(promiseCapability.[[Reject]], undefined,
+          «handlerResult.[[value]]»).
+       b. NextJob Completion(status).
+    8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+       «handlerResult.[[value]]»).
+    9. NextJob Completion(status).
+---*/
+
+var promise = new Promise(function(_, reject) {
+  reject();
+});
+var fulfilledCallCount = 0;
+var rejectedCallCount = 0;
+
+promise.then(function() {
+    fulfilledCallCount += 1;
+  }, function() {
+    rejectedCallCount += 1;
+    throw new Error();
+  });
+
+promise.then(function() {
+    $DONE('This promise should not be fulfilled.');
+  }, function() {
+    if (fulfilledCallCount !== 0) {
+      $DONE('Expected "onFulfilled" handler to not be invoked.');
+      return;
+    }
+
+    if (rejectedCallCount !== 1) {
+      $DONE('Expected "onRejected" handler to be invoked exactly once.');
+      return;
+    }
+
+    $DONE();
+  });
diff --git a/test/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js b/test/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js
new file mode 100644
index 0000000000000000000000000000000000000000..59a3916b3a9319606927f322ce3a952b33605458
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/rxn-handler-rejected-next.js
@@ -0,0 +1,52 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: All queued jobs should be executed in series
+es6id: 25.4.2.1
+info: >
+    [...]
+    7. If handlerResult is an abrupt completion, then
+       a. Let status be Call(promiseCapability.[[Reject]], undefined,
+          «handlerResult.[[value]]»).
+       b. NextJob Completion(status).
+    8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+       «handlerResult.[[value]]»).
+    9. NextJob Completion(status).
+---*/
+
+var promise = new Promise(function(_, reject) {
+  reject();
+});
+var log = '';
+
+promise.then(function() {
+    log += 'A';
+  }, function() {
+    log += 'a';
+  });
+
+promise.then(function() {
+    log += 'B';
+  }, function() {
+    log += 'b';
+  });
+
+promise.then(function() {
+    log += 'C';
+  }, function() {
+    log += 'c';
+  });
+
+promise.then(function() {
+    $DONE('This promise should not be fulfilled.');
+  }, function() {
+    if (log !== 'abc') {
+      $DONE(
+        'Expected each "onFulfilled" handler to be invoked exactly once in series. ' +
+        'Expected: abc. Actual: ' + log
+      );
+      return;
+    }
+
+    $DONE();
+  });
diff --git a/test/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js b/test/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js
new file mode 100644
index 0000000000000000000000000000000000000000..1277801c501276724928cd9372cb8cd09dde817b
--- /dev/null
+++ b/test/built-ins/Promise/prototype/then/rxn-handler-rejected-return-normal.js
@@ -0,0 +1,49 @@
+// Copyright (C) 2016 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+description: A normal completion should trigger promise fulfillment
+es6id: 25.4.5.3
+info: >
+    [...]
+    7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
+       resultCapability).
+
+    25.4.5.3.1 PerformPromiseThen
+    [...]
+    9. Else if the value of promise's [[PromiseState]] internal slot is
+       "rejected",
+       a. Let reason be the value of promise's [[PromiseResult]] internal slot.
+       b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
+          «rejectReaction, reason»).
+
+    25.4.2.1 PromiseReactionJob
+    [...]
+    7. If handlerResult is an abrupt completion, then
+       a. Let status be Call(promiseCapability.[[Reject]], undefined,
+          «handlerResult.[[value]]»).
+       b. NextJob Completion(status).
+    8. Let status be Call(promiseCapability.[[Resolve]], undefined,
+       «handlerResult.[[value]]»).
+    9. NextJob Completion(status).
+---*/
+
+var value = {};
+var p1 = new Promise(function(_, reject) {
+  reject();
+});
+var p2;
+
+p2 = p1.then(function() {}, function() {
+    return value;
+  });
+
+p2.then(function(x) {
+    if (x !== value) {
+      $DONE('The `onFulfilled` handler should be invoked with the promise result.');
+      return;
+    }
+
+    $DONE();
+  }, function() {
+    $DONE('The `onRejected` handler should not be invoked.');
+  });