Repository: jhipster/generator-jhipster
Pull request #9233 (2019-02-10 14:56:19)

[v5 maintenance] Fix needleApi injection, external resources public API and add unit tests
According to https://github.com/sudheerj/generator-jhipster-primeng/issues/67 the needle API PR broke compatibility. I would like to handle needleApi construction in the generator-base constructor but it seems not working since module not always extend directly the generator-base.

To fix that I suggest to add a needleApi getter which initialise the variable if needed.

Also when during my tests I found a bug  in the addExternalResourcesToRoot and I fix that too.

@sudheerj
Could you please test this PR for me and tell me if you always have the problem ?
If it's ok for you I will remove the WIP tag.
thanks you

Regards,

PS: need to be merged to master to

-   [x] [Travis tests](https://travis-ci.org/jhipster/generator-jhipster/pull_requests) are green
-   [x] Tests are added where necessary
-   [x] Documentation is added/updated where necessary
-   [x] Coding Rules & Commit Guidelines as per our [CONTRIBUTING.md document](https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md) are followed

<!--
Please also reference the issue number in a commit message to [automatically close the related Github issue](https://help.github.com/articles/closing-issues-via-commit-messages/)

Note: It is also possible to add `[skip ci]` to your commit message to skip Travis tests
-->



Patch:
diff --git a/generators/generator-base.js b/generators/generator-base.js
index eca521e7bb..3ca1d3a0d9 100644
--- a/generators/generator-base.js
+++ b/generators/generator-base.js
@@ -48,11 +48,6 @@ const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR;
  * The method signatures in public API should not be changed without a major version change
  */
 module.exports = class extends PrivateBase {
-    constructor(args, opts) {
-        super(args, opts);
-        this.needleApi = new NeedleApi(this);
-    }
-
     /**
      * Deprecated
      * Get the JHipster configuration from the .yo-rc.json file.
@@ -95,7 +90,7 @@ module.exports = class extends PrivateBase {
      * @param {string} comment - comment to add before resources content.
      */
     addExternalResourcesToRoot(resources, comment) {
-        this.needleApi.base.addExternalResourcesToRoot(resources, comment);
+        this.needleApi.client.addExternalResourcesToRoot(resources, comment);
     }
 
     /**
@@ -2098,4 +2093,11 @@ module.exports = class extends PrivateBase {
     asDto(name) {
         return name + this.dtoSuffix;
     }
+
+    get needleApi() {
+        if (this._needleApi === undefined || this._needleApi === null) {
+            this._needleApi = new NeedleApi(this);
+        }
+        return this._needleApi;
+    }
 };
diff --git a/generators/internal/needle-api/index.js b/generators/internal/needle-api/index.js
index f1195387aa..8c70448900 100644
--- a/generators/internal/needle-api/index.js
+++ b/generators/internal/needle-api/index.js
@@ -17,6 +17,7 @@
  * limitations under the License.
  */
 const Base = require('./needle-base');
+const Client = require('./needle-client');
 const ClientAngular = require('./needle-client-angular');
 const ClientReact = require('./needle-client-react');
 const ClientWebpack = require('./needle-client-webpack');
@@ -29,11 +30,12 @@ const ServerLiquibase = require('./needle-server-liquibase');
 module.exports = class NeedleApi {
     constructor(generator) {
         this.base = new Base(generator);
-        this.serverMaven = new ServerMaven(generator);
+        this.client = new Client(generator);
         this.clientAngular = new ClientAngular(generator);
         this.clientReact = new ClientReact(generator);
         this.clientWebpack = new ClientWebpack(generator);
         this.clientI18n = new ClientI18n(generator);
+        this.serverMaven = new ServerMaven(generator);
         this.serverCache = new ServerCache(generator);
         this.serverLiquibase = new ServerLiquibase(generator);
         this.serverGradle = new ServerGradle(generator);


Test patch:
diff --git a/test/needle-api/needle-client.spec.js b/test/needle-api/needle-client.spec.js
new file mode 100644
index 0000000000..1b6136a8a6
--- /dev/null
+++ b/test/needle-api/needle-client.spec.js
@@ -0,0 +1,86 @@
+const path = require('path');
+const assert = require('yeoman-assert');
+const helpers = require('yeoman-test');
+const ClientGenerator = require('../../generators/client');
+const constants = require('../../generators/generator-constants');
+
+const CLIENT_MAIN_SRC_DIR = constants.CLIENT_MAIN_SRC_DIR;
+
+const mockBlueprintSubGen = class extends ClientGenerator {
+    constructor(args, opts) {
+        super(args, { fromBlueprint: true, ...opts }); // fromBlueprint variable is important
+
+        const jhContext = (this.jhipsterContext = this.options.jhipsterContext);
+
+        if (!jhContext) {
+            this.error('This is a JHipster blueprint and should be used only like jhipster --blueprint myblueprint');
+        }
+
+        this.configOptions = jhContext.configOptions || {};
+        // This sets up options for this sub generator and is being reused from JHipster
+        jhContext.setupEntityOptions(this, jhContext, this);
+    }
+
+    get initializing() {
+        return super._initializing();
+    }
+
+    get prompting() {
+        return super._prompting();
+    }
+
+    get configuring() {
+        return super._configuring();
+    }
+
+    get default() {
+        return super._default();
+    }
+
+    get writing() {
+        const phaseFromJHipster = super._writing();
+        const customPhaseSteps = {
+            addExternalResourcesToRootStep() {
+                this.addExternalResourcesToRoot('<link rel="stylesheet" href="content/css/my.css">', 'Comment added by JHipster API');
+            }
+        };
+        return { ...phaseFromJHipster, ...customPhaseSteps };
+    }
+};
+
+describe('needle API Client: JHipster client generator with blueprint', () => {
+    const blueprintNames = ['generator-jhipster-myblueprint', 'myblueprint'];
+
+    blueprintNames.forEach(blueprintName => {
+        describe(`generate client with blueprint option '${blueprintName}'`, () => {
+            before(done => {
+                helpers
+                    .run(path.join(__dirname, '../../generators/client'))
+                    .withOptions({
+                        'from-cli': true,
+                        build: 'maven',
+                        auth: 'jwt',
+                        db: 'mysql',
+                        skipInstall: true,
+                        blueprint: blueprintName,
+                        skipChecks: true
+                    })
+                    .withGenerators([[mockBlueprintSubGen, 'jhipster-myblueprint:client']])
+                    .withPrompts({
+                        baseName: 'jhipster',
+                        clientFramework: 'angularX',
+                        useSass: true,
+                        enableTranslation: true,
+                        nativeLanguage: 'en',
+                        languages: ['en', 'fr']
+                    })
+                    .on('end', done);
+            });
+
+            it('Assert index.html contain the comment and the resource added', () => {
+                assert.fileContent(`${CLIENT_MAIN_SRC_DIR}index.html`, '<!-- Comment added by JHipster API -->');
+                assert.fileContent(`${CLIENT_MAIN_SRC_DIR}index.html`, '<link rel="stylesheet" href="content/css/my.css">');
+            });
+        });
+    });
+});