From 15939a7ae93574c42f99e7858debf99d6c30d454 Mon Sep 17 00:00:00 2001 From: Andrew Connell Date: Thu, 3 Sep 2015 16:23:39 -0400 Subject: [PATCH 1/6] added ability to select Office products where addin is supported [issue#14](/OfficeDev/generator-office/issues/14) --- generators/app/index.js | 44 +++++++++ generators/content/index.js | 88 +++++++++++++++++- .../content/templates/common/manifest.xml | 3 - generators/taskpane/index.js | 89 ++++++++++++++++++- .../taskpane/templates/common/manifest.xml | 4 - package.json | 7 +- test/app.js | 3 + test/content/existingproj-html.js | 68 +++++++++++++- test/content/existingproj-manifestonly.js | 65 ++++++++++++++ test/content/existingproj-ng.js | 74 +++++++++++++-- test/content/newproj-html.js | 65 ++++++++++++++ test/content/newproj-manifestonly.js | 65 ++++++++++++++ test/content/newproj-ng.js | 64 +++++++++++++ test/taskpane/existingproj-html.js | 66 +++++++++++++- test/taskpane/existingproj-manifestonly.js | 67 +++++++++++++- test/taskpane/existingproj-ng.js | 70 ++++++++++++++- test/taskpane/newproj-html.js | 67 +++++++++++++- test/taskpane/newproj-manifestonly.js | 64 +++++++++++++ test/taskpane/newproj-ng.js | 66 +++++++++++++- tsd.json | 3 + 20 files changed, 1014 insertions(+), 28 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index c733cee4..8529ac16 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -35,6 +35,12 @@ module.exports = generators.Base.extend({ required: false }); + this.option('clients', { + type: String, + desc: 'Office client product that can host the add-in', + required: false + }); + }, // constructor() /** @@ -116,6 +122,41 @@ module.exports = generators.Base.extend({ name: 'Manifest.xml only (no application source files)', value: 'manifest-only' }] + }, + // office client application that can host the addin + { + name: 'clients', + message: 'Supported Office applications:', + type: 'checkbox', + choices: [ + { + name: 'Word', + value: 'docx', + checked: true + }, + { + name: 'Excel', + value: 'xlsx', + checked: true + }, + { + name: 'PowerPoint', + value: 'pptx', + checked: true + }, + { + name: 'Project', + value: 'mpp', + checked: true + } + ], + when: this.options.clients === undefined, + validate: function (clientsAnswer) { + if (clientsAnswer.length < 1) { + return 'Must select at least one Office application'; + } + return true; + } }]; // trigger prompts @@ -141,6 +182,7 @@ module.exports = generators.Base.extend({ name: this.genConfig.name, 'root-path': this.genConfig['root-path'], tech: this.genConfig.tech, + clients: this.genConfig.clients, 'skip-install': this.options['skip-install'] } }, { @@ -156,6 +198,7 @@ module.exports = generators.Base.extend({ name: this.genConfig.name, 'root-path': this.genConfig['root-path'], tech: this.genConfig.tech, + clients: this.genConfig.clients, 'skip-install': this.options['skip-install'] } }, { @@ -170,6 +213,7 @@ module.exports = generators.Base.extend({ name: this.genConfig.name, 'root-path': this.genConfig['root-path'], tech: this.genConfig.tech, + clients: this.genConfig.clients, 'skip-install': this.options['skip-install'] } }, { diff --git a/generators/content/index.js b/generators/content/index.js index b1c65915..b832f2fd 100644 --- a/generators/content/index.js +++ b/generators/content/index.js @@ -5,6 +5,8 @@ var chalk = require('chalk'); var path = require('path'); var extend = require('deep-extend'); var guid = require('uuid'); +var Xml2Js = require('xml2js'); +var _ = require('lodash'); module.exports = generators.Base.extend({ /** @@ -38,6 +40,12 @@ module.exports = generators.Base.extend({ required: false }); + this.option('clients', { + type: String, + desc: 'Office client product that can host the add-in', + required: false + }); + // create global config object on this generator this.genConfig = {}; }, // constructor() @@ -91,6 +99,41 @@ module.exports = generators.Base.extend({ name: 'Manifest.xml only (no application source files)', value: 'manifest-only' }] + }, + // office client application that can host the addin + { + name: 'clients', + message: 'Supported Office applications:', + type: 'checkbox', + choices: [ + { + name: 'Word', + value: 'Document', + checked: true + }, + { + name: 'Excel', + value: 'Workbook', + checked: true + }, + { + name: 'PowerPoint', + value: 'Presentation', + checked: true + }, + { + name: 'Project', + value: 'Project', + checked: true + } + ], + when: this.options.clients === undefined, + validate: function (clientsAnswer) { + if (clientsAnswer.length < 1) { + return 'Must select at least one Office application'; + } + return true; + } }]; // trigger prompts @@ -347,7 +390,49 @@ module.exports = generators.Base.extend({ } done(); - } // app() + }, // app() + + /** + * Update the manifest.xml element with the selected + * Office client hosts supported by this addin. + */ + updateManifestHosts: function () { + var done = this.async(); + + // workaround to 'this' context issue + var yoGenerator = this; + + // load manifest.xml + var manifestXml = yoGenerator.fs.read(yoGenerator.destinationPath('manifest.xml')); + + // convert it to JSON + var parser = new Xml2Js.Parser(); + parser.parseString(manifestXml, function (err, manifestJson) { + // create array of selected Office products + var supportedHostsJson = []; + _.forEach(yoGenerator.genConfig.clients, function (officeClient) { + supportedHostsJson.push({ + '$': { + Name: officeClient + } + }) + }); + // create host entry + manifestJson.OfficeApp.Hosts[0] = { + Host: supportedHostsJson + }; + + // convert JSON => XML + var xmlBuilder = new Xml2Js.Builder(); + var updatedManifestXml = xmlBuilder.buildObject(manifestJson); + + // write updated manifest + yoGenerator.fs.write(yoGenerator.destinationPath('manifest.xml'), updatedManifestXml); + + done(); + }); + } // updateManifestHosts() + }, // writing() /** @@ -371,5 +456,4 @@ module.exports = generators.Base.extend({ */ // end: { } - }); \ No newline at end of file diff --git a/generators/content/templates/common/manifest.xml b/generators/content/templates/common/manifest.xml index 22e7c38d..6a7ad221 100644 --- a/generators/content/templates/common/manifest.xml +++ b/generators/content/templates/common/manifest.xml @@ -9,9 +9,6 @@ - - - diff --git a/generators/taskpane/index.js b/generators/taskpane/index.js index 2039d859..2353ba2c 100644 --- a/generators/taskpane/index.js +++ b/generators/taskpane/index.js @@ -5,6 +5,8 @@ var chalk = require('chalk'); var path = require('path'); var extend = require('deep-extend'); var guid = require('uuid'); +var Xml2Js = require('xml2js'); +var _ = require('lodash'); module.exports = generators.Base.extend({ /** @@ -37,7 +39,13 @@ module.exports = generators.Base.extend({ desc: 'Technology to use for the Add-in (html = HTML; ng = Angular)', required: false }); - + + this.option('clients', { + type: String, + desc: 'Office client product that can host the add-in', + required: false + }); + // create global config object on this generator this.genConfig = {}; }, // constructor() @@ -91,6 +99,41 @@ module.exports = generators.Base.extend({ name: 'Manifest.xml only (no application source files)', value: 'manifest-only' }] + }, + // office client application that can host the addin + { + name: 'clients', + message: 'Supported Office applications:', + type: 'checkbox', + choices: [ + { + name: 'Word', + value: 'Document', + checked: true + }, + { + name: 'Excel', + value: 'Workbook', + checked: true + }, + { + name: 'PowerPoint', + value: 'Presentation', + checked: true + }, + { + name: 'Project', + value: 'Project', + checked: true + } + ], + when: this.options.clients === undefined, + validate: function (clientsAnswer) { + if (clientsAnswer.length < 1) { + return 'Must select at least one Office application'; + } + return true; + } }]; // trigger prompts @@ -345,7 +388,49 @@ module.exports = generators.Base.extend({ } } done(); - } // app() + }, // app() + + /** + * Update the manifest.xml element with the selected + * Office client hosts supported by this addin. + */ + updateManifestHosts: function () { + var done = this.async(); + + // workaround to 'this' context issue + var yoGenerator = this; + + // load manifest.xml + var manifestXml = yoGenerator.fs.read(yoGenerator.destinationPath('manifest.xml')); + + // convert it to JSON + var parser = new Xml2Js.Parser(); + parser.parseString(manifestXml, function (err, manifestJson) { + // create array of selected Office products + var supportedHostsJson = []; + _.forEach(yoGenerator.genConfig.clients, function (officeClient) { + supportedHostsJson.push({ + '$': { + Name: officeClient + } + }) + }); + // create host entry + manifestJson.OfficeApp.Hosts[0] = { + Host: supportedHostsJson + }; + + // convert JSON => XML + var xmlBuilder = new Xml2Js.Builder(); + var updatedManifestXml = xmlBuilder.buildObject(manifestJson); + + // write updated manifest + yoGenerator.fs.write(yoGenerator.destinationPath('manifest.xml'), updatedManifestXml); + + done(); + }); + } // updateManifestHosts() + }, // writing() /** diff --git a/generators/taskpane/templates/common/manifest.xml b/generators/taskpane/templates/common/manifest.xml index bf48226f..a6058b22 100644 --- a/generators/taskpane/templates/common/manifest.xml +++ b/generators/taskpane/templates/common/manifest.xml @@ -9,10 +9,6 @@ - - - - diff --git a/package.json b/package.json index d23568e9..45557914 100644 --- a/package.json +++ b/package.json @@ -55,9 +55,11 @@ "dependencies": { "chalk": "^1.0.0", "deep-extend": "^0.4.0", + "lodash": "^3.10.1", "uuid": "^2.0.1", "yeoman-generator": "^0.20.3", - "yosay": "^1.0.2" + "yosay": "^1.0.2", + "xml2js": "^0.4.10" }, "devDependencies": { "chai": "^3.2.0", @@ -71,7 +73,6 @@ "mocha": "*", "mockery": "^1.4.0", "validator": "^4.0.3", - "which": "^1.1.1", - "xml2js": "^0.4.10" + "which": "^1.1.1" } } diff --git a/test/app.js b/test/app.js index eedd6c60..904eebb3 100644 --- a/test/app.js +++ b/test/app.js @@ -31,6 +31,7 @@ describe('office:app', function () { rootPath: '', type: 'mail', tech: 'html', + clients: ['Document', 'Workbook'], 'skip-install': true } @@ -70,6 +71,7 @@ describe('office:app', function () { rootPath: '', type: 'taskpane', tech: 'html', + clients: ['Document', 'Workbook'], 'skip-install': true } @@ -109,6 +111,7 @@ describe('office:app', function () { rootPath: '', type: 'content', tech: 'html', + clients: ['Document', 'Workbook'], 'skip-install': true } diff --git a/test/content/existingproj-html.js b/test/content/existingproj-html.js index e4123551..ca5376bc 100644 --- a/test/content/existingproj-html.js +++ b/test/content/existingproj-html.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -84,6 +85,9 @@ describe('office:content', function () { //set language to html options.tech = 'html'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + // run the generator helpers.run(path.join(__dirname, '../../generators/content')) .withOptions(options) @@ -127,7 +131,7 @@ describe('office:content', function () { addinRootPath + '/images/close.png', addinRootPath + '/scripts/MicrosoftAjax.js', addinRootPath + '/scripts/jquery.fabric.js', - addinRootPath + '/scripts/jquery.fabric.min.js' + addinRootPath + '/scripts/jquery.fabric.min.js' ]; assert.file(expected); done(); @@ -206,6 +210,66 @@ describe('office:content', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') /** @@ -222,7 +286,7 @@ describe('office:content', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.not.exist; diff --git a/test/content/existingproj-manifestonly.js b/test/content/existingproj-manifestonly.js index 635217ff..df7beaa3 100644 --- a/test/content/existingproj-manifestonly.js +++ b/test/content/existingproj-manifestonly.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -51,6 +52,10 @@ describe('office:content', function () { beforeEach(function (done) { //set language to html options.tech = 'manifest-only'; + + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + options.startPage = 'https://localhost:8443/manifest-only/index.html'; // run the generator @@ -103,6 +108,66 @@ describe('office:content', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') }); // describe('technology:manifest-only') diff --git a/test/content/existingproj-ng.js b/test/content/existingproj-ng.js index a600b4db..6c1ec6d4 100644 --- a/test/content/existingproj-ng.js +++ b/test/content/existingproj-ng.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -84,6 +85,9 @@ describe('office:content', function () { //set language to html options.tech = 'ng'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + helpers.run(path.join(__dirname, '../../generators/content')) .withOptions(options) .on('ready', function (gen) { @@ -126,7 +130,7 @@ describe('office:content', function () { addinRootPath + '/images/close.png', addinRootPath + '/scripts/MicrosoftAjax.js', addinRootPath + '/scripts/jquery.fabric.js', - addinRootPath + '/scripts/jquery.fabric.min.js' + addinRootPath + '/scripts/jquery.fabric.min.js' ]; @@ -210,6 +214,66 @@ describe('office:content', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); // describe('manifest.xml contents') /** @@ -226,7 +290,7 @@ describe('office:content', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.exist; @@ -241,14 +305,14 @@ describe('office:content', function () { * gulpfile.js is good */ describe('gulpfule.js contents', function () { - + it('contains task \'serve-static\'', function (done) { - + assert.file('gulpfile.js'); assert.fileContent('gulpfile.js', 'gulp.task(\'serve-static\','); done(); }); - + }); // describe('gulpfile.js contents') }); // describe('technology:ng') diff --git a/test/content/newproj-html.js b/test/content/newproj-html.js index 8d9e50d5..46bf0f13 100644 --- a/test/content/newproj-html.js +++ b/test/content/newproj-html.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -37,6 +38,7 @@ describe('office:content', function () { name: 'Some\'s bad * character$ ~!@#$%^&*()', rootPath: '', tech: 'html', + clients: ['Document', 'Workbook', 'Presentation', 'Project'], startPage: 'https://localhost:8443/manifest-only/index.html' }; @@ -79,6 +81,9 @@ describe('office:content', function () { beforeEach(function (done) { //set language to html options.tech = 'html'; + + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; // run the generator helpers.run(path.join(__dirname, '../../generators/content')) @@ -196,6 +201,66 @@ describe('office:content', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') /** diff --git a/test/content/newproj-manifestonly.js b/test/content/newproj-manifestonly.js index 864b50b0..755f4684 100644 --- a/test/content/newproj-manifestonly.js +++ b/test/content/newproj-manifestonly.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -47,6 +48,10 @@ describe('office:content', function () { beforeEach(function (done) { //set language to html options.tech = 'manifest-only'; + + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + options.startPage = 'https://localhost:8443/manifest-only/index.html'; // run the generator @@ -99,6 +104,66 @@ describe('office:content', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') }); // describe('technology:manifest-only') diff --git a/test/content/newproj-ng.js b/test/content/newproj-ng.js index c66baeb6..91fc396f 100644 --- a/test/content/newproj-ng.js +++ b/test/content/newproj-ng.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -80,6 +81,9 @@ describe('office:content', function () { //set language to html options.tech = 'ng'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + // run the generator helpers.run(path.join(__dirname, '../../generators/content')) .withOptions(options) @@ -200,6 +204,66 @@ describe('office:content', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found,' exist').to.be.true; + + done(); + }); + }); // describe('manifest.xml contents') /** diff --git a/test/taskpane/existingproj-html.js b/test/taskpane/existingproj-html.js index b0379d66..7ebd8bde 100644 --- a/test/taskpane/existingproj-html.js +++ b/test/taskpane/existingproj-html.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -50,6 +51,9 @@ describe('office:taskpane', function () { //set language to html options.tech = 'html'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + // run the generator helpers.run(path.join(__dirname, '../../generators/taskpane')) .withOptions(options) @@ -172,6 +176,66 @@ describe('office:taskpane', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') /** @@ -188,7 +252,7 @@ describe('office:taskpane', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.not.exist; diff --git a/test/taskpane/existingproj-manifestonly.js b/test/taskpane/existingproj-manifestonly.js index 324b3cc4..c7acda68 100644 --- a/test/taskpane/existingproj-manifestonly.js +++ b/test/taskpane/existingproj-manifestonly.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -29,7 +30,7 @@ describe('office:taskpane', function () { }; done(); }); - + describe('run on existing project (non-empty folder)', function () { var addinRootPath = 'src/public'; @@ -48,6 +49,10 @@ describe('office:taskpane', function () { beforeEach(function (done) { //set language to html options.tech = 'manifest-only'; + + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + options.startPage = 'https://localhost:8443/manifest-only/index.html'; // run the generator @@ -100,6 +105,66 @@ describe('office:taskpane', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') }); // describe('technology:manifest-only') diff --git a/test/taskpane/existingproj-ng.js b/test/taskpane/existingproj-ng.js index 40b23274..8434f870 100644 --- a/test/taskpane/existingproj-ng.js +++ b/test/taskpane/existingproj-ng.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -29,7 +30,7 @@ describe('office:taskpane', function () { }; done(); }); - + describe('run on existing project (non-empty folder)', function () { var addinRootPath = 'src/public'; @@ -50,6 +51,9 @@ describe('office:taskpane', function () { //set language to html options.tech = 'ng'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + helpers.run(path.join(__dirname, '../../generators/taskpane')) .withOptions(options) .on('ready', function (gen) { @@ -92,7 +96,7 @@ describe('office:taskpane', function () { addinRootPath + '/images/close.png', addinRootPath + '/scripts/MicrosoftAjax.js', addinRootPath + '/scripts/jquery.fabric.js', - addinRootPath + '/scripts/jquery.fabric.min.js' + addinRootPath + '/scripts/jquery.fabric.min.js' ]; @@ -176,6 +180,66 @@ describe('office:taskpane', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); // describe('manifest.xml contents') /** @@ -192,7 +256,7 @@ describe('office:taskpane', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.exist; diff --git a/test/taskpane/newproj-html.js b/test/taskpane/newproj-html.js index e91c7657..c9c256cb 100644 --- a/test/taskpane/newproj-html.js +++ b/test/taskpane/newproj-html.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -38,6 +39,7 @@ describe('office:taskpane', function () { name: 'Some\'s bad * character$ ~!@#$%^&*()', rootPath: '', tech: 'html', + clients: ['Document', 'Workbook', 'Presentation', 'Project'], startPage: 'https://localhost:8443/manifest-only/index.html' }; @@ -81,6 +83,9 @@ describe('office:taskpane', function () { //set language to html options.tech = 'html'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + // run the generator helpers.run(path.join(__dirname, '../../generators/taskpane')) .withOptions(options) @@ -197,6 +202,66 @@ describe('office:taskpane', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') /** @@ -213,7 +278,7 @@ describe('office:taskpane', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.not.exist; diff --git a/test/taskpane/newproj-manifestonly.js b/test/taskpane/newproj-manifestonly.js index 3d0cf935..b11f08f5 100644 --- a/test/taskpane/newproj-manifestonly.js +++ b/test/taskpane/newproj-manifestonly.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -50,6 +51,9 @@ describe('office:taskpane', function () { options.tech = 'manifest-only'; options.startPage = 'https://localhost:8443/manifest-only/index.html'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + // run the generator helpers.run(path.join(__dirname, '../../generators/taskpane')) .withOptions(options) @@ -100,6 +104,66 @@ describe('office:taskpane', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); //describe('manifest.xml contents') }); // describe('technology:manifest-only') diff --git a/test/taskpane/newproj-ng.js b/test/taskpane/newproj-ng.js index db97d429..cc143617 100644 --- a/test/taskpane/newproj-ng.js +++ b/test/taskpane/newproj-ng.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -81,6 +82,9 @@ describe('office:taskpane', function () { //set language to html options.tech = 'ng'; + // set products + options.clients = ['Document', 'Workbook', 'Presentation', 'Project']; + // run the generator helpers.run(path.join(__dirname, '../../generators/taskpane')) .withOptions(options) @@ -201,6 +205,66 @@ describe('office:taskpane', function () { done(); }); + /** + * Word present in host entry. + */ + it('includes Word in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Document') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Excel present in host entry. + */ + it('includes Excel in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Workbook') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * PowerPoint present in host entry. + */ + it('includes PowerPoint in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Presentation') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + + /** + * Project present in host entry. + */ + it('includes Project in Hosts', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { + if (h.$.Name == 'Project') { + found = true; + } + }); + expect(found, ' exist').to.be.true; + + done(); + }); + }); // describe('manifest.xml contents') /** @@ -217,7 +281,7 @@ describe('office:taskpane', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.exist; diff --git a/tsd.json b/tsd.json index bf82d598..f9050369 100644 --- a/tsd.json +++ b/tsd.json @@ -37,6 +37,9 @@ }, "gulp-mocha/gulp-mocha.d.ts": { "commit": "fa8d9683f37d07ed79617a6e037916c6718aeb11" + }, + "lodash/lodash.d.ts": { + "commit": "9ce3cd4ded7536d40b8d65264ad729f442f5a052" } } } From 468448a6ec6b48e2440cf3962acac22d175ec4c3 Mon Sep 17 00:00:00 2001 From: Andrew Connell Date: Thu, 3 Sep 2015 17:00:29 -0400 Subject: [PATCH 2/6] fixed bug where generator should only prompt for office clients when user selects a non-mail addin --- generators/app/index.js | 88 ++++++++++++++++++++++++----------------- test/app.js | 1 - 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index 8529ac16..92387f28 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -122,41 +122,6 @@ module.exports = generators.Base.extend({ name: 'Manifest.xml only (no application source files)', value: 'manifest-only' }] - }, - // office client application that can host the addin - { - name: 'clients', - message: 'Supported Office applications:', - type: 'checkbox', - choices: [ - { - name: 'Word', - value: 'docx', - checked: true - }, - { - name: 'Excel', - value: 'xlsx', - checked: true - }, - { - name: 'PowerPoint', - value: 'pptx', - checked: true - }, - { - name: 'Project', - value: 'mpp', - checked: true - } - ], - when: this.options.clients === undefined, - validate: function (clientsAnswer) { - if (clientsAnswer.length < 1) { - return 'Must select at least one Office application'; - } - return true; - } }]; // trigger prompts @@ -166,7 +131,58 @@ module.exports = generators.Base.extend({ done(); }.bind(this)); - } // askFor() + }, // askFor() + + askForOfficeClients: function () { + // if it's a mail addin, don't ask for Office client + if (this.genConfig.type === 'mail') + return; + + var done = this.async(); + + // office client application that can host the addin + var prompts = [{ + name: 'clients', + message: 'Supported Office applications:', + type: 'checkbox', + choices: [ + { + name: 'Word', + value: 'Document', + checked: true + }, + { + name: 'Excel', + value: 'Workbook', + checked: true + }, + { + name: 'PowerPoint', + value: 'Presentation', + checked: true + }, + { + name: 'Project', + value: 'Project', + checked: true + } + ], + when: this.options.clients === undefined, + validate: function (clientsAnswer) { + if (clientsAnswer.length < 1) { + return 'Must select at least one Office application'; + } + return true; + } + }]; + + // trigger prompts + this.prompt(prompts, function (responses) { + this.genConfig = extend(this.genConfig, responses); + done(); + }.bind(this)); + + } // askForOfficeClients() }, // prompting() diff --git a/test/app.js b/test/app.js index 904eebb3..68336d27 100644 --- a/test/app.js +++ b/test/app.js @@ -31,7 +31,6 @@ describe('office:app', function () { rootPath: '', type: 'mail', tech: 'html', - clients: ['Document', 'Workbook'], 'skip-install': true } From 6a85b8b18463f7ef1c750298d6153196afa238de Mon Sep 17 00:00:00 2001 From: Andrew Connell Date: Fri, 4 Sep 2015 05:48:05 -0400 Subject: [PATCH 3/6] remvoed HighResolutionIconUrl as only needed in mail addins - ref: https://msdn.microsoft.com/en-us/library/office/fp161044.aspx --- generators/content/templates/common/manifest.xml | 1 - generators/taskpane/templates/common/manifest.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/generators/content/templates/common/manifest.xml b/generators/content/templates/common/manifest.xml index 6a7ad221..9b858d90 100644 --- a/generators/content/templates/common/manifest.xml +++ b/generators/content/templates/common/manifest.xml @@ -6,7 +6,6 @@ en-US - diff --git a/generators/taskpane/templates/common/manifest.xml b/generators/taskpane/templates/common/manifest.xml index a6058b22..a1d7875e 100644 --- a/generators/taskpane/templates/common/manifest.xml +++ b/generators/taskpane/templates/common/manifest.xml @@ -6,7 +6,6 @@ en-US - From 6dd72e5261e13b7b4a1213c13012a8d35e5fd3bc Mon Sep 17 00:00:00 2001 From: Andrew Connell Date: Fri, 4 Sep 2015 09:57:19 -0400 Subject: [PATCH 4/6] added prompt for different outlook forms for mail addin [issue#13](/OfficeDev/generator-office/issues/13) --- generators/app/index.js | 62 ++++++- generators/mail/index.js | 161 +++++++++++++++++- generators/mail/templates/common/manifest.xml | 10 +- test/app.js | 3 +- test/mail/existingproj-html.js | 113 +++++++++++- test/mail/existingproj-manifestonly.js | 105 +++++++++++- test/mail/existingproj-ng.js | 123 ++++++++++++- test/mail/newproj-html.js | 113 +++++++++++- test/mail/newproj-manifestonly.js | 103 +++++++++++ test/mail/newproj-ng.js | 121 ++++++++++++- test/taskpane/newproj-html.js | 4 +- 11 files changed, 892 insertions(+), 26 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index 92387f28..fecf8ec5 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -41,6 +41,12 @@ module.exports = generators.Base.extend({ required: false }); + this.option('outlookForm', { + type: String, + desc: 'Supported Outlook forms', + required: false + }); + }, // constructor() /** @@ -182,8 +188,58 @@ module.exports = generators.Base.extend({ done(); }.bind(this)); - } // askForOfficeClients() - + }, // askForOfficeClients() + + askForOutlookForms: function () { + // if it's a mail addin, ask for Outlook forms + if (this.genConfig.type !== 'mail') + return; + + var done = this.async(); + + // outlook form options + var prompts = [{ + name: 'outlookForm', + message: 'Supported Outlook forms:', + type: 'checkbox', + choices: [ + { + name: 'E-Mail message - read form', + value: 'mail-read', + checked: true + }, + { + name: 'E-Mail message - compose form', + value: 'mail-compose', + checked: true + }, + { + name: 'Appointment - read form', + value: 'appointment-read', + checked: true + }, + { + name: 'Appointment - compose form', + value: 'appointment-compose', + checked: true + } + ], + when: this.options.outlookForm === undefined, + validate: function (answers) { + if (answers.length < 1) { + return 'Must select at least one Outlook form type'; + } + return true; + } + }]; + + // trigger prompts + this.prompt(prompts, function (responses) { + this.genConfig = extend(this.genConfig, responses); + done(); + }.bind(this)); + } + }, // prompting() default: function () { @@ -198,7 +254,7 @@ module.exports = generators.Base.extend({ name: this.genConfig.name, 'root-path': this.genConfig['root-path'], tech: this.genConfig.tech, - clients: this.genConfig.clients, + outlookForm: this.genConfig.outlookForm, 'skip-install': this.options['skip-install'] } }, { diff --git a/generators/mail/index.js b/generators/mail/index.js index b2ac01b8..3ca705b7 100644 --- a/generators/mail/index.js +++ b/generators/mail/index.js @@ -3,8 +3,10 @@ var generators = require('yeoman-generator'); var chalk = require('chalk'); var path = require('path'); +var _ = require('lodash'); var extend = require('deep-extend'); var guid = require('uuid'); +var Xml2Js = require('xml2js'); module.exports = generators.Base.extend({ /** @@ -37,6 +39,13 @@ module.exports = generators.Base.extend({ desc: 'Technology to use for the Add-in (html = HTML; ng = Angular)', required: false }); + + this.option('outlookForm', { + type: String, + desc: 'Supported Outlook forms', + required: false + }); + // create global config object on this generator this.genConfig = {}; }, // constructor() @@ -90,6 +99,40 @@ module.exports = generators.Base.extend({ name: 'Manifest.xml only (no application source files)', value: 'manifest-only' }] + }, + { + name: 'outlookForm', + message: 'Supported Outlook forms:', + type: 'checkbox', + choices: [ + { + name: 'E-Mail message - read form', + value: 'mail-read', + checked: true + }, + { + name: 'E-Mail message - compose form', + value: 'mail-compose', + checked: true + }, + { + name: 'Appointment - read form', + value: 'appointment-read', + checked: true + }, + { + name: 'Appointment - compose form', + value: 'appointment-compose', + checked: true + } + ], + when: this.options.outlookForm === undefined, + validate: function (answers) { + if (answers.length < 1) { + return 'Must select at least one Outlook form type'; + } + return true; + } }]; // trigger prompts @@ -278,6 +321,9 @@ module.exports = generators.Base.extend({ this.genConfig.projectId = guid.v4(); if (this.genConfig.tech === 'manifest-only') { + // set start page same for both forms + this.genConfig.startPageReadForm = this.genConfig.startPage; + this.genConfig.startPageEditForm = this.genConfig.startPage; // create the manifest file this.fs.copyTpl(this.templatePath('common/manifest.xml'), this.destinationPath('manifest.xml'), this.genConfig); } else { @@ -306,7 +352,8 @@ module.exports = generators.Base.extend({ switch (this.genConfig.tech) { case 'html': // determine startpage for addin - this.genConfig.startPage = 'https://localhost:8443/appcompose/home/home.html'; + this.genConfig.startPageReadForm = 'https://localhost:8443/appread/home/home.html'; + this.genConfig.startPageEditForm = 'https://localhost:8443/appcompose/home/home.html'; // copy tsd & jsconfig files this.fs.copy(this.templatePath('html/_tsd.json'), this.destinationPath('tsd.json')); @@ -330,7 +377,8 @@ module.exports = generators.Base.extend({ break; case 'ng': // determine startpage for addin - this.genConfig.startPage = 'https://localhost:8443/appcompose/index.html'; + this.genConfig.startPageReadForm = 'https://localhost:8443/appread/index.html'; + this.genConfig.startPageEditForm = 'https://localhost:8443/appcompose/index.html'; // copy tsd & jsconfig files this.fs.copy(this.templatePath('ng/_tsd.json'), this.destinationPath('tsd.json')); @@ -359,7 +407,114 @@ module.exports = generators.Base.extend({ } done(); - } // app() + }, // app() + + /** + * Update the manifest.xml to reflect the selected + * Outlook client forms supported by this addin. + */ + updateManifestForms: function () { + var done = this.async(); + + // workaround to 'this' context issue + var yoGenerator = this; + + // load manifest.xml + var manifestXml = yoGenerator.fs.read(yoGenerator.destinationPath('manifest.xml')); + + // convert it to JSON + var parser = new Xml2Js.Parser(); + parser.parseString(manifestXml, function (err, manifestJson) { + + // if mail/appointment read not present, remove the form setting + _.remove(manifestJson.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsl:type'] === 'ItemRead') { + return true; + } else { + return false; + } + }); + + // if mail/appointment edit not present, remove the form setting + _.remove(manifestJson.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsl:type'] === 'ItemEdit') { + return true; + } else { + return false; + } + }); + + // create array of selected form types + var supportedFormTypesJson = []; + _.forEach(yoGenerator.genConfig.outlookForm, function (formType) { + switch (formType) { + case 'mail-read': + supportedFormTypesJson.push({ + '$': { + 'xsi:type': 'ItemIs', + ItemType: 'Message', + FormType: 'Read' + } + }); + break; + case 'mail-compose': + supportedFormTypesJson.push({ + '$': { + 'xsi:type': 'ItemIs', + ItemType: 'Message', + FormType: 'Edit' + } + }); + break; + case 'appointment-read': + supportedFormTypesJson.push({ + '$': { + 'xsi:type': 'ItemIs', + ItemType: 'Appointment', + FormType: 'Read' + } + }); + break; + case 'appointment-compose': + supportedFormTypesJson.push({ + '$': { + 'xsi:type': 'ItemIs', + ItemType: 'Appointment', + FormType: 'Edit' + } + }); + break; + }; + }); + + var ruleEntry = undefined; + // if only one rule, add it + if (supportedFormTypesJson.length == 1) { + ruleEntry = supportedFormTypesJson[0]; + } else { + // create container of rules & ad it + ruleEntry = { + '$': { + 'xsi:type': "RuleCollection", + Mode: 'Or', + }, + Rule: supportedFormTypesJson + }; + } + // add the rule to the manifest + manifestJson.OfficeApp.Rule[0] = ruleEntry; + + // convert JSON => XML + var xmlBuilder = new Xml2Js.Builder(); + var updatedManifestXml = xmlBuilder.buildObject(manifestJson); + + // write updated manifest + yoGenerator.fs.write(yoGenerator.destinationPath('manifest.xml'), updatedManifestXml); + + done(); + }); + + } // updateManifestForms() }, // writing() /** diff --git a/generators/mail/templates/common/manifest.xml b/generators/mail/templates/common/manifest.xml index 3450937d..42625fe2 100644 --- a/generators/mail/templates/common/manifest.xml +++ b/generators/mail/templates/common/manifest.xml @@ -18,16 +18,20 @@ +
+ + + 250 + +
- +
ReadWriteItem - - false \ No newline at end of file diff --git a/test/app.js b/test/app.js index 68336d27..312f0199 100644 --- a/test/app.js +++ b/test/app.js @@ -31,6 +31,7 @@ describe('office:app', function () { rootPath: '', type: 'mail', tech: 'html', + outlookForm: ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose'], 'skip-install': true } @@ -99,7 +100,7 @@ describe('office:app', function () { }); - }); // describe('runs taskpane subgenerator') + }); // describe('runs content subgenerator') describe('runs content subgenerator', function () { diff --git a/test/mail/existingproj-html.js b/test/mail/existingproj-html.js index b80c0583..f1ce4548 100644 --- a/test/mail/existingproj-html.js +++ b/test/mail/existingproj-html.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -37,6 +38,7 @@ describe('office:mail', function () { name: 'Some\'s bad * character$ ~!@#$%^&*()', rootPath: '', tech: 'html', + outlookForm: ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose'], startPage: 'https://localhost:8443/manifest-only/index.html' }; @@ -80,6 +82,9 @@ describe('office:mail', function () { //set language to html options.tech = 'html'; + // set outlook form type + options.outlookForm = ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose']; + // run the generator helpers.run(path.join(__dirname, '../../generators/mail')) .withOptions(options) @@ -203,7 +208,113 @@ describe('office:mail', function () { }); it('has correct start page', function (done) { - expect(manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue).to.equal('https://localhost:8443/appcompose/home/home.html'); + var valid = false; + var subject = manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue; + + if (subject === 'https://localhost:8443/appcompose/home/home.html' || + subject === 'https://localhost:8443/appread/home/home.html') { + valid = true; + } + + expect(valid, 'start page is not valid compose or edit form').to.be.true; + done(); + }); + + /** + * Form for ItemRead present + */ + it('includes form for ItemRead', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemRead') { + found = true; + } + }); + + expect(found, '
exist').to.be.true; + done(); + }); + + /** + * Form for ItemEdit present + */ + it('includes form for ItemEdit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemEdit') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Rule for Mail Read present + */ + it('includes rule for mail read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Mail Edit present + */ + it('includes rule for mail edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Read present + */ + it('includes rule for appointment read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Edit present + */ + it('includes rule for appointment edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; done(); }); diff --git a/test/mail/existingproj-manifestonly.js b/test/mail/existingproj-manifestonly.js index fcf444e2..44736139 100644 --- a/test/mail/existingproj-manifestonly.js +++ b/test/mail/existingproj-manifestonly.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -28,7 +29,7 @@ describe('office:mail', function () { }; done(); }); - + describe('run on existing project (non-empty folder)', function () { var addinRootPath = 'src/public'; @@ -47,6 +48,10 @@ describe('office:mail', function () { beforeEach(function (done) { //set language to html options.tech = 'manifest-only'; + + // set outlook form type + options.outlookForm = ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose']; + options.startPage = 'https://localhost:8443/manifest-only/index.html'; // run the generator @@ -99,6 +104,104 @@ describe('office:mail', function () { done(); }); + /** + * Form for ItemRead present + */ + it('includes form for ItemRead', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemRead') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Form for ItemEdit present + */ + it('includes form for ItemEdit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemEdit') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Rule for Mail Read present + */ + it('includes rule for mail read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Mail Edit present + */ + it('includes rule for mail edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Read present + */ + it('includes rule for appointment read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Edit present + */ + it('includes rule for appointment edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + }); //describe('manifest.xml contents') }); // describe('technology:manifest-only') diff --git a/test/mail/existingproj-ng.js b/test/mail/existingproj-ng.js index 19e7041b..edc6d6b6 100644 --- a/test/mail/existingproj-ng.js +++ b/test/mail/existingproj-ng.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -37,6 +38,7 @@ describe('office:mail', function () { name: 'Some\'s bad * character$ ~!@#$%^&*()', rootPath: '', tech: 'ng', + outlookForm: ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose'], startPage: 'https://localhost:8443/manifest-only/index.html' }; @@ -80,6 +82,9 @@ describe('office:mail', function () { //set language to html options.tech = 'ng'; + // set outlook form type + options.outlookForm = ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose']; + helpers.run(path.join(__dirname, '../../generators/mail')) .withOptions(options) .on('ready', function (gen) { @@ -128,7 +133,7 @@ describe('office:mail', function () { addinRootPath + '/images/close.png', addinRootPath + '/scripts/MicrosoftAjax.js', addinRootPath + '/scripts/jquery.fabric.js', - addinRootPath + '/scripts/jquery.fabric.min.js' + addinRootPath + '/scripts/jquery.fabric.min.js' ]; @@ -208,7 +213,113 @@ describe('office:mail', function () { }); it('has correct start page', function (done) { - expect(manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue).to.equal('https://localhost:8443/appcompose/index.html'); + var valid = false; + var subject = manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue; + + if (subject === 'https://localhost:8443/appcompose/index.html' || + subject === 'https://localhost:8443/appread/index.html') { + valid = true; + } + + expect(valid, 'start page is not valid compose or edit form').to.be.true; + done(); + }); + + /** + * Form for ItemRead present + */ + it('includes form for ItemRead', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemRead') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Form for ItemEdit present + */ + it('includes form for ItemEdit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemEdit') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Rule for Mail Read present + */ + it('includes rule for mail read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Mail Edit present + */ + it('includes rule for mail edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Read present + */ + it('includes rule for appointment read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Edit present + */ + it('includes rule for appointment edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; done(); }); @@ -228,7 +339,7 @@ describe('office:mail', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.exist; @@ -243,14 +354,14 @@ describe('office:mail', function () { * gulpfile.js is good */ describe('gulpfule.js contents', function () { - + it('contains task \'serve-static\'', function (done) { - + assert.file('gulpfile.js'); assert.fileContent('gulpfile.js', 'gulp.task(\'serve-static\','); done(); }); - + }); // describe('gulpfile.js contents') }); // describe('technology:ng') diff --git a/test/mail/newproj-html.js b/test/mail/newproj-html.js index 8019989c..1ec9f3fa 100644 --- a/test/mail/newproj-html.js +++ b/test/mail/newproj-html.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -37,6 +38,7 @@ describe('office:mail', function () { name: 'Some\'s bad * character$ ~!@#$%^&*()', rootPath: '', tech: 'html', + outlookForm: ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose'], startPage: 'https://localhost:8443/manifest-only/index.html' }; @@ -80,6 +82,9 @@ describe('office:mail', function () { //set language to html options.tech = 'html'; + // set outlook form type + options.outlookForm = ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose']; + // run the generator helpers.run(path.join(__dirname, '../../generators/mail')) .withOptions(options) @@ -197,7 +202,113 @@ describe('office:mail', function () { }); it('has correct start page', function (done) { - expect(manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue).to.equal('https://localhost:8443/appcompose/home/home.html'); + var valid = false; + var subject = manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue; + + if (subject === 'https://localhost:8443/appcompose/home/home.html' || + subject === 'https://localhost:8443/appread/home/home.html') { + valid = true; + } + + expect(valid, 'start page is not valid compose or edit form').to.be.true; + done(); + }); + + /** + * Form for ItemRead present + */ + it('includes form for ItemRead', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemRead') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Form for ItemEdit present + */ + it('includes form for ItemEdit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemEdit') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Rule for Mail Read present + */ + it('includes rule for mail read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Mail Edit present + */ + it('includes rule for mail edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Read present + */ + it('includes rule for appointment read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Edit present + */ + it('includes rule for appointment edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; done(); }); diff --git a/test/mail/newproj-manifestonly.js b/test/mail/newproj-manifestonly.js index 8bb55afe..e2200a8d 100644 --- a/test/mail/newproj-manifestonly.js +++ b/test/mail/newproj-manifestonly.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -47,6 +48,10 @@ describe('office:mail', function () { beforeEach(function (done) { //set language to html options.tech = 'manifest-only'; + + // set outlook form type + options.outlookForm = ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose']; + options.startPage = 'https://localhost:8443/manifest-only/index.html'; // run the generator @@ -99,6 +104,104 @@ describe('office:mail', function () { done(); }); + /** + * Form for ItemRead present + */ + it('includes form for ItemRead', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemRead') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Form for ItemEdit present + */ + it('includes form for ItemEdit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemEdit') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Rule for Mail Read present + */ + it('includes rule for mail read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Mail Edit present + */ + it('includes rule for mail edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Read present + */ + it('includes rule for appointment read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Edit present + */ + it('includes rule for appointment edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + }); //describe('manifest.xml contents') }); // describe('technology:manifest-only') diff --git a/test/mail/newproj-ng.js b/test/mail/newproj-ng.js index 32953c25..f1af75e0 100644 --- a/test/mail/newproj-ng.js +++ b/test/mail/newproj-ng.js @@ -3,6 +3,7 @@ var fs = require('fs'); var path = require('path'); +var _ = require('lodash'); var mockery = require('mockery'); var assert = require('yeoman-generator').assert; var helpers = require('yeoman-generator').test; @@ -80,6 +81,9 @@ describe('office:mail', function () { //set language to html options.tech = 'ng'; + // set outlook form type + options.outlookForm = ['mail-read', 'mail-compose', 'appointment-read', 'appointment-compose']; + // run the generator helpers.run(path.join(__dirname, '../../generators/mail')) .withOptions(options) @@ -202,7 +206,114 @@ describe('office:mail', function () { }); it('has correct start page', function (done) { - expect(manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue).to.equal('https://localhost:8443/appcompose/index.html'); + var valid = false; + var subject = manifest.OfficeApp.FormSettings[0].Form[0].DesktopSettings[0].SourceLocation[0].$.DefaultValue; + + if (subject === 'https://localhost:8443/appcompose/index.html' || + subject === 'https://localhost:8443/appread/index.html') { + valid = true; + } + + expect(valid, 'start page is not valid compose or edit form').to.be.true; + done(); + }); + + /** + * Form for ItemRead present + */ + it('includes form for ItemRead', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemRead') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Form for ItemEdit present + */ + it('includes form for ItemEdit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.FormSettings[0].Form, function (formSetting) { + if (formSetting.$['xsi:type'] === 'ItemEdit') { + found = true; + } + }); + + expect(found, ' exist').to.be.true; + done(); + }); + + /** + * Rule for Mail Read present + */ + it('includes rule for mail read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Read') { + found = true; + } + + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Mail Edit present + */ + it('includes rule for mail edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Message' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Read present + */ + it('includes rule for appointment read', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Read') { + found = true; + } + }); + + expect(found, '').to.be.true; + done(); + }); + + /** + * Rule for Appointment Edit present + */ + it('includes rule for appointment edit', function (done) { + var found = false; + _.forEach(manifest.OfficeApp.Rule[0].Rule, function (rule) { + if (rule.$['xsi:type'] === 'ItemIs' && + rule.$.ItemType === 'Appointment' && + rule.$.FormType === 'Edit') { + found = true; + } + }); + + expect(found, '').to.be.true; done(); }); @@ -222,7 +333,7 @@ describe('office:mail', function () { }); }); - it ('has correct *.d.ts references', function (done) { + it('has correct *.d.ts references', function (done) { expect(tsd.installed).to.exist; expect(tsd.installed["jquery/jquery.d.ts"]).to.exist; expect(tsd.installed["angularjs/angular.d.ts"]).to.exist; @@ -237,14 +348,14 @@ describe('office:mail', function () { * gulpfile.js is good */ describe('gulpfule.js contents', function () { - + it('contains task \'serve-static\'', function (done) { - + assert.file('gulpfile.js'); assert.fileContent('gulpfile.js', 'gulp.task(\'serve-static\','); done(); }); - + }); // describe('gulpfile.js contents') }); // describe('technology:ng') diff --git a/test/taskpane/newproj-html.js b/test/taskpane/newproj-html.js index c9c256cb..fe948125 100644 --- a/test/taskpane/newproj-html.js +++ b/test/taskpane/newproj-html.js @@ -203,8 +203,8 @@ describe('office:taskpane', function () { }); /** - * Word present in host entry. - */ + * Word present in host entry. + */ it('includes Word in Hosts', function (done) { var found = false; _.forEach(manifest.OfficeApp.Hosts[0].Host, function (h) { From 2aef78e3e6e71dbb9656392a9d9e8642df04ed7e Mon Sep 17 00:00:00 2001 From: Andrew Connell Date: Fri, 4 Sep 2015 10:18:28 -0400 Subject: [PATCH 5/6] updated docs for v0.2.0 milestone --- README.md | 19 +++++++++++++++++++ docs/ex-content-html.md | 8 ++++++++ docs/ex-content-ng.md | 8 ++++++++ docs/ex-mail-html.md | 8 ++++++++ docs/ex-mail-ng.md | 9 ++++++++- docs/ex-taskpane-html.md | 8 ++++++++ docs/ex-taskpane-ng.md | 9 ++++++++- 7 files changed, 67 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 965a9b9f..ab84bdfe 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,25 @@ Technology to use for the project. The supported options include HTML (`html`) o - Default: undefined / null - Optional +### `--clients: [ 'Document' | 'Workbook' | 'Presentation' | 'Project' ]` + +The Microsoft Office client application that can host the add-in. + +> This applies only to task pane or content add-ins. + + - Type: String[] + - Default: undefined / null + - Optional + +### `--outlookForm: [ 'mail-read' | 'mail-compose' | 'appointment-read' | 'appointment-compose' ]` + +The type of form within Outlook that can host the add-in. + +> This applies only to mail add-ins. + + - Type: String[] + - Default: undefined / null + - Optional ## Sub Generators diff --git a/docs/ex-content-html.md b/docs/ex-content-html.md index c5a9d971..dc73bfe3 100644 --- a/docs/ex-content-html.md +++ b/docs/ex-content-html.md @@ -16,11 +16,15 @@ $ yo office --skip-install - **Root folder of the project:** {blank} - **Office project type:** Content Add-in - **Technology to use:** Html, CSS & JavaScript +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ``` . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json +├── tsd.json ├── app │   ├── app.css │   ├── app.js @@ -75,6 +79,7 @@ $ yo office --skip-install - **Root folder of the project:** src/public - **Office project type:** Content Add-in - **Technology to use:** Html, CSS & JavaScript +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ### Results: @@ -82,8 +87,11 @@ $ yo office --skip-install . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml ├── package.json +├── tsd.json └── src ├── public │   ├── app diff --git a/docs/ex-content-ng.md b/docs/ex-content-ng.md index aad768a9..c6ef188d 100644 --- a/docs/ex-content-ng.md +++ b/docs/ex-content-ng.md @@ -16,13 +16,17 @@ $ yo office --skip-install - **Root folder of the project:** {blank} - **Office project type:** Content Add-in - **Technology to use:** Angular +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ``` . ├── .bowerrc ├── bower.json +├── gulpfile.js ├── index.html +├── jsconfig.json ├── manifest.xml +├── tsd.json ├── app │   ├── app.module.js │   ├── app.routes.js @@ -77,6 +81,7 @@ $ yo office --skip-install - **Root folder of the project:** src/public - **Office project type:** Content Add-in - **Technology to use:** Angular +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ### Results: @@ -84,8 +89,11 @@ $ yo office --skip-install . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml ├── package.json +├── tsd.json └── src ├── public │   ├── index.html diff --git a/docs/ex-mail-html.md b/docs/ex-mail-html.md index 716f3d5d..9f142bdc 100644 --- a/docs/ex-mail-html.md +++ b/docs/ex-mail-html.md @@ -16,12 +16,16 @@ $ yo office --skip-install - **Root folder of the project:** {blank} - **Office project type:** Mail Add-in (read & compose forms) - **Technology to use:** Html, CSS & JavaScript +- **Supported Outlook forms:** E-Mail message - read form, Appointment - read form ``` . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml +├── tsd.json ├── appcompose │   ├── app.css │   ├── app.js @@ -82,6 +86,7 @@ $ yo office --skip-install - **Root folder of the project:** src/public - **Office project type:** Mail Add-in (read & compose forms) - **Technology to use:** Html, CSS & JavaScript +- **Supported Outlook forms:** E-Mail message - read form, Appointment - read form ### Results: @@ -89,8 +94,11 @@ $ yo office --skip-install . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml ├── package.json +├── tsd.json └── src ├── public │   ├── appcompose diff --git a/docs/ex-mail-ng.md b/docs/ex-mail-ng.md index b172bc74..47b0797c 100644 --- a/docs/ex-mail-ng.md +++ b/docs/ex-mail-ng.md @@ -16,12 +16,16 @@ $ yo office --skip-install - **Root folder of the project:** {blank} - **Office project type:** Mail Add-in (read & compose forms) - **Technology to use:** Angular +- **Supported Outlook forms:** E-Mail message - read form, Appointment - read form ``` . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml +├── tsd.json ├── appcompose │   ├── app.module.js │   ├── app.routes.js @@ -86,7 +90,7 @@ $ yo office --skip-install - **Root folder of the project:** src/public - **Office project type:** Mail Add-in (read & compose forms) - **Technology to use:** Angular - +- **Supported Outlook forms:** E-Mail message - read form, Appointment - read form ### Results: @@ -94,8 +98,11 @@ $ yo office --skip-install . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml ├── package.json +├── tsd.json └── src ├── public │   ├── index.html diff --git a/docs/ex-taskpane-html.md b/docs/ex-taskpane-html.md index 940593ef..8d380f92 100644 --- a/docs/ex-taskpane-html.md +++ b/docs/ex-taskpane-html.md @@ -16,11 +16,15 @@ $ yo office --skip-install - **Root folder of the project:** {blank} - **Office project type:** Task Pane Add-in - **Technology to use:** Html, CSS & JavaScript +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ``` . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json +├── tsd.json ├── app │   ├── app.css │   ├── app.js @@ -75,6 +79,7 @@ $ yo office --skip-install - **Root folder of the project:** src/public - **Office project type:** Task Pane Add-in - **Technology to use:** Html, CSS & JavaScript +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ### Results: @@ -82,8 +87,11 @@ $ yo office --skip-install . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml ├── package.json +├── tsd.json └── src ├── public │   ├── app diff --git a/docs/ex-taskpane-ng.md b/docs/ex-taskpane-ng.md index 73588f94..fbdbca7f 100644 --- a/docs/ex-taskpane-ng.md +++ b/docs/ex-taskpane-ng.md @@ -16,13 +16,17 @@ $ yo office --skip-install - **Root folder of the project:** {blank} - **Office project type:** Task Pane Add-in - **Technology to use:** Angular +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ``` . ├── .bowerrc ├── bower.json +├── gulpfile.js ├── index.html +├── jsconfig.json ├── manifest.xml +├── tsd.json ├── app │   ├── app.module.js │   ├── app.routes.js @@ -77,7 +81,7 @@ $ yo office --skip-install - **Root folder of the project:** src/public - **Office project type:** Task Pane Add-in - **Technology to use:** Angular - +- **Supported Office Applications:** Word, Excel, PowerPoint, Project ### Results: @@ -85,8 +89,11 @@ $ yo office --skip-install . ├── .bowerrc ├── bower.json +├── gulpfile.js +├── jsconfig.json ├── manifest.xml ├── package.json +├── tsd.json └── src ├── public │   ├── index.html From eadcdf6c73ddeea892aba47d5cb4e2840e2f6738 Mon Sep 17 00:00:00 2001 From: Andrew Connell Date: Fri, 4 Sep 2015 10:26:14 -0400 Subject: [PATCH 6/6] fixed code coverage issues - not able to test --- generators/app/index.js | 4 ++-- generators/content/index.js | 2 +- generators/mail/index.js | 2 +- generators/taskpane/index.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index fecf8ec5..2e1356f9 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -174,7 +174,7 @@ module.exports = generators.Base.extend({ } ], when: this.options.clients === undefined, - validate: function (clientsAnswer) { + validate: /* istanbul ignore next */ function (clientsAnswer) { if (clientsAnswer.length < 1) { return 'Must select at least one Office application'; } @@ -225,7 +225,7 @@ module.exports = generators.Base.extend({ } ], when: this.options.outlookForm === undefined, - validate: function (answers) { + validate: /* istanbul ignore next */ function (answers) { if (answers.length < 1) { return 'Must select at least one Outlook form type'; } diff --git a/generators/content/index.js b/generators/content/index.js index b832f2fd..1befe196 100644 --- a/generators/content/index.js +++ b/generators/content/index.js @@ -128,7 +128,7 @@ module.exports = generators.Base.extend({ } ], when: this.options.clients === undefined, - validate: function (clientsAnswer) { + validate: /* istanbul ignore next */ function (clientsAnswer) { if (clientsAnswer.length < 1) { return 'Must select at least one Office application'; } diff --git a/generators/mail/index.js b/generators/mail/index.js index 3ca705b7..0e3f2035 100644 --- a/generators/mail/index.js +++ b/generators/mail/index.js @@ -127,7 +127,7 @@ module.exports = generators.Base.extend({ } ], when: this.options.outlookForm === undefined, - validate: function (answers) { + validate: /* istanbul ignore next */ function (answers) { if (answers.length < 1) { return 'Must select at least one Outlook form type'; } diff --git a/generators/taskpane/index.js b/generators/taskpane/index.js index 2353ba2c..17721781 100644 --- a/generators/taskpane/index.js +++ b/generators/taskpane/index.js @@ -128,7 +128,7 @@ module.exports = generators.Base.extend({ } ], when: this.options.clients === undefined, - validate: function (clientsAnswer) { + validate: /* istanbul ignore next */function (clientsAnswer) { if (clientsAnswer.length < 1) { return 'Must select at least one Office application'; }