Browse Source

fix: UI tests in the theme shared package relating the ng v22 upgrade

pull/25729/head
sumeyye 3 months ago
parent
commit
c4c59f11e6
  1. 32
      npm/ng-packs/packages/theme-shared/src/lib/tests/button.component.spec.ts
  2. 22
      npm/ng-packs/packages/theme-shared/src/lib/tests/card-body.component.spec.ts
  3. 24
      npm/ng-packs/packages/theme-shared/src/lib/tests/card-footer.component.spec.ts
  4. 22
      npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.component.spec.ts
  5. 11
      npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.directive.spec.ts
  6. 18
      npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts
  7. 27
      npm/ng-packs/packages/theme-shared/src/lib/tests/ellipsis.directive.spec.ts
  8. 20
      npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts
  9. 22
      npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts
  10. 21
      npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts
  11. 7
      npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts

32
npm/ng-packs/packages/theme-shared/src/lib/tests/button.component.spec.ts

@ -1,19 +1,25 @@
import { ɵSIGNAL as SIGNAL } from '@angular/core';
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest';
import { ButtonComponent } from '../components'; import { ButtonComponent } from '../components';
const setInputSignal = <T>(inputSignal: () => T, value: T) => {
const node = inputSignal[SIGNAL];
node.applyValueToInputSignal(node, value);
};
describe('ButtonComponent', () => { describe('ButtonComponent', () => {
let spectator: SpectatorHost<ButtonComponent>; let spectator: SpectatorHost<ButtonComponent>;
const createHost = createHostFactory(ButtonComponent); const createHost = createHostFactory(ButtonComponent);
beforeEach( beforeEach(
() => () => {
(spectator = createHost( spectator = createHost('<abp-button>Button</abp-button>', {
'<abp-button iconClass="fa fa-check" [attributes]="attributes">Button</abp-button>', detectChanges: false,
{ });
hostProps: { attributes: { autofocus: '', name: 'abp-button' } }, setInputSignal(spectator.component.iconClass, 'fa fa-check');
}, spectator.detectChanges();
)), },
); );
it('should display the button', () => { it('should display the button', () => {
@ -48,23 +54,17 @@ describe('ButtonComponent', () => {
}); });
it('should display the spinner icon when loading input is true', () => { it('should display the spinner icon when loading input is true', () => {
spectator = createHost( setInputSignal(spectator.component.loading, true);
'<abp-button iconClass="fa fa-check" [loading]="loading">Button</abp-button>',
{ hostProps: { loading: true } },
);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('i')).toHaveClass('fa-spinner'); expect(spectator.query('i')).toHaveClass('fa-spinner');
}); });
it('should clear the spinner icon when loading input becomes false', () => { it('should clear the spinner icon when loading input becomes false', () => {
spectator = createHost( setInputSignal(spectator.component.loading, true);
'<abp-button iconClass="fa fa-check" [loading]="loading">Button</abp-button>',
{ hostProps: { loading: true } },
);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('i')).toHaveClass('fa-spinner'); expect(spectator.query('i')).toHaveClass('fa-spinner');
spectator.setHostInput({ loading: false }); setInputSignal(spectator.component.loading, false);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('i')).toHaveClass('fa-check'); expect(spectator.query('i')).toHaveClass('fa-check');
expect(spectator.query('i')).not.toHaveClass('fa-spinner'); expect(spectator.query('i')).not.toHaveClass('fa-spinner');

22
npm/ng-packs/packages/theme-shared/src/lib/tests/card-body.component.spec.ts

@ -1,5 +1,6 @@
import { createHostFactory, SpectatorHost } from '@ngneat/spectator'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator';
import { CardBodyComponent } from '../components'; import { CardBodyComponent } from '../components';
import { setInputSignal } from './utils';
describe('AbpCardBodyComponent', () => { describe('AbpCardBodyComponent', () => {
let spectator: SpectatorHost<CardBodyComponent>; let spectator: SpectatorHost<CardBodyComponent>;
@ -8,16 +9,17 @@ describe('AbpCardBodyComponent', () => {
beforeEach( beforeEach(
() => () =>
(spectator = createHost( {
` <abp-card-body spectator = createHost(
[cardBodyStyle]="{'background-color':'red'}" `<abp-card-body> <p>Body</p> </abp-card-body>`,
> {
<p>Body</p> detectChanges: false,
</abp-card-body>`, hostProps: { attributes: { autofocus: '', name: 'abp-card-body' } },
{ },
hostProps: { attributes: { autofocus: '', name: 'abp-card-body' } }, );
}, setInputSignal(spectator.component.cardBodyStyle, 'background-color: red;');
)), spectator.detectChanges();
},
); );
it('should create an instance', () => { it('should create an instance', () => {

24
npm/ng-packs/packages/theme-shared/src/lib/tests/card-footer.component.spec.ts

@ -1,5 +1,6 @@
import { createHostFactory, SpectatorHost } from '@ngneat/spectator'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator';
import { CardFooterComponent } from '../components'; import { CardFooterComponent } from '../components';
import { setInputSignal } from './utils';
describe('AbpCardFooterComponent', () => { describe('AbpCardFooterComponent', () => {
let spectator: SpectatorHost<CardFooterComponent>; let spectator: SpectatorHost<CardFooterComponent>;
@ -8,16 +9,19 @@ describe('AbpCardFooterComponent', () => {
beforeEach( beforeEach(
() => () =>
(spectator = createHost( {
`<abp-card-footer spectator = createHost(
[cardFooterStyle]="{'background-color':'red'}" `<abp-card-footer>
> <p>Footer</p>
<p>Footer</p> </abp-card-footer>`,
</abp-card-footer>`, {
{ detectChanges: false,
hostProps: { attributes: { autofocus: '', name: 'abp-card-footer' } }, hostProps: { attributes: { autofocus: '', name: 'abp-card-footer' } },
}, },
)), );
setInputSignal(spectator.component.cardFooterStyle, 'background-color: red;');
spectator.detectChanges();
},
); );
it('should create an instance', () => { it('should create an instance', () => {

22
npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.component.spec.ts

@ -1,5 +1,6 @@
import { createHostFactory, SpectatorHost } from '@ngneat/spectator'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator';
import { CardHeaderComponent } from '../components'; import { CardHeaderComponent } from '../components';
import { setInputSignal } from './utils';
describe('AbpCardHeaderComponent', () => { describe('AbpCardHeaderComponent', () => {
let spectator: SpectatorHost<CardHeaderComponent>; let spectator: SpectatorHost<CardHeaderComponent>;
@ -7,16 +8,17 @@ describe('AbpCardHeaderComponent', () => {
beforeEach( beforeEach(
() => () =>
(spectator = createHost( {
` <abp-card-header spectator = createHost(
[cardHeaderStyle]="{'background-color':'red'}" `<abp-card-header> Header </abp-card-header>`,
> {
Header detectChanges: false,
</abp-card-header>`, hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } },
{ },
hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } }, );
}, setInputSignal(spectator.component.cardHeaderStyle, 'background-color: red;');
)), spectator.detectChanges();
},
); );
it('should create an instance', () => { it('should create an instance', () => {

11
npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.directive.spec.ts

@ -7,15 +7,14 @@ describe('AbpCardHeaderDirective', () => {
const createHost = createHostFactory(CardHeaderDirective); const createHost = createHostFactory(CardHeaderDirective);
beforeEach( beforeEach(
() => () => {
(spectator = createHost( spectator = createHost(
`<div `<div abpCardHeader></div>`,
abpCardHeader>
</div>`,
{ {
hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } }, hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } },
}, },
)), );
},
); );
it('should create an instance', () => { it('should create an instance', () => {

18
npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts

@ -1,5 +1,6 @@
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest';
import { FormCheckboxComponent } from '../components/checkbox/checkbox.component'; import { FormCheckboxComponent } from '../components/checkbox/checkbox.component';
import { setInputSignal } from './utils';
describe('FormCheckboxComponent', () => { describe('FormCheckboxComponent', () => {
let spectator: SpectatorHost<FormCheckboxComponent>; let spectator: SpectatorHost<FormCheckboxComponent>;
@ -7,13 +8,18 @@ describe('FormCheckboxComponent', () => {
const createHost = createHostFactory(FormCheckboxComponent); const createHost = createHostFactory(FormCheckboxComponent);
beforeEach( beforeEach(
() => () => {
(spectator = createHost( spectator = createHost(
'<abp-checkbox></abp-checkbox>', '<abp-checkbox />',
{ {
detectChanges: false,
hostProps: { attributes: { autofocus: '', name: 'abp-checkbox' } }, hostProps: { attributes: { autofocus: '', name: 'abp-checkbox' } },
}, },
)), );
setInputSignal(spectator.component.checkboxId, 'checkbox-id');
setInputSignal(spectator.component.checkboxReadonly, true);
spectator.detectChanges();
},
); );
it('should display the input', () => { it('should display the input', () => {
@ -29,13 +35,13 @@ describe('FormCheckboxComponent', () => {
}); });
it('should be readonly when checkboxReadonly is true', () => { it('should be readonly when checkboxReadonly is true', () => {
spectator.component.checkboxReadonly = true; setInputSignal(spectator.component.checkboxReadonly, true);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('[readonly]')).toBeTruthy(); expect(spectator.query('[readonly]')).toBeTruthy();
}); });
it('should not contain readonly when checboxReadonly is false', () => { it('should not contain readonly when checboxReadonly is false', () => {
spectator.component.checkboxReadonly = false; setInputSignal(spectator.component.checkboxReadonly, false);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('[disabled]')).toBeFalsy(); expect(spectator.query('[disabled]')).toBeFalsy();
}); });

27
npm/ng-packs/packages/theme-shared/src/lib/tests/ellipsis.directive.spec.ts

@ -1,5 +1,6 @@
import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest'; import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest';
import { EllipsisDirective } from '../directives/ellipsis.directive'; import { EllipsisDirective } from '../directives/ellipsis.directive';
import { setInputSignal } from './utils';
describe('EllipsisDirective', () => { describe('EllipsisDirective', () => {
let spectator: SpectatorDirective<EllipsisDirective>; let spectator: SpectatorDirective<EllipsisDirective>;
@ -13,12 +14,13 @@ describe('EllipsisDirective', () => {
spectator = createDirective( spectator = createDirective(
'<div [abpEllipsis]="width" [abpEllipsisEnabled]="true" [title]="title">test content</div>', '<div [abpEllipsis]="width" [abpEllipsisEnabled]="true" [title]="title">test content</div>',
{ {
hostProps: { detectChanges: false,
title: 'test title',
width: '100px',
},
}, },
); );
setInputSignal(spectator.directive.width, '100px');
setInputSignal(spectator.directive.enabled, true);
setInputSignal(spectator.directive.title, 'title');
spectator.detectChanges();
directive = spectator.directive; directive = spectator.directive;
el = spectator.query('div'); el = spectator.query('div');
}); });
@ -28,15 +30,15 @@ describe('EllipsisDirective', () => {
}); });
test('should have 100px ellipsis width', () => { test('should have 100px ellipsis width', () => {
expect(directive.width).toBe('100px'); expect(directive.width()).toBe('100px');
}); });
test('should be enabled if abpEllipsisEnabled input is true', () => { test('should be enabled if abpEllipsisEnabled input is true', () => {
expect(directive.enabled).toBe(true); expect(directive.enabled()).toBe(true);
}); });
test('should have given title', () => { test('should have given title', () => {
expect(directive.title).toBe('test title'); expect(directive.title()).toBe('title');
}); });
test('should add abp-ellipsis-inline class to element if width is given', () => { test('should add abp-ellipsis-inline class to element if width is given', () => {
@ -48,6 +50,7 @@ describe('EllipsisDirective when title is not specified', () => {
let spectator: SpectatorDirective<EllipsisDirective>; let spectator: SpectatorDirective<EllipsisDirective>;
let directive: EllipsisDirective; let directive: EllipsisDirective;
let el: HTMLDivElement; let el: HTMLDivElement;
const createDirective = createDirectiveFactory({ const createDirective = createDirectiveFactory({
directive: EllipsisDirective, directive: EllipsisDirective,
}); });
@ -62,12 +65,16 @@ describe('EllipsisDirective when title is not specified', () => {
}, },
}, },
); );
setInputSignal(spectator.directive.width, '100px');
setInputSignal(spectator.directive.enabled, true);
setInputSignal(spectator.directive.title, undefined);
spectator.detectChanges();
directive = spectator.directive; directive = spectator.directive;
el = spectator.query('div') as HTMLDivElement; el = spectator.query('div') as HTMLDivElement;
}); });
test('should have element innerText as title', () => { test('should have element innerText as title', () => {
expect(directive.title).toBe(el.innerText); expect(directive.title()).toBe(el.innerText);
}); });
}); });
@ -89,6 +96,10 @@ describe('EllipsisDirective when width is not given', () => {
}, },
}, },
); );
setInputSignal(spectator.directive.width, undefined);
setInputSignal(spectator.directive.enabled, true);
setInputSignal(spectator.directive.title, 'test title');
spectator.detectChanges();
directive = spectator.directive; directive = spectator.directive;
el = spectator.query('div') as HTMLDivElement; el = spectator.query('div') as HTMLDivElement;
}); });

20
npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts

@ -1,5 +1,6 @@
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest';
import { FormInputComponent } from '../components/form-input/form-input.component'; import { FormInputComponent } from '../components/form-input/form-input.component';
import { setInputSignal } from './utils';
describe('FormInputComponent', () => { describe('FormInputComponent', () => {
@ -8,13 +9,14 @@ describe('FormInputComponent', () => {
const createHost = createHostFactory(FormInputComponent); const createHost = createHostFactory(FormInputComponent);
beforeEach( beforeEach(
() => () => {
(spectator = createHost( spectator = createHost(
'<abp-form-input></abp-form-input>', '<abp-form-input />',
{ {
hostProps: { attributes: { autofocus: '', name: 'abp-form-input' } }, hostProps: { attributes: { autofocus: '', name: 'abp-form-input' } },
}, },
)), );
},
); );
it('should display the input', () => { it('should display the input', () => {
@ -30,13 +32,13 @@ describe('FormInputComponent', () => {
}); });
it('should be readonly when inputReadonly is true', () => { it('should be readonly when inputReadonly is true', () => {
spectator.component.inputReadonly = true; setInputSignal(spectator.component.inputReadonly, true);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('[readonly]')).toBeTruthy(); expect(spectator.query('[readonly]')).toBeTruthy();
}); });
it('should not contain readonly when inputReadonly is false', () => { it('should not contain readonly when inputReadonly is false', () => {
spectator.component.inputReadonly = false; setInputSignal(spectator.component.inputReadonly, false);
spectator.detectComponentChanges(); spectator.detectComponentChanges();
expect(spectator.query('[disabled]')).toBeFalsy(); expect(spectator.query('[disabled]')).toBeFalsy();
}); });

22
npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts

@ -4,7 +4,8 @@ import { NavigationStart, Router } from '@angular/router';
import { createComponentFactory, Spectator } from '@ngneat/spectator/vitest'; import { createComponentFactory, Spectator } from '@ngneat/spectator/vitest';
import { combineLatest, firstValueFrom, Subject, timer } from 'rxjs'; import { combineLatest, firstValueFrom, Subject, timer } from 'rxjs';
import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component'; import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component';
import { setupComponentResources } from './utils'; import { setupComponentResources, setInputSignal } from './utils';
describe('LoaderBarComponent', () => { describe('LoaderBarComponent', () => {
let spectator: Spectator<LoaderBarComponent>; let spectator: Spectator<LoaderBarComponent>;
@ -34,8 +35,8 @@ describe('LoaderBarComponent', () => {
}); });
it('should initial variable values are correct', () => { it('should initial variable values are correct', () => {
expect(spectator.component.containerClass).toBe('abp-loader-bar'); expect(spectator.component.containerClass()).toBe('abp-loader-bar');
expect(spectator.component.color).toBe('#77b6ff'); expect(spectator.component.color()).toBe('#77b6ff');
}); });
it('should increase the progressLevel', async () => { it('should increase the progressLevel', async () => {
@ -45,8 +46,7 @@ describe('LoaderBarComponent', () => {
spectator.detectChanges(); spectator.detectChanges();
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
expect(spectator.component.progressLevel()).toBeGreaterThan(0);
expect(spectator.component.progressLevel > 0).toBeTruthy();
}); });
@ -100,15 +100,15 @@ describe('LoaderBarComponent', () => {
spectator.detectChanges(); spectator.detectChanges();
attempts = 0; attempts = 0;
while (spectator.component.progressLevel !== 100 && attempts < 50) { while (spectator.component.progressLevel() !== 100 && attempts < 50) {
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
spectator.detectChanges(); spectator.detectChanges();
attempts++; attempts++;
} }
expect(spectator.component.progressLevel).toBe(100); expect(spectator.component.progressLevel()).toBe(100);
await firstValueFrom(timer(spectator.component.stopDelay + 10)); await firstValueFrom(timer(spectator.component.stopDelay + 10));
expect(spectator.component.progressLevel).toBe(0); expect(spectator.component.progressLevel()).toBe(0);
}); });
it('should stop the loading with navigation', async () => { it('should stop the loading with navigation', async () => {
@ -130,15 +130,15 @@ describe('LoaderBarComponent', () => {
spectator.detectChanges(); spectator.detectChanges();
attempts = 0; attempts = 0;
while (spectator.component.progressLevel !== 100 && attempts < 50) { while (spectator.component.progressLevel() !== 100 && attempts < 50) {
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
spectator.detectChanges(); spectator.detectChanges();
attempts++; attempts++;
} }
expect(spectator.component.progressLevel).toBe(100); expect(spectator.component.progressLevel()).toBe(100);
await firstValueFrom(timer(spectator.component.stopDelay + 10)); await firstValueFrom(timer(spectator.component.stopDelay + 10));
expect(spectator.component.progressLevel).toBe(0); expect(spectator.component.progressLevel()).toBe(0);
}); });
describe('#startLoading', () => { describe('#startLoading', () => {

21
npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts

@ -1,7 +1,8 @@
import { Component } from '@angular/core';
import { SpectatorDirective, createDirectiveFactory } from '@ngneat/spectator/vitest'; import { SpectatorDirective, createDirectiveFactory } from '@ngneat/spectator/vitest';
import { LoadingDirective } from '../directives'; import { LoadingDirective } from '../directives';
import { LoadingComponent } from '../components'; import { LoadingComponent } from '../components';
import { Component } from '@angular/core'; import { setInputSignal } from './utils';
@Component({ @Component({
selector: 'abp-dummy', selector: 'abp-dummy',
@ -30,10 +31,10 @@ describe('LoadingDirective', () => {
}); });
it('should handle loading input', async () => { it('should handle loading input', async () => {
spectator.directive.loading = false; setInputSignal(spectator.directive.loading, false);
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
expect(spectator.directive).toBeTruthy(); expect(spectator.directive).toBeTruthy();
expect(spectator.directive.loading).toBe(false); expect(spectator.directive.loading()).toBe(false);
}); });
}); });
@ -42,11 +43,15 @@ describe('LoadingDirective', () => {
beforeEach(() => { beforeEach(() => {
spectator = createDirective( spectator = createDirective(
'<div [abpLoading]="loading" [abpLoadingDelay]="delay" [abpLoadingTargetElement]="target">Testing Loading Directive</div>', '<div abpLoading>Testing Loading Directive</div>',
{ {
hostProps: { loading: true, target: mockTarget, delay: 0 }, detectChanges: false,
}, },
); );
setInputSignal(spectator.directive.loading, true);
setInputSignal(spectator.directive.delay, 0);
setInputSignal(spectator.directive.targetElementInput, mockTarget);
spectator.detectChanges();
}); });
it('should create directive with custom target', () => { it('should create directive with custom target', () => {
@ -55,17 +60,17 @@ describe('LoadingDirective', () => {
}); });
it('should handle delay input', async () => { it('should handle delay input', async () => {
spectator.directive.delay = 100; setInputSignal(spectator.directive.delay, 100);
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
expect(spectator.directive).toBeTruthy(); expect(spectator.directive).toBeTruthy();
}); });
it('should handle loading state changes', async() => { it('should handle loading state changes', async() => {
spectator.directive.loading = false; setInputSignal(spectator.directive.loading, false);
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
expect(spectator.directive).toBeTruthy(); expect(spectator.directive).toBeTruthy();
spectator.directive.loading = true; setInputSignal(spectator.directive.loading, true);
await new Promise(resolve => setTimeout(resolve, 10)); await new Promise(resolve => setTimeout(resolve, 10));
expect(spectator.directive).toBeTruthy(); expect(spectator.directive).toBeTruthy();
}); });

7
npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts

@ -8,10 +8,13 @@ import { ToasterService } from '../services/toaster.service';
describe('ToasterService', () => { describe('ToasterService', () => {
let spectator: SpectatorService<ToasterService>; let spectator: SpectatorService<ToasterService>;
let service: ToasterService; let service: ToasterService;
const mockComponentRef = { const mockComponentRef = {
changeDetectorRef: { detectChanges: vi.fn() }, changeDetectorRef: { detectChanges: vi.fn() },
instance: {} as ToastContainerComponent, instance: {
} as unknown as ComponentRef<ToastContainerComponent>; setToasts: vi.fn(), remove: vi.fn(), toasts: [], top: 0, right: 0, bottom: 0, left: 0,
},
};
const contentProjectionService = { const contentProjectionService = {
projectContent: vi.fn().mockReturnValue(mockComponentRef), projectContent: vi.fn().mockReturnValue(mockComponentRef),

Loading…
Cancel
Save