UNPKG

12.2 kBPlain TextView Raw
1import {expect} from "chai";
2import {FileSystem, fileSystemEventNames, pathSeparator} from '../src/universal';
3import {EventsMatcher} from '../test-kit/drivers/events-matcher';
4import * as Promise from 'bluebird';
5import {EventEmitter} from 'eventemitter3';
6
7
8export const dirName = 'foo';
9export const fileName = 'bar.txt';
10export const content = 'content';
11export const ignoredDir = 'ignored';
12export const ignoredFile = `${dirName}${pathSeparator}ignored.txt`;
13
14export function assertFileSystemContract(fsProvider: () => Promise<FileSystem>, options:EventsMatcher.Options) {
15 describe(`filesystem contract`, () => {
16 let fs: FileSystem;
17 let matcher: EventsMatcher;
18 beforeEach(() => {
19 matcher = new EventsMatcher(options);
20 return fsProvider()
21 .then(newFs => {
22 fs = newFs;
23 matcher.track(fs.events as any as EventEmitter, ...fileSystemEventNames);
24 });
25 });
26
27 it(`initially empty`, function() {
28 return expect(fs.loadDirectoryTree()).to.become({type:'dir', name:'', fullPath:'', children:[]});
29 });
30
31 it(`loading a non-existing file - fails`, function() {
32 return expect(fs.loadTextFile(fileName)).to.be.rejectedWith(Error);
33 });
34
35 it(`loading a directory as a file - fails`, function() {
36 return fs.ensureDirectory(dirName)
37 .then(() => {
38 return matcher.expect([{type: 'directoryCreated', fullPath:dirName}])
39 })
40 .then(() => expect(fs.loadTextFile(dirName)).to.be.rejectedWith(Error))
41 .then(() => matcher.expect([]));
42 });
43
44 it(`saving an illegal file name - fails`, function() {
45 return expect(fs.saveFile('', content)).to.be.rejectedWith(Error)
46 .then(() => matcher.expect([]));
47 });
48
49 it(`ensuring existence of directory`, function() {
50 const dirName = fileName;
51 const expectedStructure = {
52 type:'dir', name:'', fullPath:'', children:[
53 {type:'dir', name:dirName, fullPath:dirName, children:[]}
54 ]};
55 return fs.ensureDirectory(dirName)
56 .then(() => matcher.expect([{type: 'directoryCreated', fullPath:dirName}]))
57 .then(() => expect(fs.loadDirectoryTree()).to.become(expectedStructure))
58 .then(() => fs.ensureDirectory(dirName)) //2nd time does nothing
59 .then(() => expect(fs.loadDirectoryTree()).to.become(expectedStructure))
60 .then(() => matcher.expect([]))
61 });
62
63 it(`saving a file over a directory - fails`, function() {
64 return fs.ensureDirectory(dirName)
65 .then(() => matcher.expect([{type: 'directoryCreated', fullPath:dirName}]))
66 .then(() => expect(fs.saveFile(dirName, content)).to.be.rejectedWith(Error))
67 .then(() => expect(fs.loadDirectoryTree()).to.become({
68 type:'dir', name:'', fullPath:'', children:[
69 {type:'dir', name:dirName, fullPath:dirName, children:[]}
70 ]}))
71 .then(() => matcher.expect([]));
72 });
73
74 it(`saving a file over a file in its path - fails`, function() {
75 const fileNameAsDir = dirName;
76 return fs.saveFile(fileNameAsDir, content)
77 .then(() => matcher.expect([{type: 'fileCreated', fullPath:fileNameAsDir, newContent:content}]))
78 .then(() => expect(fs.saveFile(`${fileNameAsDir}/${fileName}`, '_${content}')).to.be.rejectedWith(Error))
79 .then(() => expect(fs.loadDirectoryTree()).to.become({
80 type:'dir', name:'', fullPath:'', children:[
81 {type:'file', name:fileNameAsDir, fullPath:fileNameAsDir}
82 ]}))
83 .then(() => matcher.expect([]));
84 });
85
86 it(`saving a new file (and a new directory to hold it)`, function() {
87 return fs.saveFile(`${dirName}/${fileName}`, content)
88 .then(() => matcher.expect([{type: 'directoryCreated', fullPath:dirName}, {type: 'fileCreated', fullPath:`${dirName}/${fileName}`, newContent:content}]))
89 .then(() => expect(fs.loadDirectoryTree()).to.become({
90 type:'dir', name:'', fullPath:'', children:[
91 {type:'dir', name:dirName, fullPath:dirName, children:[
92 {type:'file', name:fileName, fullPath:`${dirName}/${fileName}`}]}]}))
93 .then(() => matcher.expect([]));
94 });
95
96 it(`saving a file with different content`, function() {
97 const newContent = `_${content}`;
98 return fs.saveFile(fileName, content)
99 .then(() => matcher.expect([{type: 'fileCreated', fullPath:fileName, newContent:content}]))
100 .then(() => expect(fs.loadTextFile(fileName)).to.become(content))
101 .then(() => fs.saveFile(fileName, newContent))
102 .then(() => matcher.expect([{type: 'fileChanged', fullPath:fileName, newContent:newContent}]))
103 .then(() => expect(fs.loadTextFile(fileName)).to.become(newContent))
104 .then(() => matcher.expect([]));
105 });
106
107 it(`saving a file with same content`, function() {
108 const expectedStructure = {
109 type:'dir', name:'', fullPath:'', children:[
110 {name: fileName, fullPath: fileName, type: 'file'}
111 ]};
112
113 return fs.saveFile(fileName, content)
114 .then(() => matcher.expect([{type: 'fileCreated', fullPath:fileName, newContent:content}]))
115 .then(() => expect(fs.loadTextFile(fileName)).to.become(content))
116 .then(() => fs.saveFile(fileName, content)) // may or may not trigger an event
117 .then(() => expect(fs.loadDirectoryTree()).to.become(expectedStructure))
118 .then(() => expect(fs.loadTextFile(fileName)).to.become(content));
119 });
120
121 it(`deleting root directory - fails`, function() {
122 return expect(fs.deleteDirectory('')).to.be.rejectedWith(Error)
123 .then(() => matcher.expect([]));
124 });
125
126 it(`deleting a directory`, function() {
127 return fs.ensureDirectory(`${dirName}/_${dirName}`)
128 .then(() => matcher.expect([
129 {type: 'directoryCreated', fullPath:dirName},
130 {type: 'directoryCreated', fullPath:`${dirName}/_${dirName}`}]))
131 .then(() => fs.deleteDirectory(`${dirName}/_${dirName}`))
132 .then(() => matcher.expect([{type: 'directoryDeleted', fullPath:`${dirName}/_${dirName}`}]))
133 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([
134 {children:[], fullPath:dirName, name:dirName, type:'dir'}]))
135 .then(() => matcher.expect([]));
136 });
137
138 it(`deleting non existing directory succeeds`, function() {
139 return fs.deleteDirectory(`${dirName}/_${dirName}`)
140 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([]))
141 .then(() => matcher.expect([]));
142 });
143
144 it(`deleting directory which is actually a file - fails`, function() {
145 return fs.saveFile(fileName, content)
146 .then(() => matcher.expect([{type: 'fileCreated', fullPath:fileName, newContent:content}]))
147 .then(() => expect(fs.deleteDirectory(fileName)).to.be.rejectedWith(Error))
148 .then(() => matcher.expect([]));
149 });
150
151 it(`deleting non-empty directory without recursive flag - fails`, function() {
152 return fs.saveFile(`${dirName}/_${dirName}/${fileName}`, content)
153 .then(() => matcher.expect([
154 {type: 'directoryCreated', fullPath:dirName},
155 {type: 'directoryCreated', fullPath:`${dirName}/_${dirName}`},
156 {type: 'fileCreated', fullPath:`${dirName}/_${dirName}/${fileName}`, newContent:content}]))
157 .then(() => expect(fs.deleteDirectory(`${dirName}/_${dirName}`)).to.be.rejectedWith(Error))
158 .then(() => matcher.expect([]));
159 });
160
161 it(`deleting non-empty directory with recursive flag`, function() {
162 const filePath = `${dirName}/_${dirName}/${fileName}`;
163 return fs.saveFile(filePath, content)
164 .then(() => matcher.expect([
165 {type: 'directoryCreated', fullPath:dirName},
166 {type: 'directoryCreated', fullPath:`${dirName}/_${dirName}`},
167 {type: 'fileCreated', fullPath:filePath, newContent:content}]))
168 .then(() => fs.deleteDirectory(dirName, true))
169 .then(() => matcher.expect([
170 {type: 'directoryDeleted', fullPath:dirName},
171 {type: 'fileDeleted', fullPath:filePath}
172 ]))
173 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([]))
174 .then(() => matcher.expect([]));
175 });
176
177 it(`deleting file which is actually a directory - fails`, function() {
178 const dirNameAsFileName = fileName;
179 return fs.ensureDirectory(dirNameAsFileName)
180 .then(() => matcher.expect([{type: 'directoryCreated', fullPath:dirNameAsFileName}]))
181 .then(() => expect(fs.deleteFile(dirNameAsFileName)).to.be.rejectedWith(Error))
182 .then(() => matcher.expect([]));
183 });
184
185 it(`deleting only one file`, function() {
186 return fs.saveFile(fileName, content)
187 .then(() => matcher.expect([{type: 'fileCreated', fullPath:fileName, newContent:content}]))
188 .then(() => fs.saveFile(`_${fileName}`, `_${content}`))
189 .then(() => matcher.expect([{type: 'fileCreated', fullPath:`_${fileName}`, newContent:`_${content}`}]))
190 .then(() => fs.deleteFile(`_${fileName}`))
191 .then(() => matcher.expect([{type: 'fileDeleted', fullPath:`_${fileName}`}]))
192 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([{fullPath:fileName, name:fileName, type:'file'}]))
193 .then(() => matcher.expect([]));
194 });
195
196 it(`deleting non existing file succeeds`, function() {
197 return fs.deleteFile(fileName)
198 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([]))
199 .then(() => matcher.expect([]));
200 });
201
202 it(`deleting non existing file (deep path) succeeds`, function() {
203 return fs.deleteFile(`${dirName}/${fileName}`)
204 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([]))
205 .then(() => matcher.expect([]));
206 });
207
208 it(`deleting ignored file succeeds`, function() {
209 return fs.deleteFile(ignoredFile)
210 .then(() => matcher.expect([]))
211 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([]));
212 });
213
214 it(`deleting ignored directory succeeds`, function() {
215 return fs.deleteDirectory(ignoredDir)
216 .then(() => matcher.expect([]))
217 .then(() => expect(fs.loadDirectoryTree()).to.eventually.have.property('children').eql([]));
218 });
219
220 it(`saving ignored file - fails`, function() {
221 return expect(fs.saveFile(ignoredFile, 'foo')).to.be.rejectedWith(Error);
222 });
223
224 it(`saving ignored dir - fails`, function() {
225 return expect(fs.ensureDirectory(ignoredDir)).to.be.rejectedWith(Error);
226 });
227
228 it(`loading existed ignored file - fails`, function() {
229 return fs.ensureDirectory(dirName)
230 .then(() => expect(fs.loadTextFile(ignoredFile)).to.be.rejectedWith(Error));
231 });
232
233 });
234}
235