Skip to content

Commit

Permalink
Fix overriding HttpClient in DxHttpModule (T1248609) (#27932)
Browse files Browse the repository at this point in the history
  • Loading branch information
GoodDayForSurf authored Aug 28, 2024
1 parent 45256e0 commit 2b10a4c
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 10 deletions.
1 change: 1 addition & 0 deletions apps/demos/configs/Angular/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ window.config = {
/* devextreme-angular umd maps */
'devextreme-angular': 'bundles:devextreme-angular/devextreme-angular.umd.js',
'devextreme-angular/core': 'bundles:devextreme-angular/devextreme-angular-core.umd.js',
'devextreme-angular/http': 'bundles:devextreme-angular/devextreme-angular-http.umd.js',
...componentNames.reduce((acc, name) => {
acc[`devextreme-angular/ui/${name}`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}.umd.js`;
return acc;
Expand Down
13 changes: 7 additions & 6 deletions apps/demos/rollup.devextreme-angular.umd.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ const componentNames = fs.readdirSync(baseDir)
.map((fileName) => fileName.replace('.mjs.map', ''));

const inputs = {
'devextreme-angular-core': `${baseDir}devextreme-angular-core.mjs`,
'devextreme-angular': `${baseDir}devextreme-angular.mjs`,
...componentNames.reduce((acc, name) => {
acc[name] = `${baseDir}${name}.mjs`;
'devextreme-angular': `${baseDir}devextreme-angular.mjs`,
'devextreme-angular-core': `${baseDir}devextreme-angular-core.mjs`,
'devextreme-angular-http': `${baseDir}devextreme-angular-http.mjs`,
...componentNames.reduce((acc, name) => {
acc[name] = `${baseDir}${name}.mjs`;

return acc;
}, {}),
return acc;
}, {}),
};

const getLibName = (file) => file
Expand Down
15 changes: 11 additions & 4 deletions packages/devextreme-angular/src/http/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { NgModule } from '@angular/core';
import { NgModule, Injector, createNgModuleRef } from '@angular/core';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import devextremeAjax from 'devextreme/core/utils/ajax';
// eslint-disable-next-line import/named
import { sendRequestFactory } from './ajax';

@NgModule({
exports: [],
imports: [HttpClientModule],
imports: [],
providers: [],
})
export class DxHttpModule {
constructor(httpClient: HttpClient) {
constructor(injector: Injector) {
let httpClient: HttpClient = injector.get(HttpClient, null);

if (!httpClient) {
const moduleRef = createNgModuleRef(HttpClientModule, injector);

httpClient = moduleRef.injector.get(HttpClient);
}

devextremeAjax.inject({ sendRequest: sendRequestFactory(httpClient) });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import {
provideHttpClient,
withInterceptors,
HttpInterceptorFn,
HttpClient,
} from '@angular/common/http';
import { ApplicationRef, Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { DxHttpModule } from 'devextreme-angular/http';
import DataSource from 'devextreme/data/data_source';
import ODataStore from 'devextreme/data/odata/store';
import { throwError } from 'rxjs';

const TEST_URL = '';
const interceptors: Record<string, () => void> = {};

interceptors.interceptorFn = () => {};

const testInterceptorFn: HttpInterceptorFn = () => {
interceptors.interceptorFn();
return throwError(() => ({
status: 403,
statusText: 'Request intercepted. Access Denied',
}));
};

@Component({
standalone: true,
selector: 'test-app',
imports: [DxHttpModule],
template: '---',
})
class TestAppComponent {
constructor(private readonly httpClient: HttpClient) {}

fetchData() {
return this.httpClient.get(TEST_URL).toPromise();
}

loadDataSource() {
const dataSource = new DataSource({
store: new ODataStore({
version: 2,
url: TEST_URL,
}),
});

return dataSource.load() as Promise<unknown>;
}
}

describe('Using DxHttpModule in application with interceptors provided in bootstrapApplication() ', () => {
let httpTestingControllerMock: HttpTestingController;
let component: TestAppComponent;

beforeEach(async () => {
const testApp = document.createElement('test-app');

document.body.appendChild(testApp);

TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
});

const appRef = await bootstrapApplication(TestAppComponent, {
providers: [
provideHttpClient(withInterceptors([testInterceptorFn])),
{ provide: HttpClientTestingModule },
],
});

const applicationRef = appRef.injector.get(ApplicationRef);

component = applicationRef.components[0].instance as TestAppComponent;

httpTestingControllerMock = TestBed.inject(HttpTestingController);
});

afterEach(() => {
httpTestingControllerMock?.verify();
});

it('should call interceptors while calling httpClient directly ', (done) => {
const interceptorFnSpy = spyOn(interceptors, 'interceptorFn');

component
.fetchData()
.catch(() => {
expect(interceptorFnSpy).toHaveBeenCalledTimes(1);
done();
}).finally(() => {});
});

it('dataSource load() should be intercepted', (done) => {
const interceptorFnSpy = spyOn(interceptors, 'interceptorFn');

// eslint-disable-next-line no-void
void component.loadDataSource()
.catch(() => {
expect(interceptorFnSpy).toHaveBeenCalledTimes(1);
done();
});
});
});

0 comments on commit 2b10a4c

Please sign in to comment.