chromium/ui/file_manager/file_manager/foreground/js/directory_contents_unittest.ts

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {assertEquals, assertFalse} from 'chrome://webui-test/chromeos/chai_assert.js';

import type {VolumeInfo} from '../../background/js/volume_info.js';
import type {VolumeManager} from '../../background/js/volume_manager.js';
import type {FilesAppEntry} from '../../common/js/files_app_entry_types.js';
import {installMockChrome} from '../../common/js/mock_chrome.js';
import {RootType} from '../../common/js/volume_manager_types.js';

import {FileFilter, RecentContentScanner} from './directory_contents.js';

/**
 * Mock chrome APIs.
 */
const mockChrome = {
  fileManagerPrivate: {
    getRecentFiles:
        (_1: chrome.fileManagerPrivate.SourceRestriction, query: string,
         _2: number, _3: chrome.fileManagerPrivate.FileCategory, _4: boolean,
         callback: (entries: FileEntry[]) => void) => {
          const entries: FileEntry[] = [
            {name: '1.txt'} as FileEntry,
            {name: '2.txt'} as FileEntry,
            {name: '3.png'} as FileEntry,
          ];
          callback(entries.filter(e => e.name.indexOf(query) !== -1));
        },
  },
};

/**
 * Initializes the test environment.
 */
export function setUp() {
  // Install mock chrome APIs.
  installMockChrome(mockChrome);
}

/**
 * Check that files are shown or hidden correctly.
 */
export function testHiddenFiles() {
  let volumeManagerRootType = RootType.DOWNLOADS;
  // Create a fake volume manager that provides entry location info.
  const volumeManager = {
    getLocationInfo: (_: FileEntry) => {
      return {
        rootType: volumeManagerRootType,
      };
    },
  } as VolumeManager;

  const entry = (fullPath: string): FileEntry => {
    return {
      name: fullPath.split('/').pop()!,
      fullPath,
      filesystem: {name: 'test'} as FileSystem,
    } as FileEntry;
  };

  // Create a set of entries in root dir, and in /PvmDefault dir.
  const entries: FileEntry[] = [];
  for (const e of ['.test', 'test', '$RECYCLE.BIN', '$okForNow', '~okForNow']) {
    entries.push(entry('/' + e));
    entries.push(entry('/PvmDefault/' + e));
  }

  const filter = new FileFilter(volumeManager);

  // .test should be hidden in any dir.
  // $RECYCLE.BIN is hidden in downloads:/PvmDefault only.
  assertFalse(filter.isHiddenFilesVisible());
  let hidden = entries.filter(entry => !filter.filter(entry));
  assertEquals(3, hidden.length);
  assertEquals('/.test', hidden[0]!.fullPath);
  assertEquals('/PvmDefault/.test', hidden[1]!.fullPath);
  assertEquals('/PvmDefault/$RECYCLE.BIN', hidden[2]!.fullPath);

  // No files hidden when we show hidden files.
  filter.setHiddenFilesVisible(true);
  hidden = entries.filter(entry => !filter.filter(entry));
  assertEquals(0, hidden.length);

  // $RECYCLE.BIN is not hidden in other volumes.
  volumeManagerRootType = 'testroot' as RootType;
  filter.setHiddenFilesVisible(false);
  hidden = entries.filter(entry => !filter.filter(entry));
  assertEquals(2, hidden.length);
  assertEquals('/.test', hidden[0]!.fullPath);
  assertEquals('/PvmDefault/.test', hidden[1]!.fullPath);

  // Still no files hidden when we show hidden files.
  filter.setHiddenFilesVisible(true);
  hidden = entries.filter(entry => !filter.filter(entry));
  assertEquals(0, hidden.length);
}

/**
 * Check the recent entries which doesn't match the query or whose volume is
 * disallowed will be filtered out.
 */
export async function testRecentScannerFilter() {
  // Mock volume manager
  const volumeManager = {
    getVolumeInfo: (entry) => {
      if (entry.name === '1.txt') {
        return null;
      }
      return {
        volumeId: 'fakeId',
      } as VolumeInfo;
    },
  } as VolumeManager;
  const scanner = new RecentContentScanner('txt', 30, volumeManager);
  let entriesCallbackResult: Array<Entry|FilesAppEntry> = [];
  function entriesCallback(entries: Array<Entry|FilesAppEntry>) {
    entriesCallbackResult = entries;
  }
  function otherCallback() {}
  await scanner.scan(entriesCallback, otherCallback, otherCallback);
  // 1.txt: volume is not allowed; 3.png: query is not matched.
  assertEquals(1, entriesCallbackResult.length);
  assertEquals('2.txt', entriesCallbackResult[0]!.name);
}