diff --git a/.all-contributorsrc b/.all-contributorsrc
index 96c7a291..dbc27208 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -274,6 +274,16 @@
         "doc",
         "test"
       ]
+    },
+    {
+      "login": "meirka",
+      "name": "MeIr",
+      "avatar_url": "https://avatars.githubusercontent.com/u/750901?v=4",
+      "profile": "https://github.com/meirka",
+      "contributions": [
+        "bug",
+        "test"
+      ]
     }
   ],
   "contributorsPerLine": 7,
diff --git a/.githooks/pre-commit b/.githooks/pre-commit
new file mode 100644
index 00000000..f0f7d343
--- /dev/null
+++ b/.githooks/pre-commit
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+npm run pre-commit
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 998b0652..80741a41 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,6 +7,10 @@ on:
       - 'beta'
   pull_request: {}
 
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
 jobs:
   build_test_release:
     strategy:
@@ -34,4 +38,3 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
           CI: true
-          HUSKY: 0
diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh
deleted file mode 100644
index ca2720e0..00000000
--- a/.husky/_/husky.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/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/.husky/pre-commit b/.husky/pre-commit
deleted file mode 100644
index d0612ad3..00000000
--- a/.husky/pre-commit
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-. "$(dirname "$0")/_/husky.sh"
-
-npm run pre-commit
diff --git a/.node-version b/.node-version
new file mode 100644
index 00000000..b6a7d89c
--- /dev/null
+++ b/.node-version
@@ -0,0 +1 @@
+16
diff --git a/README.md b/README.md
index d750dae4..a66015c9 100644
--- a/README.md
+++ b/README.md
@@ -219,6 +219,9 @@ Thanks goes to these people ([emoji key][emojis]):
     <td align="center"><a href="https://matan.io"><img src="https://avatars.githubusercontent.com/u/12711091?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matan Borenkraout</b></sub></a><br /><a href="#maintenance-MatanBobi" title="Maintenance">🚧</a></td>
     <td align="center"><a href="https://github.com/mleimer"><img src="https://avatars.githubusercontent.com/u/14271564?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mleimer</b></sub></a><br /><a href="https://github.com/testing-library/angular-testing-library/commits?author=mleimer" title="Documentation">📖</a> <a href="https://github.com/testing-library/angular-testing-library/commits?author=mleimer" title="Tests">⚠️</a></td>
   </tr>
+  <tr>
+    <td align="center"><a href="https://github.com/meirka"><img src="https://avatars.githubusercontent.com/u/750901?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MeIr</b></sub></a><br /><a href="https://github.com/testing-library/angular-testing-library/issues?q=author%3Ameirka" title="Bug reports">🐛</a> <a href="https://github.com/testing-library/angular-testing-library/commits?author=meirka" title="Tests">⚠️</a></td>
+  </tr>
 </table>
 
 <!-- markdownlint-restore -->
diff --git a/angular.json b/angular.json
index 50afdec9..dfd6bcf1 100644
--- a/angular.json
+++ b/angular.json
@@ -1,296 +1,9 @@
 {
-  "version": 1,
-  "cli": {
-    "analytics": false
-  },
-  "defaultProject": "example-app",
+  "version": 2,
   "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"]
-        }
-      }
-    }
+    "example-app": "apps/example-app",
+    "example-app-karma": "apps/example-app-karma",
+    "jest-utils": "projects/jest-utils",
+    "testing-library": "projects/testing-library"
   }
 }
diff --git a/apps/example-app-karma/src/test.ts b/apps/example-app-karma/src/test.ts
index 0a45adb5..827caf48 100644
--- a/apps/example-app-karma/src/test.ts
+++ b/apps/example-app-karma/src/test.ts
@@ -2,11 +2,7 @@
 import 'zone.js/dist/zone-testing';
 import { getTestBed } from '@angular/core/testing';
 import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
-import JasmineDOM from '@testing-library/jasmine-dom/dist';
-
-beforeAll(() => {
-  (jasmine.getEnv() as any).addMatchers(JasmineDOM);
-});
+import '@testing-library/jasmine-dom';
 
 declare const require: any;
 
diff --git a/apps/example-app/src/app/examples/01-nested-component.ts b/apps/example-app/src/app/examples/01-nested-component.ts
index 5b0faeb2..51087b44 100644
--- a/apps/example-app/src/app/examples/01-nested-component.ts
+++ b/apps/example-app/src/app/examples/01-nested-component.ts
@@ -5,7 +5,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core';
   template: ' <button (click)="raise.emit()">{{ name }}</button> ',
 })
 export class NestedButtonComponent {
-  @Input() name: string;
+  @Input() name = '';
   @Output() raise = new EventEmitter<void>();
 }
 
@@ -14,7 +14,7 @@ export class NestedButtonComponent {
   template: ' <span data-testid="value">{{ value }}</span> ',
 })
 export class NestedValueComponent {
-  @Input() value: number;
+  @Input() value?: number;
 }
 
 @Component({
diff --git a/apps/example-app/src/app/examples/03-forms.spec.ts b/apps/example-app/src/app/examples/03-forms.spec.ts
index 6be38a45..2a53a5f0 100644
--- a/apps/example-app/src/app/examples/03-forms.spec.ts
+++ b/apps/example-app/src/app/examples/03-forms.spec.ts
@@ -23,7 +23,7 @@ test('is possible to fill in a form and verify error messages (with the help of
   userEvent.selectOptions(colorControl, 'G');
 
   expect(screen.queryByText('name is required')).not.toBeInTheDocument();
-  expect(screen.queryByText('score must be lesser than 10')).toBeInTheDocument();
+  expect(screen.getByText('score must be lesser than 10')).toBeInTheDocument();
   expect(screen.queryByText('color is required')).not.toBeInTheDocument();
 
   expect(scoreControl).toBeInvalid();
diff --git a/apps/example-app/src/app/examples/03-forms.ts b/apps/example-app/src/app/examples/03-forms.ts
index bc035a14..f68766e4 100644
--- a/apps/example-app/src/app/examples/03-forms.ts
+++ b/apps/example-app/src/app/examples/03-forms.ts
@@ -1,5 +1,5 @@
 import { Component } from '@angular/core';
-import { FormBuilder, Validators, ValidationErrors } from '@angular/forms';
+import { FormBuilder, Validators } from '@angular/forms';
 
 @Component({
   selector: 'app-fixture',
@@ -46,8 +46,8 @@ export class FormsComponent {
   get formErrors() {
     return Object.keys(this.form.controls)
       .map((formKey) => {
-        const controlErrors: ValidationErrors = this.form.get(formKey).errors;
-        if (controlErrors != null) {
+        const controlErrors = this.form.get(formKey)?.errors;
+        if (controlErrors) {
           return Object.keys(controlErrors).map((keyError) => {
             const error = controlErrors[keyError];
             switch (keyError) {
diff --git a/apps/example-app/src/app/examples/04-forms-with-material.spec.ts b/apps/example-app/src/app/examples/04-forms-with-material.spec.ts
index c215d9c4..6d7e1e18 100644
--- a/apps/example-app/src/app/examples/04-forms-with-material.spec.ts
+++ b/apps/example-app/src/app/examples/04-forms-with-material.spec.ts
@@ -25,7 +25,7 @@ test('is possible to fill in a form and verify error messages (with the help of
   userEvent.click(screen.getByText(/green/i));
 
   expect(screen.queryByText('name is required')).not.toBeInTheDocument();
-  expect(screen.queryByText('score must be lesser than 10')).toBeInTheDocument();
+  expect(screen.getByText('score must be lesser than 10')).toBeInTheDocument();
   expect(screen.queryByText('color is required')).not.toBeInTheDocument();
 
   expect(scoreControl).toBeInvalid();
@@ -37,13 +37,40 @@ test('is possible to fill in a form and verify error messages (with the help of
 
   expect(nameControl).toHaveValue('Tim');
   expect(scoreControl).toHaveValue(7);
+  expect(colorControl).toHaveTextContent('Green');
 
   const form = screen.getByRole('form');
   expect(form).toHaveFormValues({
     name: 'Tim',
     score: 7,
   });
+  expect((fixture.componentInstance as MaterialFormsComponent).form?.get('color')?.value).toBe('G');
+});
+
+test('set and show pre-set form values', async () => {
+  const { fixture, detectChanges } = await render(MaterialFormsComponent, {
+    imports: [MaterialModule],
+  });
+
+  fixture.componentInstance.form.setValue({
+    name: 'Max',
+    score: 4,
+    color: 'B',
+  });
+  detectChanges();
+
+  const nameControl = screen.getByLabelText(/name/i);
+  const scoreControl = screen.getByRole('spinbutton', { name: /score/i });
+  const colorControl = screen.getByRole('combobox', { name: /color/i });
+
+  expect(nameControl).toHaveValue('Max');
+  expect(scoreControl).toHaveValue(4);
+  expect(colorControl).toHaveTextContent('Blue');
 
-  // not added to the form?
-  expect((fixture.componentInstance as MaterialFormsComponent).form.get('color').value).toBe('G');
+  const form = screen.getByRole('form');
+  expect(form).toHaveFormValues({
+    name: 'Max',
+    score: 4,
+  });
+  expect((fixture.componentInstance as MaterialFormsComponent).form?.get('color')?.value).toBe('B');
 });
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 2718e389..f27f4f1e 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
@@ -1,5 +1,5 @@
 import { Component } from '@angular/core';
-import { FormBuilder, Validators, ValidationErrors } from '@angular/forms';
+import { FormBuilder, Validators } from '@angular/forms';
 
 @Component({
   selector: 'app-fixture',
@@ -24,6 +24,9 @@ import { FormBuilder, Validators, ValidationErrors } from '@angular/forms';
 
       <mat-form-field>
         <mat-select placeholder="Color" name="color" formControlName="color">
+          <mat-select-trigger>
+            {{ colorControlDisplayValue }}
+          </mat-select-trigger>
           <mat-option value="">---</mat-option>
           <mat-option *ngFor="let color of colors" [value]="color.id">{{ color.value }}</mat-option>
         </mat-select>
@@ -60,16 +63,21 @@ export class MaterialFormsComponent {
   form = this.formBuilder.group({
     name: ['', Validators.required],
     score: [0, [Validators.min(1), Validators.max(10)]],
-    color: ['', Validators.required],
+    color: [null, Validators.required],
   });
 
   constructor(private formBuilder: FormBuilder) {}
 
+  get colorControlDisplayValue(): string | undefined {
+    const selectedId = this.form.get('color')?.value;
+    return this.colors.filter(color => color.id === selectedId)[0]?.value;
+  }
+
   get formErrors() {
     return Object.keys(this.form.controls)
       .map((formKey) => {
-        const controlErrors: ValidationErrors = this.form.get(formKey).errors;
-        if (controlErrors != null) {
+        const controlErrors = this.form.get(formKey)?.errors;
+        if (controlErrors) {
           return Object.keys(controlErrors).map((keyError) => {
             const error = controlErrors[keyError];
             switch (keyError) {
diff --git a/apps/example-app/src/app/examples/06-with-ngrx-store.ts b/apps/example-app/src/app/examples/06-with-ngrx-store.ts
index f260b978..470f52d9 100644
--- a/apps/example-app/src/app/examples/06-with-ngrx-store.ts
+++ b/apps/example-app/src/app/examples/06-with-ngrx-store.ts
@@ -3,16 +3,12 @@ import { createSelector, Store, createAction, createReducer, on, select } from '
 
 const increment = createAction('increment');
 const decrement = createAction('decrement');
-const counterReducer = createReducer(
+export const reducer = createReducer(
   0,
   on(increment, (state) => state + 1),
   on(decrement, (state) => state - 1),
 );
 
-export function reducer(state, action) {
-  return counterReducer(state, action);
-}
-
 const selectValue = createSelector(
   (state: any) => state.value,
   (value) => value * 10,
diff --git a/apps/example-app/src/app/examples/08-directive.spec.ts b/apps/example-app/src/app/examples/08-directive.spec.ts
index 5df9413a..efd2a5b9 100644
--- a/apps/example-app/src/app/examples/08-directive.spec.ts
+++ b/apps/example-app/src/app/examples/08-directive.spec.ts
@@ -10,14 +10,14 @@ test('it is possible to test directives', async () => {
   const directive = screen.getByTestId('dir');
 
   expect(screen.queryByText('I am visible now...')).not.toBeInTheDocument();
-  expect(screen.queryByText('SPOILER')).toBeInTheDocument();
+  expect(screen.getByText('SPOILER')).toBeInTheDocument();
 
   fireEvent.mouseOver(directive);
   expect(screen.queryByText('SPOILER')).not.toBeInTheDocument();
-  expect(screen.queryByText('I am visible now...')).toBeInTheDocument();
+  expect(screen.getByText('I am visible now...')).toBeInTheDocument();
 
   fireEvent.mouseLeave(directive);
-  expect(screen.queryByText('SPOILER')).toBeInTheDocument();
+  expect(screen.getByText('SPOILER')).toBeInTheDocument();
   expect(screen.queryByText('I am visible now...')).not.toBeInTheDocument();
 });
 
@@ -34,14 +34,14 @@ test('it is possible to test directives with props', async () => {
   });
 
   expect(screen.queryByText(visible)).not.toBeInTheDocument();
-  expect(screen.queryByText(hidden)).toBeInTheDocument();
+  expect(screen.getByText(hidden)).toBeInTheDocument();
 
-  fireEvent.mouseOver(screen.queryByText(hidden));
+  fireEvent.mouseOver(screen.getByText(hidden));
   expect(screen.queryByText(hidden)).not.toBeInTheDocument();
-  expect(screen.queryByText(visible)).toBeInTheDocument();
+  expect(screen.getByText(visible)).toBeInTheDocument();
 
-  fireEvent.mouseLeave(screen.queryByText(visible));
-  expect(screen.queryByText(hidden)).toBeInTheDocument();
+  fireEvent.mouseLeave(screen.getByText(visible));
+  expect(screen.getByText(hidden)).toBeInTheDocument();
   expect(screen.queryByText(visible)).not.toBeInTheDocument();
 });
 
@@ -54,13 +54,13 @@ test('it is possible to test directives with props in template', async () => {
   });
 
   expect(screen.queryByText(visible)).not.toBeInTheDocument();
-  expect(screen.queryByText(hidden)).toBeInTheDocument();
+  expect(screen.getByText(hidden)).toBeInTheDocument();
 
-  fireEvent.mouseOver(screen.queryByText(hidden));
+  fireEvent.mouseOver(screen.getByText(hidden));
   expect(screen.queryByText(hidden)).not.toBeInTheDocument();
-  expect(screen.queryByText(visible)).toBeInTheDocument();
+  expect(screen.getByText(visible)).toBeInTheDocument();
 
-  fireEvent.mouseLeave(screen.queryByText(visible));
-  expect(screen.queryByText(hidden)).toBeInTheDocument();
+  fireEvent.mouseLeave(screen.getByText(visible));
+  expect(screen.getByText(hidden)).toBeInTheDocument();
   expect(screen.queryByText(visible)).not.toBeInTheDocument();
 });
diff --git a/apps/example-app/src/app/examples/09-router.spec.ts b/apps/example-app/src/app/examples/09-router.spec.ts
index cb6743fc..16f037fc 100644
--- a/apps/example-app/src/app/examples/09-router.spec.ts
+++ b/apps/example-app/src/app/examples/09-router.spec.ts
@@ -25,19 +25,19 @@ test('it can navigate to routes', async () => {
   expect(screen.queryByText(/Detail one/i)).not.toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /load one/i }));
-  expect(screen.queryByRole('heading', { name: /Detail one/i })).toBeInTheDocument();
+  expect(screen.getByRole('heading', { name: /Detail one/i })).toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /load three/i }));
   expect(screen.queryByRole('heading', { name: /Detail one/i })).not.toBeInTheDocument();
-  expect(screen.queryByRole('heading', { name: /Detail three/i })).toBeInTheDocument();
+  expect(screen.getByRole('heading', { name: /Detail three/i })).toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /back to parent/i }));
   expect(screen.queryByRole('heading', { name: /Detail three/i })).not.toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /load two/i }));
-  expect(screen.queryByRole('heading', { name: /Detail two/i })).toBeInTheDocument();
+  expect(screen.getByRole('heading', { name: /Detail two/i })).toBeInTheDocument();
   await navigate(screen.getByRole('link', { name: /hidden x/i }));
-  expect(screen.queryByText(/You found the treasure!/i)).toBeInTheDocument();
+  expect(screen.getByText(/You found the treasure!/i)).toBeInTheDocument();
 });
 
 test('it can navigate to routes with a base path', async () => {
@@ -64,20 +64,20 @@ test('it can navigate to routes with a base path', async () => {
   expect(screen.queryByRole('heading', { name: /Detail one/i })).not.toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /load one/i }), basePath);
-  expect(screen.queryByRole('heading', { name: /Detail one/i })).toBeInTheDocument();
+  expect(screen.getByRole('heading', { name: /Detail one/i })).toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /load three/i }), basePath);
   expect(screen.queryByRole('heading', { name: /Detail one/i })).not.toBeInTheDocument();
-  expect(screen.queryByRole('heading', { name: /Detail three/i })).toBeInTheDocument();
+  expect(screen.getByRole('heading', { name: /Detail three/i })).toBeInTheDocument();
 
   await navigate(screen.getByRole('link', { name: /back to parent/i }));
   expect(screen.queryByRole('heading', { name: /Detail three/i })).not.toBeInTheDocument();
 
   // It's possible to just use strings
   await navigate('base/detail/two?text=Hello&subtext=World');
-  expect(screen.queryByRole('heading', { name: /Detail two/i })).toBeInTheDocument();
+  expect(screen.getByRole('heading', { name: /Detail two/i })).toBeInTheDocument();
   expect(screen.getByText(/Hello World/i)).toBeInTheDocument();
 
   await navigate('/hidden-detail', basePath);
-  expect(screen.queryByText(/You found the treasure!/i)).toBeInTheDocument();
+  expect(screen.getByText(/You found the treasure!/i)).toBeInTheDocument();
 });
diff --git a/apps/example-app/src/app/examples/12-service-component.ts b/apps/example-app/src/app/examples/12-service-component.ts
index af35f10a..d272e270 100644
--- a/apps/example-app/src/app/examples/12-service-component.ts
+++ b/apps/example-app/src/app/examples/12-service-component.ts
@@ -2,8 +2,8 @@ import { Component, Injectable } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 export class Customer {
-  id: string;
-  name: string;
+  id!: string;
+  name!: string;
 }
 
 @Injectable({
diff --git a/apps/example-app/src/app/examples/15-dialog.component.spec.ts b/apps/example-app/src/app/examples/15-dialog.component.spec.ts
index f0fbd465..31cf2fba 100644
--- a/apps/example-app/src/app/examples/15-dialog.component.spec.ts
+++ b/apps/example-app/src/app/examples/15-dialog.component.spec.ts
@@ -32,15 +32,17 @@ test('closes the dialog via the backdrop', async () => {
   const openDialogButton = await screen.findByRole('button', { name: /open dialog/i });
   userEvent.click(openDialogButton);
 
-  await screen.findByRole('dialog');
-  await screen.findByRole('heading', { name: /dialog title/i });
+  const dialogControl = await screen.findByRole('dialog');
+  expect(dialogControl).toBeInTheDocument();
+  const dialogTitleControl = await screen.findByRole('heading', { name: /dialog title/i });
+  expect(dialogTitleControl).toBeInTheDocument();
 
   // using fireEvent because of:
   // unable to click element as it has or inherits pointer-events set to "none"
-  // eslint-disable-next-line testing-library/no-node-access
-  fireEvent.click(document.querySelector('.cdk-overlay-backdrop'));
+  // eslint-disable-next-line testing-library/no-node-access, @typescript-eslint/no-non-null-assertion
+  fireEvent.click(document.querySelector('.cdk-overlay-backdrop')!);
 
-  await waitForElementToBeRemoved(() => screen.getByRole('dialog'));
+  await waitForElementToBeRemoved(() => screen.queryByRole('dialog'));
 
   const dialogTitle = screen.queryByRole('heading', { name: /dialog title/i });
   expect(dialogTitle).not.toBeInTheDocument();
@@ -54,13 +56,15 @@ test('opens and closes the dialog with buttons', async () => {
   const openDialogButton = await screen.findByRole('button', { name: /open dialog/i });
   userEvent.click(openDialogButton);
 
-  await screen.findByRole('dialog');
-  await screen.findByRole('heading', { name: /dialog title/i });
+  const dialogControl = await screen.findByRole('dialog');
+  expect(dialogControl).toBeInTheDocument();
+  const dialogTitleControl = await screen.findByRole('heading', { name: /dialog title/i });
+  expect(dialogTitleControl).toBeInTheDocument();
 
   const cancelButton = await screen.findByRole('button', { name: /cancel/i });
   userEvent.click(cancelButton);
 
-  await waitForElementToBeRemoved(() => screen.getByRole('dialog'));
+  await waitForElementToBeRemoved(() => screen.queryByRole('dialog'));
 
   const dialogTitle = screen.queryByRole('heading', { name: /dialog title/i });
   expect(dialogTitle).not.toBeInTheDocument();
diff --git a/apps/example-app/src/app/examples/16-input-getter-setter.ts b/apps/example-app/src/app/examples/16-input-getter-setter.ts
index 11f8c949..22d9641a 100644
--- a/apps/example-app/src/app/examples/16-input-getter-setter.ts
+++ b/apps/example-app/src/app/examples/16-input-getter-setter.ts
@@ -18,6 +18,6 @@ export class InputGetterSetter {
     return 'I am value from getter ' + this.originalValue;
   }
 
-  private originalValue: string;
-  derivedValue: string;
+  private originalValue?: string;
+  derivedValue?: string;
 }
diff --git a/apps/example-app/src/app/examples/18-html-as-input.spec.ts b/apps/example-app/src/app/examples/18-html-as-input.spec.ts
new file mode 100644
index 00000000..5a56b412
--- /dev/null
+++ b/apps/example-app/src/app/examples/18-html-as-input.spec.ts
@@ -0,0 +1,36 @@
+import { render, screen } from '@testing-library/angular';
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+  name: 'stripHTML',
+})
+class StripHTMLPipe implements PipeTransform {
+  transform(stringValueWithHTML: string): string {
+    return stringValueWithHTML.replace(/<[^>]*>?/gm, '');
+  }
+}
+
+const STRING_WITH_HTML =
+  'Some <em>database</em> <b>field</b> <div><span>with <strong>stripped</strong> HTML</span></div>';
+
+// https://github.com/testing-library/angular-testing-library/pull/271
+test('passes HTML as component properties', async () => {
+  await render(`<p>{{ stringWithHtml | stripHTML }}</p>`, {
+    componentProperties: {
+      stringWithHtml: STRING_WITH_HTML,
+    },
+    declarations: [StripHTMLPipe],
+  });
+
+  expect(screen.getByText('Some database field with stripped HTML')).toBeInTheDocument();
+});
+
+
+test('throws when passed HTML is passed in directly', async () => {
+  await expect(() =>
+    render(`<p data-testid="test"> {{ '${STRING_WITH_HTML}' | stripHTML }} </p>`, {
+      declarations: [StripHTMLPipe],
+    }),
+  ).rejects.toThrow();
+});
+
diff --git a/apps/example-app/src/app/issues/issue-106.spec.ts b/apps/example-app/src/app/issues/issue-106.spec.ts
index b1f6cc2c..56097a83 100644
--- a/apps/example-app/src/app/issues/issue-106.spec.ts
+++ b/apps/example-app/src/app/issues/issue-106.spec.ts
@@ -1,6 +1,7 @@
 import { Component } from '@angular/core';
 import { BehaviorSubject } from 'rxjs';
-import { render, screen, fireEvent, waitFor } from '@testing-library/angular';
+import { render, screen, fireEvent } from '@testing-library/angular';
+import { waitFor } from '@testing-library/dom';
 
 @Component({
   template: `<button (click)="toggleShow()" data-testid="toggle">toggle</button>
@@ -27,6 +28,9 @@ test('https://github.com/testing-library/angular-testing-library/issues/106', as
   // await waitFor(() => expect(hiddenText).not.toBeNull());
 
   // succeeds
+  /// Next line is disabled, because we wish to test the behavior of the library and test the bug/issue #106
+  /// @see https://github.com/testing-library/angular-testing-library/pull/277/files#r779743116
+  // eslint-disable-next-line testing-library/prefer-presence-queries, testing-library/prefer-find-by
   await waitFor(() => expect(screen.queryByTestId('getme')).toBeInTheDocument());
 });
 
diff --git a/apps/example-app/src/app/issues/issue-254.spec.ts b/apps/example-app/src/app/issues/issue-254.spec.ts
index 01960b4f..917f35de 100644
--- a/apps/example-app/src/app/issues/issue-254.spec.ts
+++ b/apps/example-app/src/app/issues/issue-254.spec.ts
@@ -1,12 +1,11 @@
-/* eslint-disable @typescript-eslint/naming-convention */
 import { Component, Inject, OnInit } from '@angular/core';
 import { render, screen } from '@testing-library/angular';
 import { createMock } from '@testing-library/angular/jest-utils';
 
 interface Division {
-  JobType: string;
-  JobBullets: string[];
-  Description: string;
+  jobType?: string;
+  jobBullets?: string[];
+  description?: string;
 }
 
 @Inject({
@@ -21,25 +20,25 @@ class JobsService {
 @Component({
   selector: 'app-home-career-oportunities',
   template: ` <ul class="popu-category-bullets">
-    <li class="text-dark" *ngFor="let bullet of dedicated.JobBullets">
+    <li class="text-dark" *ngFor="let bullet of dedicated?.jobBullets">
       {{ bullet }}
     </li>
   </ul>`,
 })
 class CareerOportunitiesComponent implements OnInit {
-  dedicated = {} as Division;
-  intermodal = {} as Division;
-  noCdl = {} as Division;
-  otr = {} as Division;
+  dedicated: Division | undefined;
+  intermodal: Division | undefined;
+  noCdl: Division | undefined;
+  otr: Division | undefined;
 
   constructor(private jobsService: JobsService) {}
 
   ngOnInit(): void {
     this.jobsService.divisions().then((apiDivisions) => {
-      this.dedicated = apiDivisions.find((c) => c.JobType === 'DEDICATED');
-      this.intermodal = apiDivisions.find((c) => c.JobType === 'INTERMODAL');
-      this.noCdl = apiDivisions.find((c) => c.JobType === 'NO_CDL');
-      this.otr = apiDivisions.find((c) => c.JobType === 'OVER_THE_ROAD');
+      this.dedicated = apiDivisions.find((c) => c.jobType === 'DEDICATED');
+      this.intermodal = apiDivisions.find((c) => c.jobType === 'INTERMODAL');
+      this.noCdl = apiDivisions.find((c) => c.jobType === 'NO_CDL');
+      this.otr = apiDivisions.find((c) => c.jobType === 'OVER_THE_ROAD');
     });
   }
 }
@@ -47,20 +46,20 @@ class CareerOportunitiesComponent implements OnInit {
 test('Render Component', async () => {
   const divisions2: Division[] = [
     {
-      JobType: 'INTERMODAL',
-      JobBullets: ['Local Routes', 'Flexible Schedules', 'Competitive Pay'],
-      Description: '',
+      jobType: 'INTERMODAL',
+      jobBullets: ['Local Routes', 'Flexible Schedules', 'Competitive Pay'],
+      description: '',
     },
-    { JobType: 'NO_CDL', JobBullets: ['We Train', 'We Hire', 'We Pay'], Description: '' },
+    { jobType: 'NO_CDL', jobBullets: ['We Train', 'We Hire', 'We Pay'], description: '' },
     {
-      JobType: 'OVER_THE_ROAD',
-      JobBullets: ['Great Miles', 'Competitive Pay', 'Explore the Country'],
-      Description: '',
+      jobType: 'OVER_THE_ROAD',
+      jobBullets: ['Great Miles', 'Competitive Pay', 'Explore the Country'],
+      description: '',
     },
     {
-      JobType: 'DEDICATED',
-      JobBullets: ['Regular Routes', 'Consistent Miles', 'Great Pay'],
-      Description: '',
+      jobType: 'DEDICATED',
+      jobBullets: ['Regular Routes', 'Consistent Miles', 'Great Pay'],
+      description: '',
     },
   ];
   const jobService = createMock(JobsService);
@@ -74,5 +73,6 @@ test('Render Component', async () => {
       },
     ],
   });
-  await screen.findAllByRole('listitem');
+  const listItemControl = await screen.findAllByRole('listitem');
+  expect(listItemControl).toHaveLength(3);
 });
diff --git a/apps/example-app/tsconfig.app.json b/apps/example-app/tsconfig.app.json
index 4de7101b..a009fad9 100644
--- a/apps/example-app/tsconfig.app.json
+++ b/apps/example-app/tsconfig.app.json
@@ -3,7 +3,8 @@
   "compilerOptions": {
     "outDir": "../../dist/out-tsc",
     "types": [],
-    "allowJs": true
+    "allowJs": true,
+    "target": "ES2017"
   },
   "files": ["src/main.ts", "src/polyfills.ts"],
   "include": ["src/**/*.d.ts"],
diff --git a/lint-staged.config.js b/lint-staged.config.js
index a10d3ccf..00ee30fd 100644
--- a/lint-staged.config.js
+++ b/lint-staged.config.js
@@ -1,4 +1,4 @@
 module.exports = {
-  '*.{ts,js}': ['eslint --fix', 'git add'],
-  '*.{json,md}': ['prettier --write', 'git add'],
+  '*.{ts,js}': ['eslint --fix'],
+  '*.{ts,js,json,md}': ['prettier --write'],
 };
diff --git a/package.json b/package.json
index 3c7c74ec..977d7a88 100644
--- a/package.json
+++ b/package.json
@@ -25,78 +25,77 @@
     "format:check": "nx format:check",
     "pre-commit": "lint-staged",
     "semantic-release": "semantic-release",
-    "prepare": "husky install"
+    "prepare": "git config core.hookspath .githooks"
   },
   "dependencies": {
-    "@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",
+    "@angular/animations": "13.1.1",
+    "@angular/cdk": "13.1.1",
+    "@angular/common": "13.1.1",
+    "@angular/compiler": "13.1.1",
+    "@angular/core": "13.1.1",
+    "@angular/material": "13.1.1",
+    "@angular/platform-browser": "13.1.1",
+    "@angular/platform-browser-dynamic": "13.1.1",
+    "@angular/router": "13.1.1",
+    "@ngrx/store": "13.0.2",
+    "@nrwl/angular": "13.4.3",
+    "@nrwl/nx-cloud": "13.0.2",
     "@testing-library/dom": "^8.11.1",
-    "@testing-library/user-event": "^13.5.0",
-    "rxjs": "^7.4.0",
+    "rxjs": "^7.5.1",
     "tslib": "~2.3.1",
     "zone.js": "~0.11.4"
   },
   "devDependencies": {
-    "@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",
+    "@angular-devkit/build-angular": "13.1.2",
+    "@angular-eslint/eslint-plugin": "13.0.1",
+    "@angular-eslint/eslint-plugin-template": "13.0.1",
+    "@angular-eslint/template-parser": "13.0.1",
+    "@angular/cli": "13.1.2",
+    "@angular/compiler-cli": "13.1.1",
+    "@angular/forms": "13.1.1",
+    "@angular/language-service": "13.1.1",
+    "@nrwl/cli": "13.4.3",
+    "@nrwl/eslint-plugin-nx": "13.4.3",
+    "@nrwl/jest": "13.4.3",
+    "@nrwl/linter": "13.4.3",
+    "@nrwl/node": "13.4.3",
+    "@nrwl/nx-plugin": "13.4.3",
+    "@nrwl/workspace": "13.4.3",
     "@testing-library/jasmine-dom": "^1.2.0",
     "@testing-library/jest-dom": "^5.15.1",
+    "@testing-library/user-event": "^13.5.0",
     "@types/jasmine": "^3.10.2",
-    "@types/jest": "27.0.3",
+    "@types/jest": "27.4.0",
     "@types/node": "14.14.37",
-    "@typescript-eslint/eslint-plugin": "4.33.0",
-    "@typescript-eslint/parser": "4.33.0",
+    "@typescript-eslint/eslint-plugin": "~5.3.0",
+    "@typescript-eslint/parser": "~5.3.0",
     "cpy-cli": "^3.1.1",
-    "eslint": "7.32.0",
+    "eslint": "~8.6.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": "^7.0.0",
+    "eslint-plugin-import": "~2.25.4",
+    "eslint-plugin-jasmine": "~4.1.3",
+    "eslint-plugin-jest": "~25.3.4",
+    "eslint-plugin-jest-dom": "~4.0.1",
+    "eslint-plugin-testing-library": "~5.0.1",
     "jasmine-core": "^3.10.1",
     "jasmine-spec-reporter": "^7.0.0",
-    "jest": "27.3.1",
+    "jest": "27.4.7",
     "jest-preset-angular": "11.0.1",
     "karma": "^6.3.9",
     "karma-chrome-launcher": "^3.1.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",
+    "lint-staged": "^12.1.6",
+    "ng-packagr": "13.1.2",
+    "postcss": "^8.4.5",
     "postcss-import": "^14.0.2",
-    "postcss-preset-env": "^7.0.1",
+    "postcss-preset-env": "^7.2.0",
     "postcss-url": "^10.1.3",
     "prettier": "^2.4.1",
     "rimraf": "^3.0.2",
     "semantic-release": "^18.0.0",
-    "ts-jest": "27.0.7",
+    "ts-jest": "27.1.2",
     "ts-node": "~10.4.0",
-    "typescript": "4.4.4"
+    "typescript": "4.5.4"
   }
 }
diff --git a/projects/jest-utils/tsconfig.json b/projects/jest-utils/tsconfig.json
index fd77caf1..24663f6f 100644
--- a/projects/jest-utils/tsconfig.json
+++ b/projects/jest-utils/tsconfig.json
@@ -6,13 +6,15 @@
     {
       "path": "./tsconfig.lib.json"
     },
+    {
+      "path": "./tsconfig.lib.prod.json"
+    },
     {
       "path": "./tsconfig.spec.json"
     }
   ],
   "compilerOptions": {},
   "angularCompilerOptions": {
-    "compilationMode": "partial",
     "strictInjectionParameters": true,
     "strictInputAccessModifiers": true,
     "strictTemplates": true,
diff --git a/projects/jest-utils/tsconfig.lib.json b/projects/jest-utils/tsconfig.lib.json
index 22fef254..0566ff84 100644
--- a/projects/jest-utils/tsconfig.lib.json
+++ b/projects/jest-utils/tsconfig.lib.json
@@ -1,11 +1,12 @@
 {
   "extends": "./tsconfig.json",
   "compilerOptions": {
-    "outDir": "../../out-tsc/lib",
+    "outDir": "../../dist/out-tsc",
     "declaration": true,
     "declarationMap": true,
     "inlineSources": true,
     "types": ["jest"]
   },
-  "exclude": ["src/test.ts", "**/*.spec.ts", "**/*.test.ts"]
+  "exclude": ["src/test.ts", "**/*.spec.ts", "**/*.test.ts"],
+  "include": ["**/*.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/testing-library/.eslintrc.json b/projects/testing-library/.eslintrc.json
index 4089aa79..918e7859 100644
--- a/projects/testing-library/.eslintrc.json
+++ b/projects/testing-library/.eslintrc.json
@@ -2,6 +2,12 @@
   "extends": "../../.eslintrc.json",
   "ignorePatterns": ["!**/*"],
   "overrides": [
+    {
+      "files": ["*.ts"],
+      "rules": {
+        "@typescript-eslint/ban-ts-comment": "off"
+      }
+    },
     {
       "files": ["*.ts"],
       "extends": ["plugin:@nrwl/nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
@@ -9,6 +15,7 @@
         "project": ["projects/testing-library/tsconfig.*?.json"]
       },
       "rules": {
+        "@typescript-eslint/ban-ts-comment": "off",
         "@angular-eslint/directive-selector": [
           "error",
           {
diff --git a/projects/testing-library/package.json b/projects/testing-library/package.json
index e41389cf..7d14c654 100644
--- a/projects/testing-library/package.json
+++ b/projects/testing-library/package.json
@@ -31,13 +31,13 @@
   "peerDependencies": {
     "@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"
+    "@angular/core": ">= 13.0.0",
+    "rxjs": ">= 7.4.0"
   },
   "dependencies": {
     "@testing-library/dom": "^8.0.0",
-    "tslib": "^2.0.0"
+    "tslib": "^2.3.1"
   },
   "publishConfig": {
     "access": "public"
diff --git a/projects/testing-library/project.json b/projects/testing-library/project.json
index fe6d0834..1caa86ee 100644
--- a/projects/testing-library/project.json
+++ b/projects/testing-library/project.json
@@ -23,11 +23,7 @@
     "lint": {
       "executor": "@nrwl/linter:eslint",
       "options": {
-        "lintFilePatterns": [
-          "projects/testing-library/**/*.ts",
-          "projects/testing-library/**/*.html",
-          "projects/testing-library/src/**/*.html"
-        ]
+        "lintFilePatterns": ["projects/testing-library/**/*.ts", "projects/testing-library/**/*.html"]
       },
       "outputs": ["{options.outputFile}"]
     },
diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts
index 7f5a02a7..7799c3ce 100644
--- a/projects/testing-library/src/lib/models.ts
+++ b/projects/testing-library/src/lib/models.ts
@@ -20,7 +20,7 @@ export interface RenderResult<ComponentType, WrapperType = ComponentType> extend
    * element: The to be printed HTML element, if not provided it will log the whole component's DOM
    */
   debug: (
-    element?: Element | HTMLDocument | (Element | HTMLDocument)[],
+    element?: Element | Document | (Element | Document)[],
     maxLength?: number,
     options?: PrettyDOMOptions,
   ) => void;
@@ -268,8 +268,8 @@ export interface RenderTemplateOptions<WrapperType, Properties extends object =
    * `WrapperComponent`, an empty component that strips the `ng-version` attribute
    *
    * @example
-   * const component = await render(SpoilerDirective, {
-   *  template: `<div spoiler message='SPOILER'></div>`
+   * const component = await render(`<div spoiler message='SPOILER'></div>`, {
+   *  declarations: [SpoilerDirective]
    *  wrapper: CustomWrapperComponent
    * })
    */
diff --git a/projects/testing-library/src/lib/testing-library.ts b/projects/testing-library/src/lib/testing-library.ts
index 1a517aa2..8a6ad6a7 100644
--- a/projects/testing-library/src/lib/testing-library.ts
+++ b/projects/testing-library/src/lib/testing-library.ts
@@ -22,10 +22,9 @@ import {
   within as dtlWithin,
   waitForOptions as dtlWaitForOptions,
   configure as dtlConfigure,
-  Queries,
-  getQueriesForElement,
   queries as dtlQueries,
 } from '@testing-library/dom';
+import type { Queries, BoundFunctions } from '@testing-library/dom';
 import { RenderComponentOptions, RenderTemplateOptions, RenderResult } from './models';
 import { getConfig } from './config';
 
@@ -53,12 +52,11 @@ export async function render<SutType, WrapperType = SutType>(
     providers = [],
     schemas = [],
     queries,
-    template = undefined,
-    wrapper = WrapperComponent,
+    wrapper = WrapperComponent as Type<WrapperType>,
     componentProperties = {},
     componentProviders = [],
     excludeComponentDeclaration = false,
-    routes,
+    routes = [],
     removeAngularAttributes = false,
     defaultImports = [],
   } = { ...globalConfig, ...renderOptions };
@@ -89,13 +87,13 @@ export async function render<SutType, WrapperType = SutType>(
   await TestBed.compileComponents();
 
   componentProviders
-    .reduce((acc, provider) => acc.concat(provider), [])
-    .forEach((p) => {
+    .reduce((acc, provider) => acc.concat(provider), [] as any[])
+    .forEach((p: any) => {
       const { provide, ...provider } = p;
       TestBed.overrideProvider(provide, provider);
     });
 
-  const componentContainer = createComponentFixture(sut, { wrapper });
+  const componentContainer = createComponentFixture(sut, wrapper);
 
   let fixture: ComponentFixture<SutType>;
   let detectChanges: () => void;
@@ -118,13 +116,12 @@ export async function render<SutType, WrapperType = SutType>(
     fixture.componentRef.injector.get(ChangeDetectorRef).detectChanges();
   };
 
-  let router = routes ? inject(Router) : null;
   const zone = inject(NgZone);
-  const navigate = async (elementOrPath: Element | string, basePath = '') => {
-    if (!router) {
-      router = inject(Router);
-    }
 
+  const router = inject(Router);
+  router?.initialNavigation();
+
+  const navigate = async (elementOrPath: Element | string, basePath = ''): Promise<boolean> => {
     const href = typeof elementOrPath === 'string' ? elementOrPath : elementOrPath.getAttribute('href');
     const [path, params] = (basePath + href).split('?');
     const queryParams = params
@@ -139,16 +136,18 @@ export async function render<SutType, WrapperType = SutType>(
             qp[key] = [currentValue, value];
           }
           return qp;
-        }, {})
+        }, {} as Record<string, string | string[]>)
       : undefined;
 
-    const navigateOptions: NavigationExtras = queryParams
+    const navigateOptions: NavigationExtras | undefined = queryParams
       ? {
           queryParams,
         }
       : undefined;
 
-    const doNavigate = () => (navigateOptions ? router.navigate([path], navigateOptions) : router.navigate([path]));
+    const doNavigate = () => {
+      return navigateOptions ? router?.navigate([path], navigateOptions) : router?.navigate([path]);
+    };
 
     let result;
 
@@ -159,21 +158,25 @@ export async function render<SutType, WrapperType = SutType>(
     }
 
     detectChanges();
-    return result;
+    return result ?? false;
   };
 
   return {
+    // @ts-ignore: fixture assigned
     fixture,
     detectChanges: () => detectChanges(),
     navigate,
     rerender,
     change,
+    // @ts-ignore: fixture assigned
     debugElement: typeof sut === 'string' ? fixture.debugElement : fixture.debugElement.query(By.directive(sut)),
+    // @ts-ignore: fixture assigned
     container: fixture.nativeElement,
     debug: (element = fixture.nativeElement, maxLength, options) =>
       Array.isArray(element)
         ? element.forEach((e) => console.log(dtlPrettyDOM(e, maxLength, options)))
         : console.log(dtlPrettyDOM(element, maxLength, options)),
+    // @ts-ignore: fixture assigned
     ...replaceFindWithFindAndDetectChanges(dtlGetQueriesForElement(fixture.nativeElement, queries)),
   };
 
@@ -220,9 +223,9 @@ async function createComponent<SutType>(component: Type<SutType>): Promise<Compo
   return TestBed.createComponent(component);
 }
 
-function createComponentFixture<SutType>(
+function createComponentFixture<SutType, WrapperType>(
   sut: Type<SutType> | string,
-  { wrapper }: Pick<RenderTemplateOptions<SutType>, 'wrapper'>,
+  wrapper: Type<WrapperType>,
 ): Type<any> {
   if (typeof sut === 'string') {
     TestBed.overrideTemplate(wrapper, sut);
@@ -236,13 +239,10 @@ function setComponentProperties<SutType>(
   { componentProperties = {} }: Pick<RenderTemplateOptions<SutType, any>, 'componentProperties'>,
 ) {
   for (const key of Object.keys(componentProperties)) {
-    const descriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(
-      fixture.componentInstance.constructor.prototype,
-      key,
-    );
+    const descriptor = Object.getOwnPropertyDescriptor((fixture.componentInstance as any).constructor.prototype, key);
     let _value = componentProperties[key];
     const defaultGetter = () => _value;
-    const extendedSetter = (value) => {
+    const extendedSetter = (value: any) => {
       _value = value;
       descriptor?.set?.call(fixture.componentInstance, _value);
       fixture.detectChanges();
@@ -268,21 +268,24 @@ function hasOnChangesHook<SutType>(componentInstance: SutType): componentInstanc
   );
 }
 
-function getChangesObj<SutType>(oldProps: Partial<SutType> | null, newProps: Partial<SutType>) {
+function getChangesObj<SutType extends Record<string, any>>(
+  oldProps: Partial<SutType> | null,
+  newProps: Partial<SutType>,
+) {
   const isFirstChange = oldProps === null;
   return Object.keys(newProps).reduce<SimpleChanges>(
     (changes, key) => ({
       ...changes,
       [key]: new SimpleChange(isFirstChange ? null : oldProps[key], newProps[key], isFirstChange),
     }),
-    {},
+    {} as SutType,
   );
 }
 
 function addAutoDeclarations<SutType>(
   sut: Type<SutType> | string,
   {
-    declarations,
+    declarations = [],
     excludeComponentDeclaration,
     wrapper,
   }: Pick<RenderTemplateOptions<any>, 'declarations' | 'excludeComponentDeclaration' | 'wrapper'>,
@@ -295,7 +298,7 @@ function addAutoDeclarations<SutType>(
   return [...declarations, ...components()];
 }
 
-function addAutoImports({ imports, routes }: Pick<RenderComponentOptions<any>, 'imports' | 'routes'>) {
+function addAutoImports({ imports = [], routes }: Pick<RenderComponentOptions<any>, 'imports' | 'routes'>) {
   const animations = () => {
     const animationIsDefined =
       imports.indexOf(NoopAnimationsModule) > -1 || imports.indexOf(BrowserAnimationsModule) > -1;
@@ -341,19 +344,19 @@ async function waitForElementToBeRemovedWrapper<T>(
   callback: (() => T) | T,
   options?: dtlWaitForOptions,
 ): Promise<void> {
-  let cb;
+  let cb: () => T;
   if (typeof callback !== 'function') {
     const elements = (Array.isArray(callback) ? callback : [callback]) as Element[];
     const getRemainingElements = elements.map((element) => {
-      let parent = element.parentElement;
+      let parent = element.parentElement as Element;
       while (parent.parentElement) {
         parent = parent.parentElement;
       }
       return () => (parent.contains(element) ? element : null);
     });
-    cb = () => getRemainingElements.map((c) => c()).filter(Boolean);
+    cb = () => getRemainingElements.map((c) => c()).find(Boolean) as unknown as T;
   } else {
-    cb = callback;
+    cb = callback as () => T;
   }
 
   return await dtlWaitForElementToBeRemoved(() => {
@@ -367,7 +370,7 @@ function cleanup() {
   mountedFixtures.forEach(cleanupAtFixture);
 }
 
-function cleanupAtFixture(fixture) {
+function cleanupAtFixture(fixture: ComponentFixture<any>) {
   fixture.destroy();
 
   if (!fixture.nativeElement.getAttribute('ng-version') && fixture.nativeElement.parentNode === document.body) {
@@ -394,25 +397,21 @@ class WrapperComponent {}
 /**
  * Wrap findBy queries to poke the Angular change detection cycle
  */
-function replaceFindWithFindAndDetectChanges<T>(originalQueriesForContainer: T): T {
+function replaceFindWithFindAndDetectChanges<T extends Record<string, any>>(originalQueriesForContainer: T): T {
   return Object.keys(originalQueriesForContainer).reduce((newQueries, key) => {
     const getByQuery = originalQueriesForContainer[key.replace('find', 'get')];
     if (key.startsWith('find') && getByQuery) {
-      newQueries[key] = async (text, options, waitOptions) => {
+      newQueries[key] = async (...queryOptions: any[]) => {
+        const waitOptions = queryOptions.length === 3 ? queryOptions.pop() : undefined;
         // original implementation at https://github.com/testing-library/dom-testing-library/blob/main/src/query-helpers.js
-        const result = await waitForWrapper(
-          detectChangesForMountedFixtures,
-          () => getByQuery(text, options),
-          waitOptions,
-        );
-        return result;
+        return await waitForWrapper(detectChangesForMountedFixtures, () => getByQuery(...queryOptions), waitOptions);
       };
     } else {
       newQueries[key] = originalQueriesForContainer[key];
     }
 
     return newQueries;
-  }, {} as T);
+  }, {} as Record<string, any>) as T;
 }
 
 /**
@@ -422,7 +421,7 @@ function detectChangesForMountedFixtures() {
   mountedFixtures.forEach((fixture) => {
     try {
       fixture.detectChanges();
-    } catch (err) {
+    } catch (err: any) {
       if (!err.message.startsWith('ViewDestroyedError')) {
         throw err;
       }
@@ -438,12 +437,11 @@ const screen = replaceFindWithFindAndDetectChanges(dtlScreen);
 /**
  * Re-export within with patched queries
  */
-
-const within: typeof getQueriesForElement = <T extends Queries = typeof dtlQueries>(
+const within = <QueriesToBind extends Queries = typeof dtlQueries, T extends QueriesToBind = QueriesToBind>(
   element: HTMLElement,
   queriesToBind?: T,
-) => {
-  const container = dtlWithin(element, queriesToBind);
+): BoundFunctions<T> => {
+  const container = dtlWithin<T>(element, queriesToBind);
   return replaceFindWithFindAndDetectChanges(container);
 };
 
diff --git a/projects/testing-library/tests/auto-cleanup.spec.ts b/projects/testing-library/tests/auto-cleanup.spec.ts
index c69eda62..1e37f242 100644
--- a/projects/testing-library/tests/auto-cleanup.spec.ts
+++ b/projects/testing-library/tests/auto-cleanup.spec.ts
@@ -6,7 +6,7 @@ import { render } from '../src/public_api';
   template: `Hello {{ name }}!`,
 })
 class FixtureComponent {
-  @Input() name: string;
+  @Input() name = '';
 }
 
 describe('Angular auto clean up - previous components only get cleanup up on init (based on root-id)', () => {
diff --git a/projects/testing-library/tests/change.spec.ts b/projects/testing-library/tests/change.spec.ts
index 85cc3667..1ba67513 100644
--- a/projects/testing-library/tests/change.spec.ts
+++ b/projects/testing-library/tests/change.spec.ts
@@ -7,7 +7,7 @@ import { render, screen } from '../src/public_api';
 })
 class FixtureComponent {
   @Input() firstName = 'Sarah';
-  @Input() lastName;
+  @Input() lastName?: string;
 }
 
 test('changes the component with updated props', async () => {
@@ -44,7 +44,7 @@ test('changes the component with updated props while keeping other props untouch
 })
 class FixtureWithNgOnChangesComponent implements OnChanges {
   @Input() name = 'Sarah';
-  @Input() nameChanged: (name: string, isFirstChange: boolean) => void;
+  @Input() nameChanged?: (name: string, isFirstChange: boolean) => void;
 
   ngOnChanges(changes: SimpleChanges) {
     if (changes.name && this.nameChanged) {
@@ -72,7 +72,7 @@ test('will call ngOnChanges on change', async () => {
   template: ` <div data-testid="number" [class.active]="activeField === 'number'">Number</div> `,
 })
 class FixtureWithOnPushComponent {
-  @Input() activeField: string;
+  @Input() activeField = '';
 }
 
 test('update properties on change', async () => {
diff --git a/projects/testing-library/tests/config.spec.ts b/projects/testing-library/tests/config.spec.ts
index ccd004f5..bb8c61fc 100644
--- a/projects/testing-library/tests/config.spec.ts
+++ b/projects/testing-library/tests/config.spec.ts
@@ -1,6 +1,6 @@
 import { Component } from '@angular/core';
 import { TestBed } from '@angular/core/testing';
-import { render, configure } from '../src/public_api';
+import { render, configure, Config } from '../src/public_api';
 import { ReactiveFormsModule, FormBuilder } from '@angular/forms';
 
 @Component({
@@ -22,12 +22,12 @@ class FormsComponent {
   constructor(private formBuilder: FormBuilder) {}
 }
 
-let originalConfig;
+let originalConfig: Config;
 beforeEach(() => {
   // Grab the existing configuration so we can restore
   // it at the end of the test
   configure((existingConfig) => {
-    originalConfig = existingConfig;
+    originalConfig = existingConfig as Config;
     // Don't change the existing config
     return {};
   });
diff --git a/projects/testing-library/tests/integration.spec.ts b/projects/testing-library/tests/integration.spec.ts
index afd56698..112177e1 100644
--- a/projects/testing-library/tests/integration.spec.ts
+++ b/projects/testing-library/tests/integration.spec.ts
@@ -36,7 +36,9 @@ class EntitiesComponent {
   query = new BehaviorSubject<string>('');
   readonly entities = this.query.pipe(
     debounceTime(DEBOUNCE_TIME),
-    switchMap((q) => this.entitiesService.fetchAll().pipe(map((ent) => ent.filter((e) => e.name.includes(q))))),
+    switchMap((q) =>
+      this.entitiesService.fetchAll().pipe(map((ent: any) => ent.filter((e: any) => e.name.includes(q)))),
+    ),
     startWith(entities),
   );
 
@@ -65,7 +67,7 @@ class EntitiesComponent {
   `,
 })
 class TableComponent {
-  @Input() entities: any[];
+  @Input() entities: any[] = [];
   @Output() edit = new EventEmitter<string>();
 }
 
diff --git a/projects/testing-library/tests/issues/issue-188.spec.ts b/projects/testing-library/tests/issues/issue-188.spec.ts
index 8077358a..b150dacc 100644
--- a/projects/testing-library/tests/issues/issue-188.spec.ts
+++ b/projects/testing-library/tests/issues/issue-188.spec.ts
@@ -6,9 +6,9 @@ import { render, screen } from '../../src/public_api';
   template: `<h1>Hello {{ formattedName }}</h1>`,
 })
 class BugOnChangeComponent implements OnChanges {
-  @Input() name: string;
+  @Input() name?: string;
 
-  formattedName: string;
+  formattedName?: string;
 
   ngOnChanges(changes: SimpleChanges) {
     if (changes.name) {
diff --git a/projects/testing-library/tests/issues/issue-280.spec.ts b/projects/testing-library/tests/issues/issue-280.spec.ts
new file mode 100644
index 00000000..19f644ef
--- /dev/null
+++ b/projects/testing-library/tests/issues/issue-280.spec.ts
@@ -0,0 +1,58 @@
+import { Location } from '@angular/common';
+import { Component, NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import userEvent from '@testing-library/user-event';
+import { render, screen } from '../../src/public_api';
+
+@Component({
+  template: `<div>Navigate</div>
+    <router-outlet></router-outlet>`,
+})
+class MainComponent {}
+
+@Component({
+  template: `<div>first page</div>
+    <a routerLink="/second">go to second</a>`,
+})
+class FirstComponent {}
+
+@Component({
+  template: `<div>second page</div>
+    <button (click)="goBack()">navigate back</button>`,
+})
+class SecondComponent {
+  constructor(private location: Location) {}
+  goBack() {
+    this.location.back();
+  }
+}
+
+const routes: Routes = [
+  { path: '', redirectTo: '/first', pathMatch: 'full' },
+  { path: 'first', component: FirstComponent },
+  { path: 'second', component: SecondComponent },
+];
+
+@NgModule({
+  declarations: [FirstComponent, SecondComponent],
+  imports: [RouterModule.forRoot(routes)],
+  exports: [RouterModule],
+})
+class AppRoutingModule {}
+
+test('navigate to second page and back', async () => {
+  await render(MainComponent, { imports: [AppRoutingModule, RouterTestingModule] });
+
+  expect(await screen.findByText('Navigate')).toBeInTheDocument();
+  expect(await screen.findByText('first page')).toBeInTheDocument();
+
+  userEvent.click(await screen.findByText('go to second'));
+
+  expect(await screen.findByText('second page')).toBeInTheDocument();
+  expect(await screen.findByText('navigate back')).toBeInTheDocument();
+
+  userEvent.click(await screen.findByText('navigate back'));
+
+  expect(await screen.findByText('first page')).toBeInTheDocument();
+});
diff --git a/projects/testing-library/tests/rerender.spec.ts b/projects/testing-library/tests/rerender.spec.ts
index 443560a2..0edf69ea 100644
--- a/projects/testing-library/tests/rerender.spec.ts
+++ b/projects/testing-library/tests/rerender.spec.ts
@@ -7,7 +7,7 @@ import { render, screen } from '../src/public_api';
 })
 class FixtureComponent {
   @Input() firstName = 'Sarah';
-  @Input() lastName;
+  @Input() lastName?: string;
 }
 
 test('rerenders the component with updated props', async () => {
diff --git a/projects/testing-library/tsconfig.json b/projects/testing-library/tsconfig.json
index fd77caf1..24663f6f 100644
--- a/projects/testing-library/tsconfig.json
+++ b/projects/testing-library/tsconfig.json
@@ -6,13 +6,15 @@
     {
       "path": "./tsconfig.lib.json"
     },
+    {
+      "path": "./tsconfig.lib.prod.json"
+    },
     {
       "path": "./tsconfig.spec.json"
     }
   ],
   "compilerOptions": {},
   "angularCompilerOptions": {
-    "compilationMode": "partial",
     "strictInjectionParameters": true,
     "strictInputAccessModifiers": true,
     "strictTemplates": true,
diff --git a/projects/testing-library/tsconfig.lib.json b/projects/testing-library/tsconfig.lib.json
index f7b1b9ca..7d77d4c9 100644
--- a/projects/testing-library/tsconfig.lib.json
+++ b/projects/testing-library/tsconfig.lib.json
@@ -1,11 +1,12 @@
 {
   "extends": "./tsconfig.json",
   "compilerOptions": {
-    "outDir": "../../out-tsc/lib",
+    "outDir": "../../dist/out-tsc",
     "declaration": true,
     "declarationMap": true,
     "inlineSources": true,
     "types": ["node", "jest"]
   },
-  "exclude": ["src/test.ts", "**/*.spec.ts", "**/*.test.ts"]
+  "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts"],
+  "include": ["**/*.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/tsconfig.base.json b/tsconfig.base.json
index 0ad01d03..1e0de6e1 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -13,9 +13,14 @@
     "sourceMap": true,
     "target": "es2015",
     "typeRoots": ["node_modules/@types"],
+    "strict": true,
+    "exactOptionalPropertyTypes": true,
     "forceConsistentCasingInFileNames": true,
-    "noImplicitReturns": true,
+    "noImplicitOverride": true,
     "noFallthroughCasesInSwitch": true,
+    "noImplicitReturns": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
     "paths": {
       "@testing-library/angular": ["projects/testing-library"],
       "@testing-library/angular/jest-utils": ["projects/jest-utils"]
diff --git a/workspace.json b/workspace.json
deleted file mode 100644
index dfd6bcf1..00000000
--- a/workspace.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "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"
-  }
-}