www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

fileTest.js (8841B)


      1 describe("Zotero.File", function () {
      2 	describe("#getContentsAsync()", function () {
      3 		it("should handle an empty file", function* () {
      4 			var path = OS.Path.join(getTestDataDirectory().path, "empty");
      5 			assert.equal((yield Zotero.File.getContentsAsync(path)), "");
      6 		})
      7 		
      8 		it("should handle an extended character", function* () {
      9 			var contents = yield Zotero.File.getContentsAsync(
     10 				OS.Path.join(getTestDataDirectory().path, "charsets", "utf8.txt")
     11 			);
     12 			assert.lengthOf(contents, 3);
     13 			assert.equal(contents, "A\u72acB");
     14 		})
     15 		
     16 		it("should handle an extended Windows-1252 character", function* () {
     17 			var contents = yield Zotero.File.getContentsAsync(
     18 				OS.Path.join(getTestDataDirectory().path, "charsets", "windows1252.txt"),
     19 				"windows-1252"
     20 			);
     21 			assert.lengthOf(contents, 1);
     22 			assert.equal(contents, "\u00E9");
     23 		})
     24 		
     25 		it("should handle a GBK character", function* () {
     26 			var contents = yield Zotero.File.getContentsAsync(
     27 				OS.Path.join(getTestDataDirectory().path, "charsets", "gbk.txt"),
     28 				"gbk"
     29 			);
     30 			assert.lengthOf(contents, 1);
     31 			assert.equal(contents, "\u4e02");
     32 		})
     33 		
     34 		it("should handle an invalid character", function* () {
     35 			var contents = yield Zotero.File.getContentsAsync(
     36 				OS.Path.join(getTestDataDirectory().path, "charsets", "invalid.txt")
     37 			);
     38 			assert.lengthOf(contents, 3);
     39 			assert.equal(contents, "A\uFFFDB");
     40 		})
     41 		
     42 		it("should respect maxLength", function* () {
     43 			var contents = yield Zotero.File.getContentsAsync(
     44 				OS.Path.join(getTestDataDirectory().path, "test.txt"),
     45 				false,
     46 				6
     47 			);
     48 			assert.lengthOf(contents, 6);
     49 			assert.equal(contents, "Zotero");
     50 		});
     51 		
     52 		it("should get a file from a file: URI", function* () {
     53 			var contents = yield Zotero.File.getContentsAsync(
     54 				OS.Path.toFileURI(OS.Path.join(getTestDataDirectory().path, "test.txt"))
     55 			);
     56 			assert.isTrue(contents.startsWith('Zotero'));
     57 		});
     58 	})
     59 	
     60 	describe("#getBinaryContentsAsync()", function () {
     61 		var magicPNG = ["89", "50", "4e", "47", "0d", "0a", "1a", "0a"].map(x => parseInt(x, 16));
     62 		
     63 		it("should return a binary string", function* () {
     64 			var contents = yield Zotero.File.getBinaryContentsAsync(
     65 				OS.Path.join(getTestDataDirectory().path, "test.png")
     66 			);
     67 			assert.isAbove(contents.length, magicPNG.length);
     68 			for (let i = 0; i < magicPNG.length; i++) {
     69 				assert.equal(magicPNG[i], contents.charCodeAt(i));
     70 			}
     71 		});
     72 		
     73 		it("should respect maxLength", function* () {
     74 			var contents = yield Zotero.File.getBinaryContentsAsync(
     75 				OS.Path.join(getTestDataDirectory().path, "test.png"),
     76 				magicPNG.length
     77 			);
     78 			assert.lengthOf(contents, magicPNG.length)
     79 			for (let i = 0; i < contents.length; i++) {
     80 				assert.equal(magicPNG[i], contents.charCodeAt(i));
     81 			}
     82 		});
     83 	});
     84 	
     85 	describe("#putContentsAsync()", function () {
     86 		it("should save via .tmp file", function* () {
     87 			var tmpDir = yield getTempDirectory();
     88 			var destFile = OS.Path.join(tmpDir, 'test.txt')
     89 			var tmpFile = destFile + ".tmp";
     90 			yield Zotero.File.putContentsAsync(tmpFile, 'A');
     91 			assert.isTrue(yield OS.File.exists(tmpFile));
     92 			yield Zotero.File.putContentsAsync(destFile, 'B');
     93 			assert.isFalse(yield OS.File.exists(tmpFile));
     94 			// Make sure .tmp file created when creating temp file was deleted too
     95 			assert.isFalse(yield OS.File.exists(tmpFile + '.tmp'));
     96 		});
     97 	});
     98 	
     99 	
    100 	describe("#rename()", function () {
    101 		it("should rename a file", async function () {
    102 			var tmpDir = await getTempDirectory();
    103 			var sourceFile = OS.Path.join(tmpDir, 'a');
    104 			var destFile = OS.Path.join(tmpDir, 'b');
    105 			await Zotero.File.putContentsAsync(sourceFile, '');
    106 			await Zotero.File.rename(sourceFile, 'b');
    107 			assert.isTrue(await OS.File.exists(destFile));
    108 		});
    109 		
    110 		it("should overwrite an existing file if `overwrite` is true", async function () {
    111 			var tmpDir = await getTempDirectory();
    112 			var sourceFile = OS.Path.join(tmpDir, 'a');
    113 			var destFile = OS.Path.join(tmpDir, 'b');
    114 			await Zotero.File.putContentsAsync(sourceFile, 'a');
    115 			await Zotero.File.putContentsAsync(destFile, 'b');
    116 			await Zotero.File.rename(sourceFile, 'b', { overwrite: true });
    117 			assert.isTrue(await OS.File.exists(destFile));
    118 			assert.equal(await Zotero.File.getContentsAsync(destFile), 'a');
    119 		});
    120 		
    121 		it("should get a unique name if target file exists and `unique` is true", async function () {
    122 			var tmpDir = await getTempDirectory();
    123 			var sourceFile = OS.Path.join(tmpDir, 'a');
    124 			var destFile = OS.Path.join(tmpDir, 'b');
    125 			await Zotero.File.putContentsAsync(sourceFile, 'a');
    126 			await Zotero.File.putContentsAsync(destFile, 'b');
    127 			var newFilename = await Zotero.File.rename(sourceFile, 'b', { unique: true });
    128 			var realDestFile = OS.Path.join(tmpDir, newFilename);
    129 			assert.equal(newFilename, 'b 2');
    130 			assert.isTrue(await OS.File.exists(realDestFile));
    131 			assert.equal(await Zotero.File.getContentsAsync(realDestFile), 'a');
    132 		});
    133 	});
    134 	
    135 	
    136 	describe("#getClosestDirectory()", function () {
    137 		it("should return directory for file that exists", function* () {
    138 			var tmpDir = yield getTempDirectory();
    139 			var closest = yield Zotero.File.getClosestDirectory(tmpDir);
    140 			assert.equal(closest, tmpDir);
    141 		});
    142 		
    143 		it("should return parent directory for missing file", function* () {
    144 			var tmpDir = yield getTempDirectory();
    145 			var closest = yield Zotero.File.getClosestDirectory(OS.Path.join(tmpDir, 'a'));
    146 			assert.equal(closest, tmpDir);
    147 		});
    148 		
    149 		it("should find an existing directory three levels up from a missing file", function* () {
    150 			var tmpDir = yield getTempDirectory();
    151 			var closest = yield Zotero.File.getClosestDirectory(OS.Path.join(tmpDir, 'a', 'b', 'c'));
    152 			assert.equal(closest, tmpDir);
    153 		});
    154 		
    155 		it("should return false for a path that doesn't exist at all", function* () {
    156 			assert.isFalse(yield Zotero.File.getClosestDirectory('/a/b/c'));
    157 		});
    158 	});
    159 	
    160 	
    161 	describe("#copyDirectory()", function () {
    162 		it("should copy all files within a directory", function* () {
    163 			var tmpDir = Zotero.getTempDirectory().path;
    164 			var tmpCopyDir = OS.Path.join(tmpDir, "copyDirectory")
    165 			var source = OS.Path.join(tmpCopyDir, "1");
    166 			var target = OS.Path.join(tmpCopyDir, "2");
    167 			yield OS.File.makeDir(source, {
    168 				from: tmpDir
    169 			});
    170 			
    171 			yield Zotero.File.putContentsAsync(OS.Path.join(source, "A"), "Test 1");
    172 			yield Zotero.File.putContentsAsync(OS.Path.join(source, "B"), "Test 2");
    173 			
    174 			yield OS.File.removeDir(target, {
    175 				ignoreAbsent: true
    176 			});
    177 			
    178 			yield Zotero.File.copyDirectory(source, target);
    179 			
    180 			assert.equal(
    181 				(yield Zotero.File.getContentsAsync(OS.Path.join(target, "A"))),
    182 				"Test 1"
    183 			);
    184 			assert.equal(
    185 				(yield Zotero.File.getContentsAsync(OS.Path.join(target, "B"))),
    186 				"Test 2"
    187 			);
    188 		})
    189 	})
    190 	
    191 	describe("#zipDirectory()", function () {
    192 		it("should compress a directory recursively", function* () {
    193 			var tmpPath = Zotero.getTempDirectory().path;
    194 			var path = OS.Path.join(tmpPath, Zotero.Utilities.randomString());
    195 			yield OS.File.makeDir(path, { unixMode: 0o755 });
    196 			yield Zotero.File.putContentsAsync(OS.Path.join(path, '.zotero-ft-cache'), '');
    197 			yield Zotero.File.putContentsAsync(OS.Path.join(path, 'a.txt'), 'A');
    198 			// Create subdirectory
    199 			var subPath = OS.Path.join(path, 'sub');
    200 			yield OS.File.makeDir(subPath, { unixMode: 0o755 });
    201 			yield Zotero.File.putContentsAsync(OS.Path.join(subPath, 'b.txt'), 'B');
    202 			
    203 			var zipFile = OS.Path.join(tmpPath, 'test.zip');
    204 			yield Zotero.File.zipDirectory(path, zipFile);
    205 			
    206 			var zr = Components.classes["@mozilla.org/libjar/zip-reader;1"]
    207 				.createInstance(Components.interfaces.nsIZipReader);
    208 			zr.open(Zotero.File.pathToFile(zipFile));
    209 			var entries = zr.findEntries('*');
    210 			var files = {};
    211 			var is = Components.classes['@mozilla.org/scriptableinputstream;1']
    212 				.createInstance(Components.interfaces.nsIScriptableInputStream);
    213 			while (entries.hasMore()) {
    214 				let entryPointer = entries.getNext();
    215 				let entry = zr.getEntry(entryPointer);
    216 				let inputStream = zr.getInputStream(entryPointer);
    217 				is.init(inputStream);
    218 				files[entryPointer] = is.read(entry.realSize);
    219 			}
    220 			zr.close();
    221 			
    222 			assert.notProperty(files, '.zotero-ft-cache');
    223 			assert.propertyVal(files, 'a.txt', 'A');
    224 			assert.propertyVal(files, 'sub/b.txt', 'B');
    225 		});
    226 	});
    227 	
    228 	
    229 	describe("#checkFileAccessError()", function () {
    230 		it("should catch OS.File access-denied errors", function* () {
    231 			// We can't modify a real OS.File.Error, but we also don't do an instanceof check in
    232 			// checkFileAccessError, so just set the expected properties.
    233 			var e = {
    234 				operation: 'open',
    235 				becauseAccessDenied: true,
    236 				path: '/tmp/test'
    237 			};
    238 			try {
    239 				Zotero.File.checkFileAccessError(e, e.path, 'create');
    240 			}
    241 			catch (e) {
    242 				if (e instanceof Zotero.Error) {
    243 					return;
    244 				}
    245 				throw e;
    246 			}
    247 			throw new Error("Error not thrown");
    248 		});
    249 	});
    250 })