Browser storage
Test Native (Somewhat patched to fix buggy safari impl) Sandbox Memory IndexedDB Cache storage
getDirectoryHandle(create=false) rejects for non-existing directories
getDirectoryHandle(create=true) creates an empty directory
getDirectoryHandle(create=false) returns existing directories
getDirectoryHandle(create=true) returns existing directories without erasing
getDirectoryHandle() when a file already exists with the same name
getDirectoryHandle() with empty name
getDirectoryHandle(create=true) with empty name
getDirectoryHandle() with ".." name
getDirectoryHandle(create=false) with a path separator when the directory exists
getDirectoryHandle(create=true) with a path separator
getFileHandle(create=false) rejects for non-existing files
getFileHandle(create=true) creates an empty file for non-existing files
getFileHandle(create=false) returns existing files
getFileHandle(create=true) returns existing files without erasing
getFileHandle(create=false) when a directory already exists with the same name
getFileHandle(create=true) when a directory already exists with the same name
getFileHandle() with empty name
getFileHandle() with "." name
getFileHandle() with ".." name
getFileHandle(create=false) with a path separator when the file exists.
getFileHandle(create=true) with a path separator
removeEntry() to remove a file
removeEntry() on an already removed file should fail
removeEntry() to remove an empty directory
removeEntry() on a non-empty directory should fail
removeEntry() with empty name should fail
removeEntry() with "." name should fail
removeEntry() with ".." name should fail
removeEntry() with a path separator should fail.
getFile() provides a file that can be sliced
getFile() returns last modified time
resolve() returns relative path as array for existing dir descendant
resolve() returns relative path as array for existing file descendant
resolve() returns empty array when itself passed as arg
resolve() returns null for non-existing descendant
can be piped to with a string
can be piped to with an ArrayBuffer
can be piped to with a Blob
can be piped to with a param object with write command
can be piped to with a param object with multiple commands
multiple operations can be queued
plays well with fetch
abort() aborts write
write() with an empty blob to an empty file
write() a blob to an empty file
write() with WriteParams without position to an empty file
write() a string to an empty file with zero offset
write() a blob to an empty file with zero offset
write() called consecutively appends
write() WriteParams without position and string appends
write() WriteParams without position and blob appends
write() called with a string and a valid offset
write() called with a blob and a valid offset
write() called with an larger offset than size
write() with an empty string to an empty file
write() with a valid utf-8 string
write() with a string with unix line ending preserved
write() with a string with windows line ending preserved
write() with an empty array buffer to an empty file
write() with a valid typed array buffer
atomic writes: write() after close() fails
atomic writes: truncate() after close() fails
atomic writes: close() after close() fails
atomic writes: only one close() operation may succeed
getWriter() can be used
writing small bits advances the position
WriteParams: truncate missing size param
WriteParams: write missing data param
WriteParams: seek missing position param
truncate() to shrink a file
truncate() to grow a file
createWritable() fails when parent directory is removed
createWritable({keepExistingData: true}): atomic writable file stream initialized with source contents
createWritable({keepExistingData: false}) removes previous data
cursor position: truncate size > offset
cursor position: truncate size < offset
commands are queued
queryPermission({ mode: read }) returns granted
queryPermission({ mode: readwrite }) returns granted
isSameEntry for identical directory handles returns true
isSameEntry for different directories returns false
isSameEntry for different handles for the same directory
isSameEntry for identical file handles returns true
isSameEntry for different files returns false
isSameEntry comparing a file to a file in a different directory returns false
isSameEntry comparing a file to a directory returns false
Large real data test
Total
      getOriginPrivateDirectory(),
      getOriginPrivateDirectory(import('./adapters/sandbox.js'))
      getOriginPrivateDirectory(import('./adapters/memory.js'))
      getOriginPrivateDirectory(import('./adapters/indexeddb.js'))
      getOriginPrivateDirectory(import('./adapters/cache.js'))
    
Manual save & open file(s)/directory
Manual Testing
showDirectoryPicker({
  _preferPolyfill:
})
showOpenFilePicker({
  _preferPolyfill:
  multiple:
  excludeAcceptAllOption:
  types:
})
showSaveFilePicker({
  _preferPolyfill:
  suggestedName:
  excludeAcceptAllOption:
  types:
})
Drag and drop

The DataTransfer have implemented DataTransferItem.prototype.getAsFileSystemHandle() That lets you convert a item into a filesystem handle. This is polyfilled for you.
elm.ondragover = evt => evt.preventDefault()
elm.ondrop = async evt => {
  evt.preventDefault()
  for (const dataTransferItem of dataTransfer.items) {
    const handle = await dataTransferItem.getAsFileSystemHandle()
    console.log(handle.kind)
  }
}
Drop anywhere
on page