browser_formdata_face.js (4873B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 /** 7 * This test ensures that collecting form data for form-associated custom 8 * elements works as expected. 9 */ 10 add_task(async function test_face_restore() { 11 const URL = `data:text/html;charset=utf-8,<!DOCTYPE html> 12 <h1>mozilla</h1> 13 <script> 14 restoredStates = {}; 15 customElements.define("c-e", class extends HTMLElement { 16 static formAssociated = true; 17 constructor() { 18 super(); 19 this.internals = this.attachInternals(); 20 } 21 formStateRestoreCallback(state, reason) { 22 if (reason == "restore") { 23 restoredStates[this.id] = state; 24 } 25 } 26 }); 27 </script> 28 <form> 29 <c-e id="test1"></c-e> 30 <c-e id="test2"></c-e> 31 <c-e id="test3"></c-e> 32 <c-e id="test4"></c-e> 33 <c-e id="test5"></c-e> 34 <c-e id="test6"></c-e> 35 </form>`; 36 37 // Load a tab with a FACE. 38 let tab = (gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, URL)); 39 let browser = tab.linkedBrowser; 40 await promiseBrowserLoaded(browser); 41 42 // Set the FACE state and value. 43 await SpecialPowers.spawn(browser, ["c-e"], selector => { 44 function formDataWith(...entries) { 45 const formData = new content.FormData(); 46 for (let [key, value] of entries) { 47 formData.append(key, value); 48 } 49 return formData; 50 } 51 const states = [ 52 "test state", 53 new content.File(["state"], "state.txt"), 54 formDataWith(["1", "state"], ["2", new content.Blob(["state_blob"])]), 55 null, 56 undefined, 57 null, 58 ]; 59 const values = [ 60 "test value", 61 new content.File(["value"], "value.txt"), 62 formDataWith(["1", "value"], ["2", new content.Blob(["value_blob"])]), 63 "null state", 64 "both value and state", 65 null, 66 ]; 67 68 [...content.document.querySelectorAll(selector)].forEach((node, i) => { 69 node.internals.setFormValue(values[i], states[i]); 70 }); 71 }); 72 73 // Close and restore the tab. 74 await promiseRemoveTabAndSessionState(tab); 75 76 { 77 let [ 78 { 79 state: { formdata }, 80 }, 81 ] = ss.getClosedTabDataForWindow(window); 82 83 is(formdata.id.test1.value, "test value", "String value should be stored"); 84 is(formdata.id.test1.state, "test state", "String state should be stored"); 85 86 let storedFile = formdata.id.test2.value; 87 is(storedFile.name, "value.txt", "File value name should be stored"); 88 is(await storedFile.text(), "value", "File value text should be stored"); 89 storedFile = formdata.id.test2.state; 90 is(storedFile.name, "state.txt", "File state name should be stored"); 91 is(await storedFile.text(), "state", "File state text should be stored"); 92 93 let storedFormData = formdata.id.test3.value; 94 is( 95 storedFormData.get("1"), 96 "value", 97 "FormData value string should be stored" 98 ); 99 is( 100 await storedFormData.get("2").text(), 101 "value_blob", 102 "Form value blob should be stored" 103 ); 104 storedFormData = formdata.id.test3.state; 105 is( 106 storedFormData.get("1"), 107 "state", 108 "FormData state string should be stored" 109 ); 110 is( 111 await storedFormData.get("2").text(), 112 "state_blob", 113 "Form state blob should be stored" 114 ); 115 116 is(formdata.id.test4.state, null, "Null state stored"); 117 is(formdata.id.test4.value, "null state", "Value with null state stored"); 118 119 is( 120 formdata.id.test5.value, 121 "both value and state", 122 "Undefined state should be set to value" 123 ); 124 is( 125 formdata.id.test5.state, 126 "both value and state", 127 "Undefined state should be set to value" 128 ); 129 130 ok( 131 !("test6" in formdata.id), 132 "Completely null values should not be stored" 133 ); 134 } 135 136 tab = ss.undoCloseTab(window, 0); 137 browser = tab.linkedBrowser; 138 await promiseTabRestored(tab); 139 140 // Check that the FACE state was restored. 141 await SpecialPowers.spawn(browser, ["restoredStates"], async prop => { 142 let restoredStates = content.wrappedJSObject[prop]; 143 is(restoredStates.test1, "test state", "String should be stored"); 144 145 let storedFile = restoredStates.test2; 146 is(storedFile.name, "state.txt", "File name should be stored"); 147 is(await storedFile.text(), "state", "File text should be stored"); 148 149 const storedFormData = restoredStates.test3; 150 is(storedFormData.get("1"), "state", "Form data string should be stored"); 151 is( 152 await storedFormData.get("2").text(), 153 "state_blob", 154 "Form data blob should be stored" 155 ); 156 157 ok(!("test4" in restoredStates), "Null values don't get restored"); 158 159 is( 160 restoredStates.test5, 161 "both value and state", 162 "Undefined state should be set to value" 163 ); 164 }); 165 166 // Cleanup. 167 gBrowser.removeTab(tab); 168 });