Reputation: 711
I'm not able to set up my testing-library integration tests so they recognize the global interface with the third party static methods from my component library Preline UI
I'm using JSDOM and angular-testing-library
, but I don't know how I can get autoInit()
to fire and keep getting an error that the test cannot find HSStaticMethods
, which means the internal functionality is not being loaded and I can not test if their components actually integrate with my app!
declare global {
interface Window {
HSStaticMethods: IStaticMethods;
}
}
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-component',
templateUrl: './app.component.html',
standalone: true,
})
export class AppComponent implements OnInit {
private readonly router = inject(Router);
public ngOnInit(): void {
this.router.events.subscribe((event: Event) => {
if (event instanceof NavigationEnd) {
setTimeout(() => {
// https://www.preline.co/docs/frameworks-angular.html
window.HSStaticMethods.autoInit();
}, 100);
}
});
}
I've tried
declare global
to test-setup.ts
and the test itselfjest.config.ts
:export default {
moduleNameMapper: {
preline: 'node_modules/preline/dist/preline.js', // added this
}
}
My tsconfig.spec.json
:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node", "@testing-library/jest-dom", "preline"] // added the lib just in case?
},
"files": ["src/test-setup.ts"],
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
And here's the actual integration test:
import { signal } from '@angular/core';
import type { RouterEvent } from '@angular/router';
import { NavigationEnd, Router } from '@angular/router';
import type { IUser } from '@front-and-workspace/projects/grip-clone';
import { render } from '@testing-library/angular';
import { screen } from '@testing-library/dom';
import userEvent from '@testing-library/user-event';
import type { IStaticMethods } from 'preline';
import { BehaviorSubject } from 'rxjs';
import { AppComponent } from './app.component';
import { AuthService } from './auth/auth.service';
// I got desperate and started adding this everywhere :(
declare global {
interface Window {
// eslint-disable-next-line @typescript-eslint/naming-convention
HSStaticMethods: IStaticMethods;
}
}
jest.useFakeTimers(); // Jest timer so I can control when the setTimeout goes off
it('should open the Preline dropdown', async () => {
const user = userEvent.setup();
const mockEvents$ = new BehaviorSubject<null | RouterEvent>(null);
const { fixture } = await render(AppComponent, {
providers: [
{
provide: Router,
useValue: {
events: mockEvents$,
routerState: { root: '' },
createUrlTree: jest.fn(),
serializeUrl: jest.fn().mockReturnValue(''),
},
},
],
});
mockEvents$.next(new NavigationEnd(0, '', ''));
jest.runAllTimers(); // ERROR: TypeError: Cannot read properties of undefined (reading 'autoInit')
let themeToggleDropdownContainer = screen.getByTestId(
'front-and-workspace-theme-toggle-dropdown-container',
);
expect(themeToggleDropdownContainer.className).toBe('hs-dropdown');
await user.click(
screen.getByTestId('front-and-workspace-theme-toggle-button'),
);
themeToggleDropdownContainer = screen.getByTestId(
'front-and-workspace-theme-toggle-dropdown-container',
);
fixture.detectChanges();
//Check if drop-down was opened
expect(themeToggleDropdownContainer.className).toBe('hs-dropdown open');
});
Upvotes: 0
Views: 19
Reputation: 711
The solution was to import 'preline' in my test-setup.ts
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/jest-globals';
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
import 'preline'; // this
setupZoneTestEnv();
And finally override window.matchMedia
in the test itself. Here is the final integration test:
import { provideRouter } from '@angular/router';
import { render } from '@testing-library/angular';
import { screen } from '@testing-library/dom';
import userEvent from '@testing-library/user-event';
import { AppComponent } from './app.component';
beforeAll(() => {
Object.defineProperty(window, 'matchMedia', {
value: jest.fn().mockImplementation(() => ({})),
});
});
it('should open the Preline dropdown', async () => {
const user = userEvent.setup();
await render(AppComponent, {
providers: [provideRouter([])],
});
let themeToggleDropdownContainer = screen.getByTestId(
'theme-toggle-dropdown-container',
);
expect(themeToggleDropdownContainer.className).toBe('hs-dropdown');
await user.click(screen.getByTestId('theme-toggle-button'));
themeToggleDropdownContainer = screen.getByTestId(
'theme-toggle-dropdown-container',
);
expect(themeToggleDropdownContainer.className).toBe('hs-dropdown open');
});
Upvotes: 0