diff --git a/projects/cdk/components/portal-host/test/portal-host.component.spec.ts b/projects/cdk/components/portal-host/test/portal-host.component.spec.ts
new file mode 100644
index 000000000000..42446c538f51
--- /dev/null
+++ b/projects/cdk/components/portal-host/test/portal-host.component.spec.ts
@@ -0,0 +1,47 @@
+import {Component, ViewChild} from '@angular/core';
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+import {NoopAnimationsModule} from '@angular/platform-browser/animations';
+import {PolymorpheusModule} from '@tinkoff/ng-polymorpheus';
+import {configureTestSuite} from 'ng-bullet';
+import {TuiPortalHostComponent} from '../portal-host.component';
+import {TuiPortalHostModule} from '../portal-host.module';
+
+describe('PortalHost', () => {
+ @Component({
+ template: `
+
+
+
+ `,
+ })
+ class TestComponent {
+ @ViewChild(TuiPortalHostComponent)
+ portalHost?: TuiPortalHostComponent;
+ }
+
+ let fixture: ComponentFixture;
+ let testComponent: TestComponent;
+
+ configureTestSuite(() => {
+ TestBed.configureTestingModule({
+ imports: [NoopAnimationsModule, PolymorpheusModule, TuiPortalHostModule],
+ declarations: [TestComponent],
+ });
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TestComponent);
+ testComponent = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('calculates clientRect', () => {
+ expect(testComponent.portalHost!.clientRect.top).toBeGreaterThanOrEqual(0);
+ });
+
+ it('calculates fixedPositionOffset', () => {
+ expect(
+ testComponent.portalHost!.fixedPositionOffset().top,
+ ).toBeGreaterThanOrEqual(0);
+ });
+});
diff --git a/projects/cdk/components/portal-host/test/portal.service.spec.ts b/projects/cdk/components/portal-host/test/portal.service.spec.ts
new file mode 100644
index 000000000000..15ab3bb70e0b
--- /dev/null
+++ b/projects/cdk/components/portal-host/test/portal.service.spec.ts
@@ -0,0 +1,47 @@
+import {TuiPortalService} from '../portal.service';
+
+describe('PortalService', () => {
+ let service: TuiPortalService;
+
+ beforeEach(() => {
+ service = new TuiPortalService();
+ });
+
+ it('Template removing', () => {
+ let called = 0;
+ const viewRefStub: any = {destroy: () => called++};
+
+ service.removeTemplate(viewRefStub);
+ });
+
+ it('HostView removing', () => {
+ let called = 0;
+ const componentRefStub: any = {hostView: {destroy: () => called++}};
+
+ service.remove(componentRefStub);
+ });
+
+ it('throws an error with no host', () => {
+ const a: any = null;
+ const b: any = null;
+
+ try {
+ service.add(a, b);
+ fail();
+ } catch (e) {
+ expect(e).toBeTruthy();
+ }
+ });
+
+ it('addTemplateChild with host attached', () => {
+ const a: any = null;
+ const result = {};
+ const componentPortalStub: any = {
+ addTemplateChild: () => result,
+ };
+
+ service.attach(componentPortalStub);
+
+ expect(service.addTemplate(a)).toBe(result as any);
+ });
+});
diff --git a/projects/cdk/observables/test/watch.spec.ts b/projects/cdk/observables/test/watch.spec.ts
new file mode 100644
index 000000000000..016fbb2cef96
--- /dev/null
+++ b/projects/cdk/observables/test/watch.spec.ts
@@ -0,0 +1,26 @@
+import {fakeAsync, tick} from '@angular/core/testing';
+import {Subject} from 'rxjs';
+import {watch} from '../watch';
+
+describe('Watch operator function', () => {
+ let $: Subject;
+ let called = 0;
+
+ const chrStub: any = {
+ markForCheck: () => called++,
+ };
+
+ beforeEach(() => {
+ $ = new Subject();
+ called = 0;
+ });
+
+ it('initially emits nothing, after event emits "true" and after a tick emits "false"', fakeAsync(() => {
+ $.pipe(watch(chrStub)).subscribe();
+
+ $.next();
+ tick();
+
+ expect(called).toBe(1);
+ }));
+});