Skip to content

Commit b667c14

Browse files
authored
Merge pull request #2 from bendemboski/fix-index
Fix index require path :(
2 parents 3bfa6e7 + 423a84b commit b667c14

File tree

6 files changed

+188
-40
lines changed

6 files changed

+188
-40
lines changed

index.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
const createHandler = require('./lib/create-handler');
1+
const { join } = require('path');
2+
const createHandler = require('./lib/handler');
23

34
function requiredParam(param, errorMessage) {
45
if (!param) {
@@ -16,8 +17,7 @@ function requiredParam(param, errorMessage) {
1617
* @param {Object} options.protocol electron.protocol
1718
* @param {String} options.name name of your protocol, defaults to `serve`
1819
* @param {String} options.endpoint endpoint of your protocol, defaults to `dist`
19-
* @param {String} options.directoryIndexFile directory index. usally the default, `index.html`
20-
* @param {String} options.indexPath defaults to cwd + directoryIndexFile
20+
* @param {String} options.indexPath defaults to 'index.html' in cwd
2121
*
2222
* @return {String} name of your protocol
2323
*/
@@ -27,15 +27,16 @@ module.exports = function protocolServe({
2727
protocol,
2828
name = 'serve',
2929
endpoint = 'dist',
30-
directoryIndexFile = 'index.html',
3130
indexPath = undefined,
3231
}) {
3332
requiredParam(cwd, 'cwd must be specified, should be a valid path');
3433
requiredParam(protocol, 'protocol must be specified, should be electron.protocol');
3534
requiredParam(app, 'app must be specified, should be electron.app');
3635

36+
indexPath = indexPath || join(cwd, 'index.html');
37+
3738
app.on('ready', () => {
38-
const options = { cwd, name, endpoint, directoryIndexFile, indexPath };
39+
const options = { cwd, name, endpoint, indexPath };
3940
protocol.registerFileProtocol(name, createHandler(options), error => {
4041
if (error) {
4142
console.error('Failed to register protocol');

lib/handler.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,46 @@
11
const { join } = require('path');
22
const fs = require('fs');
3-
const url = require('url');
3+
const { parse: urlParse } = require('url');
44

55
module.exports = function createHandler({
66
cwd,
77
name,
88
endpoint,
9-
directoryIndexFile,
109
indexPath,
1110
}) {
12-
indexPath = indexPath || join(cwd, directoryIndexFile);
1311
const cache = {};
1412

15-
return (request, callback) => {
13+
return ({ url }, callback) => {
1614
let {
1715
host,
1816
pathname,
19-
} = url.parse(request.url);
17+
} = urlParse(url);
2018

2119
pathname = pathname || '';
2220

2321
if (host !== endpoint) {
2422
callback({ error: `Unrecognized ${name}:// endpoint: '${host}'` });
25-
23+
2624
return;
2725
}
2826

2927
const pathSegments = pathname.split('/').filter(segment => segment !== '');
30-
31-
if (pathSegments.length === 0) {
32-
pathSegments.push(directoryIndexFile);
33-
}
34-
3528
const filepath = join(cwd, ...pathSegments);
3629

3730
// Basic request caching
3831
if (!cache[url]) {
3932
try {
4033
fs.accessSync(filepath);
4134

42-
cache[url] = filepath;
35+
if (fs.statSync(filepath).isFile()) {
36+
cache[url] = filepath;
37+
}
4338
} catch (err) {
4439
//
4540
}
4641
}
4742

48-
// redirect unmet requests to directoryIndexFile
43+
// redirect unmet requests to indexPath
4944
callback({ path: cache[url] || indexPath });
5045
};
5146
};

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@
1818
"mocha": "^3.2.0",
1919
"sinon": "^1.17.7"
2020
},
21-
"dependencies": {}
21+
"dependencies": {
22+
"mock-require": "^2.0.1"
23+
}
2224
}

tests/unit/handler-test.js

+51-21
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,26 @@ const sinon = require('sinon');
33
const Promise = require('bluebird');
44
const fs = require('fs');
55
const { join, resolve } = require('path');
6-
const createHandler = require('../../lib/handler');
6+
const subject = require('../../lib/handler');
77

88
describe('handler', () => {
99
let sandbox;
1010
let mockFiles;
11+
let mockDirs;
1112

1213
before(() => {
1314
sandbox = sinon.sandbox.create();
1415
// Stub accessSync to act like only files in mockFiles exist
1516
sandbox.stub(fs, 'accessSync', path => {
16-
if (mockFiles.indexOf(path) === -1) {
17+
if (mockFiles.indexOf(path) === -1 && mockDirs.indexOf(path) === -1) {
1718
throw new Error('Doesn\'t exist');
1819
}
1920
});
21+
sandbox.stub(fs, 'statSync', path => ({
22+
isFile() {
23+
return mockFiles.indexOf(path) !== -1;
24+
},
25+
}));
2026
});
2127

2228
after(() => {
@@ -25,19 +31,22 @@ describe('handler', () => {
2531

2632
beforeEach(() => {
2733
mockFiles = [];
34+
mockDirs = [];
2835
});
2936

30-
// Create a handler with the specified options and call it with the given URL
31-
function handlerExec(url, options = {}) {
32-
return new Promise((resolve, reject) => {
33-
let handler = createHandler(Object.assign({
34-
cwd: '.',
35-
name: 'serve',
36-
endpoint: 'dist',
37-
directoryIndexFile: 'index.html',
38-
indexPath: undefined,
39-
}, options));
37+
// Create a handler with the specified options
38+
function createHandler(options) {
39+
return subject(Object.assign({
40+
cwd: '.',
41+
name: 'serve',
42+
endpoint: 'dist',
43+
indexPath: join('.', 'index.html'),
44+
}, options));
45+
}
4046

47+
// Call the handler with the given URL
48+
function callHandler(handler, url) {
49+
return new Promise((resolve, reject) => {
4150
handler({ url }, ({ path, error }) => {
4251
if (path !== undefined) {
4352
resolve(path);
@@ -48,32 +57,47 @@ describe('handler', () => {
4857
});
4958
}
5059

60+
// Create a handler with the specified options and call it with the given URL
61+
function handlerExec(url, options = {}) {
62+
return callHandler(createHandler(options), url);
63+
}
64+
5165
it('works', () => {
66+
mockDirs.push('.');
5267
mockFiles.push('script.js');
5368
return handlerExec('serve://dist/script.js').then(path => {
5469
assert.equal(path, 'script.js');
5570
});
5671
});
5772

58-
it('serves directoryIndexFile from the root', () => {
59-
mockFiles.push('foo.html');
60-
return handlerExec('serve://dist', {
61-
directoryIndexFile: 'foo.html',
73+
it('works with multiple requests', () => {
74+
mockDirs.push('.');
75+
mockFiles.push('script1.js');
76+
mockFiles.push('script2.js');
77+
78+
let handler = createHandler();
79+
return callHandler(handler, 'serve://dist/script1.js').then(path => {
80+
assert.equal(path, 'script1.js');
81+
82+
return callHandler(handler, 'serve://dist/script2.js');
6283
}).then(path => {
63-
assert.equal(path, 'foo.html');
84+
assert.equal(path, 'script2.js');
6485
});
6586
});
6687

67-
it('serves directoryIndexFile for missing files', () => {
88+
it('serves indexPath from the root', () => {
89+
mockDirs.push('.');
6890
mockFiles.push('foo.html');
69-
return handlerExec('serve://dist/missing.js', {
70-
directoryIndexFile: 'foo.html',
91+
return handlerExec('serve://dist', {
92+
cwd: '.',
93+
indexPath: join('.', 'foo.html'),
7194
}).then(path => {
72-
assert.equal(path, 'foo.html');
95+
assert.equal(path, join('.', 'foo.html'));
7396
});
7497
});
7598

7699
it('respects relative cwd', () => {
100+
mockDirs.push(join('foo', 'bar'));
77101
mockFiles.push(join('foo', 'bar', 'script.js'));
78102
return handlerExec('serve://dist/script.js', {
79103
cwd: join('foo', 'bar'),
@@ -83,6 +107,7 @@ describe('handler', () => {
83107
});
84108

85109
it('respects absolute cwd', () => {
110+
mockDirs.push(resolve('foo', 'bar'));
86111
mockFiles.push(resolve('foo', 'bar', 'script.js'));
87112
return handlerExec('serve://dist/script.js', {
88113
cwd: resolve('foo', 'bar'),
@@ -92,6 +117,7 @@ describe('handler', () => {
92117
});
93118

94119
it('respects endpoint', () => {
120+
mockDirs.push('.');
95121
mockFiles.push('script.js');
96122
return handlerExec('serve://custom/script.js', {
97123
endpoint: 'custom',
@@ -101,22 +127,26 @@ describe('handler', () => {
101127
});
102128

103129
it('respects indexPath for missing files', () => {
130+
mockDirs.push('bar');
104131
mockFiles.push(join('foo', 'bar.html'));
105132
return handlerExec('serve://dist/missing.js', {
133+
cwd: 'bar',
106134
indexPath: join('foo', 'bar.html'),
107135
}).then(path => {
108136
assert.equal(path, join('foo', 'bar.html'));
109137
});
110138
});
111139

112140
it('ignores hashes', () => {
141+
mockDirs.push('.');
113142
mockFiles.push('script.js');
114143
return handlerExec('serve://dist/script.js#hash').then(path => {
115144
assert.equal(path, 'script.js');
116145
});
117146
});
118147

119148
it('ignores query params', () => {
149+
mockDirs.push('.');
120150
mockFiles.push('script.js');
121151
return handlerExec('serve://dist/script.js?query=param').then(path => {
122152
assert.equal(path, 'script.js');

tests/unit/index-test.js

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
const { assert } = require('chai');
2+
const mock = require('mock-require');
3+
const { join } = require('path');
4+
5+
describe('index', () => {
6+
let app;
7+
let protocol;
8+
let onAppReady;
9+
let protocolName;
10+
let handlerOptions;
11+
12+
function register(options) {
13+
require('../..')(Object.assign({
14+
cwd: '.',
15+
app,
16+
protocol,
17+
}, options));
18+
}
19+
20+
before(() => {
21+
mock('../../lib/handler', options => handlerOptions = options);
22+
});
23+
24+
after(() => {
25+
mock.stop('../../lib/handler');
26+
});
27+
28+
beforeEach(() => {
29+
app = {
30+
on(evt, cb) {
31+
if (evt === 'ready') {
32+
onAppReady = cb;
33+
}
34+
},
35+
};
36+
37+
protocol = {
38+
registerFileProtocol(name/*, handler, errorHandler*/) {
39+
protocolName = name;
40+
},
41+
};
42+
});
43+
44+
it('works', () => {
45+
register();
46+
assert.ok(onAppReady);
47+
onAppReady();
48+
49+
assert.equal(protocolName, 'serve');
50+
assert.deepEqual(handlerOptions, {
51+
cwd: '.',
52+
name: 'serve',
53+
endpoint: 'dist',
54+
indexPath: join('.', 'index.html'),
55+
});
56+
});
57+
58+
it('works with a custom cwd', () => {
59+
register({
60+
cwd: join('foo', 'bar'),
61+
});
62+
assert.ok(onAppReady);
63+
onAppReady();
64+
65+
assert.equal(protocolName, 'serve');
66+
assert.deepEqual(handlerOptions, {
67+
cwd: join('foo', 'bar'),
68+
name: 'serve',
69+
endpoint: 'dist',
70+
indexPath: join('foo', 'bar', 'index.html'),
71+
});
72+
});
73+
74+
it('works with non-default arguments', () => {
75+
register({
76+
cwd: join('my', 'old'),
77+
name: 'friend',
78+
endpoint: 'so',
79+
indexPath: join('we', 'meet', 'again.html'),
80+
});
81+
assert.ok(onAppReady);
82+
onAppReady();
83+
84+
assert.equal(protocolName, 'friend');
85+
assert.deepEqual(handlerOptions, {
86+
cwd: join('my', 'old'),
87+
name: 'friend',
88+
endpoint: 'so',
89+
indexPath: join('we', 'meet', 'again.html'),
90+
});
91+
});
92+
93+
it('required a cwd', () => {
94+
assert.throws(() => register({ cwd: undefined }));
95+
});
96+
97+
it('required an app', () => {
98+
assert.throws(() => register({ app: undefined }));
99+
});
100+
101+
it('required a protocol', () => {
102+
assert.throws(() => register({ protocol: undefined }));
103+
});
104+
});

0 commit comments

Comments
 (0)