Added support for files generated with version 4

This commit is contained in:
Chris 2016-06-15 12:59:16 +02:00
parent 9867271cbb
commit ed4686edd0
19 changed files with 422 additions and 148 deletions

View File

@ -19,23 +19,31 @@ class ComponentGenerator extends Generators.Base {
let settings = utils.yeoman.getAllSettingsFromComponentName(this.name, this.config.get('style'));
let componentType = this.options.stateless ? 'Stateless' : 'Base';
// Set the template base. If it cannot be guessed,
// use files from the default directory. If it cannot be
// guessed, assume we have something REALLY REALLY old here...
let templateBase = this.config.get('generatedWithVersion');
if(!templateBase) {
templateBase = 3;
}
// Create the style template
this.fs.copyTpl(
this.templatePath(`styles/Component${settings.style.suffix}`),
this.templatePath(`${templateBase}/styles/Component${settings.style.suffix}`),
this.destinationPath(settings.style.path + settings.style.fileName),
settings
);
// Create the component
this.fs.copyTpl(
this.templatePath(`components/${componentType}.js`),
this.templatePath(`${templateBase}/components/${componentType}.js`),
this.destinationPath(settings.component.path + settings.component.fileName),
settings
);
// Create the unit test
this.fs.copyTpl(
this.templatePath('tests/Base.js'),
this.templatePath(`${templateBase}/tests/Base.js`),
this.destinationPath(settings.test.path + settings.test.fileName),
settings
);

View File

@ -0,0 +1,20 @@
import React from 'react';
import cssmodules from 'react-css-modules';
import styles from '<%= style.webpackPath %>';
@cssmodules(styles)
class <%= component.className %> extends React.Component {
render() {
return (
<div className="<%= style.className %>" styleName="<%= style.className %>">
Please edit <%= component.path %><%= component.fileName %> to update this component!
</div>
);
}
}
<%= component.className %>.displayName = '<%= component.displayName %>';
<%= component.className %>.propTypes = {};
<%= component.className %>.defaultProps = {};
export default <%= component.className %>;

View File

@ -0,0 +1,18 @@
import React from 'react';
import cssmodules from 'react-css-modules';
import styles from '<%= style.webpackPath %>';
function <%= component.className %>() {
return (
<div className="<%= style.className %>">
Please edit <%= component.path %><%= component.fileName %> to update this component!
</div>
);
}
<%= component.className %>.displayName = '<%= component.displayName %>';
<%= component.className %>.propTypes = {};
<%= component.className %>.defaultProps = {};
export default cssmodules(<%= component.className %>, styles);

View File

@ -0,0 +1,3 @@
.<%= style.className %> {
border: 1px dashed #f00;
}

View File

@ -0,0 +1,3 @@
.<%= style.className %> {
border: 1px dashed #f00;
}

View File

@ -0,0 +1,2 @@
.<%= style.className %>
border: 1px dashed #f00

View File

@ -0,0 +1,3 @@
.<%= style.className %> {
border: 1px dashed #f00;
}

View File

@ -0,0 +1,2 @@
.<%= style.className %>
border 1px dashed #f00

View File

@ -0,0 +1,18 @@
import React from 'react';
import { shallow } from 'enzyme';
import <%= component.className %> from '<%= component.webpackPath %>';
describe('<<%= component.className %> />', () => {
let component;
beforeEach(() => {
component = shallow(<%= component.className %>);
});
describe('when rendering the component', () => {
it('should have a className of "index"', () => {
expect(component.hasClass('<%= style.className %>')).to.equal(true);
});
});
});

View File

@ -94,7 +94,7 @@ describe('react-webpack:app', () => {
'src/actions/README.md',
'src/index.js',
'src/components/App.js',
'src/components/app.css',
'src/components/app.cssmodule.css',
'src/favicon.ico',
'src/images/yeoman.png',
'src/index.html',
@ -116,6 +116,7 @@ describe('react-webpack:app', () => {
});
});
/*
describe.skip('react-webpack:app with PostCSS support', () => {
let prompts = {};
@ -214,3 +215,4 @@ describe.skip('react-webpack:app with PostCSS support', () => {
});
});
});
*/

View File

@ -5,177 +5,372 @@ let helpers = require('yeoman-test');
describe('react-webpack:component', () => {
let generatorComponent = path.join(__dirname, '../../../generators/component');
const generatorComponent = path.join(__dirname, '../../../generators/component');
// List of available style types. Please add a line that says
// testComponentWithStyle(styleTypes.KEY); to the bottom of the file
// to run all unit tests for this filetype.
const styleTypes = {
css: {
type: 'css',
fileName: 'src/styles/Mycomponent.css',
expandedFileName: 'src/styles/my/littleSpecial/Test.css',
assertions: {
componentImport: 'require(\'styles//Mycomponent.css\');',
styleContent: '.mycomponent-component'
}
},
sass: {
type: 'sass',
fileName: 'src/styles/Mycomponent.sass',
expandedFileName: 'src/styles/my/littleSpecial/Test.sass',
assertions: {
componentImport: 'require(\'styles//Mycomponent.sass\');',
styleContent: '.mycomponent-component'
}
},
scss: {
type: 'scss',
fileName: 'src/styles/Mycomponent.scss',
expandedFileName: 'src/styles/my/littleSpecial/Test.scss',
assertions: {
componentImport: 'require(\'styles//Mycomponent.scss\');',
styleContent: '.mycomponent-component'
}
},
less: {
type: 'less',
fileName: 'src/styles/Mycomponent.less',
expandedFileName: 'src/styles/my/littleSpecial/Test.less',
assertions: {
componentImport: 'require(\'styles//Mycomponent.less\');',
styleContent: '.mycomponent-component'
}
},
stylus: {
type: 'stylus',
fileName: 'src/styles/Mycomponent.styl',
expandedFileName: 'src/styles/my/littleSpecial/Test.styl',
assertions: {
componentImport: 'require(\'styles//Mycomponent.styl\');',
styleContent: '.mycomponent-component'
}
}
};
describe('when using version 3 of the generator', () => {
/**
* Return a newly generated component with given name and style
* @param {String} name Name of the component
* @param {String} styleType Styling language to use
* @param {Object} options Options to use for the generator
* @param {Function} callback Test callback to run
*/
function createGeneratedComponent(name, styleType, options, callback) {
helpers.run(generatorComponent)
.withArguments([name])
.withOptions(options)
.on('ready', (instance) => {
instance.config.set('style', styleType);
})
.on('end', callback);
}
// List of available style types. Please add a line that says
// testComponentWithStyle(styleTypes.KEY); to the bottom of the file
// to run all unit tests for this filetype.
const styleTypes = {
css: {
type: 'css',
fileName: 'src/styles/Mycomponent.css',
expandedFileName: 'src/styles/my/littleSpecial/Test.css',
assertions: {
componentImport: 'require(\'styles//Mycomponent.css\');',
styleContent: '.mycomponent-component'
}
},
sass: {
type: 'sass',
fileName: 'src/styles/Mycomponent.sass',
expandedFileName: 'src/styles/my/littleSpecial/Test.sass',
assertions: {
componentImport: 'require(\'styles//Mycomponent.sass\');',
styleContent: '.mycomponent-component'
}
},
scss: {
type: 'scss',
fileName: 'src/styles/Mycomponent.scss',
expandedFileName: 'src/styles/my/littleSpecial/Test.scss',
assertions: {
componentImport: 'require(\'styles//Mycomponent.scss\');',
styleContent: '.mycomponent-component'
}
},
less: {
type: 'less',
fileName: 'src/styles/Mycomponent.less',
expandedFileName: 'src/styles/my/littleSpecial/Test.less',
assertions: {
componentImport: 'require(\'styles//Mycomponent.less\');',
styleContent: '.mycomponent-component'
}
},
stylus: {
type: 'stylus',
fileName: 'src/styles/Mycomponent.styl',
expandedFileName: 'src/styles/my/littleSpecial/Test.styl',
assertions: {
componentImport: 'require(\'styles//Mycomponent.styl\');',
styleContent: '.mycomponent-component'
}
}
};
/**
* Test a component with styling applied
* @param {Object} style The style to apply (see styleTypes above)
* @param {Object} options Options to use [optional]
*/
function testComponentWithStyle(style, options) {
// Make sure we always have options
if(!options) {
options = {};
/**
* Return a newly generated component with given name and style
* @param {String} name Name of the component
* @param {String} styleType Styling language to use
* @param {Object} options Options to use for the generator
* @param {Function} callback Test callback to run
*/
function createGeneratedComponent(name, styleType, options, callback) {
helpers.run(generatorComponent)
.withArguments([name])
.withOptions(options)
.on('ready', (instance) => {
instance.config.set('style', styleType);
instance.config.set('generatedWithVersion', 3);
})
.on('end', callback);
}
describe(`When using style type "${style.type}"`, () => {
/**
* Test a component with styling applied
* @param {Object} style The style to apply (see styleTypes above)
* @param {Object} options Options to use [optional]
*/
function testComponentWithStyle(style, options) {
describe('When writing is called', () => {
// Make sure we always have options
if(!options) {
options = {};
}
it(`should create the react component, its ${style.type}-stylesheet and test file`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
describe(`when using style type "${style.type}"`, () => {
assert.file([
'src/components/MycomponentComponent.js',
style.fileName,
'test/components/MycomponentComponentTest.js'
]);
done();
describe('when writing is called', () => {
it(`should create the react component, its ${style.type}-stylesheet and test file`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.file([
'src/components/MycomponentComponent.js',
style.fileName,
'test/components/MycomponentComponentTest.js'
]);
done();
});
});
});
describe('when creating a component', () => {
it('should always import REACT', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'import React from \'react\';');
done();
});
});
it(`should require the created ${style.type} file`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', style.assertions.componentImport);
done();
});
});
it('should have its displayName set per default', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'displayName = \'MycomponentComponent\';');
done();
});
});
it('should export the created component', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'export default MycomponentComponent');
done();
});
});
it('should be possible to create components in a subfolder', (done) => {
createGeneratedComponent('my/little !special/test', style.type, options, () => {
assert.file([
'src/components/my/littleSpecial/TestComponent.js',
style.expandedFileName,
'test/components/my/littleSpecial/TestComponentTest.js'
]);
done();
});
});
});
describe('Style', () => {
it(`should add the components ${style.type} class to the stylesheet`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent(style.fileName, style.assertions.styleContent);
done();
});
});
});
describe('Test', () => {
it('should import the react component', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
done();
});
});
});
});
}
describe('When creating a component', () => {
// Run all tests for all available style types.
testComponentWithStyle(styleTypes.css);
testComponentWithStyle(styleTypes.sass);
testComponentWithStyle(styleTypes.scss);
testComponentWithStyle(styleTypes.less);
testComponentWithStyle(styleTypes.stylus);
it('should always import REACT', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'import React from \'react\';');
done();
// Test stateless components (should be enough when testing with defaults)
testComponentWithStyle(styleTypes.css, { stateless: true });
});
describe('when using version 4 of the generator', () => {
// List of available style types. Please add a line that says
// testComponentWithStyle(styleTypes.KEY); to the bottom of the file
// to run all unit tests for this filetype.
const styleTypes = {
css: {
type: 'css',
fileName: 'src/styles/Mycomponent.css',
expandedFileName: 'src/styles/my/littleSpecial/Test.css',
assertions: {
componentImport: 'import styles from \'styles//Mycomponent.css\';',
styleContent: '.mycomponent-component'
}
},
sass: {
type: 'sass',
fileName: 'src/styles/Mycomponent.sass',
expandedFileName: 'src/styles/my/littleSpecial/Test.sass',
assertions: {
componentImport: 'import styles from \'styles//Mycomponent.sass\';',
styleContent: '.mycomponent-component'
}
},
scss: {
type: 'scss',
fileName: 'src/styles/Mycomponent.scss',
expandedFileName: 'src/styles/my/littleSpecial/Test.scss',
assertions: {
componentImport: 'import styles from \'styles//Mycomponent.scss\';',
styleContent: '.mycomponent-component'
}
},
less: {
type: 'less',
fileName: 'src/styles/Mycomponent.less',
expandedFileName: 'src/styles/my/littleSpecial/Test.less',
assertions: {
componentImport: 'import styles from \'styles//Mycomponent.less\';',
styleContent: '.mycomponent-component'
}
},
stylus: {
type: 'stylus',
fileName: 'src/styles/Mycomponent.styl',
expandedFileName: 'src/styles/my/littleSpecial/Test.styl',
assertions: {
componentImport: 'import styles from \'styles//Mycomponent.styl\';',
styleContent: '.mycomponent-component'
}
}
};
/**
* @var {yeoman.generator} generator
* Global generator instance, set by createGeneratedComponent
*/
let generator;
/**
* Return a newly generated component with given name and style
* @param {String} name Name of the component
* @param {String} styleType Styling language to use
* @param {Object} options Options to use for the generator
* @param {Function} callback Test callback to run
*/
function createGeneratedComponent(name, styleType, options, callback) {
helpers.run(generatorComponent)
.withArguments([name])
.withOptions(options)
.on('ready', (instance) => {
instance.config.set('style', styleType);
instance.config.set('generatedWithVersion', 4);
generator = instance;
})
.on('end', callback);
}
/**
* Test a component with styling applied
* @param {Object} style The style to apply (see styleTypes above)
* @param {Object} options Options to use [optional]
*/
function testComponentWithStyle(style, options) {
// Make sure we always have options
if(!options) {
options = {};
}
describe(`when using style type "${style.type}"`, () => {
describe('when writing is called', () => {
it(`should create the react component, its ${style.type}-stylesheet and test file`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.file([
'src/components/MycomponentComponent.js',
style.fileName,
'test/components/MycomponentComponentTest.js'
]);
done();
});
});
});
it(`should require the created ${style.type} file`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', style.assertions.componentImport);
done();
describe('when creating a component', () => {
it('should always import REACT', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'import React from \'react\';');
done();
});
});
it(`should require the created ${style.type} file`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', style.assertions.componentImport);
done();
});
});
it('should have its displayName set per default', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'displayName = \'MycomponentComponent\';');
done();
});
});
it('should export the created component', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
let exportAssertion;
if(generator.options.stateless) {
exportAssertion = 'export default cssmodules(MycomponentComponent, styles);';
} else {
exportAssertion = 'export default MycomponentComponent';
}
assert.fileContent('src/components/MycomponentComponent.js', exportAssertion);
done();
});
});
it('should be possible to create components in a subfolder', (done) => {
createGeneratedComponent('my/little !special/test', style.type, options, () => {
assert.file([
'src/components/my/littleSpecial/TestComponent.js',
style.expandedFileName,
'test/components/my/littleSpecial/TestComponentTest.js'
]);
done();
});
});
});
it('should have its displayName set per default', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'displayName = \'MycomponentComponent\';');
done();
describe('Style', () => {
it(`should add the components ${style.type} class to the stylesheet`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent(style.fileName, style.assertions.styleContent);
done();
});
});
});
it('should export the created component', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('src/components/MycomponentComponent.js', 'export default MycomponentComponent');
done();
});
});
describe('Test', () => {
it('should be possible to create components in a subfolder', (done) => {
createGeneratedComponent('my/little !special/test', style.type, options, () => {
assert.file([
'src/components/my/littleSpecial/TestComponent.js',
style.expandedFileName,
'test/components/my/littleSpecial/TestComponentTest.js'
]);
done();
it('should import the react component', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
done();
});
});
});
});
}
describe('Style', () => {
// Run all tests for all available style types.
testComponentWithStyle(styleTypes.css);
testComponentWithStyle(styleTypes.sass);
testComponentWithStyle(styleTypes.scss);
testComponentWithStyle(styleTypes.less);
testComponentWithStyle(styleTypes.stylus);
it(`should add the components ${style.type} class to the stylesheet`, (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent(style.fileName, style.assertions.styleContent);
done();
});
});
});
// Test stateless components (should be enough when testing with defaults)
testComponentWithStyle(styleTypes.css, { stateless: true });
});
describe('Test', () => {
it('should import the react component', (done) => {
createGeneratedComponent('mycomponent', style.type, options, () => {
assert.fileContent('test/components/MycomponentComponentTest.js', 'import MycomponentComponent from \'components//MycomponentComponent.js\';');
done();
});
});
});
});
}
// Run all tests for all available style types.
testComponentWithStyle(styleTypes.css);
testComponentWithStyle(styleTypes.sass);
testComponentWithStyle(styleTypes.scss);
testComponentWithStyle(styleTypes.less);
testComponentWithStyle(styleTypes.stylus);
// Test stateless components (should be enough when testing with defaults)
testComponentWithStyle(styleTypes.css, { stateless: true });
});