Skip to content

Commit

Permalink
jest-haste-map: simplify watch-mode test structure (#3623)
Browse files Browse the repository at this point in the history
* jest-haste-map: simplify watch-mode test structure, first step

* jest-haste-map: simplify watch-mode test structure, final step
  • Loading branch information
jeanlauliac authored and cpojer committed May 23, 2017
1 parent 9fed66e commit 51fe8ae
Showing 1 changed file with 94 additions and 187 deletions.
281 changes: 94 additions & 187 deletions packages/jest-haste-map/src/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -662,196 +662,103 @@ describe('HasteMap', () => {
);
});

it('watches for file system changes', done => {
const hasteMap = new HasteMap(
Object.assign({}, defaultConfig, {
watch: true,
}),
);
describe('file system changes processing', () => {
function waitForItToChange(hasteMap) {
return new Promise((resolve, reject) => {
hasteMap.once('change', resolve);
});
}

function mockDeleteFile(dirPath, filePath) {
const e = mockEmitters[dirPath];
e.emit('all', 'delete', filePath, dirPath, undefined);
}

const addErrorHandler = fn => {
return function() {
function hm_it(title, fn) {
it(title, async () => {
const watchConfig = Object.assign({}, defaultConfig, {watch: true});
const hm = new HasteMap(watchConfig);
await hm.build();
try {
fn.apply(null, arguments);
} catch (error) {
hasteMap.end();
done.fail(error);
await fn(hm);
} finally {
hm.end();
}
};
};
});
}

hasteMap
.build()
.then(({hasteFS: initialHasteFS, moduleMap: initialModuleMap}) => {
const filePath = '/fruits/banana.js';
expect(initialHasteFS.getModuleName(filePath)).toBeDefined();
expect(initialModuleMap.getModule('Banana')).toBe(filePath);

const next = () => {
if (!tests.length) {
hasteMap.end();
done();
return;
}

tests.shift()();
};

const statObject = {mtime: {getTime: () => 45}};
const tests = [
() => {
// Tests that the change event works correctly.
mockEmitters['/fruits'].emit(
'all',
'delete',
'banana.js',
'/fruits',
undefined,
);
mockEmitters['/fruits'].emit(
'all',
'delete',
'banana.js',
'/fruits',
undefined,
);

hasteMap.once(
'change',
addErrorHandler(({eventsQueue, hasteFS, moduleMap}) => {
expect(eventsQueue).toHaveLength(1);

expect(eventsQueue).toEqual([
{
filePath,
stat: undefined,
type: 'delete',
},
]);
// Verify we didn't change the original map.
expect(initialHasteFS.getModuleName(filePath)).toBeDefined();
expect(initialModuleMap.getModule('Banana')).toBe(filePath);

expect(hasteFS.getModuleName(filePath)).toBeNull();
expect(moduleMap.getModule('Banana')).toBeNull();

next();
}),
);
},
() => {
// Ensures the event queue can receive multiple events.
mockFs['/fruits/tomato.js'] = [
'/**',
' * @providesModule Tomato',
' */',
].join('\n');
mockFs['/fruits/pear.js'] = [
'/**',
' * @providesModule Kiwi',
' */',
].join('\n');

mockEmitters['/fruits'].emit(
'all',
'add',
'tomato.js',
'/fruits',
statObject,
);
mockEmitters['/fruits'].emit(
'all',
'change',
'pear.js',
'/fruits',
statObject,
);

hasteMap.once(
'change',
addErrorHandler(({eventsQueue, hasteFS, moduleMap}) => {
expect(eventsQueue).toEqual([
{
filePath: '/fruits/tomato.js',
stat: statObject,
type: 'add',
},
{
filePath: '/fruits/pear.js',
stat: statObject,
type: 'change',
},
]);

expect(
hasteFS.getModuleName('/fruits/tomato.js'),
).toBeDefined();
expect(moduleMap.getModule('Tomato')).toBeDefined();
expect(moduleMap.getModule('Pear')).toBeNull();
expect(moduleMap.getModule('Kiwi')).toBe('/fruits/pear.js');
next();
}),
);
},
() => {
// Does not emit duplicate change events.
mockEmitters['/fruits'].emit(
'all',
'change',
'tomato.js',
'/fruits',
statObject,
);
mockEmitters['/fruits'].emit(
'all',
'change',
'tomato.js',
'/fruits',
statObject,
);
hasteMap.once(
'change',
addErrorHandler(({eventsQueue, hasteFS, moduleMap}) => {
expect(eventsQueue).toHaveLength(1);
next();
}),
);
},
() => {
// Emits a change even if a file in node_modules has changed.
mockEmitters['/fruits'].emit(
'all',
'add',
'apple.js',
'/fruits/node_modules/',
statObject,
);
hasteMap.once(
'change',
addErrorHandler(({eventsQueue, hasteFS, moduleMap}) => {
const filePath = '/fruits/node_modules/apple.js';
expect(eventsQueue).toHaveLength(1);
expect(eventsQueue).toEqual([
{
filePath,
stat: statObject,
type: 'add',
},
]);

expect(hasteFS.getModuleName(filePath)).toBeDefined();
next();
}),
);
},
];

next();
})
.catch(
addErrorHandler(error => {
throw error;
}),
);
hm_it('provides a new set of hasteHS and moduleMap', async hm => {
const initialResult = await hm.build();
const filePath = '/fruits/banana.js';
expect(initialResult.hasteFS.getModuleName(filePath)).toBeDefined();
expect(initialResult.moduleMap.getModule('Banana')).toBe(filePath);
mockDeleteFile('/fruits', 'banana.js');
mockDeleteFile('/fruits', 'banana.js');
const {eventsQueue, hasteFS, moduleMap} = await waitForItToChange(hm);
expect(eventsQueue).toHaveLength(1);
const deletedBanana = {filePath, stat: undefined, type: 'delete'};
expect(eventsQueue).toEqual([deletedBanana]);
// Verify we didn't change the original map.
expect(initialResult.hasteFS.getModuleName(filePath)).toBeDefined();
expect(initialResult.moduleMap.getModule('Banana')).toBe(filePath);
expect(hasteFS.getModuleName(filePath)).toBeNull();
expect(moduleMap.getModule('Banana')).toBeNull();
});

const MOCK_STAT = {mtime: {getTime: () => 45}};

hm_it('handles several change events at once', async hm => {
mockFs['/fruits/tomato.js'] = [
'/**',
' * @providesModule Tomato',
' */',
].join('\n');
mockFs['/fruits/pear.js'] = [
'/**',
' * @providesModule Kiwi',
' */',
].join('\n');
const e = mockEmitters['/fruits'];
e.emit('all', 'add', 'tomato.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'pear.js', '/fruits', MOCK_STAT);
const {eventsQueue, hasteFS, moduleMap} = await waitForItToChange(hm);
expect(eventsQueue).toEqual([
{
filePath: '/fruits/tomato.js',
stat: MOCK_STAT,
type: 'add',
},
{
filePath: '/fruits/pear.js',
stat: MOCK_STAT,
type: 'change',
},
]);
expect(hasteFS.getModuleName('/fruits/tomato.js')).not.toBeNull();
expect(moduleMap.getModule('Tomato')).toBeDefined();
expect(moduleMap.getModule('Pear')).toBeNull();
expect(moduleMap.getModule('Kiwi')).toBe('/fruits/pear.js');
});

hm_it('does not emit duplicate change events', async hm => {
const e = mockEmitters['/fruits'];
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT);
e.emit('all', 'change', 'tomato.js', '/fruits', MOCK_STAT);
const {eventsQueue} = await waitForItToChange(hm);
expect(eventsQueue).toHaveLength(1);
});

hm_it(
'emits a change even if a file in node_modules has changed',
async hm => {
const e = mockEmitters['/fruits'];
e.emit('all', 'add', 'apple.js', '/fruits/node_modules/', MOCK_STAT);
const {eventsQueue, hasteFS} = await waitForItToChange(hm);
const filePath = '/fruits/node_modules/apple.js';
expect(eventsQueue).toHaveLength(1);
expect(eventsQueue).toEqual([{filePath, stat: MOCK_STAT, type: 'add'}]);
expect(hasteFS.getModuleName(filePath)).toBeDefined();
},
);
});
});

0 comments on commit 51fe8ae

Please sign in to comment.