import { chain , noop , Rule , Tree } from '@angular-devkit/schematics' ; import { ANGULAR_JSON , TSCONFIG_JSON } from '../constants' ; import { addPackageToPackageJson , addScriptToPackageJson , AppOrLibType , copyConfigFiles , deleteFile , findDefaultProjectNameInAngularJson , removePackageFromPackageJson , tsconfigFilePath , updateJson } from '../utils' ; import { jest } from '../versions' ; import { NgEssentialsOptions } from './schema' ; export function addJest ( options ) { if ( ! options . jest || ! options . firstRun ) { return chain ( [ ] ) ; } return chain ( [ ( tree ) => { const defaultProjectName = findDefaultProjectNameInAngularJson ( tree ) ; const hasDefaultApplication = defaultProjectName !== '' ; return chain ( [ preparePackageJson ( ) , prepareAngularJson ( hasDefaultApplication , defaultProjectName ) , prepareTsConfig ( hasDefaultApplication ) , addConfigFiles ( ) , removeKarmaAssets ( hasDefaultApplication ) ] ) ; } ] ) ; } function preparePackageJson ( ) { return chain ( [ removePackageFromPackageJson ( 'devDependencies' , '@types/jasmine' ) , removePackageFromPackageJson ( 'devDependencies' , 'jasmine-core' ) , removePackageFromPackageJson ( 'devDependencies' , 'jasmine-spec-reporter' ) , removePackageFromPackageJson ( 'devDependencies' , 'karma' ) , removePackageFromPackageJson ( 'devDependencies' , 'karma-chrome-launcher' ) , removePackageFromPackageJson ( 'devDependencies' , 'karma-coverage-istanbul-reporter' ) , removePackageFromPackageJson ( 'devDependencies' , 'karma-jasmine' ) , removePackageFromPackageJson ( 'devDependencies' , 'karma-jasmine-html-reporter' ) , addPackageToPackageJson ( 'devDependencies' , '@angular-builders/jest' , jest . jestBuilderVersion ) , addPackageToPackageJson ( 'devDependencies' , '@types/jest' , jest . jestTypeVersion ) , addPackageToPackageJson ( 'devDependencies' , 'jest' , jest . jestVersion ) , addPackageToPackageJson ( 'devDependencies' , 'jest-preset-angular' , jest . presetAngularVersion ) , addPackageToPackageJson ( 'devDependencies' , 'ts-jest' , jest . tsJestVersion ) , addScriptToPackageJson ( 'test' , 'ng test --coverage' ) , addScriptToPackageJson ( 'test:watch' , 'ng test --watch' ) ] ) ; } function prepareAngularJson ( hasDefaultApplication , defaultProjectName ) { return chain ( [ hasDefaultApplication ? switchToJestBuilderInAngularJson ( defaultProjectName ) : noop ( ) ] ) ; } export function switchToJestBuilderInAngularJson ( projectName ) { return updateJson ( ANGULAR_JSON , ( json ) => { json [ 'projects' ] [ projectName ] [ 'architect' ] [ 'test' ] . builder = '@angular-builders/jest:run' ; json [ 'projects' ] [ projectName ] [ 'architect' ] [ 'test' ] . options = { } ; return json ; } ) ; } function prepareTsConfig ( hasDefaultApplication ) { return chain ( [ prepareGlobalTsSpecConfigForJest ( ) , hasDefaultApplication ? prepareTsAppOrLibConfigForJest ( '.' , 'app' ) : noop ( ) ] ) ; } function prepareGlobalTsSpecConfigForJest ( ) { return ( host ) => { const specConfigFile = tsconfigFilePath ( '.' , 'spec' ) ; if ( host . exists ( specConfigFile ) ) { return updateJson ( specConfigFile , ( json ) => { if ( json [ 'files' ] ) { delete json [ 'files' ] ; } if ( json [ 'include' ] ) { delete json [ 'include' ] ; } return { ... json , compilerOptions : { emitDecoratorMetadata : true , esModuleInterop : true , types : [ 'jest' ] } } ; } ) ; } else { host . create ( specConfigFile , `{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "esModuleInterop": true,
    "types": ["jest"]
  }
}` ) ; } } ; } function prepareTsAppOrLibConfigForJest ( rootPath , context ) { return updateJson ( tsconfigFilePath ( rootPath , context ) , ( json ) => { return { ... json , exclude : [ '**/*.spec.ts' ] } ; } ) ; } function addConfigFiles ( ) { return chain ( [ createLaunchJson , copyConfigFiles ( 'jest' ) ] ) ; } function createLaunchJson ( ) { return ( host ) => { host . create ( './.vscode/launch.json' , `{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "ng serve",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:4200/#",
      "webRoot": "\${workspaceFolder}"
    },
    {
      "name": "ng test",
      "type": "node",
      "request": "launch",
      "program": "\${workspaceFolder}/node_modules/@angular/cli/bin/ng",
      "args": ["test", "-- --runInBand"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen"
    }
  ]
}` ) ; return host ; } ; } function removeKarmaAssets ( hasDefaultApplication ) { return chain ( [ deleteFile ( 'karma.conf.js' ) , hasDefaultApplication ? deleteFile ( 'src/test.ts' ) : noop ( ) ] ) ; } export function prepareJest ( projectName , projectPath , context ) { return chain ( [ switchToJestBuilderInAngularJson ( projectName ) , deleteFile ( `${ projectPath }/karma.conf.js` ) , deleteFile ( `${ projectPath }/src/test.ts` ) , prepareTsAppOrLibConfigForJest ( projectPath , context ) , deleteTsSpecConfig ( projectPath ) , prepareGlobalTsSpecConfigForJest ( ) , createJestConfig ( projectPath ) ] ) ; } function deleteTsSpecConfig ( rootPath ) { return ( host ) => { host . delete ( `${ rootPath }/tsconfig.spec.json` ) ; } ; } function createJestConfig ( rootPath ) { return ( host ) => { host . create ( `${ rootPath }/jest.config.js` , `const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('../../tsconfig');

module.exports = {
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
    prefix: '<rootDir>/',
  }),
};` ) ; } ; }