17

How do I get the Angular CLI to serve up the right environments/environment*.ts file in Angular 7?

I've tried configuring the replacement of the environment.ts with environment.test.ts in three different places with no success.

I've tried running it with ng test and with ng test --configuration test.

Every single time, if I debug the tests, I find that it's using environment.prod.ts(?!) instead of environment.test.ts.

Here is a screenshot to show the three places I've tried to do the fileReplacements: enter image description here Here is the entire config for reference:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "mms": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "mms",
      "schematics": {},
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/mms",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/web.config"
            ],
            "styles": [
              "src/styles.scss",
              "src/assets/libs/pikaday/pikaday.scss",
              "src/assets/scss/dragula/dragula.css",
              "src/assets/libs/hopscotch/css/hopscotch.css",
              "src/assets/scss/site.scss"
            ],
            "scripts": [
              "src/assets/libs/hopscotch/js/hopscotch.js",
              "src/assets/libs/pikaday/pikaday.js",
              "src/assets/libs/bitmovin-loader.js"
            ]
          },
          "configurations": {
            "test": {
              "fileReplacements": [{
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.test.ts"
              }]
            },
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                },
                {
                  "replace": "src/index.html",
                  "with": "src/index.prod.html"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            },
            "mastermock": {
              "main": "src/main-mock.ts",
              "fileReplacements": [{
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.mock.ts"
              }]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "mms:build",
            "proxyConfig": "proxy.conf.json"
          },
          "configurations": {
            "production": {
              "browserTarget": "mms:build:production"
            },
            "mastermock": {
              "browserTarget": "mms:build:mastermock",
              "proxyConfig": "proxy.conf.json"
            }
          }
        },
        "serve-local": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "mms:build",
            "proxyConfig": "proxy.local.conf.json"
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "mms:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": [
              "src/styles.scss"
            ],
            "scripts": [],
            "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/web.config"
            ],
            "codeCoverageExclude": [
              "**/*.mock.ts",
              "**/*.module.ts"
            ],
            "fileReplacements": [{
              "replace": "src/environments/environment.ts",
              "with": "src/environments/environment.test.ts"
            }]
          },
          "configurations": {
            "test": {
              "fileReplacements": [{
                "replace": "src/environments/environment.ts",
                "with": "src/environments/environment.test.ts"
              }]
            },
            "production": {
              "karmaConfig": "src/karma.conf.prod.js"
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**",
              "**/*.dev.ts",
              "**/e2e/**"
            ]
          }
        }
      }
    },
    "mms-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.dev.js",
            "devServerTarget": "mms:serve"
          },
          "configurations": {
            "local": {
              "protractorConfig": "e2e/protractor.conf.dev.js",
              "devServerTarget": "mms:serve-local"
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "mms",
  "schematics": {
    "@ngrx/schematics:component": {
      "styleext": "scss"
    }
  },
  "cli": {
    "defaultCollection": "@ngrx/schematics"
  }
}
jkyoutsey
  • 1,969
  • 2
  • 20
  • 31
  • 1
    Try simply importing the desired environment file in your unit tests like this "import { environment } from './../environments/environment.test';". – robert Jan 16 '19 at 21:17
  • @robert that led me to look deeper. Looks like VSCode "helped" me by importing the .prod file into my component classes! Removing the .prod should fix my issue. – jkyoutsey Jan 16 '19 at 21:23

3 Answers3

11
  1. This was caused by Visual Studio Code "helping" me by importing: import { environment } from '@environments/environment.prod';
  2. The right place for fileReplacements is in architect.test.options.fileReplacements.
  3. In order to prevent VSCode from ever "helping" me like this again, I'm going to rename all of the environment.*.ts files other than environment.ts to something like DO-NOT-IMPORT.ENVIRONMENT.*.ts. At least that'll yell at me if I get the wrong import.
jkyoutsey
  • 1,969
  • 2
  • 20
  • 31
  • 1
    This is exactly right. My test was importing the right environment file, but my production file under test was not. Thanks for being specific about where the option goes. – lortimer May 28 '19 at 22:47
  • Do not name config files like this. You can just add to tsconfig.ts path like "@environment": [ "./path/to/environment.ts" ] – KusokBanana Dec 12 '19 at 10:11
  • @KusokBanana see point #1. If you don't pay very careful attention then VSCode does the wrong thing too easily. This form of naming makes mistakes more obvious. It's not a rule, just a recommendation that could save you some time! – jkyoutsey Dec 12 '19 at 14:03
  • @KusokBanana I do see what you're saying, and how it would work as long as VSCode never decides to import from anything except the `@environment` path. It's not a bad way of solving this either. – jkyoutsey Dec 12 '19 at 20:26
  • 1
    @jkyoutsey If you do as I said then VSCode will never decide to import from environment.prod.ts because this would cause an error while compiling (or while using TSLint). The problem is not worth changing names of files – KusokBanana Dec 13 '19 at 15:16
  • Didn't know that `architect.test.options` has `fileReplacements` option. Thanks – epsilon Apr 12 '21 at 10:46
  • @jkyoutsey This doesn't seem to work for me in an Nx jest environment – Jonathan002 Jul 13 '21 at 04:42
  • @Jonathan002 I don't use NX or Jest so I can't help you out on that one. I'm sure the smart NX folks probably already have a good solution for this! – jkyoutsey Jul 13 '21 at 20:31
1

When you add a custom environment configuration, you need to add it also to the test element in the angular.json file, otherwise tests just run with the default environment configuration.

For instance, lets say you added an extra environment configuration named "customenv" to the already existing build.configurations element:

"build": {
    ...

    "configurations": {
        "production": {
            "budgets": [
                {
                    "type": "initial",
                    "maximumWarning": "500kb",
                    "maximumError": "1mb"
                },
                {
                    "type": "anyComponentStyle",
                    "maximumWarning": "2kb",
                    "maximumError": "4kb"
                }
            ],
            "fileReplacements": [
                {
                    "replace": "src/environments/environment.ts",
                    "with": "src/environments/environment.prod.ts"
                }
            ],
            "outputHashing": "all"
        },
        "development": {
            "buildOptimizer": false,
            "optimization": false,
            "vendorChunk": true,
            "extractLicenses": false,
            "sourceMap": true,
            "namedChunks": true
        },
        "customenv": {
            "fileReplacements": [
                {
                    "replace": "src/environments/environment.ts",
                    "with": "src/environments/environment.customenv.ts"
                }
            ]
        }
    },
    "defaultConfiguration": "production"
},

At this point you can run

ng build --configuration=customenv

And then you might have also modified the already existing serve.configurations element like this:

"serve": {
    ...
    "configurations": {
        "production": {
            "browserTarget": "myproject:build:production"
        },
        "development": {
            "browserTarget": "myproject:build:development"
        },
        "testws": {
            "browserTarget": "myproject:build:customenv"
        }
    },
    "defaultConfiguration": "development"
},

So now you can run:

ng serve --configuration=customenv

But if you try to run

ng test --configuration=customenv

You get the error:

An unhandled exception occurred: Configuration 'customenv' is not set in the workspace.

To be able to do that, you need to create a test.configurations element and add only the new custom environment:

"test": {
    ...                  
    "configurations": {                        
        "customenv": {
            "fileReplacements": [
                {
                    "replace": "src/environments/environment.ts",
                    "with": "src/environments/environment.customenv.ts"
                }
            ]
        }
    },
Mister Smith
  • 27,417
  • 21
  • 110
  • 193
1

You can add fileReplacements to the test section of angular.json

"test": {
      "builder": "@angular-devkit/build-angular:karma",
      "options": {
        "main": "src/test.ts",
        "polyfills": "src/polyfills.ts",
        "tsConfig": "tsconfig.spec.json",
        "karmaConfig": "karma.conf.js",
        "fileReplacements": [{
          "replace": "src/environments/environment.ts",
          "with": "src/environments/environment.test.ts"
        }],

Tested angular-12.

Interlated
  • 5,108
  • 6
  • 48
  • 79