@@ -54,6 +54,8 @@ export async function render<SutType, WrapperType = SutType>(
5454 queries,
5555 wrapper = WrapperComponent as Type < WrapperType > ,
5656 componentProperties = { } ,
57+ componentInputs = { } ,
58+ componentOutputs = { } ,
5759 componentProviders = [ ] ,
5860 componentImports : componentImports ,
5961 excludeComponentDeclaration = false ,
@@ -102,25 +104,51 @@ export async function render<SutType, WrapperType = SutType>(
102104
103105 if ( typeof router ?. initialNavigation === 'function' ) {
104106 if ( zone ) {
105- zone . run ( ( ) => router ? .initialNavigation ( ) ) ;
107+ zone . run ( ( ) => router . initialNavigation ( ) ) ;
106108 } else {
107- router ? .initialNavigation ( ) ;
109+ router . initialNavigation ( ) ;
108110 }
109111 }
110112
111113 let fixture : ComponentFixture < SutType > ;
112114 let detectChanges : ( ) => void ;
113115
114- await renderFixture ( componentProperties ) ;
116+ await renderFixture ( componentProperties , componentInputs , componentOutputs ) ;
115117
116- const rerender = async ( rerenderedProperties : Partial < SutType > ) => {
117- await renderFixture ( rerenderedProperties ) ;
118+ const rerender = async (
119+ properties ?: Pick < RenderTemplateOptions < SutType > , 'componentProperties' | 'componentInputs' | 'componentOutputs' > ,
120+ ) => {
121+ await renderFixture (
122+ properties ?. componentProperties ?? { } ,
123+ properties ?. componentInputs ?? { } ,
124+ properties ?. componentOutputs ?? { } ,
125+ ) ;
126+ } ;
127+
128+ const changeInput = ( changedInputProperties : Partial < SutType > ) => {
129+ if ( Object . keys ( changedInputProperties ) . length === 0 ) {
130+ return ;
131+ }
132+
133+ const changes = getChangesObj ( fixture . componentInstance as Record < string , any > , changedInputProperties ) ;
134+
135+ setComponentInputs ( fixture , changedInputProperties ) ;
136+
137+ if ( hasOnChangesHook ( fixture . componentInstance ) ) {
138+ fixture . componentInstance . ngOnChanges ( changes ) ;
139+ }
140+
141+ fixture . componentRef . injector . get ( ChangeDetectorRef ) . detectChanges ( ) ;
118142 } ;
119143
120144 const change = ( changedProperties : Partial < SutType > ) => {
145+ if ( Object . keys ( changedProperties ) . length === 0 ) {
146+ return ;
147+ }
148+
121149 const changes = getChangesObj ( fixture . componentInstance as Record < string , any > , changedProperties ) ;
122150
123- setComponentProperties ( fixture , { componentProperties : changedProperties } ) ;
151+ setComponentProperties ( fixture , changedProperties ) ;
124152
125153 if ( hasOnChangesHook ( fixture . componentInstance ) ) {
126154 fixture . componentInstance . ngOnChanges ( changes ) ;
@@ -176,6 +204,7 @@ export async function render<SutType, WrapperType = SutType>(
176204 navigate,
177205 rerender,
178206 change,
207+ changeInput,
179208 // @ts -ignore: fixture assigned
180209 debugElement : fixture . debugElement ,
181210 // @ts -ignore: fixture assigned
@@ -188,13 +217,16 @@ export async function render<SutType, WrapperType = SutType>(
188217 ...replaceFindWithFindAndDetectChanges ( dtlGetQueriesForElement ( fixture . nativeElement , queries ) ) ,
189218 } ;
190219
191- async function renderFixture ( properties : Partial < SutType > ) {
220+ async function renderFixture ( properties : Partial < SutType > , inputs : Partial < SutType > , outputs : Partial < SutType > ) {
192221 if ( fixture ) {
193222 cleanupAtFixture ( fixture ) ;
194223 }
195224
196225 fixture = await createComponent ( componentContainer ) ;
197- setComponentProperties ( fixture , { componentProperties : properties } ) ;
226+
227+ setComponentProperties ( fixture , properties ) ;
228+ setComponentInputs ( fixture , inputs ) ;
229+ setComponentOutputs ( fixture , outputs ) ;
198230
199231 if ( removeAngularAttributes ) {
200232 fixture . nativeElement . removeAttribute ( 'ng-version' ) ;
@@ -244,7 +276,7 @@ function createComponentFixture<SutType, WrapperType>(
244276
245277function setComponentProperties < SutType > (
246278 fixture : ComponentFixture < SutType > ,
247- { componentProperties = { } } : Pick < RenderTemplateOptions < SutType , any > , 'componentProperties' > ,
279+ componentProperties : RenderTemplateOptions < SutType , any > [ 'componentProperties' ] = { } ,
248280) {
249281 for ( const key of Object . keys ( componentProperties ) ) {
250282 const descriptor = Object . getOwnPropertyDescriptor ( ( fixture . componentInstance as any ) . constructor . prototype , key ) ;
@@ -270,6 +302,24 @@ function setComponentProperties<SutType>(
270302 return fixture ;
271303}
272304
305+ function setComponentOutputs < SutType > (
306+ fixture : ComponentFixture < SutType > ,
307+ componentOutputs : RenderTemplateOptions < SutType , any > [ 'componentOutputs' ] = { } ,
308+ ) {
309+ for ( const [ name , value ] of Object . entries ( componentOutputs ) ) {
310+ ( fixture . componentInstance as any ) [ name ] = value ;
311+ }
312+ }
313+
314+ function setComponentInputs < SutType > (
315+ fixture : ComponentFixture < SutType > ,
316+ componentInputs : RenderTemplateOptions < SutType > [ 'componentInputs' ] = { } ,
317+ ) {
318+ for ( const [ name , value ] of Object . entries ( componentInputs ) ) {
319+ fixture . componentRef . setInput ( name , value ) ;
320+ }
321+ }
322+
273323function overrideComponentImports < SutType > ( sut : Type < SutType > | string , imports : ( Type < any > | any [ ] ) [ ] | undefined ) {
274324 if ( imports ) {
275325 if ( typeof sut === 'function' && ɵisStandalone ( sut ) ) {
0 commit comments