├── logo.png ├── preview.gif ├── test ├── conditions │ ├── simple-config │ │ └── gue.json │ ├── wrong-template │ │ └── gue.json │ ├── right-template │ │ ├── gue.json │ │ └── right.vue │ └── default-template │ │ ├── gue.json │ │ ├── black.vue │ │ └── white.vue ├── templates │ ├── myUnitTmp.js │ └── myVueTmp.vue ├── cleanup.js └── index.js ├── src ├── config.js ├── utils.js ├── templates │ ├── sample-component.js │ └── sample-unit.js ├── bin.js ├── logger.js └── index.js ├── .travis.yml ├── .gitignore ├── LICENSE ├── package.json └── README.md /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/gue/master/logo.png -------------------------------------------------------------------------------- /preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hosein2398/gue/master/preview.gif -------------------------------------------------------------------------------- /test/conditions/simple-config/gue.json: -------------------------------------------------------------------------------- 1 | { 2 | "componentRoot": "./somewhereYouLike" 3 | } -------------------------------------------------------------------------------- /test/conditions/wrong-template/gue.json: -------------------------------------------------------------------------------- 1 | { 2 | "componentSource": { 3 | "some" : "./sefsfsf", 4 | "another" : "./nowhere" 5 | } 6 | } -------------------------------------------------------------------------------- /test/conditions/right-template/gue.json: -------------------------------------------------------------------------------- 1 | { 2 | "componentSource": { 3 | "some" : "./some/sdf.vue", 4 | "right" : "./right.vue" 5 | } 6 | } -------------------------------------------------------------------------------- /test/conditions/default-template/gue.json: -------------------------------------------------------------------------------- 1 | { 2 | "componentSource": { 3 | "white" : "./white.vue", 4 | "black:default" : "./black.vue" 5 | } 6 | } -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | const JoyCon = require('joycon'); 2 | 3 | const joycon = new JoyCon(); 4 | 5 | const conf = joycon.loadSync(['gue.json']); 6 | 7 | module.exports = conf; 8 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | exports.isObject = obj => obj !== null && obj.constructor.name === 'Object'; 2 | 3 | exports.isObjectEmpty = obj => !Object.keys(obj).length; 4 | 5 | exports.findDefault = obj => Object.keys(obj).find(i => i.split(':').length > 1); 6 | 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | os: 3 | - linux 4 | - osx 5 | 6 | cache: 7 | directories: 8 | - node_modules 9 | - $HOME/.npm 10 | 11 | node_js: 12 | - "10" 13 | 14 | services: 15 | - xvfb 16 | before_script: 17 | - npm install 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node build artifacts 2 | node_modules 3 | npm-debug.log 4 | doc 5 | .nyc_output 6 | 7 | # Local development 8 | *.env 9 | *.dev 10 | .DS_Store 11 | 12 | # Docker 13 | Dockerfile 14 | docker-compose.yml 15 | 16 | # File Manager(dolphin) 17 | .directory -------------------------------------------------------------------------------- /test/templates/myUnitTmp.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import <%NAME%> from '<%PATH%>' 3 | 4 | describe('custom Gue test file', () => { 5 | it('here is a test', () => { 6 | const defaultData = <%NAME%>.data() 7 | expect(defaultData.gue).toBe('cool!') 8 | }) 9 | 10 | }) -------------------------------------------------------------------------------- /test/conditions/right-template/right.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | export default { 8 | name: "<%NAME%>", 9 | props: [], 10 | mounted() { 11 | 12 | }, 13 | data() { 14 | return { 15 | test: null 16 | } 17 | }, 18 | methods: { 19 | 20 | }, 21 | computed: { 22 | 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/templates/sample-component.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | 7 | 8 | export default { 9 | name: "<%NAME%>", 10 | props: [], 11 | mounted() { 12 | 13 | }, 14 | data() { 15 | return { 16 | 17 | } 18 | }, 19 | methods: { 20 | 21 | }, 22 | computed: { 23 | 24 | } 25 | } 26 | 27 | 32 | `; 33 | -------------------------------------------------------------------------------- /test/conditions/default-template/black.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | export default { 8 | name: "<%NAME%>", 9 | props: [], 10 | mounted() { 11 | 12 | }, 13 | data() { 14 | return { 15 | test: null 16 | } 17 | }, 18 | methods: { 19 | 20 | }, 21 | computed: { 22 | 23 | } 24 | } 25 | 26 | 28 | -------------------------------------------------------------------------------- /test/conditions/default-template/white.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | export default { 8 | name: "<%NAME%>", 9 | props: [], 10 | mounted() { 11 | 12 | }, 13 | data() { 14 | return { 15 | test: null 16 | } 17 | }, 18 | methods: { 19 | 20 | }, 21 | computed: { 22 | 23 | } 24 | } 25 | 26 | 28 | -------------------------------------------------------------------------------- /test/templates/myVueTmp.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | export default { 8 | name: "<%NAME%>", 9 | props: [], 10 | mounted() { 11 | 12 | }, 13 | data() { 14 | return { 15 | test: null 16 | } 17 | }, 18 | methods: { 19 | 20 | }, 21 | computed: { 22 | 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/templates/sample-unit.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | import Vue from 'vue' 3 | import <%NAME%> from '<%PATH%>' 4 | 5 | describe('created method', () => { 6 | it('sets the correct default data', () => { 7 | const defaultData = <%NAME%>.data() 8 | expect(defaultData.message).toBe('hello!') 9 | }) 10 | 11 | it('correctly sets the message when created', () => { 12 | const vm = new Vue(<%NAME%>).$mount() 13 | expect(vm.message).toBe('bye!') 14 | }) 15 | 16 | }) 17 | `; 18 | -------------------------------------------------------------------------------- /test/cleanup.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const rimraf = require('rimraf'); 4 | 5 | const directory = './test'; 6 | const files = fs.readdirSync(directory); 7 | 8 | for (const file of files) { 9 | const doNotRemove = [ 10 | 'index.js', 11 | '.nyc_output', 12 | 'cleanup.js', 13 | 'gue.json', 14 | 'templates', 15 | 'conditions' 16 | ]; 17 | if (doNotRemove.includes(file)) { 18 | continue; 19 | } 20 | 21 | rimraf.sync(path.join(directory, file)); 22 | } 23 | -------------------------------------------------------------------------------- /src/bin.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const program = require('commander'); 3 | const logger = require('./logger'); 4 | const Gue = require('.'); 5 | 6 | program 7 | .arguments(' [direcroty]') 8 | .option('-u, --unit', 'create unit test of the component too') 9 | .option('-t, --template ', 'define which template to use'); 10 | 11 | const params = program.parse(process.argv); 12 | 13 | try { 14 | // eslint-disable-next-line no-negated-condition 15 | if (!params.args[0]) { 16 | logger.warn(` 17 | You must supply a name for your component 18 | Usage: gue [directory] [options]`); 19 | } else { 20 | const gue = new Gue(params.args[0], params.args[1], params); 21 | gue.generate(); 22 | } 23 | } catch (error) { 24 | logger.error(error); 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (C) Hosein Barzegaran 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/logger.js: -------------------------------------------------------------------------------- 1 | const box = require('boxen'); 2 | const chalk = require('chalk'); 3 | class Logger { 4 | success(name, dir, type) { 5 | console.log( 6 | box( 7 | `${chalk.hex('#45d03c')('✔️')} Created ${chalk.hex('#45d03c')( 8 | name 9 | )} ${type} in ${chalk.hex('#45d03c')(dir)}`, 10 | { 11 | padding: 1 12 | } 13 | ) 14 | ); 15 | } 16 | 17 | duplicate(name, dir, type) { 18 | console.log( 19 | box( 20 | `${chalk.hex('#e6e600')('💡')} You already have ${chalk.hex('#e6e600')( 21 | name 22 | )} ${type} in ${chalk.hex('#e6e600')(dir)}`, 23 | {padding: 1} 24 | ) 25 | ); 26 | } 27 | 28 | warn(m) { 29 | console.log( 30 | box( 31 | `${chalk.hex('#e6e600')('💡')} ${m}`, 32 | {padding: 1} 33 | ) 34 | ); 35 | } 36 | 37 | error(e) { 38 | console.log( 39 | box(`⚠️ ${chalk.red('Oops something went wrong')}`, {padding: 1}) 40 | ); 41 | console.log(e); 42 | } 43 | 44 | fatal(e) { 45 | console.log( 46 | box(`⚠️ ${chalk.red(e)}`, {padding: 1}) 47 | ); 48 | throw new Error(e); 49 | } 50 | } 51 | 52 | module.exports = new Logger(); 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-gue", 3 | "version": "0.2.0", 4 | "description": "Vue component generator", 5 | "repository": { 6 | "url": "https://github.com/hosein2398/gue", 7 | "type": "git" 8 | }, 9 | "author": "Hosein2398", 10 | "keywords": [ 11 | "vue", 12 | "cli", 13 | "component", 14 | "generate", 15 | "generate component" 16 | ], 17 | "files": [ 18 | "src" 19 | ], 20 | "license": "MIT", 21 | "main": "src/index.js", 22 | "scripts": { 23 | "lint": "xo", 24 | "cleanTestDir": "node ./test/cleanup.js", 25 | "pretest": "npm run cleanTestDir", 26 | "test": "cd test && ../node_modules/.bin/tap ./index.js", 27 | "posttest": "npm run cleanTestDir", 28 | "commit": "git-cz" 29 | }, 30 | "bin": { 31 | "gue": "src/bin.js" 32 | }, 33 | "dependencies": { 34 | "boxen": "^4.1.0", 35 | "chalk": "^2.4.2", 36 | "commander": "^3.0.2", 37 | "joycon": "^2.2.5" 38 | }, 39 | "devDependencies": { 40 | "commitizen": "^4.0.3", 41 | "cz-conventional-changelog": "^3.0.2", 42 | "husky": "^3.0.9", 43 | "rimraf": "^3.0.0", 44 | "tap": "^14.7.2", 45 | "xo": "^0.25.3" 46 | }, 47 | "xo": { 48 | "space": true, 49 | "rules": { 50 | "no-unused-expressions": [ 51 | "error", 52 | { 53 | "allowShortCircuit": true 54 | } 55 | ] 56 | }, 57 | "ignore": [ 58 | "./test/templates/myUnitTmp.js" 59 | ] 60 | }, 61 | "config": { 62 | "commitizen": { 63 | "path": "./node_modules/cz-conventional-changelog" 64 | } 65 | }, 66 | "husky": { 67 | "hooks": { 68 | "pre-commit": "npm run lint" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | const logger = require('./logger'); 5 | const configFile = require('./config'); 6 | const cmpTemplate = require('./templates/sample-component'); 7 | const unitTemplate = require('./templates/sample-unit'); 8 | const {isObject, findDefault, isObjectEmpty} = require('./utils'); 9 | 10 | class Gue { 11 | constructor(componentName, distDir, options) { 12 | this.componentName = componentName; 13 | this.options = options; 14 | const config = configFile.data; 15 | this.componentSource = config && config.componentSource ? config.componentSource : ''; 16 | this.componentRoot = config && config.componentRoot ? config.componentRoot : ''; 17 | this.unitSource = config && config.unitSource ? config.unitSource : ''; 18 | this.unitRoot = config && config.unitRoot ? config.unitRoot : './tests/unit/'; 19 | this.distDir = distDir ? 20 | distDir : 21 | (this.componentRoot ? 22 | '' : 23 | './src/components'); 24 | } 25 | 26 | generate() { 27 | this.writeComponent(); 28 | this.options.unit && this.writeUnit(); 29 | } 30 | 31 | writeComponent() { 32 | const dir = this.makeComponentDistDir(); 33 | const data = this.formatComponent(dir); 34 | // TODO: if there was error in writing this dir should not be created too 35 | this.checkDirStatus(dir); 36 | this.checkFileStatus(dir, 'component') && 37 | fs.writeFileSync(dir, data) === undefined && // Since this method returns undefined 38 | logger.success(this.componentName, dir, 'component'); 39 | } 40 | 41 | writeUnit() { 42 | const dir = this.makeUnitDistDir(); 43 | const data = this.formatUnit(dir); 44 | this.checkDirStatus(dir); 45 | this.checkFileStatus(dir, 'test file') && 46 | fs.writeFileSync(dir, data) === undefined && 47 | logger.success(this.componentName, dir, 'test file'); 48 | } 49 | 50 | formatComponent() { 51 | let data; 52 | if (this.options.template) { 53 | this.checkConfigExist(); 54 | if (!isObject(this.componentSource)) { 55 | logger.fatal('When using -t your componentSource must be an object'); 56 | } 57 | 58 | if (isObject(this.componentSource)) { 59 | if (!(this.options.template in this.componentSource)) { 60 | logger.fatal(`There is no "${this.options.template}" template in componentSource in gue config file`); 61 | } 62 | 63 | data = fs.readFileSync(this.componentSource[this.options.template], {encoding: 'utf8'}); 64 | } 65 | } else if (isObject(this.componentSource)) { 66 | const defaultTemplate = findDefault(this.componentSource); 67 | if (!defaultTemplate) { 68 | logger.fatal('No default component defined in componentSource object'); 69 | } 70 | 71 | data = fs.readFileSync(this.componentSource[defaultTemplate], {encoding: 'utf8'}); 72 | } else { 73 | data = this.componentSource ? 74 | fs.readFileSync(this.componentSource, {encoding: 'utf8'}) : 75 | cmpTemplate; 76 | } 77 | 78 | const rex = /<%NAME%>/g; 79 | return data.replace(rex, this.componentName); 80 | } 81 | 82 | formatUnit() { 83 | let data = this.unitSource ? 84 | fs.readFileSync(this.unitSource, {encoding: 'utf8'}) : 85 | unitTemplate; 86 | const rexName = /<%NAME%>/g; 87 | const rexPath = /<%PATH%>/g; 88 | // Want first argumet to be directory not a file 89 | const unitPath = path.relative(this.makeUnitDistDir().split('/').slice(0, -1).join('/'), this.makeComponentDistDir()); 90 | data = data.replace(rexName, this.componentName); 91 | return data.replace(rexPath, unitPath); 92 | } 93 | 94 | makeComponentDistDir() { 95 | return path.join( 96 | this.componentRoot, 97 | this.distDir, 98 | `${this.componentName}.vue` 99 | ); 100 | } 101 | 102 | makeUnitDistDir() { 103 | return path.join(this.unitRoot, `${this.componentName}.js`); 104 | } 105 | 106 | checkDirStatus(direcrories) { 107 | const spilitedDirs = direcrories.split('/'); 108 | // Since we don't need .vue in our path 109 | const removeLast = spilitedDirs.slice(0, -1); 110 | const joinedDirs = removeLast.join('/'); 111 | const exists = fs.existsSync(joinedDirs); 112 | if (!exists) { 113 | fs.mkdirSync(joinedDirs, {recursive: true}); 114 | } 115 | } 116 | 117 | checkFileStatus(dirs, type) { 118 | if (fs.existsSync(dirs)) { 119 | logger.duplicate(this.componentName, dirs, type); 120 | return false; 121 | } 122 | 123 | return true; 124 | } 125 | 126 | checkConfigExist() { 127 | if (isObjectEmpty(configFile)) { 128 | logger.fatal('Could not find any config file in root directory'); 129 | } 130 | } 131 | 132 | run() { 133 | this.generate(); 134 | } 135 | } 136 | 137 | module.exports = Gue; 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Gue [![Build Status](https://travis-ci.org/hosein2398/gue.svg?branch=master)](https://travis-ci.org/hosein2398/gue) [![Coverage Status](https://coveralls.io/repos/github/hosein2398/gue/badge.svg?branch=master&kill_cache=1)](https://coveralls.io/github/hosein2398/gue?branch=master) 3 | 4 | 5 | 6 | > Vue js component generator 7 | 8 |

9 | 10 |

11 | 12 | ## Demo 13 |

14 | 15 |

16 | 17 | 18 | Features 19 | * 📜 Generate Vue component 20 | * 🧰 Generate test file for the component 21 | * ⚙️ Dynamic path for component 22 | * 📁 Configurable root directory for components and tests 23 | * 📝 Custom templates for components and test 24 | ## Installing 25 | > Note that this package is published under name of `vue-gue` 26 | ``` 27 | npm i -g vue-gue 28 | ``` 29 | 30 | ## Getting started 31 | Head over to root of your project in terminal, say you want to create a component named `footer`: 32 | ``` 33 | gue footer 34 | ``` 35 | This will generate `footer` component in `./src/components/footer.vue` 36 | #### Change directory of component 37 | You can define a directory which you want your component to be generated in. 38 | ``` 39 | gue tab ./menu 40 | ``` 41 | This will generate `tab` component in `./menu/tab.vue` 42 | > Consider behavior of directory parameter when you have a config file and you don't. [details](#usage) 43 | > For a consistent way to change root directory of components see [config](#config-file). 44 | 45 | #### Generate test file 46 | Now if you want a component and also it's corresponding unit test file you can do: 47 | ``` 48 | gue footer -u 49 | ``` 50 | This will generate `footer` component in `./src/components/footer.vue` and also a test file in `./tests/unit/footer.js` 51 | > To change any of these directories see [config](#config-file) 52 | ## Usage 53 | General usage is like: 54 | ``` 55 | $ gue --help 56 | 57 | Usage: gue [direcroty] [options] 58 | 59 | Options: 60 | -u, --unit create unit test of the component too 61 | -t, --template define which template to use 62 | -h, --help output usage information 63 | 64 | ``` 65 | * <componentName> is mandatory. 66 | * [directory] is optional, and is a relative path. 67 | If you have a config file this will be a `subdirectory` of your [componentRoot](#options) 68 | If you don't, then this will lead to generation of component in exact `direcroty` 69 | * [options] are optional, available options are `-u` which will generate test file, and `-t` which is used to define which template for components to use. 70 | 71 | ## Config file 72 | Gue accepts a config file to change default settings. In root directory of project make a file `gue.json`, and Gue will automatically recognize and use it. 73 | #### Options 74 | Here are available options for config file: 75 | * `componentRoot`: root directory which components will be generated in. should be relative path. 76 | * `componentSource`: path to custom component template. Or an object to define [multiple templates](#using-multiple-custom-templates). 77 | * `unitRoot`: directory which test will be generated in. should be a relative path. 78 | * `unitSource`: path to custom test file template. 79 | 80 | An example of a config file with all options: 81 | ```json 82 | { 83 | "componentRoot":"./front-end/src/components", 84 | "unitRoot":"./front-end/test", 85 | "componentSource":"./myTemplates/myVueTemplate.vue", 86 | "unitSource":"./myTemplates/myTestTemplate.js" 87 | } 88 | ``` 89 | Now if you run gue to create a `clock` component in your project, it'll generate it in `./front-end/src/components/clock.vue`. 90 | If you run following command in the same project: 91 | ``` 92 | gue title ./header 93 | ``` 94 | Will generate `./front-end/src/components/header/title.vue` 95 | 96 | #### Custom templates 97 | As said you can use custom templates in Gue, define path to them with `componentSource` and `unitSource` so that Gue will use them instead of it's default ones. 98 | ##### Variables 99 | In your component template you can use variable `<%NAME%>` and Gue will replace it with name of component when generating. 100 | And also in test template you use `<%NAME%>` and `<%PATH%>` which will be replaced with path where component is located, relative to path of test file. 101 | Here is an example of custom component template: 102 | ``` 103 | 108 | 109 | export default { 110 | name: "<%NAME%>", 111 | data() { 112 | return { 113 | someData: "a sample" 114 | } 115 | } 116 | 118 | ``` 119 | To see other examples look at [templates folder](https://github.com/hosein2398/gue/tree/master/src/templates). 120 | ##### Using multiple custom templates 121 | You can use multiple custom templates. So `componentSource` can be object (multiple templates) or a string (single template). Multiple templates can be created like: 122 | ```json 123 | { 124 | "componentSource": { 125 | "component" : "./tmps/component.vue", 126 | "page" : "./tmps/page.vue" 127 | } 128 | } 129 | ``` 130 | And when using Gue you have to tell it which component template to use: 131 | ``` 132 | gue menu -t component 133 | gue setting ./pages -t page 134 | ``` 135 | You can define one of your templates as `default` one, so that you don't have to type `-t` every time. Default component can be specified with `:default` postfix: 136 | ```json 137 | { 138 | "componentSource": { 139 | "component:default" : "./tmps/component.vue", 140 | "page" : "./tmps/page.vue" 141 | } 142 | } 143 | ``` 144 | Now if you type any command without `-t`, component template will be used. 145 | ``` 146 | gue foo 147 | ``` 148 | Will use `component` template to generate foo component. No need of `-t component` -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const tap = require('tap'); 4 | const Gue = require('../src'); 5 | const defaultVueTemplate = require('../src/templates/sample-component'); 6 | const defaultUnitTemplate = require('../src/templates/sample-unit'); 7 | 8 | const initCwd = process.cwd(); 9 | 10 | function getContent(dir) { 11 | return fs.readFileSync(dir, {encoding: 'utf8'}); 12 | } 13 | 14 | function formatComponent(name, comp) { 15 | const data = comp; 16 | const rex = /<%NAME%>/g; 17 | return data.replace(rex, name); 18 | } 19 | 20 | function formatTest(name, unitPath, tmp) { 21 | let data = tmp; 22 | const rexName = /<%NAME%>/g; 23 | const rexPath = /<%PATH%>/g; 24 | data = data.replace(rexName, name); 25 | return data.replace(rexPath, unitPath); 26 | } 27 | 28 | /* 29 | * Since we want to test diffrent config files and config files are 30 | * recognized automatically from root dir, we need to change cwd 31 | * every time. And since config file gets resolved only once when 32 | * you require the module(here ./src module) we need to clear cache of 33 | * require so when we change the directory, the module ./src/config gets 34 | * evaluated again and it recognizes config file in new cwd. 35 | */ 36 | function cleanCacheAndChageCwd(dir) { 37 | delete require.cache[require.resolve('../src/config')]; 38 | delete require.cache[require.resolve('../src')]; 39 | process.chdir(path.resolve(initCwd, dir)); 40 | } 41 | 42 | const customVueTemplate = getContent('./templates/myVueTmp.vue'); 43 | const customUnitTemplate = getContent('./templates/myUnitTmp.js'); 44 | 45 | tap.test('Without dir parameter', t => { 46 | const name = 'firstTest'; 47 | const dir = './src/components/firstTest.vue'; 48 | const gue = new Gue(name, null, {}); 49 | gue.run(); 50 | t.plan(1); 51 | t.equal(getContent(dir), formatComponent(name, defaultVueTemplate)); 52 | }); 53 | 54 | tap.test('With directory parameter', t => { 55 | const name = 'secondTest'; 56 | const dir = './somewhere/secondTest.vue'; 57 | const gue = new Gue(name, './somewhere', {}); 58 | gue.run(); 59 | t.plan(1); 60 | t.equal(getContent(dir), formatComponent(name, defaultVueTemplate)); 61 | }); 62 | 63 | tap.test('With test param and without dir parameter', t => { 64 | const name = 'thirdTest'; 65 | const dir = './src/components/thirdTest.vue'; 66 | const testDir = './tests/unit/thirdTest.js'; 67 | const gue = new Gue(name, null, {unit: true}); 68 | gue.run(); 69 | t.plan(2); 70 | t.equal(getContent(dir), formatComponent(name, defaultVueTemplate)); 71 | t.equal( 72 | getContent(testDir), 73 | formatTest(name, '../../src/components/thirdTest.vue', defaultUnitTemplate) 74 | ); 75 | }); 76 | 77 | tap.test('With test param and with dir parameter', t => { 78 | const name = 'fourthTest'; 79 | const dir = './path-to-nowhere/fourthTest.vue'; 80 | const testDir = './tests/unit/fourthTest.js'; 81 | const gue = new Gue(name, 'path-to-nowhere', {unit: true}); 82 | gue.run(); 83 | t.plan(2); 84 | t.equal(getContent(dir), formatComponent(name, defaultVueTemplate)); 85 | t.equal( 86 | getContent(testDir), 87 | formatTest(name, '../../path-to-nowhere/fourthTest.vue', defaultUnitTemplate) 88 | ); 89 | }); 90 | 91 | tap.test('Duplicate', t => { 92 | const name = 'firstTest'; 93 | const dir = './src/components/firstTest.vue'; 94 | const gue = new Gue(name, null, {}); 95 | t.plan(1); 96 | t.false(gue.checkFileStatus(dir, 'component')); 97 | }); 98 | 99 | tap.test('Custom component file', t => { 100 | const name = 'fifthTest'; 101 | const dir = './src/components/fifthTest.vue'; 102 | const gue = new Gue(name, null, {}); 103 | gue.componentSource = './templates/myVueTmp.vue'; 104 | gue.run(); 105 | t.plan(1); 106 | t.equal(getContent(dir), formatComponent(name, customVueTemplate)); 107 | }); 108 | 109 | tap.test('Custom test file', t => { 110 | const name = 'seventhTest'; 111 | const testDir = './tests/unit/seventhTest.js'; 112 | const gue = new Gue(name, null, {unit: true}); 113 | gue.unitSource = './templates/myUnitTmp.js'; 114 | gue.run(); 115 | t.plan(1); 116 | t.equal(getContent(testDir), formatTest(name, '../../src/components/seventhTest.vue', customUnitTemplate)); 117 | }); 118 | 119 | tap.test('Custom root dir for component && custom component file && sub directory', t => { 120 | const name = 'eighthTest'; 121 | const dir = './custom-root/subdir/eighthTest.vue'; 122 | const gue = new Gue(name, 'subdir', {}); 123 | gue.componentRoot = './custom-root'; 124 | gue.componentSource = './templates/myVueTmp.vue'; 125 | gue.run(); 126 | t.plan(1); 127 | t.equal(getContent(dir), formatComponent(name, customVueTemplate)); 128 | }); 129 | 130 | tap.test('Custom root dir for test && custom test file', t => { 131 | const name = 'ninthTest'; 132 | const testDir = './custom-unit-root/ninthTest.js'; 133 | const gue = new Gue(name, null, {unit: true}); 134 | gue.unitRoot = './custom-unit-root'; 135 | gue.unitSource = './templates/myUnitTmp.js'; 136 | gue.run(); 137 | t.plan(1); 138 | t.equal(getContent(testDir), formatTest(name, '../src/components/ninthTest.vue', customUnitTemplate)); 139 | }); 140 | 141 | tap.test('Should throw when there is -t but componentSource is not object', t => { 142 | cleanCacheAndChageCwd('./conditions/simple-config'); 143 | const Gue = require('../src'); 144 | const name = 'tenthTest'; 145 | const gue = new Gue(name, null, {template: 'foo'}); 146 | t.plan(1); 147 | // TODO: check the exact error 148 | t.throw(() => { 149 | gue.generate(); 150 | }); 151 | }); 152 | 153 | tap.test('Should throw when template name is not in config', t => { 154 | cleanCacheAndChageCwd('./conditions/wrong-template'); 155 | const Gue = require('../src'); 156 | const name = 'eleventhTest'; 157 | const gue = new Gue(name, null, {template: 'foo'}); 158 | t.plan(1); 159 | // TODO: check the exact error 160 | t.throw(() => { 161 | gue.generate(); 162 | }); 163 | }); 164 | 165 | tap.test('Should work with multiple templates and choose right one', t => { 166 | cleanCacheAndChageCwd('./conditions/right-template'); 167 | const Gue = require('../src'); 168 | const name = 'twelvethTest'; 169 | // Note that we are now in: ./conditions/right-template 170 | const dir = './src/components/twelvethTest.vue'; 171 | const cutomTemplateDir = './right.vue'; 172 | const gue = new Gue(name, null, {template: 'right'}); 173 | gue.run(); 174 | t.plan(1); 175 | t.equal(getContent(dir), formatComponent(name, getContent(cutomTemplateDir))); 176 | }); 177 | 178 | tap.test('Should throw when componentSource is object but there is not default template(and -t is not passed of course)', t => { 179 | cleanCacheAndChageCwd('./conditions/right-template'); 180 | const Gue = require('../src'); 181 | const name = 'foo'; 182 | const gue = new Gue(name, null, {}); 183 | t.plan(1); 184 | t.throw(() => { 185 | gue.generate(); 186 | }); 187 | }); 188 | 189 | tap.test('Should recognize default template when there is no -t', t => { 190 | cleanCacheAndChageCwd('./conditions/default-template'); 191 | const Gue = require('../src'); 192 | const name = 'iBlack'; 193 | // Note that we are now in: ./conditions/default-template 194 | const dir = './src/components/iBlack.vue'; 195 | const cutomTemplateDir = './black.vue'; 196 | const gue = new Gue(name, null, {}); 197 | gue.run(); 198 | t.plan(1); 199 | t.equal(getContent(dir), formatComponent(name, getContent(cutomTemplateDir))); 200 | }); 201 | --------------------------------------------------------------------------------