diff options
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-file/tests/tests.js')
| -rw-r--r-- | StoneIsland/plugins/cordova-plugin-file/tests/tests.js | 4163 |
1 files changed, 4163 insertions, 0 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-file/tests/tests.js b/StoneIsland/plugins/cordova-plugin-file/tests/tests.js new file mode 100644 index 00000000..a9ae20aa --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-file/tests/tests.js @@ -0,0 +1,4163 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/* eslint-env jasmine */ +/* global WebKitBlobBuilder */ + +exports.defineAutoTests = function () { + /* eslint-disable no-undef */ + var isBrowser = (cordova.platformId === 'browser'); + // Use feature detection to determine current browser instead of checking user-agent + var isChrome = isBrowser && window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL; + var isIE = isBrowser && (window.msIndexedDB); + var isIndexedDBShim = isBrowser && !isChrome; // Firefox and IE for example + + var isWindows = (cordova.platformId === 'windows' || cordova.platformId === 'windows8'); + /* eslint-enable no-undef */ + var MEDIUM_TIMEOUT = 15000; + + describe('File API', function () { + // Adding a Jasmine helper matcher, to report errors when comparing to FileError better. + var fileErrorMap = { + 1: 'NOT_FOUND_ERR', + 2: 'SECURITY_ERR', + 3: 'ABORT_ERR', + 4: 'NOT_READABLE_ERR', + 5: 'ENCODING_ERR', + 6: 'NO_MODIFICATION_ALLOWED_ERR', + 7: 'INVALID_STATE_ERR', + 8: 'SYNTAX_ERR', + 9: 'INVALID_MODIFICATION_ERR', + 10: 'QUOTA_EXCEEDED_ERR', + 11: 'TYPE_MISMATCH_ERR', + 12: 'PATH_EXISTS_ERR' + }; + var root; + var temp_root; + var persistent_root; + beforeEach(function (done) { + // Custom Matchers + jasmine.Expectation.addMatchers({ + toBeFileError: function () { + return { + compare: function (error, code) { + var pass = error.code === code; + return { + pass: pass, + message: 'Expected FileError with code ' + fileErrorMap[error.code] + ' (' + error.code + ') to be ' + fileErrorMap[code] + '(' + code + ')' + }; + } + }; + }, + toCanonicallyMatch: function () { + return { + compare: function (currentPath, path) { + var a = path.split('/').join('').split('\\').join(''); + var b = currentPath.split('/').join('').split('\\').join(''); + var pass = a === b; + return { + pass: pass, + message: 'Expected paths to match : ' + path + ' should be ' + currentPath + }; + } + }; + }, + toFailWithMessage: function () { + return { + compare: function (error, message) { // eslint-disable-line handle-callback-err + var pass = false; + return { + pass: pass, + message: message + }; + } + }; + }, + toBeDataUrl: function () { + return { + compare: function (url) { + var pass = false; + // "data:application/octet-stream;base64," + var header = url.substr(0, url.indexOf(',')); + var headerParts = header.split(/[:;]/); + if (headerParts.length === 3 && + headerParts[0] === 'data' && + headerParts[2] === 'base64') { + pass = true; + } + var message = 'Expected ' + url + ' to be a valid data url. ' + header + ' is not valid header for data uris'; + return { + pass: pass, + message: message + }; + } + }; + } + }); + // Define global variables + var onError = function (e) { + console.log('[ERROR] Problem setting up root filesystem for test running! Error to follow.'); + console.log(JSON.stringify(e)); + }; + window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fileSystem) { // eslint-disable-line no-undef + root = fileSystem.root; + // set in file.tests.js + persistent_root = root; + window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, function (fileSystem) { // eslint-disable-line no-undef + temp_root = fileSystem.root; + // set in file.tests.js + done(); + }, onError); + }, onError); + }); + // HELPER FUNCTIONS + // deletes specified file or directory + var deleteEntry = function (name, success, error) { + // deletes entry, if it exists + // entry.remove success callback is required: http://www.w3.org/TR/2011/WD-file-system-api-20110419/#the-entry-interface + success = success || function () {}; + error = error || failed.bind(null, success, 'deleteEntry failed.'); + + window.resolveLocalFileSystemURL(root.toURL() + '/' + name, function (entry) { + if (entry.isDirectory === true) { + entry.removeRecursively(success, error); + } else { + entry.remove(success, error); + } + }, success); + }; + // deletes file, if it exists, then invokes callback + var deleteFile = function (fileName, callback) { + // entry.remove success callback is required: http://www.w3.org/TR/2011/WD-file-system-api-20110419/#the-entry-interface + callback = callback || function () {}; + + root.getFile(fileName, null, // remove file system entry + function (entry) { + entry.remove(callback, function () { + console.log('[ERROR] deleteFile cleanup method invoked fail callback.'); + }); + }, // doesn't exist + callback); + }; + // deletes and re-creates the specified file + var createFile = function (fileName, success, error) { + deleteEntry(fileName, function () { + root.getFile(fileName, { + create: true + }, success, error); + }, error); + }; + // deletes and re-creates the specified directory + var createDirectory = function (dirName, success, error) { + deleteEntry(dirName, function () { + root.getDirectory(dirName, { + create: true + }, success, error); + }, error); + }; + function failed (done, msg, error) { + var info = typeof msg === 'undefined' ? 'Unexpected error callback' : msg; + var codeMsg = (error && error.code) ? (': ' + fileErrorMap[error.code]) : ''; + expect(true).toFailWithMessage(info + '\n' + JSON.stringify(error) + codeMsg); + done(); + } + var succeed = function (done, msg) { + var info = typeof msg === 'undefined' ? 'Unexpected success callback' : msg; + expect(true).toFailWithMessage(info); + done(); + }; + var joinURL = function (base, extension) { + if (base.charAt(base.length - 1) !== '/' && extension.charAt(0) !== '/') { + return base + '/' + extension; + } + if (base.charAt(base.length - 1) === '/' && extension.charAt(0) === '/') { + return base + extension.substring(1); + } + return base + extension; + }; + describe('FileError object', function () { + /* eslint-disable no-undef */ + it('file.spec.1 should define FileError constants', function () { + expect(FileError.NOT_FOUND_ERR).toBe(1); + expect(FileError.SECURITY_ERR).toBe(2); + expect(FileError.ABORT_ERR).toBe(3); + expect(FileError.NOT_READABLE_ERR).toBe(4); + expect(FileError.ENCODING_ERR).toBe(5); + expect(FileError.NO_MODIFICATION_ALLOWED_ERR).toBe(6); + expect(FileError.INVALID_STATE_ERR).toBe(7); + expect(FileError.SYNTAX_ERR).toBe(8); + expect(FileError.INVALID_MODIFICATION_ERR).toBe(9); + expect(FileError.QUOTA_EXCEEDED_ERR).toBe(10); + expect(FileError.TYPE_MISMATCH_ERR).toBe(11); + expect(FileError.PATH_EXISTS_ERR).toBe(12); + }); + }); + describe('LocalFileSystem', function () { + it('file.spec.2 should define LocalFileSystem constants', function () { + expect(LocalFileSystem.TEMPORARY).toBe(0); + expect(LocalFileSystem.PERSISTENT).toBe(1); + /* eslint-enable no-undef */ + }); + describe('window.requestFileSystem', function () { + it('file.spec.3 should be defined', function () { + expect(window.requestFileSystem).toBeDefined(); + }); + it('file.spec.4 should be able to retrieve a PERSISTENT file system', function (done) { + var win = function (fileSystem) { + expect(fileSystem).toBeDefined(); + expect(fileSystem.name).toBeDefined(); + if (isChrome) { + expect(fileSystem.name).toContain('Persistent'); + } else { + expect(fileSystem.name).toBe('persistent'); + } + expect(fileSystem.root).toBeDefined(); + expect(fileSystem.root.filesystem).toBeDefined(); + // Shouldn't use cdvfile by default. + expect(fileSystem.root.toURL()).not.toMatch(/^cdvfile:/); + // All DirectoryEntry URLs should always have a trailing slash. + expect(fileSystem.root.toURL()).toMatch(/\/$/); + done(); + }; + + // Request a little bit of space on the filesystem, unless we're running in a browser where that could cause a prompt. + var spaceRequired = isBrowser ? 0 : 1024; + + // retrieve PERSISTENT file system + window.requestFileSystem(LocalFileSystem.PERSISTENT, spaceRequired, win, failed.bind(null, done, 'window.requestFileSystem - Error retrieving PERSISTENT file system')); // eslint-disable-line no-undef + }); + it('file.spec.5 should be able to retrieve a TEMPORARY file system', function (done) { + var win = function (fileSystem) { + expect(fileSystem).toBeDefined(); + if (isChrome) { + expect(fileSystem.name).toContain('Temporary'); + } else { + expect(fileSystem.name).toBe('temporary'); + } + expect(fileSystem.root).toBeDefined(); + expect(fileSystem.root.filesystem).toBeDefined(); + expect(fileSystem.root.filesystem).toBe(fileSystem); + done(); + }; + // retrieve TEMPORARY file system + window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, win, failed.bind(null, done, 'window.requestFileSystem - Error retrieving TEMPORARY file system')); // eslint-disable-line no-undef + }); + it('file.spec.6 should error if you request a file system that is too large', function (done) { + if (isBrowser) { + /* window.requestFileSystem TEMPORARY and PERSISTENT filesystem quota is not limited in Chrome. + Firefox filesystem size is not limited but every 50MB request user permission. + IE10 allows up to 10mb of combined AppCache and IndexedDB used in implementation + of filesystem without prompting, once you hit that level you will be asked if you + want to allow it to be increased up to a max of 250mb per site. + So `size` parameter for `requestFileSystem` function does not affect on filesystem in Firefox and IE. */ + pending(); + } + + var fail = function (error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.QUOTA_EXCEEDED_ERR); // eslint-disable-line no-undef + done(); + }; + // win = createWin('window.requestFileSystem'); + // Request the file system + window.requestFileSystem(LocalFileSystem.TEMPORARY, 1000000000000000, failed.bind(null, done, 'window.requestFileSystem - Error retrieving TEMPORARY file system'), fail); // eslint-disable-line no-undef + }); + it('file.spec.7 should error out if you request a file system that does not exist', function (done) { + + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + /* INVALID_MODIFICATION_ERR (code: 9) or ??? (code: 13) is thrown instead of SYNTAX_ERR(code: 8) + on requesting of a non-existant filesystem. */ + // expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + } else { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } + done(); + }; + // Request the file system + window.requestFileSystem(-1, 0, succeed.bind(null, done, 'window.requestFileSystem'), fail); + }); + }); + describe('window.resolveLocalFileSystemURL', function () { + it('file.spec.8 should be defined', function () { + expect(window.resolveLocalFileSystemURL).toBeDefined(); + }); + it('file.spec.9 should resolve a valid file name', function (done) { + var fileName = 'file.spec.9'; + var win = function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.name).toCanonicallyMatch(fileName); + expect(fileEntry.toURL()).not.toMatch(/^cdvfile:/, 'should not use cdvfile URL'); + expect(fileEntry.toURL()).not.toMatch(/\/$/, 'URL should not end with a slash'); + // Clean-up + deleteEntry(fileName, done); + }; + createFile(fileName, function (entry) { + window.resolveLocalFileSystemURL(entry.toURL(), win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving file URL: ' + entry.toURL())); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName), failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.9.1 should resolve a file even with a terminating slash', function (done) { + var fileName = 'file.spec.9.1'; + var win = function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.name).toCanonicallyMatch(fileName); + expect(fileEntry.toURL()).not.toMatch(/^cdvfile:/, 'should not use cdvfile URL'); + expect(fileEntry.toURL()).not.toMatch(/\/$/, 'URL should not end with a slash'); + // Clean-up + deleteEntry(fileName, done); + }; + createFile(fileName, function (entry) { + var entryURL = entry.toURL() + '/'; + window.resolveLocalFileSystemURL(entryURL, win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving file URL: ' + entryURL)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName), failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.9.5 should resolve a directory', function (done) { + var fileName = 'file.spec.9.5'; + var win = function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(false); + expect(fileEntry.isDirectory).toBe(true); + expect(fileEntry.name).toCanonicallyMatch(fileName); + expect(fileEntry.toURL()).not.toMatch(/^cdvfile:/, 'should not use cdvfile URL'); + expect(fileEntry.toURL()).toMatch(/\/$/, 'URL end with a slash'); + // cleanup + deleteEntry(fileName, done); + }; + function gotDirectory (entry) { + // lookup file system entry + window.resolveLocalFileSystemURL(entry.toURL(), win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving directory URL: ' + entry.toURL())); + } + createDirectory(fileName, gotDirectory, failed.bind(null, done, 'createDirectory - Error creating directory: ' + fileName), failed.bind(null, done, 'createDirectory - Error creating directory: ' + fileName)); + }); + it('file.spec.9.6 should resolve a directory even without a terminating slash', function (done) { + var fileName = 'file.spec.9.6'; + var win = function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(false); + expect(fileEntry.isDirectory).toBe(true); + expect(fileEntry.name).toCanonicallyMatch(fileName); + expect(fileEntry.toURL()).not.toMatch(/^cdvfile:/, 'should not use cdvfile URL'); + expect(fileEntry.toURL()).toMatch(/\/$/, 'URL end with a slash'); + // cleanup + deleteEntry(fileName, done); + }; + function gotDirectory (entry) { + // lookup file system entry + var entryURL = entry.toURL(); + entryURL = entryURL.substring(0, entryURL.length - 1); + window.resolveLocalFileSystemURL(entryURL, win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving directory URL: ' + entryURL)); + } + createDirectory(fileName, gotDirectory, failed.bind(null, done, 'createDirectory - Error creating directory: ' + fileName), failed.bind(null, done, 'createDirectory - Error creating directory: ' + fileName)); + }); + + it('file.spec.9.7 should resolve a file with valid nativeURL', function (done) { + if (isBrowser) { + pending('browsers doesn\'t return nativeURL'); + } + var fileName = 'de.create.file'; + var win = function (entry) { + var path = entry.nativeURL.split('///')[1]; + expect(/\/{2,}/.test(path)).toBeFalsy(); + // cleanup + deleteEntry(entry.name, done); + }; + root.getFile(fileName, { + create: true + }, win, succeed.bind(null, done, 'root.getFile - Error unexpected callback, file should not exists: ' + fileName)); + }); + + it('file.spec.10 resolve valid file name with parameters', function (done) { + var fileName = 'resolve.file.uri.params'; + var win = function (fileEntry) { + expect(fileEntry).toBeDefined(); + if (fileEntry.toURL().toLowerCase().substring(0, 10) === 'cdvfile://') { + expect(fileEntry.fullPath).toBe('/' + fileName + '?1234567890'); + } + expect(fileEntry.name).toBe(fileName); + // cleanup + deleteEntry(fileName, done); + }; + // create a new file entry + createFile(fileName, function (entry) { + window.resolveLocalFileSystemURL(entry.toURL() + '?1234567890', win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving file URI: ' + entry.toURL())); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.11 should error (NOT_FOUND_ERR) when resolving (non-existent) invalid file name', function (done) { + var fileName = cordova.platformId === 'windowsphone' ? root.toURL() + '/' + 'this.is.not.a.valid.file.txt' : joinURL(root.toURL(), 'this.is.not.a.valid.file.txt'); // eslint-disable-line no-undef + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }; + // lookup file system entry + window.resolveLocalFileSystemURL(fileName, succeed.bind(null, done, 'window.resolveLocalFileSystemURL - Error unexpected callback resolving file URI: ' + fileName), fail); + }); + it('file.spec.12 should error (ENCODING_ERR) when resolving invalid URI with leading /', function (done) { + var fileName = '/this.is.not.a.valid.url'; + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // O.o chrome returns error code 0 + } else { + expect(error).toBeFileError(FileError.ENCODING_ERR); // eslint-disable-line no-undef + } + done(); + }; + // lookup file system entry + window.resolveLocalFileSystemURL(fileName, succeed.bind(null, done, 'window.resolveLocalFileSystemURL - Error unexpected callback resolving file URI: ' + fileName), fail); + }); + }); + }); + // LocalFileSystem + describe('Metadata interface', function () { + it('file.spec.13 should exist and have the right properties', function () { + var metadata = new Metadata(); // eslint-disable-line no-undef + expect(metadata).toBeDefined(); + expect(metadata.modificationTime).toBeDefined(); + }); + }); + describe('Flags interface', function () { + it('file.spec.14 should exist and have the right properties', function () { + var flags = new Flags(false, true); // eslint-disable-line no-undef + expect(flags).toBeDefined(); + expect(flags.create).toBeDefined(); + expect(flags.create).toBe(false); + expect(flags.exclusive).toBeDefined(); + expect(flags.exclusive).toBe(true); + }); + }); + describe('FileSystem interface', function () { + it('file.spec.15 should have a root that is a DirectoryEntry', function (done) { + var win = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(false); + expect(entry.isDirectory).toBe(true); + expect(entry.name).toBeDefined(); + expect(entry.fullPath).toBeDefined(); + expect(entry.getMetadata).toBeDefined(); + expect(entry.moveTo).toBeDefined(); + expect(entry.copyTo).toBeDefined(); + expect(entry.toURL).toBeDefined(); + expect(entry.remove).toBeDefined(); + expect(entry.getParent).toBeDefined(); + expect(entry.createReader).toBeDefined(); + expect(entry.getFile).toBeDefined(); + expect(entry.getDirectory).toBeDefined(); + expect(entry.removeRecursively).toBeDefined(); + done(); + }; + window.resolveLocalFileSystemURL(root.toURL(), win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving file URI: ' + root.toURL())); + }); + }); + describe('DirectoryEntry', function () { + it('file.spec.16 getFile: get Entry for file that does not exist', function (done) { + var fileName = 'de.no.file'; + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }; + // create:false, exclusive:false, file does not exist + root.getFile(fileName, { + create: false + }, succeed.bind(null, done, 'root.getFile - Error unexpected callback, file should not exists: ' + fileName), fail); + }); + it('file.spec.17 getFile: create new file', function (done) { + var fileName = 'de.create.file'; + var filePath = joinURL(root.fullPath, fileName); + var win = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(entry.name, done); + }; + // create:true, exclusive:false, file does not exist + root.getFile(fileName, { + create: true + }, win, succeed.bind(null, done, 'root.getFile - Error unexpected callback, file should not exists: ' + fileName)); + }); + it('file.spec.18 getFile: create new file (exclusive)', function (done) { + var fileName = 'de.create.exclusive.file'; + var filePath = joinURL(root.fullPath, fileName); + var win = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toBe(fileName); + expect(entry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(entry.name, done); + }; + // create:true, exclusive:true, file does not exist + root.getFile(fileName, { + create: true, + exclusive: true + }, win, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + }); + it('file.spec.19 getFile: create file that already exists', function (done) { + var fileName = 'de.create.existing.file'; + var filePath = joinURL(root.fullPath, fileName); + + function win (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(entry.name, done); + } + + function getFile (file) { + // create:true, exclusive:false, file exists + root.getFile(fileName, { + create: true + }, win, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + } + + // create file to kick off it + root.getFile(fileName, { + create: true + }, getFile, failed.bind(null, done, 'root.getFile - Error on initial creating file: ' + fileName)); + }); + it('file.spec.20 getFile: create file that already exists (exclusive)', function (done) { + var fileName = 'de.create.exclusive.existing.file'; + var existingFile; + + function fail (error) { + expect(error).toBeDefined(); + if (isChrome) { + /* INVALID_MODIFICATION_ERR (code: 9) or ??? (code: 13) is thrown instead of PATH_EXISTS_ERR(code: 12) + on trying to exclusively create a file, which already exists in Chrome. */ + // expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + } else { + expect(error).toBeFileError(FileError.PATH_EXISTS_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(existingFile.name, done); + } + + function getFile (file) { + existingFile = file; + // create:true, exclusive:true, file exists + root.getFile(fileName, { + create: true, + exclusive: true + }, succeed.bind(null, done, 'root.getFile - getFile function - Error unexpected callback, file should exists: ' + fileName), fail); + } + + // create file to kick off it + root.getFile(fileName, { + create: true + }, getFile, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + }); + it('file.spec.21 DirectoryEntry.getFile: get Entry for existing file', function (done) { + var fileName = 'de.get.file'; + var filePath = joinURL(root.fullPath, fileName); + var win = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toCanonicallyMatch(filePath); + expect(entry.filesystem).toBeDefined(); + expect(entry.filesystem).toBe(root.filesystem); + // clean up + deleteEntry(entry.name, done); + }; + var getFile = function (file) { + // create:false, exclusive:false, file exists + root.getFile(fileName, { + create: false + }, win, failed.bind(null, done, 'root.getFile - Error getting file entry: ' + fileName)); + }; + // create file to kick off it + root.getFile(fileName, { + create: true + }, getFile, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + }); + it('file.spec.22 DirectoryEntry.getFile: get FileEntry for invalid path', function (done) { + if (isBrowser) { + /* The plugin does not follow to ["8.3 Naming restrictions"] + (http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions). */ + pending(); + } + + var fileName = 'de:invalid:path'; + var fail = function (error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); // eslint-disable-line no-undef + done(); + }; + // create:false, exclusive:false, invalid path + root.getFile(fileName, { + create: false + }, succeed.bind(null, done, 'root.getFile - Error unexpected callback, file should not exists: ' + fileName), fail); + }); + it('file.spec.23 DirectoryEntry.getDirectory: get Entry for directory that does not exist', function (done) { + var dirName = 'de.no.dir'; + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }; + // create:false, exclusive:false, directory does not exist + root.getDirectory(dirName, { + create: false + }, succeed.bind(null, done, 'root.getDirectory - Error unexpected callback, directory should not exists: ' + dirName), fail); + }); + it('file.spec.24 DirectoryEntry.getDirectory: create new dir with space then resolveLocalFileSystemURL', function (done) { + var dirName = 'de create dir'; + + function win (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(joinURL(root.fullPath, dirName)); + // cleanup + deleteEntry(directory.name, done); + } + + function getDir (dirEntry) { + expect(dirEntry.filesystem).toBeDefined(); + expect(dirEntry.filesystem).toBe(root.filesystem); + var dirURI = dirEntry.toURL(); + // now encode URI and try to resolve + window.resolveLocalFileSystemURL(dirURI, win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - getDir function - Error resolving directory: ' + dirURI)); + } + + // create:true, exclusive:false, directory does not exist + root.getDirectory(dirName, { + create: true + }, getDir, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + // This test is excluded, and should probably be removed. Filesystem + // should always be properly encoded URLs, and *not* raw paths, and it + // doesn't make sense to double-encode the URLs and expect that to be + // handled by the implementation. + // If a particular platform uses paths internally rather than URLs, // then that platform should careful to pass them correctly to its + // backend. + xit('file.spec.25 DirectoryEntry.getDirectory: create new dir with space resolveLocalFileSystemURL with encoded URI', function (done) { + var dirName = 'de create dir2'; + var dirPath = joinURL(root.fullPath, dirName); + + function win (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + // cleanup + deleteEntry(directory.name, done); + } + + function getDir (dirEntry) { + var dirURI = dirEntry.toURL(); + // now encode URI and try to resolve + window.resolveLocalFileSystemURL(encodeURI(dirURI), win, failed.bind(null, done, 'window.resolveLocalFileSystemURL - getDir function - Error resolving directory: ' + dirURI)); + } + + // create:true, exclusive:false, directory does not exist + root.getDirectory(dirName, { + create: true + }, getDir, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.26 DirectoryEntry.getDirectory: create new directory', function (done) { + var dirName = 'de.create.dir'; + var dirPath = joinURL(root.fullPath, dirName); + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + expect(directory.filesystem).toBeDefined(); + expect(directory.filesystem).toBe(root.filesystem); + // cleanup + deleteEntry(directory.name, done); + }; + // create:true, exclusive:false, directory does not exist + root.getDirectory(dirName, { + create: true + }, win, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.27 DirectoryEntry.getDirectory: create new directory (exclusive)', function (done) { + var dirName = 'de.create.exclusive.dir'; + var dirPath = joinURL(root.fullPath, dirName); + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + expect(directory.filesystem).toBeDefined(); + expect(directory.filesystem).toBe(root.filesystem); + // cleanup + deleteEntry(directory.name, done); + }; + // create:true, exclusive:true, directory does not exist + root.getDirectory(dirName, { + create: true, + exclusive: true + }, win, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.28 DirectoryEntry.getDirectory: create directory that already exists', function (done) { + var dirName = 'de.create.existing.dir'; + var dirPath = joinURL(root.fullPath, dirName); + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + // cleanup + deleteEntry(directory.name, done); + }; + // create directory to kick off it + root.getDirectory(dirName, { + create: true + }, function () { + root.getDirectory(dirName, { + create: true + }, win, failed.bind(null, done, 'root.getDirectory - Error creating existent second directory : ' + dirName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.29 DirectoryEntry.getDirectory: create directory that already exists (exclusive)', function (done) { + + var dirName = 'de.create.exclusive.existing.dir'; + var existingDir; + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + /* INVALID_MODIFICATION_ERR (code: 9) or ??? (code: 13) is thrown instead of PATH_EXISTS_ERR(code: 12) + on trying to exclusively create a file or directory, which already exists (Chrome). */ + // expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + } else { + expect(error).toBeFileError(FileError.PATH_EXISTS_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(existingDir.name, done); + }; + // create directory to kick off it + root.getDirectory(dirName, { + create: true + }, function (directory) { + existingDir = directory; + // create:true, exclusive:true, directory exists + root.getDirectory(dirName, { + create: true, + exclusive: true + }, failed.bind(null, done, 'root.getDirectory - Unexpected success callback, second directory should not be created : ' + dirName), fail); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.30 DirectoryEntry.getDirectory: get Entry for existing directory', function (done) { + var dirName = 'de.get.dir'; + var dirPath = joinURL(root.fullPath, dirName); + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + expect(directory.fullPath).toCanonicallyMatch(dirPath); + // cleanup + deleteEntry(directory.name, done); + }; + // create directory to kick it off + root.getDirectory(dirName, { + create: true + }, function () { + root.getDirectory(dirName, { + create: false + }, win, failed.bind(null, done, 'root.getDirectory - Error getting directory entry : ' + dirName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.31 DirectoryEntry.getDirectory: get DirectoryEntry for invalid path', function (done) { + if (isBrowser) { + /* The plugin does not follow to ["8.3 Naming restrictions"] + (http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions). */ + pending(); + } + + var dirName = 'de:invalid:path'; + var fail = function (error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); // eslint-disable-line no-undef + done(); + }; + // create:false, exclusive:false, invalid path + root.getDirectory(dirName, { + create: false + }, succeed.bind(null, done, 'root.getDirectory - Unexpected success callback, directory should not exists: ' + dirName), fail); + }); + it('file.spec.32 DirectoryEntry.getDirectory: get DirectoryEntry for existing file', function (done) { + var fileName = 'de.existing.file'; + var existingFile; + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns an unknown error with code 17 + } else { + expect(error).toBeFileError(FileError.TYPE_MISMATCH_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(existingFile.name, done); + }; + // create file to kick off it + root.getFile(fileName, { + create: true + }, function (file) { + existingFile = file; + root.getDirectory(fileName, { + create: false + }, succeed.bind(null, done, 'root.getDirectory - Unexpected success callback, directory should not exists: ' + fileName), fail); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + fileName)); + }); + it('file.spec.33 DirectoryEntry.getFile: get FileEntry for existing directory', function (done) { + var dirName = 'de.existing.dir'; + var existingDir; + var fail = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns an unknown error with code 17 + } else { + expect(error).toBeFileError(FileError.TYPE_MISMATCH_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(existingDir.name, done); + }; + // create directory to kick off it + root.getDirectory(dirName, { + create: true + }, function (directory) { + existingDir = directory; + root.getFile(dirName, { + create: false + }, succeed.bind(null, done, 'root.getFile - Unexpected success callback, file should not exists: ' + dirName), fail); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.34 DirectoryEntry.removeRecursively on directory', function (done) { + var dirName = 'de.removeRecursively'; + var subDirName = 'dir'; + var dirExists = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }; + // create a new directory entry to kick off it + root.getDirectory(dirName, { + create: true + }, function (entry) { + entry.getDirectory(subDirName, { + create: true + }, function (dir) { + entry.removeRecursively(function () { + root.getDirectory(dirName, { + create: false + }, succeed.bind(null, done, 'root.getDirectory - Unexpected success callback, directory should not exists: ' + dirName), dirExists); + }, failed.bind(null, done, 'entry.removeRecursively - Error removing directory recursively : ' + dirName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + subDirName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.35 createReader: create reader on existing directory', function () { + // create reader for root directory + var reader = root.createReader(); + expect(reader).toBeDefined(); + expect(typeof reader.readEntries).toBe('function'); + }); + it('file.spec.36 removeRecursively on root file system', function (done) { + + var remove = function (error) { + expect(error).toBeDefined(); + if (isChrome) { + /* INVALID_MODIFICATION_ERR (code: 9) or ??? (code: 13) is thrown instead of + NO_MODIFICATION_ALLOWED_ERR(code: 6) on trying to call removeRecursively + on the root file system (Chrome). */ + // expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + } else { + expect(error).toBeFileError(FileError.NO_MODIFICATION_ALLOWED_ERR); // eslint-disable-line no-undef + } + done(); + }; + // remove root file system + root.removeRecursively(succeed.bind(null, done, 'root.removeRecursively - Unexpected success callback, root cannot be removed'), remove); + }); + }); + describe('DirectoryReader interface', function () { + describe('readEntries', function () { + it('file.spec.37 should read contents of existing directory', function (done) { + var reader; + var win = function (entries) { + expect(entries).toBeDefined(); + expect(entries instanceof Array).toBe(true); + done(); + }; + // create reader for root directory + reader = root.createReader(); + // read entries + reader.readEntries(win, failed.bind(null, done, 'reader.readEntries - Error reading entries')); + }); + it('file.spec.37.1 should read contents of existing directory', function (done) { + var dirName = 'readEntries.dir'; + var fileName = 'readeEntries.file'; + root.getDirectory(dirName, { + create: true + }, function (directory) { + directory.getFile(fileName, { + create: true + }, function (fileEntry) { + var reader = directory.createReader(); + reader.readEntries(function (entries) { + expect(entries).toBeDefined(); + expect(entries instanceof Array).toBe(true); + expect(entries.length).toBe(1); + expect(entries[0].fullPath).toCanonicallyMatch(fileEntry.fullPath); + expect(entries[0].filesystem).not.toBe(null); + if (isChrome) { + // Slicing '[object {type}]' -> '{type}' + expect(entries[0].filesystem.toString().slice(8, -1)).toEqual('DOMFileSystem'); + } else { + expect(entries[0].filesystem instanceof FileSystem).toBe(true); // eslint-disable-line no-undef + } + + // cleanup + deleteEntry(directory.name, done); + }, failed.bind(null, done, 'reader.readEntries - Error reading entries from directory: ' + dirName)); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + fileName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.109 should return an empty entry list on the second call', function (done) { + var reader; + var fileName = 'test109.txt'; + // Add a file to ensure the root directory is non-empty and then read the contents of the directory. + root.getFile(fileName, { + create: true + }, function (entry) { + reader = root.createReader(); + // First read + reader.readEntries(function (entries) { + expect(entries).toBeDefined(); + expect(entries instanceof Array).toBe(true); + expect(entries.length).not.toBe(0); + // Second read + reader.readEntries(function (entries_) { + expect(entries_).toBeDefined(); + expect(entries_ instanceof Array).toBe(true); + expect(entries_.length).toBe(0); + // Clean up + deleteEntry(entry.name, done); + }, failed.bind(null, done, 'reader.readEntries - Error during SECOND reading of entries from [root] directory')); + }, failed.bind(null, done, 'reader.readEntries - Error during FIRST reading of entries from [root] directory')); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + fileName)); + }); + }); + it('file.spec.38 should read contents of directory that has been removed', function (done) { + var dirName = 'de.createReader.notfound'; + // create a new directory entry to kick off it + root.getDirectory(dirName, { + create: true + }, function (directory) { + directory.removeRecursively(function () { + var reader = directory.createReader(); + reader.readEntries(succeed.bind(null, done, 'reader.readEntries - Unexpected success callback, it should not read entries from deleted dir: ' + dirName), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + root.getDirectory(dirName, { + create: false + }, succeed.bind(null, done, 'root.getDirectory - Unexpected success callback, it should not get deleted directory: ' + dirName), function (err) { + expect(err).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }); + }); + }, failed.bind(null, done, 'directory.removeRecursively - Error removing directory recursively : ' + dirName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + }); + // DirectoryReader interface + describe('File', function () { + it('file.spec.39 constructor should be defined', function () { + expect(File).toBeDefined(); // eslint-disable-line no-undef + expect(typeof File).toBe('function'); + }); + it('file.spec.40 should be define File attributes', function () { + var file = new File(); // eslint-disable-line no-undef + expect(file.name).toBeDefined(); + expect(file.type).toBeDefined(); + expect(file.lastModifiedDate).toBeDefined(); + expect(file.size).toBeDefined(); + }); + }); + // File + describe('FileEntry', function () { + + it('file.spec.41 should be define FileEntry methods', function (done) { + var fileName = 'fe.methods'; + var testFileEntry = function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(typeof fileEntry.createWriter).toBe('function'); + expect(typeof fileEntry.file).toBe('function'); + // cleanup + deleteEntry(fileEntry.name, done); + }; + // create a new file entry to kick off it + root.getFile(fileName, { + create: true + }, testFileEntry, failed.bind(null, done, 'root.getFile - Error creating file : ' + fileName)); + }); + it('file.spec.42 createWriter should return a FileWriter object', function (done) { + var fileName = 'fe.createWriter'; + var testFile; + var testWriter = function (writer) { + expect(writer).toBeDefined(); + if (isChrome) { + // Slicing '[object {type}]' -> '{type}' + expect(writer.toString().slice(8, -1)).toEqual('FileWriter'); + } else { + expect(writer instanceof FileWriter).toBe(true); // eslint-disable-line no-undef + } + + // cleanup + deleteEntry(testFile.name, done); + }; + // create a new file entry to kick off it + root.getFile(fileName, { + create: true + }, function (fileEntry) { + testFile = fileEntry; + fileEntry.createWriter(testWriter, failed.bind(null, done, 'fileEntry.createWriter - Error creating Writer from entry')); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + fileName)); + }); + it('file.spec.43 file should return a File object', function (done) { + var fileName = 'fe.file'; + var newFile; + var testFile = function (file) { + expect(file).toBeDefined(); + if (isChrome) { + // Slicing '[object {type}]' -> '{type}' + expect(file.toString().slice(8, -1)).toEqual('File'); + } else { + expect(file instanceof File).toBe(true); // eslint-disable-line no-undef + } + + // cleanup + deleteEntry(newFile.name, done); + }; + // create a new file entry to kick off it + root.getFile(fileName, { + create: true + }, function (fileEntry) { + newFile = fileEntry; + fileEntry.file(testFile, failed.bind(null, done, 'fileEntry.file - Error reading file using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + fileName)); + }); + it('file.spec.44 file: on File that has been removed', function (done) { + var fileName = 'fe.no.file'; + // create a new file entry to kick off it + root.getFile(fileName, { + create: true + }, function (fileEntry) { + fileEntry.remove(function () { + fileEntry.file(succeed.bind(null, done, 'fileEntry.file - Unexpected success callback, file it should not be created from removed entry'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }); + }, failed.bind(null, done, 'fileEntry.remove - Error removing entry : ' + fileName)); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + fileName)); + }); + }); + // FileEntry + describe('Entry', function () { + it('file.spec.45 Entry object', function (done) { + var fileName = 'entry'; + var fullPath = joinURL(root.fullPath, fileName); + var winEntry = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(fileName); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(typeof entry.getMetadata).toBe('function'); + expect(typeof entry.setMetadata).toBe('function'); + expect(typeof entry.moveTo).toBe('function'); + expect(typeof entry.copyTo).toBe('function'); + expect(typeof entry.toURL).toBe('function'); + expect(typeof entry.remove).toBe('function'); + expect(typeof entry.getParent).toBe('function'); + expect(typeof entry.createWriter).toBe('function'); + expect(typeof entry.file).toBe('function'); + // Clean up + deleteEntry(fileName, done); + }; + // create a new file entry + createFile(fileName, winEntry, failed.bind(null, done, 'createFile - Error creating file : ' + fileName)); + }); + it('file.spec.46 Entry.getMetadata on file', function (done) { + var fileName = 'entry.metadata.file'; + // create a new file entry + createFile(fileName, function (entry) { + entry.getMetadata(function (metadata) { + expect(metadata).toBeDefined(); + expect(metadata.modificationTime instanceof Date).toBe(true); + expect(typeof metadata.size).toBe('number'); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'entry.getMetadata - Error getting metadata from entry : ' + fileName)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + fileName)); + }); + it('file.spec.47 Entry.getMetadata on directory', function (done) { + if (isIndexedDBShim) { + /* Does not support metadata for directories (Firefox, IE) */ + pending(); + } + + var dirName = 'entry.metadata.dir'; + // create a new directory entry + createDirectory(dirName, function (entry) { + entry.getMetadata(function (metadata) { + expect(metadata).toBeDefined(); + expect(metadata.modificationTime instanceof Date).toBe(true); + expect(typeof metadata.size).toBe('number'); + expect(metadata.size).toBe(0); + // cleanup + deleteEntry(dirName, done); + }, failed.bind(null, done, 'entry.getMetadata - Error getting metadata from entry : ' + dirName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.48 Entry.getParent on file in root file system', function (done) { + var fileName = 'entry.parent.file'; + var rootPath = root.fullPath; + // create a new file entry + createFile(fileName, function (entry) { + entry.getParent(function (parent) { + expect(parent).toBeDefined(); + expect(parent.fullPath).toCanonicallyMatch(rootPath); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'entry.getParent - Error getting parent directory of file : ' + fileName)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + fileName)); + }); + it('file.spec.49 Entry.getParent on directory in root file system', function (done) { + var dirName = 'entry.parent.dir'; + var rootPath = root.fullPath; + // create a new directory entry + createDirectory(dirName, function (entry) { + entry.getParent(function (parent) { + expect(parent).toBeDefined(); + expect(parent.fullPath).toCanonicallyMatch(rootPath); + // cleanup + deleteEntry(dirName, done); + }, failed.bind(null, done, 'entry.getParent - Error getting parent directory of directory : ' + dirName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.50 Entry.getParent on root file system', function (done) { + var rootPath = root.fullPath; + var winParent = function (parent) { + expect(parent).toBeDefined(); + expect(parent.fullPath).toCanonicallyMatch(rootPath); + done(); + }; + // create a new directory entry + root.getParent(winParent, failed.bind(null, done, 'root.getParent - Error getting parent directory of root')); + }); + it('file.spec.51 Entry.toURL on file', function (done) { + var fileName = 'entry.uri.file'; + var rootPath = root.fullPath; + var winURI = function (entry) { + var uri = entry.toURL(); + expect(uri).toBeDefined(); + expect(uri.indexOf(rootPath)).not.toBe(-1); + // cleanup + deleteEntry(fileName, done); + }; + // create a new file entry + createFile(fileName, winURI, failed.bind(null, done, 'createFile - Error creating file : ' + fileName)); + }); + it('file.spec.52 Entry.toURL on directory', function (done) { + var dirName_1 = 'num 1'; + var dirName_2 = 'num 2'; + var rootPath = root.fullPath; + createDirectory(dirName_1, function (entry) { + entry.getDirectory(dirName_2, { + create: true + }, function (entryFile) { + var uri = entryFile.toURL(); + expect(uri).toBeDefined(); + expect(uri).toContain('/num%201/num%202/'); + expect(uri.indexOf(rootPath)).not.toBe(-1); + // cleanup + deleteEntry(dirName_1, done); + }, failed.bind(null, done, 'entry.getDirectory - Error creating directory : ' + dirName_2)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dirName_1)); + }); + it('file.spec.53 Entry.remove on file', function (done) { + var fileName = 'entr .rm.file'; + // create a new file entry + createFile(fileName, function (entry) { + expect(entry).toBeDefined(); + entry.remove(function () { + root.getFile(fileName, null, succeed.bind(null, done, 'root.getFile - Unexpected success callback, it should not get deleted file : ' + fileName), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(fileName, done); + }); + }, failed.bind(null, done, 'entry.remove - Error removing entry : ' + fileName)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + fileName)); + }); + it('file.spec.53.1 Entry.remove on filename with #s', function (done) { + if (isBrowser) { + pending('Browsers can\'t do that'); + } + var fileName = 'entry.#rm#.file'; + // create a new file entry + createFile(fileName, function (entry) { + expect(entry).toBeDefined(); + entry.remove(function () { + root.getFile(fileName, null, succeed.bind(null, done, 'root.getFile - Unexpected success callback, it should not get deleted file : ' + fileName), function (error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + // cleanup + deleteEntry(fileName, done); + }); + }, failed.bind(null, done, 'entry.remove - Error removing entry : ' + fileName)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + fileName)); + }); + it('file.spec.54 remove on empty directory', function (done) { + var dirName = 'entry.rm.dir'; + // create a new directory entry + createDirectory(dirName, function (entry) { + expect(entry).toBeDefined(); + entry.remove(function () { + root.getDirectory(dirName, null, succeed.bind(null, done, 'root.getDirectory - Unexpected success callback, it should not get deleted directory : ' + dirName), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(dirName, done); + }); + }, failed.bind(null, done, 'entry.remove - Error removing entry : ' + dirName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.55 remove on non-empty directory', function (done) { + if (isIndexedDBShim) { + /* Both Entry.remove and directoryEntry.removeRecursively don't fail when removing + non-empty directories - directories being removed are cleaned + along with contents instead (Firefox, IE) */ + pending(); + } + + var dirName = 'ent y.rm.dir.not.empty'; + var fileName = 're ove.txt'; + var fullPath = joinURL(root.fullPath, dirName); + // create a new directory entry + createDirectory(dirName, function (entry) { + entry.getFile(fileName, { + create: true + }, function (fileEntry) { + entry.remove(succeed.bind(null, done, 'entry.remove - Unexpected success callback, it should not remove a directory that contains files : ' + dirName), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome is returning unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + root.getDirectory(dirName, null, function (entry) { + expect(entry).toBeDefined(); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + // cleanup + deleteEntry(dirName, done); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory : ' + dirName)); + }); + }, failed.bind(null, done, 'entry.getFile - Error creating file : ' + fileName + ' inside of ' + dirName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dirName)); + }); + it('file.spec.56 remove on root file system', function (done) { + + // remove entry that doesn't exist + root.remove(succeed.bind(null, done, 'entry.remove - Unexpected success callback, it should not remove entry that it does not exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + /* INVALID_MODIFICATION_ERR (code: 9) or ??? (code: 13) is thrown instead of + NO_MODIFICATION_ALLOWED_ERR(code: 6) on trying to call removeRecursively + on the root file system. */ + // expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); + } else { + expect(error).toBeFileError(FileError.NO_MODIFICATION_ALLOWED_ERR); // eslint-disable-line no-undef + } + done(); + }); + }); + it('file.spec.57 copyTo: file', function (done) { + var file1 = 'entry copy.file1'; + var file2 = 'entry copy.file2'; + var fullPath = joinURL(root.fullPath, file2); + // create a new file entry to kick off it + deleteEntry(file2, function () { + createFile(file1, function (fileEntry) { + // copy file1 to file2 + fileEntry.copyTo(root, file2, function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(entry.name).toCanonicallyMatch(file2); + root.getFile(file2, { + create: false + }, function (entry2) { + expect(entry2).toBeDefined(); + expect(entry2.isFile).toBe(true); + expect(entry2.isDirectory).toBe(false); + expect(entry2.fullPath).toCanonicallyMatch(fullPath); + expect(entry2.name).toCanonicallyMatch(file2); + // cleanup + deleteEntry(file1, function () { + deleteEntry(file2, done); + }); + }, failed.bind(null, done, 'root.getFile - Error getting copied file : ' + file2)); + }, failed.bind(null, done, 'fileEntry.copyTo - Error copying file : ' + file2)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'deleteEntry - Error removing file : ' + file2)); + }); + it('file.spec.58 copyTo: file onto itself', function (done) { + var file1 = 'entry.copy.fos.file1'; + // create a new file entry to kick off it + createFile(file1, function (entry) { + // copy file1 onto itself + entry.copyTo(root, null, succeed.bind(null, done, 'entry.copyTo - Unexpected success callback, it should not copy a null file'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(file1, done); + }); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }); + it('file.spec.59 copyTo: directory', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.copy.srcDir'; + var dstDir = 'entry.copy.dstDir'; + var dstPath = joinURL(root.fullPath, dstDir); + var filePath = joinURL(dstPath, file1); + // create a new directory entry to kick off it + deleteEntry(dstDir, function () { + createDirectory(srcDir, function (directory) { + // create a file within new directory + directory.getFile(file1, { + create: true + }, function () { + directory.copyTo(root, dstDir, function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + root.getDirectory(dstDir, { + create: false + }, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + dirEntry.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + expect(fileEntry.name).toCanonicallyMatch(file1); + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }, failed.bind(null, done, 'dirEntry.getFile - Error getting file : ' + file1)); + }, failed.bind(null, done, 'root.getDirectory - Error getting copied directory : ' + dstDir)); + }, failed.bind(null, done, 'directory.copyTo - Error copying directory : ' + srcDir + ' to :' + dstDir)); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.60 copyTo: directory to backup at same root directory', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.copy srcDirSame'; + var dstDir = 'entry.copy srcDirSame-backup'; + var dstPath = joinURL(root.fullPath, dstDir); + var filePath = joinURL(dstPath, file1); + // create a new directory entry to kick off it + deleteEntry(dstDir, function () { + createDirectory(srcDir, function (directory) { + directory.getFile(file1, { + create: true + }, function () { + directory.copyTo(root, dstDir, function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + root.getDirectory(dstDir, { + create: false + }, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + dirEntry.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + expect(fileEntry.name).toCanonicallyMatch(file1); + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }, failed.bind(null, done, 'dirEntry.getFile - Error getting file : ' + file1)); + }, failed.bind(null, done, 'root.getDirectory - Error getting copied directory : ' + dstDir)); + }, failed.bind(null, done, 'directory.copyTo - Error copying directory : ' + srcDir + ' to :' + dstDir)); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.61 copyTo: directory onto itself', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.copy.dos.srcDir'; + var srcPath = joinURL(root.fullPath, srcDir); + var filePath = joinURL(srcPath, file1); + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // create a file within new directory + directory.getFile(file1, { + create: true + }, function (fileEntry) { + // copy srcDir onto itself + directory.copyTo(root, null, succeed.bind(null, done, 'directory.copyTo - Unexpected success callback, it should not copy file: ' + srcDir + ' to a null destination'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + root.getDirectory(srcDir, { + create: false + }, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(srcPath); + dirEntry.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(srcDir, done); + }, failed.bind(null, done, 'dirEntry.getFile - Error getting file : ' + file1)); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory : ' + srcDir)); + }); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.62 copyTo: directory into itself', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var srcDir = 'entry.copy.dis.srcDir'; + var dstDir = 'entry.copy.dis.dstDir'; + var srcPath = joinURL(root.fullPath, srcDir); + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // copy source directory into itself + directory.copyTo(directory, dstDir, succeed.bind(null, done, 'directory.copyTo - Unexpected success callback, it should not copy a directory ' + srcDir + ' into itself'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + root.getDirectory(srcDir, { + create: false + }, function (dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(srcPath); + // cleanup + deleteEntry(srcDir, done); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory : ' + srcDir)); + }); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.63 copyTo: directory that does not exist', function (done) { + var file1 = 'entry.copy.dnf.file1'; + var dirName = 'dir-foo'; + createFile(file1, function (fileEntry) { + createDirectory(dirName, function (dirEntry) { + dirEntry.remove(function () { + fileEntry.copyTo(dirEntry, null, succeed.bind(null, done, 'fileEntry.copyTo - Unexpected success callback, it should not copy a file ' + file1 + ' into a removed directory'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }); + }, failed.bind(null, done, 'dirEntry.remove - Error removing directory : ' + dirName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dirName)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }); + it('file.spec.64 copyTo: invalid target name', function (done) { + if (isBrowser) { + /* The plugin does not follow ["8.3 Naming restrictions"] + (http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions */ + pending(); + } + + var file1 = 'entry.copy.itn.file1'; + var file2 = 'bad:file:name'; + // create a new file entry + createFile(file1, function (entry) { + // copy file1 to file2 + entry.copyTo(root, file2, succeed.bind(null, done, 'entry.copyTo - Unexpected success callback, it should not copy a file ' + file1 + ' to an invalid file name: ' + file2), function (error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); // eslint-disable-line no-undef + // cleanup + deleteEntry(file1, done); + }); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }); + it('file.spec.65 moveTo: file to same parent', function (done) { + var file1 = 'entry.move.fsp.file1'; + var file2 = 'entry.move.fsp.file2'; + var dstPath = joinURL(root.fullPath, file2); + // create a new file entry to kick off it + createFile(file1, function (entry) { + // move file1 to file2 + entry.moveTo(root, file2, function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(dstPath); + expect(entry.name).toCanonicallyMatch(file2); + root.getFile(file2, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(dstPath); + root.getFile(file1, { + create: false + }, succeed.bind(null, done, 'root.getFile - Unexpected success callback, it should not get invalid or moved file: ' + file1), function (error) { + // expect(navigator.fileMgr.testFileExists(srcPath) === false, "original file should not exist."); + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(file1, function () { + deleteEntry(file2, done); + }); + }); + }, failed.bind(null, done, 'root.getFile - Error getting file : ' + file2)); + }, failed.bind(null, done, 'entry.moveTo - Error moving file : ' + file1 + ' to root as: ' + file2)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }); + it('file.spec.66 moveTo: file to new parent', function (done) { + var file1 = 'entry.move.fnp.file1'; + var dir = 'entry.move.fnp.dir'; + var dstPath = joinURL(joinURL(root.fullPath, dir), file1); + // ensure destination directory is cleaned up first + deleteEntry(dir, function () { + // create a new file entry to kick off it + createFile(file1, function (entry) { + // create a parent directory to move file to + root.getDirectory(dir, { + create: true + }, function (directory) { + // move file1 to new directory + // move the file + entry.moveTo(directory, null, function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.fullPath).toCanonicallyMatch(dstPath); + expect(entry.name).toCanonicallyMatch(file1); + // test the moved file exists + directory.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(dstPath); + root.getFile(file1, { + create: false + }, succeed.bind(null, done, 'root.getFile - Unexpected success callback, it should not get invalid or moved file: ' + file1), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(file1, function () { + deleteEntry(dir, done); + }); + }); + }, failed.bind(null, done, 'directory.getFile - Error getting file : ' + file1 + ' from: ' + dir)); + }, failed.bind(null, done, 'entry.moveTo - Error moving file : ' + file1 + ' to: ' + dir + ' with the same name')); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dir)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dir)); + }); + it('file.spec.67 moveTo: directory to same parent', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.move.dsp.srcDir'; + var dstDir = 'entry.move.dsp.dstDir'; + var dstPath = joinURL(root.fullPath, dstDir); + var filePath = joinURL(dstPath, file1); + // ensure destination directory is cleaned up before it + deleteEntry(dstDir, function () { + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // create a file within directory + directory.getFile(file1, { + create: true + }, function () { + // move srcDir to dstDir + directory.moveTo(root, dstDir, function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + // test that moved file exists in destination dir + directory.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // check that the moved file no longer exists in original dir + root.getFile(file1, { + create: false + }, succeed.bind(null, done, 'directory.getFile - Unexpected success callback, it should not get invalid or moved file: ' + file1), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }); + }, failed.bind(null, done, 'directory.getFile - Error getting file : ' + file1 + ' from: ' + srcDir)); + }, failed.bind(null, done, 'entry.moveTo - Error moving directory : ' + srcDir + ' to root as: ' + dstDir)); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.68 moveTo: directory to same parent with same name', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.move.dsp.srcDir'; + var dstDir = 'entry.move.dsp.srcDir-backup'; + var dstPath = joinURL(root.fullPath, dstDir); + var filePath = joinURL(dstPath, file1); + // ensure destination directory is cleaned up before it + deleteEntry(dstDir, function () { + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // create a file within directory + directory.getFile(file1, { + create: true + }, function () { + // move srcDir to dstDir + directory.moveTo(root, dstDir, function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + // check that moved file exists in destination dir + directory.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // check that the moved file no longer exists in original dir + root.getFile(file1, { + create: false + }, succeed.bind(null, done, 'directory.getFile - Unexpected success callback, it should not get invalid or moved file: ' + file1), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }); + }, failed.bind(null, done, 'directory.getFile - Error getting file : ' + file1 + ' from: ' + srcDir)); + }, failed.bind(null, done, 'entry.moveTo - Error moving directory : ' + srcDir + ' to root as: ' + dstDir)); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.69 moveTo: directory to new parent', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.move.dnp.srcDir'; + var dstDir = 'entry.move.dnp.dstDir'; + var dstPath = joinURL(root.fullPath, dstDir); + var filePath = joinURL(dstPath, file1); + // ensure destination directory is cleaned up before it + deleteEntry(dstDir, function () { + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // create a file within directory + directory.getFile(file1, { + create: true + }, function () { + // move srcDir to dstDir + directory.moveTo(root, dstDir, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + // test that moved file exists in destination dir + dirEntry.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // test that the moved file no longer exists in original dir + root.getFile(file1, { + create: false + }, succeed.bind(null, done, 'root.getFile - Unexpected success callback, it should not get invalid or moved file: ' + file1), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }); + }, failed.bind(null, done, 'directory.getFile - Error getting file : ' + file1 + ' from: ' + dstDir)); + }, failed.bind(null, done, 'directory.moveTo - Error moving directory : ' + srcDir + ' to root as: ' + dstDir)); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + + it('file.spec.131 moveTo: directories tree to new parent', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var srcDir = 'entry.move.dnp.srcDir'; + var srcDirNestedFirst = 'entry.move.dnp.srcDir.Nested1'; + var srcDirNestedSecond = 'entry.move.dnp.srcDir.Nested2'; + var dstDir = 'entry.move.dnp.dstDir'; + + createDirectory(dstDir, function (dstDirectory) { + createDirectory(srcDir, function (srcDirectory) { + srcDirectory.getDirectory(srcDirNestedFirst, { create: true }, function () { + srcDirectory.getDirectory(srcDirNestedSecond, { create: true }, function () { + srcDirectory.moveTo(dstDirectory, srcDir, function successMove (transferredDirectory) { + var directoryReader = transferredDirectory.createReader(); + directoryReader.readEntries(function successRead (entries) { + expect(entries.length).toBe(2); + if (!isChrome) { + expect(entries[0].name).toBe(srcDirNestedFirst); + expect(entries[1].name).toBe(srcDirNestedSecond); + } + deleteEntry(dstDir, done); + }, failed.bind(null, done, 'Error getting entries from: ' + transferredDirectory)); + }, failed.bind(null, done, 'directory.moveTo - Error moving directory : ' + srcDir + ' to root as: ' + dstDir)); + }, failed.bind(null, done, 'directory.getDirectory - Error creating directory : ' + srcDirNestedSecond)); + }, failed.bind(null, done, 'directory.getDirectory - Error creating directory : ' + srcDirNestedFirst)); + }, failed.bind(null, done, 'createDirectory - Error creating source directory : ' + srcDir)); + }, failed.bind(null, done, 'createDirectory - Error creating dest directory : ' + dstDir)); + }); + + it('file.spec.70 moveTo: directory onto itself', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.move.dos.srcDir'; + var srcPath = joinURL(root.fullPath, srcDir); + var filePath = joinURL(srcPath, file1); + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // create a file within new directory + directory.getFile(file1, { + create: true + }, function () { + // move srcDir onto itself + directory.moveTo(root, null, succeed.bind(null, done, 'directory.moveTo - Unexpected success callback, it should not move directory to invalid path'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // test that original dir still exists + root.getDirectory(srcDir, { + create: false + }, function (dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(srcPath); + dirEntry.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(srcDir, done); + }, failed.bind(null, done, 'dirEntry.getFile - Error getting file : ' + file1 + ' from: ' + srcDir)); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory : ' + srcDir)); + }); + }, failed.bind(null, done, 'directory.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.71 moveTo: directory into itself', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var srcDir = 'entry.move.dis.srcDir'; + var dstDir = 'entry.move.dis.dstDir'; + var srcPath = joinURL(root.fullPath, srcDir); + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // move source directory into itself + directory.moveTo(directory, dstDir, succeed.bind(null, done, 'directory.moveTo - Unexpected success callback, it should not move a directory into itself: ' + srcDir), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // make sure original directory still exists + root.getDirectory(srcDir, { + create: false + }, function (entry) { + expect(entry).toBeDefined(); + expect(entry.fullPath).toCanonicallyMatch(srcPath); + // cleanup + deleteEntry(srcDir, done); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory, making sure that original directory still exists: ' + srcDir)); + }); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.130 moveTo: directory into similar directory', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var srcDir = 'entry.move.dis.srcDir'; + var dstDir = 'entry.move.dis.srcDir-backup'; + // create a new directory entry to kick off it + createDirectory(srcDir, function (srcDirEntry) { + deleteEntry(dstDir, function () { + createDirectory(dstDir, function (dstDirEntry) { + // move source directory into itself + srcDirEntry.moveTo(dstDirEntry, 'file', function (newDirEntry) { + expect(newDirEntry).toBeDefined(); + deleteEntry(dstDir, done); + }, failed.bind(null, done, 'directory.moveTo - Error moving a directory into a similarly-named directory: ' + srcDir)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + dstDir)); + }, failed.bind(null, done, 'deleteEntry - Error deleting directory : ' + dstDir)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.72 moveTo: file onto itself', function (done) { + var file1 = 'entry.move.fos.file1'; + var filePath = joinURL(root.fullPath, file1); + // create a new file entry to kick off it + createFile(file1, function (entry) { + // move file1 onto itself + entry.moveTo(root, null, succeed.bind(null, done, 'entry.moveTo - Unexpected success callback, it should not move a file: ' + file1 + ' into the same parent'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // test that original file still exists + root.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(file1, done); + }, failed.bind(null, done, 'root.getFile - Error getting file, making sure that original file still exists: ' + file1)); + }); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }); + it('file.spec.73 moveTo: file onto existing directory', function (done) { + var file1 = 'entry.move.fod.file1'; + var dstDir = 'entry.move.fod.dstDir'; + var subDir = 'subDir'; + var dirPath = joinURL(joinURL(root.fullPath, dstDir), subDir); + var filePath = joinURL(root.fullPath, file1); + // ensure destination directory is cleaned up before it + deleteEntry(dstDir, function () { + // create a new file entry to kick off it + createFile(file1, function (entry) { + // create top level directory + root.getDirectory(dstDir, { + create: true + }, function (directory) { + // create sub-directory + directory.getDirectory(subDir, { + create: true + }, function (subDirectory) { + // move file1 onto sub-directory + entry.moveTo(directory, subDir, succeed.bind(null, done, 'entry.moveTo - Unexpected success callback, it should not move a file: ' + file1 + ' into directory: ' + dstDir + '\n' + subDir + ' directory already exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // check that original dir still exists + directory.getDirectory(subDir, { + create: false + }, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dirPath); + // check that original file still exists + root.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(file1, function () { + deleteEntry(dstDir, done); + }); + }, failed.bind(null, done, 'root.getFile - Error getting file, making sure that original file still exists: ' + file1)); + }, failed.bind(null, done, 'directory.getDirectory - Error getting directory, making sure that original directory still exists: ' + subDir)); + }); + }, failed.bind(null, done, 'directory.getDirectory - Error creating directory : ' + subDir)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory : ' + dstDir)); + }, failed.bind(null, done, 'createFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.74 moveTo: directory onto existing file', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'entry.move.dof.file1'; + var srcDir = 'entry.move.dof.srcDir'; + var dirPath = joinURL(root.fullPath, srcDir); + var filePath = joinURL(root.fullPath, file1); + // create a new directory entry to kick off it + createDirectory(srcDir, function (entry) { + // create file + root.getFile(file1, { + create: true + }, function (fileEntry) { + // move directory onto file + entry.moveTo(root, file1, succeed.bind(null, done, 'entry.moveTo - Unexpected success callback, it should not move : \n' + srcDir + ' into root directory renamed as ' + file1 + '\n' + file1 + ' file already exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // test that original directory exists + root.getDirectory(srcDir, { + create: false + }, function (dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dirPath); + // test that original file exists + root.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(file1, function () { + deleteEntry(srcDir, done); + }); + }, failed.bind(null, done, 'root.getFile - Error getting file, making sure that original file still exists: ' + file1)); + }, failed.bind(null, done, 'directory.getDirectory - Error getting directory, making sure that original directory still exists: ' + srcDir)); + }); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.75 copyTo: directory onto existing file', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'entry.copy.dof.file1'; + var srcDir = 'entry.copy.dof.srcDir'; + var dirPath = joinURL(root.fullPath, srcDir); + var filePath = joinURL(root.fullPath, file1); + // create a new directory entry to kick off it + createDirectory(srcDir, function (entry) { + // create file + root.getFile(file1, { + create: true + }, function () { + // copy directory onto file + entry.copyTo(root, file1, succeed.bind(null, done, 'entry.copyTo - Unexpected success callback, it should not copy : \n' + srcDir + ' into root directory renamed as ' + file1 + '\n' + file1 + ' file already exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // check that original dir still exists + root.getDirectory(srcDir, { + create: false + }, function (dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dirPath); + // test that original file still exists + root.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // cleanup + deleteEntry(file1, function () { + deleteEntry(srcDir, done); + }); + }, failed.bind(null, done, 'root.getFile - Error getting file, making sure that original file still exists: ' + file1)); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory, making sure that original directory still exists: ' + srcDir)); + }); + }, failed.bind(null, done, 'root.getFile - Error creating file : ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }); + it('file.spec.76 moveTo: directory onto directory that is not empty', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var srcDir = 'entry.move.dod.srcDir'; + var dstDir = 'entry.move.dod.dstDir'; + var subDir = 'subDir'; + var srcPath = joinURL(root.fullPath, srcDir); + var dstPath = joinURL(joinURL(root.fullPath, dstDir), subDir); + // ensure destination directory is cleaned up before it + deleteEntry(dstDir, function () { + // create a new file entry to kick off it + createDirectory(srcDir, function (entry) { + // create top level directory + root.getDirectory(dstDir, { + create: true + }, function (directory) { + // create sub-directory + directory.getDirectory(subDir, { + create: true + }, function () { + // move srcDir onto dstDir (not empty) + entry.moveTo(root, dstDir, succeed.bind(null, done, 'entry.moveTo - Unexpected success callback, it should not copy : \n' + srcDir + ' into root directory renamed as ' + dstDir + '\n' + dstDir + ' directory already exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + // chrome returns unknown error with code 13 + } else { + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } + // making sure destination directory still exists + directory.getDirectory(subDir, { + create: false + }, function (dirEntry) { + // returning confirms existence so just check fullPath entry + expect(dirEntry).toBeDefined(); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + // making sure source directory exists + root.getDirectory(srcDir, { + create: false + }, function (srcEntry) { + expect(srcEntry).toBeDefined(); + expect(srcEntry.fullPath).toCanonicallyMatch(srcPath); + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }, failed.bind(null, done, 'root.getDirectory - Error getting directory, making sure that original directory still exists: ' + srcDir)); + }, failed.bind(null, done, 'directory.getDirectory - Error getting directory, making sure that original directory still exists: ' + subDir)); + }); + }, failed.bind(null, done, 'directory.getDirectory - Error creating directory : ' + subDir)); + }, failed.bind(null, done, 'directory.getDirectory - Error creating directory : ' + subDir)); + }, failed.bind(null, done, 'createDirectory - Error creating directory : ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.77 moveTo: file replace existing file', function (done) { + var file1 = 'entry.move.frf.file1'; + var file2 = 'entry.move.frf.file2'; + var file2Path = joinURL(root.fullPath, file2); + // create a new directory entry to kick off it + createFile(file1, function (entry) { + // create file + root.getFile(file2, { + create: true + }, function () { + // replace file2 with file1 + entry.moveTo(root, file2, function (entry2) { + expect(entry2).toBeDefined(); + expect(entry2.isFile).toBe(true); + expect(entry2.isDirectory).toBe(false); + expect(entry2.fullPath).toCanonicallyMatch(file2Path); + expect(entry2.name).toCanonicallyMatch(file2); + // old file should not exists + root.getFile(file1, { + create: false + }, succeed.bind(null, done, 'root.getFile - Unexpected success callback, file: ' + file1 + ' should not exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // test that new file exists + root.getFile(file2, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(file2Path); + // cleanup + deleteEntry(file1, function () { + deleteEntry(file2, done); + }); + }, failed.bind(null, done, 'root.getFile - Error getting moved file: ' + file2)); + }); + }, failed.bind(null, done, 'entry.moveTo - Error moving file : ' + file1 + ' to root as: ' + file2)); + }, failed.bind(null, done, 'root.getFile - Error creating file: ' + file2)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + file1)); + }); + it('file.spec.78 moveTo: directory replace empty directory', function (done) { + if (isIndexedDBShim) { + /* `copyTo` and `moveTo` functions do not support directories (Firefox, IE) */ + pending(); + } + + var file1 = 'file1'; + var srcDir = 'entry.move.drd.srcDir'; + var dstDir = 'entry.move.drd.dstDir'; + var dstPath = joinURL(root.fullPath, dstDir); + var filePath = dstPath + '/' + file1; + // ensure destination directory is cleaned up before it + deleteEntry(dstDir, function () { + // create a new directory entry to kick off it + createDirectory(srcDir, function (directory) { + // create a file within source directory + directory.getFile(file1, { + create: true + }, function () { + // create destination directory + root.getDirectory(dstDir, { + create: true + }, function () { + // move srcDir to dstDir + directory.moveTo(root, dstDir, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + // check that old directory contents have been moved + dirEntry.getFile(file1, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.fullPath).toCanonicallyMatch(filePath); + // check that old directory no longer exists + root.getDirectory(srcDir, { + create: false + }, succeed.bind(null, done, 'root.getDirectory - Unexpected success callback, directory: ' + srcDir + ' should not exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(srcDir, function () { + deleteEntry(dstDir, done); + }); + }); + }, failed.bind(null, done, 'dirEntry.getFile - Error getting moved file: ' + file1)); + }, failed.bind(null, done, 'entry.moveTo - Error moving directory : ' + srcDir + ' to root as: ' + dstDir)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory: ' + dstDir)); + }, failed.bind(null, done, 'root.getFile - Error creating file: ' + file1)); + }, failed.bind(null, done, 'createDirectory - Error creating directory: ' + srcDir)); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }); + it('file.spec.79 moveTo: directory that does not exist', function (done) { + if (isChrome) { + pending('chrome freak out about non-existend dir not being a DirectoryEntry'); + } + var file1 = 'entry.move.dnf.file1'; + var dstDir = 'entry.move.dnf.dstDir'; + var dstPath = joinURL(root.fullPath, dstDir); + // create a new file entry to kick off it + createFile(file1, function (entry) { + // move file to directory that does not exist + var directory = new DirectoryEntry(); // eslint-disable-line no-undef + directory.filesystem = root.filesystem; + directory.fullPath = dstPath; + entry.moveTo(directory, null, succeed.bind(null, done, 'entry.moveTo - Unexpected success callback, parent directory: ' + dstPath + ' should not exists'), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + /* INVALID_MODIFICATION_ERR (code: 9) is thrown instead of NOT_FOUND_ERR(code: 1) + on trying to moveTo directory that does not exist. */ + expect(error).toBeFileError(FileError.INVALID_MODIFICATION_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + // cleanup + deleteEntry(file1, done); + }); + }, failed.bind(null, done, 'createFile - Error creating file: ' + file1)); + }); + it('file.spec.80 moveTo: invalid target name', function (done) { + if (isBrowser) { + /* The plugin does not follow ["8.3 Naming restrictions"] + (http://www.w3.org/TR/2011/WD-file-system-api-20110419/#naming-restrictions */ + pending(); + } + + var file1 = 'entry.move.itn.file1'; + var file2 = 'bad:file:name'; + // create a new file entry to kick off it + createFile(file1, function (entry) { + // move file1 to file2 + entry.moveTo(root, file2, succeed.bind(null, done, 'entry.moveTo - Unexpected success callback, : ' + file1 + ' to root as: ' + file2), function (error) { + expect(error).toBeDefined(); + expect(error).toBeFileError(FileError.ENCODING_ERR); // eslint-disable-line no-undef + // cleanup + deleteEntry(file1, done); + }); + }, failed.bind(null, done, 'createFile - Error creating file: ' + file1)); + }); + }); + // Entry + describe('FileReader', function () { + it('file.spec.81 should have correct methods', function () { + var reader = new FileReader(); // eslint-disable-line no-undef + expect(reader).toBeDefined(); + expect(typeof reader.readAsBinaryString).toBe('function'); + expect(typeof reader.readAsDataURL).toBe('function'); + expect(typeof reader.readAsText).toBe('function'); + expect(typeof reader.readAsArrayBuffer).toBe('function'); + expect(typeof reader.abort).toBe('function'); + expect(reader.result).toBe(null); + }); + }); + // FileReader + describe('Read method', function () { + it('file.spec.82 should error out on non-existent file', function (done) { + var fileName = cordova.platformId === 'windowsphone' ? root.toURL() + '/' + 'somefile.txt' : 'somefile.txt'; // eslint-disable-line no-undef + var verifier = function (evt) { + expect(evt).toBeDefined(); + if (isChrome) { + expect(evt.target.error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(evt.target.error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }; + root.getFile(fileName, { + create: true + }, function (entry) { + entry.file(function (file) { + deleteEntry(fileName, function () { + // Create FileReader + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onerror = verifier; + reader.onload = succeed.bind(null, done, 'reader.onload - Unexpected success callback, file: ' + fileName + ' it should not exists'); + reader.readAsText(file); + }, failed.bind(null, done, 'deleteEntry - Error removing file: ' + fileName)); + }, failed.bind(null, done, 'entry.file - Error reading file: ' + fileName)); + }, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + }); + it('file.spec.83 should be able to read native blob objects', function (done) { + // Skip test if blobs are not supported (e.g.: Android 2.3). + if (typeof window.Blob === 'undefined' || typeof window.Uint8Array === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + } + var contents = 'asdf'; + var uint8Array = new Uint8Array(contents.length); + for (var i = 0; i < contents.length; ++i) { + uint8Array[i] = contents.charCodeAt(i); + } + var Builder = window.BlobBuilder || window.WebKitBlobBuilder; + var blob; + if (Builder) { + var builder = new Builder(); + builder.append(uint8Array.buffer); + builder.append(contents); + blob = builder.getBlob('text/plain'); + } else { + try { + // iOS 6 does not support Views, so pass in the buffer. + blob = new Blob([uint8Array.buffer, contents]); // eslint-disable-line no-undef + } catch (e) { + // Skip the test if we can't create a blob (e.g.: iOS 5). + if (e instanceof TypeError) { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + } + throw e; + } + } + var verifier = function (evt) { + expect(evt).toBeDefined(); + expect(evt.target.result).toBe('asdfasdf'); + done(); + }; + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onloadend = verifier; + reader.readAsText(blob); + }); + function writeDummyFile (writeBinary, callback, done, fileContents) { + var fileName = 'dummy.txt'; + var fileEntry = null; + // use default string if file data is not provided + var fileData = fileContents !== undefined ? fileContents : + '\u20AC\xEB - There is an exception to every rule. Except this one.'; + var fileDataAsBinaryString = fileContents !== undefined ? fileContents : + '\xe2\x82\xac\xc3\xab - There is an exception to every rule. Except this one.'; + + function createWriter (fe) { + fileEntry = fe; + fileEntry.createWriter(writeFile, failed.bind(null, done, 'fileEntry.createWriter - Error reading file: ' + fileName)); + } + + // writes file and reads it back in + function writeFile (writer) { + writer.onwriteend = function () { + fileEntry.file(function (f) { + callback(fileEntry, f, fileData, fileDataAsBinaryString); + }, failed.bind(null, done, 'writer.onwriteend - Error writing data on file: ' + fileName)); + }; + writer.write(fileData); + } + + fileData += writeBinary ? 'bin:\x01\x00' : ''; + fileDataAsBinaryString += writeBinary ? 'bin:\x01\x00' : ''; + // create a file, write to it, and read it in again + createFile(fileName, createWriter, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + } + function runReaderTest (funcName, writeBinary, done, progressFunc, verifierFunc, sliceStart, sliceEnd, fileContents) { + writeDummyFile(writeBinary, function (fileEntry, file, fileData, fileDataAsBinaryString) { + var verifier = function (evt) { + expect(evt).toBeDefined(); + verifierFunc(evt, fileData, fileDataAsBinaryString); + }; + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onprogress = progressFunc; + reader.onload = verifier; + reader.onerror = failed.bind(null, done, 'reader.onerror - Error reading file: ' + file + ' using function: ' + funcName); + if (sliceEnd !== undefined) { + // 'type' is specified so that is will be preserved in the resulting file: + // http://www.w3.org/TR/FileAPI/#slice-method-algo -> "6.4.1. The slice method" -> 4. A), 6. c) + file = file.slice(sliceStart, sliceEnd, file.type); + } else if (sliceStart !== undefined) { + file = file.slice(sliceStart, file.size, file.type); + } + reader[funcName](file); + }, done, fileContents); + } + function arrayBufferEqualsString (ab, str) { + var buf = new Uint8Array(ab); + var match = buf.length === str.length; + for (var i = 0; match && i < buf.length; i++) { + match = buf[i] === str.charCodeAt(i); + } + return match; + } + it('file.spec.84 should read file properly, readAsText', function (done) { + runReaderTest('readAsText', false, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileData); + done(); + }); + }); + it('file.spec.84.1 should read JSON file properly, readAsText', function (done) { + var testObject = {key1: 'value1', key2: 2}; + runReaderTest('readAsText', false, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toEqual(JSON.stringify(testObject)); + done(); + }, undefined, undefined, JSON.stringify(testObject)); + }); + it('file.spec.85 should read file properly, Data URI', function (done) { + runReaderTest('readAsDataURL', true, done, null, function (evt, fileData, fileDataAsBinaryString) { + /* `readAsDataURL` function is supported, but the mediatype in Chrome depends on entry name extension, + mediatype in IE is always empty (which is the same as `text-plain` according the specification), + the mediatype in Firefox is always `application/octet-stream`. + For example, if the content is `abcdefg` then Firefox returns `data:application/octet-stream;base64,YWJjZGVmZw==`, + IE returns `data:;base64,YWJjZGVmZw==`, Chrome returns `data:<mediatype depending on extension of entry name>;base64,YWJjZGVmZw==`. */ + expect(evt.target.result).toBeDataUrl(); + + // The atob function it is completely ignored during mobilespec execution, besides the returned object: evt + // it is encoded and the atob function is aimed to decode a string. Even with btoa (encode) the function it gets stucked + // because of the Unicode characters that contains the fileData object. + // Issue reported at JIRA with all the details: CB-7095 + + // expect(evt.target.result.slice(23)).toBe(atob(fileData)); + + done(); + }); + }); + it('file.spec.86 should read file properly, readAsBinaryString', function (done) { + if (isIE) { + /* `readAsBinaryString` function is not supported by IE and has not the stub. */ + pending(); + } + + runReaderTest('readAsBinaryString', true, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileDataAsBinaryString); + done(); + }); + }); + it('file.spec.87 should read file properly, readAsArrayBuffer', function (done) { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + } + runReaderTest('readAsArrayBuffer', true, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(arrayBufferEqualsString(evt.target.result, fileDataAsBinaryString)).toBe(true); + done(); + }); + }); + it('file.spec.88 should read sliced file: readAsText', function (done) { + runReaderTest('readAsText', false, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileDataAsBinaryString.slice(10, 40)); + done(); + }, 10, 40); + }); + it('file.spec.89 should read sliced file: slice past eof', function (done) { + runReaderTest('readAsText', false, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileData.slice(-5, 9999)); + done(); + }, -5, 9999); + }); + it('file.spec.90 should read sliced file: slice to eof', function (done) { + runReaderTest('readAsText', false, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileData.slice(-5)); + done(); + }, -5); + }); + it('file.spec.91 should read empty slice', function (done) { + runReaderTest('readAsText', false, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(''); + done(); + }, 0, 0); + }); + it('file.spec.92 should read sliced file properly, readAsDataURL', function (done) { + runReaderTest('readAsDataURL', true, done, null, function (evt, fileData, fileDataAsBinaryString) { + /* `readAsDataURL` function is supported, but the mediatype in Chrome depends on entry name extension, + mediatype in IE is always empty (which is the same as `text-plain` according the specification), + the mediatype in Firefox is always `application/octet-stream`. + For example, if the content is `abcdefg` then Firefox returns `data:application/octet-stream;base64,YWJjZGVmZw==`, + IE returns `data:;base64,YWJjZGVmZw==`, Chrome returns `data:<mediatype depending on extension of entry name>;base64,YWJjZGVmZw==`. */ + expect(evt.target.result).toBeDataUrl(); + + // The atob function it is completely ignored during mobilespec execution, besides the returned object: evt + // it is encoded and the atob function is aimed to decode a string. Even with btoa (encode) the function it gets stucked + // because of the Unicode characters that contains the fileData object. + // Issue reported at JIRA with all the details: CB-7095 + + // expect(evt.target.result.slice(23)).toBe(atob(fileDataAsBinaryString.slice(10, -3))); + + done(); + }, 10, -3); + }); + it('file.spec.93 should read sliced file properly, readAsBinaryString', function (done) { + if (isIE) { + /* `readAsBinaryString` function is not supported by IE and has not the stub. */ + pending(); + } + + runReaderTest('readAsBinaryString', true, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(evt.target.result).toBe(fileDataAsBinaryString.slice(-10, -5)); + done(); + }, -10, -5); + }); + it('file.spec.94 should read sliced file properly, readAsArrayBuffer', function (done) { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + } + runReaderTest('readAsArrayBuffer', true, done, null, function (evt, fileData, fileDataAsBinaryString) { + expect(arrayBufferEqualsString(evt.target.result, fileDataAsBinaryString.slice(0, -1))).toBe(true); + done(); + }, 0, -1); + }); + it('file.spec.94.5 should read large file in multiple chunks, readAsArrayBuffer', function (done) { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + } + + var largeText = ''; + for (var i = 0; i < 1000; i++) { + largeText += 'Test ' + i + '\n'; + } + + // Set the chunk size so that the read will take 5 chunks + FileReader.READ_CHUNK_SIZE = Math.floor(largeText.length / 4) + 1; // eslint-disable-line no-undef + + var chunkCount = 0; + var lastProgressValue = -1; + var progressFunc = function (evt) { + expect(evt.loaded).toBeDefined(); + expect(evt.total).toBeDefined(); + + expect(evt.total >= largeText.length).toBe(true); + expect(evt.total <= largeText.length + 5).toBe(true); + expect(evt.loaded > lastProgressValue).toBe(true); + expect(evt.loaded <= evt.total).toBe(true); + + lastProgressValue = evt.loaded; + chunkCount++; + }; + + runReaderTest( + 'readAsArrayBuffer', true, done, progressFunc, + function (evt, fileData, fileDataAsBinaryString) { + expect(arrayBufferEqualsString(evt.target.result, fileDataAsBinaryString.slice(0, -1))).toBe(true); + expect(lastProgressValue >= largeText.length).toBe(true); + expect(lastProgressValue <= largeText.length + 5).toBe(true); + if (!isChrome) { + // chrome downloads it in one chunk -.- + expect(chunkCount).toBe(5); + } + done(); + }, + 0, -1, largeText); + }); + it('file.spec.94.6 should read large file in multiple chunks, readAsDataURL', function (done) { + var largeText = ''; + for (var i = 0; i < 10; i++) { + largeText += 'Test ' + i + '\n'; + } + + // Set the chunk size so that the read will take 5 chunks + FileReader.READ_CHUNK_SIZE = Math.floor(largeText.length / 4) + 1; // eslint-disable-line no-undef + + var lastProgressValue = 0; + var progressFunc = function (evt) { + expect(evt.total).toBeDefined(); + expect(evt.total).toEqual(largeText.length); + + expect(evt.loaded).toBeDefined(); + expect(evt.loaded).toBeGreaterThan(lastProgressValue); + expect(evt.loaded).toBeLessThan(evt.total + 1); + + lastProgressValue = evt.loaded; + }; + + runReaderTest('readAsDataURL', false, done, progressFunc, + function (evt, fileData, fileDataAsBinaryString) { + expect(function () { + // Cut off data uri prefix + var base64Data = evt.target.result.substring(evt.target.result.indexOf(',') + 1); + expect(window.atob(base64Data)).toEqual(fileData); + }).not.toThrow(); + + expect(lastProgressValue).toEqual(largeText.length); + done(); + }, + undefined, undefined, largeText); + }); + }); + // Read method + describe('FileWriter', function () { + it('file.spec.95 should have correct methods', function (done) { + // retrieve a FileWriter object + var fileName = 'writer.methods'; + // FileWriter + root.getFile(fileName, { + create: true + }, function (fileEntry) { + fileEntry.createWriter(function (writer) { + expect(writer).toBeDefined(); + expect(typeof writer.write).toBe('function'); + expect(typeof writer.seek).toBe('function'); + expect(typeof writer.truncate).toBe('function'); + expect(typeof writer.abort).toBe('function'); + // cleanup + deleteFile(fileName, done); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + }); + it('file.spec.96 should be able to write and append to file, createWriter', function (done) { + var fileName = 'writer.append.createWriter'; // file content + var content = 'There is an exception to every rule.'; // for checkin file length + var exception = ' Except this one.'; + var length = content.length; + // create file, then write and append to it + createFile(fileName, function (fileEntry) { + // writes initial file content + fileEntry.createWriter(function (writer) { + // Verifiers declaration + function verifier (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // Append some more data + writer.onwriteend = secondVerifier; + length += exception.length; + writer.seek(writer.length); + writer.write(exception); + } + function secondVerifier (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onloadend = thirdVerifier; + reader.onerror = failed.bind(null, done, 'reader.onerror - Error reading file: ' + fileName); + fileEntry.file(function (f) { reader.readAsText(f); }); + } + function thirdVerifier (evt) { + expect(evt.target.result).toBe(content + exception); + // cleanup + deleteFile(fileName, done); + } + + // Write process + writer.onwriteend = verifier; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.97 should be able to write and append to file, File object', function (done) { + var fileName = 'writer.append.File'; // file content + var content = 'There is an exception to every rule.'; // for checkin file length + var exception = ' Except this one.'; + var length = content.length; + root.getFile(fileName, { + create: true + }, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifiers declaration + function verifier () { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // Append some more data + writer.onwriteend = secondVerifier; + length += exception.length; + writer.seek(writer.length); + writer.write(exception); + } + function secondVerifier () { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onloadend = thirdVerifier; + reader.onerror = failed.bind(null, done, 'reader.onerror - Error reading file: ' + fileName); + fileEntry.file(function (f) { reader.readAsText(f); }); + } + function thirdVerifier (evt) { + expect(evt.target.result).toBe(content + exception); + // cleanup + deleteFile(fileName, done); + } + + // Write process + writer.onwriteend = verifier; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'root.getFile - Error creating file: ' + fileName)); + }); + it('file.spec.98 should be able to seek to the middle of the file and write more data than file.length', function (done) { + var fileName = 'writer.seek.write'; // file content + var content = 'This is our sentence.'; // for checking file length + var exception = 'newer sentence.'; + var length = content.length; + // create file, then write and append to it + createFile(fileName, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifiers declaration + function verifier (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // Append some more data + writer.onwriteend = secondVerifier; + length = 12 + exception.length; + writer.seek(12); + writer.write(exception); + } + function secondVerifier (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onloadend = thirdVerifier; + reader.onerror = failed.bind(null, done, 'reader.onerror - Error reading file: ' + fileName); + fileEntry.file(function (f) { reader.readAsText(f); }); + } + function thirdVerifier (evt) { + expect(evt.target.result).toBe(content.substr(0, 12) + exception); + // cleanup + deleteFile(fileName, done); + } + + // Write process + writer.onwriteend = verifier; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.99 should be able to seek to the middle of the file and write less data than file.length', function (done) { + if (isBrowser) { + /* Browser (re)writes as follows: "This is our sentence." -> "This is new.sentence.", + i.e. the length is not being changed from content.length and writer length will be equal 21 */ + pending(); + } + + var fileName = 'writer.seek.write2'; // file content + var content = 'This is our sentence.'; // for checking file length + var exception = 'new.'; + var length = content.length; + // create file, then write and append to it + createFile(fileName, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifiers declaration + function verifier (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // Append some more data + writer.onwriteend = secondVerifier; + length = 8 + exception.length; + writer.seek(8); + writer.write(exception); + } + function secondVerifier (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onloadend = thirdVerifier; + reader.onerror = failed.bind(null, done, 'reader.onerror - Error reading file: ' + fileName); + fileEntry.file(function (f) { reader.readAsText(f); }); + } + function thirdVerifier (evt) { + expect(evt.target.result).toBe(content.substr(0, 8) + exception); + // cleanup + deleteFile(fileName, done); + } + + // Write process + writer.onwriteend = verifier; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.100 should be able to write XML data', function (done) { + var fileName = 'writer.xml'; // file content + var content = '<?xml version="1.0" encoding="UTF-8"?>\n<test prop="ack">\nData\n</test>\n'; // for testing file length + var length = content.length; + // creates file, then write XML data + createFile(fileName, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifier content + var verifier = function (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // cleanup + deleteFile(fileName, done); + }; + // Write process + writer.onwriteend = verifier; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.101 should be able to write JSON data', function (done) { + var fileName = 'writer.json'; // file content + var content = '{ "name": "Guy Incognito", "email": "here@there.com" }'; // for testing file length + var length = content.length; + // creates file, then write JSON content + createFile(fileName, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifier declaration + var verifier = function (evt) { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // cleanup + deleteFile(fileName, done); + }; + // Write process + writer.onwriteend = verifier; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.102 should be able to seek', function (done) { + var fileName = 'writer.seek'; // file content + var content = 'There is an exception to every rule. Except this one.'; // for testing file length + var length = content.length; + // creates file, then write JSON content + createFile(fileName, function (fileEntry) { + // writes file content and tests writer.seek + fileEntry.createWriter(function (writer) { + // Verifier declaration + var verifier = function () { + expect(writer.position).toBe(length); + writer.seek(-5); + expect(writer.position).toBe(length - 5); + writer.seek(length + 100); + expect(writer.position).toBe(length); + writer.seek(10); + expect(writer.position).toBe(10); + // cleanup + deleteFile(fileName, done); + }; + // Write process + writer.onwriteend = verifier; + writer.seek(-100); + expect(writer.position).toBe(0); + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.103 should be able to truncate', function (done) { + if (isIndexedDBShim) { + /* `abort` and `truncate` functions are not supported (Firefox, IE) */ + pending(); + } + + var fileName = 'writer.truncate'; + var content = 'There is an exception to every rule. Except this one.'; + // creates file, writes to it, then truncates it + createFile(fileName, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifier declaration + var verifier = function () { + expect(writer.length).toBe(36); + expect(writer.position).toBe(36); + // cleanup + deleteFile(fileName, done); + }; + // Write process + writer.onwriteend = function () { + // Truncate process after write + writer.onwriteend = verifier; + writer.truncate(36); + }; + writer.write(content); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.104 should be able to write binary data from an ArrayBuffer', function (done) { + // Skip test if ArrayBuffers are not supported (e.g.: Android 2.3). + if (typeof window.ArrayBuffer === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + return; + } + var fileName = 'bufferwriter.bin'; // file content + var data = new ArrayBuffer(32); + var dataView = new Int8Array(data); // for verifying file length + var length = 32; + for (var i = 0; i < dataView.length; i++) { + dataView[i] = i; + } + // creates file, then write content + createFile(fileName, function (fileEntry) { + // writes file content + fileEntry.createWriter(function (writer) { + // Verifier declaration + var verifier = function () { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // cleanup + deleteFile(fileName, done); + }; + // Write process + writer.onwriteend = verifier; + writer.write(data); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.105 should be able to write binary data from a Blob', function (done) { + // Skip test if Blobs are not supported (e.g.: Android 2.3). + if ((typeof window.Blob === 'undefined' && typeof window.WebKitBlobBuilder === 'undefined') || typeof window.ArrayBuffer === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + return; + } + var fileName = 'blobwriter.bin'; // file content + var data = new ArrayBuffer(32); + var dataView = new Int8Array(data); + var blob; // for verifying file length + var length = 32; + for (var i = 0; i < dataView.length; i++) { + dataView[i] = i; + } + try { + // Mobile Safari: Use Blob constructor + blob = new Blob([data], { // eslint-disable-line no-undef + 'type': 'application/octet-stream' + }); + } catch (e) { + if (window.WebKitBlobBuilder) { + // Android Browser: Use deprecated BlobBuilder + var builder = new WebKitBlobBuilder(); + builder.append(data); + blob = builder.getBlob('application/octet-stream'); + } else { + // We have no way defined to create a Blob, so fail + fail(); + } + } + if (typeof blob !== 'undefined') { + // creates file, then write content + createFile(fileName, function (fileEntry) { + fileEntry.createWriter(function (writer) { + // Verifier declaration + var verifier = function () { + expect(writer.length).toBe(length); + expect(writer.position).toBe(length); + // cleanup + deleteFile(fileName, done); + }; + // Write process + writer.onwriteend = verifier; + writer.write(blob); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + } + }); + it('file.spec.106 should be able to write a File to a FileWriter', function (done) { + var dummyFileName = 'dummy.txt'; + var outputFileName = 'verify.txt'; + var dummyFileText = 'This text should be written to two files'; + var verifier = function (outputFileWriter) { + expect(outputFileWriter.length).toBe(dummyFileText.length); + expect(outputFileWriter.position).toBe(dummyFileText.length); + deleteFile(outputFileName, done); + }; + var writeFile = function (fileName, fileData, win) { + var theWriter; + var write_file = function (fileEntry) { + // writes file content to new file + fileEntry.createWriter(function (writer) { + theWriter = writer; + writer.onwriteend = function (ev) { + if (typeof fileData.length !== 'undefined') { + expect(theWriter.length).toBe(fileData.length); + expect(theWriter.position).toBe(fileData.length); + } + win(theWriter); + }; + writer.onerror = failed.bind(null, done, 'writer.onerror - Error writing content on file: ' + fileName); + writer.write(fileData); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }; + createFile(fileName, write_file, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }; + var openFile = function (fileName, callback) { + root.getFile(fileName, { + create: false + }, function (fileEntry) { + fileEntry.file(callback, failed.bind(null, done, 'fileEntry.file - Error reading file using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'root.getFile - Error getting file: ' + fileName)); + }; + writeFile(dummyFileName, dummyFileText, function (dummyFileWriter) { + openFile(dummyFileName, function (file) { + writeFile(outputFileName, file, verifier); + }); + }); + }); + it('file.spec.107 should be able to write a sliced File to a FileWriter', function (done) { + var dummyFileName = 'dummy2.txt'; + var outputFileName = 'verify2.txt'; + var dummyFileText = 'This text should be written to two files'; + var verifier = function (outputFileWriter) { + expect(outputFileWriter.length).toBe(10); + expect(outputFileWriter.position).toBe(10); + deleteFile(outputFileName, done); + }; + var writeFile = function (fileName, fileData, win) { + var theWriter; + var write_file = function (fileEntry) { + // writes file content to new file + fileEntry.createWriter(function (writer) { + theWriter = writer; + writer.onwriteend = function (ev) { + if (typeof fileData.length !== 'undefined') { + expect(theWriter.length).toBe(fileData.length); + expect(theWriter.position).toBe(fileData.length); + } + win(theWriter); + }; + writer.onerror = failed.bind(null, done, 'writer.onerror - Error writing content on file: ' + fileName); + writer.write(fileData); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }; + createFile(fileName, write_file, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }; + var openFile = function (fileName, callback) { + root.getFile(fileName, { + create: false + }, function (fileEntry) { + fileEntry.file(callback, failed.bind(null, done, 'fileEntry.file - Error reading file using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'root.getFile - Error getting file: ' + fileName)); + }; + writeFile(dummyFileName, dummyFileText, function (dummyFileWriter) { + openFile(dummyFileName, function (file) { + writeFile(outputFileName, file.slice(10, 20), verifier); + }); + }); + }); + it('file.spec.108 should be able to write binary data from a File', function (done) { + // Skip test if Blobs are not supported (e.g.: Android 2.3). + if (typeof window.Blob === 'undefined' && typeof window.WebKitBlobBuilder === 'undefined') { + expect(true).toFailWithMessage('Platform does not supported this feature'); + done(); + } + var dummyFileName = 'blobwriter.bin'; + var outputFileName = 'verify.bin'; // file content + var data = new ArrayBuffer(32); + var dataView = new Int8Array(data); + var blob; // for verifying file length + var length = 32; + var verifier = function (outputFileWriter) { + expect(outputFileWriter.length).toBe(length); + expect(outputFileWriter.position).toBe(length); + // cleanup + deleteFile(outputFileName); + done(); + }; + var writeFile = function (fileName, fileData, win) { + var theWriter; + var write_file = function (fileEntry) { + // writes file content to new file + fileEntry.createWriter(function (writer) { + theWriter = writer; + writer.onwriteend = function (ev) { + if (typeof fileData.length !== 'undefined') { + expect(theWriter.length).toBe(fileData.length); + expect(theWriter.position).toBe(fileData.length); + } + win(theWriter); + }; + writer.onerror = failed.bind(null, done, 'writer.onerror - Error writing content on file: ' + fileName); + writer.write(fileData); + }, failed.bind(null, done, 'fileEntry.createWriter - Error creating writer using fileEntry: ' + fileEntry.name)); + }; + createFile(fileName, write_file, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }; + var openFile = function (fileName, callback) { + root.getFile(fileName, { + create: false + }, function (fileEntry) { + fileEntry.file(callback, failed.bind(null, done, 'fileEntry.file - Error reading file using fileEntry: ' + fileEntry.name)); + }, failed.bind(null, done, 'root.getFile - Error getting file: ' + fileName)); + }; + for (var i = 0; i < dataView.length; i++) { + dataView[i] = i; + } + try { + // Mobile Safari: Use Blob constructor + blob = new Blob([data], { // eslint-disable-line no-undef + 'type': 'application/octet-stream' + }); + } catch (e) { + if (window.WebKitBlobBuilder) { + // Android Browser: Use deprecated BlobBuilder + var builder = new WebKitBlobBuilder(); + builder.append(data); + blob = builder.getBlob('application/octet-stream'); + } else { + // We have no way defined to create a Blob, so fail + fail(); + } + } + if (typeof blob !== 'undefined') { + // creates file, then write content + writeFile(dummyFileName, blob, function (dummyFileWriter) { + openFile(dummyFileName, function (file) { + writeFile(outputFileName, file, verifier); + }); + }); + } + }); + }); + // FileWritter + describe('Backwards compatibility', function () { + /* These specs exist to test that the File plugin can still recognize file:/// + * URLs, and can resolve them to FileEntry and DirectoryEntry objects. + * They rely on an undocumented interface to File which provides absolute file + * paths, which are not used internally anymore. + * If that interface is not present, then these tests will silently succeed. + */ + it('file.spec.109 should be able to resolve a file:/// URL', function (done) { + var localFilename = 'file.txt'; + var originalEntry; + root.getFile(localFilename, { + create: true + }, function (entry) { + originalEntry = entry; + /* This is an undocumented interface to File which exists only for testing + * backwards compatibilty. By obtaining the raw filesystem path of the download + * location, we can pass that to ft.download() to make sure that previously-stored + * paths are still valid. + */ + cordova.exec(function (localPath) { // eslint-disable-line no-undef + window.resolveLocalFileSystemURL('file://' + encodeURI(localPath), function (fileEntry) { + expect(fileEntry.toURL()).toEqual(originalEntry.toURL()); + // cleanup + deleteFile(localFilename); + done(); + }, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving URI: file://' + encodeURI(localPath))); + }, done, 'File', '_getLocalFilesystemPath', [entry.toURL()]); + }, failed.bind(null, done, 'root.getFile - Error creating file: ' + localFilename)); + }); + }); + // Backwards Compatibility + describe('Parent References', function () { + /* These specs verify that paths with parent references i("..") in them + * work correctly, and do not cause the application to crash. + */ + it('file.spec.110 should not throw exception resolving parent refefences', function (done) { + /* This is a direct copy of file.spec.9, with the filename changed, * as reported in CB-5721. + */ + var fileName = 'resolve.file.uri'; + var dirName = 'resolve.dir.uri'; + // create a new file entry + createDirectory(dirName, function () { + createFile(dirName + '/../' + fileName, function (entry) { + // lookup file system entry + window.resolveLocalFileSystemURL(entry.toURL(), function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.name).toCanonicallyMatch(fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'window.resolveLocalFileSystemURL - Error resolving URI: ' + entry.toURL())); + }, failed.bind(null, done, 'createFile - Error creating file: ../' + fileName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory: ' + dirName)); + }); + it('file.spec.111 should not traverse above above the root directory', function (done) { + var fileName = 'traverse.file.uri'; + // create a new file entry + createFile(fileName, function (entry) { + // lookup file system entry + root.getFile('../' + fileName, { + create: false + }, function (fileEntry) { + // Note: we expect this to still resolve, as the correct behaviour is to ignore the ../, not to fail out. + expect(fileEntry).toBeDefined(); + expect(fileEntry.name).toBe(fileName); + expect(fileEntry.fullPath).toCanonicallyMatch(root.fullPath + '/' + fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'root.getFile - Error getting file: ../' + fileName)); + }, failed.bind(null, done, 'createFile - Error creating file: ../' + fileName)); + }); + it('file.spec.112 should traverse above above the current directory', function (done) { + var fileName = 'traverse2.file.uri'; + var dirName = 'traverse2.subdir'; + // create a new directory and a file entry + createFile(fileName, function () { + createDirectory(dirName, function (entry) { + // lookup file system entry + entry.getFile('../' + fileName, { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.name).toBe(fileName); + expect(fileEntry.fullPath).toCanonicallyMatch('/' + fileName); + // cleanup + deleteEntry(fileName, function () { + deleteEntry(dirName, done); + }); + }, failed.bind(null, done, 'entry.getFile - Error getting file: ' + fileName + ' recently created above: ' + dirName)); + }, failed.bind(null, done, 'createDirectory - Error creating directory: ' + dirName)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.113 getFile: get Entry should error for missing file above root directory', function (done) { + var fileName = '../missing.file'; + // create:false, exclusive:false, file does not exist + root.getFile(fileName, { + create: false + }, succeed.bind(null, done, 'root.getFile - Unexpected success callback, it should not locate nonexistent file: ' + fileName), function (error) { + expect(error).toBeDefined(); + if (isChrome) { + expect(error).toBeFileError(FileError.SYNTAX_ERR); // eslint-disable-line no-undef + } else { + expect(error).toBeFileError(FileError.NOT_FOUND_ERR); // eslint-disable-line no-undef + } + done(); + }); + }); + }); + // Parent References + describe('toNativeURL interface', function () { + /* These specs verify that FileEntries have a toNativeURL method + * which appears to be sane. + */ + var pathExpect = cordova.platformId === 'windowsphone' ? '//nativ' : 'file://'; // eslint-disable-line no-undef + if (isChrome) { + pathExpect = 'filesystem:http://'; + } + it('file.spec.114 fileEntry should have a toNativeURL method', function (done) { + var fileName = 'native.file.uri'; + if (isWindows) { + var rootPath = root.fullPath; + pathExpect = rootPath.substr(0, rootPath.indexOf(':')); + } + // create a new file entry + createFile(fileName, function (entry) { + expect(entry.toNativeURL).toBeDefined(); + expect(entry.name).toCanonicallyMatch(fileName); + expect(typeof entry.toNativeURL).toBe('function'); + var nativeURL = entry.toNativeURL(); + expect(typeof nativeURL).toBe('string'); + expect(nativeURL.substring(0, pathExpect.length)).toEqual(pathExpect); + expect(nativeURL.substring(nativeURL.length - fileName.length)).toEqual(fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.115 DirectoryReader should return entries with toNativeURL method', function (done) { + var dirName = 'nativeEntries.dir'; + var fileName = 'nativeEntries.file'; + var directory; + var checkEntries = function (entries) { + expect(entries).toBeDefined(); + expect(entries instanceof Array).toBe(true); + expect(entries.length).toBe(1); + expect(entries[0].toNativeURL).toBeDefined(); + expect(typeof entries[0].toNativeURL).toBe('function'); + var nativeURL = entries[0].toNativeURL(); + expect(typeof nativeURL).toBe('string'); + expect(nativeURL.substring(0, pathExpect.length)).toEqual(pathExpect); + expect(nativeURL.substring(nativeURL.length - fileName.length)).toEqual(fileName); + // cleanup + directory.removeRecursively(function () {}, null); + done(); + }; + // create a new file entry + root.getDirectory(dirName, { + create: true + }, function (dir) { + directory = dir; + directory.getFile(fileName, { + create: true + }, function (fileEntry) { + var reader = directory.createReader(); + reader.readEntries(checkEntries, failed.bind(null, done, 'reader.readEntries - Error reading entries from directory: ' + dirName)); + }, failed.bind(null, done, 'directory.getFile - Error creating file: ' + fileName)); + }, failed.bind(null, done, 'root.getDirectory - Error creating directory: ' + dirName)); + }); + it('file.spec.116 resolveLocalFileSystemURL should return entries with toNativeURL method', function (done) { + var fileName = 'native.resolve.uri'; + // create a new file entry + createFile(fileName, function (entry) { + resolveLocalFileSystemURL(entry.toURL(), function (entry) { // eslint-disable-line no-undef + expect(entry.toNativeURL).toBeDefined(); + expect(entry.name).toCanonicallyMatch(fileName); + expect(typeof entry.toNativeURL).toBe('function'); + var nativeURL = entry.toNativeURL(); + expect(typeof nativeURL).toBe('string'); + expect(nativeURL.substring(0, pathExpect.length)).toEqual(pathExpect); + expect(nativeURL.substring(nativeURL.length - fileName.length)).toEqual(fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'resolveLocalFileSystemURL - Error resolving file URL: ' + entry.toURL())); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + }); + // toNativeURL interface + describe('resolveLocalFileSystemURL on file://', function () { + /* These specs verify that window.resolveLocalFileSystemURL works correctly on file:// URLs + */ + it('file.spec.117 should not resolve native URLs outside of FS roots', function (done) { + // lookup file system entry + window.resolveLocalFileSystemURL('file:///this.is.an.invalid.url', succeed.bind(null, done, 'window.resolveLocalFileSystemURL - Unexpected success callback, it should not resolve invalid URL: file:///this.is.an.invalid.url'), function (error) { + expect(error).toBeDefined(); + done(); + }); + }); + it('file.spec.118 should not resolve native URLs outside of FS roots', function (done) { + // lookup file system entry + window.resolveLocalFileSystemURL('file://localhost/this.is.an.invalid.url', succeed.bind(null, done, 'window.resolveLocalFileSystemURL - Unexpected success callback, it should not resolve invalid URL: file://localhost/this.is.an.invalid.url'), function (error) { + expect(error).toBeDefined(); + done(); + }); + }); + it('file.spec.119 should not resolve invalid native URLs', function (done) { + // lookup file system entry + window.resolveLocalFileSystemURL('file://localhost', succeed.bind(null, done, 'window.resolveLocalFileSystemURL - Unexpected success callback, it should not resolve invalid URL: file://localhost'), function (error) { + expect(error).toBeDefined(); + done(); + }); + }); + it('file.spec.120 should not resolve invalid native URLs with query strings', function (done) { + // lookup file system entry + window.resolveLocalFileSystemURL('file://localhost?test/test', succeed.bind(null, done, 'window.resolveLocalFileSystemURL - Unexpected success callback, it should not resolve invalid URL: file://localhost?test/test'), function (error) { + expect(error).toBeDefined(); + done(); + }); + }); + it('file.spec.121 should resolve native URLs returned by API', function (done) { + var fileName = 'native.resolve.uri1'; + // create a new file entry + createFile(fileName, function (entry) { + /* eslint-disable no-undef */ + resolveLocalFileSystemURL(entry.toNativeURL(), function (fileEntry) { + expect(fileEntry.fullPath).toCanonicallyMatch(root.fullPath + '/' + fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'resolveLocalFileSystemURL - Error resolving file URL: ' + entry.toNativeURL())); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.122 should resolve native URLs returned by API with localhost', function (done) { + var fileName = 'native.resolve.uri2'; + // create a new file entry + createFile(fileName, function (entry) { + var url = entry.toNativeURL(); + url = url.replace('///', '//localhost/'); + resolveLocalFileSystemURL(url, function (fileEntry) { + expect(fileEntry.fullPath).toCanonicallyMatch(root.fullPath + '/' + fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'resolveLocalFileSystemURL - Error resolving file URL: ' + url)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.123 should resolve native URLs returned by API with query string', function (done) { + var fileName = 'native.resolve.uri3'; + // create a new file entry + createFile(fileName, function (entry) { + var url = entry.toNativeURL(); + url = url + '?test/test'; + resolveLocalFileSystemURL(url, function (fileEntry) { + expect(fileEntry.fullPath).toCanonicallyMatch(root.fullPath + '/' + fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'resolveLocalFileSystemURL - Error resolving file URL: ' + url)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + it('file.spec.124 should resolve native URLs returned by API with localhost and query string', function (done) { + var fileName = 'native.resolve.uri4'; + // create a new file entry + createFile(fileName, function (entry) { + var url = entry.toNativeURL(); + url = url.replace('///', '//localhost/') + '?test/test'; + resolveLocalFileSystemURL(url, function (fileEntry) { + /* eslint-enable no-undef */ + expect(fileEntry.fullPath).toCanonicallyMatch(root.fullPath + '/' + fileName); + // cleanup + deleteEntry(fileName, done); + }, failed.bind(null, done, 'resolveLocalFileSystemURL - Error resolving file URL: ' + url)); + }, failed.bind(null, done, 'createFile - Error creating file: ' + fileName)); + }); + }); + // resolveLocalFileSystemURL on file:// + describe('cross-file-system copy and move', function () { + /* These specs verify that Entry.copyTo and Entry.moveTo work correctly + * when crossing filesystem boundaries. + */ + it('file.spec.125 copyTo: temporary -> persistent', function (done) { + var file1 = 'entry.copy.file1a'; + var file2 = 'entry.copy.file2a'; + var sourceEntry; + var fullPath = joinURL(root.fullPath, file2); + var validateFile = function (entry) { + // a bit redundant since copy returned this entry already + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(file2); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(entry.filesystem).toBeDefined(); + if (isChrome) { + expect(entry.filesystem.name).toContain('Persistent'); + } else { + expect(entry.filesystem.name).toEqual('persistent'); + } + // cleanup + deleteEntry(entry.name); + deleteEntry(sourceEntry.name, done); + }; + var createSourceAndTransfer = function () { + temp_root.getFile(file1, { + create: true + }, function (entry) { + expect(entry.filesystem).toBeDefined(); + if (isChrome) { + expect(entry.filesystem.name).toContain('Temporary'); + } else { + expect(entry.filesystem.name).toEqual('temporary'); + } + sourceEntry = entry; + // Save for later cleanup + entry.copyTo(persistent_root, file2, validateFile, failed.bind(null, done, 'entry.copyTo - Error copying file: ' + file1 + ' to PERSISTENT root as: ' + file2)); + }, failed.bind(null, done, 'temp_root.getFile - Error creating file: ' + file1 + 'at TEMPORAL root')); + }; + // Delete any existing file to start things off + persistent_root.getFile(file2, {}, function (entry) { + entry.remove(createSourceAndTransfer, failed.bind(null, done, 'entry.remove - Error removing file: ' + file2)); + }, createSourceAndTransfer); + }); + it('file.spec.126 copyTo: persistent -> temporary', function (done) { + var file1 = 'entry.copy.file1b'; + var file2 = 'entry.copy.file2b'; + var sourceEntry; + var fullPath = joinURL(temp_root.fullPath, file2); + var validateFile = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(file2); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + if (isChrome) { + expect(entry.filesystem.name).toContain('Temporary'); + } else { + expect(entry.filesystem.name).toEqual('temporary'); + } + // cleanup + deleteEntry(entry.name); + deleteEntry(sourceEntry.name, done); + }; + var createSourceAndTransfer = function () { + persistent_root.getFile(file1, { + create: true + }, function (entry) { + expect(entry).toBeDefined(); + expect(entry.filesystem).toBeDefined(); + if (isChrome) { + expect(entry.filesystem.name).toContain('Persistent'); + } else { + expect(entry.filesystem.name).toEqual('persistent'); + } + sourceEntry = entry; + // Save for later cleanup + entry.copyTo(temp_root, file2, validateFile, failed.bind(null, done, 'entry.copyTo - Error copying file: ' + file1 + ' to TEMPORAL root as: ' + file2)); + }, failed.bind(null, done, 'persistent_root.getFile - Error creating file: ' + file1 + 'at PERSISTENT root')); + }; + // Delete any existing file to start things off + temp_root.getFile(file2, {}, function (entry) { + entry.remove(createSourceAndTransfer, failed.bind(null, done, 'entry.remove - Error removing file: ' + file2)); + }, createSourceAndTransfer); + }); + it('file.spec.127 moveTo: temporary -> persistent', function (done) { + var file1 = 'entry.copy.file1a'; + var file2 = 'entry.copy.file2a'; + var sourceEntry; + var fullPath = joinURL(root.fullPath, file2); + var validateFile = function (entry) { + // a bit redundant since copy returned this entry already + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(file2); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(entry.filesystem).toBeDefined(); + if (isChrome) { + expect(entry.filesystem.name).toContain('Persistent'); + } else { + expect(entry.filesystem.name).toEqual('persistent'); + } + // cleanup + deleteEntry(entry.name); + deleteEntry(sourceEntry.name, done); + }; + var createSourceAndTransfer = function () { + temp_root.getFile(file1, { + create: true + }, function (entry) { + expect(entry.filesystem).toBeDefined(); + if (isChrome) { + expect(entry.filesystem.name).toContain('Temporary'); + } else { + expect(entry.filesystem.name).toEqual('temporary'); + } + sourceEntry = entry; + // Save for later cleanup + entry.moveTo(persistent_root, file2, validateFile, failed.bind(null, done, 'entry.moveTo - Error moving file: ' + file1 + ' to PERSISTENT root as: ' + file2)); + }, failed.bind(null, done, 'temp_root.getFile - Error creating file: ' + file1 + 'at TEMPORAL root')); + }; + // Delete any existing file to start things off + persistent_root.getFile(file2, {}, function (entry) { + entry.remove(createSourceAndTransfer, failed.bind(null, done, 'entry.remove - Error removing file: ' + file2)); + }, createSourceAndTransfer); + }); + it('file.spec.128 moveTo: persistent -> temporary', function (done) { + var file1 = 'entry.copy.file1b'; + var file2 = 'entry.copy.file2b'; + var sourceEntry; + var fullPath = joinURL(temp_root.fullPath, file2); + var validateFile = function (entry) { + expect(entry).toBeDefined(); + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(file2); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + if (isChrome) { + expect(entry.filesystem.name).toContain('Temporary'); + } else { + expect(entry.filesystem.name).toEqual('temporary'); + } + // cleanup + deleteEntry(entry.name); + deleteEntry(sourceEntry.name, done); + }; + var createSourceAndTransfer = function () { + persistent_root.getFile(file1, { + create: true + }, function (entry) { + expect(entry).toBeDefined(); + expect(entry.filesystem).toBeDefined(); + if (isChrome) { + expect(entry.filesystem.name).toContain('Persistent'); + } else { + expect(entry.filesystem.name).toEqual('persistent'); + } + sourceEntry = entry; + // Save for later cleanup + entry.moveTo(temp_root, file2, validateFile, failed.bind(null, done, 'entry.moveTo - Error moving file: ' + file1 + ' to TEMPORAL root as: ' + file2)); + }, failed.bind(null, done, 'persistent_root.getFile - Error creating file: ' + file1 + 'at PERSISTENT root')); + }; + // Delete any existing file to start things off + temp_root.getFile(file2, {}, function (entry) { + entry.remove(createSourceAndTransfer, failed.bind(null, done, 'entry.remove - Error removing file: ' + file2)); + }, createSourceAndTransfer); + }); + it('file.spec.129 cordova.file.*Directory are set', function () { + var expectedPaths = ['applicationDirectory', 'applicationStorageDirectory', 'dataDirectory', 'cacheDirectory']; + /* eslint-disable no-undef */ + if (cordova.platformId === 'android' || cordova.platformId === 'amazon-fireos') { + if (cordova.file.externalApplicationStorageDirectory !== null) { + // https://issues.apache.org/jira/browse/CB-10411 + // If external storage can't be mounted, the cordova.file.external* properties are null. + expectedPaths.push('externalApplicationStorageDirectory', 'externalRootDirectory', 'externalCacheDirectory', 'externalDataDirectory'); + } + } else if (cordova.platformId === 'blackberry10') { + expectedPaths.push('externalRootDirectory', 'sharedDirectory'); + } else if (cordova.platformId === 'ios') { + expectedPaths.push('syncedDataDirectory', 'documentsDirectory', 'tempDirectory'); + } else if (cordova.platformId === 'osx') { + expectedPaths.push('documentsDirectory', 'tempDirectory', 'rootDirectory'); + } else { + console.log('Skipping test due on unsupported platform.'); + return; + } + for (var i = 0; i < expectedPaths.length; ++i) { + expect(typeof cordova.file[expectedPaths[i]]).toBe('string'); + expect(cordova.file[expectedPaths[i]]).toMatch(/\/$/, 'Path should end with a slash'); + } + }); + }); + describe('resolveLocalFileSystemURL on cdvfile://', function () { + it('file.spec.147 should be able to resolve cdvfile applicationDirectory fs root', function (done) { + var cdvfileApplicationDirectoryFsRootName; + if (cordova.platformId === 'android') { + cdvfileApplicationDirectoryFsRootName = 'assets'; + } else if (cordova.platformId === 'ios') { + cdvfileApplicationDirectoryFsRootName = 'bundle'; + } else { + pending(); + } + + resolveLocalFileSystemURL('cdvfile://localhost/' + cdvfileApplicationDirectoryFsRootName + '/', function (applicationDirectoryRoot) { + expect(applicationDirectoryRoot.isFile).toBe(false); + expect(applicationDirectoryRoot.isDirectory).toBe(true); + expect(applicationDirectoryRoot.name).toCanonicallyMatch(''); + expect(applicationDirectoryRoot.fullPath).toCanonicallyMatch('/'); + expect(applicationDirectoryRoot.filesystem.name).toEqual(cdvfileApplicationDirectoryFsRootName); + + // Requires HelloCordova www assets, <allow-navigation href="cdvfile:*" /> in config.xml or + // cdvfile: in CSP and <access origin="cdvfile://*" /> in config.xml + resolveLocalFileSystemURL('cdvfile://localhost/' + cdvfileApplicationDirectoryFsRootName + '/www/img/logo.png', function (entry) { + /* eslint-enable no-undef */ + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch('logo.png'); + expect(entry.fullPath).toCanonicallyMatch('/www/img/logo.png'); + expect(entry.filesystem.name).toEqual(cdvfileApplicationDirectoryFsRootName); + + var img = new Image(); // eslint-disable-line no-undef + img.onerror = function (err) { + expect(err).not.toBeDefined(); + done(); + }; + img.onload = function () { + done(); + }; + img.src = entry.toInternalURL(); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for cdvfile applicationDirectory')); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for cdvfile applicationDirectory')); + }); + }); + // cross-file-system copy and move + describe('IndexedDB-based impl', function () { + it('file.spec.131 Nested file or nested directory should be removed when removing a parent directory', function (done) { + var parentDirName = 'deletedDir131'; + var nestedDirName = 'nestedDir131'; + var nestedFileName = 'nestedFile131.txt'; + + createDirectory(parentDirName, function (parent) { + parent.getDirectory(nestedDirName, { create: true }, function () { + parent.getFile(nestedFileName, { create: true }, function () { + parent.removeRecursively(function () { + root.getDirectory(parentDirName, { create: false }, failed.bind(this, done, 'root.getDirectory - unexpected success callback : ' + parentDirName), function () { + parent.getFile(nestedFileName, { create: false }, failed.bind(this, done, 'getFile - unexpected success callback : ' + nestedFileName), function () { + parent.getDirectory(nestedDirName, { create: false }, failed.bind(this, done, 'getDirectory - unexpected success callback : ' + nestedDirName), done); + }); + }); + }, failed.bind(this, done, 'removeRecursively - Error removing directory : ' + parentDirName)); + }, failed.bind(this, done, 'getFile - Error creating file : ' + nestedFileName)); + }, failed.bind(this, done, 'getDirectory - Error creating directory : ' + nestedDirName)); + }, failed.bind(this, done, 'root.getDirectory - Error creating directory : ' + parentDirName)); + }); + it('file.spec.132 Entry should be created succesfully when using relative paths if its parent directory exists', function (done) { + /* Directory entries have to be created successively. + For example, the call `fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback)` + will fail if dir1 did not exist. */ + var parentName = 'parentName132'; + var nestedName = 'nestedName132'; + var path = parentName + '/' + nestedName; + + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(nestedName); + expect(directory.fullPath).toCanonicallyMatch('/' + path + '/'); + deleteEntry(directory.name); + deleteEntry(parentName, done); + }; + + createDirectory(parentName, function () { + root.getDirectory(parentName + '/' + nestedName, {create: true}, win, + failed.bind(this, done, 'root.getDirectory - Error getting directory : ' + path)); + }, failed.bind(this, done, 'root.getDirectory - Error getting directory : ' + parentName)); + }); + it('file.spec.133 A file being removed should not affect another file with name being a prefix of the removed file name.', function (done) { + + // Names include special symbols so that we check the IndexedDB range used + var deletedFileName = 'deletedFile.0'; + var secondFileName = 'deletedFile.0.1'; + + var win = function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + expect(fileEntry.isDirectory).toBe(false); + expect(fileEntry.name).toCanonicallyMatch(secondFileName); + deleteEntry(fileEntry.name, done); + }; + + createFile(deletedFileName, function (deletedFile) { + createFile(secondFileName, function () { + deletedFile.remove(function () { + root.getFile(deletedFileName, {create: false}, failed.bind(this, done, 'getFile - unexpected success callback getting deleted file : ' + deletedFileName), function () { + root.getFile(secondFileName, {create: false}, win, failed.bind(this, done, 'getFile - Error getting file after deleting deletedFile : ' + secondFileName)); + }); + }, failed.bind(this, done, 'remove - Error removing file : ' + deletedFileName)); + }, failed.bind(this, done, 'getFile - Error creating file : ' + secondFileName)); + }, failed.bind(this, done, 'getFile - Error creating file : ' + deletedFileName)); + }); + it('file.spec.134 A directory being removed should not affect another directory with name being a prefix of the removed directory name.', function (done) { + + // Names include special symbols so that we check the IndexedDB range used + var deletedDirName = 'deletedDir.0'; + var secondDirName = 'deletedDir.0.1'; + + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(secondDirName); + deleteEntry(directory.name, done); + }; + + createDirectory(deletedDirName, function (deletedDir) { + createDirectory(secondDirName, function () { + deletedDir.remove(function () { + root.getDirectory(deletedDirName, {create: false}, failed.bind(this, done, 'getDirectory - unexpected success callback getting deleted directory : ' + deletedDirName), function () { + root.getDirectory(secondDirName, {create: false}, win, failed.bind(this, done, 'getDirectory - Error getting directory after deleting deletedDirectory : ' + secondDirName)); + }); + }, failed.bind(this, done, 'remove - Error removing directory : ' + deletedDirName)); + }, failed.bind(this, done, 'root.getDirectory - Error creating directory : ' + secondDirName)); + }, failed.bind(this, done, 'root.getDirectory - Error creating directory : ' + deletedDirName)); + }); + it('file.spec.135 Deletion of a child directory should not affect the parent directory.', function (done) { + + var parentName = 'parentName135'; + var childName = 'childName135'; + + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(parentName); + deleteEntry(directory.name, done); + }; + + createDirectory(parentName, function (parent) { + parent.getDirectory(childName, {create: true}, function (child) { + child.removeRecursively(function () { + root.getDirectory(parentName, {create: false}, win, failed.bind(this, done, 'root.getDirectory - Error getting parent directory : ' + parentName)); + }, + failed.bind(this, done, 'getDirectory - Error removing directory : ' + childName)); + }, failed.bind(this, done, 'getDirectory - Error creating directory : ' + childName)); + }, failed.bind(this, done, 'root.getDirectory - Error creating directory : ' + parentName)); + }); + it('file.spec.136 Paths should support Unicode symbols.', function (done) { + + var dirName = '文件插件'; + + var win = function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.name).toCanonicallyMatch(dirName); + deleteEntry(directory.name, done); + }; + + createDirectory(dirName, function () { + root.getDirectory(dirName, {create: false}, win, + failed.bind(this, done, 'root.getDirectory - Error getting directory : ' + dirName)); + }, failed.bind(this, done, 'root.getDirectory - Error creating directory : ' + dirName)); + }); + }); + // Content and Asset URLs + if (cordova.platformId === 'android') { // eslint-disable-line no-undef + describe('content: URLs', function () { + // Warning: Default HelloWorld www directory structure is required for these tests (www/index.html at least) + function testContentCopy (src, done) { + var file2 = 'entry.copy.file2b'; + var fullPath = joinURL(temp_root.fullPath, file2); + var validateFile = function (entry) { + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(file2); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(entry.filesystem.name).toEqual('temporary'); + // cleanup + deleteEntry(entry.name, done); + }; + var transfer = function () { + resolveLocalFileSystemURL(src, function (entry) { // eslint-disable-line no-undef + expect(entry).toBeDefined(); + expect(entry.filesystem.name).toEqual('content'); + entry.copyTo(temp_root, file2, validateFile, failed.bind(null, done, 'entry.copyTo - Error copying file: ' + entry.toURL() + ' to TEMPORAL root as: ' + file2)); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for content provider')); + }; + // Delete any existing file to start things off + temp_root.getFile(file2, {}, function (entry) { + entry.remove(transfer, failed.bind(null, done, 'entry.remove - Error removing file: ' + file2)); + }, transfer); + } + it('file.spec.138 copyTo: content', function (done) { + testContentCopy('content://org.apache.cordova.file.testprovider/www/index.html', done); + }); + it('file.spec.139 copyTo: content /w space and query', function (done) { + testContentCopy('content://org.apache.cordova.file.testprovider/?name=foo%20bar&realPath=%2Fwww%2Findex.html', done); + }); + it('file.spec.140 delete: content should fail', function (done) { + resolveLocalFileSystemURL('content://org.apache.cordova.file.testprovider/www/index.html', function (entry) { // eslint-disable-line no-undef + entry.remove(failed.bind(null, done, 'expected delete to fail'), done); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for content provider')); + }); + }); + + // these tests ensure that you can read and copy from android_asset folder + // for details see https://issues.apache.org/jira/browse/CB-6428 + // and https://mail-archives.apache.org/mod_mbox/cordova-dev/201508.mbox/%3C782154441.8406572.1440182722528.JavaMail.yahoo%40mail.yahoo.com%3E + describe('asset: URLs', function () { + it('file.spec.141 filePaths.applicationStorage', function () { + expect(cordova.file.applicationDirectory).toEqual('file:///android_asset/'); // eslint-disable-line no-undef + }, MEDIUM_TIMEOUT); + it('file.spec.142 assets should be enumerable', function (done) { + resolveLocalFileSystemURL('file:///android_asset/www/fixtures/asset-test', function (entry) { // eslint-disable-line no-undef + var reader = entry.createReader(); + reader.readEntries(function (entries) { + expect(entries.length).not.toBe(0); + done(); + }, failed.bind(null, done, 'reader.readEntries - Error during reading of entries from assets directory')); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for assets')); + }, MEDIUM_TIMEOUT); + it('file.spec.145 asset subdirectories should be obtainable', function (done) { + resolveLocalFileSystemURL('file:///android_asset/www/fixtures', function (entry) { // eslint-disable-line no-undef + entry.getDirectory('asset-test', { create: false }, function (subDir) { + expect(subDir).toBeDefined(); + expect(subDir.isFile).toBe(false); + expect(subDir.isDirectory).toBe(true); + expect(subDir.name).toCanonicallyMatch('asset-test'); + done(); + }, failed.bind(null, done, 'entry.getDirectory - Error getting asset subdirectory')); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for assets')); + }, MEDIUM_TIMEOUT); + it('file.spec.146 asset files should be readable', function (done) { + resolveLocalFileSystemURL('file:///android_asset/www/fixtures/asset-test/asset-test.txt', function (entry) { // eslint-disable-line no-undef + expect(entry.isFile).toBe(true); + entry.file(function (file) { + expect(file).toBeDefined(); + var reader = new FileReader(); // eslint-disable-line no-undef + reader.onerror = failed.bind(null, done, 'reader.readAsText - Error reading asset text file'); + reader.onloadend = function () { + expect(this.result).toBeDefined(); + expect(this.result.length).not.toBe(0); + done(); + }; + reader.readAsText(file); + }, failed.bind(null, done, 'entry.file - Error reading asset file')); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for assets')); + }, MEDIUM_TIMEOUT); + it('file.spec.143 copyTo: asset -> temporary', function (done) { + var file2 = 'entry.copy.file2b'; + var fullPath = joinURL(temp_root.fullPath, file2); + var validateFile = function (entry) { + expect(entry.isFile).toBe(true); + expect(entry.isDirectory).toBe(false); + expect(entry.name).toCanonicallyMatch(file2); + expect(entry.fullPath).toCanonicallyMatch(fullPath); + expect(entry.filesystem.name).toEqual('temporary'); + // cleanup + deleteEntry(entry.name, done); + }; + var transfer = function () { + resolveLocalFileSystemURL('file:///android_asset/www/index.html', function (entry) { // eslint-disable-line no-undef + expect(entry.filesystem.name).toEqual('assets'); + entry.copyTo(temp_root, file2, validateFile, failed.bind(null, done, 'entry.copyTo - Error copying file: ' + entry.toURL() + ' to TEMPORAL root as: ' + file2)); + }, failed.bind(null, done, 'resolveLocalFileSystemURL failed for assets')); + }; + // Delete any existing file to start things off + temp_root.getFile(file2, {}, function (entry) { + entry.remove(transfer, failed.bind(null, done, 'entry.remove - Error removing file: ' + file2)); + }, transfer); + }, MEDIUM_TIMEOUT); + }); + it('file.spec.144 copyTo: asset directory', function (done) { + var srcUrl = 'file:///android_asset/www/fixtures/asset-test'; + var dstDir = 'entry.copy.dstDir'; + var dstPath = joinURL(root.fullPath, dstDir); + // create a new directory entry to kick off it + deleteEntry(dstDir, function () { + resolveLocalFileSystemURL(srcUrl, function (directory) { // eslint-disable-line no-undef + directory.copyTo(root, dstDir, function (directory) { + expect(directory).toBeDefined(); + expect(directory.isFile).toBe(false); + expect(directory.isDirectory).toBe(true); + expect(directory.fullPath).toCanonicallyMatch(dstPath); + expect(directory.name).toCanonicallyMatch(dstDir); + root.getDirectory(dstDir, { + create: false + }, function (dirEntry) { + expect(dirEntry).toBeDefined(); + expect(dirEntry.isFile).toBe(false); + expect(dirEntry.isDirectory).toBe(true); + expect(dirEntry.fullPath).toCanonicallyMatch(dstPath); + expect(dirEntry.name).toCanonicallyMatch(dstDir); + dirEntry.getFile('asset-test.txt', { + create: false + }, function (fileEntry) { + expect(fileEntry).toBeDefined(); + expect(fileEntry.isFile).toBe(true); + // cleanup + deleteEntry(dstDir, done); + }, failed.bind(null, done, 'dirEntry.getFile - Error getting subfile')); + }, failed.bind(null, done, 'root.getDirectory - Error getting copied directory')); + }, failed.bind(null, done, 'directory.copyTo - Error copying directory')); + }, failed.bind(null, done, 'resolving src dir')); + }, failed.bind(null, done, 'deleteEntry - Error removing directory : ' + dstDir)); + }, MEDIUM_TIMEOUT); + } + }); + +}; +//* ***************************************************************************************** +//* **************************************Manual Tests*************************************** +//* ***************************************************************************************** + +exports.defineManualTests = function (contentEl, createActionButton) { + + function resolveFs (fsname) { + var fsURL = 'cdvfile://localhost/' + fsname + '/'; + logMessage('Resolving URL: ' + fsURL); + /* eslint-disable no-undef */ + resolveLocalFileSystemURL(fsURL, function (entry) { + logMessage('Success', 'green'); + logMessage(entry.toURL(), 'blue'); + logMessage(entry.toInternalURL(), 'blue'); + logMessage('Resolving URL: ' + entry.toURL()); + resolveLocalFileSystemURL(entry.toURL(), function (entry2) { + logMessage('Success', 'green'); + logMessage(entry2.toURL(), 'blue'); + logMessage(entry2.toInternalURL(), 'blue'); + }, logError('resolveLocalFileSystemURL')); + }, logError('resolveLocalFileSystemURL')); + } + + function testPrivateURL () { + requestFileSystem(LocalFileSystem.TEMPORARY, 0, function (fileSystem) { + logMessage('Temporary root is at ' + fileSystem.root.toNativeURL()); + fileSystem.root.getFile('testfile', { + create: true + }, function (entry) { + logMessage('Temporary file is at ' + entry.toNativeURL()); + if (entry.toNativeURL().substring(0, 12) === 'file:///var/') { + logMessage('File starts with /var/, trying /private/var'); + var newURL = 'file://localhost/private/var/' + entry.toNativeURL().substring(12) + '?and=another_thing'; + // var newURL = entry.toNativeURL(); + logMessage(newURL, 'blue'); + resolveLocalFileSystemURL(newURL, function (newEntry) { + logMessage('Successfully resolved.', 'green'); + logMessage(newEntry.toURL(), 'blue'); + logMessage(newEntry.toNativeURL(), 'blue'); + }, logError('resolveLocalFileSystemURL')); + } + }, logError('getFile')); + }, logError('requestFileSystem')); + } + + function resolveFsContactImage () { + navigator.contacts.pickContact(function (contact) { + var logBox = document.getElementById('logContactBox'); + logBox.innerHTML = ''; + var resolveResult = document.createElement('p'); + if (contact.photos) { + var photoURL = contact.photos[0].value; + resolveLocalFileSystemURL(photoURL, function (entry) { + /* eslint-enable no-undef */ + var contactImage = document.createElement('img'); + var contactLabelImage = document.createElement('p'); + contactLabelImage.innerHTML = 'Result contact image'; + contactImage.setAttribute('src', entry.toURL()); + resolveResult.innerHTML = 'Success resolve\n' + entry.toURL(); + logBox.appendChild(contactLabelImage); + logBox.appendChild(contactImage); + logBox.appendChild(resolveResult); + }, + function (err) { + console.log('resolve error' + err); + }); + } else { + resolveResult.innerHTML = 'Contact has no photos'; + logBox.appendChild(resolveResult); + } + }, + function (err) { + console.log('contact pick error' + err); + }); + } + + function clearLog () { + var log = document.getElementById('info'); + log.innerHTML = ''; + } + + function logMessage (message, color) { + var log = document.getElementById('info'); + var logLine = document.createElement('div'); + if (color) { + logLine.style.color = color; + } + logLine.innerHTML = message; + log.appendChild(logLine); + } + + function logError (serviceName) { + return function (err) { + logMessage('ERROR: ' + serviceName + ' ' + JSON.stringify(err), 'red'); + }; + } + + var fsRoots = { + 'ios': 'library,library-nosync,documents,documents-nosync,cache,bundle,root,private', + 'osx': 'library,library-nosync,documents,documents-nosync,cache,bundle,root,private', + 'android': 'files,files-external,documents,sdcard,cache,cache-external,assets,root', + 'amazon-fireos': 'files,files-external,documents,sdcard,cache,cache-external,root', + 'windows': 'temporary,persistent' + }; + + // Add title and align to content + var div = document.createElement('h2'); + div.appendChild(document.createTextNode('File Systems')); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + + div = document.createElement('h3'); + div.appendChild(document.createTextNode('Results are displayed in yellow status box below with expected results noted under that')); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + + div = document.createElement('div'); + div.setAttribute('id', 'button'); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + /* eslint-disable no-undef */ + if (fsRoots.hasOwnProperty(cordova.platformId)) { + (fsRoots[cordova.platformId].split(',')).forEach(function (fs) { + if (cordova.platformId === 'ios' && fs === 'private') { + /* eslint-enable no-undef */ + createActionButton('Test private URL (iOS)', function () { + clearLog(); + testPrivateURL(); + }, 'button'); + } else { + createActionButton(fs, function () { + clearLog(); + resolveFs(fs); + }, 'button'); + } + }); + } + + div = document.createElement('div'); + div.setAttribute('id', 'info'); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + + div = document.createElement('h3'); + div.appendChild(document.createTextNode('For each test above, file or directory should be successfully found. ' + + 'Status box should say Resolving URL was Success. The first URL resolved is the internal URL. ' + + 'The second URL resolved is the absolute URL. Blue URLs must match.')); + contentEl.appendChild(div); + + div = document.createElement('h3'); + div.appendChild(document.createTextNode('For Test private URL (iOS), the private URL (first blue URL in status box) ' + + 'should be successfully resolved. Status box should say Successfully resolved. Both blue URLs below ' + + 'that should match.')); + contentEl.appendChild(div); + + div = document.createElement('h2'); + div.appendChild(document.createTextNode('Resolving content urls')); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + + div = document.createElement('div'); + div.setAttribute('id', 'contactButton'); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + + div = document.createElement('div'); + div.setAttribute('id', 'logContactBox'); + div.setAttribute('align', 'center'); + contentEl.appendChild(div); + + createActionButton('show-contact-image', function () { + resolveFsContactImage(); + }, 'contactButton'); +}; |
