Skip to content

Commit 5b2f27f

Browse files
authored
Fs: added new VirtualFs that is based on memfs (#334)
This allows to use caches in tests without mocking anything :)
1 parent 5c3b608 commit 5b2f27f

10 files changed

Lines changed: 642 additions & 61 deletions

File tree

package-lock.json

Lines changed: 9 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"jest-cli": "^29.3.1",
9797
"jest-environment-jsdom": "^29.3.1",
9898
"lint-staged": "^10.4.2",
99+
"memfs": "^3.4.12",
99100
"mock-fs": "git+https://git@github.com/warpdesign/mock-fs.git",
100101
"pm2": "^5.2.2",
101102
"prettier": "^2.7.1",

src/components/__tests__/FileMenu.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ describe('FileMenu', () => {
7070
})
7171
})
7272

73-
it.only('should disable individual menu items when disable condition is met', () => {
73+
it('should disable individual menu items when disable condition is met', () => {
7474
const props = { ...PROPS, selectedItemsLength: 0 }
7575
const options = {
7676
providerProps: {

src/components/__tests__/Statusbar.test.tsx

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,43 @@
22
* @jest-environment jsdom
33
*/
44
import React from 'react'
5-
import { screen, setup, render, t, waitFor } from 'rtl'
5+
import { screen, setup, render, t } from 'rtl'
66
import { Statusbar } from '../Statusbar'
77
import { filterFiles, filterDirs } from '$src/utils/fileUtils'
8-
import { File } from '$src/services/Fs'
98
import { ViewState } from '$src/state/viewState'
10-
import { FileState } from '$src/state/fileState'
11-
import { action, makeObservable, observable, runInAction } from 'mobx'
9+
import { vol } from 'memfs'
1210

1311
describe('Statusbar', () => {
14-
const cache = makeObservable(
12+
vol.fromJSON(
1513
{
16-
status: 'ok',
17-
files: observable<File>([]),
18-
setShowHiddenFiles: jest.fn((show: boolean) => {
19-
cache.showHiddenFiles = show
20-
}),
21-
showHiddenFiles: false,
22-
path: '/tmp',
23-
} as unknown as FileState,
24-
{
25-
path: observable,
26-
showHiddenFiles: observable,
27-
setShowHiddenFiles: action,
14+
dir1: null,
15+
foo1: '',
16+
foo2: '',
17+
'.hidden': '',
2818
},
19+
'/virtual',
2920
)
3021

3122
const options = {
3223
providerProps: {
33-
viewState: {
34-
getVisibleCache: () => cache,
35-
} as unknown as ViewState,
24+
viewState: new ViewState(0),
3625
},
3726
}
3827

3928
const buildStatusBarText = () => {
29+
const cache = options.providerProps.viewState.getVisibleCache()
4030
const files = filterFiles(cache.files, cache.showHiddenFiles).length
4131
const folders = filterDirs(cache.files, cache.showHiddenFiles).length
32+
4233
return `${t('STATUS.FILES', { count: files })}, ${t('STATUS.FOLDERS', {
4334
count: folders,
4435
})}`
4536
}
4637

47-
beforeEach(() => {
48-
cache.status = 'ok'
49-
cache.showHiddenFiles = false
50-
cache.files.replace([
51-
{
52-
fullname: 'dir1',
53-
isDir: true,
54-
} as unknown as File,
55-
{
56-
fullname: 'foo1',
57-
isDir: false,
58-
} as unknown as File,
59-
{
60-
fullname: '.foo2',
61-
isDir: false,
62-
} as unknown as File,
63-
])
38+
beforeEach(async () => {
39+
options.providerProps.viewState = new ViewState(0)
40+
const cache = options.providerProps.viewState.addCache('/virtual', -1, true)
41+
await cache.openDirectory({ dir: '/virtual', fullname: '' })
6442

6543
jest.clearAllMocks()
6644
})
@@ -81,7 +59,7 @@ describe('Statusbar', () => {
8159
})
8260

8361
it('toggle hidden files button should be hidden if file cache is not valid', () => {
84-
cache.status = 'busy'
62+
options.providerProps.viewState.getVisibleCache().setStatus('busy')
8563
render(<Statusbar />, options)
8664

8765
expect(screen.queryByRole('button')).not.toBeInTheDocument()

src/gui/index.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ import child_process from 'child_process'
1212

1313
import { ExplorerApp } from '$src/components/App'
1414
import { i18n } from '$src/locale/i18n'
15-
import { SettingsState } from '$src/state/settingsState'
1615
// register Fs that will be available in React-Explorer
1716
// I guess there is a better place to do that
18-
import { FsGeneric } from '$src/services/plugins/FsGeneric'
1917
import { FsWsl } from '$src/services/plugins/FsWsl'
2018
import { FsLocal } from '$src/services/plugins/FsLocal'
19+
import { FsGeneric } from '$src/services/plugins/FsGeneric'
2120
import { registerFs } from '$src/services/Fs'
2221
import { AppState } from '$src/state/appState'
2322

@@ -29,9 +28,11 @@ configure({
2928
safeDescriptors: window.ENV.CY ? false : true,
3029
})
3130

31+
// TODO: there should be an easy way to automatically register new FS
3232
function initFS() {
33-
if ((process && process.env && process.env.NODE_ENV === 'test') || window.ENV.CY) {
33+
if ((process && process.env && process.env.NODE_ENV === 'test') || window.ENV.CY || typeof jest !== 'undefined') {
3434
registerFs(FsGeneric)
35+
// registerFs(FsVirtual)
3536
} else {
3637
registerFs(FsWsl)
3738
registerFs(FsLocal)
@@ -92,8 +93,5 @@ class App {
9293
}
9394
}
9495

95-
;(async () => {
96-
await new Promise((res) => setTimeout(res, 1000))
97-
const app = new App()
98-
app.init()
99-
})()
96+
const app = new App()
97+
app.init()

src/services/Fs.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/* eslint-disable @typescript-eslint/explicit-function-return-type */
22
import { Readable } from 'stream'
3+
import { FsVirtual } from '$src/services/plugins/FsVirtual'
34

45
import { isWin } from '$src/utils/platform'
56

6-
const interfaces: Array<Fs> = []
7+
const interfaces: Array<Fs> = [FsVirtual]
78

89
export interface Credentials {
910
user?: string
@@ -25,7 +26,7 @@ export interface File {
2526
name: string
2627
fullname: string
2728
extension: string
28-
target: string
29+
target: string | Buffer
2930
cDate: Date
3031
mDate: Date
3132
bDate: Date
@@ -130,7 +131,6 @@ export interface FsApi {
130131
transferId?: number,
131132
): Promise<void>
132133
getParentTree(dir: string): Array<{ dir: string; fullname: string }>
133-
134134
resolve(path: string): string
135135
sanityze(path: string): string
136136
join(...paths: string[]): string
@@ -146,7 +146,6 @@ export interface FsApi {
146146

147147
export function getFS(path: string): Fs {
148148
const newfs = interfaces.find((filesystem) => filesystem.canread(path))
149-
console.log('got FS', newfs)
150149
// if (!newfs) {
151150
// newfs = FsGeneric;
152151
// }

0 commit comments

Comments
 (0)