custom yeoman generator test: creating files - javascript

I've got a very simple yeoman generator, watchjs, that has speaker subgenerator. Below is hos it is used:
$ yo watchjs:speaker
You called the watch.js speaker subgenerator.
? Speaker file: data/speakers/speakers.json
? Speaker name: abc
{ file: 'data/speakers/speakers.json', name: 'abc' }
Generated slug is: abc
Trying to add: {
"id": "abc",
"name": "abc"
}
Mainly, there are two prompts: file - which defines the json file where data should be appended to and name - which defines actual data to be added to the file (slightly modified). I'm trying to write a simple yeoman test for this. I've been trying to follow the docs, but I'm failing all the time:
$ npm test
> generator-watchjs#0.0.2 test c:\Users\tomasz.ducin\Documents\GitHub\generator-watchjs
> mocha
Watchjs:speaker
{ file: 'speakers.json', name: 'John Doe' } // <- this is my console.log
1) "before all" hook
0 passing (59ms)
1 failing
1) Watchjs:speaker "before all" hook:
Uncaught Error: ENOENT, no such file or directory 'C:\Users\TOMASZ~1.DUC\AppData\Local\Temp\53dac48785ddecb6dabba402eeb04f91e322f844\speakers.json'
at Object.fs.openSync (fs.js:439:18)
at Object.fs.readFileSync (fs.js:290:15)
at module.exports.yeoman.generators.Base.extend.writing (c:\Users\tomasz.ducin\Documents\GitHub\generator-watchjs\speaker\index.js:43:33)
npm ERR! Test failed. See above for more details.
I can't understand where is the file actually created and where are the tests looking for it... There seems to be used a temporary windows location, but anyway, if all things work properly relative to the path, the file should have been found and it's not. Can't figure out what to do to make tests pass.
The best content of my test file is:
'use strict';
var path = require('path');
var assert = require('yeoman-generator').assert;
var helpers = require('yeoman-generator').test;
describe('watchjs:speaker', function () {
before(function (done) {
helpers.run(path.join(__dirname, '../speaker'))
.withOptions({ 'skip-install': true })
.withPrompts({ 'file': 'speakers.json', 'name': "John Doe" })
.on('end', done);
});
it('creates files', function () {
assert.file([
'speakers.json'
]);
});
});
I'm passing a specific name and file name via prompt.
I've found out that npm test call package.json's mocha command (and that's it). But I'm not an expert in mocha.
I'm using node v0.10.35 on Windows7.

First, you should use absolute paths in your test, so the location of the file is predictable.
My test would look something like this:
'use strict';
var fs = require('fs');
var path = require('path');
var assert = require('yeoman-generator').assert;
var helpers = require('yeoman-generator').test;
describe('watchjs:speaker', function () {
before(function (done) {
var self = this;
var name = 'John Doe';
var testPath = path.join(__dirname, 'temp');
// store in test obejct for later use
this.filePath = path.join(testPath, 'speaker.json');
helpers.run(path.join(__dirname, '../speaker'))
.inDir(testPath)
.withPrompts({ 'file': self.filePath, 'name': name })
.withOptions({ 'skip-install': true })
.on('end', done);
});
it('creates files', function () {
assert.file(this.filePath);
assert.fileContent(this.filePath, /\"id\":.*\"john-doe\"/);
assert.fileContent(this.filePath, /\"name\":.*\"John Doe\"/);
});
});
Second, and not directly related to your question, the test above will on the code in the repo you shared. Like I mentioned in my comment, it throws an error here if the file doesn't already exist.
I would change:
var content = JSON.parse(fs.readFileSync(this.options.file, 'utf8'));
to:
try {
var content = JSON.parse(fs.readFileSync(this.options.file, 'utf8'));
} catch(e) {
content = [];
}
With the change above, the test will pass.

Related

Cypress - How to get data of individual test like its title, state etc

I am trying to get data about single test in Cypress like title, state etc so I can create custom reporter. But none of the below options in forEach are working. It returns undefined, but when I pass normal string like 'abcd' it gets printed on console. So how do i get attributes of the test.
first.spec.js
/// <reference types="cypress" />
context('Actions', () => {
afterEach(()=> {
const testData = cy.state('runnable').currentTest;
cy.task('testOutput', {title: testData.title, state: testData.state, fullTitle: testData.fullTitle()});
// also tried
// Cypress.on('test:after:run', (test, runnable)=> {
//cy.task('testOutput', {title: runnable.title, state:runnable.state, fullTitle: runnable.fullTitle()});
//)};
});
it('test 1',()=>{
const assets = Cypress.env('assetoverride');
cy.getVar(assets);
})
});
plugin/index.js
module.exports = (on, config) => {
on('task', {
testOutput({title, state, fullTitle}){
console.log(`Test ${fullTitle} - ${state} - ${title}`)
return null;
}
});
}
If you are executing your tests localy you can run them in hedless mode by running command:
npx cypress run --spec "e2e/integration/NameOfYourTestFile.spec.js" --browser chrome --headless
This way you will get table with results in the terminal:
enter image description here

Storing global variable in a separate file for Protractor Tests

I am trying to create a separate inventory file for Protractor Test where I can store all the reusable variable to be used by different test scrips. The sample Variable list is called Vars.js and the specs should import the variables from this file and consume those. However, this fails as shown below. Can this approach actually be used for storing reusable variables? Can I actually create a separate inventory file for protractor tests outside of conf.js?
Vars.js has the following content :
"use strict";
exports.config = {
function() {
global.loginMain = 'https://mytestsite.com/auth/login';
global.TestText = 'I am the test Text';
}
};
and the spec file is as follows:
require ('./Vars.js')
require('..\\waitAbsent.js')
require("../node_modules/jasmine-expect/index.js")
describe('Vairables Import Test', function() {
console.log(global.loginMain);
console.log(global.TestText);
browser.get(global.loginMain);
it('Text Validation', function(){
expect(browser.getCurrentUrl()).toEqual('https://mytestsite.com/auth/login')
})
});
The log
[10:55:29] I/local - Selenium standalone server started at http://192.168.1.187:51256/wd/hub
undefined
undefined
Started
(node:17800) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods
instead.
F
Failures:
1) Vairables Import Test encountered a declaration exception
Message:
TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received type undefined
Stack:
TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received type undefined
at Url.parse (url.js:152:11)
at urlParse (url.js:146:13)
at Url.resolve (url.js:661:29)
at Object.urlResolve [as resolve] (url.js:657:40)
at ProtractorBrowser.get (C:\FCPS_I\FCPS\node_modules\protractor\built\browser.js:653:17)
at Suite.<anonymous> (C:\FCPS_I\FCPS\TestBed_Scripts\TestBed.js:10:13)
at Object.<anonymous> (C:\FCPS_I\FCPS\TestBed_Scripts\TestBed.js:5:1)
1 spec, 1 failure
Update: a revised Vars.js where I used params as shown below also return the same failure.
"use strict";
exports.config = {
params: {
loginMain: 'https://dss-esy.insystechinc.com/auth/login',
TestText : 'I am the test Text',
}
};
The below approach should work for you.
conf.js
exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['app.js'],
onPrepare: async() => {
global.globalVariables = require('./globalVariables');
}
};
app.js
describe('desribe the test', () => {
it('the it', async () => {
console.log(globalVariables.loginMain);
console.log(globalVariables.TestText);
})
})
globalVariables.js
module.exports = {
loginMain :'https://mytestsite.com/auth/login',
TestText : 'I am the test Text'
}

Multiple functions with onPrepare in Protractor

I have a conf.js file in my Protractor test suite.
There was a single onPrepare entry at first but now I wish to add a second.
I'm struggling to get the syntax right so that what follows onPrepare is error free.
Original entry:
onPrepare: function() {
jasmine.getEnv().addReporter(reporter);
},
and the second entry is:
const protractorImageComparison = require('protractor-image-comparison');
browser. protractorImageComparison = new protractorImageComparison(
{
baselineFolder: 'path/to/baseline/',
screenshotPath: 'path/to/save/actual/screenshots/'
}
);
},
}
Do I need to add a second function() above const?
Have you try as below?
A tip: onPrepare is the only one place in protractor conf file you can use the variable: browser, because only when run to this function the browser variable initialize complete.
onPrepare: function() {
jasmine.getEnv().addReporter(reporter);
const protractorImageComparison = require('protractor-image-comparison');
browser.protractorImageComparison = new protractorImageComparison(
{
baselineFolder: 'path/to/baseline/',
screenshotPath: 'path/to/save/actual/screenshots/'
}
);
},

yeoman sub-generator testing with composeWith

I have a generator-generator app with its own local sub-generator app. The situation is that I want the sub-generator to invoke atleast once with pre-defined argument when I run the main 'app' generator. Everything works fine except the npm test fails.
Main 'app' generator: yo mygen.
Sub generator: yo mygen:foo "lorem ipsum".
Here is the test.js
/*global describe, beforeEach, it*/
'use strict';
var path = require('path'),
yg = require('yeoman-generator');
var helpers = require('yeoman-generator').test;
var assert = require('yeoman-assert');
describe(' running `yo mygen`', function () {
before(function (done) {
var deps = [
[helpers.createDummyGenerator(), 'mygen:foo', 'blah blah blah']
];
helpers.run(path.join(__dirname, '../app'))
.inDir(path.join(__dirname, './temp')) // Clear the directory and set it as the CWD
.withOptions({ mongoose: 'app', 'skip-install': true }) // Mock options passed in
.withPrompts({
'dbName': 'demo',
'useUserAuth': false
})
.withGenerators(deps)
.on('end', done);
//done();
});
it('can be imported without blowing up', function () {
var app = require('../app');
assert(app !== undefined);
});
it('creates all required MVC files', function (done) {
var expected = [
// add files you expect to exist here.
'package.json',
'app.js',
'bower.json',
'routes/index.js',
'public/css/style.css',
'public/js/script.js',
'views/index.html',
'README.md',
'.editorconfig',
'.jshintrc'
];
assert.file(expected);
done();
});
});
describe('í ¼ running `yo mygen:foo`', function () {
before(function (done) {
helpers.run(path.join(__dirname, '../schema'))
.inDir(path.join(__dirname, './temp')) // Clear the directory and set it as the CWD
.withOptions({ mongoose: 'schema' }) // Mock options passed in
.withArguments(['ha ha ha ha hha'])
.on('end', done);
//done();
});
describe('foo generator', function () {
it('foo can be imported without blowing up', function () {
var app = require('../foo');
assert(app !== undefined);
});
it('created new MVC files for foo', function (done) {
var expected = [
// add files you expect to exist here.
'view/t1.js',
'models/t1.js',
'controller/t1.js'
];
assert.file(expected);
done();
})
});
});
And in app/index.js, in order to invoke the sub-generator, i have used:
mygenGenerator.prototype.install = function install(){
this.installDependencies();
this.composeWith("mygen:foo", {args: ["humpty dumpty saton a wall"]});
};
Searched all possible answers on stackoverflow and everywhere else. Can't figure out what to do.
Test Cases for npm test fails:
Remove the composeWith line from index.js and the test passes.
keep the composeWith line, the test goes to infinity, eventually exceed 2000ms quota and failing.

Loading external file from Karma/Jasmine test

I'm trying to accomplish a Jasmine test (using Karma and IntelliJ 13) to validate JSON files. Ideally, my test would simply load a JSON file into a data object, then let me parse through to check for valid formatting and data. I don't need to validate functions before or after, nor do I need to test against a server.
My basic setup is like this:
it("should load an external file", function(){
var asyncCallComplete, result,
_this = this;
// asyncCallComplete is set to true when the ajax call is complete
asyncCallComplete = false;
// result stores the result of the successful ajax call
result = null;
// SECTION 1 - call asynchronous function
runs(function() {
return $.ajax('/test/config.json', {
type: 'GET',
success: function(data) {
asyncCallComplete = true;
result = data;
},
error: function() {
asyncCallComplete = true;
}
});
});
// SECTION 2 - wait for the asynchronous call to complete
waitsFor(function() {
return asyncCallComplete !== false;
}, "async to complete");
// SECTION 3 - perform tests
return runs(function() {
return expect(result).not.toBeNull();
});
}
The problem is that no matter what path I use, I get a 404 error and the file won't load. I've tried loading an external JSON result from a remote server using this test service:
http://date.jsontest.com/
And this works.
My test file is named /test/mySpec.js and my karma.conf.js file is on the root. I have moved around the JSON file to all of these locations with no luck. What am I doing wrong?
UPDATE WITH ANSWER:
Per the answer below, I added this to my karma.conf.js:
// fixtures
{ pattern: 'test/*.json',
watched: true,
served: true,
included: false
}
Then, I wrote my test this way:
var json:any;
it("should load a fixture", function () {
jasmine.getFixtures().fixturesPath = "base/test/"
var f = readFixtures("registration.json");
json = JSON.parse(f);
expect(json).toBeDefined();
})
it("should have a title", function () {
expect(json.title).toNotBe(null);
})
etc...
And it passes.
Are you serving the JSON file via karma.config.js?
You can serve JSON files via fixture:
files: [
// angular
'angular.min.js',
'angular-route.js',
'angular-mocks.js',
// jasmine jquery helper
'jquery-1.10.2.min.js',
'jasmine-jquery.js',
// app
'../../public/js/app.js',
// tests
'*-spec.js',
// JSON fixture
{ pattern: '/test/*.json',
watched: true,
served: true,
included: false }
],
Serving JSON via the fixture is the easiest but because of our setup we couldn't do that easily so I wrote an alternative helper function:
Install
bower install karma-read-json
Usage
Put karma-read-json.js in your Karma files, Example:
files = [
...
'bower_components/karma-read-json/karma-read-json.js',
...
]
Make sure your JSON is being served by Karma, Example:
files = [
...
{pattern: 'json/**/*.json', included: false},
...
]
Use the readJSON function in your tests. Example:
var valid_respond = readJSON('json/foobar.json');
$httpBackend.whenGET(/.*/).respond(valid_respond);
If you are trying to load a HTML file and want to avoid using jasmine-jquery, you may take advantage of the karma-ng-html2js-preprocessor.
In your karma.conf.js :
// generate js files from html templates
preprocessors: {
'resources/*.html': 'ng-html2js'
},
files: [
...
'resources/*.html'
],
plugins: [
...
'karma-ng-html2js-preprocessor'
],
In your jasmine spec :
beforeEach(module('resources/fragment.html'));
var $templateCache;
beforeEach(inject(function (_$templateCache_) {
$templateCache = _$templateCache_;
}));
describe('some test', function () {
it('should do something', function () {
// --> load the fragment.html content from the template cache <--
var fragment = $templateCache.get('resources/fragment.html');
expect(fragment).toBe(...);
});
});
Have you tried simply requiring the json file and storing it as a global variable in your test?
I'm developing an Angular2 project right now (using the Angular CLI), and with this setup it works:
// On the very beginning of the file
let mockConfig = require('./test/config.json');

Categories

Resources