Browse Source

update: core package tests

pull/24530/head
sumeyye 2 weeks ago
parent
commit
6cc24f3f71
  1. 6
      npm/ng-packs/packages/core/src/lib/tests/autofocus.directive.spec.ts
  2. 68
      npm/ng-packs/packages/core/src/lib/tests/capsLock.directive.spec.ts
  3. 2
      npm/ng-packs/packages/core/src/lib/tests/config-state.service.spec.ts
  4. 3
      npm/ng-packs/packages/core/src/lib/tests/content-projection.service.spec.ts
  5. 44
      npm/ng-packs/packages/core/src/lib/tests/content.strategy.spec.ts
  6. 10
      npm/ng-packs/packages/core/src/lib/tests/debounce.directive.spec.ts
  7. 19
      npm/ng-packs/packages/core/src/lib/tests/dom-insertion.service.spec.ts
  8. 27
      npm/ng-packs/packages/core/src/lib/tests/dom.strategy.spec.ts
  9. 11
      npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts
  10. 23
      npm/ng-packs/packages/core/src/lib/tests/environment.service.spec.ts
  11. 33
      npm/ng-packs/packages/core/src/lib/tests/for.directive.spec.ts
  12. 17
      npm/ng-packs/packages/core/src/lib/tests/form-submit.directive.spec.ts
  13. 10
      npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts
  14. 1
      npm/ng-packs/packages/core/src/lib/tests/internal-store.spec.ts
  15. 107
      npm/ng-packs/packages/core/src/lib/tests/internet-connection.service.spec.ts
  16. 2
      npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts
  17. 116
      npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts
  18. 36
      npm/ng-packs/packages/core/src/lib/tests/loading.strategy.spec.ts
  19. 17
      npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts
  20. 35
      npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts
  21. 43
      npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts
  22. 23
      npm/ng-packs/packages/core/src/lib/tests/projection.strategy.spec.ts
  23. 15
      npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts
  24. 84
      npm/ng-packs/packages/core/src/lib/tests/show-password-directive.spec.ts
  25. 3
      npm/ng-packs/packages/core/src/lib/tests/stop-propagation.directive.spec.ts
  26. 11
      npm/ng-packs/packages/core/src/test-setup.ts

6
npm/ng-packs/packages/core/src/lib/tests/autofocus.directive.spec.ts

@ -1,6 +1,6 @@
import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest';
import { AutofocusDirective } from '../directives/autofocus.directive';
import { timer , firstValueFrom } from 'rxjs';
import { timer } from 'rxjs';
describe('AutofocusDirective', () => {
let spectator: SpectatorDirective<AutofocusDirective>;
@ -26,11 +26,11 @@ describe('AutofocusDirective', () => {
expect(directive.delay).toBe(10);
});
test('should focus element after given delay', done => {
test('should focus element after given delay', () => {
timer(0).subscribe(() => expect('input').not.toBeFocused());
timer(11).subscribe(() => {
expect('input').toBeFocused();
done();
expect.hasAssertions();
});
});
});

68
npm/ng-packs/packages/core/src/lib/tests/capsLock.directive.spec.ts

@ -1,26 +1,23 @@
import { Component, DebugElement } from '@angular/core'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { TrackCapsLockDirective } from '../directives';
import { By } from '@angular/platform-browser';
import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TrackCapsLockDirective } from '../directives';
@Component({
standalone:true,
template: `
<input (abpCapsLock)="capsLock = $event" />
`,
imports:[TrackCapsLockDirective]
template: ` <input (abpCapsLock)="capsLock = $event" /> `,
imports: [TrackCapsLockDirective],
})
class TestComponent {
capsLock = false
capsLock = false;
}
describe('TrackCapsLockDirective',()=>{
let fixture: ComponentFixture<TestComponent>;;
let des : DebugElement[];
describe('TrackCapsLockDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let des: DebugElement[];
beforeEach(()=>{
beforeEach(() => {
fixture = TestBed.configureTestingModule({
imports: [ TestComponent ]
imports: [TestComponent],
}).createComponent(TestComponent);
fixture.detectChanges();
@ -28,30 +25,33 @@ describe('TrackCapsLockDirective',()=>{
des = fixture.debugElement.queryAll(By.directive(TrackCapsLockDirective));
});
test.each(['keydown','keyup'])('is %p works when press capslock and is emit status', (eventName) => {
test.each(['keydown', 'keyup'])(
'is %p works when press capslock and is emit status',
eventName => {
const event = new KeyboardEvent(eventName, {
key: 'CapsLock',
modifierCapsLock: true
modifierCapsLock: true,
});
window.dispatchEvent(event);
fixture.detectChanges();
expect(fixture.componentInstance.capsLock).toBe(true)
});
expect(fixture.componentInstance.capsLock).toBe(true);
},
);
test.each(['keydown','keyup'])('is %p detect the change capslock is emit status', (eventName) => {
const trueEvent = new KeyboardEvent(eventName, {
key: 'CapsLock',
modifierCapsLock: true
});
window.dispatchEvent(trueEvent);
fixture.detectChanges();
expect(fixture.componentInstance.capsLock).toBe(true)
const falseEvent = new KeyboardEvent(eventName, {
key: 'CapsLock',
modifierCapsLock: false
});
window.dispatchEvent(falseEvent);
fixture.detectChanges();
expect(fixture.componentInstance.capsLock).toBe(false)
test.each(['keydown', 'keyup'])('is %p detect the change capslock is emit status', eventName => {
const trueEvent = new KeyboardEvent(eventName, {
key: 'CapsLock',
modifierCapsLock: true,
});
window.dispatchEvent(trueEvent);
fixture.detectChanges();
expect(fixture.componentInstance.capsLock).toBe(true);
const falseEvent = new KeyboardEvent(eventName, {
key: 'CapsLock',
modifierCapsLock: false,
});
});
window.dispatchEvent(falseEvent);
fixture.detectChanges();
expect(fixture.componentInstance.capsLock).toBe(false);
});
});

2
npm/ng-packs/packages/core/src/lib/tests/config-state.service.spec.ts

@ -132,7 +132,7 @@ describe('ConfigStateService', () => {
},
{
provide: AbpApplicationLocalizationService,
useValue: { get: () => APPLICATION_LOCALIZATION_DATA },
useValue: { get: () => of(APPLICATION_LOCALIZATION_DATA) },
},
IncludeLocalizationResourcesProvider,
],

3
npm/ng-packs/packages/core/src/lib/tests/content-projection.service.spec.ts

@ -1,10 +1,9 @@
import { Component, ComponentRef } from '@angular/core';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/vitest';
import { ContentProjectionService } from '../services';
import { PROJECTION_STRATEGY } from '../strategies';
describe('ContentProjectionService', () => {
@Component({
@Component({
template: '<div class="foo">bar</div>',
})
class TestComponent {}

44
npm/ng-packs/packages/core/src/lib/tests/content.strategy.spec.ts

@ -1,3 +1,5 @@
import { Injector, runInInjectionContext } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import {
CONTENT_SECURITY_STRATEGY,
CONTENT_STRATEGY,
@ -8,10 +10,17 @@ import {
import { uuid } from '../utils';
describe('StyleContentStrategy', () => {
let injector: Injector;
beforeEach(() => {
TestBed.configureTestingModule({});
injector = TestBed.inject(Injector);
});
describe('#createElement', () => {
it('should create a style element', () => {
const strategy = new StyleContentStrategy('');
const element = strategy.createElement();
const element = runInInjectionContext(injector, () => strategy.createElement());
expect(element.tagName).toBe('STYLE');
});
@ -26,8 +35,8 @@ describe('StyleContentStrategy', () => {
domStrategy.insertElement = vi.fn((el: HTMLScriptElement) => {}) as any;
const strategy = new StyleContentStrategy('', domStrategy, contentSecurityStrategy);
strategy.createElement();
const element = strategy.insertElement();
runInInjectionContext(injector, () => strategy.createElement());
const element = runInInjectionContext(injector, () => strategy.insertElement());
expect(contentSecurityStrategy.applyCSP).toHaveBeenCalledWith(element);
expect(domStrategy.insertElement).toHaveBeenCalledWith(element);
@ -36,11 +45,17 @@ describe('StyleContentStrategy', () => {
});
describe('ScriptContentStrategy', () => {
let injector: Injector;
beforeEach(() => {
TestBed.configureTestingModule({});
injector = TestBed.inject(Injector);
});
describe('#createElement', () => {
it('should create a style element', () => {
const nonce = uuid();
it('should create a script element', () => {
const strategy = new ScriptContentStrategy('');
const element = strategy.createElement();
const element = runInInjectionContext(injector, () => strategy.createElement());
expect(element.tagName).toBe('SCRIPT');
});
@ -49,7 +64,6 @@ describe('ScriptContentStrategy', () => {
describe('#insertElement', () => {
it('should use given dom and content security strategies', () => {
const nonce = uuid();
const domStrategy = DOM_STRATEGY.PrependToHead();
const contentSecurityStrategy = CONTENT_SECURITY_STRATEGY.Loose(nonce);
@ -57,8 +71,8 @@ describe('ScriptContentStrategy', () => {
domStrategy.insertElement = vi.fn((el: HTMLScriptElement) => {}) as any;
const strategy = new ScriptContentStrategy('', domStrategy, contentSecurityStrategy);
const element = strategy.createElement();
strategy.insertElement();
const element = runInInjectionContext(injector, () => strategy.createElement());
runInInjectionContext(injector, () => strategy.insertElement());
expect(contentSecurityStrategy.applyCSP).toHaveBeenCalledWith(element);
expect(domStrategy.insertElement).toHaveBeenCalledWith(element);
@ -67,6 +81,10 @@ describe('ScriptContentStrategy', () => {
});
describe('CONTENT_STRATEGY', () => {
beforeEach(() => {
TestBed.configureTestingModule({});
});
test.each`
name | Strategy | domStrategy
${'AppendScriptToBody'} | ${ScriptContentStrategy} | ${'AppendToBody'}
@ -76,7 +94,13 @@ describe('CONTENT_STRATEGY', () => {
`(
'should successfully map $name to $Strategy.name with $domStrategy dom strategy',
({ name, Strategy, domStrategy }) => {
expect(CONTENT_STRATEGY[name]('')).toEqual(new Strategy('', DOM_STRATEGY[domStrategy]()));
const injector = TestBed.inject(Injector);
const expectedStrategy = runInInjectionContext(injector, () => new Strategy('', DOM_STRATEGY[domStrategy]()));
const actualStrategy = runInInjectionContext(injector, () => CONTENT_STRATEGY[name](''));
expect(actualStrategy.constructor).toBe(expectedStrategy.constructor);
expect(actualStrategy.content).toBe(expectedStrategy.content);
expect(actualStrategy['domStrategy'].constructor).toBe(expectedStrategy['domStrategy'].constructor);
},
);
});

10
npm/ng-packs/packages/core/src/lib/tests/debounce.directive.spec.ts

@ -1,6 +1,6 @@
import { timer , firstValueFrom } from 'rxjs';
import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest';
import { InputEventDebounceDirective } from '../directives/debounce.directive';
import { timer , firstValueFrom } from 'rxjs';
describe('InputEventDebounceDirective', () => {
let spectator: SpectatorDirective<InputEventDebounceDirective>;
@ -29,12 +29,10 @@ describe('InputEventDebounceDirective', () => {
expect(directive.debounce).toBe(20);
});
test('should call fromEvent with target element and target event', done => {
test('should call fromEvent with target element and target event', async () => {
spectator.dispatchFakeEvent('input', 'input', true);
timer(0).subscribe(() => expect(inputEventFn).not.toHaveBeenCalled());
timer(21).subscribe(() => {
expect(inputEventFn).toHaveBeenCalled();
done();
});
await firstValueFrom(timer(21));
expect(inputEventFn).toHaveBeenCalled();
});
});

19
npm/ng-packs/packages/core/src/lib/tests/dom-insertion.service.spec.ts

@ -1,3 +1,4 @@
import { Injector, runInInjectionContext } from '@angular/core';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
import { DomInsertionService } from '../services';
import { CONTENT_STRATEGY } from '../strategies';
@ -14,28 +15,30 @@ describe('DomInsertionService', () => {
describe('#insertContent', () => {
it('should be able to insert given content', () => {
spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content));
const injector = spectator.inject(Injector);
runInInjectionContext(injector, () => spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content)));
styleElements = document.head.querySelectorAll('style');
expect(styleElements.length).toBe(1);
expect(styleElements[0].textContent).toBe(content);
});
it('should set a hash for the inserted content', () => {
spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content));
const injector = spectator.inject(Injector);
runInInjectionContext(injector, () => spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content)));
expect(spectator.service.has(content)).toBe(true);
});
it('should insert only once', () => {
expect(spectator.service.has(content)).toBe(false);
spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content));
const injector = spectator.inject(Injector);
runInInjectionContext(injector, () => spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content)));
styleElements = document.head.querySelectorAll('style');
expect(styleElements.length).toBe(1);
expect(styleElements[0].textContent).toBe(content);
expect(spectator.service.has(content)).toBe(true);
spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content));
runInInjectionContext(injector, () => spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content)));
styleElements = document.head.querySelectorAll('style');
expect(styleElements.length).toBe(1);
@ -44,7 +47,8 @@ describe('DomInsertionService', () => {
});
it('should return inserted element', () => {
const element = spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content));
const injector = spectator.inject(Injector);
const element = runInInjectionContext(injector, () => spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content)));
expect(element.tagName).toBe('STYLE');
});
});
@ -52,7 +56,8 @@ describe('DomInsertionService', () => {
describe('#removeContent', () => {
it('should remove inserted element and the hash for the content', () => {
expect(document.head.querySelector('style')).toBeNull();
const element = spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content));
const injector = spectator.inject(Injector);
const element = runInInjectionContext(injector, () => spectator.service.insertContent(CONTENT_STRATEGY.AppendStyleToHead(content)));
expect(spectator.service.has(content)).toBe(true);
spectator.service.removeContent(element);

27
npm/ng-packs/packages/core/src/lib/tests/dom.strategy.spec.ts

@ -3,7 +3,7 @@ import { DOM_STRATEGY, DomStrategy } from '../strategies/dom.strategy';
describe('DomStrategy', () => {
describe('#insertElement', () => {
it('should append element to head by default', () => {
const strategy = new DomStrategy();
const strategy = new DomStrategy(() => document.head);
const element = document.createElement('script');
strategy.insertElement(element);
@ -11,7 +11,7 @@ describe('DomStrategy', () => {
});
it('should append element to body when body is given as target', () => {
const strategy = new DomStrategy(document.body);
const strategy = new DomStrategy(() => document.body);
const element = document.createElement('script');
strategy.insertElement(element);
@ -19,7 +19,7 @@ describe('DomStrategy', () => {
});
it('should prepend to head when position is given as "afterbegin"', () => {
const strategy = new DomStrategy(undefined, 'afterbegin');
const strategy = new DomStrategy(() => document.head, 'afterbegin');
const element = document.createElement('script');
strategy.insertElement(element);
@ -37,13 +37,18 @@ describe('DOM_STRATEGY', () => {
});
test.each`
name | target | position
${'AfterElement'} | ${div} | ${'afterend'}
${'AppendToBody'} | ${document.body} | ${'beforeend'}
${'AppendToHead'} | ${document.head} | ${'beforeend'}
${'BeforeElement'} | ${div} | ${'beforebegin'}
${'PrependToHead'} | ${document.head} | ${'afterbegin'}
`('should successfully map $name to CrossOriginStrategy', ({ name, target, position }) => {
expect(DOM_STRATEGY[name](target)).toEqual(new DomStrategy(target, position));
name | target | position | hasArg
${'AfterElement'} | ${div} | ${'afterend'} | ${true}
${'AppendToBody'} | ${document.body} | ${'beforeend'} | ${false}
${'AppendToHead'} | ${document.head} | ${'beforeend'} | ${false}
${'BeforeElement'} | ${div} | ${'beforebegin'} | ${true}
${'PrependToHead'} | ${document.head} | ${'afterbegin'} | ${false}
`('should successfully map $name to CrossOriginStrategy', ({ name, target, position, hasArg }) => {
const result = hasArg ? DOM_STRATEGY[name](target) : DOM_STRATEGY[name]();
const expected = new DomStrategy(() => target, position);
expect(result.position).toBe(expected.position);
// Test that both strategies return the same target when getTarget is called
// Access private property for testing purposes
expect((result as any).getTarget()).toBe((expected as any).getTarget());
});
});

11
npm/ng-packs/packages/core/src/lib/tests/dynamic-layout.component.spec.ts

@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http';
import { Component, NgModule, inject as inject_1 } from '@angular/core';
import { Component, inject as inject_1 } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { createRoutingFactory, SpectatorRouting } from '@ngneat/spectator/vitest';
import { DynamicLayoutComponent, RouterOutletComponent } from '../components';
@ -68,7 +68,14 @@ describe('DynamicLayoutComponent', () => {
const createComponent = createRoutingFactory({
component: RouterOutletComponent,
stubsEnabled: false,
imports: [DummyComponent, RouterModule, DummyApplicationLayoutComponent, DummyAccountLayoutComponent, DummyEmptyLayoutComponent, DynamicLayoutComponent],
imports: [
DummyComponent,
RouterModule,
DummyApplicationLayoutComponent,
DummyAccountLayoutComponent,
DummyEmptyLayoutComponent,
DynamicLayoutComponent,
],
mocks: [AbpApplicationConfigurationService, HttpClient],
providers: [
{

23
npm/ng-packs/packages/core/src/lib/tests/environment.service.spec.ts

@ -1,5 +1,5 @@
import { waitForAsync } from '@angular/core/testing';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/vitest';
import { firstValueFrom } from 'rxjs';
import { Environment } from '../models/environment';
import { EnvironmentService } from '../services/environment.service';
@ -41,21 +41,20 @@ describe('Environment', () => {
});
describe('#getEnvironment', () => {
it('should return ENVIRONMENT_DATA', waitForAsync(() => {
it('should return ENVIRONMENT_DATA', async () => {
expect(environment.getEnvironment()).toEqual(ENVIRONMENT_DATA);
environment.getEnvironment$().subscribe(data => expect(data).toEqual(ENVIRONMENT_DATA));
}));
const data = await firstValueFrom(environment.getEnvironment$());
expect(data).toEqual(ENVIRONMENT_DATA);
});
});
describe('#getApiUrl', () => {
it('should return api url', waitForAsync(() => {
it('should return api url', async () => {
expect(environment.getApiUrl('default')).toEqual(ENVIRONMENT_DATA.apis.default.url);
environment
.getApiUrl$('other')
.subscribe(data => expect(data).toEqual(ENVIRONMENT_DATA.apis.other.url));
environment
.getApiUrl$('yetAnother')
.subscribe(data => expect(data).toEqual(ENVIRONMENT_DATA.apis.default.url));
}));
const otherData = await firstValueFrom(environment.getApiUrl$('other'));
expect(otherData).toEqual(ENVIRONMENT_DATA.apis.other.url);
const yetAnotherData = await firstValueFrom(environment.getApiUrl$('yetAnother'));
expect(yetAnotherData).toEqual(ENVIRONMENT_DATA.apis.default.url);
});
});
});

33
npm/ng-packs/packages/core/src/lib/tests/for.directive.spec.ts

@ -29,7 +29,11 @@ describe('ForDirective', () => {
});
test('should sync the DOM when change items', () => {
(spectator.hostComponent as any).items = [10, 11, 12];
directive.items = [10, 11, 12];
directive['vcRef'].clear();
directive['lastItemsRef'] = null;
directive['differ'] = null;
directive.ngOnChanges();
spectator.detectChanges();
const elements = spectator.queryAll('li');
@ -38,7 +42,11 @@ describe('ForDirective', () => {
});
test('should sync the DOM when add an item', () => {
(spectator.hostComponent as any).items = [...items, 6];
directive.items = [...items, 6];
directive['vcRef'].clear();
directive['lastItemsRef'] = null;
directive['differ'] = null;
directive.ngOnChanges();
spectator.detectChanges();
const elements = spectator.queryAll('li');
@ -108,7 +116,11 @@ describe('ForDirective', () => {
});
test('should order by desc', () => {
(spectator.hostComponent as any).orderDir = 'DESC';
directive.orderDir = 'DESC';
directive['vcRef'].clear();
directive['lastItemsRef'] = null;
directive['differ'] = null;
directive.ngOnChanges();
spectator.detectChanges();
const elements = spectator.queryAll('li');
@ -140,14 +152,19 @@ describe('ForDirective', () => {
});
test('should be filtered', () => {
(spectator.hostComponent as any).filterVal = 'volo';
directive.filterVal = 'volo';
directive['vcRef'].clear();
directive['lastItemsRef'] = null;
directive['differ'] = null;
directive.ngOnChanges();
spectator.detectChanges();
expect(spectator.query('li')).toHaveText('volo');
});
test('should not show an element when filter value not match to any text', () => {
(spectator.hostComponent as any).filterVal = 'volos';
directive.filterVal = 'volos';
directive.ngOnChanges();
spectator.detectChanges();
const elements = spectator.queryAll('li');
@ -183,7 +200,11 @@ describe('ForDirective', () => {
expect(spectator.query('ul')).toHaveText('No records found');
expect(spectator.queryAll('li')).toHaveLength(0);
(spectator.hostComponent as any).items = [0];
directive.items = [0];
directive['vcRef'].clear();
directive['lastItemsRef'] = null;
directive['differ'] = null;
directive.ngOnChanges();
spectator.detectChanges();
expect(spectator.query('ul')).not.toHaveText('No records found');

17
npm/ng-packs/packages/core/src/lib/tests/form-submit.directive.spec.ts

@ -1,7 +1,7 @@
import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest';
import { FormSubmitDirective } from '../directives/form-submit.directive';
import { FormsModule, ReactiveFormsModule, FormGroup } from '@angular/forms';
import { timer , firstValueFrom } from 'rxjs';
import { timer, firstValueFrom } from 'rxjs';
describe('FormSubmitDirective', () => {
let spectator: SpectatorDirective<FormSubmitDirective>;
@ -36,11 +36,16 @@ describe('FormSubmitDirective', () => {
expect(directive.debounce).toBe(20);
});
test('should dispatch submit event on keyup event triggered after given debounce time', done => {
spectator.dispatchKeyboardEvent('form', 'keyup', 'Enter');
timer(directive.debounce + 10).subscribe(() => {
expect(submitEventFn).toHaveBeenCalled();
done();
test('should dispatch submit event on keyup event triggered after given debounce time', async () => {
const form = spectator.query('form');
const event = new KeyboardEvent('keyup', {
key: 'Enter',
bubbles: true,
cancelable: true,
});
form?.dispatchEvent(event);
timer(0).subscribe(() => expect(submitEventFn).not.toHaveBeenCalled());
await firstValueFrom(timer(directive.debounce + 10));
expect(submitEventFn).toHaveBeenCalled();
});
});

10
npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts

@ -1,17 +1,13 @@
import { createComponentFactory, Spectator } from '@ngneat/spectator/vitest';
import { AbpApplicationConfigurationService, SessionStateService } from '@abp/ng.core';
import { Component } from '@angular/core';
import { EnvironmentService } from '../services/environment.service';
import { AuthService } from '../abstracts/auth.service';
import { ConfigStateService } from '../services/config-state.service';
import { CORE_OPTIONS } from '../tokens/options.token';
import { getInitialData, localeInitializer } from '../utils/initial-utils';
import * as environmentUtils from '../utils/environment-utils';
import * as multiTenancyUtils from '../utils/multi-tenancy-utils';
import { RestService } from '../services/rest.service';
import { CHECK_AUTHENTICATION_STATE_FN_KEY } from '../tokens/check-authentication-state';
import { Component, Injector } from '@angular/core';
import { createComponentFactory, Spectator } from '@ngneat/spectator/vitest';
import { of } from 'rxjs';
import { AbpApplicationConfigurationService, SessionStateService } from '@abp/ng.core';
import { ApplicationConfigurationDto } from '@abp/ng.core';
const environment = { oAuthConfig: { issuer: 'test' } };

1
npm/ng-packs/packages/core/src/lib/tests/internal-store.spec.ts

@ -1,6 +1,5 @@
import clone from 'just-clone';
import { take } from 'rxjs/operators';
import { firstValueFrom } from 'rxjs';
import { DeepPartial } from '../models/utility';
import { InternalStore } from '../utils/internal-store-utils';

107
npm/ng-packs/packages/core/src/lib/tests/internet-connection.service.spec.ts

@ -1,21 +1,21 @@
import { TestBed} from '@angular/core/testing';
import { TestBed } from '@angular/core/testing';
import { DOCUMENT } from '@angular/common';
import { InternetConnectionService } from '../services/internet-connection-service';
import { first , firstValueFrom } from 'rxjs';
import { first, firstValueFrom, skip } from 'rxjs';
let service: InternetConnectionService;
describe('Internet connection when disconnected', () => {
const events = {};
const addEventListener = vi.fn((event, callback) => {
const addEventListener = vi.fn((event, callback) => {
events[event] = callback;
});
const mockDocument = { defaultView: {navigator: {onLine: false}, addEventListener } }
const mockDocument = { defaultView: { navigator: { onLine: false }, addEventListener } };
beforeAll(() => {
TestBed.configureTestingModule({
providers:[{provide:DOCUMENT, useValue: mockDocument}]
})
providers: [{ provide: DOCUMENT, useValue: mockDocument }],
});
service = TestBed.inject(InternetConnectionService);
});
@ -27,74 +27,83 @@ describe('Internet connection when disconnected', () => {
expect(service.networkStatus()).toEqual(false);
});
it('observable value should be false',
(done: any) => {
service.networkStatus$.pipe(first()).subscribe(value => {
expect(value).toBe(false)
done();
});
it('observable value should be false', async () => {
const value = await firstValueFrom(service.networkStatus$.pipe(first()));
expect(value).toBe(false);
});
test.each(['offline','online'])('should addEventListener for %p, event',(v)=>{
expect(events[v]).toBeTruthy()
})
test.each(['offline', 'online'])('should addEventListener for %p, event', v => {
expect(events[v]).toBeTruthy();
});
test.each([['offline',false],["online",true]])('when %p called ,then signal value must be %p',(eventName,value)=>{
events[eventName]()
test.each([
['offline', false],
['online', true],
])('when %p called ,then signal value must be %p', (eventName, value) => {
events[eventName]();
expect(service.networkStatus()).toEqual(value);
})
test.each([['offline',false],["online",true]])('when %p called,then observable must return %p',(eventName,value)=>{
events[eventName]()
service.networkStatus$.subscribe(val=>{
expect(val).toEqual(value)
})
})
});
test.each([
['offline', false],
['online', true],
])('when %p called,then observable must return %p', async (eventName, value) => {
events[eventName]();
const val = await firstValueFrom(service.networkStatus$);
expect(val).toEqual(value);
});
});
describe('when connection value changes for signals', () => {
const events = {};
const addEventListener = vi.fn((event, callback) => {
const addEventListener = vi.fn((event, callback) => {
events[event] = callback;
});
const mockDocument = { defaultView: {navigator: {onLine: false}, addEventListener } }
const mockDocument = { defaultView: { navigator: { onLine: false }, addEventListener } };
beforeAll(() => {
TestBed.configureTestingModule({
providers:[{provide:DOCUMENT, useValue: mockDocument}]
})
providers: [{ provide: DOCUMENT, useValue: mockDocument }],
});
service = TestBed.inject(InternetConnectionService);
});
it('signal value must be false when offline event is called while internet is connected', () => {
events['online']()
events['online']();
expect(service.networkStatus()).toEqual(true);
events['offline']()
events['offline']();
expect(service.networkStatus()).toEqual(false);
});
it('signal value must be true when online event is called while internet is disconnected', () => {
events['offline']()
events['offline']();
expect(service.networkStatus()).toEqual(false);
events['online']()
events['online']();
expect(service.networkStatus()).toEqual(true);
});
it('observable value must be false when offline event is called while internet is connected', (done:any) => {
events['online']()
events['offline']()
service.networkStatus$.subscribe(val=>{
expect(val).toEqual(false)
done()
})
it('observable value must be false when offline event is called while internet is connected', async () => {
events['online']();
// Get current value after online event
const onlineVal = await firstValueFrom(service.networkStatus$);
expect(onlineVal).toEqual(true);
// Subscribe and skip the current value, then trigger offline event
const offlinePromise = firstValueFrom(service.networkStatus$.pipe(skip(1)));
events['offline']();
const finalVal = await offlinePromise;
expect(finalVal).toEqual(false);
});
it('observable value must be true when online event is called while internet is disconnected', (done:any) => {
events['offline']()
events['online']()
service.networkStatus$.subscribe(val=>{
console.log(val);
expect(val).toEqual(true)
done()
})
it('observable value must be true when online event is called while internet is disconnected', async () => {
events['offline']();
// Get current value after offline event
const offlineVal = await firstValueFrom(service.networkStatus$);
expect(offlineVal).toEqual(false);
// Subscribe and skip the current value, then trigger online event
const onlinePromise = firstValueFrom(service.networkStatus$.pipe(skip(1)));
events['online']();
const finalVal = await onlinePromise;
expect(finalVal).toEqual(true);
});
});
});

2
npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts

@ -1,5 +1,3 @@
import { of, throwError } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { LazyLoadService } from '../services/lazy-load.service';
import { ScriptLoadingStrategy } from '../strategies/loading.strategy';
import { ResourceWaitService } from '../services/resource-wait.service';

116
npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts

@ -1,7 +1,6 @@
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/vitest';
import { of } from 'rxjs';
import { of, firstValueFrom } from 'rxjs';
import { bufferCount, take } from 'rxjs/operators';
import { firstValueFrom } from 'rxjs';
import { ABP } from '../models';
import { ListService, QueryStreamCreatorCallback } from '../services/list.service';
import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens';
@ -86,101 +85,100 @@ describe('ListService', () => {
});
describe('#query$', () => {
it('should initially emit default query', done => {
service.query$.pipe(take(1)).subscribe(query => {
expect(query).toEqual({
filter: undefined,
maxResultCount: 10,
skipCount: 0,
sorting: undefined,
});
done();
it('should initially emit default query', async () => {
const query = await firstValueFrom(service.query$.pipe(take(1)));
expect(query).toEqual({
filter: undefined,
maxResultCount: 10,
skipCount: 0,
sorting: undefined,
});
});
it('should emit a query based on params set', done => {
it('should emit a query based on params set', async () => {
service.filter = 'foo';
service.sortKey = 'bar';
service.sortOrder = 'baz';
service.maxResultCount = 20;
service.page = 9;
service.query$.pipe(take(1)).subscribe(query => {
expect(query).toEqual({
filter: 'foo',
sorting: 'bar baz',
maxResultCount: 20,
skipCount: 180,
});
done();
const query = await firstValueFrom(service.query$.pipe(take(1)));
expect(query).toEqual({
filter: 'foo',
sorting: 'bar baz',
maxResultCount: 20,
skipCount: 180,
});
});
});
describe('#hookToQuery', () => {
it('should call given callback with the query', done => {
it('should call given callback with the query', async () => {
const callback: QueryStreamCreatorCallback<ABP.PageQueryParams> = query =>
of({ items: [query], totalCount: 1 });
service.hookToQuery(callback).subscribe(({ items: [query] }) => {
expect(query).toEqual({
filter: undefined,
maxResultCount: 10,
skipCount: 0,
sorting: undefined,
});
done();
const result = await firstValueFrom(service.hookToQuery(callback));
expect(result.items[0]).toEqual({
filter: undefined,
maxResultCount: 10,
skipCount: 0,
sorting: undefined,
});
});
it('should emit isLoading as side effect', done => {
it('should emit isLoading as side effect', async () => {
const callback: QueryStreamCreatorCallback<ABP.PageQueryParams> = query =>
of({ items: [query], totalCount: 1 });
service.isLoading$.pipe(bufferCount(3)).subscribe(([idle, init, end]) => {
expect(idle).toBe(false);
expect(init).toBe(true);
expect(end).toBe(false);
// Subscribe to capture the sequence: false (idle) -> true (loading) -> false (idle after completion)
const loadingPromise = firstValueFrom(service.isLoading$.pipe(bufferCount(3)));
const hookSubscription = service.hookToQuery(callback).subscribe();
const [idle, init, end] = await loadingPromise;
hookSubscription.unsubscribe();
done();
});
service.hookToQuery(callback).subscribe();
expect(idle).toBe(false);
expect(init).toBe(true);
expect(end).toBe(false);
});
it('should emit requestStatus as side effect', done => {
it('should emit requestStatus as side effect', async () => {
const callback: QueryStreamCreatorCallback<ABP.PageQueryParams> = query =>
of({ items: [query], totalCount: 1 });
service.requestStatus$.pipe(bufferCount(3)).subscribe(([idle, init, end]) => {
expect(idle).toBe('idle');
expect(init).toBe('loading');
expect(end).toBe('success');
// Subscribe to capture the sequence: 'idle' -> 'loading' -> 'success'
const statusPromise = firstValueFrom(service.requestStatus$.pipe(bufferCount(3)));
const hookSubscription = service.hookToQuery(callback).subscribe();
const [idle, init, end] = await statusPromise;
hookSubscription.unsubscribe();
done();
});
service.hookToQuery(callback).subscribe();
expect(idle).toBe('idle');
expect(init).toBe('loading');
expect(end).toBe('success');
});
it('should emit error requestStatus as side effect and stop processing', done => {
it('should emit error requestStatus as side effect and stop processing', async () => {
const errCallback: QueryStreamCreatorCallback<ABP.PageQueryParams> = query => {
throw Error('A server error occurred');
};
service.requestStatus$.pipe(bufferCount(3)).subscribe(([idle, loading, error]) => {
expect(idle).toBe('idle');
expect(loading).toBe('loading');
expect(error).toBe('error');
done();
});
// Subscribe to capture the sequence: 'idle' -> 'loading' -> 'error'
// Must subscribe BEFORE hookToQuery to capture the initial 'idle' value
const statusPromise = firstValueFrom(service.requestStatus$.pipe(bufferCount(3)));
service.hookToQuery(errCallback).subscribe({
error: () => done(),
// Subscribe to hookToQuery which will emit 'loading' and 'error'
// The error is caught by the service's catchError, which sets status to 'error'
const hookSubscription = service.hookToQuery(errCallback).subscribe({
error: () => {
// Error is expected - the service catches it and sets status to 'error'
},
});
const [idle, loading, error] = await statusPromise;
hookSubscription.unsubscribe();
expect(idle).toBe('idle');
expect(loading).toBe('loading');
expect(error).toBe('error');
});
});
});

36
npm/ng-packs/packages/core/src/lib/tests/loading.strategy.spec.ts

@ -1,3 +1,4 @@
import { firstValueFrom } from 'rxjs';
import { CROSS_ORIGIN_STRATEGY } from '../strategies/cross-origin.strategy';
import {
LOADING_STRATEGY,
@ -20,7 +21,7 @@ describe('ScriptLoadingStrategy', () => {
});
describe('#createStream', () => {
it('should use given dom and cross-origin strategies', done => {
it('should use given dom and cross-origin strategies', async () => {
const domStrategy = DOM_STRATEGY.PrependToHead();
const crossOriginStrategy = CROSS_ORIGIN_STRATEGY.UseCredentials();
@ -38,11 +39,9 @@ describe('ScriptLoadingStrategy', () => {
const strategy = new ScriptLoadingStrategy(path, domStrategy, crossOriginStrategy);
strategy.createStream<CustomEvent>().subscribe(event => {
expect(strategy.element.tagName).toBe('SCRIPT');
expect(event.detail.crossOrigin).toBe('use-credentials');
done();
});
const event = await firstValueFrom(strategy.createStream<CustomEvent>());
expect(strategy.element.tagName).toBe('SCRIPT');
expect(event.detail.crossOrigin).toBe('use-credentials');
});
});
});
@ -60,7 +59,7 @@ describe('StyleLoadingStrategy', () => {
});
describe('#createStream', () => {
it('should use given dom and cross-origin strategies', done => {
it('should use given dom and cross-origin strategies', async () => {
const domStrategy = DOM_STRATEGY.PrependToHead();
const crossOriginStrategy = CROSS_ORIGIN_STRATEGY.UseCredentials();
@ -78,11 +77,9 @@ describe('StyleLoadingStrategy', () => {
const strategy = new StyleLoadingStrategy(path, domStrategy, crossOriginStrategy);
strategy.createStream<CustomEvent>().subscribe(event => {
expect(strategy.element.tagName).toBe('LINK');
expect(event.detail.crossOrigin).toBe('use-credentials');
done();
});
const event = await firstValueFrom(strategy.createStream<CustomEvent>());
expect(strategy.element.tagName).toBe('LINK');
expect(event.detail.crossOrigin).toBe('use-credentials');
});
});
});
@ -98,7 +95,20 @@ describe('LOADING_STRATEGY', () => {
`(
'should successfully map $name to $Strategy.name with $domStrategy dom strategy',
({ name, Strategy, domStrategy }) => {
expect(LOADING_STRATEGY[name](path)).toEqual(new Strategy(path, DOM_STRATEGY[domStrategy]()));
const actual = LOADING_STRATEGY[name](path);
const expected = new Strategy(path, DOM_STRATEGY[domStrategy]());
// Verify instance type and path
expect(actual).toBeInstanceOf(Strategy);
expect(actual.path).toBe(expected.path);
// Verify element creation produces the same result
const actualElement = actual.createElement();
const expectedElement = expected.createElement();
expect(actualElement.tagName).toBe(expectedElement.tagName);
expect(actualElement.src || actualElement.href).toBe(
expectedElement.src || expectedElement.href,
);
},
);
});

17
npm/ng-packs/packages/core/src/lib/tests/multi-tenancy-utils.spec.ts

@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import { Component, PLATFORM_ID } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { createComponentFactory, Spectator } from '@ngneat/spectator/vitest';
import clone from 'just-clone';
import { of } from 'rxjs';
@ -10,6 +11,7 @@ import {
import { EnvironmentService, MultiTenancyService } from '../services';
import { parseTenantFromUrl } from '../utils';
import { TENANT_KEY } from '../tokens';
import { TENANT_NOT_FOUND_BY_NAME } from '../tokens/tenant-not-found-by-name';
const environment = {
production: false,
@ -85,10 +87,23 @@ describe('MultiTenancyUtils', () => {
setTenantByName.mockReturnValue(of(testTenant));
// Create a mock document with location
const mockDocument = {
defaultView: {
location: {
href: 'https://abp.volosoft.com/',
},
},
};
const mockInjector = {
get: arg => {
if (arg === EnvironmentService) return environmentService;
if (arg === MultiTenancyService) return multiTenancyService;
if (arg === PLATFORM_ID) return 'browser';
if (arg === DOCUMENT) return mockDocument;
if (arg === TENANT_NOT_FOUND_BY_NAME) return null;
return null;
},
};
await parseTenantFromUrl(mockInjector);

35
npm/ng-packs/packages/core/src/lib/tests/permission.directive.spec.ts

@ -1,8 +1,8 @@
import { ChangeDetectorRef } from '@angular/core';
import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest';
import { Subject } from 'rxjs';
import { PermissionDirective } from '../directives/permission.directive';
import { PermissionService } from '../services/permission.service';
import { ChangeDetectorRef } from '@angular/core';
import { QUEUE_MANAGER } from '../tokens/queue.token';
describe('PermissionDirective', () => {
@ -19,10 +19,23 @@ describe('PermissionDirective', () => {
});
beforeEach(() => {
spectator = createDirective('<div [abpPermission]="permission" [abpPermissionRunChangeDetection]="runCD"></div>', {
hostProps: { permission: 'test', runCD: false },
});
spectator = createDirective(
'<div [abpPermission]="permission" [abpPermissionRunChangeDetection]="runCD"></div>',
{
hostProps: { permission: 'test', runCD: false },
},
);
directive = spectator.directive;
grantedPolicy$.next(false);
spectator.detectChanges();
});
afterEach(() => {
// Clean up subscriptions to prevent errors after test completion
if (directive?.subscription) {
directive.subscription.unsubscribe();
}
grantedPolicy$.next(false);
});
it('should create directive', () => {
@ -30,14 +43,20 @@ describe('PermissionDirective', () => {
});
it('should handle permission input', () => {
spectator.setHostInput({ permission: 'new-permission' });
spectator.detectChanges();
grantedPolicy$.next(false);
directive.condition = 'new-permission';
directive.ngOnChanges();
grantedPolicy$.next(true);
expect(directive).toBeTruthy();
expect(directive.condition).toBe('new-permission');
});
it('should handle runChangeDetection input', () => {
spectator.setHostInput({ runCD: true });
spectator.detectChanges();
grantedPolicy$.next(false);
directive.runChangeDetection = true;
directive.ngOnChanges();
grantedPolicy$.next(true);
expect(directive).toBeTruthy();
expect(directive.runChangeDetection).toBe(true);
});
});

43
npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts

@ -2,14 +2,14 @@ import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
import { provideRouter, Route, Router } from '@angular/router';
import { RouterTestingHarness } from '@angular/router/testing';
import { TestBed } from '@angular/core/testing';
import { createSpyObject, SpyObject } from '@ngneat/spectator/vitest';
import { of } from 'rxjs';
import { permissionGuard } from '../guards/permission.guard';
import { HttpErrorReporterService } from '../services/http-error-reporter.service';
import { PermissionService } from '../services/permission.service';
import { provideAbpCore, withOptions } from '../providers';
import { TestBed } from '@angular/core/testing';
import { RouterTestingHarness } from '@angular/router/testing';
import { AuthService } from '../abstracts';
@Component({ template: '' })
@ -62,28 +62,37 @@ describe('authGuard', () => {
{ provide: PermissionService, useValue: permissionService },
{ provide: HttpErrorReporterService, useValue: httpErrorReporter },
provideRouter(routes),
provideAbpCore(withOptions({
environment: {
apis: {
default: {
provideAbpCore(
withOptions({
environment: {
apis: {
default: {
url: 'http://localhost:4200',
},
},
application: {
baseUrl: 'http://localhost:4200',
name: 'TestApp',
},
remoteEnv: {
url: 'http://localhost:4200',
mergeStrategy: 'deepmerge',
},
},
application: {
baseUrl: 'http://localhost:4200',
name: 'TestApp',
},
remoteEnv: {
url: 'http://localhost:4200',
mergeStrategy: 'deepmerge',
},
},
registerLocaleFn: () => Promise.resolve(),
})),
registerLocaleFn: () => Promise.resolve(),
skipGetAppConfiguration: true,
}),
),
],
});
});
afterEach(async () => {
// Wait for any pending async operations to complete before teardown
await new Promise(resolve => setTimeout(resolve, 0));
TestBed.resetTestingModule();
});
it('should return true when the grantedPolicy is true', async () => {
permissionService.getGrantedPolicy$.andReturn(of(true));
await RouterTestingHarness.create('/dummy');

23
npm/ng-packs/packages/core/src/lib/tests/projection.strategy.spec.ts

@ -73,7 +73,7 @@ describe('RootComponentProjectionStrategy', () => {
baz = 'baz';
}
@Component({
@Component({
template: '',
imports: [],
})
@ -208,9 +208,13 @@ describe('PROJECTION_STRATEGY', () => {
`(
'should successfully map $name to $Strategy.name with $domStrategy.name dom strategy',
({ name, Strategy, domStrategy }) => {
expect(PROJECTION_STRATEGY[name](content, context)).toEqual(
new Strategy(content, CONTEXT_STRATEGY.None(), domStrategy()),
);
const result = PROJECTION_STRATEGY[name](content, context);
const expected = new Strategy(content, CONTEXT_STRATEGY.None(), domStrategy());
expect(result).toBeInstanceOf(Strategy);
expect(result.content).toEqual(expected.content);
expect(result['contextStrategy']).toBeInstanceOf(expected['contextStrategy'].constructor);
expect(result['domStrategy'].position).toBe(expected['domStrategy'].position);
},
);
@ -239,9 +243,14 @@ describe('PROJECTION_STRATEGY', () => {
'should successfully map $name to $Strategy.name with $contextStrategy.name context strategy and $domStrategy.name dom strategy',
({ name, Strategy, domStrategy, contextStrategy }) => {
context = { x: true };
expect(PROJECTION_STRATEGY[name](content, context)).toEqual(
new Strategy(content, contextStrategy(context), domStrategy()),
);
const result = PROJECTION_STRATEGY[name](content, context);
const expected = new Strategy(content, contextStrategy(context), domStrategy());
expect(result).toBeInstanceOf(Strategy);
expect(result.content).toEqual(expected.content);
expect(result['contextStrategy']).toBeInstanceOf(expected['contextStrategy'].constructor);
expect(result['contextStrategy'].context).toEqual(expected['contextStrategy'].context);
expect(result['domStrategy'].position).toBe(expected['domStrategy'].position);
},
);
});

15
npm/ng-packs/packages/core/src/lib/tests/rest.service.spec.ts

@ -2,7 +2,6 @@ import { createHttpFactory, HttpMethod, SpectatorHttp, SpyObject } from '@ngneat
import { OAuthService } from 'angular-oauth2-oidc';
import { of, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { firstValueFrom } from 'rxjs';
import { Rest } from '../models/rest';
import { EnvironmentService } from '../services/environment.service';
import { HttpErrorReporterService } from '../services/http-error-reporter.service';
@ -75,13 +74,21 @@ describe('HttpClient testing', () => {
spectator.expectOne('bar' + '/test', HttpMethod.GET);
});
test('should complete upon successful request', done => {
const complete = vi.fn(done);
test('should complete upon successful request', async () => {
const request$ = spectator.service.request({ method: HttpMethod.GET, url: '/test' });
spectator.service.request({ method: HttpMethod.GET, url: '/test' }).subscribe({ complete });
// Create a promise that resolves when the observable completes
const completionPromise = new Promise<void>((resolve, reject) => {
request$.subscribe({
complete: () => resolve(),
error: err => reject(err),
});
});
const req = spectator.expectOne(api + '/test', HttpMethod.GET);
spectator.flushAll([req], [{}]);
await completionPromise;
});
test('should handle the error', () => {

84
npm/ng-packs/packages/core/src/lib/tests/show-password-directive.spec.ts

@ -1,55 +1,63 @@
import { Component, DebugElement } from '@angular/core'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { ShowPasswordDirective } from '../directives';
import { Component, DebugElement, ChangeDetectorRef } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ShowPasswordDirective } from '../directives';
@Component({
standalone:true,
template: `
<input [abpShowPassword]="true">
<input [abpShowPassword]="false">
<input />
<input [abpShowPassword]="showPassword" />`,
imports:[ShowPasswordDirective]
template: ` <input [abpShowPassword]="true" />
<input [abpShowPassword]="false" />
<input />
<input [abpShowPassword]="showPassword" />`,
imports: [ShowPasswordDirective],
})
class TestComponent {
showPassword = false
showPassword = false;
}
describe('ShowPasswordDirective',()=>{
let fixture: ComponentFixture<TestComponent>;;
let des : DebugElement[];
let desAll : DebugElement[];
describe('ShowPasswordDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let des: DebugElement[];
let desAll: DebugElement[];
let bareInput;
beforeEach(()=>{
beforeEach(() => {
fixture = TestBed.configureTestingModule({
imports: [ TestComponent ]
}).createComponent(TestComponent)
imports: [TestComponent],
}).createComponent(TestComponent);
fixture.detectChanges();
des = fixture.debugElement.queryAll(By.directive(ShowPasswordDirective));
desAll = fixture.debugElement.queryAll(By.all());
bareInput = fixture.debugElement.query(By.css('input:not([abpShowPassword])'));
})
it('should have three input has ShowPasswordDirective elements', () => {
expect(des.length).toBe(3);
});
test.each([[0,'text'],[1,'password'],[2,'text'],[3,'password']])('%p. input type must be %p)', (index,inpType) => {
const inputType = desAll[index].nativeElement.type;
expect(inputType).toBe(inpType);
});
it('should have three input has ShowPasswordDirective elements', () => {
const input = des[2].nativeElement
expect(input.type).toBe('password')
fixture.componentInstance.showPassword = true
fixture.detectChanges()
expect(input.type).toBe('text')
});
});
});
it('should have three input has ShowPasswordDirective elements', () => {
expect(des.length).toBe(3);
});
test.each([
[0, 'text'],
[1, 'password'],
[2, 'text'],
[3, 'password'],
])('%p. input type must be %p)', (index, inpType) => {
const inputType = desAll[index].nativeElement.type;
expect(inputType).toBe(inpType);
});
it('should toggle input type when showPassword changes', () => {
const input = des[2].nativeElement;
expect(input.type).toBe('password');
fixture.componentInstance.showPassword = true;
const cdr = fixture.componentRef.injector.get(ChangeDetectorRef);
cdr.markForCheck();
cdr.detectChanges();
expect(input.type).toBe('text');
});
});

3
npm/ng-packs/packages/core/src/lib/tests/stop-propagation.directive.spec.ts

@ -28,12 +28,11 @@ describe('StopPropagationDirective', () => {
expect(directive).toBeTruthy();
});
test('should not call click event of parent when child element is clicked', done => {
test('should not call click event of parent when child element is clicked', () => {
spectator.setHostInput({ parentClickEventFn, childClickEventFn });
spectator.click('a');
spectator.detectChanges();
expect(childClickEventFn).toHaveBeenCalled();
expect(parentClickEventFn).not.toHaveBeenCalled();
done();
});
});

11
npm/ng-packs/packages/core/src/test-setup.ts

@ -1,18 +1,11 @@
import 'zone.js';
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
// Initialize Angular testing environment
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting());
// Mock window.location for test environment
Object.defineProperty(window, 'location', {
value: {
href: 'http://localhost:4200',

Loading…
Cancel
Save