OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 'use strict'; | 5 'use strict'; |
6 | 6 |
7 // This file provides |assert_selection(sample, tester, expectedText, options)| | 7 // This file provides |assert_selection(sample, tester, expectedText, options)| |
8 // assertion to W3C test harness to write editing test cases easier. | 8 // assertion to W3C test harness to write editing test cases easier. |
9 // | 9 // |
10 // |sample| is an HTML fragment text which is inserted as |innerHTML|. It should | 10 // |sample| is an HTML fragment text which is inserted as |innerHTML|. It should |
11 // have at least one focus boundary point marker "|" and at most one anchor | 11 // have at least one focus boundary point marker "|" and at most one anchor |
12 // boundary point marker "^". | 12 // boundary point marker "^". |
13 // | 13 // |
14 // |tester| is either name with parameter of execCommand or function taking | 14 // |tester| is either name with parameter of execCommand or function taking |
15 // one parameter |Selection|. | 15 // one parameter |Selection|. |
16 // | 16 // |
17 // |expectedText| is an HTML fragment text containing at most one focus marker | 17 // |expectedText| is an HTML fragment text containing at most one focus marker |
18 // and anchor marker. If resulting selection is none, you don't need to have | 18 // and anchor marker. If resulting selection is none, you don't need to have |
19 // anchor and focus markers. | 19 // anchor and focus markers. |
20 // | 20 // |
21 // |options| is a string as description, undefined, or a dictionary containing: | 21 // |options| is a string as description, undefined, or a dictionary containing: |
22 // description: A description | 22 // description: A description |
23 // dumpAs: 'domtree' or 'flattree'. Default is 'domtree'. | 23 // dumpAs: 'domtree' or 'flattree'. Default is 'domtree'. |
24 // removeSampleIfSucceeded: A boolean. Default is true. | 24 // removeSampleIfSucceeded: A boolean. Default is true. |
25 // dumpFromRoot: A boolean. Default is false. | |
yosin_UTC9
2017/03/17 10:04:11
Could you move "assert_selection.js" change to ano
| |
25 // | 26 // |
26 // Example: | 27 // Example: |
27 // test(() => { | 28 // test(() => { |
28 // assert_selection( | 29 // assert_selection( |
29 // '|foo', | 30 // '|foo', |
30 // (selection) => selection.modify('extent', 'forward, 'character'), | 31 // (selection) => selection.modify('extent', 'forward, 'character'), |
31 // '<a href="http://bar">^f|oo</a>' | 32 // '<a href="http://bar">^f|oo</a>' |
32 // }); | 33 // }); |
33 // | 34 // |
34 // test(() => { | 35 // test(() => { |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 } | 613 } |
613 this.emit(endMarker); | 614 this.emit(endMarker); |
614 this.emit(value.substr(end)); | 615 this.emit(value.substr(end)); |
615 } | 616 } |
616 this.emit('</textarea>'); | 617 this.emit('</textarea>'); |
617 } | 618 } |
618 | 619 |
619 /** | 620 /** |
620 * @public | 621 * @public |
621 * @param {!HTMLDocument} document | 622 * @param {!HTMLDocument} document |
623 * @param {boolean} dumpFromRoot | |
622 */ | 624 */ |
623 serialize(document) { | 625 serialize(document, dumpFromRoot) { |
624 if (document.body) | 626 if (document.body && !dumpFromRoot) |
625 this.serializeChildren(document.body); | 627 this.serializeChildren(document.body); |
626 else | 628 else |
627 this.serializeInternal(document.documentElement); | 629 this.serializeInternal(document.documentElement); |
628 return this.strings_.join(''); | 630 return this.strings_.join(''); |
629 } | 631 } |
630 | 632 |
631 /** | 633 /** |
632 * @private | 634 * @private |
633 * @param {!HTMLElement} element | 635 * @param {!HTMLElement} element |
634 */ | 636 */ |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 } | 783 } |
782 | 784 |
783 /** | 785 /** |
784 * @public | 786 * @public |
785 */ | 787 */ |
786 remove() { this.iframe_.remove(); } | 788 remove() { this.iframe_.remove(); } |
787 | 789 |
788 /** | 790 /** |
789 * @public | 791 * @public |
790 * @param {!Traversal} traversal | 792 * @param {!Traversal} traversal |
793 * @param {boolean} dumpFromRoot | |
791 * @return {string} | 794 * @return {string} |
792 */ | 795 */ |
793 serialize(traversal) { | 796 serialize(traversal, dumpFromRoot) { |
794 /** @type {!SampleSelection} */ | 797 /** @type {!SampleSelection} */ |
795 const selection = traversal.fromDOMSelection(this.selection_); | 798 const selection = traversal.fromDOMSelection(this.selection_); |
796 /** @type {!Serializer} */ | 799 /** @type {!Serializer} */ |
797 const serializer = new Serializer(selection, traversal); | 800 const serializer = new Serializer(selection, traversal); |
798 return serializer.serialize(this.document_); | 801 return serializer.serialize(this.document_, dumpFromRoot); |
799 } | 802 } |
800 } | 803 } |
801 | 804 |
802 function assembleDescription() { | 805 function assembleDescription() { |
803 function getStack() { | 806 function getStack() { |
804 let stack; | 807 let stack; |
805 try { | 808 try { |
806 throw new Error('get line number'); | 809 throw new Error('get line number'); |
807 } catch (error) { | 810 } catch (error) { |
808 stack = error.stack.split('\n').slice(1); | 811 stack = error.stack.split('\n').slice(1); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
866 * @param {function(!Selection)|string} | 869 * @param {function(!Selection)|string} |
867 * @param {string} expectedText | 870 * @param {string} expectedText |
868 * @param {Object=} opt_options | 871 * @param {Object=} opt_options |
869 * @return {!Sample} | 872 * @return {!Sample} |
870 */ | 873 */ |
871 function assertSelection( | 874 function assertSelection( |
872 inputText, tester, expectedText, opt_options = {}) { | 875 inputText, tester, expectedText, opt_options = {}) { |
873 const kDescription = 'description'; | 876 const kDescription = 'description'; |
874 const kDumpAs = 'dumpAs'; | 877 const kDumpAs = 'dumpAs'; |
875 const kRemoveSampleIfSucceeded = 'removeSampleIfSucceeded'; | 878 const kRemoveSampleIfSucceeded = 'removeSampleIfSucceeded'; |
879 const kDumpFromRoot = 'dumpFromRoot'; | |
876 /** @type {!Object} */ | 880 /** @type {!Object} */ |
877 const options = typeof(opt_options) === 'string' | 881 const options = typeof(opt_options) === 'string' |
878 ? {description: opt_options} : opt_options; | 882 ? {description: opt_options} : opt_options; |
879 /** @type {string} */ | 883 /** @type {string} */ |
880 const description = kDescription in options | 884 const description = kDescription in options |
881 ? options[kDescription] : assembleDescription(); | 885 ? options[kDescription] : assembleDescription(); |
882 /** @type {boolean} */ | 886 /** @type {boolean} */ |
883 const removeSampleIfSucceeded = kRemoveSampleIfSucceeded in options | 887 const removeSampleIfSucceeded = kRemoveSampleIfSucceeded in options |
884 ? !!options[kRemoveSampleIfSucceeded] : true; | 888 ? !!options[kRemoveSampleIfSucceeded] : true; |
885 /** @type {DumpAs} */ | 889 /** @type {DumpAs} */ |
886 const dumpAs = options[kDumpAs] || DumpAs.DOM_TREE; | 890 const dumpAs = options[kDumpAs] || DumpAs.DOM_TREE; |
891 /** @type {boolean} */ | |
892 const dumpFromRoot = options[kDumpFromRoot] || false; | |
887 | 893 |
888 checkExpectedText(expectedText); | 894 checkExpectedText(expectedText); |
889 const sample = new Sample(inputText); | 895 const sample = new Sample(inputText); |
890 if (typeof(tester) === 'function') { | 896 if (typeof(tester) === 'function') { |
891 tester.call(window, sample.selection); | 897 tester.call(window, sample.selection); |
892 } else if (typeof(tester) === 'string') { | 898 } else if (typeof(tester) === 'string') { |
893 const strings = tester.split(/ (.+)/); | 899 const strings = tester.split(/ (.+)/); |
894 sample.document.execCommand(strings[0], false, strings[1]); | 900 sample.document.execCommand(strings[0], false, strings[1]); |
895 } else { | 901 } else { |
896 throw new Error(`Invalid tester: ${tester}`); | 902 throw new Error(`Invalid tester: ${tester}`); |
897 } | 903 } |
898 | 904 |
899 /** @type {!Traversal} */ | 905 /** @type {!Traversal} */ |
900 const traversal = (() => { | 906 const traversal = (() => { |
901 switch (dumpAs) { | 907 switch (dumpAs) { |
902 case DumpAs.DOM_TREE: | 908 case DumpAs.DOM_TREE: |
903 return new DOMTreeTraversal(); | 909 return new DOMTreeTraversal(); |
904 case DumpAs.FLAT_TREE: | 910 case DumpAs.FLAT_TREE: |
905 if (!window.internals) | 911 if (!window.internals) |
906 throw new Error('This test requires window.internals.'); | 912 throw new Error('This test requires window.internals.'); |
907 return new FlatTreeTraversal(); | 913 return new FlatTreeTraversal(); |
908 default: | 914 default: |
909 throw `${kDumpAs} must be one of ` + | 915 throw `${kDumpAs} must be one of ` + |
910 `{${Object.values(DumpAs).join(', ')}}` + | 916 `{${Object.values(DumpAs).join(', ')}}` + |
911 ` instead of '${dumpAs}'`; | 917 ` instead of '${dumpAs}'`; |
912 } | 918 } |
913 })(); | 919 })(); |
914 | 920 |
915 /** @type {string} */ | 921 /** @type {string} */ |
916 const actualText = sample.serialize(traversal); | 922 const actualText = sample.serialize(traversal, dumpFromRoot); |
917 // We keep sample HTML when assertion is false for ease of debugging test | 923 // We keep sample HTML when assertion is false for ease of debugging test |
918 // case. | 924 // case. |
919 if (actualText === expectedText) { | 925 if (actualText === expectedText) { |
920 if (removeSampleIfSucceeded) | 926 if (removeSampleIfSucceeded) |
921 sample.remove(); | 927 sample.remove(); |
922 return sample; | 928 return sample; |
923 } | 929 } |
924 throw new Error(`${description}\n` + | 930 throw new Error(`${description}\n` + |
925 `\t expected ${expectedText},\n` + | 931 `\t expected ${expectedText},\n` + |
926 `\t but got ${actualText},\n` + | 932 `\t but got ${actualText},\n` + |
927 `\t sameupto ${commonPrefixOf(expectedText, actualText)}`); | 933 `\t sameupto ${commonPrefixOf(expectedText, actualText)}`); |
928 } | 934 } |
929 | 935 |
930 // Export symbols | 936 // Export symbols |
931 window.Sample = Sample; | 937 window.Sample = Sample; |
932 window.assert_selection = assertSelection; | 938 window.assert_selection = assertSelection; |
933 })(); | 939 })(); |
OLD | NEW |