|
1 /* vim: set ts=2 et sw=2 tw=80: */ |
|
2 /* Any copyright is dedicated to the Public Domain. |
|
3 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
4 /* Bug 653427 */ |
|
5 |
|
6 let tempScope = {}; |
|
7 Cu.import("resource://gre/modules/NetUtil.jsm", tempScope); |
|
8 Cu.import("resource://gre/modules/FileUtils.jsm", tempScope); |
|
9 let NetUtil = tempScope.NetUtil; |
|
10 let FileUtils = tempScope.FileUtils; |
|
11 |
|
12 // only finish() when correct number of tests are done |
|
13 const expected = 9; |
|
14 var count = 0; |
|
15 function done() |
|
16 { |
|
17 if (++count == expected) { |
|
18 cleanup(); |
|
19 finish(); |
|
20 } |
|
21 } |
|
22 |
|
23 var gFile; |
|
24 |
|
25 var oldPrompt = Services.prompt; |
|
26 var promptButton = -1; |
|
27 |
|
28 function test() |
|
29 { |
|
30 waitForExplicitFinish(); |
|
31 |
|
32 gFile = createTempFile("fileForBug653427.tmp"); |
|
33 writeFile(gFile, "text", testUnsaved.call(this)); |
|
34 |
|
35 Services.prompt = { |
|
36 confirmEx: function() { |
|
37 return promptButton; |
|
38 } |
|
39 }; |
|
40 |
|
41 testNew(); |
|
42 testSavedFile(); |
|
43 |
|
44 gBrowser.selectedTab = gBrowser.addTab(); |
|
45 content.location = "data:text/html,<p>test scratchpad save file prompt on closing"; |
|
46 } |
|
47 |
|
48 function testNew() |
|
49 { |
|
50 openScratchpad(function(win) { |
|
51 win.Scratchpad.close(function() { |
|
52 ok(win.closed, "new scratchpad window should close without prompting") |
|
53 done(); |
|
54 }); |
|
55 }, {noFocus: true}); |
|
56 } |
|
57 |
|
58 function testSavedFile() |
|
59 { |
|
60 openScratchpad(function(win) { |
|
61 win.Scratchpad.filename = "test.js"; |
|
62 win.Scratchpad.editor.dirty = false; |
|
63 win.Scratchpad.close(function() { |
|
64 ok(win.closed, "scratchpad from file with no changes should close") |
|
65 done(); |
|
66 }); |
|
67 }, {noFocus: true}); |
|
68 } |
|
69 |
|
70 function testUnsaved() |
|
71 { |
|
72 function setFilename(aScratchpad, aFile) { |
|
73 aScratchpad.setFilename(aFile); |
|
74 } |
|
75 |
|
76 testUnsavedFileCancel(setFilename); |
|
77 testUnsavedFileSave(setFilename); |
|
78 testUnsavedFileDontSave(setFilename); |
|
79 testCancelAfterLoad(); |
|
80 |
|
81 function mockSaveFile(aScratchpad) { |
|
82 let SaveFileStub = function (aCallback) { |
|
83 /* |
|
84 * An argument for aCallback must pass Components.isSuccessCode |
|
85 * |
|
86 * A version of isSuccessCode in JavaScript: |
|
87 * function isSuccessCode(returnCode) { |
|
88 * return (returnCode & 0x80000000) == 0; |
|
89 * } |
|
90 */ |
|
91 aCallback(1); |
|
92 }; |
|
93 |
|
94 aScratchpad.saveFile = SaveFileStub; |
|
95 } |
|
96 |
|
97 // Run these tests again but this time without setting a filename to |
|
98 // test that Scratchpad always asks for confirmation on dirty editor. |
|
99 testUnsavedFileCancel(mockSaveFile); |
|
100 testUnsavedFileSave(mockSaveFile); |
|
101 testUnsavedFileDontSave(); |
|
102 } |
|
103 |
|
104 function testUnsavedFileCancel(aCallback=function () {}) |
|
105 { |
|
106 openScratchpad(function(win) { |
|
107 aCallback(win.Scratchpad, "test.js"); |
|
108 win.Scratchpad.editor.dirty = true; |
|
109 |
|
110 promptButton = win.BUTTON_POSITION_CANCEL; |
|
111 |
|
112 win.Scratchpad.close(function() { |
|
113 ok(!win.closed, "cancelling dialog shouldn't close scratchpad"); |
|
114 win.close(); |
|
115 done(); |
|
116 }); |
|
117 }, {noFocus: true}); |
|
118 } |
|
119 |
|
120 // Test a regression where our confirmation dialog wasn't appearing |
|
121 // after openFile calls. See bug 801982. |
|
122 function testCancelAfterLoad() |
|
123 { |
|
124 openScratchpad(function(win) { |
|
125 win.Scratchpad.setRecentFile(gFile); |
|
126 win.Scratchpad.openFile(0); |
|
127 win.Scratchpad.editor.dirty = true; |
|
128 promptButton = win.BUTTON_POSITION_CANCEL; |
|
129 |
|
130 let EventStub = { |
|
131 called: false, |
|
132 preventDefault: function() { |
|
133 EventStub.called = true; |
|
134 } |
|
135 }; |
|
136 |
|
137 win.Scratchpad.onClose(EventStub, function() { |
|
138 ok(!win.closed, "cancelling dialog shouldn't close scratchpad"); |
|
139 ok(EventStub.called, "aEvent.preventDefault was called"); |
|
140 |
|
141 win.Scratchpad.editor.dirty = false; |
|
142 win.close(); |
|
143 done(); |
|
144 }); |
|
145 }, {noFocus: true}); |
|
146 } |
|
147 |
|
148 function testUnsavedFileSave(aCallback=function () {}) |
|
149 { |
|
150 openScratchpad(function(win) { |
|
151 win.Scratchpad.importFromFile(gFile, true, function(status, content) { |
|
152 aCallback(win.Scratchpad, gFile.path); |
|
153 |
|
154 let text = "new text"; |
|
155 win.Scratchpad.setText(text); |
|
156 |
|
157 promptButton = win.BUTTON_POSITION_SAVE; |
|
158 |
|
159 win.Scratchpad.close(function() { |
|
160 ok(win.closed, 'pressing "Save" in dialog should close scratchpad'); |
|
161 readFile(gFile, function(savedContent) { |
|
162 is(savedContent, text, 'prompted "Save" worked when closing scratchpad'); |
|
163 done(); |
|
164 }); |
|
165 }); |
|
166 }); |
|
167 }, {noFocus: true}); |
|
168 } |
|
169 |
|
170 function testUnsavedFileDontSave(aCallback=function () {}) |
|
171 { |
|
172 openScratchpad(function(win) { |
|
173 aCallback(win.Scratchpad, gFile.path); |
|
174 win.Scratchpad.editor.dirty = true; |
|
175 |
|
176 promptButton = win.BUTTON_POSITION_DONT_SAVE; |
|
177 |
|
178 win.Scratchpad.close(function() { |
|
179 ok(win.closed, 'pressing "Don\'t Save" in dialog should close scratchpad'); |
|
180 done(); |
|
181 }); |
|
182 }, {noFocus: true}); |
|
183 } |
|
184 |
|
185 function cleanup() |
|
186 { |
|
187 Services.prompt = oldPrompt; |
|
188 gFile.remove(false); |
|
189 gFile = null; |
|
190 } |
|
191 |
|
192 function createTempFile(name) |
|
193 { |
|
194 let file = FileUtils.getFile("TmpD", [name]); |
|
195 file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); |
|
196 file.QueryInterface(Ci.nsILocalFile) |
|
197 return file; |
|
198 } |
|
199 |
|
200 function writeFile(file, content, callback) |
|
201 { |
|
202 let fout = Cc["@mozilla.org/network/file-output-stream;1"]. |
|
203 createInstance(Ci.nsIFileOutputStream); |
|
204 fout.init(file.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20, |
|
205 0644, fout.DEFER_OPEN); |
|
206 |
|
207 let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]. |
|
208 createInstance(Ci.nsIScriptableUnicodeConverter); |
|
209 converter.charset = "UTF-8"; |
|
210 let fileContentStream = converter.convertToInputStream(content); |
|
211 |
|
212 NetUtil.asyncCopy(fileContentStream, fout, callback); |
|
213 } |
|
214 |
|
215 function readFile(file, callback) |
|
216 { |
|
217 let channel = NetUtil.newChannel(file); |
|
218 channel.contentType = "application/javascript"; |
|
219 |
|
220 NetUtil.asyncFetch(channel, function(inputStream, status) { |
|
221 ok(Components.isSuccessCode(status), |
|
222 "file was read successfully"); |
|
223 |
|
224 let content = NetUtil.readInputStreamToString(inputStream, |
|
225 inputStream.available()); |
|
226 callback(content); |
|
227 }); |
|
228 } |