Skip to content

Commit

Permalink
MAID-2144 (maidsafe-archive#129)
Browse files Browse the repository at this point in the history
* first fetches index.html by default

* passes subdirectory fallback

* CI fixes

* CI fix

* checks for leading slash

* CI fix

* explains additional catch block and adds test cases

* const index.html

* increase coverage
  • Loading branch information
hunterlester authored and bochaco committed Aug 18, 2017
1 parent 001eda9 commit 822c355
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 9 deletions.
33 changes: 26 additions & 7 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,20 @@ class SAFEApp extends EventEmitter {
* @returns {Promise<File>} the file object found for that URL
*/
webFetch(url) {
if (!url) return Promise.reject(new Error('No URL provided.'));
const parsedUrl = parseUrl(url);
if (!parsedUrl) return Promise.reject(new Error('Not a proper URL!'));

const hostname = parsedUrl.hostname;
const path = parsedUrl.pathname || '';
let path = parsedUrl.pathname || '';

const tokens = path.split('/');
if (!tokens[tokens.length - 1] && tokens.length > 1) { tokens.pop(); }

if (!tokens[tokens.length - 1].split('.')[1]) {
tokens.push(consts.INDEX_HTML);
path = tokens.join('/');
}

// lets' unpack
const hostParts = hostname.split('.');
const lookupName = hostParts.pop(); // last one is 'domain'
Expand All @@ -125,13 +134,23 @@ class SAFEApp extends EventEmitter {
// Error codes -305 and -301 correspond to 'NfsError::FileNotFound'
if (err.code === -305 || err.code === -301) {
let newPath;
if (!path || !path.length) {
newPath = '/index.html';
} else if (path[path.length - 1] === '/') {
newPath = `${path}index.html`;
if (path[path.length - 1] === '/') {
newPath = `${path}${consts.INDEX_HTML}`;
} else if (path[0] === '/') {
// directly try the non-slash version
return emulation.fetch(path.slice(1, path.length));
return emulation.fetch(path.slice(1, path.length))
.catch(() => {
// NOTE: This catch block handles the cases where a user intends/
// to fetch a path without index.html
// For clarification, comment out lines 132 through 143/
// then run mocha in ../test/browsing.js to see which/
// cases fail.
const pathArray = path.split('/');
if (pathArray[pathArray.length - 1] === consts.INDEX_HTML) {
pathArray.pop();
return emulation.fetch(pathArray.join('/'));
}
});
}

if (newPath) {
Expand Down
4 changes: 3 additions & 1 deletion src/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ const SYSTEM_URI_LIB_FILENAME = {

const MD_META_KEY = '_metadata';

const INDEX_HTML = 'index.html';

module.exports = {
LIB_FILENAME,
SYSTEM_URI_LIB_FILENAME,
Expand All @@ -66,6 +68,6 @@ module.exports = {
FILE_READ_FROM_BEGIN,
FILE_READ_TO_END,
MD_META_KEY,

INDEX_HTML,
inTesting
};
27 changes: 27 additions & 0 deletions test/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const h = require('./helpers');

const createTestApp = h.createTestApp;
const createAuthenticatedTestApp = h.createAuthenticatedTestApp;
const createTestAppWithNetworkCB = h.createTestAppWithNetworkCB;
const createTestAppWithOptions = h.createTestAppWithOptions;

describe('Smoke test', () => {
it('unauthorised connection', () => {
Expand All @@ -20,6 +22,31 @@ describe('Smoke test', () => {
.then((resp) => should(resp.uri).startWith('safe-auth:'));
});

it('can take a network state callback', () => {
const networkCb = (state) => `NETWORK STATE: ${state}`;
const app = createTestAppWithNetworkCB(
null,
networkCb
);
should.exist(app._networkStateCallBack); // eslint-disable-line no-underscore-dangle
});

it('can take an options object to configure logging and scheme registration', () => {
const optionsObject = {
log: false,
registerScheme: false
};
const app = createTestAppWithOptions(
null,
optionsObject
);

const optionsObjectsEqual = Object.keys(app.options).every(
(option) => app.options[option] === optionsObject[option]
);
should(optionsObjectsEqual).be.true();
});

it('should build some containers uri', () => {
const app = createTestApp();
return app.auth.genContainerAuthUri({ private: ['Insert'] })
Expand Down
4 changes: 4 additions & 0 deletions test/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const createAuthenticatedTestApp = h.createAuthenticatedTestApp;
describe('Access Container', () => {
const app = createAuthenticatedTestApp('_test_scope', { _public: ['Read'], _publicNames: ['Read', 'Insert'] });

it('should have a connection object after completing app authentication', () => {
should.exist(app.connection);
});

it('is authenticated for testing', () => {
should(app.auth.registered).be.true();
});
Expand Down
51 changes: 51 additions & 0 deletions test/browsing.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ function createRandomPrivateServiceDomain(content, path, service) {
}

describe('Browsing', () => {
it('returns rejected promise if no url is provided', function test() {
this.timeout(20000);
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
return createRandomDomain(content, '', '')
.then(() => createAnonTestApp()
.then((app) => {
should(app.webFetch()).be.rejected();
}
));
});

it('fetch content', function test() {
this.timeout(20000);
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
Expand Down Expand Up @@ -151,6 +162,46 @@ describe('Browsing', () => {
));
});

it('/my.folder/index.html', function test() {
this.timeout(20000);
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
return createRandomDomain(content, '/my.folder/index.html', '')
.then((domain) => createAnonTestApp()
.then((app) => app.webFetch(`safe://${domain}/my.folder/index.html`)
.then((co) => should(co.toString()).equal(content))
));
});

it('/my.folder/', function test() {
this.timeout(20000);
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
return createRandomDomain(content, '/my.folder/index.html', '')
.then((domain) => createAnonTestApp()
.then((app) => app.webFetch(`safe://${domain}/my.folder/`)
.then((co) => should(co.toString()).equal(content))
));
});

it('/path/my.file', function test() {
this.timeout(20000);
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
return createRandomDomain(content, '/path/my.file', '')
.then((domain) => createAnonTestApp()
.then((app) => app.webFetch(`safe://${domain}/path/my.file`)
.then((co) => should(co.toString()).equal(content))
));
});

it('trailing slash after domain', function test() {
this.timeout(20000);
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
return createRandomDomain(content, '/index.html', 'www')
.then((domain) => createAnonTestApp()
.then((app) => app.webFetch(`safe://${domain}/`)
.then((co) => should(co.toString()).equal(content))
));
});

describe('errors', () => {
const content = `hello world, on ${Math.round(Math.random() * 100000)}`;
let domain; // eslint-disable-line no-unused-vars
Expand Down
22 changes: 21 additions & 1 deletion test/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ function createTestApp(scope) {
}, null, { log: false }));
}

function createTestAppWithNetworkCB(scope, networkCB) {
return h.autoref(new App({
id: 'net.maidsafe.test.javascript.id',
name: 'JS Test',
vendor: 'MaidSafe Ltd.',
scope
}, networkCB, { log: false }));
}

function createTestAppWithOptions(scope, options) {
return h.autoref(new App({
id: 'net.maidsafe.test.javascript.id',
name: 'JS Test',
vendor: 'MaidSafe Ltd.',
scope
}, null, options));
}

function createAnonTestApp(scope) {
const app = createTestApp(scope);
return app.auth.loginForTest();
Expand All @@ -40,5 +58,7 @@ module.exports = {
createAuthenticatedTestApp,
createRandomXorName,
createRandomSecKey,
createRandomNonce
createRandomNonce,
createTestAppWithNetworkCB,
createTestAppWithOptions
};

0 comments on commit 822c355

Please sign in to comment.