1+ import React from 'react' ;
2+ import { cleanup , render } from '@testing-library/react' ;
3+ import { Provider } from 'react-redux' ;
4+ import { DateTime } from 'luxon' ;
5+ import { RootState } from '../store' ;
6+ import { metafileAdded , metafileRemoved } from '../slices/metafiles' ;
7+ import { mockStore } from '../../test-utils/mock-store' ;
8+ import { DndProvider } from 'react-dnd' ;
9+ import Canvas from '../../components/Canvas' ;
10+ import { HTML5Backend } from 'react-dnd-html5-backend' ;
11+ import { removeUndefined } from '../../containers/format' ;
12+ import { fetchMetafile , fetchNewMetafile , FileMetafile } from '../thunks/metafiles' ;
13+ import { file , mock , MockInstance } from '../../test-utils/mock-fs' ;
14+
15+ const mockedStore : RootState = {
16+ stacks : {
17+ ids : [ ] ,
18+ entities : { }
19+ } ,
20+ cards : {
21+ ids : [ ] ,
22+ entities : { }
23+ } ,
24+ filetypes : {
25+ ids : [ ] ,
26+ entities : { }
27+ } ,
28+ metafiles : {
29+ ids : [ '821c9159-292b-4639-b90e-e84fc12740ee' , '46ae0111-0c82-4ee2-9ee5-cd5bdf8d8a71' , '88e2gd50-3a5q-6401-b5b3-203c6710e35c' ] ,
30+ entities : {
31+ '821c9159-292b-4639-b90e-e84fc12740ee' : {
32+ id : '821c9159-292b-4639-b90e-e84fc12740ee' ,
33+ name : 'test.js' ,
34+ modified : DateTime . fromISO ( '2019-11-19T19:19:47.572-08:00' ) . valueOf ( ) ,
35+ content : 'var rand: number = Math.floor(Math.random() * 6) + 1;'
36+ } ,
37+ '46ae0111-0c82-4ee2-9ee5-cd5bdf8d8a71' : {
38+ id : '46ae0111-0c82-4ee2-9ee5-cd5bdf8d8a71' ,
39+ name : 'example.ts' ,
40+ path : 'foo/example.ts' ,
41+ modified : DateTime . fromISO ( '2015-06-19T19:10:47.319-08:00' ) . valueOf ( ) ,
42+ content : 'const rand = Math.floor(Math.random() * 6) + 1;' ,
43+ repo : '23' ,
44+ branch : 'master'
45+ } ,
46+ '88e2gd50-3a5q-6401-b5b3-203c6710e35c' : {
47+ id : '88e2gd50-3a5q-6401-b5b3-203c6710e35c' ,
48+ name : 'bar.js' ,
49+ path : 'foo/bar.js' ,
50+ modified : DateTime . fromISO ( '2015-06-19T19:10:47.319-08:00' ) . valueOf ( ) ,
51+ content : 'file contents' ,
52+ }
53+ }
54+ } ,
55+ cached : {
56+ ids : [ ] ,
57+ entities : { }
58+ } ,
59+ repos : {
60+ ids : [ ] ,
61+ entities : { }
62+ } ,
63+ branches : {
64+ ids : [ ] ,
65+ entities : { }
66+ } ,
67+ modals : {
68+ ids : [ ] ,
69+ entities : { }
70+ }
71+ }
72+
73+ const metafile1 : FileMetafile = {
74+ id : 'b859d4e8-b932-4fc7-a2f7-29a8ef8cd8f8' ,
75+ name : 'turtle.asp' ,
76+ modified : DateTime . fromISO ( '2017-01-05T19:09:22.744-08:00' ) . valueOf ( ) ,
77+ path : 'test/turtle.asp' ,
78+ content : 'example'
79+ }
80+
81+ const metafile2 : FileMetafile = {
82+ id : 'h8114d71-b100-fg9a-0c1d3516d991' ,
83+ name : 'turtle.asp' ,
84+ modified : DateTime . fromISO ( '2017-01-05T19:09:22.744-08:00' ) . valueOf ( ) ,
85+ path : 'test/turtle.asp' ,
86+ content : 'example'
87+ }
88+
89+ describe ( 'cacheMiddleware Redux middleware' , ( ) => {
90+ const store = mockStore ( mockedStore ) ;
91+
92+ let mockedInstance : MockInstance ;
93+
94+ beforeAll ( async ( ) => {
95+ const instance = await mock ( {
96+ 'test/turtle.asp' : file ( { content : 'example' , mtime : new Date ( 1 ) } )
97+ } ) ;
98+ return mockedInstance = instance ;
99+ } ) ;
100+ afterAll ( ( ) => mockedInstance . reset ( ) ) ;
101+
102+ afterEach ( ( ) => {
103+ cleanup ;
104+ store . clearActions ( ) ;
105+ jest . resetAllMocks ( ) ;
106+ } ) ;
107+
108+ const produceComponent = ( ) => {
109+ render (
110+ < Provider store = { store } >
111+ < DndProvider backend = { HTML5Backend } >
112+ < Canvas />
113+ </ DndProvider >
114+ </ Provider >
115+ ) ;
116+ } ;
117+
118+ it ( 'initial state has no cached files' , ( ) => {
119+ produceComponent ( ) ;
120+ expect ( store . getState ( ) . cached . ids ) . toHaveLength ( 0 ) ;
121+ } ) ;
122+
123+ it ( 'adding a metafile triggers the creation of a file cache' , async ( ) => {
124+ produceComponent ( ) ;
125+ store . dispatch ( metafileAdded ( metafile1 ) ) ;
126+ expect ( removeUndefined ( Object . values ( store . getState ( ) . cached . entities ) ) ) . toStrictEqual (
127+ expect . arrayContaining ( [ expect . objectContaining ( {
128+ path : metafile1 . path ,
129+ reserves : 0
130+ } ) ] )
131+ ) ;
132+ } ) ;
133+
134+ it ( 'fetching a new file triggers the creation of a file cache' , async ( ) => {
135+ produceComponent ( ) ;
136+ await store . dispatch ( fetchNewMetafile ( { filepath : metafile1 . path } ) ) . unwrap ( ) ;
137+ expect ( store . getActions ( ) ) . toStrictEqual (
138+ expect . arrayContaining ( [ expect . objectContaining ( { type : 'cached/cachedAdded' } ) ] )
139+ ) ;
140+ expect ( removeUndefined ( Object . values ( store . getState ( ) . cached . entities ) ) ) . toStrictEqual (
141+ expect . arrayContaining ( [ expect . objectContaining ( { path : metafile1 . path } ) ] )
142+ ) ;
143+ } ) ;
144+
145+ it ( 'fetching multiple metafiles for the same file increases reserves in the cached file' , async ( ) => {
146+ produceComponent ( ) ;
147+ await store . dispatch ( fetchMetafile ( { filepath : metafile1 . path } ) ) . unwrap ( ) ;
148+ await store . dispatch ( fetchMetafile ( { filepath : metafile2 . path } ) ) . unwrap ( ) ;
149+ const cached = removeUndefined ( Object . values ( store . getState ( ) . cached . entities ) ) ;
150+ expect ( cached ) . toHaveLength ( 1 ) ;
151+ expect ( cached ) . toStrictEqual (
152+ expect . arrayContaining ( [
153+ expect . objectContaining ( {
154+ path : metafile1 . path ,
155+ reserves : 2
156+ } )
157+ ] )
158+ ) ;
159+ } ) ;
160+
161+ it ( 'removing a metafile decreases reserves in the cached files' , async ( ) => {
162+ produceComponent ( ) ;
163+ const metafile = await store . dispatch ( fetchMetafile ( { filepath : metafile1 . path } ) ) . unwrap ( ) ;
164+ await store . dispatch ( fetchMetafile ( { filepath : metafile2 . path } ) ) . unwrap ( ) ;
165+ expect ( removeUndefined ( Object . values ( store . getState ( ) . cached . entities ) ) ) . toStrictEqual (
166+ expect . arrayContaining ( [
167+ expect . objectContaining ( {
168+ path : metafile . path ,
169+ reserves : 2
170+ } )
171+ ] )
172+ ) ;
173+ store . dispatch ( metafileRemoved ( metafile . id ) ) ;
174+ expect ( removeUndefined ( Object . values ( store . getState ( ) . cached . entities ) ) ) . toStrictEqual (
175+ expect . arrayContaining ( [
176+ expect . objectContaining ( {
177+ path : metafile1 . path ,
178+ reserves : 1
179+ } )
180+ ] )
181+ ) ;
182+ } ) ;
183+ } ) ;
0 commit comments