UNPKG

pwabuilder-lib

Version:
652 lines (561 loc) 22.1 kB
'use strict'; var fs = require('fs'), http = require('http'), path = require('path'), url = require('url'); var should = require('should'); var manifestTools = require('../lib/manifestTools'), validationConstants = require('../lib/constants').validation; var manifestTypeDetector = require('../lib/manifestTools/manifestTypeDetector'); var responseFunction; var server = http.createServer(function (req, res) { if (responseFunction) { responseFunction(req, res); } else { res.writeHead(404); res.end(); } }); var assetsDirectory = path.join(__dirname, 'assets'); var inputFiles = { notExistingFile: path.join(assetsDirectory, 'notExistingFile.json'), invalidManifest: path.join(assetsDirectory, 'invalid.json'), invalidManifestFormat: path.join(assetsDirectory, 'invalidManifestFormat.json'), validManifest: path.join(assetsDirectory, 'manifest.json'), issue88Manifest: path.join(assetsDirectory, 'manifest_#88.json') }; var outputFiles = { invalidManifestPath: path.join(assetsDirectory, 'notExistingDirectory', 'notExistingFile.json'), validManifestPath: path.join(assetsDirectory, 'output-manifest.json') }; // configure test platforms var platformConfig = require('../test-assets/platformConfig'); platformConfig(); describe('Manifest Tools', function () { describe('getManifestFromFile()', function () { it('Should return an Error if path is invalid', function (done) { manifestTools.getManifestFromFile(inputFiles.notExistingFile, function (err){ should.exist(err); done(); }); }); it('Should return an Error if JSON format is invalid', function (done) { manifestTools.getManifestFromFile(inputFiles.invalidManifest, function (err){ should.exist(err); err.should.have.property('message', 'Invalid manifest format.'); done(); }); }); it('Should return an Error if manifest format is invalid', function (done) { manifestTools.getManifestFromFile(inputFiles.invalidManifestFormat, function (err){ should.exist(err); err.should.have.property('message', 'Unable to detect the input manifest format. Try specifying the correct format using the -f <format> option. Available formats are: w3c, chromeos, edgeextension.'); done(); }); }); it('Should return a manifest object if input manifest is valid', function (done) { manifestTools.getManifestFromFile(inputFiles.validManifest, function(err, manifestInfo){ should.not.exist(err); should.exist(manifestInfo); manifestInfo.should.have.property('content'); done(); }); }); }); describe('writeToFile()', function () { it('Should return an Error if manifest info is undefined', function (done) { manifestTools.writeToFile(undefined, outputFiles.invalidManifestPath, function (err){ should.exist(err); err.should.have.property('message', 'Manifest content is empty or invalid.'); done(); }); }); it('Should return an Error if content property is undefined', function (done) { manifestTools.writeToFile({ key: 'value' }, outputFiles.invalidManifestPath, function (err){ should.exist(err); err.should.have.property('message', 'Manifest content is empty or invalid.'); done(); }); }); it('Should return an Error if an error occurs while writing the file', function(done) { manifestTools.writeToFile({ content: { 'start_url': 'url' } }, outputFiles.invalidManifestPath, function(err){ should.exist(err); done(); }); }); it('Should write only the manifest information object content in file', function(done) { manifestTools.writeToFile({ content: { 'start_url': 'url' } }, outputFiles.validManifestPath, function(err){ should.not.exist(err); done(); }); }); after(function() { // runs after all tests in this block fs.exists(outputFiles.validManifestPath, function (exists) { if(exists) { fs.unlink(outputFiles.validManifestPath, function (err) { if (err) { throw err; } }); } }); }); }); describe('fetchManifestUrlFromSite()', function () { before(function () { server.listen(8042); }); it('Should return an Error if url is invalid', function(done) { responseFunction = function() { should.fail('This function should not be called in this test'); }; manifestTools.fetchManifestUrlFromSite('invalid url', function(err) { should.exist(err); err.should.have.property('message', 'Failed to retrieve manifest from site.'); done(); }); }); it('Should return an Error if server returns 404', function(done) { responseFunction = function(req, res) { res.writeHead(404); res.end(); }; manifestTools.fetchManifestUrlFromSite('http://localhost:8042/notfound', function(err) { should.exist(err); err.should.have.property('message', 'Failed to retrieve manifest from site.'); done(); }); }); it('Should return undefined if no manifest tag is found', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<!doctype>' + '<html>' + '<head>' + '<title>test</title>' + '</head>' + '<body></body>' + '</html>'); }; manifestTools.fetchManifestUrlFromSite('http://localhost:8042/urlWithoutManifestTag', function(err, manifestUrl) { should.not.exist(err); should.not.exist(manifestUrl); done(); }); }); it('Should return the manifest url if the manifest tag has a relative url', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<!doctype>' + '<html>' + '<head>' + '<title>test</title>' + '<link rel="manifest" href="manifest.json">' + '</head>' + '<body></body>' + '</html>'); }; manifestTools.fetchManifestUrlFromSite('http://localhost:8042/urlWithManifestTag', function(err, manifestUrl) { should.not.exist(err); should.exist(manifestUrl); manifestUrl.should.be.equal('http://localhost:8042/manifest.json'); done(); }); }); it('Should return the manifest url if the manifest tag contains other words', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<!doctype>' + '<html>' + '<head>' + '<title>test</title>' + '<link rel="something manifest another thing" href="manifest.json">' + '</head>' + '<body></body>' + '</html>'); }; manifestTools.fetchManifestUrlFromSite('http://localhost:8042/urlWithManifestTag', function(err, manifestUrl) { should.not.exist(err); should.exist(manifestUrl); manifestUrl.should.be.equal('http://localhost:8042/manifest.json'); done(); }); }); it('Should return the manifest url if the manifest tag has an absolute url', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<!doctype>' + '<html>' + '<head>' + '<title>test</title>' + '<link rel="manifest" href="http://www.contoso.com/manifest.json">' + '</head>' + '<body></body>' + '</html>'); }; manifestTools.fetchManifestUrlFromSite('http://localhost:8042/urlWithManifestTag', function(err, manifestUrl) { should.not.exist(err); should.exist(manifestUrl); manifestUrl.should.be.equal('http://www.contoso.com/manifest.json'); done(); }); }); afterEach(function () { responseFunction = undefined; }); after(function () { server.close(); }); }); describe('downloadManifestFromUrl()', function () { before(function () { server.listen(8042); }); it('Should return an Error if url is invalid', function(done) { responseFunction = function() { should.fail('This function should not be called in this test'); }; manifestTools.downloadManifestFromUrl('invalid url', function(err) { should.exist(err); err.should.have.property('message', 'Failed to download manifest data.'); done(); }); }); it('Should return an Error if server returns 404', function(done) { responseFunction = function(req, res) { res.writeHead(404); res.end(); }; manifestTools.downloadManifestFromUrl('http://localhost:8042/notfound', function(err) { should.exist(err); err.should.have.property('message', 'Failed to download manifest data.'); done(); }); }); it('Should return an Error if downloaded manifest is invalid', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('invalid json'); }; manifestTools.downloadManifestFromUrl('http://localhost:8042/invalidJson', function(err) { should.exist(err); err.should.have.property('message', 'Invalid manifest format.'); done(); }); }); it('Should return the manifest info object from a site', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({'start_url': 'http://www.contoso.com/'})); }; manifestTools.downloadManifestFromUrl('http://localhost:8042/validManifest.json', function(err, manifestInfo) { should.not.exist(err); should.exist(manifestInfo); manifestInfo.should.have.properties('content', 'format'); done(); }); }); afterEach(function () { responseFunction = undefined; }); after(function () { server.close(); }); }); describe('getManifestFromSite()', function () { before(function () { server.listen(8042); }); it('Should return an Error if url is invalid', function(done) { responseFunction = function() { should.fail('This function should not be called in this test'); }; manifestTools.getManifestFromSite('invalid url', function(err) { should.exist(err); err.should.have.property('message', 'Failed to retrieve manifest from site.'); done(); }); }); it('Should return an Error if server returns 404', function(done) { responseFunction = function(req, res) { res.writeHead(404); res.end(); }; manifestTools.getManifestFromSite('http://localhost:8042/notfound', function(err) { should.exist(err); err.should.have.property('message', 'Failed to retrieve manifest from site.'); done(); }); }); it('Should return the manifest info object from a site', function(done) { responseFunction = function(req, res) { var url_parts = url.parse(req.url); var route = url_parts.pathname; if (route === '/manifest.json') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({'start_url': 'http://www.contoso.com/'})); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<!doctype>' + '<html>' + '<head>' + '<title>test</title>' + '<link rel="manifest" href="http://localhost:8042/manifest.json">' + '</head>' + '<body></body>' + '</html>'); } }; manifestTools.getManifestFromSite('http://localhost:8042/urlWithManifestTag', function(err, manifestInfo) { should.not.exist(err); should.exist(manifestInfo); manifestInfo.should.have.properties('content', 'format'); manifestInfo.content.should.have.property('start_url', 'http://www.contoso.com/'); done(); }); }); it('Should create a manifest info object if no manifest tag is found', function(done) { responseFunction = function(req, res) { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<!doctype>' + '<html>' + '<head>' + '<title>test</title>' + '</head>' + '<body></body>' + '</html>'); }; var siteUrl ='http://localhost:8042/urlWithoutManifestTag'; manifestTools.getManifestFromSite(siteUrl, function(err, manifestInfo) { should.not.exist(err); should.exist(manifestInfo); manifestInfo.should.have.properties('content', 'format'); manifestInfo.content.should.have.property('start_url', '/urlWithoutManifestTag'); done(); }); }); afterEach(function () { responseFunction = undefined; }); after(function () { server.close(); }); }); describe('convertTo()', function () { it('Should return an Error if manifest info is undefined', function(done) { manifestTools.convertTo(undefined, 'W3C', function(err){ should.exist(err); err.should.have.property('message', 'Manifest content is empty or not initialized.'); done(); }); }); it('Should return an Error if content property is undefined', function(done) { manifestTools.convertTo({ key: 'value' }, 'W3C', function(err) { should.exist(err); err.should.have.property('message', 'Manifest content is empty or not initialized.'); done(); }); }); it('Should return the same object if the format is the same', function (done) { var manifestInfo = { content: { 'start_url': 'url' }, format: 'W3C' }; manifestTools.convertTo(manifestInfo, 'W3C', function(err, result) { should.not.exist(err); result.should.be.exactly(manifestInfo); done(); }); }); it('Should use w3c as default format', function (done) { var manifestInfo = { content: { 'start_url': 'url' } }; manifestTools.convertTo(manifestInfo, undefined, function(err, result) { should.not.exist(err); result.should.be.exactly(manifestInfo); result.should.have.property('format', 'w3c'); done(); }); }); it('Should return an Error if input format is invalid', function(done) { var manifestInfo = { content: { 'start_url': 'url' }, format: 'invalid format' }; manifestTools.convertTo(manifestInfo, 'W3C', function(err) { should.exist(err); err.should.have.property('message', 'Manifest format is not recognized.'); done(); }); }); it('Should return an Error if output format is invalid', function(done) { var manifestInfo = { content: { 'start_url': 'url' }, format: 'W3C' }; manifestTools.convertTo(manifestInfo, 'invalid format', function(err) { should.exist(err); err.should.have.property('message', 'Manifest format is not recognized.'); done(); }); }); it('Should convert from Chrome OS manifest format to W3C manifest format', function() { var manifestInfo = { content: { 'name': 'Sample', 'description': 'Chrome Web App Sample', 'version': '0.0.1', 'app': { 'launch': { 'web_url': 'http://example.com' } }, 'icons': { '16': 'icon-16.png', '48': 'icon-48.png', '128': 'icon-128.png' }, 'permissions': [ 'notifications', 'background' ] }, format: 'chromeos' }; manifestTools.convertTo(manifestInfo, 'W3C', function(err, convertedManifest) { var result = manifestTypeDetector.detect(convertedManifest.content); should.exist(result); result.should.be.equal('w3c'); }); }); it('Convert from chromeOS to W3C', function (done) { var manifestInfo = { content: { 'name': 'Google Mail', 'description': 'Read your gmail', 'version': '1', 'app': { 'urls': [ '*://mail.google.com/mail/', '*://www.google.com/mail/' ], 'launch': { 'web_url': 'http://mail.google.com/mail/' } }, 'icons': { '64': 'icon_64.png', '128': 'icon_128.png' }, 'permissions': [ 'unlimitedStorage', 'notifications'] }, format: 'chromeos' }; var expectedManifestInfo = { content: { 'name': 'Google Mail', 'start_url': 'http://mail.google.com/mail/', 'icons': [{ 'src': 'icon_64.png', 'sizes': '64x64' }, { 'src': 'icon_128.png', 'sizes': '128x128' }], mjs_api_access: [ {'match': 'http://mail.google.com/mail/*', 'platform': 'chrome', 'access': 'unlimitedStorage, notifications' }, {'match': '*://mail.google.com/mail/*', 'platform': 'chrome', 'access': 'unlimitedStorage, notifications' }, {'match': '*://www.google.com/mail/*', 'platform': 'chrome', 'access': 'unlimitedStorage, notifications' } ], mjs_extended_scope: [ '*://mail.google.com/mail/*', '*://www.google.com/mail/*' ] }, format: 'w3c' }; manifestTools.convertTo(manifestInfo, 'W3C', function(err, result) { should.not.exist(err); result.should.be.eql(expectedManifestInfo); done(); }); }); }); describe('validateManifest()', function () { it('Should validate only the general rules if no platforms are passed', function (done) { var manifestInfo = { content: { 'name': 'Google Mail', 'start_url': 'http://mail.google.com/mail/', 'icons': [{ 'src': 'icon_64.png', 'sizes': '64x64' }, { 'src': 'icon_128.png', 'sizes': '128x128' }] }, format: 'w3c' }; manifestTools.validateManifest(manifestInfo, undefined, function(){ done(); }); }); it('Issue #88', function (done) { manifestTools.getManifestFromFile(inputFiles.issue88Manifest, function (err, manifestObject){ var w3cmanifest = { content: manifestObject, format: 'w3c'}; manifestTools.validateAndNormalizeStartUrl ('http://thishereweb.com', w3cmanifest.content, function(err){ should.not.exist(err); done(); }); }); }); it('Should validate platforms that are passed as parameter', function (done) { var manifestInfo = { content: { 'name': 'Google Mail', 'start_url': 'http://example.com/', }, format: 'w3c' }; manifestTools.validateManifest(manifestInfo, ['ios', 'windows', 'firefox', 'chrome', 'android'], function() { done(); }); }); it('Should validate short name is required', function (done) { var manifestInfo = { content: { 'short_name': '', 'start_url': 'http://example.com/' }, format: 'w3c' }; var expectedValidation = { 'description': 'A short name for the application is required', 'platform': validationConstants.platforms.all, 'level': validationConstants.levels.error, 'member': validationConstants.manifestMembers.short_name, 'code': validationConstants.codes.requiredValue }; manifestTools.validateManifest(manifestInfo, ['ios', 'windows', 'firefox', 'chrome', 'android'], function (err, validationResults) { should.not.exist(err); validationResults.should.containEql(expectedValidation); done(); }); }); it('Should validate start url is required', function (done) { var manifestInfo = { content: { 'short_name': 'MyApp', 'start_url': '' }, format: 'w3c' }; var expectedValidation = { 'description': 'The start URL for the target web site is required', 'platform': validationConstants.platforms.all, 'level': validationConstants.levels.error, 'member': validationConstants.manifestMembers.start_url, 'code': validationConstants.codes.requiredValue }; manifestTools.validateManifest(manifestInfo, ['ios', 'windows', 'firefox', 'chrome', 'android'], function (err, validationResults) { should.not.exist(err); validationResults.should.containEql(expectedValidation); done(); }); }); }); });