diff --git a/test/built-ins/String/prototype/normalize/form-is-not-valid-throws.js b/test/built-ins/String/prototype/normalize/form-is-not-valid-throws.js
new file mode 100644
index 0000000000000000000000000000000000000000..df00afc8b252e13c064ec8c0925d6ae7ac82a9e9
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/form-is-not-valid-throws.js
@@ -0,0 +1,25 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Throws a RangeError if ToString(form) value is not a valid form name.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  ...
+  7. If f is not one of "NFC", "NFD", "NFKC", or "NFKD", throw a RangeError
+  exception.
+---*/
+
+assert.throws(RangeError, function() {
+  'foo'.normalize('bar');
+});
+
+assert.throws(RangeError, function() {
+  'foo'.normalize('NFC1');
+});
+
+assert.throws(RangeError, function() {
+  'foo'.normalize(null);
+});
diff --git a/test/built-ins/String/prototype/normalize/length.js b/test/built-ins/String/prototype/normalize/length.js
new file mode 100644
index 0000000000000000000000000000000000000000..4f6cbe696e67a6cf901c4fc4d6f882ccac004751
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/length.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  String.prototype.normalize.length value and descriptor.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  17 ECMAScript Standard Built-in Objects
+
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(
+  String.prototype.normalize.length, 0,
+  'The value of `String.prototype.normalize.length` is `0`'
+);
+
+verifyNotEnumerable(String.prototype.normalize, 'length');
+verifyNotWritable(String.prototype.normalize, 'length');
+verifyConfigurable(String.prototype.normalize, 'length');
diff --git a/test/built-ins/String/prototype/normalize/name.js b/test/built-ins/String/prototype/normalize/name.js
new file mode 100644
index 0000000000000000000000000000000000000000..a596698e61ceffe4b023c28fa1d646b1a6f9096e
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/name.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  String.prototype.normalize.name value and descriptor.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  17 ECMAScript Standard Built-in Objects
+
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(
+  String.prototype.normalize.name, 'normalize',
+  'The value of `String.prototype.normalize.name` is `"normalize"`'
+);
+
+verifyNotEnumerable(String.prototype.normalize, 'name');
+verifyNotWritable(String.prototype.normalize, 'name');
+verifyConfigurable(String.prototype.normalize, 'name');
diff --git a/test/built-ins/String/prototype/normalize/normalize.js b/test/built-ins/String/prototype/normalize/normalize.js
new file mode 100644
index 0000000000000000000000000000000000000000..00cb9f7521476ceb9ec97f1dae2ca0b127237173
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/normalize.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Property type and descriptor.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  17 ECMAScript Standard Built-in Objects
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(
+  typeof String.prototype.normalize,
+  'function',
+  '`typeof String.prototype.normalize` is `function`'
+);
+
+verifyNotEnumerable(String.prototype, 'normalize');
+verifyWritable(String.prototype, 'normalize');
+verifyConfigurable(String.prototype, 'normalize');
diff --git a/test/built-ins/String/prototype/normalize/return-abrupt-from-form-as-symbol.js b/test/built-ins/String/prototype/normalize/return-abrupt-from-form-as-symbol.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c65c1aa15c81fcd53687ff1680d9c7b2fbd8bd1
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-abrupt-from-form-as-symbol.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns abrupt from ToString(form) as a Symbol.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  ...
+  4. If form is not provided or form is undefined, let form be "NFC".
+  5. Let f be ToString(form).
+  6. ReturnIfAbrupt(f).
+features: [Symbol]
+---*/
+
+var s = Symbol('foo');
+
+assert.throws(TypeError, function() {
+  'foo'.normalize(s);
+});
diff --git a/test/built-ins/String/prototype/normalize/return-abrupt-from-form.js b/test/built-ins/String/prototype/normalize/return-abrupt-from-form.js
new file mode 100644
index 0000000000000000000000000000000000000000..ea3d55901b7d4160211285578f3a4c976ee740d0
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-abrupt-from-form.js
@@ -0,0 +1,24 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns abrupt from ToString(form)
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  ...
+  4. If form is not provided or form is undefined, let form be "NFC".
+  5. Let f be ToString(form).
+  6. ReturnIfAbrupt(f).
+---*/
+
+var o = {
+  toString: function() {
+    throw new Test262Error();
+  }
+};
+
+assert.throws(Test262Error, function() {
+  'foo'.normalize(o);
+});
diff --git a/test/built-ins/String/prototype/normalize/return-abrupt-from-this-as-symbol.js b/test/built-ins/String/prototype/normalize/return-abrupt-from-this-as-symbol.js
new file mode 100644
index 0000000000000000000000000000000000000000..e9efe4b607d0244947575a81352c2cbf518395a5
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-abrupt-from-this-as-symbol.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns abrupt from ToString(this) where this is a Symbol
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  1. Let O be RequireObjectCoercible(this value).
+  2. Let S be ToString(O).
+  3. ReturnIfAbrupt(S).
+features: [Symbol]
+---*/
+
+var s = Symbol('foo');
+
+assert.throws(TypeError, function() {
+  String.prototype.normalize.call(s);
+});
diff --git a/test/built-ins/String/prototype/normalize/return-abrupt-from-this.js b/test/built-ins/String/prototype/normalize/return-abrupt-from-this.js
new file mode 100644
index 0000000000000000000000000000000000000000..d965846da16f09d9eef65014a53751b4cbb4d286
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-abrupt-from-this.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns abrupt from ToString(this)
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  1. Let O be RequireObjectCoercible(this value).
+  2. Let S be ToString(O).
+  3. ReturnIfAbrupt(S).
+---*/
+
+var o = {
+  toString: function() {
+    throw new Test262Error();
+  }
+};
+
+assert.throws(Test262Error, function() {
+  String.prototype.normalize.call(o);
+});
diff --git a/test/built-ins/String/prototype/normalize/return-normalized-string-from-coerced-form.js b/test/built-ins/String/prototype/normalize/return-normalized-string-from-coerced-form.js
new file mode 100644
index 0000000000000000000000000000000000000000..e05053586b721b7028ed6c95a039718e9f564792
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-normalized-string-from-coerced-form.js
@@ -0,0 +1,37 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns normalized string from coerced form.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  ...
+  4. If form is not provided or form is undefined, let form be "NFC".
+  5. Let f be ToString(form).
+  6. ReturnIfAbrupt(f).
+  7. If f is not one of "NFC", "NFD", "NFKC", or "NFKD", throw a RangeError
+  exception.
+  8. Let ns be the String value that is the result of normalizing S into the
+  normalization form named by f as specified in
+  http://www.unicode.org/reports/tr15/tr15-29.html.
+  9. Return ns.
+---*/
+
+var s = '\u00C5\u2ADC\u0958\u2126\u0344';
+var nfc = '\xC5\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301';
+var nfd = 'A\u030A\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301';
+var o = {
+  toString: function() { return 'NFC'; }
+};
+
+assert.sameValue(s.normalize(['NFC']), nfc, 'coerced array - NFC');
+assert.sameValue(s.normalize(o), nfc, 'coerced object - NFC');
+
+o = {
+  toString: function() { return 'NFD'; }
+};
+
+assert.sameValue(s.normalize(['NFD']), nfd, 'coerced array - NFD');
+assert.sameValue(s.normalize(o), nfd, 'coerced object - NFD');
diff --git a/test/built-ins/String/prototype/normalize/return-normalized-string-using-default-parameter.js b/test/built-ins/String/prototype/normalize/return-normalized-string-using-default-parameter.js
new file mode 100644
index 0000000000000000000000000000000000000000..539a01255eabe9b48d0aa483cc74741a19aa7497
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-normalized-string-using-default-parameter.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns normalized string.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  ...
+  4. If form is not provided or form is undefined, let form be "NFC".
+  ...
+  8. Let ns be the String value that is the result of normalizing S into the
+  normalization form named by f as specified in
+  http://www.unicode.org/reports/tr15/tr15-29.html.
+  9. Return ns.
+---*/
+
+var s = '\u00C5\u2ADC\u0958\u2126\u0344';
+var nfc = '\xC5\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301';
+
+assert.sameValue(s.normalize(), nfc, 'Use NFC as the default form');
+assert.sameValue(s.normalize(undefined), nfc, 'Use NFC as the default form');
diff --git a/test/built-ins/String/prototype/normalize/return-normalized-string.js b/test/built-ins/String/prototype/normalize/return-normalized-string.js
new file mode 100644
index 0000000000000000000000000000000000000000..05849bbcac03984dad7c1819c2ccc9dcc50d71d4
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/return-normalized-string.js
@@ -0,0 +1,48 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Returns normalized string.
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  ...
+  7. If f is not one of "NFC", "NFD", "NFKC", or "NFKD", throw a RangeError
+  exception.
+  8. Let ns be the String value that is the result of normalizing S into the
+  normalization form named by f as specified in
+  http://www.unicode.org/reports/tr15/tr15-29.html.
+  9. Return ns.
+---*/
+
+var s = '\u1E9B\u0323';
+
+assert.sameValue(s.normalize('NFC'), '\u1E9B\u0323', 'Normalized on NFC');
+assert.sameValue(s.normalize('NFD'), '\u017F\u0323\u0307', 'Normalized on NFD');
+assert.sameValue(s.normalize('NFKC'), '\u1E69', 'Normalized on NFKC');
+assert.sameValue(s.normalize('NFKD'), '\u0073\u0323\u0307', 'Normalized on NFKD');
+
+assert.sameValue(
+  '\u00C5\u2ADC\u0958\u2126\u0344'.normalize('NFC'),
+  '\xC5\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301',
+  'Normalized on NFC'
+);
+
+assert.sameValue(
+  '\u00C5\u2ADC\u0958\u2126\u0344'.normalize('NFD'),
+  'A\u030A\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301',
+  'Normalized on NFD'
+);
+
+assert.sameValue(
+  '\u00C5\u2ADC\u0958\u2126\u0344'.normalize('NFKC'),
+  '\xC5\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301',
+  'Normalized on NFKC'
+);
+
+assert.sameValue(
+  '\u00C5\u2ADC\u0958\u2126\u0344'.normalize('NFKD'),
+  'A\u030A\u2ADD\u0338\u0915\u093C\u03A9\u0308\u0301',
+  'Normalized on NFKD'
+);
diff --git a/test/built-ins/String/prototype/normalize/this-is-null-throws.js b/test/built-ins/String/prototype/normalize/this-is-null-throws.js
new file mode 100644
index 0000000000000000000000000000000000000000..124c1c6f1600954f84e5bdf6db2a01ef40357cc3
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/this-is-null-throws.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Throws TypeError when `this` is null
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  1. Let O be RequireObjectCoercible(this value).
+  2. Let S be ToString(O).
+---*/
+
+assert.throws(TypeError, function() {
+  String.prototype.normalize.call(null);
+});
diff --git a/test/built-ins/String/prototype/normalize/this-is-undefined-throws.js b/test/built-ins/String/prototype/normalize/this-is-undefined-throws.js
new file mode 100644
index 0000000000000000000000000000000000000000..3e6a7e6ea078af959a10757a275e4b931e202b1c
--- /dev/null
+++ b/test/built-ins/String/prototype/normalize/this-is-undefined-throws.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 21.1.3.12
+description: >
+  Throws TypeError when `this` is undefined
+info: >
+  21.1.3.12 String.prototype.normalize ( [ form ] )
+
+  1. Let O be RequireObjectCoercible(this value).
+  2. Let S be ToString(O).
+---*/
+
+assert.throws(TypeError, function() {
+  String.prototype.normalize.call(undefined);
+});