diff --git a/.all-contributorsrc b/.all-contributorsrc
index 2ec350fc..96c7a291 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -195,7 +195,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/4863062?v=4",
"profile": "https://github.com/the-ult",
"contributions": [
- "code"
+ "code",
+ "maintenance"
]
},
{
@@ -263,6 +264,16 @@
"contributions": [
"maintenance"
]
+ },
+ {
+ "login": "mleimer",
+ "name": "mleimer",
+ "avatar_url": "https://avatars.githubusercontent.com/u/14271564?v=4",
+ "profile": "https://github.com/mleimer",
+ "contributions": [
+ "doc",
+ "test"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e85298ba..998b0652 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -4,14 +4,15 @@ on:
push:
branches:
- 'main'
+ - 'beta'
pull_request: {}
jobs:
build_test_release:
strategy:
matrix:
- node-version: ${{ fromJSON(github.ref == 'refs/heads/main' && '[16]' || '[12,14,16]') }}
- os: ${{ fromJSON(github.ref == 'refs/heads/main' && '["ubuntu-latest"]' || '["ubuntu-latest", "windows-latest"]') }}
+ node-version: ${{ fromJSON((github.ref == 'refs/heads/main' || github.ref == 'refs/heads/beta') && '[16]' || '[12,14,16]') }}
+ os: ${{ fromJSON((github.ref == 'refs/heads/main' || github.ref == 'refs/heads/beta') && '["ubuntu-latest"]' || '["ubuntu-latest", "windows-latest"]') }}
runs-on: ${{ matrix.os }}
steps:
@@ -27,7 +28,7 @@ jobs:
- name: test
run: npm run test
- name: Release
- if: github.repository == 'testing-library/angular-testing-library' && github.ref == 'refs/heads/main'
+ if: github.repository == 'testing-library/angular-testing-library' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/beta')
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 82985ca5..b1a42cd6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,9 @@
!.vscode/extensions.json
# misc
+/.angular/cache
+.angular
+.cache
/.sass-cache
/connect.lock
/coverage
diff --git a/.husky/.gitignore b/.husky/.gitignore
deleted file mode 100644
index 31354ec1..00000000
--- a/.husky/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-_
diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh
new file mode 100644
index 00000000..ca2720e0
--- /dev/null
+++ b/.husky/_/husky.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+if [ -z "$husky_skip_init" ]; then
+ debug () {
+ [ "$HUSKY_DEBUG" = "1" ] && echo "husky (debug) - $1"
+ }
+
+ readonly hook_name="$(basename "$0")"
+ debug "starting $hook_name..."
+
+ if [ "$HUSKY" = "0" ]; then
+ debug "HUSKY env variable is set to 0, skipping hook"
+ exit 0
+ fi
+
+ if [ -f ~/.huskyrc ]; then
+ debug "sourcing ~/.huskyrc"
+ . ~/.huskyrc
+ fi
+
+ export readonly husky_skip_init=1
+ sh -e "$0" "$@"
+ exitCode="$?"
+
+ if [ $exitCode != 0 ]; then
+ echo "husky - $hook_name hook exited with code $exitCode (error)"
+ exit $exitCode
+ fi
+
+ exit 0
+fi
diff --git a/.nxignore b/.nxignore
new file mode 100644
index 00000000..aeb6b7f1
--- /dev/null
+++ b/.nxignore
@@ -0,0 +1 @@
+/projects/vscode-atl-render
diff --git a/.prettierignore b/.prettierignore
index 2cbf2c26..9aa8a3df 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -35,6 +35,8 @@ CHANGELOG.md
!.vscode/extensions.json
# misc
+.cache
+.angular
/.sass-cache
/connect.lock
/coverage
diff --git a/README.md b/README.md
index 06728b9d..d750dae4 100644
--- a/README.md
+++ b/README.md
@@ -207,7 +207,7 @@ Thanks goes to these people ([emoji key][emojis]):
 Bo Vandersteene 💻 |
 Janek 💻 ⚠️ |
 Gleb Irovich 💻 ⚠️ |
-  Arjen 💻 |
+  Arjen 💻 🚧 |
 Suguru Inatomi 💻 🤔 |
@@ -217,6 +217,7 @@ Thanks goes to these people ([emoji key][emojis]):
 Michael Westphal 💻 ⚠️ |
 Lukas 💻 |
 Matan Borenkraout 🚧 |
+  mleimer 📖 ⚠️ |
diff --git a/angular.json b/angular.json
deleted file mode 100644
index 50afdec9..00000000
--- a/angular.json
+++ /dev/null
@@ -1,296 +0,0 @@
-{
- "version": 1,
- "cli": {
- "analytics": false
- },
- "defaultProject": "example-app",
- "projects": {
- "example-app": {
- "projectType": "application",
- "root": "apps/example-app",
- "sourceRoot": "apps/example-app/src",
- "prefix": "app",
- "schematics": {},
- "architect": {
- "build": {
- "builder": "@angular-devkit/build-angular:browser",
- "options": {
- "outputPath": "dist/apps/example-app",
- "index": "apps/example-app/src/index.html",
- "main": "apps/example-app/src/main.ts",
- "polyfills": "apps/example-app/src/polyfills.ts",
- "tsConfig": "apps/example-app/tsconfig.app.json",
- "assets": ["apps/example-app/src/favicon.ico", "apps/example-app/src/assets"],
- "styles": ["apps/example-app/src/styles.css"],
- "scripts": [],
- "vendorChunk": true,
- "extractLicenses": false,
- "buildOptimizer": false,
- "sourceMap": true,
- "optimization": false,
- "namedChunks": true
- },
- "configurations": {
- "production": {
- "budgets": [
- {
- "type": "anyComponentStyle",
- "maximumWarning": "6kb"
- }
- ],
- "fileReplacements": [
- {
- "replace": "apps/example-app/src/environments/environment.ts",
- "with": "apps/example-app/src/environments/environment.prod.ts"
- }
- ],
- "optimization": true,
- "outputHashing": "all",
- "sourceMap": false,
- "namedChunks": false,
- "extractLicenses": true,
- "vendorChunk": false,
- "buildOptimizer": true
- }
- },
- "outputs": ["{options.outputPath}"]
- },
- "serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
- "options": {
- "browserTarget": "example-app:build"
- },
- "configurations": {
- "production": {
- "browserTarget": "example-app:build:production"
- }
- }
- },
- "extract-i18n": {
- "builder": "@angular-devkit/build-angular:extract-i18n",
- "options": {
- "browserTarget": "example-app:build"
- }
- },
- "lint": {
- "builder": "@nrwl/linter:eslint",
- "options": {
- "lintFilePatterns": [
- "apps/example-app/**/*.ts",
- "apps/example-app/**/*.html",
- "apps/example-app/src/**/*.html",
- "apps/example-app/src/**/*.html",
- "apps/example-app/src/**/*.html"
- ]
- },
- "outputs": ["{options.outputFile}"]
- },
- "test": {
- "builder": "@nrwl/jest:jest",
- "options": {
- "jestConfig": "apps/example-app/jest.config.js"
- },
- "outputs": ["coverage/"]
- }
- }
- },
- "example-app-karma": {
- "projectType": "application",
- "root": "apps/example-app-karma",
- "sourceRoot": "apps/example-app-karma/src",
- "prefix": "app",
- "schematics": {},
- "architect": {
- "build": {
- "builder": "@angular-devkit/build-angular:browser",
- "options": {
- "outputPath": "dist/apps/example-app-karma",
- "index": "apps/example-app-karma/src/index.html",
- "main": "apps/example-app-karma/src/main.ts",
- "polyfills": "apps/example-app-karma/src/polyfills.ts",
- "tsConfig": "apps/example-app-karma/tsconfig.app.json",
- "assets": ["apps/example-app-karma/src/favicon.ico", "apps/example-app-karma/src/assets"],
- "styles": [],
- "scripts": [],
- "vendorChunk": true,
- "extractLicenses": false,
- "buildOptimizer": false,
- "sourceMap": true,
- "optimization": false,
- "namedChunks": true
- },
- "configurations": {
- "production": {
- "budgets": [
- {
- "type": "anyComponentStyle",
- "maximumWarning": "6kb"
- }
- ],
- "fileReplacements": [
- {
- "replace": "apps/example-app-karma/src/environments/environment.ts",
- "with": "apps/example-app-karma/src/environments/environment.prod.ts"
- }
- ],
- "optimization": true,
- "outputHashing": "all",
- "sourceMap": false,
- "namedChunks": false,
- "extractLicenses": true,
- "vendorChunk": false,
- "buildOptimizer": true
- }
- },
- "outputs": ["{options.outputPath}"]
- },
- "serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
- "options": {
- "browserTarget": "example-app-karma:build"
- },
- "configurations": {
- "production": {
- "browserTarget": "example-app-karma:build:production"
- }
- }
- },
- "lint": {
- "builder": "@nrwl/linter:eslint",
- "options": {
- "lintFilePatterns": [
- "apps/example-app-karma/**/*.ts",
- "apps/example-app-karma/**/*.html",
- "apps/example-app-karma/src/**/*.html",
- "apps/example-app-karma/src/**/*.html",
- "apps/example-app-karma/src/**/*.html"
- ]
- },
- "outputs": ["{options.outputFile}"]
- },
- "test": {
- "builder": "@angular-devkit/build-angular:karma",
- "options": {
- "main": "apps/example-app-karma/src/test.ts",
- "tsConfig": "apps/example-app-karma/tsconfig.spec.json",
- "polyfills": "apps/example-app-karma/src/polyfills.ts",
- "karmaConfig": "apps/example-app-karma/karma.conf.js",
- "styles": [],
- "scripts": [],
- "assets": []
- }
- }
- }
- },
- "jest-utils": {
- "root": "projects/jest-utils",
- "sourceRoot": "projects/jest-utils/src",
- "projectType": "library",
- "prefix": "lib",
- "architect": {
- "build-package": {
- "builder": "@angular-devkit/build-angular:ng-packagr",
- "options": {
- "tsConfig": "projects/jest-utils/tsconfig.lib.json",
- "project": "projects/jest-utils/ng-package.json"
- },
- "configurations": {
- "production": {
- "project": "projects/jest-utils/ng-package.json",
- "tsConfig": "projects/jest-utils/tsconfig.lib.json"
- }
- }
- },
- "lint": {
- "builder": "@nrwl/linter:eslint",
- "options": {
- "lintFilePatterns": [
- "projects/jest-utils/**/*.ts",
- "projects/jest-utils/**/*.html",
- "projects/jest-utils/src/**/*.html",
- "projects/jest-utils/src/**/*.html",
- "projects/jest-utils/src/**/*.html"
- ]
- },
- "outputs": ["{options.outputFile}"]
- },
- "build": {
- "builder": "@nrwl/workspace:run-commands",
- "options": {
- "parallel": false,
- "commands": [
- {
- "command": "ng run jest-utils:build-package"
- }
- ]
- }
- },
- "test": {
- "builder": "@nrwl/jest:jest",
- "options": {
- "jestConfig": "projects/jest-utils/jest.config.js"
- },
- "outputs": ["coverage/projects/jest-utils"]
- }
- }
- },
- "testing-library": {
- "root": "projects/testing-library",
- "sourceRoot": "projects/testing-library/src",
- "projectType": "library",
- "prefix": "lib",
- "architect": {
- "build-package": {
- "builder": "@angular-devkit/build-angular:ng-packagr",
- "options": {
- "tsConfig": "projects/testing-library/tsconfig.lib.json",
- "project": "projects/testing-library/ng-package.json"
- },
- "configurations": {
- "production": {
- "project": "projects/testing-library/ng-package.json",
- "tsConfig": "projects/testing-library/tsconfig.lib.json"
- }
- }
- },
- "lint": {
- "builder": "@nrwl/linter:eslint",
- "options": {
- "lintFilePatterns": [
- "projects/testing-library/**/*.ts",
- "projects/testing-library/**/*.html",
- "projects/testing-library/src/**/*.html",
- "projects/testing-library/src/**/*.html",
- "projects/testing-library/src/**/*.html"
- ]
- },
- "outputs": ["{options.outputFile}"]
- },
- "build": {
- "builder": "@nrwl/workspace:run-commands",
- "options": {
- "parallel": false,
- "commands": [
- {
- "command": "ng run testing-library:build-package"
- },
- {
- "command": "npm run build:schematics"
- },
- {
- "command": "cpy ./README.md ./dist/@testing-library/angular"
- }
- ]
- }
- },
- "test": {
- "builder": "@nrwl/jest:jest",
- "options": {
- "jestConfig": "projects/testing-library/jest.config.js"
- },
- "outputs": ["coverage/projects/testing-library"]
- }
- }
- }
- }
-}
diff --git a/apps/example-app-karma/project.json b/apps/example-app-karma/project.json
new file mode 100644
index 00000000..94b4a463
--- /dev/null
+++ b/apps/example-app-karma/project.json
@@ -0,0 +1,82 @@
+{
+ "projectType": "application",
+ "root": "apps/example-app-karma",
+ "sourceRoot": "apps/example-app-karma/src",
+ "prefix": "app",
+ "generators": {},
+ "targets": {
+ "build": {
+ "executor": "@angular-devkit/build-angular:browser",
+ "outputs": ["{options.outputPath}"],
+ "options": {
+ "outputPath": "dist/apps/example-app-karma",
+ "index": "apps/example-app-karma/src/index.html",
+ "main": "apps/example-app-karma/src/main.ts",
+ "polyfills": "apps/example-app-karma/src/polyfills.ts",
+ "tsConfig": "apps/example-app-karma/tsconfig.app.json",
+ "assets": ["apps/example-app-karma/src/favicon.ico", "apps/example-app-karma/src/assets"],
+ "styles": [],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "budgets": [
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "6kb"
+ }
+ ],
+ "fileReplacements": [
+ {
+ "replace": "apps/example-app-karma/src/environments/environment.ts",
+ "with": "apps/example-app-karma/src/environments/environment.prod.ts"
+ }
+ ],
+ "outputHashing": "all"
+ },
+ "development": {
+ "buildOptimizer": false,
+ "optimization": false,
+ "vendorChunk": true,
+ "extractLicenses": false,
+ "sourceMap": true,
+ "namedChunks": true
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "executor": "@angular-devkit/build-angular:dev-server",
+ "configurations": {
+ "production": {
+ "browserTarget": "example-app-karma:build:production"
+ },
+ "development": {
+ "browserTarget": "example-app-karma:build:development"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "options": {
+ "lintFilePatterns": [
+ "apps/example-app-karma/**/*.ts",
+ "apps/example-app-karma/**/*.html",
+ "apps/example-app-karma/src/**/*.html"
+ ]
+ },
+ "outputs": ["{options.outputFile}"]
+ },
+ "test": {
+ "executor": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "apps/example-app-karma/src/test.ts",
+ "tsConfig": "apps/example-app-karma/tsconfig.spec.json",
+ "polyfills": "apps/example-app-karma/src/polyfills.ts",
+ "karmaConfig": "apps/example-app-karma/karma.conf.js"
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/apps/example-app-karma/src/app/issues/issue-222.spec.ts b/apps/example-app-karma/src/app/issues/issue-222.spec.ts
index 740d8184..b6ac5204 100644
--- a/apps/example-app-karma/src/app/issues/issue-222.spec.ts
+++ b/apps/example-app-karma/src/app/issues/issue-222.spec.ts
@@ -1,6 +1,6 @@
import { render, screen } from '@testing-library/angular';
-it('https://github.com/testing-library/angular-testing-library/issues/222', async () => {
+it('https://github.com/testing-library/angular-testing-library/issues/222 with rerender', async () => {
const { rerender } = await render(`Hello {{ name}}
`, {
componentProperties: {
name: 'Sarah',
@@ -8,7 +8,21 @@ it('https://github.com/testing-library/angular-testing-library/issues/222', asyn
});
expect(screen.getByText('Hello Sarah')).toBeTruthy();
- rerender({ name: 'Mark' });
+
+ await rerender({ name: 'Mark' });
+
+ expect(screen.getByText('Hello Mark')).toBeTruthy();
+});
+
+it('https://github.com/testing-library/angular-testing-library/issues/222 with change', async () => {
+ const { change } = await render(`Hello {{ name}}
`, {
+ componentProperties: {
+ name: 'Sarah',
+ },
+ });
+
+ expect(screen.getByText('Hello Sarah')).toBeTruthy();
+ await change({ name: 'Mark' });
expect(screen.getByText('Hello Mark')).toBeTruthy();
});
diff --git a/apps/example-app-karma/src/environments/environment.ts b/apps/example-app-karma/src/environments/environment.ts
index 85db3caf..64c3e6c7 100644
--- a/apps/example-app-karma/src/environments/environment.ts
+++ b/apps/example-app-karma/src/environments/environment.ts
@@ -1,6 +1,6 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
-// The list of file replacements can be found in `angular.json`.
+// The list of file replacements can be found in `workspace.json`.
export const environment = {
production: false,
diff --git a/apps/example-app-karma/src/polyfills.ts b/apps/example-app-karma/src/polyfills.ts
index bb20fec0..f84fd8a6 100644
--- a/apps/example-app-karma/src/polyfills.ts
+++ b/apps/example-app-karma/src/polyfills.ts
@@ -34,22 +34,12 @@
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
-/** IE10 and IE11 requires the following for NgClass support on SVG elements */
-// import 'classlist.js'; // Run `npm install --save classlist.js`.
-
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
-/**
- * Web Animations `@angular/platform-browser/animations`
- * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
- * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
- **/
-// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
-
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
diff --git a/apps/example-app-karma/src/test.ts b/apps/example-app-karma/src/test.ts
index 867baf94..0a45adb5 100644
--- a/apps/example-app-karma/src/test.ts
+++ b/apps/example-app-karma/src/test.ts
@@ -11,7 +11,7 @@ beforeAll(() => {
declare const require: any;
// First, initialize the Angular testing environment.
-getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
+getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {});
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
diff --git a/apps/example-app-karma/tsconfig.app.json b/apps/example-app-karma/tsconfig.app.json
index 629fd434..4de7101b 100644
--- a/apps/example-app-karma/tsconfig.app.json
+++ b/apps/example-app-karma/tsconfig.app.json
@@ -5,5 +5,7 @@
"types": [],
"allowJs": true
},
- "files": ["src/main.ts", "src/polyfills.ts"]
+ "files": ["src/main.ts", "src/polyfills.ts"],
+ "include": ["src/**/*.d.ts"],
+ "exclude": ["**/*.test.ts", "**/*.spec.ts"]
}
diff --git a/apps/example-app-karma/tsconfig.json b/apps/example-app-karma/tsconfig.json
index e1d5ba47..0cfe7c56 100644
--- a/apps/example-app-karma/tsconfig.json
+++ b/apps/example-app-karma/tsconfig.json
@@ -1,5 +1,5 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"compilerOptions": {},
diff --git a/apps/example-app/project.json b/apps/example-app/project.json
new file mode 100644
index 00000000..ebab97cb
--- /dev/null
+++ b/apps/example-app/project.json
@@ -0,0 +1,82 @@
+{
+ "projectType": "application",
+ "root": "apps/example-app",
+ "sourceRoot": "apps/example-app/src",
+ "prefix": "app",
+ "generators": {},
+ "targets": {
+ "build": {
+ "executor": "@angular-devkit/build-angular:browser",
+ "outputs": ["{options.outputPath}"],
+ "options": {
+ "outputPath": "dist/apps/example-app",
+ "index": "apps/example-app/src/index.html",
+ "main": "apps/example-app/src/main.ts",
+ "polyfills": "apps/example-app/src/polyfills.ts",
+ "tsConfig": "apps/example-app/tsconfig.app.json",
+ "assets": ["apps/example-app/src/favicon.ico", "apps/example-app/src/assets"],
+ "styles": ["apps/example-app/src/styles.css"],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "budgets": [
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "6kb"
+ }
+ ],
+ "fileReplacements": [
+ {
+ "replace": "apps/example-app/src/environments/environment.ts",
+ "with": "apps/example-app/src/environments/environment.prod.ts"
+ }
+ ],
+ "outputHashing": "all"
+ },
+ "development": {
+ "buildOptimizer": false,
+ "optimization": false,
+ "vendorChunk": true,
+ "extractLicenses": false,
+ "sourceMap": true,
+ "namedChunks": true
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "serve": {
+ "executor": "@angular-devkit/build-angular:dev-server",
+ "configurations": {
+ "production": {
+ "browserTarget": "example-app:build:production"
+ },
+ "development": {
+ "browserTarget": "example-app:build:development"
+ }
+ },
+ "defaultConfiguration": "development"
+ },
+ "extract-i18n": {
+ "executor": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "example-app:build"
+ }
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "options": {
+ "lintFilePatterns": ["apps/example-app/**/*.ts", "apps/example-app/**/*.html", "apps/example-app/src/**/*.html"]
+ },
+ "outputs": ["{options.outputFile}"]
+ },
+ "test": {
+ "executor": "@nrwl/jest:jest",
+ "options": {
+ "jestConfig": "apps/example-app/jest.config.js"
+ },
+ "outputs": ["coverage/"]
+ }
+ },
+ "tags": []
+}
diff --git a/apps/example-app/src/app/examples/02-input-output.spec.ts b/apps/example-app/src/app/examples/02-input-output.spec.ts
index 663d63e0..f1bd4a1c 100644
--- a/apps/example-app/src/app/examples/02-input-output.spec.ts
+++ b/apps/example-app/src/app/examples/02-input-output.spec.ts
@@ -33,8 +33,8 @@ test('is possible to set input and listen for output', async () => {
test('is possible to set input and listen for output with the template syntax', async () => {
const sendSpy = jest.fn();
- await render(InputOutputComponent, {
- template: '',
+ await render('', {
+ declarations: [InputOutputComponent],
componentProperties: {
sendValue: sendSpy,
},
diff --git a/apps/example-app/src/app/examples/03-forms.ts b/apps/example-app/src/app/examples/03-forms.ts
index 03fa74f3..bc035a14 100644
--- a/apps/example-app/src/app/examples/03-forms.ts
+++ b/apps/example-app/src/app/examples/03-forms.ts
@@ -57,9 +57,12 @@ export class FormsComponent {
return `${formKey} must be greater than ${error.min}`;
case 'max':
return `${formKey} must be lesser than ${error.max}`;
+ default:
+ return `${formKey} is invalid`;
}
});
}
+ return [];
})
.reduce((errors, value) => errors.concat(value), [])
.filter(Boolean);
diff --git a/apps/example-app/src/app/examples/04-forms-with-material.ts b/apps/example-app/src/app/examples/04-forms-with-material.ts
index e9a026ce..2718e389 100644
--- a/apps/example-app/src/app/examples/04-forms-with-material.ts
+++ b/apps/example-app/src/app/examples/04-forms-with-material.ts
@@ -79,9 +79,12 @@ export class MaterialFormsComponent {
return `${formKey} must be greater than ${error.min}`;
case 'max':
return `${formKey} must be lesser than ${error.max}`;
+ default:
+ return `${formKey} is invalid`;
}
});
}
+ return [];
})
.reduce((errors, value) => errors.concat(value), [])
.filter(Boolean);
diff --git a/apps/example-app/src/app/examples/11-ng-content.spec.ts b/apps/example-app/src/app/examples/11-ng-content.spec.ts
index 14a1630c..f061e862 100644
--- a/apps/example-app/src/app/examples/11-ng-content.spec.ts
+++ b/apps/example-app/src/app/examples/11-ng-content.spec.ts
@@ -1,14 +1,12 @@
-import { TestBed } from '@angular/core/testing';
import { render, screen } from '@testing-library/angular';
import { CellComponent } from './11-ng-content';
test('it is possible to test ng-content without selector', async () => {
const projection = 'it should be showed into a p element!';
-
- TestBed.overrideComponent(CellComponent, { set: { selector: 'cell' } });
- await render(CellComponent, {
- template: `${projection} | `,
+
+ await render(`${projection}`, {
+ declarations: [CellComponent]
});
expect(screen.getByText(projection)).toBeInTheDocument();
diff --git a/apps/example-app/src/app/examples/11-ng-content.ts b/apps/example-app/src/app/examples/11-ng-content.ts
index 302563f1..47845919 100644
--- a/apps/example-app/src/app/examples/11-ng-content.ts
+++ b/apps/example-app/src/app/examples/11-ng-content.ts
@@ -1,6 +1,7 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
+ selector: 'app-fixture',
template: `
diff --git a/apps/example-app/src/app/examples/16-input-getter-setter.spec.ts b/apps/example-app/src/app/examples/16-input-getter-setter.spec.ts
index 28d736c6..1d87edf9 100644
--- a/apps/example-app/src/app/examples/16-input-getter-setter.spec.ts
+++ b/apps/example-app/src/app/examples/16-input-getter-setter.spec.ts
@@ -10,16 +10,29 @@ test('should run logic in the input setter and getter', async () => {
expect(getterValueControl).toHaveTextContent('I am value from getter Angular');
});
-test('should run logic in the input setter and getter while re-rendering', async () => {
- const { rerender } = await render(InputGetterSetter, { componentProperties: { value: 'Angular' } });
+test('should run logic in the input setter and getter while changing', async () => {
+ const { change } = await render(InputGetterSetter, { componentProperties: { value: 'Angular' } });
const valueControl = screen.getByTestId('value');
const getterValueControl = screen.getByTestId('value-getter');
expect(valueControl).toHaveTextContent('I am value from setter Angular');
expect(getterValueControl).toHaveTextContent('I am value from getter Angular');
- await rerender({ value: 'React' });
+ await change({ value: 'React' });
expect(valueControl).toHaveTextContent('I am value from setter React');
expect(getterValueControl).toHaveTextContent('I am value from getter React');
});
+
+test('should run logic in the input setter and getter while re-rendering', async () => {
+ const { rerender } = await render(InputGetterSetter, { componentProperties: { value: 'Angular' } });
+
+ expect(screen.getByTestId('value')).toHaveTextContent('I am value from setter Angular');
+ expect(screen.getByTestId('value-getter')).toHaveTextContent('I am value from getter Angular');
+
+ await rerender({ value: 'React' });
+
+ // note we have to re-query because the elements are not the same anymore
+ expect(screen.getByTestId('value')).toHaveTextContent('I am value from setter React');
+ expect(screen.getByTestId('value-getter')).toHaveTextContent('I am value from getter React');
+});
diff --git a/apps/example-app/src/app/examples/17-component-with-attribute-selector.spec.ts b/apps/example-app/src/app/examples/17-component-with-attribute-selector.spec.ts
new file mode 100644
index 00000000..cd6334d1
--- /dev/null
+++ b/apps/example-app/src/app/examples/17-component-with-attribute-selector.spec.ts
@@ -0,0 +1,14 @@
+import { render, screen } from '@testing-library/angular';
+import {ComponentWithAttributeSelectorComponent} from './17-component-with-attribute-selector';
+
+// Note: At this stage it is not possible to use the render(ComponentWithAttributeSelectorComponent, {...}) syntax
+// for components with attribute selectors!
+test('is possible to set input of component with attribute selector through template', async () => {
+ await render(``, {
+ declarations: [ComponentWithAttributeSelectorComponent]
+ });
+
+ const valueControl = screen.getByTestId('value');
+
+ expect(valueControl).toHaveTextContent('42');
+});
diff --git a/apps/example-app/src/app/examples/17-component-with-attribute-selector.ts b/apps/example-app/src/app/examples/17-component-with-attribute-selector.ts
new file mode 100644
index 00000000..2d0b904b
--- /dev/null
+++ b/apps/example-app/src/app/examples/17-component-with-attribute-selector.ts
@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-fixture-component-with-attribute-selector[value]',
+ template: `
+ {{ value }}
+ `,
+})
+export class ComponentWithAttributeSelectorComponent {
+ @Input() value!: number;
+}
diff --git a/apps/example-app/src/polyfills.ts b/apps/example-app/src/polyfills.ts
index bb20fec0..f84fd8a6 100644
--- a/apps/example-app/src/polyfills.ts
+++ b/apps/example-app/src/polyfills.ts
@@ -34,22 +34,12 @@
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
-/** IE10 and IE11 requires the following for NgClass support on SVG elements */
-// import 'classlist.js'; // Run `npm install --save classlist.js`.
-
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
-/**
- * Web Animations `@angular/platform-browser/animations`
- * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
- * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
- **/
-// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
-
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
diff --git a/apps/example-app/tsconfig.app.json b/apps/example-app/tsconfig.app.json
index 629fd434..4de7101b 100644
--- a/apps/example-app/tsconfig.app.json
+++ b/apps/example-app/tsconfig.app.json
@@ -5,5 +5,7 @@
"types": [],
"allowJs": true
},
- "files": ["src/main.ts", "src/polyfills.ts"]
+ "files": ["src/main.ts", "src/polyfills.ts"],
+ "include": ["src/**/*.d.ts"],
+ "exclude": ["**/*.test.ts", "**/*.spec.ts"]
}
diff --git a/apps/example-app/tsconfig.json b/apps/example-app/tsconfig.json
index de50e310..523f7fc7 100644
--- a/apps/example-app/tsconfig.json
+++ b/apps/example-app/tsconfig.json
@@ -1,5 +1,5 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"compilerOptions": {},
diff --git a/apps/example-app/tsconfig.spec.json b/apps/example-app/tsconfig.spec.json
index afe056ed..d8a4c20f 100644
--- a/apps/example-app/tsconfig.spec.json
+++ b/apps/example-app/tsconfig.spec.json
@@ -6,5 +6,5 @@
"types": ["jest", "node", "@testing-library/jest-dom"]
},
"files": ["src/test-setup.ts"],
- "include": ["**/*.spec.ts", "**/*.d.ts"]
+ "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts"]
}
diff --git a/decorate-angular-cli.js b/decorate-angular-cli.js
new file mode 100644
index 00000000..bc81a837
--- /dev/null
+++ b/decorate-angular-cli.js
@@ -0,0 +1,69 @@
+/**
+ * This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching
+ * and faster execution of tasks.
+ *
+ * It does this by:
+ *
+ * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command.
+ * - Symlinking the ng to nx command, so all commands run through the Nx CLI
+ * - Updating the package.json postinstall script to give you control over this script
+ *
+ * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it.
+ * Every command you run should work the same when using the Nx CLI, except faster.
+ *
+ * Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case,
+ * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked.
+ * The Nx CLI simply does some optimizations before invoking the Angular CLI.
+ *
+ * To opt out of this patch:
+ * - Replace occurrences of nx with ng in your package.json
+ * - Remove the script from your postinstall script in your package.json
+ * - Delete and reinstall your node_modules
+ */
+
+const fs = require('fs');
+const os = require('os');
+const cp = require('child_process');
+const isWindows = os.platform() === 'win32';
+let output;
+try {
+ output = require('@nrwl/workspace').output;
+} catch (e) {
+ console.warn('Angular CLI could not be decorated to enable computation caching. Please ensure @nrwl/workspace is installed.');
+ process.exit(0);
+}
+
+/**
+ * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still
+ * invoke the Nx CLI and get the benefits of computation caching.
+ */
+function symlinkNgCLItoNxCLI() {
+ try {
+ const ngPath = './node_modules/.bin/ng';
+ const nxPath = './node_modules/.bin/nx';
+ if (isWindows) {
+ /**
+ * This is the most reliable way to create symlink-like behavior on Windows.
+ * Such that it works in all shells and works with npx.
+ */
+ ['', '.cmd', '.ps1'].forEach(ext => {
+ if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext));
+ });
+ } else {
+ // If unix-based, symlink
+ cp.execSync(`ln -sf ./nx ${ngPath}`);
+ }
+ }
+ catch(e) {
+ output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message });
+ throw e;
+ }
+}
+
+try {
+ symlinkNgCLItoNxCLI();
+ require('@nrwl/cli/lib/decorate-cli').decorateCli();
+ output.log({ title: 'Angular CLI has been decorated to enable computation caching.' });
+} catch(e) {
+ output.error({ title: 'Decoration of the Angular CLI did not complete successfully' });
+}
diff --git a/jest.preset.js b/jest.preset.js
index 3f434cfc..c9b13e14 100644
--- a/jest.preset.js
+++ b/jest.preset.js
@@ -3,8 +3,9 @@ module.exports = {
...nxPreset,
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
transform: {
- '^.+\\.(ts|js|html)$': 'ts-jest',
+ '^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular',
},
+ transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
resolver: '@nrwl/jest/plugins/resolver',
moduleFileExtensions: ['ts', 'js', 'html'],
globals: {
@@ -13,4 +14,9 @@ module.exports = {
stringifyContentPathRegex: '\\.(html|svg)$',
},
},
+ snapshotSerializers: [
+ 'jest-preset-angular/build/serializers/no-ng-attributes',
+ 'jest-preset-angular/build/serializers/ng-snapshot',
+ 'jest-preset-angular/build/serializers/html-comment',
+ ],
};
diff --git a/nx.json b/nx.json
index c9020cab..d8e87c08 100644
--- a/nx.json
+++ b/nx.json
@@ -1,18 +1,27 @@
{
+ "npmScope": "testing-library",
+ "affected": {
+ "defaultBase": "main"
+ },
+ "workspaceLayout": {
+ "appsDir": "apps",
+ "libsDir": "projects"
+ },
+ "cli": {
+ "analytics": false,
+ "cache": {
+ "enabled": true,
+ "path": "./.cache/angular",
+ "environment": "all"
+ }
+ },
"implicitDependencies": {
- "angular.json": "*",
"package.json": {
"dependencies": "*",
"devDependencies": "*"
},
- "tsconfig.base.json": "*",
- ".eslintrc.json": "*",
- "nx.json": "*"
- },
- "affected": {
- "defaultBase": "main"
+ ".eslintrc.json": "*"
},
- "npmScope": "testing-library",
"tasksRunnerOptions": {
"default": {
"runner": "@nrwl/nx-cloud",
@@ -20,22 +29,56 @@
"accessToken": "M2Q4YjlkNjMtMzY1NC00ZjkwLTk1ZjgtZjg5Y2VkMzFjM2FifHJlYWQtd3JpdGU=",
"cacheableOperations": ["build", "test", "lint", "e2e"],
"canTrackAnalytics": false,
- "showUsageWarnings": true
+ "showUsageWarnings": true,
+ "parallel": 3
}
}
},
- "projects": {
- "example-app": {
- "tags": []
+ "targetDependencies": {
+ "build": [
+ {
+ "target": "build",
+ "projects": "dependencies"
+ }
+ ]
+ },
+ "generators": {
+ "@nrlw/workspace:library": {
+ "linter": "eslint",
+ "unitTestRunner": "jest",
+ "strict": true,
+ "standaloneConfig": true,
+ "buildable": true
+ },
+ "@nrwl/angular:application": {
+ "style": "scss",
+ "linter": "eslint",
+ "unitTestRunner": "jest",
+ "e2eTestRunner": "cypress",
+ "strict": true,
+ "standaloneConfig": true,
+ "tags": ["type:app"]
},
- "example-app-karma": {
- "tags": []
+ "@nrwl/angular:library": {
+ "style": "scss",
+ "linter": "eslint",
+ "unitTestRunner": "jest",
+ "strict": true,
+ "standaloneConfig": true,
+ "publishable": true
},
- "jest-utils": {
- "tags": []
+ "@nrwl/angular:component": {
+ "style": "scss",
+ "displayBlock": true,
+ "changeDetection": "OnPush"
},
- "testing-library": {
- "tags": []
+ "@schematics/angular": {
+ "component": {
+ "style": "scss",
+ "displayBlock": true,
+ "changeDetection": "OnPush"
+ }
}
- }
+ },
+ "defaultProject": "example-app"
}
diff --git a/package.json b/package.json
index bf69d070..3c7c74ec 100644
--- a/package.json
+++ b/package.json
@@ -2,16 +2,16 @@
"name": "@testing-library/angular-app",
"version": "0.0.0-semantically-released",
"scripts": {
- "ng": "ng",
+ "ng": "nx",
"nx": "nx",
- "postinstall": "ngcc",
- "start": "ng serve",
+ "postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main",
+ "start": "nx serve",
"prebuild": "rimraf dist",
"build": "nx run-many --target=build --projects=testing-library,jest-utils",
"build:schematics": "tsc -p ./projects/testing-library/tsconfig.schematics.json",
"test": "nx run-many --target=test --all",
- "lint": "nx workspace-lint && ng lint",
- "e2e": "ng e2e",
+ "lint": "nx workspace-lint && nx lint",
+ "e2e": "nx e2e",
"affected:apps": "nx affected:apps",
"affected:libs": "nx affected:libs",
"affected:build": "nx affected:build",
@@ -28,72 +28,75 @@
"prepare": "husky install"
},
"dependencies": {
- "@angular/animations": "12.2.0",
- "@angular/cdk": "12.2.0",
- "@angular/common": "12.2.0",
- "@angular/compiler": "12.2.0",
- "@angular/core": "12.2.0",
- "@angular/forms": "12.2.0",
- "@angular/material": "12.2.0",
- "@angular/platform-browser": "12.2.0",
- "@angular/platform-browser-dynamic": "12.2.0",
- "@angular/router": "12.2.0",
- "@ngrx/store": "12.4.0",
- "@nrwl/angular": "12.9.0",
- "@nrwl/nx-cloud": "12.3.12",
- "@testing-library/dom": "^8.0.0",
- "@testing-library/user-event": "^13.1.9",
- "core-js": "^3.6.5",
- "rxjs": "^6.5.5",
- "tslib": "^2.0.0",
- "zone.js": "0.11.4"
+ "@angular/animations": "13.0.2",
+ "@angular/cdk": "13.0.2",
+ "@angular/common": "13.0.2",
+ "@angular/compiler": "13.0.2",
+ "@angular/core": "13.0.2",
+ "@angular/forms": "13.0.2",
+ "@angular/material": "13.0.2",
+ "@angular/platform-browser": "13.0.2",
+ "@angular/platform-browser-dynamic": "13.0.2",
+ "@angular/router": "13.0.2",
+ "@ngrx/store": "13.0.1",
+ "@nrwl/angular": "13.2.2",
+ "@nrwl/nx-cloud": "12.5.4",
+ "@testing-library/dom": "^8.11.1",
+ "@testing-library/user-event": "^13.5.0",
+ "rxjs": "^7.4.0",
+ "tslib": "~2.3.1",
+ "zone.js": "~0.11.4"
},
"devDependencies": {
- "@angular-devkit/build-angular": "12.2.7",
- "@angular-eslint/eslint-plugin": "12.3.1",
- "@angular-eslint/eslint-plugin-template": "12.3.1",
- "@angular-eslint/template-parser": "12.3.1",
- "@angular/cli": "12.2.7",
- "@angular/compiler-cli": "12.2.0",
- "@angular/language-service": "12.2.0",
- "@nrwl/cli": "12.9.0",
- "@nrwl/eslint-plugin-nx": "12.9.0",
- "@nrwl/jest": "12.9.0",
- "@nrwl/linter": "12.9.0",
- "@nrwl/node": "12.9.0",
- "@nrwl/nx-plugin": "12.9.0",
- "@nrwl/workspace": "12.9.0",
+ "@angular-devkit/build-angular": "13.0.3",
+ "@angular-eslint/eslint-plugin": "12.6.1",
+ "@angular-eslint/eslint-plugin-template": "12.6.1",
+ "@angular-eslint/template-parser": "12.6.1",
+ "@angular/cli": "13.0.3",
+ "@angular/compiler-cli": "13.0.2",
+ "@angular/language-service": "13.0.2",
+ "@nrwl/cli": "13.2.2",
+ "@nrwl/eslint-plugin-nx": "13.2.2",
+ "@nrwl/jest": "13.2.2",
+ "@nrwl/linter": "13.2.2",
+ "@nrwl/node": "13.2.2",
+ "@nrwl/nx-plugin": "13.2.2",
+ "@nrwl/workspace": "13.2.2",
"@testing-library/jasmine-dom": "^1.2.0",
- "@testing-library/jest-dom": "^5.11.10",
- "@types/jasmine": "^3.5.0",
- "@types/jest": "^27.0.2",
+ "@testing-library/jest-dom": "^5.15.1",
+ "@types/jasmine": "^3.10.2",
+ "@types/jest": "27.0.3",
"@types/node": "14.14.37",
- "@typescript-eslint/eslint-plugin": "4.28.5",
- "@typescript-eslint/parser": "4.28.5",
+ "@typescript-eslint/eslint-plugin": "4.33.0",
+ "@typescript-eslint/parser": "4.33.0",
"cpy-cli": "^3.1.1",
- "eslint": "^7.25.0",
+ "eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-import": "2.23.4",
"eslint-plugin-jasmine": "^4.1.2",
"eslint-plugin-jest": "24.3.6",
"eslint-plugin-jest-dom": "3.9.0",
"eslint-plugin-testing-library": "4.9.0",
- "husky": "^6.0.0",
- "jasmine-core": "^3.7.0",
- "jasmine-spec-reporter": "^5.0.0",
- "jest": "^27.0.6",
- "jest-preset-angular": "9.0.7",
- "karma": "^6.3.4",
+ "husky": "^7.0.0",
+ "jasmine-core": "^3.10.1",
+ "jasmine-spec-reporter": "^7.0.0",
+ "jest": "27.3.1",
+ "jest-preset-angular": "11.0.1",
+ "karma": "^6.3.9",
"karma-chrome-launcher": "^3.1.0",
- "karma-jasmine": "^4.0.0",
- "karma-jasmine-html-reporter": "^1.5.0",
- "lint-staged": "^10.2.11",
- "ng-packagr": "12.2.2",
- "prettier": "^2.3.0",
+ "karma-jasmine": "^4.0.1",
+ "karma-jasmine-html-reporter": "^1.7.0",
+ "lint-staged": "^12.1.2",
+ "ng-packagr": "~13.0.7",
+ "postcss": "^8.3.11",
+ "postcss-import": "^14.0.2",
+ "postcss-preset-env": "^7.0.1",
+ "postcss-url": "^10.1.3",
+ "prettier": "^2.4.1",
"rimraf": "^3.0.2",
- "semantic-release": "^17.1.1",
- "ts-jest": "^27.0.3",
- "ts-node": "9.1.1",
- "typescript": "4.3.5"
+ "semantic-release": "^18.0.0",
+ "ts-jest": "27.0.7",
+ "ts-node": "~10.4.0",
+ "typescript": "4.4.4"
}
}
diff --git a/projects/jest-utils/package.json b/projects/jest-utils/package.json
index 09dc20bf..4462dc31 100644
--- a/projects/jest-utils/package.json
+++ b/projects/jest-utils/package.json
@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/testing-library/angular-testing-library#readme",
"peerDependencies": {
- "jest": ">=23.4.0"
+ "jest": ">=27.0.0"
},
"publishConfig": {
"access": "public"
diff --git a/projects/jest-utils/project.json b/projects/jest-utils/project.json
new file mode 100644
index 00000000..8c4976f6
--- /dev/null
+++ b/projects/jest-utils/project.json
@@ -0,0 +1,54 @@
+{
+ "projectType": "library",
+ "root": "projects/jest-utils",
+ "sourceRoot": "projects/jest-utils/src",
+ "prefix": "lib",
+ "targets": {
+ "build-package": {
+ "executor": "@nrwl/angular:package",
+ "outputs": ["dist/@testing-library/angular/jest-utils"],
+ "options": {
+ "project": "projects/jest-utils/ng-package.json"
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "projects/jest-utils/tsconfig.lib.prod.json"
+ },
+ "development": {
+ "tsConfig": "projects/jest-utils/tsconfig.lib.json"
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "options": {
+ "lintFilePatterns": [
+ "projects/jest-utils/**/*.ts",
+ "projects/jest-utils/**/*.html",
+ "projects/jest-utils/src/**/*.html"
+ ]
+ },
+ "outputs": ["{options.outputFile}"]
+ },
+ "build": {
+ "executor": "@nrwl/workspace:run-commands",
+ "options": {
+ "parallel": false,
+ "commands": [
+ {
+ "command": "nx run jest-utils:build-package"
+ }
+ ]
+ }
+ },
+ "test": {
+ "executor": "@nrwl/jest:jest",
+ "options": {
+ "jestConfig": "projects/jest-utils/jest.config.js"
+ },
+ "outputs": ["coverage/projects/jest-utils"]
+ }
+ },
+ "tags": []
+}
diff --git a/projects/jest-utils/src/lib/create-mock.ts b/projects/jest-utils/src/lib/create-mock.ts
index 2796d972..73cbf406 100644
--- a/projects/jest-utils/src/lib/create-mock.ts
+++ b/projects/jest-utils/src/lib/create-mock.ts
@@ -16,7 +16,7 @@ export function createMock(type: Type): Mock {
}
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
- if (typeof descriptor.value === 'function') {
+ if (typeof descriptor?.value === 'function') {
mock[prop] = jest.fn();
}
}
diff --git a/projects/jest-utils/tests/create-mock.spec.ts b/projects/jest-utils/tests/create-mock.spec.ts
index ded7ab1c..2393fe30 100644
--- a/projects/jest-utils/tests/create-mock.spec.ts
+++ b/projects/jest-utils/tests/create-mock.spec.ts
@@ -45,10 +45,12 @@ test('provides a mock service', async () => {
test('provides a mock service with values', async () => {
await render(FixtureComponent, {
- providers: [provideMockWithValues(FixtureService, {
- bar: 'value',
- concat: jest.fn(() => 'a concatenated value')
- })],
+ providers: [
+ provideMockWithValues(FixtureService, {
+ bar: 'value',
+ concat: jest.fn(() => 'a concatenated value'),
+ }),
+ ],
});
const service = TestBed.inject(FixtureService);
diff --git a/projects/jest-utils/tsconfig.json b/projects/jest-utils/tsconfig.json
new file mode 100644
index 00000000..24663f6f
--- /dev/null
+++ b/projects/jest-utils/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.lib.prod.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {},
+ "angularCompilerOptions": {
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true,
+ "flatModuleId": "AUTOGENERATED",
+ "flatModuleOutFile": "AUTOGENERATED"
+ }
+}
diff --git a/projects/jest-utils/tsconfig.lib.json b/projects/jest-utils/tsconfig.lib.json
index 7a6179a2..22fef254 100644
--- a/projects/jest-utils/tsconfig.lib.json
+++ b/projects/jest-utils/tsconfig.lib.json
@@ -1,29 +1,11 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
- "target": "es2015",
- "declarationMap": false,
- "module": "es2015",
- "moduleResolution": "node",
"declaration": true,
- "sourceMap": true,
+ "declarationMap": true,
"inlineSources": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "importHelpers": true,
- "allowSyntheticDefaultImports": true,
- "types": ["jest"],
- "lib": ["dom", "es2018"]
+ "types": ["jest"]
},
- "angularCompilerOptions": {
- "enableIvy": false,
- "skipTemplateCodegen": true,
- "strictMetadataEmit": true,
- "fullTemplateTypeCheck": true,
- "strictInjectionParameters": true,
- "flatModuleId": "AUTOGENERATED",
- "flatModuleOutFile": "AUTOGENERATED"
- },
- "exclude": ["src/test.ts", "**/*.spec.ts"]
+ "exclude": ["src/test.ts", "**/*.spec.ts", "**/*.test.ts"]
}
diff --git a/projects/jest-utils/tsconfig.lib.prod.json b/projects/jest-utils/tsconfig.lib.prod.json
new file mode 100644
index 00000000..2a2faa88
--- /dev/null
+++ b/projects/jest-utils/tsconfig.lib.prod.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.lib.json",
+ "compilerOptions": {
+ "declarationMap": false
+ },
+ "angularCompilerOptions": {
+ "compilationMode": "partial"
+ }
+}
diff --git a/projects/jest-utils/tsconfig.spec.json b/projects/jest-utils/tsconfig.spec.json
index 091c5cf3..73461f35 100644
--- a/projects/jest-utils/tsconfig.spec.json
+++ b/projects/jest-utils/tsconfig.spec.json
@@ -1,9 +1,9 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"types": ["node", "jest", "@testing-library/jest-dom"]
},
"files": ["test-setup.ts"],
- "include": ["**/*.spec.ts", "**/*.d.ts"]
+ "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts"]
}
diff --git a/projects/testing-library/package.json b/projects/testing-library/package.json
index f1922ae6..e41389cf 100644
--- a/projects/testing-library/package.json
+++ b/projects/testing-library/package.json
@@ -29,11 +29,11 @@
"migrations": "./schematics/migrations/migration.json"
},
"peerDependencies": {
- "@angular/common": ">= 10.0.0",
- "@angular/platform-browser": ">= 10.0.0",
- "@angular/animations": ">= 10.0.0",
- "@angular/router": ">= 10.0.0",
- "@angular/core": ">= 10.0.0"
+ "@angular/common": ">= 13.0.0",
+ "@angular/platform-browser": ">= 13.0.0",
+ "@angular/animations": ">= 13.0.0",
+ "@angular/router": ">= 13.0.0",
+ "@angular/core": ">= 13.0.0"
},
"dependencies": {
"@testing-library/dom": "^8.0.0",
diff --git a/projects/testing-library/project.json b/projects/testing-library/project.json
new file mode 100644
index 00000000..fe6d0834
--- /dev/null
+++ b/projects/testing-library/project.json
@@ -0,0 +1,60 @@
+{
+ "projectType": "library",
+ "root": "projects/testing-library",
+ "sourceRoot": "projects/testing-library/src",
+ "prefix": "lib",
+ "targets": {
+ "build-package": {
+ "executor": "@nrwl/angular:package",
+ "outputs": ["dist/@testing-library/angular"],
+ "options": {
+ "project": "projects/testing-library/ng-package.json"
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "projects/testing-library/tsconfig.lib.prod.json"
+ },
+ "development": {
+ "tsConfig": "projects/testing-library/tsconfig.lib.json"
+ }
+ },
+ "defaultConfiguration": "production"
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "options": {
+ "lintFilePatterns": [
+ "projects/testing-library/**/*.ts",
+ "projects/testing-library/**/*.html",
+ "projects/testing-library/src/**/*.html"
+ ]
+ },
+ "outputs": ["{options.outputFile}"]
+ },
+ "build": {
+ "executor": "@nrwl/workspace:run-commands",
+ "options": {
+ "parallel": false,
+ "commands": [
+ {
+ "command": "nx run testing-library:build-package"
+ },
+ {
+ "command": "npm run build:schematics"
+ },
+ {
+ "command": "cpy ./README.md ./dist/@testing-library/angular"
+ }
+ ]
+ }
+ },
+ "test": {
+ "executor": "@nrwl/jest:jest",
+ "options": {
+ "jestConfig": "projects/testing-library/jest.config.js"
+ },
+ "outputs": ["coverage/projects/testing-library"]
+ }
+ },
+ "tags": []
+}
diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts
index 54b5f2ee..7f5a02a7 100644
--- a/projects/testing-library/src/lib/models.ts
+++ b/projects/testing-library/src/lib/models.ts
@@ -54,9 +54,16 @@ export interface RenderResult extend
navigate: (elementOrPath: Element | string, basePath?: string) => Promise;
/**
* @description
- * Re-render the same component with different props.
+ * Re-render the same component with different properties.
+ * This creates a new instance of the component.
*/
- rerender: (componentProperties: Partial) => void;
+ rerender: (rerenderedProperties: Partial) => void;
+
+ /**
+ * @description
+ * Keeps the current fixture intact and invokes ngOnChanges with the updated properties.
+ */
+ change: (changedProperties: Partial) => void;
}
export interface RenderComponentOptions {
@@ -249,43 +256,6 @@ export interface RenderComponentOptions
- extends RenderComponentOptions {
- /**
- * @description
- * The template to render the directive.
- * This template will override the template from the WrapperComponent.
- *
- * @example
- * const component = await render(SpoilerDirective, {
- * template: ``
- * })
- *
- * @deprecated Use `render(template, { declarations: [SomeDirective] })` instead.
- */
- template: string;
- /**
- * @description
- * An Angular component to wrap the component in.
- * The template will be overridden with the `template` option.
- *
- * @default
- * `WrapperComponent`, an empty component that strips the `ng-version` attribute
- *
- * @example
- * const component = await render(SpoilerDirective, {
- * template: ``
- * wrapper: CustomWrapperComponent
- * })
- */
- wrapper?: Type;
- componentProperties?: Partial;
-}
-
// eslint-disable-next-line @typescript-eslint/ban-types
export interface RenderTemplateOptions
extends RenderComponentOptions {
diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts
index 36ee871b..1a517aa2 100644
--- a/projects/testing-library/src/lib/testing-library.ts
+++ b/projects/testing-library/src/lib/testing-library.ts
@@ -26,7 +26,7 @@ import {
getQueriesForElement,
queries as dtlQueries,
} from '@testing-library/dom';
-import { RenderComponentOptions, RenderDirectiveOptions, RenderTemplateOptions, RenderResult } from './models';
+import { RenderComponentOptions, RenderTemplateOptions, RenderResult } from './models';
import { getConfig } from './config';
const mountedFixtures = new Set>();
@@ -36,13 +36,6 @@ export async function render(
component: Type,
renderOptions?: RenderComponentOptions,
): Promise>;
-/**
- * @deprecated Use `render(template, { declarations: [DirectiveType] })` instead.
- */
-export async function render(
- component: Type,
- renderOptions?: RenderDirectiveOptions,
-): Promise>;
export async function render(
template: string,
renderOptions?: RenderTemplateOptions,
@@ -50,10 +43,7 @@ export async function render(
export async function render(
sut: Type | string,
- renderOptions:
- | RenderComponentOptions
- | RenderDirectiveOptions
- | RenderTemplateOptions = {},
+ renderOptions: RenderComponentOptions | RenderTemplateOptions = {},
): Promise> {
const { dom: domConfig, ...globalConfig } = getConfig();
const {
@@ -86,7 +76,6 @@ export async function render(
declarations: addAutoDeclarations(sut, {
declarations,
excludeComponentDeclaration,
- template,
wrapper,
}),
imports: addAutoImports({
@@ -97,53 +86,30 @@ export async function render(
schemas: [...schemas],
});
- if (componentProviders) {
- componentProviders
- .reduce((acc, provider) => acc.concat(provider), [])
- .forEach((p) => {
- const { provide, ...provider } = p;
- TestBed.overrideProvider(provide, provider);
- });
- }
-
- const fixture = await createComponentFixture(sut, { template, wrapper });
- setComponentProperties(fixture, { componentProperties });
-
- if (removeAngularAttributes) {
- fixture.nativeElement.removeAttribute('ng-version');
- const idAttribute = fixture.nativeElement.getAttribute('id');
- if (idAttribute && idAttribute.startsWith('root')) {
- fixture.nativeElement.removeAttribute('id');
- }
- }
-
- mountedFixtures.add(fixture);
-
await TestBed.compileComponents();
- let isAlive = true;
- fixture.componentRef.onDestroy(() => (isAlive = false));
+ componentProviders
+ .reduce((acc, provider) => acc.concat(provider), [])
+ .forEach((p) => {
+ const { provide, ...provider } = p;
+ TestBed.overrideProvider(provide, provider);
+ });
- function detectChanges() {
- if (isAlive) {
- fixture.detectChanges();
- }
- }
+ const componentContainer = createComponentFixture(sut, { wrapper });
- // Call ngOnChanges on initial render
- if (hasOnChangesHook(fixture.componentInstance)) {
- const changes = getChangesObj(null, componentProperties);
- fixture.componentInstance.ngOnChanges(changes);
- }
+ let fixture: ComponentFixture;
+ let detectChanges: () => void;
- if (detectChangesOnRender) {
- detectChanges();
- }
+ await renderFixture(componentProperties);
- const rerender = (rerenderedProperties: Partial) => {
- const changes = getChangesObj(fixture.componentInstance, rerenderedProperties);
+ const rerender = async (rerenderedProperties: Partial) => {
+ await renderFixture(rerenderedProperties);
+ };
- setComponentProperties(fixture, { componentProperties: rerenderedProperties });
+ const change = (changedProperties: Partial) => {
+ const changes = getChangesObj(fixture.componentInstance, changedProperties);
+
+ setComponentProperties(fixture, { componentProperties: changedProperties });
if (hasOnChangesHook(fixture.componentInstance)) {
fixture.componentInstance.ngOnChanges(changes);
@@ -164,8 +130,14 @@ export async function render(
const queryParams = params
? params.split('&').reduce((qp, q) => {
const [key, value] = q.split('=');
- // TODO(Breaking): group same keys qp[key] ? [...qp[key], value] : value
- qp[key] = value;
+ const currentValue = qp[key];
+ if (typeof currentValue === 'undefined') {
+ qp[key] = value;
+ } else if (Array.isArray(currentValue)) {
+ qp[key] = [...currentValue, value];
+ } else {
+ qp[key] = [currentValue, value];
+ }
return qp;
}, {})
: undefined;
@@ -192,9 +164,10 @@ export async function render(
return {
fixture,
- detectChanges,
+ detectChanges: () => detectChanges(),
navigate,
rerender,
+ change,
debugElement: typeof sut === 'string' ? fixture.debugElement : fixture.debugElement.query(By.directive(sut)),
container: fixture.nativeElement,
debug: (element = fixture.nativeElement, maxLength, options) =>
@@ -203,6 +176,42 @@ export async function render(
: console.log(dtlPrettyDOM(element, maxLength, options)),
...replaceFindWithFindAndDetectChanges(dtlGetQueriesForElement(fixture.nativeElement, queries)),
};
+
+ async function renderFixture(properties: Partial) {
+ if (fixture) {
+ cleanupAtFixture(fixture);
+ }
+
+ fixture = await createComponent(componentContainer);
+ setComponentProperties(fixture, { componentProperties: properties });
+
+ if (removeAngularAttributes) {
+ fixture.nativeElement.removeAttribute('ng-version');
+ const idAttribute = fixture.nativeElement.getAttribute('id');
+ if (idAttribute && idAttribute.startsWith('root')) {
+ fixture.nativeElement.removeAttribute('id');
+ }
+ }
+ mountedFixtures.add(fixture);
+
+ let isAlive = true;
+ fixture.componentRef.onDestroy(() => (isAlive = false));
+
+ if (hasOnChangesHook(fixture.componentInstance)) {
+ const changes = getChangesObj(null, componentProperties);
+ fixture.componentInstance.ngOnChanges(changes);
+ }
+
+ detectChanges = () => {
+ if (isAlive) {
+ fixture.detectChanges();
+ }
+ };
+
+ if (detectChangesOnRender) {
+ detectChanges();
+ }
+ }
}
async function createComponent(component: Type): Promise> {
@@ -211,24 +220,20 @@ async function createComponent(component: Type): Promise(
+function createComponentFixture(
sut: Type | string,
- { template, wrapper }: Pick, 'template' | 'wrapper'>,
-): Promise> {
+ { wrapper }: Pick, 'wrapper'>,
+): Type {
if (typeof sut === 'string') {
TestBed.overrideTemplate(wrapper, sut);
- return createComponent(wrapper);
- }
- if (template) {
- TestBed.overrideTemplate(wrapper, template);
- return createComponent(wrapper);
+ return wrapper;
}
- return createComponent(sut);
+ return sut;
}
function setComponentProperties(
fixture: ComponentFixture,
- { componentProperties = {} }: Pick, 'componentProperties'>,
+ { componentProperties = {} }: Pick, 'componentProperties'>,
) {
for (const key of Object.keys(componentProperties)) {
const descriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(
@@ -279,19 +284,15 @@ function addAutoDeclarations(
{
declarations,
excludeComponentDeclaration,
- template,
wrapper,
- }: Pick, 'declarations' | 'excludeComponentDeclaration' | 'template' | 'wrapper'>,
+ }: Pick, 'declarations' | 'excludeComponentDeclaration' | 'wrapper'>,
) {
if (typeof sut === 'string') {
return [...declarations, wrapper];
}
- const wrappers = () => (template ? [wrapper] : []);
-
const components = () => (excludeComponentDeclaration ? [] : [sut]);
-
- return [...declarations, ...wrappers(), ...components()];
+ return [...declarations, ...components()];
}
function addAutoImports({ imports, routes }: Pick, 'imports' | 'routes'>) {
@@ -387,9 +388,7 @@ if (typeof process === 'undefined' || !process.env?.ATL_SKIP_AUTO_CLEANUP) {
}
}
-// TODO: rename to `atl-wrapper-component`
-// eslint-disable-next-line @angular-eslint/component-selector
-@Component({ selector: 'wrapper-component', template: '' })
+@Component({ selector: 'atl-wrapper-component', template: '' })
class WrapperComponent {}
/**
diff --git a/projects/testing-library/tests/change.spec.ts b/projects/testing-library/tests/change.spec.ts
new file mode 100644
index 00000000..85cc3667
--- /dev/null
+++ b/projects/testing-library/tests/change.spec.ts
@@ -0,0 +1,85 @@
+import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { render, screen } from '../src/public_api';
+
+@Component({
+ selector: 'atl-fixture',
+ template: ` {{ firstName }} {{ lastName }} `,
+})
+class FixtureComponent {
+ @Input() firstName = 'Sarah';
+ @Input() lastName;
+}
+
+test('changes the component with updated props', async () => {
+ const { change } = await render(FixtureComponent);
+ expect(screen.getByText('Sarah')).toBeInTheDocument();
+
+ const firstName = 'Mark';
+ change({ firstName });
+
+ expect(screen.getByText(firstName)).toBeInTheDocument();
+});
+
+test('changes the component with updated props while keeping other props untouched', async () => {
+ const firstName = 'Mark';
+ const lastName = 'Peeters';
+ const { change } = await render(FixtureComponent, {
+ componentProperties: {
+ firstName,
+ lastName,
+ },
+ });
+
+ expect(screen.getByText(`${firstName} ${lastName}`)).toBeInTheDocument();
+
+ const firstName2 = 'Chris';
+ change({ firstName: firstName2 });
+
+ expect(screen.getByText(`${firstName2} ${lastName}`)).toBeInTheDocument();
+});
+
+@Component({
+ selector: 'atl-fixture',
+ template: ` {{ name }} `,
+})
+class FixtureWithNgOnChangesComponent implements OnChanges {
+ @Input() name = 'Sarah';
+ @Input() nameChanged: (name: string, isFirstChange: boolean) => void;
+
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes.name && this.nameChanged) {
+ this.nameChanged(changes.name.currentValue, changes.name.isFirstChange());
+ }
+ }
+}
+
+test('will call ngOnChanges on change', async () => {
+ const nameChanged = jest.fn();
+ const componentProperties = { nameChanged };
+ const { change } = await render(FixtureWithNgOnChangesComponent, { componentProperties });
+ expect(screen.getByText('Sarah')).toBeInTheDocument();
+
+ const name = 'Mark';
+ change({ name });
+
+ expect(screen.getByText(name)).toBeInTheDocument();
+ expect(nameChanged).toHaveBeenCalledWith(name, false);
+});
+
+@Component({
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ selector: 'atl-fixture',
+ template: ` Number
`,
+})
+class FixtureWithOnPushComponent {
+ @Input() activeField: string;
+}
+
+test('update properties on change', async () => {
+ const { change } = await render(FixtureWithOnPushComponent);
+ const numberHtmlElementRef = screen.queryByTestId('number');
+
+ expect(numberHtmlElementRef).not.toHaveClass('active');
+ change({ activeField: 'number' });
+ expect(numberHtmlElementRef).toHaveClass('active');
+});
diff --git a/projects/testing-library/tests/render-template.spec.ts b/projects/testing-library/tests/render-template.spec.ts
index 60c2a074..9dd20d01 100644
--- a/projects/testing-library/tests/render-template.spec.ts
+++ b/projects/testing-library/tests/render-template.spec.ts
@@ -62,15 +62,6 @@ test('the component renders', async () => {
expect(screen.getByText('Hello Angular!')).toBeInTheDocument();
});
-test('the directive renders (compatibility with the deprecated signature)', async () => {
- const view = await render(OnOffDirective, {
- template: '',
- });
-
- // eslint-disable-next-line testing-library/no-container
- expect(view.container.querySelector('[onoff]')).toBeInTheDocument();
-});
-
test('uses the default props', async () => {
await render('', {
declarations: [OnOffDirective],
diff --git a/projects/testing-library/tests/render.spec.ts b/projects/testing-library/tests/render.spec.ts
index 678da79c..8312bd4a 100644
--- a/projects/testing-library/tests/render.spec.ts
+++ b/projects/testing-library/tests/render.spec.ts
@@ -10,7 +10,7 @@ import {
} from '@angular/core';
import { NoopAnimationsModule, BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TestBed } from '@angular/core/testing';
-import { render, fireEvent, screen } from '../src/public_api';
+import { render, fireEvent } from '../src/public_api';
@Component({
selector: 'atl-fixture',
diff --git a/projects/testing-library/tests/rerender.spec.ts b/projects/testing-library/tests/rerender.spec.ts
index c98bd1bc..443560a2 100644
--- a/projects/testing-library/tests/rerender.spec.ts
+++ b/projects/testing-library/tests/rerender.spec.ts
@@ -1,66 +1,40 @@
-import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { Component, Input } from '@angular/core';
import { render, screen } from '../src/public_api';
@Component({
selector: 'atl-fixture',
- template: ` {{ name }} `,
+ template: ` {{ firstName }} {{ lastName }} `,
})
class FixtureComponent {
- @Input() name = 'Sarah';
+ @Input() firstName = 'Sarah';
+ @Input() lastName;
}
-test('will rerender the component with updated props', async () => {
+test('rerenders the component with updated props', async () => {
const { rerender } = await render(FixtureComponent);
expect(screen.getByText('Sarah')).toBeInTheDocument();
- const name = 'Mark';
- rerender({ name });
+ const firstName = 'Mark';
+ await rerender({ firstName });
- expect(screen.getByText(name)).toBeInTheDocument();
+ expect(screen.getByText(firstName)).toBeInTheDocument();
});
-@Component({
- selector: 'atl-fixture',
- template: ` {{ name }} `,
-})
-class FixtureWithNgOnChangesComponent implements OnChanges {
- @Input() name = 'Sarah';
- @Input() nameChanged: (name: string, isFirstChange: boolean) => void;
-
- ngOnChanges(changes: SimpleChanges) {
- if (changes.name && this.nameChanged) {
- this.nameChanged(changes.name.currentValue, changes.name.isFirstChange());
- }
- }
-}
-
-test('will call ngOnChanges on rerender', async () => {
- const nameChanged = jest.fn();
- const componentProperties = { nameChanged };
- const { rerender } = await render(FixtureWithNgOnChangesComponent, { componentProperties });
- expect(screen.getByText('Sarah')).toBeInTheDocument();
+test('rerenders the component with updated props and resets other props', async () => {
+ const firstName = 'Mark';
+ const lastName = 'Peeters';
+ const { rerender } = await render(FixtureComponent, {
+ componentProperties: {
+ firstName,
+ lastName,
+ },
+ });
- const name = 'Mark';
- rerender({ name });
-
- expect(screen.getByText(name)).toBeInTheDocument();
- expect(nameChanged).toHaveBeenCalledWith(name, false);
-});
-
-@Component({
- changeDetection: ChangeDetectionStrategy.OnPush,
- selector: 'atl-fixture',
- template: ` Number
`,
-})
-class FixtureWithOnPushComponent {
- @Input() activeField: string;
-}
+ expect(screen.getByText(`${firstName} ${lastName}`)).toBeInTheDocument();
-test('update properties on rerender', async () => {
- const { rerender } = await render(FixtureWithOnPushComponent);
- const numberHtmlElementRef = screen.queryByTestId('number');
+ const firstName2 = 'Chris';
+ rerender({ firstName: firstName2 });
- expect(numberHtmlElementRef).not.toHaveClass('active');
- rerender({ activeField: 'number' });
- expect(numberHtmlElementRef).toHaveClass('active');
+ expect(screen.queryByText(`${firstName2} ${lastName}`)).not.toBeInTheDocument();
+ expect(screen.queryByText(firstName2)).not.toBeInTheDocument();
});
diff --git a/projects/testing-library/tsconfig.json b/projects/testing-library/tsconfig.json
new file mode 100644
index 00000000..24663f6f
--- /dev/null
+++ b/projects/testing-library/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.lib.json"
+ },
+ {
+ "path": "./tsconfig.lib.prod.json"
+ },
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ],
+ "compilerOptions": {},
+ "angularCompilerOptions": {
+ "strictInjectionParameters": true,
+ "strictInputAccessModifiers": true,
+ "strictTemplates": true,
+ "flatModuleId": "AUTOGENERATED",
+ "flatModuleOutFile": "AUTOGENERATED"
+ }
+}
diff --git a/projects/testing-library/tsconfig.lib.json b/projects/testing-library/tsconfig.lib.json
index 8506c888..f7b1b9ca 100644
--- a/projects/testing-library/tsconfig.lib.json
+++ b/projects/testing-library/tsconfig.lib.json
@@ -1,28 +1,11 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
- "declarationMap": false,
- "target": "es2015",
- "module": "ES2015",
- "moduleResolution": "node",
"declaration": true,
- "sourceMap": true,
+ "declarationMap": true,
"inlineSources": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "importHelpers": false,
- "types": ["node", "jest"],
- "lib": ["dom", "es2018"]
+ "types": ["node", "jest"]
},
- "angularCompilerOptions": {
- "enableIvy": false,
- "skipTemplateCodegen": true,
- "strictMetadataEmit": true,
- "fullTemplateTypeCheck": true,
- "strictInjectionParameters": true,
- "flatModuleId": "AUTOGENERATED",
- "flatModuleOutFile": "AUTOGENERATED"
- },
- "exclude": ["src/test.ts", "**/*.spec.ts"]
+ "exclude": ["src/test.ts", "**/*.spec.ts", "**/*.test.ts"]
}
diff --git a/projects/testing-library/tsconfig.lib.prod.json b/projects/testing-library/tsconfig.lib.prod.json
new file mode 100644
index 00000000..2a2faa88
--- /dev/null
+++ b/projects/testing-library/tsconfig.lib.prod.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.lib.json",
+ "compilerOptions": {
+ "declarationMap": false
+ },
+ "angularCompilerOptions": {
+ "compilationMode": "partial"
+ }
+}
diff --git a/projects/testing-library/tsconfig.schematics.json b/projects/testing-library/tsconfig.schematics.json
index 91de9574..0573a52a 100644
--- a/projects/testing-library/tsconfig.schematics.json
+++ b/projects/testing-library/tsconfig.schematics.json
@@ -1,5 +1,5 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "../../tsconfig.base.json",
"compilerOptions": {
"strict": true,
"target": "es6",
diff --git a/projects/testing-library/tsconfig.spec.json b/projects/testing-library/tsconfig.spec.json
index 091c5cf3..73461f35 100644
--- a/projects/testing-library/tsconfig.spec.json
+++ b/projects/testing-library/tsconfig.spec.json
@@ -1,9 +1,9 @@
{
- "extends": "../../tsconfig.json",
+ "extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"types": ["node", "jest", "@testing-library/jest-dom"]
},
"files": ["test-setup.ts"],
- "include": ["**/*.spec.ts", "**/*.d.ts"]
+ "include": ["**/*.spec.ts", "**/*.test.ts", "**/*.d.ts"]
}
diff --git a/projects/vscode-atl-render/.vscode/launch.json b/projects/vscode-atl-render/.vscode/launch.json
index 0e191b59..4058e694 100644
--- a/projects/vscode-atl-render/.vscode/launch.json
+++ b/projects/vscode-atl-render/.vscode/launch.json
@@ -3,15 +3,13 @@
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Extension",
- "type": "extensionHost",
- "request": "launch",
- "args": [
- "--extensionDevelopmentPath=${workspaceFolder}"
- ]
- }
- ]
-}
\ No newline at end of file
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "args": ["--extensionDevelopmentPath=${workspaceFolder}"]
+ }
+ ]
+}
diff --git a/tsconfig.json b/tsconfig.base.json
similarity index 73%
rename from tsconfig.json
rename to tsconfig.base.json
index 69eb7ed5..0ad01d03 100644
--- a/tsconfig.json
+++ b/tsconfig.base.json
@@ -2,20 +2,24 @@
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
+ "declaration": false,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
"importHelpers": true,
+ "lib": ["es2018", "dom"],
"module": "esnext",
+ "moduleResolution": "node",
"outDir": "./dist/out-tsc",
"sourceMap": true,
- "declaration": false,
- "moduleResolution": "node",
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
"target": "es2015",
"typeRoots": ["node_modules/@types"],
- "lib": ["es2017", "dom"],
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
"paths": {
"@testing-library/angular": ["projects/testing-library"],
"@testing-library/angular/jest-utils": ["projects/jest-utils"]
}
- }
+ },
+ "exclude": ["node_modules", "tmp"]
}
diff --git a/workspace.json b/workspace.json
new file mode 100644
index 00000000..dfd6bcf1
--- /dev/null
+++ b/workspace.json
@@ -0,0 +1,9 @@
+{
+ "version": 2,
+ "projects": {
+ "example-app": "apps/example-app",
+ "example-app-karma": "apps/example-app-karma",
+ "jest-utils": "projects/jest-utils",
+ "testing-library": "projects/testing-library"
+ }
+}