I'm attempting to write a test for my Yeoman generator which calls a command-line utility to generate some files in the folder I'm scaffolding. I've seen various examples of how to set a timeout to wait for a function to finish but am struggling to get it to work locally.
Here's my test:
describe('Should properly scaffold with config for Spring and wsdl2rest', function () {
before(function () {
basicProps.name = 'MyAppMock';
basicProps.package = 'com.generator.mock';
basicProps.camelVersion = '2.18.2';
basicProps.camelDSL = 'spring';
var wsdlPath = path.join(__dirname, '../test/address.wsdl');
basicProps.wsdl = wsdlPath;
basicProps.outdirectory = 'src/main/java';
return helpers.run(path.join(__dirname, '../app'))
.inTmpDir(function (dir) {
var done = this.async(); // `this` is the RunContext object.
fs.copy(path.join(__dirname, '../templates'), dir, done);
basicProps.outdirectory = path.join(dir, 'src/main/java');
})
.withOptions({ wsdl2rest: true })
.withPrompts({ name: basicProps.name })
.withPrompts({ camelVersion: basicProps.camelVersion })
.withPrompts({ camelDSL: basicProps.camelDSL })
.withPrompts({ package: basicProps.package })
.withPrompts({ wsdl: basicProps.wsdl })
.withPrompts({ outdirectory: basicProps.outdirectory })
.toPromise();
});
it('Should create the basic structure two ways', function () {
assert.file('pom.xml');
assert.file('README.md');
assert.file('src/main/resources/META-INF/spring/camel-context.xml');
assert.file('src/main/resources/META-INF/spring/camel-context-rest.xml')
});
});
The problem is that the command-line executable is finishing AFTER the test to see if the files that it generates are there so I'm getting:
Creating wsdl2rest java output directory
calling: java -jar C:\Users\brianf\Documents\GitHub\generator-camel-project-fork\app\wsdl2rest\target\wsdl2rest-impl-fatjar-0.1.3-SNAPSHOT.jar --wsdl file:///C:/Users/brianf/Documents/GitHub/generator-camel-project-fork/test/address.wsdl --out C:\Users\brianf\AppData\Local\Temp\8d84f15024327cbe792407e1294ab46a5b4a1080\src\main\java --camel-context C:\Users\brianf\AppData\Local\Temp\8d84f15024327cbe792407e1294ab46a5b4a1080\src\main\resources\META-INF\spring\camel-context-rest.xml
1) Should create the basic structure two ways
11 passing (411ms)
1 failing
1) generator-camel:wsdl2rest
Should properly scaffold with config for Spring and wsdl2rest
Should create the basic structure two ways:
AssertionError [ERR_ASSERTION]: src/main/resources/META-INF/spring/camel-context-rest.xml, no such file or directory
+ expected - actual
-false
+true
at convertArgs.forEach.file (node_modules\yeoman-assert\index.js:56:12)
at Array.forEach (<anonymous>)
at Function.assert.file (node_modules\yeoman-assert\index.js:54:26)
at Context.<anonymous> (test\app.js:206:14)
stdout: Retrieving document at 'file:/C:/Users/brianf/Documents/GitHub/generator-camel-project-fork/test/address.wsdl'.
stderr: log4j:WARN No appenders could be found for logger (org.jboss.fuse.wsdl2rest.impl.WSDLProcessorImpl).
stderr: log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
wsdl2rest generated artifacts successfully
What's the secret to getting this thing to wait? I'm positive I'm missing something obvious, but I'm mostly a Java programmer not JavaScript and struggling a bit with some of the asynchronous aspects of the language.
Thanks in advance!
Update: Though it has been suggested that I use Mocha's asynchronous code options (https://mochajs.org/#asynchronous-code) I am having a difficult time wrestling those concepts into the test I have written and could use some additional help if anybody has tackled this with Yeoman generator testing?
Thanks to @Evan, we found a solution yesterday...
There are two parts - one was the fact that the method we created to actually call our Java jar wasn't returning a Promise... so we changed it to:
console.log('calling: ' + cmdString);
return new Promise((resolve, reject) => {
const wsdl2rest = exec(cmdString);
wsdl2rest.stdout.on('data', function (data) {
console.log(`stdout: ${data}`);
});
wsdl2rest.stderr.on('data', function (data) {
console.log(`stderr: ${data}`);
});
wsdl2rest.on('close', function (code) {
if (code === 0) {
console.log(`wsdl2rest generated artifacts successfully`);
resolve()
} else {
reject()
console.log(`stderr: ${code}`);
console.log(`wsdl2rest did not generate artifacts successfully - please check the log file for details`);
}
});
})
And we changed the test to be:
describe('generator-camel:wsdl2rest', function () {
describe('Should properly scaffold with config for Spring and wsdl2rest', function () {
it('Should create the basic structure two ways', function () {
basicProps.name = 'MyAppMock';
basicProps.package = 'com.generator.mock';
basicProps.camelVersion = '2.18.2';
basicProps.camelDSL = 'spring';
var wsdlPath = path.join(__dirname, '../test/address.wsdl');
basicProps.wsdl = wsdlPath;
basicProps.outdirectory = 'src/main/java';
return helpers.run(path.join(__dirname, '../app'))
.inTmpDir(function (dir) {
var done = this.async(); // `this` is the RunContext object.
fs.copy(path.join(__dirname, '../templates'), dir, done);
basicProps.outdirectory = path.join(dir, 'src/main/java');
})
.withOptions({ wsdl2rest: true })
.withPrompts({ name: basicProps.name })
.withPrompts({ camelVersion: basicProps.camelVersion })
.withPrompts({ camelDSL: basicProps.camelDSL })
.withPrompts({ package: basicProps.package })
.withPrompts({ wsdl: basicProps.wsdl })
.withPrompts({ outdirectory: basicProps.outdirectory })
.toPromise()
.then(() => {
assert.file('pom.xml');
assert.file('README.md');
assert.file('src/main/resources/META-INF/spring/camel-context.xml');
assert.file('src/main/resources/META-INF/spring/camel-context-rest.xml')
});
});
});
With all of this in place, we're able to run toPromise and it waits to do the asserts.
Thank you for the guidance Evan!