From 2cb3da01f5c6af19e08ce8daf0a0c5f4f87a4451 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Mon, 6 Jan 2020 18:41:05 +0100 Subject: [PATCH 01/15] feat(scully): pick commits for prompts picked commits from https://github.com/scullyio/scully/issues/100 --- schematics/scully/src/add-post/schema.json | 26 +++++++++---------- .../scully/src/create-markdown/schema.json | 6 +++-- schematics/scully/src/ng-add/schema.json | 23 ++++++++-------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/schematics/scully/src/add-post/schema.json b/schematics/scully/src/add-post/schema.json index 204a4aa4c..5f2650210 100644 --- a/schematics/scully/src/add-post/schema.json +++ b/schematics/scully/src/add-post/schema.json @@ -1,14 +1,14 @@ - { - "$schema": "http://json-schema.org/schema", - "id": "Scully-ng-add-blog", - "title": "Scully ng-add-blog schematic", - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "add the title for the post" - } - }, - "required": [] - } + "$schema": "http://json-schema.org/schema", + "id": "Scully-ng-add-blog", + "title": "Scully ng-add-blog schematic", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "add the title for the post", + "x-prompt": "What title do you want to use for the post?" + } + }, + "required": [] +} diff --git a/schematics/scully/src/create-markdown/schema.json b/schematics/scully/src/create-markdown/schema.json index c5d477e6c..1f70cdb0d 100644 --- a/schematics/scully/src/create-markdown/schema.json +++ b/schematics/scully/src/create-markdown/schema.json @@ -12,11 +12,13 @@ }, "name": { "type": "string", - "description": "add the name for the folder and module" + "description": "add the name for the folder and module", + "x-prompt": "What name do you want to use for the folder and module?" }, "slug": { "type": "string", - "description": "add the name for the :${slug}" + "description": "add the name for the :${slug}", + "x-prompt": "What slug do you want for the markdown file?" } }, "required": [] diff --git a/schematics/scully/src/ng-add/schema.json b/schematics/scully/src/ng-add/schema.json index 640d11330..88586f643 100644 --- a/schematics/scully/src/ng-add/schema.json +++ b/schematics/scully/src/ng-add/schema.json @@ -1,13 +1,14 @@ { - "$schema": "http://json-schema.org/schema", - "id": "scully-ng-add", - "title": "scully ng-add schematic", - "type": "object", - "properties": { - "blog": { - "type": "boolean", - "description": "add full blog" - } - }, - "required": [] + "$schema": "http://json-schema.org/schema", + "id": "scully-ng-add", + "title": "scully ng-add schematic", + "type": "object", + "properties": { + "blog": { + "type": "boolean", + "description": "add full blog", + "x-prompt": "Should we set up a blog for you?" + } + }, + "required": [] } From 268e4eac446e918d8d349f33d6ec2e85b5ced8ae Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Mon, 6 Jan 2020 19:58:18 +0100 Subject: [PATCH 02/15] feat(scully): add options for @scullyio/init:markdown --- .../scully/src/create-markdown/index.ts | 54 +++++++++-------- .../scully/src/create-markdown/schema.json | 28 ++++++--- .../scully/src/create-markdown/schema.ts | 21 ++++++- schematics/scully/src/utils/utils.ts | 59 +++++++++---------- 4 files changed, 96 insertions(+), 66 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index afbb500d0..3b48c431b 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -1,50 +1,56 @@ -import { Rule, Tree, url, applyTemplates, move, chain, SchematicContext } from '@angular-devkit/schematics'; -import { strings, normalize } from '@angular-devkit/core'; +import {Rule, Tree, url, applyTemplates, move, chain, SchematicContext} from '@angular-devkit/schematics'; +import {strings, normalize} from '@angular-devkit/core'; import {Schema as MyServiceSchema} from './schema'; import {addRouteToModule, addRouteToScullyConfig, applyWithOverwrite, getPrefix} from '../utils/utils'; export default function(options: MyServiceSchema): Rule { return (host: Tree, context: SchematicContext) => { try { - options.name = options.name ? options.name : 'blog'; const name = options.name; - const nameD = strings.dasherize(options.name); + const nameDasherized = strings.dasherize(options.name); + const sourceDir = options.sourceDir + ? strings.dasherize(options.sourceDir) // use sourceDir when provided + : strings.dasherize(options.name); // fall back to name when not provided const date = new Date(); const fullDay = `${date.getMonth() + 1}-${date.getDate()}-${date.getFullYear()}`; - const path = `./${nameD}/${fullDay}-${nameD}.md`; + const path = `./${sourceDir}/${fullDay}-${nameDasherized}.md`; if (!host.exists(path)) { - host.create(path, `--- + host.create( + path, + `--- title: This is the ${name} description: ${name} description publish: false --- # Page ${name} example -`); - context.logger.info(`✅ ${fullDay}-${nameD} file created`); +` + ); + context.logger.info(`✅ ${path} file created`); } - let scullyJson; + let scullyJs; try { - scullyJson = (host.read('/scully.config.js')).toString(); + scullyJs = host.read('/scully.config.js').toString(); } catch (e) { // for test in schematics - scullyJson = `exports.config = { + scullyJs = `exports.config = { projectRoot: "./src/app", routes: { - '/demo/:id': { - type: 'fake', - numberOfPages: 100 - }, }, };`; } - options.slug = options.slug ? options.slug : 'id'; - const newScullyJson = addRouteToScullyConfig(scullyJson, {name, slug: options.slug, type: 'contentFolder'}); + const newScullyJson = addRouteToScullyConfig(scullyJs, { + name, + slug: options.slug, + type: 'contentFolder', + sourceDir: options.sourceDir, + route: options.route, + }); host.overwrite(`/scully.config.js`, newScullyJson); context.logger.info('✅️ Update scully.config.js'); - options.path = options.path ? options.path : strings.dasherize(`./src/app/${name}`); + const pathName = strings.dasherize(`./src/app/${name}`); let prefix = 'app'; if (host.exists('./angular.json')) { prefix = getPrefix(host.read('./angular.json').toString()); @@ -57,16 +63,12 @@ publish: false dasherize: strings.dasherize, name: options.name, slug: options.slug, - prefix + prefix, }), - move(normalize(options.path as string)) + move(normalize(pathName)), ]); - return chain([ - templateSource - ]); - - } catch (e) { } + return chain([templateSource]); + } catch (e) {} }; } - diff --git a/schematics/scully/src/create-markdown/schema.json b/schematics/scully/src/create-markdown/schema.json index 1f70cdb0d..f6f28ef9d 100644 --- a/schematics/scully/src/create-markdown/schema.json +++ b/schematics/scully/src/create-markdown/schema.json @@ -4,22 +4,36 @@ "title": "scully create markdown module schematic", "type": "object", "properties": { + "name": { + "type": "string", + "description": "add the name for the module", + "x-prompt": "What name do you want to use for the folder and module?", + "default": "blog" + }, + "slug": { + "type": "string", + "description": "add the name for the :${slug}", + "x-prompt": "What slug do you want for the markdown file?", + "default": "id" + }, "routingScope": { "enum": ["Child", "Root"], "type": "string", "description": "The scope for the new routing module.", "default": "Child" }, - "name": { + "sourceDir": { "type": "string", - "description": "add the name for the folder and module", - "x-prompt": "What name do you want to use for the folder and module?" + "description": "add the name for the source dir to store the markdown files", + "x-prompt": "Where do you want to store your markdown files?", + "default": "blog" }, - "slug": { + "route": { "type": "string", - "description": "add the name for the :${slug}", - "x-prompt": "What slug do you want for the markdown file?" + "description": "define the route where your post will be available", + "x-prompt": "Under which route do you want your files to be requested?", + "default": "blog" } }, - "required": [] + "required": ["name", "slug"] } diff --git a/schematics/scully/src/create-markdown/schema.ts b/schematics/scully/src/create-markdown/schema.ts index c62ba62a8..5687890b3 100644 --- a/schematics/scully/src/create-markdown/schema.ts +++ b/schematics/scully/src/create-markdown/schema.ts @@ -1,5 +1,22 @@ export interface Schema { + /** + * add the name for the module + */ name: string; - path?: string; - slug?: string; + /** + * add the name for the :${slug} + */ + slug: string; + /** + * The scope for the new routing module. + */ + routingScope?: 'Child' | 'Root'; + /** + * add the name for the source dir to store the markdown files + */ + sourceDir?: string; + /** + * define the route where your post will be available + */ + route?: string; } diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index bd5648c46..0f4305da1 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -1,8 +1,8 @@ import {apply, forEach, mergeWith, Rule, SchematicContext, Source, Tree} from '@angular-devkit/schematics'; import {normalize, strings} from '@angular-devkit/core'; -import { buildRelativePath } from '@schematics/angular/utility/find-module'; -import { addRouteDeclarationToModule } from '@schematics/angular/utility/ast-utils'; +import {buildRelativePath} from '@schematics/angular/utility/find-module'; +import {addRouteDeclarationToModule} from '@schematics/angular/utility/ast-utils'; import ts = require('@schematics/angular/third_party/github.com/Microsoft/TypeScript/lib/typescript'); import {InsertChange} from '@schematics/angular/utility/change'; import {ModuleOptions} from '@schematics/angular/utility/find-module'; @@ -11,27 +11,31 @@ interface Data { name: string; type: string; slug: string; + sourceDir?: string; + route?: string; } export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { - const addRoute = `\n '/${strings.dasherize(data.name)}/:${data.slug}': { + const baseRoute = data.route ? strings.dasherize(data.route) : strings.dasherize(data.name); + const contentDirectoy = data.sourceDir ? strings.dasherize(data.sourceDir) : strings.dasherize(data.name); + const addRoute = `\n '/${baseRoute}/:${data.slug}': { type: '${data.type}', ${data.slug}: { - folder: "./${strings.dasherize(data.name)}" + folder: "./${contentDirectoy}" } },`; - let output; - if (+scullyConfigJs.search(/routes: \{/g) > 0) { - const position = +scullyConfigJs.search(/routes: \{/g) + 'routes: {'.length; - output = [scullyConfigJs.slice(0, position), addRoute, scullyConfigJs.slice(position)].join(''); - } else if (+scullyConfigJs.search(/routes:\{/g) > 0) { - const position = +scullyConfigJs.search(/routes:\{/g) + 'routes:{'.length; - output = [scullyConfigJs.slice(0, position), addRoute, scullyConfigJs.slice(position)].join(''); - } else { - console.log('Scully can\'t found the scully.config.js'); - return scullyConfigJs; - } - return output; + let output; + if (+scullyConfigJs.search(/routes: \{/g) > 0) { + const position = +scullyConfigJs.search(/routes: \{/g) + 'routes: {'.length; + output = [scullyConfigJs.slice(0, position), addRoute, scullyConfigJs.slice(position)].join(''); + } else if (+scullyConfigJs.search(/routes:\{/g) > 0) { + const position = +scullyConfigJs.search(/routes:\{/g) + 'routes:{'.length; + output = [scullyConfigJs.slice(0, position), addRoute, scullyConfigJs.slice(position)].join(''); + } else { + console.log(`Scully can't find the scully.config.js`); + return scullyConfigJs; + } + return output; } /* @@ -53,27 +57,24 @@ function needComa(fullText: string, matchs: string[]) { } */ - export function applyWithOverwrite(source: Source, rules: Rule[]): Rule { return (tree: Tree, context: SchematicContext) => { const rule = mergeWith( apply(source, [ ...rules, - forEach((fileEntry) => { + forEach(fileEntry => { if (tree.exists(fileEntry.path)) { tree.overwrite(fileEntry.path, fileEntry.content); return null; } return fileEntry; }), - - ]), + ]) ); return rule(tree, context); }; } - export function getPrefix(angularjson: string) { const angularJSON = JSON.parse(angularjson); const prefixs = []; @@ -84,13 +85,12 @@ export function getPrefix(angularjson: string) { if (prefixs.length > 1) { // TODO: ask for prefix we need return prefixs[0].prefix; - } else if (prefixs.length === 1) { + } else if (prefixs.length === 1) { return prefixs[0].prefix; } } export function addRouteToModule(host: Tree, options: any) { - let path = './src/app/app-routing.module.ts'; if (!host.exists(path)) { path = './src/app/app.module.ts'; @@ -104,28 +104,25 @@ export function addRouteToModule(host: Tree, options: any) { const addDeclaration = addRouteDeclarationToModule( ts.createSourceFile(path, sourceText, ts.ScriptTarget.Latest, true), path, - buildRoute(options, 'app.module'), + buildRoute(options, 'app.module', options.route) ) as InsertChange; const recorder = host.beginUpdate(path); recorder.insertLeft(addDeclaration.pos, addDeclaration.toAdd); host.commitUpdate(recorder); - } -function buildRoute(options: ModuleOptions, modulePath: string) { +function buildRoute(options: ModuleOptions, modulePath: string, route?: string) { const relativeModulePath = buildRelativeModulePath(options, modulePath); const moduleName = `${strings.classify(options.name)}Module`; const loadChildren = `() => import('${relativeModulePath}').then(m => m.${moduleName})`; - return `{ path: '${options.name}', loadChildren: ${loadChildren} }`; + const basePath = route ? strings.dasherize(route) : strings.dasherize(options.name); + return `{ path: '${basePath}', loadChildren: ${loadChildren} }`; } function buildRelativeModulePath(options: ModuleOptions, modulePath: string): string { // tslint:disable-next-line:no-shadowed-variable - const importModulePath = normalize(`/${options.name}/` - + strings.dasherize(options.name) - + '.module', - ); + const importModulePath = normalize(`/${options.name}/` + strings.dasherize(options.name) + '.module'); return buildRelativePath(modulePath, importModulePath); } From 30778545520a74593fe7c8e92c9ba7cd79430a44 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Mon, 6 Jan 2020 20:08:49 +0100 Subject: [PATCH 03/15] fix(scully): fix x-prompt description --- schematics/scully/src/create-markdown/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematics/scully/src/create-markdown/schema.json b/schematics/scully/src/create-markdown/schema.json index f6f28ef9d..a0e6457d6 100644 --- a/schematics/scully/src/create-markdown/schema.json +++ b/schematics/scully/src/create-markdown/schema.json @@ -7,7 +7,7 @@ "name": { "type": "string", "description": "add the name for the module", - "x-prompt": "What name do you want to use for the folder and module?", + "x-prompt": "What name do you want to use for the module?", "default": "blog" }, "slug": { From 31e1ebdd7ad990de14efb7155ad7214dcf54ce6a Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Mon, 6 Jan 2020 20:09:08 +0100 Subject: [PATCH 04/15] fix(scully): use yyyy-mm-dd format --- schematics/scully/src/create-markdown/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 3b48c431b..9ea1b2a89 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -12,7 +12,8 @@ export default function(options: MyServiceSchema): Rule { ? strings.dasherize(options.sourceDir) // use sourceDir when provided : strings.dasherize(options.name); // fall back to name when not provided const date = new Date(); - const fullDay = `${date.getMonth() + 1}-${date.getDate()}-${date.getFullYear()}`; + // format yyyy-mm-dd + const fullDay = date.toISOString().substring(0, 10); const path = `./${sourceDir}/${fullDay}-${nameDasherized}.md`; if (!host.exists(path)) { host.create( From d082dda680989459e61e42d14f9c112c80868c2e Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Mon, 6 Jan 2020 20:30:41 +0100 Subject: [PATCH 05/15] feat(scully): provide options for @scullyio/init:post --- schematics/scully/src/add-post/index.ts | 23 ++++++++++--------- schematics/scully/src/add-post/schema.json | 11 +++++++-- schematics/scully/src/add-post/schema.ts | 12 +++++++++- .../scully/src/create-markdown/index.ts | 17 ++++++++------ 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/schematics/scully/src/add-post/index.ts b/schematics/scully/src/add-post/index.ts index 1137eb0d5..368b60a97 100644 --- a/schematics/scully/src/add-post/index.ts +++ b/schematics/scully/src/add-post/index.ts @@ -1,27 +1,28 @@ -import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics'; +import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {Schema} from './schema'; -import { strings } from '@angular-devkit/core'; +import {strings} from '@angular-devkit/core'; export default function(options: Schema): Rule { return (host: Tree, context: SchematicContext) => { - - const name = options.name ? options.name : 'blog-X'; - const namD = options.name ? strings.dasherize(options.name) : 'blog-X'; - if (!host.exists(`./blog/${namD}.md`)) { - host.create(`./blog/${namD}.md`, - `--- + const name = options.name; + const nameDasherized = options.name ? strings.dasherize(options.name) : 'blog-X'; + const targetDasherized = options.target ? strings.dasherize(options.target) : 'blog'; + if (!host.exists(`./${targetDasherized}/${nameDasherized}.md`)) { + host.create( + `./blog/${nameDasherized}.md`, + `--- title: ${name} description: blog description publish: false --- # ${name} -`); - context.logger.info(`✅️Blog ${name} file created`); +` + ); + context.logger.info(`✅️ Blog ${name} file created`); } else { // return name exist throw new SchematicsException(`${name} exist in your blog folder`); } }; } - diff --git a/schematics/scully/src/add-post/schema.json b/schematics/scully/src/add-post/schema.json index 5f2650210..d5b2a3904 100644 --- a/schematics/scully/src/add-post/schema.json +++ b/schematics/scully/src/add-post/schema.json @@ -7,8 +7,15 @@ "name": { "type": "string", "description": "add the title for the post", - "x-prompt": "What title do you want to use for the post?" + "x-prompt": "What title do you want to use for the post?", + "default": "blog-X" + }, + "target": { + "type": "string", + "description": "define the target directory for the new post file", + "x-prompt": "What's the target folder for this post?", + "default": "blog" } }, - "required": [] + "required": ["name"] } diff --git a/schematics/scully/src/add-post/schema.ts b/schematics/scully/src/add-post/schema.ts index 6b7dd9502..85600185e 100644 --- a/schematics/scully/src/add-post/schema.ts +++ b/schematics/scully/src/add-post/schema.ts @@ -1,3 +1,13 @@ +/** + * Scully ng-add-blog schematic + */ export interface Schema { - name: string; + /** + * add the title for the post + */ + name: string; + /** + * define the target directory for the new post file + */ + target?: string; } diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 9ea1b2a89..8973effc0 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -3,10 +3,13 @@ import {strings, normalize} from '@angular-devkit/core'; import {Schema as MyServiceSchema} from './schema'; import {addRouteToModule, addRouteToScullyConfig, applyWithOverwrite, getPrefix} from '../utils/utils'; +const SCULLY_CONF_FILE = '/scully.config.js'; +const ANGULAR_CONF_FILE = './angular.json'; + export default function(options: MyServiceSchema): Rule { return (host: Tree, context: SchematicContext) => { try { - const name = options.name; + const name = options.name ? options.name : 'blog'; const nameDasherized = strings.dasherize(options.name); const sourceDir = options.sourceDir ? strings.dasherize(options.sourceDir) // use sourceDir when provided @@ -32,7 +35,7 @@ publish: false let scullyJs; try { - scullyJs = host.read('/scully.config.js').toString(); + scullyJs = host.read(SCULLY_CONF_FILE).toString(); } catch (e) { // for test in schematics scullyJs = `exports.config = { @@ -45,16 +48,16 @@ publish: false name, slug: options.slug, type: 'contentFolder', - sourceDir: options.sourceDir, + sourceDir, route: options.route, }); - host.overwrite(`/scully.config.js`, newScullyJson); - context.logger.info('✅️ Update scully.config.js'); + host.overwrite(SCULLY_CONF_FILE, newScullyJson); + context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); const pathName = strings.dasherize(`./src/app/${name}`); let prefix = 'app'; - if (host.exists('./angular.json')) { - prefix = getPrefix(host.read('./angular.json').toString()); + if (host.exists(ANGULAR_CONF_FILE)) { + prefix = getPrefix(host.read(ANGULAR_CONF_FILE).toString()); addRouteToModule(host, options); } From 01f4531ea24013e3efe4503632ad0d1a33f0f80d Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 07:13:22 +0100 Subject: [PATCH 06/15] fix(scully): fix filename for post --- schematics/scully/src/add-post/index.ts | 9 +-- schematics/scully/src/collection.json | 1 + schematics/scully/src/ng-add/index_spec.ts | 39 +++++++++++ .../scully/src/ng-add/package-config.ts | 42 +++++------- schematics/scully/src/scully/index.ts | 18 ++--- schematics/scully/src/scully/index_spec.ts | 41 +++++++++-- schematics/scully/src/scully/schema.ts | 3 + schematics/scully/src/utils/test-utils.ts | 25 +++++++ schematics/scully/src/utils/utils.ts | 68 ++++++++++++++++++- 9 files changed, 201 insertions(+), 45 deletions(-) create mode 100644 schematics/scully/src/ng-add/index_spec.ts create mode 100644 schematics/scully/src/scully/schema.ts create mode 100644 schematics/scully/src/utils/test-utils.ts diff --git a/schematics/scully/src/add-post/index.ts b/schematics/scully/src/add-post/index.ts index 368b60a97..b28b9c9f1 100644 --- a/schematics/scully/src/add-post/index.ts +++ b/schematics/scully/src/add-post/index.ts @@ -7,9 +7,10 @@ export default function(options: Schema): Rule { const name = options.name; const nameDasherized = options.name ? strings.dasherize(options.name) : 'blog-X'; const targetDasherized = options.target ? strings.dasherize(options.target) : 'blog'; - if (!host.exists(`./${targetDasherized}/${nameDasherized}.md`)) { + const filename = `./${targetDasherized}/${nameDasherized}.md`; + if (!host.exists(filename)) { host.create( - `./blog/${nameDasherized}.md`, + filename, `--- title: ${name} description: blog description @@ -19,10 +20,10 @@ publish: false # ${name} ` ); - context.logger.info(`✅️ Blog ${name} file created`); + context.logger.info(`✅️ Blog ${filename} file created`); } else { // return name exist - throw new SchematicsException(`${name} exist in your blog folder`); + throw new SchematicsException(`${nameDasherized} exist in your ${targetDasherized} folder`); } }; } diff --git a/schematics/scully/src/collection.json b/schematics/scully/src/collection.json index 73c41df6c..a08a20285 100644 --- a/schematics/scully/src/collection.json +++ b/schematics/scully/src/collection.json @@ -1,5 +1,6 @@ { "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", + "id": "scully-schematics", "schematics": { "ng-add": { "description": "Add scully to the application.", diff --git a/schematics/scully/src/ng-add/index_spec.ts b/schematics/scully/src/ng-add/index_spec.ts new file mode 100644 index 000000000..59c91c39d --- /dev/null +++ b/schematics/scully/src/ng-add/index_spec.ts @@ -0,0 +1,39 @@ +import {HostTree} from '@angular-devkit/schematics'; +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; +import {getFileContent} from '@schematics/angular/utility/test'; +import * as path from 'path'; + +import {setupProject} from '../utils/test-utils'; +import {Schema} from './schema'; +import {scullyVersion, scullyComponentVersion} from './version-names'; + +const collectionPath = path.join(__dirname, '../collection.json'); +const PACKAGE_JSON_PATH = '/package.json'; + +describe('scully', () => { + const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); + const project = 'foo'; + const defaultOptions: Schema = { + blog: true, + }; + let appTree: UnitTestTree; + + beforeEach(async () => { + appTree = new UnitTestTree(new HostTree()); + appTree = await setupProject(appTree, schematicRunner, project); + }); + + describe('when using the default options', () => { + beforeEach(async () => { + appTree = await schematicRunner.runSchematicAsync('ng-add', defaultOptions, appTree).toPromise(); + }); + + it('should add dependencies', () => { + const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); + const {dependencies} = packageJson; + expect(appTree.files).toContain(PACKAGE_JSON_PATH); + expect(dependencies['@scullyio/ng-lib']).toEqual(scullyVersion); + expect(dependencies['@scullyio/scully']).toEqual(scullyComponentVersion); + }); + }); +}); diff --git a/schematics/scully/src/ng-add/package-config.ts b/schematics/scully/src/ng-add/package-config.ts index 6493c1025..63aa9dd32 100644 --- a/schematics/scully/src/ng-add/package-config.ts +++ b/schematics/scully/src/ng-add/package-config.ts @@ -7,49 +7,41 @@ */ import {Tree} from '@angular-devkit/schematics'; +import {overwritePackageJson, getPackageJson, PackageJsonConfigPart} from '../utils/utils'; /** * Sorts the keys of the given object. * @returns A new object instance with sorted keys */ -function sortObjectByKeys(obj: object) { - // @ts-ignore - return Object.keys(obj).sort().reduce((result, key) => (result[key] = obj[key]) && result, {}); +function sortObjectByKeys(obj: PackageJsonConfigPart) { + // @ts-ignore + return Object.keys(obj) + .sort() + .reduce((result: any, key: string) => (result[key] = obj[key]) && result, {}); } /** Adds a package to the package.json in the given host tree. */ -export function addPackageToPackageJson(host: Tree, pkg: string, version: string): Tree { +export function addPackageToPackageJson(hostTree: Tree, pkg: string, version: string): Tree { + const packageJson = getPackageJson(hostTree); - if (host.exists('package.json')) { - const sourceText = host.read('package.json')!.toString('utf-8'); - const json = JSON.parse(sourceText); - - if (!json.dependencies) { - json.dependencies = {}; - } - - if (!json.dependencies[pkg]) { - json.dependencies[pkg] = version; - json.dependencies = sortObjectByKeys(json.dependencies); - } - - host.overwrite('package.json', JSON.stringify(json, null, 2)); + if (!packageJson.dependencies) { + packageJson.dependencies = {}; } - return host; + if (!packageJson.dependencies[pkg]) { + packageJson.dependencies[pkg] = version; + packageJson.dependencies = sortObjectByKeys(packageJson.dependencies); + } + return overwritePackageJson(hostTree, packageJson); } /** Gets the version of the specified package by looking at the package.json in the given tree. */ export function getPackageVersionFromPackageJson(tree: Tree, name: string): string | null { - if (!tree.exists('package.json')) { - return null; - } - - const packageJson = JSON.parse(tree.read('package.json')!.toString('utf8')); + const packageJson = getPackageJson(tree); if (packageJson.dependencies && packageJson.dependencies[name]) { return packageJson.dependencies[name]; } return null; -} \ No newline at end of file +} diff --git a/schematics/scully/src/scully/index.ts b/schematics/scully/src/scully/index.ts index a5e74d62f..d822f001d 100644 --- a/schematics/scully/src/scully/index.ts +++ b/schematics/scully/src/scully/index.ts @@ -1,10 +1,9 @@ import {Rule, SchematicContext, Tree, SchematicsException} from '@angular-devkit/schematics'; +import {Schema} from './schema'; // for now we dont have any option for use // @ts-ignore -export function scully(options: any): Rule { - +export function scully(options: Schema): Rule { return (tree: Tree, context: SchematicContext) => { - // project workspace data const workspaceConfigBuffer = tree.read('angular.json'); if (!workspaceConfigBuffer) { @@ -13,7 +12,9 @@ export function scully(options: any): Rule { // modify package json for support npm commands const content: Buffer | null = tree.read(`/package.json`); let jsonContent; - if (content) { jsonContent = JSON.parse(content.toString()); } + if (content) { + jsonContent = JSON.parse(content.toString()); + } /* tslint:disable:no-string-literal */ jsonContent.scripts['scully'] = 'scully'; /* tslint:enable:no-string-literal */ @@ -23,15 +24,16 @@ export function scully(options: any): Rule { // add config file if (!tree.exists('./scully.config.js')) { - tree.create('./scully.config.js', + tree.create( + './scully.config.js', `exports.config = { projectRoot: "./src/app", routes: { } -};`); +};` + ); } - // end return + // end return }; - } diff --git a/schematics/scully/src/scully/index_spec.ts b/schematics/scully/src/scully/index_spec.ts index fad780353..2b91b5c9d 100644 --- a/schematics/scully/src/scully/index_spec.ts +++ b/schematics/scully/src/scully/index_spec.ts @@ -1,16 +1,43 @@ -import { Tree } from '@angular-devkit/schematics'; -import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; +import {HostTree} from '@angular-devkit/schematics'; +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; +import {getFileContent} from '@schematics/angular/utility/test'; import * as path from 'path'; +import {setupProject} from '../utils/test-utils'; +import {Schema} from './schema'; const collectionPath = path.join(__dirname, '../collection.json'); +const PACKAGE_JSON_PATH = '/package.json'; +const SCULLY_PATH = '/scully.config.js'; +describe('scully schematic', () => { + const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); + const project = 'foo'; + const defaultOptions: Schema = { + project: 'foo', + }; + let appTree: UnitTestTree; -describe('scully', () => { - it('works', () => { - const runner = new SchematicTestRunner('schematics', collectionPath); - const tree = runner.runSchematic('scully', {}, Tree.empty()); + beforeEach(async () => { + appTree = new UnitTestTree(new HostTree()); + appTree = await setupProject(appTree, schematicRunner, project); + }); + + describe('when using the default options', () => { + beforeEach(async () => { + appTree = await schematicRunner.runSchematicAsync('scully', defaultOptions, appTree).toPromise(); + }); + + it('add config file', () => { + expect(appTree.files).toContain(SCULLY_PATH); + }); - expect(tree.files).toEqual([]); + it(`should modify the 'package.json'`, () => { + const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); + const {scripts} = packageJson; + expect(appTree.files).toContain(PACKAGE_JSON_PATH); + expect(scripts.scully).toEqual('scully'); + expect(scripts['scully:serve']).toEqual('scully serve'); + }); }); }); diff --git a/schematics/scully/src/scully/schema.ts b/schematics/scully/src/scully/schema.ts new file mode 100644 index 000000000..e76548202 --- /dev/null +++ b/schematics/scully/src/scully/schema.ts @@ -0,0 +1,3 @@ +export interface Schema { + project: string; +} diff --git a/schematics/scully/src/utils/test-utils.ts b/schematics/scully/src/utils/test-utils.ts new file mode 100644 index 000000000..5565b88a4 --- /dev/null +++ b/schematics/scully/src/utils/test-utils.ts @@ -0,0 +1,25 @@ +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; + +export async function setupProject(tree: UnitTestTree, schematicRunner: SchematicTestRunner, name: string) { + tree = await schematicRunner + .runExternalSchematicAsync('@schematics/angular', 'workspace', { + name: 'workspace', + version: ' ^9.0.0-rc.4', + newProjectRoot: '', + }) + .toPromise(); + + tree = await schematicRunner + .runExternalSchematicAsync( + '@schematics/angular', + 'application', + { + name, + projectRoot: '', + }, + tree + ) + .toPromise(); + + return tree; +} diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index 0f4305da1..225ff5111 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -1,5 +1,15 @@ -import {apply, forEach, mergeWith, Rule, SchematicContext, Source, Tree} from '@angular-devkit/schematics'; +import { + apply, + forEach, + mergeWith, + Rule, + SchematicContext, + Source, + Tree, + SchematicsException, +} from '@angular-devkit/schematics'; import {normalize, strings} from '@angular-devkit/core'; +import {join} from 'path'; import {buildRelativePath} from '@schematics/angular/utility/find-module'; import {addRouteDeclarationToModule} from '@schematics/angular/utility/ast-utils'; @@ -7,6 +17,7 @@ import ts = require('@schematics/angular/third_party/github.com/Microsoft/TypeSc import {InsertChange} from '@schematics/angular/utility/change'; import {ModuleOptions} from '@schematics/angular/utility/find-module'; +const PACKAGE_JSON = 'package.json'; interface Data { name: string; type: string; @@ -15,6 +26,16 @@ interface Data { route?: string; } +export interface PackageJson { + dependencies: PackageJsonConfigPart; + devDependencies: PackageJsonConfigPart; + scripts?: PackageJsonConfigPart; +} + +export interface PackageJsonConfigPart { + [key: string]: T; +} + export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { const baseRoute = data.route ? strings.dasherize(data.route) : strings.dasherize(data.name); const contentDirectoy = data.sourceDir ? strings.dasherize(data.sourceDir) : strings.dasherize(data.name); @@ -126,3 +147,48 @@ function buildRelativeModulePath(options: ModuleOptions, modulePath: string): st return buildRelativePath(modulePath, importModulePath); } + +class FileNotFoundException extends Error { + constructor(fileName: string) { + const message = `File ${fileName} not found!`; + super(message); + } +} + +export const getJsonFile = (tree: Tree, path: string): T => { + const file = tree.get(path); + if (!file) { + throw new FileNotFoundException(path); + } + + try { + const content = JSON.parse(file.content.toString()); + + return content as T; + } catch (e) { + throw new SchematicsException(`File ${path} could not be parsed!`); + } +}; + +export const getFileContents = (tree: Tree, filePath: string): string => { + const buffer = tree.read(filePath) || ''; + + return buffer.toString(); +}; + +export const getPackageJson = (tree: Tree, workingDirectory: string = ''): PackageJson => { + const url = join(workingDirectory, PACKAGE_JSON); + + return getJsonFile(tree, url); +}; + +export const overwritePackageJson = ( + tree: Tree, + content: PackageJson, + workingDirectory: string = '' +): Tree => { + const url = join(workingDirectory, PACKAGE_JSON); + + tree.overwrite(url, JSON.stringify(content, null, 2)); + return tree; +}; From cc4875867abf3e0f81f71f0f920f693511b597bb Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 07:25:31 +0100 Subject: [PATCH 07/15] fix(scully): remove defaults from `route` and `sourceDir` --- schematics/scully/src/create-markdown/schema.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/schematics/scully/src/create-markdown/schema.json b/schematics/scully/src/create-markdown/schema.json index a0e6457d6..673a5d8bd 100644 --- a/schematics/scully/src/create-markdown/schema.json +++ b/schematics/scully/src/create-markdown/schema.json @@ -25,14 +25,12 @@ "sourceDir": { "type": "string", "description": "add the name for the source dir to store the markdown files", - "x-prompt": "Where do you want to store your markdown files?", - "default": "blog" + "x-prompt": "Where do you want to store your markdown files?" }, "route": { "type": "string", "description": "define the route where your post will be available", - "x-prompt": "Under which route do you want your files to be requested?", - "default": "blog" + "x-prompt": "Under which route do you want your files to be requested?" } }, "required": ["name", "slug"] From b69dd35b0557d56568ad520292306ee31a99425c Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 07:29:11 +0100 Subject: [PATCH 08/15] docs(scully): update options --- docs/blog.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/blog.md b/docs/blog.md index 5e257f405..f7455c447 100644 --- a/docs/blog.md +++ b/docs/blog.md @@ -31,6 +31,16 @@ or ng g @scullyio/init:markdown --name="my text" --slug="my slug id" ``` +the following table shows all vailable options: + +| option | description | default | +| -------------- | ------------------------------------------------------------------------------ | ------------------------ | +| `name` | define the name for the created module | 'blog' | +| `slug` | define the name for the `:slug` | 'id' | +| `routingScope` | set a routing scope (`Root` or `Child`) | Child | +| `sourceDir` | define a source dir name (when not used, `name` is used instead) | value from `name` option | +| `route` | define a route path before the `:slug` (when not used, `name` is used instead) | value from `name` option | + > If your markdown content will include code blocks, you may want the [code to be highlighted](utils.md). ## Generating New Blog Posts @@ -41,7 +51,14 @@ To add a new blog post, run the following command. ng g @scullyio/init:post --name="This is my post" ``` -[Check how to integrate Scully with other tools.](utils.md) +the following table shows all vailable options: + +| option | description | default | +| -------- | ------------------------------------------------- | -------- | +| `name` | define the name for the created post | 'blog-X' | +| `target` | define the target directory for the new post file | 'blog' | + +[Check how to integrate Scully with other tools.](utils.md) --- From 50e7bec04e3ff4a3abcfa414b205f25495a571a6 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 18:24:45 +0100 Subject: [PATCH 09/15] refactor(scully): split into smaller chainable Rules --- schematics/scully/src/ng-add/index.ts | 174 +++++++++++++------------- 1 file changed, 89 insertions(+), 85 deletions(-) diff --git a/schematics/scully/src/ng-add/index.ts b/schematics/scully/src/ng-add/index.ts index 7b60e5d18..18f181843 100644 --- a/schematics/scully/src/ng-add/index.ts +++ b/schematics/scully/src/ng-add/index.ts @@ -1,103 +1,107 @@ -import { - chain, Rule, SchematicContext, Tree, -} from '@angular-devkit/schematics'; +import {chain, Rule, SchematicContext, Tree} from '@angular-devkit/schematics'; import {addPackageToPackageJson} from './package-config'; import {Schema} from './schema'; import {scullyVersion, scullyComponentVersion} from './version-names'; import {addModuleImportToRootModule, getProjectFromWorkspace, getWorkspace} from 'schematics-utilities'; import {NodePackageInstallTask, RunSchematicTask} from '@angular-devkit/schematics/tasks'; -export default function(options: Schema): Rule { - return (host: Tree, context: SchematicContext) => { - addPackageToPackageJson(host, '@scullyio/scully', `${scullyVersion}`); - addPackageToPackageJson(host, '@scullyio/ng-lib', `${scullyComponentVersion}`); - context.logger.info('✅️ Added dependency'); -// @ts-ignore - try { - // @ts-ignore - const workspace = getWorkspace(host); - // @ts-ignore - const project = getProjectFromWorkspace(workspace, options.project); - // import the httpClient we need for the plugins - addModuleImportToRootModule(host, 'HttpClientModule', '@angular/common/http', project); - context.logger.info('✅️ Import HttpClientModule into root module'); - } catch (e) { } +export default (options: Schema): Rule => { + return chain([ + addDependencies(options), + addHttpClientModule(options), + addPolyfill(options), + injectIdleService(options), + runScullySchmeatic(options), + ]); +}; - // add new polyfills - // @ts-ignore - let polyfills = host.read('./src/polyfills.ts').toString(); - if (polyfills.includes('SCULLY IMPORTS')) { - context.logger.info('⚠️️ Skipping polyfills.ts'); - } else { - polyfills = - polyfills + - `\n/*************************************************************************************************** - \n* SCULLY IMPORTS - \n*/ - \n// tslint:disable-next-line: align \nimport 'zone.js/dist/task-tracking';`; - host.overwrite('./src/polyfills.ts', polyfills); - } +const addDependencies = (options: Schema) => (tree: Tree, context: SchematicContext) => { + addPackageToPackageJson(tree, '@scullyio/scully', `${scullyVersion}`); + addPackageToPackageJson(tree, '@scullyio/ng-lib', `${scullyComponentVersion}`); + context.logger.info('✅️ Added dependency'); +}; + +const addHttpClientModule = (options: Schema) => (tree: Tree, context: SchematicContext) => { + try { + const workspace = getWorkspace(tree); + const project = getProjectFromWorkspace(workspace); + // import the httpClient we need for the plugins + addModuleImportToRootModule(tree, 'HttpClientModule', '@angular/common/http', project); + context.logger.info('✅️ Import HttpClientModule into root module'); + } catch (e) {} +}; - try { - // inject idleService - const appComponent = host.read('./src/app/app.component.ts').toString(); - if (appComponent.includes('IdleMonitorService')) { - context.logger.info('⚠️️ Skipping ./src/app/app.component.ts'); +const addPolyfill = (options: Schema) => (tree: Tree, context: SchematicContext) => { + let polyfills = tree.read('./src/polyfills.ts').toString(); + if (polyfills.includes('SCULLY IMPORTS')) { + context.logger.info('⚠️ Skipping polyfills.ts'); + } else { + polyfills = + polyfills + + `\n/*************************************************************************************************** +\n* SCULLY IMPORTS +\n*/ +\n// tslint:disable-next-line: align \nimport 'zone.js/dist/task-tracking';`; + tree.overwrite('./src/polyfills.ts', polyfills); + } +}; + +const injectIdleService = (options: Schema) => (tree: Tree, context: SchematicContext) => { + try { + const appComponentPath = './src/app/app.component.ts'; + const appComponent = tree.read(appComponentPath).toString(); + if (appComponent.includes('IdleMonitorService')) { + context.logger.info(`⚠️️ Skipping ${appComponentPath}`); + } else { + const idleImport = `import {IdleMonitorService} from '@scullyio/ng-lib';`; + // add + const idImport = `${idleImport} \n ${appComponent}`; + const idle = 'private idle: IdleMonitorService'; + let output = ''; + // check if exist + if (idImport.search(/constructor/) === -1) { + // add if no exist the constructor + const add = ` \n constructor (${idle}) { } \n`; + const position = + idImport.search(/export class AppComponent {/g) + 'export class AppComponent {'.length; + output = [idImport.slice(0, position), add, idImport.slice(position)].join(''); } else { - const idleImport = "import {IdleMonitorService} from '@scullyio/ng-lib';"; - // add - const idImport = `${idleImport} \n ${appComponent}`; - const idle = 'private idle: IdleMonitorService'; - let output = ''; - // check if exist - if (idImport.search(/constructor/).toString() === '-1') { - // add if no exist the constructor - const add = ` \n constructor (${idle}) { } \n`; - const position = - idImport.search(/export class AppComponent {/g) + 'export class AppComponent {'.length; + const coma = haveMoreInjects(idImport); + const add = `${idle}${coma}`; + if (idImport.search(/constructor \(/) === -1) { + const position = idImport.search(/constructor\(/g) + 'constructor('.length; output = [idImport.slice(0, position), add, idImport.slice(position)].join(''); } else { - const coma = haveMoreInjects(idImport); - const add = `${idle}${coma}`; - if (idImport.search(/constructor \(/).toString() === '-1') { - const position = idImport.search(/constructor\(/g) + 'constructor('.length; - output = [idImport.slice(0, position), add, idImport.slice(position)].join(''); - } else { - const position = idImport.search(/constructor \(/g) + 'constructor ('.length; - output = [idImport.slice(0, position), add, idImport.slice(position)].join(''); - } - } - host.overwrite('./src/app/app.component.ts', output); - } - - function haveMoreInjects(fullComponent: string) { - const match = '\(([^()]*(private|public)[^()]*)\)'; - // @ts-ignore - if (fullComponent.search(match).toString !== '-1') { - return ','; + const position = idImport.search(/constructor \(/g) + 'constructor ('.length; + output = [idImport.slice(0, position), add, idImport.slice(position)].join(''); } - return ''; } - - - } catch (e) { - console.log('error in idle service'); + tree.overwrite(appComponentPath, output); } - - const nextRules: Rule[] = []; - // tslint:disable-next-line:triple-equals - if (options.blog === true) { - // @ts-ignore - nextRules.push(context.addTask(new RunSchematicTask('blog', options), [])); + function haveMoreInjects(fullComponent: string) { + const match = '(([^()]*(private|public)[^()]*))'; + if (fullComponent.search(match) !== -1) { + return ','; + } + return ''; } - // tslint:disable-next-line:no-shadowed-variable - nextRules.push((tree: Tree, context: SchematicContext) => { - const installTaskId = context.addTask(new NodePackageInstallTask()); - context.addTask(new RunSchematicTask('scully', options), [installTaskId]); - }); + } catch (e) { + console.log('error in idle service'); + } +}; - return chain(nextRules); +const runScullySchmeatic = (options: Schema) => (tree: Tree, context: SchematicContext) => { + const nextRules: Rule[] = []; + if (options.blog === true) { + // @ts-ignore + nextRules.push(context.addTask(new RunSchematicTask('blog', options), [])); + } + // tslint:disable-next-line:no-shadowed-variable + nextRules.push((tree: Tree, context: SchematicContext) => { + const installTaskId = context.addTask(new NodePackageInstallTask()); + context.addTask(new RunSchematicTask('scully', options), [installTaskId]); + }); - }; -} + chain(nextRules); +}; From 242e808f8d0a42ab11fe2fcf84a053e53d5fbf1e Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 18:25:05 +0100 Subject: [PATCH 10/15] test(scully): add tests for ng-add schematic --- schematics/scully/src/ng-add/index_spec.ts | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/schematics/scully/src/ng-add/index_spec.ts b/schematics/scully/src/ng-add/index_spec.ts index 59c91c39d..d0dca63da 100644 --- a/schematics/scully/src/ng-add/index_spec.ts +++ b/schematics/scully/src/ng-add/index_spec.ts @@ -35,5 +35,29 @@ describe('scully', () => { expect(dependencies['@scullyio/ng-lib']).toEqual(scullyVersion); expect(dependencies['@scullyio/scully']).toEqual(scullyComponentVersion); }); + + it('should add dependencies', () => { + const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); + const {dependencies} = packageJson; + expect(appTree.files).toContain(PACKAGE_JSON_PATH); + expect(dependencies['@scullyio/ng-lib']).toEqual(scullyVersion); + expect(dependencies['@scullyio/scully']).toEqual(scullyComponentVersion); + }); + + it('should add the HttpClientModule', () => { + const appModuleContent = getFileContent(appTree, 'src/app/app.module.ts'); + expect(appModuleContent).toMatch(/import.*HttpClientModule.*from.*\@angular\/common\/http/g); + expect(appModuleContent).toMatch(/imports.*:.*\[.*HttpClientModule\s+\]/s); + }); + + it('should add the polyfill', () => { + const appModuleContent = getFileContent(appTree, 'src/polyfills.ts'); + expect(appModuleContent).toMatch(/import.*zone\.js\/dist\/task-tracking/g); + }); + + it('should inject the idle service into AppComponent', () => { + const appModuleContent = getFileContent(appTree, 'src/app/app.component.ts'); + expect(appModuleContent).toMatch(/constructor*.*.private idle: IdleMonitorService/s); + }); }); }); From 026818f299a637acf6aadb7d202f33d2b36ac5d3 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 19:12:09 +0100 Subject: [PATCH 11/15] test(scully): add more schematic tests --- schematics/scully/src/add-post/index_spec.ts | 32 ++++++++++++++++ .../scully/src/create-markdown/index.ts | 4 +- .../scully/src/create-markdown/index_spec.ts | 38 +++++++++++++++++++ schematics/scully/src/ng-add/index_spec.ts | 2 +- 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 schematics/scully/src/add-post/index_spec.ts create mode 100644 schematics/scully/src/create-markdown/index_spec.ts diff --git a/schematics/scully/src/add-post/index_spec.ts b/schematics/scully/src/add-post/index_spec.ts new file mode 100644 index 000000000..940f70d59 --- /dev/null +++ b/schematics/scully/src/add-post/index_spec.ts @@ -0,0 +1,32 @@ +import {HostTree} from '@angular-devkit/schematics'; +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; +import * as path from 'path'; + +import {setupProject} from '../utils/test-utils'; +import {Schema} from './schema'; + +const collectionPath = path.join(__dirname, '../collection.json'); + +describe('add-post', () => { + const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); + const project = 'foo'; + const defaultOptions: Schema = { + name: 'Foo barBaz', + }; + let appTree: UnitTestTree; + + beforeEach(async () => { + appTree = new UnitTestTree(new HostTree()); + appTree = await setupProject(appTree, schematicRunner, project); + }); + + describe('when using the default options', () => { + beforeEach(async () => { + appTree = await schematicRunner.runSchematicAsync('post', defaultOptions, appTree).toPromise(); + }); + + it('should create a new dasherized post', () => { + expect(appTree.files).toContain('/blog/foo-bar-baz.md'); + }); + }); +}); diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 8973effc0..a773e2819 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -44,14 +44,14 @@ publish: false }, };`; } - const newScullyJson = addRouteToScullyConfig(scullyJs, { + const newScullyJs = addRouteToScullyConfig(scullyJs, { name, slug: options.slug, type: 'contentFolder', sourceDir, route: options.route, }); - host.overwrite(SCULLY_CONF_FILE, newScullyJson); + host.overwrite(SCULLY_CONF_FILE, newScullyJs); context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); const pathName = strings.dasherize(`./src/app/${name}`); diff --git a/schematics/scully/src/create-markdown/index_spec.ts b/schematics/scully/src/create-markdown/index_spec.ts new file mode 100644 index 000000000..e5b566ae6 --- /dev/null +++ b/schematics/scully/src/create-markdown/index_spec.ts @@ -0,0 +1,38 @@ +import {HostTree} from '@angular-devkit/schematics'; +import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; +import {getFileContent} from '@schematics/angular/utility/test'; +import * as path from 'path'; + +import {setupProject} from '../utils/test-utils'; +import {Schema} from './schema'; + +const collectionPath = path.join(__dirname, '../collection.json'); + +describe('create-markdown', () => { + const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); + const project = 'foo'; + const defaultOptions: Schema = { + name: 'blog', + slug: 'id', + }; + let appTree: UnitTestTree; + + beforeEach(async () => { + appTree = new UnitTestTree(new HostTree()); + appTree = await setupProject(appTree, schematicRunner, project); + }); + + describe('when using the default options', () => { + beforeEach(async () => { + appTree = await schematicRunner.runSchematicAsync('md', defaultOptions, appTree).toPromise(); + }); + + it('should create the markdown file in the default directory', () => { + const dayString = new Date().toISOString().substring(0, 10); + const mdFileContent = getFileContent(appTree, `blog/${dayString}-blog.md`); + expect(mdFileContent).toMatch(/title: This is the blog/g); + expect(mdFileContent).toMatch(/description: blog/g); + expect(mdFileContent).toMatch(/# Page blog example/g); + }); + }); +}); diff --git a/schematics/scully/src/ng-add/index_spec.ts b/schematics/scully/src/ng-add/index_spec.ts index d0dca63da..bdb3287e0 100644 --- a/schematics/scully/src/ng-add/index_spec.ts +++ b/schematics/scully/src/ng-add/index_spec.ts @@ -10,7 +10,7 @@ import {scullyVersion, scullyComponentVersion} from './version-names'; const collectionPath = path.join(__dirname, '../collection.json'); const PACKAGE_JSON_PATH = '/package.json'; -describe('scully', () => { +describe('ng-add schematic', () => { const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); const project = 'foo'; const defaultOptions: Schema = { From df7500f3cd7dc0e3318eaead6580a156f43d42d0 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Tue, 7 Jan 2020 23:03:06 +0100 Subject: [PATCH 12/15] feat(scully): add `metaDataFile` option and tests --- docs/blog.md | 9 ++-- .../scully/assets/meta-data-template.yml | 8 ++++ schematics/scully/package-lock.json | 46 +++++++++++++++++-- schematics/scully/package.json | 2 + schematics/scully/src/add-post/index.ts | 45 ++++++++++++++---- schematics/scully/src/add-post/index_spec.ts | 28 ++++++++++- schematics/scully/src/add-post/schema.json | 5 ++ schematics/scully/src/add-post/schema.ts | 4 ++ 8 files changed, 128 insertions(+), 19 deletions(-) create mode 100644 schematics/scully/assets/meta-data-template.yml diff --git a/docs/blog.md b/docs/blog.md index f7455c447..3eccde44a 100644 --- a/docs/blog.md +++ b/docs/blog.md @@ -53,10 +53,11 @@ ng g @scullyio/init:post --name="This is my post" the following table shows all vailable options: -| option | description | default | -| -------- | ------------------------------------------------- | -------- | -| `name` | define the name for the created post | 'blog-X' | -| `target` | define the target directory for the new post file | 'blog' | +| option | description | default | +| -------------- | ------------------------------------------------------ | --------- | +| `name` | define the name for the created post | 'blog-X' | +| `target` | define the target directory for the new post file | 'blog' | +| `metaDataFile` | use a meta data yaml template from a file for the post | undefined | [Check how to integrate Scully with other tools.](utils.md) diff --git a/schematics/scully/assets/meta-data-template.yml b/schematics/scully/assets/meta-data-template.yml new file mode 100644 index 000000000..cd31dc109 --- /dev/null +++ b/schematics/scully/assets/meta-data-template.yml @@ -0,0 +1,8 @@ +title: override-me +thumbnail: assets/images/default.jpg +author: John Doe +mail: John.Doe@example.com +keywords: + - angular + - scully +language: en diff --git a/schematics/scully/package-lock.json b/schematics/scully/package-lock.json index 4be72152d..173bb8a7d 100644 --- a/schematics/scully/package-lock.json +++ b/schematics/scully/package-lock.json @@ -101,12 +101,20 @@ "@types/jasmine": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.0.tgz", - "integrity": "sha512-kGCRI9oiCxFS6soGKlyzhMzDydfcPix9PpTkr7h11huxOxhWwP37Tg7DYBaQ18eQTNreZEuLkhpbGSqVNZPnnw==" + "integrity": "sha512-kGCRI9oiCxFS6soGKlyzhMzDydfcPix9PpTkr7h11huxOxhWwP37Tg7DYBaQ18eQTNreZEuLkhpbGSqVNZPnnw==", + "dev": true + }, + "@types/js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==", + "dev": true }, "@types/node": { "version": "8.10.59", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.59.tgz", - "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==" + "integrity": "sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ==", + "dev": true }, "@yarnpkg/lockfile": { "version": "1.1.0", @@ -167,6 +175,14 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -376,6 +392,11 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -579,6 +600,7 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.5.0.tgz", "integrity": "sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ==", + "dev": true, "requires": { "glob": "^7.1.4", "jasmine-core": "~3.5.0" @@ -587,7 +609,17 @@ "jasmine-core": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz", - "integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==" + "integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } }, "json-parse-better-errors": { "version": "1.0.2", @@ -1278,6 +1310,11 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -1372,7 +1409,8 @@ "typescript": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==" + "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "dev": true }, "unique-filename": { "version": "1.1.1", diff --git a/schematics/scully/package.json b/schematics/scully/package.json index 76ba7366f..3b7f225ec 100644 --- a/schematics/scully/package.json +++ b/schematics/scully/package.json @@ -31,10 +31,12 @@ "@angular-devkit/core": "^9.0.0-rc.5", "@angular-devkit/schematics": "^9.0.0-rc.5", "@schematics/angular": "^9.0.0-rc.5", + "js-yaml": "^3.13.1", "schematics-utilities": "^2.0.0" }, "devDependencies": { "@types/jasmine": "^3.3.9", + "@types/js-yaml": "^3.12.1", "@types/node": "^8.0.31", "jasmine": "^3.3.1", "typescript": "~3.5.3" diff --git a/schematics/scully/src/add-post/index.ts b/schematics/scully/src/add-post/index.ts index b28b9c9f1..728b7c27c 100644 --- a/schematics/scully/src/add-post/index.ts +++ b/schematics/scully/src/add-post/index.ts @@ -1,6 +1,9 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; -import {Schema} from './schema'; import {strings} from '@angular-devkit/core'; +import fs = require('fs'); +import yaml = require('js-yaml'); + +import {Schema} from './schema'; export default function(options: Schema): Rule { return (host: Tree, context: SchematicContext) => { @@ -8,18 +11,40 @@ export default function(options: Schema): Rule { const nameDasherized = options.name ? strings.dasherize(options.name) : 'blog-X'; const targetDasherized = options.target ? strings.dasherize(options.target) : 'blog'; const filename = `./${targetDasherized}/${nameDasherized}.md`; + + let metaData = { + title: '', + description: 'blog description', + publish: false, + }; + + if (options.metaDataFile) { + let metaDataContents = ''; + try { + metaDataContents = fs.readFileSync(options.metaDataFile, 'utf8'); + } catch (e) { + throw new SchematicsException(`File ${options.metaDataFile} not found`); + } + + try { + // check if yaml is valid + metaData = yaml.safeLoad(metaDataContents); + context.logger.info(`✅️ Meta Data File ${options.metaDataFile} successfully parsed`); + } catch (e) { + throw new SchematicsException(`${options.metaDataFile} contains no valid yaml`); + } + } + + // set title from option and override if alreay in metaDataFile template + metaData.title = name; + if (!host.exists(filename)) { - host.create( - filename, - `--- -title: ${name} -description: blog description -publish: false ---- + const content = `--- +${yaml.safeDump(metaData)}--- # ${name} -` - ); +`; + host.create(filename, content); context.logger.info(`✅️ Blog ${filename} file created`); } else { // return name exist diff --git a/schematics/scully/src/add-post/index_spec.ts b/schematics/scully/src/add-post/index_spec.ts index 940f70d59..36fe92633 100644 --- a/schematics/scully/src/add-post/index_spec.ts +++ b/schematics/scully/src/add-post/index_spec.ts @@ -1,11 +1,13 @@ import {HostTree} from '@angular-devkit/schematics'; import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; +import {getFileContent} from '@schematics/angular/utility/test'; import * as path from 'path'; import {setupProject} from '../utils/test-utils'; import {Schema} from './schema'; const collectionPath = path.join(__dirname, '../collection.json'); +const META_DATA_TEMPLATE_PATH = 'assets/meta-data-template.yml'; describe('add-post', () => { const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); @@ -14,6 +16,7 @@ describe('add-post', () => { name: 'Foo barBaz', }; let appTree: UnitTestTree; + const expectedFileName = '/blog/foo-bar-baz.md'; beforeEach(async () => { appTree = new UnitTestTree(new HostTree()); @@ -26,7 +29,30 @@ describe('add-post', () => { }); it('should create a new dasherized post', () => { - expect(appTree.files).toContain('/blog/foo-bar-baz.md'); + expect(appTree.files).toContain(expectedFileName); + const mdFileContent = getFileContent(appTree, expectedFileName); + expect(mdFileContent).toMatch(/title: Foo barBaz/g); + expect(mdFileContent).toMatch(/description: blog description/g); + expect(mdFileContent).toMatch(/publish: false/g); + }); + }); + + describe('when using `metaDataFile` option', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('post', {...defaultOptions, metaDataFile: META_DATA_TEMPLATE_PATH}, appTree) + .toPromise(); + }); + + it('should add the meta data but keep title from options', () => { + expect(appTree.files).toContain(expectedFileName); + const mdFileContent = getFileContent(appTree, expectedFileName); + expect(mdFileContent).toMatch(/title: Foo barBaz/g); + expect(mdFileContent).toMatch(/thumbnail: assets\/images\/default\.jpg/g); + expect(mdFileContent).toMatch(/author: John Doe/g); + expect(mdFileContent).toMatch(/mail: John.Doe@example.com/g); + expect(mdFileContent).toMatch(/keywords:\s+-\ angular\s+-\ scully/s); + expect(mdFileContent).toMatch(/language: en/g); }); }); }); diff --git a/schematics/scully/src/add-post/schema.json b/schematics/scully/src/add-post/schema.json index d5b2a3904..f58a3e9cf 100644 --- a/schematics/scully/src/add-post/schema.json +++ b/schematics/scully/src/add-post/schema.json @@ -15,6 +15,11 @@ "description": "define the target directory for the new post file", "x-prompt": "What's the target folder for this post?", "default": "blog" + }, + "metaDataFile": { + "type": "string", + "description": "use a meta data template file that's data will be added to the post", + "default": "" } }, "required": ["name"] diff --git a/schematics/scully/src/add-post/schema.ts b/schematics/scully/src/add-post/schema.ts index 85600185e..d9331720c 100644 --- a/schematics/scully/src/add-post/schema.ts +++ b/schematics/scully/src/add-post/schema.ts @@ -10,4 +10,8 @@ export interface Schema { * define the target directory for the new post file */ target?: string; + /** + * use a meta data template file that's data will be added to the post + */ + metaDataFile?: string; } From 24f0b666f03688413fdf1201ea369decc025ab7e Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Wed, 8 Jan 2020 07:45:52 +0100 Subject: [PATCH 13/15] test(scully): add test for using `target` option --- schematics/scully/src/add-post/index_spec.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/schematics/scully/src/add-post/index_spec.ts b/schematics/scully/src/add-post/index_spec.ts index 36fe92633..48b4a853b 100644 --- a/schematics/scully/src/add-post/index_spec.ts +++ b/schematics/scully/src/add-post/index_spec.ts @@ -16,7 +16,7 @@ describe('add-post', () => { name: 'Foo barBaz', }; let appTree: UnitTestTree; - const expectedFileName = '/blog/foo-bar-baz.md'; + let expectedFileName = '/blog/foo-bar-baz.md'; beforeEach(async () => { appTree = new UnitTestTree(new HostTree()); @@ -37,6 +37,23 @@ describe('add-post', () => { }); }); + describe('when using a different `target`', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('post', {...defaultOptions, target: 'foo/bar'}, appTree) + .toPromise(); + }); + + it('should create a new dasherized post inside the target dir', () => { + expectedFileName = '/foo/bar/foo-bar-baz.md'; + expect(appTree.files).toContain(expectedFileName); + const mdFileContent = getFileContent(appTree, expectedFileName); + expect(mdFileContent).toMatch(/title: Foo barBaz/g); + expect(mdFileContent).toMatch(/description: blog description/g); + expect(mdFileContent).toMatch(/publish: false/g); + }); + }); + describe('when using `metaDataFile` option', () => { beforeEach(async () => { appTree = await schematicRunner From 68c5c0cbd6cadb79bb31b96b495b4f5b8da8d138 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Wed, 8 Jan 2020 07:53:53 +0100 Subject: [PATCH 14/15] fix(scully): add correct Schema infos for add-blog --- schematics/scully/src/add-blog/index.ts | 18 +++++++++++++----- schematics/scully/src/add-blog/schema.json | 2 +- schematics/scully/src/add-blog/schema.ts | 6 ++++++ 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 schematics/scully/src/add-blog/schema.ts diff --git a/schematics/scully/src/add-blog/index.ts b/schematics/scully/src/add-blog/index.ts index 9dcc340d7..b8da109f8 100644 --- a/schematics/scully/src/add-blog/index.ts +++ b/schematics/scully/src/add-blog/index.ts @@ -1,10 +1,18 @@ -import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; +import {Rule, SchematicContext, Tree} from '@angular-devkit/schematics'; import {RunSchematicTask} from '@angular-devkit/schematics/tasks'; +import {Schema} from './schema'; +import {Schema as MarkownSchema} from '../create-markdown/schema'; -export default function(options: any): Rule { +export default function(options: Schema): Rule { return (tree: Tree, context: SchematicContext) => { - options.name = 'blog'; - options.slug = 'slug'; - context.addTask(new RunSchematicTask('create-markdown', options), []); + const makrdownOptions: MarkownSchema = { + name: 'blog', + slug: 'slug', + }; + + if (options.routingScope) { + makrdownOptions.routingScope = options.routingScope; + } + context.addTask(new RunSchematicTask('create-markdown', makrdownOptions), []); }; } diff --git a/schematics/scully/src/add-blog/schema.json b/schematics/scully/src/add-blog/schema.json index 916d0fe43..29e020dcc 100644 --- a/schematics/scully/src/add-blog/schema.json +++ b/schematics/scully/src/add-blog/schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/schema", - "id": "add-component", + "id": "add-blog", "title": "Scully add component schematic", "type": "object", "properties": { diff --git a/schematics/scully/src/add-blog/schema.ts b/schematics/scully/src/add-blog/schema.ts new file mode 100644 index 000000000..c0f5d7f30 --- /dev/null +++ b/schematics/scully/src/add-blog/schema.ts @@ -0,0 +1,6 @@ +export interface Schema { + /** + * The scope for the new routing module. + */ + routingScope?: 'Child' | 'Root'; +} From a799ccfc25d51d913ca5dee8d0aad3bbce5461b3 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Wed, 8 Jan 2020 07:56:19 +0100 Subject: [PATCH 15/15] test(scully): fix test --- schematics/scully/src/add-post/index_spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/schematics/scully/src/add-post/index_spec.ts b/schematics/scully/src/add-post/index_spec.ts index 48b4a853b..172fed362 100644 --- a/schematics/scully/src/add-post/index_spec.ts +++ b/schematics/scully/src/add-post/index_spec.ts @@ -16,7 +16,7 @@ describe('add-post', () => { name: 'Foo barBaz', }; let appTree: UnitTestTree; - let expectedFileName = '/blog/foo-bar-baz.md'; + const expectedFileName = '/blog/foo-bar-baz.md'; beforeEach(async () => { appTree = new UnitTestTree(new HostTree()); @@ -45,9 +45,9 @@ describe('add-post', () => { }); it('should create a new dasherized post inside the target dir', () => { - expectedFileName = '/foo/bar/foo-bar-baz.md'; - expect(appTree.files).toContain(expectedFileName); - const mdFileContent = getFileContent(appTree, expectedFileName); + const expected = '/foo/bar/foo-bar-baz.md'; + expect(appTree.files).toContain(expected); + const mdFileContent = getFileContent(appTree, expected); expect(mdFileContent).toMatch(/title: Foo barBaz/g); expect(mdFileContent).toMatch(/description: blog description/g); expect(mdFileContent).toMatch(/publish: false/g);