From d612b2d6af69516e1d1909972c9c94632df8510a Mon Sep 17 00:00:00 2001 From: wancat Date: Fri, 8 Mar 2024 00:13:38 +0800 Subject: [PATCH] feat: add file matcher --- .eslintrc.js | 2 + packages/game/src/condition/FileMatcher.ts | 15 ++++ packages/game/src/types.ts | 14 ++++ packages/game/test/asyncCondition.test.ts | 92 ++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 packages/game/src/condition/FileMatcher.ts create mode 100644 packages/game/test/asyncCondition.test.ts diff --git a/.eslintrc.js b/.eslintrc.js index d53065a..f1ee5a6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -66,6 +66,8 @@ module.exports = { '@typescript-eslint/no-useless-constructor': 'error', 'no-empty-function': 'off', '@typescript-eslint/no-empty-function': 'error', + 'no-shadow': 'off', + '@typescript-eslint/no-shadow': 'error', }, overrides: [ { diff --git a/packages/game/src/condition/FileMatcher.ts b/packages/game/src/condition/FileMatcher.ts new file mode 100644 index 0000000..ac9f709 --- /dev/null +++ b/packages/game/src/condition/FileMatcher.ts @@ -0,0 +1,15 @@ +import { FileInput, IFileExistenceChecker } from '../types' + +interface FileExistenceInput extends FileInput { + exists: boolean +} + +export async function checkFiles( + checker: IFileExistenceChecker, + files: FileExistenceInput[] +) { + const existences = await Promise.all( + files.map((file) => checker.exists(file)) + ) + return existences.every((exists, index) => exists === files[index].exists) +} diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts index 8227198..57724a9 100644 --- a/packages/game/src/types.ts +++ b/packages/game/src/types.ts @@ -13,3 +13,17 @@ export interface ICondition { or?: ICondition[] not?: ICondition } + +export enum FileType { + FILE = 'file', + FOLDER = 'folder', +} + +export interface FileInput { + path: string + type: FileType +} + +export interface IFileExistenceChecker { + exists(file: FileInput): Promise +} diff --git a/packages/game/test/asyncCondition.test.ts b/packages/game/test/asyncCondition.test.ts new file mode 100644 index 0000000..1a6503a --- /dev/null +++ b/packages/game/test/asyncCondition.test.ts @@ -0,0 +1,92 @@ +import { test, expect } from '@jest/globals' +import { IFileExistenceChecker, FileType, FileInput } from '../src/types.js' +import { checkFiles } from '../src/condition/FileMatcher.js' + +class MockFileChecker implements IFileExistenceChecker { + private files: FileInput[] = [ + { + path: '/home/user/hello.txt', + type: FileType.FILE, + }, + { + path: '/home/user/world.txt', + type: FileType.FILE, + }, + { + path: '/home/user/Downloads', + type: FileType.FOLDER, + }, + ] + + async exists(file: FileInput): Promise { + return this.files.some((f) => f.path === file.path && f.type === file.type) + } +} + +test('file matcher', async () => { + const checker = new MockFileChecker() + expect( + await checkFiles(checker, [ + { + path: '/home/user/hello.txt', + type: FileType.FILE, + exists: true, + }, + ]) + ).toBe(true) + expect( + await checkFiles(checker, [ + { + path: '/home/user/not-exists.txt', + type: FileType.FILE, + exists: true, + }, + ]) + ).toBe(false) + expect( + await checkFiles(checker, [ + { + path: '/home/user/not-exists.txt', + type: FileType.FILE, + exists: false, + }, + ]) + ).toBe(true) + expect( + await checkFiles(checker, [ + { + path: '/home/user/Downloads', + type: FileType.FOLDER, + exists: true, + }, + ]) + ).toBe(true) + expect( + await checkFiles(checker, [ + { + path: '/home/user/hello.txt', + type: FileType.FILE, + exists: true, + }, + { + path: '/home/user/Downloads', + type: FileType.FOLDER, + exists: true, + }, + ]) + ).toBe(true) + expect( + await checkFiles(checker, [ + { + path: '/home/user/hello.txt', + type: FileType.FILE, + exists: true, + }, + { + path: '/home/user/not-exist.txt', + type: FileType.FILE, + exists: true, + }, + ]) + ).toBe(false) +})