@openmrs/esm-form-entry-app 11.3.1-pre.9637 → 11.3.1-pre.9641

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11644,12 +11644,12 @@
11644
11644
  ],
11645
11645
  "files": [
11646
11646
  "main.c9fedbf76d90aec0.css",
11647
- "main.4fe416d153a1af95.js"
11647
+ "main.9dec6586faceb3d4.js"
11648
11648
  ],
11649
11649
  "auxiliaryFiles": [
11650
- "main.4fe416d153a1af95.js.map"
11650
+ "main.9dec6586faceb3d4.js.map"
11651
11651
  ],
11652
- "hash": "6f7e3a38ca3f152b",
11652
+ "hash": "efb1b8777777bb4a",
11653
11653
  "childrenByOrder": {}
11654
11654
  },
11655
11655
  {
@@ -15024,7 +15024,7 @@
15024
15024
  "auxiliaryFiles": [
15025
15025
  "openmrs-esm-form-entry-app.js.map"
15026
15026
  ],
15027
- "hash": "ecce7d49aa42f315",
15027
+ "hash": "da3cb6338fc8aefd",
15028
15028
  "childrenByOrder": {}
15029
15029
  },
15030
15030
  {
@@ -27367,9 +27367,9 @@
27367
27367
  "initial": false,
27368
27368
  "entry": false,
27369
27369
  "recorded": false,
27370
- "size": 6078284,
27370
+ "size": 6078801,
27371
27371
  "sizes": {
27372
- "javascript": 6078284
27372
+ "javascript": 6078801
27373
27373
  },
27374
27374
  "names": [
27375
27375
  "bootstrap"
@@ -27380,12 +27380,12 @@
27380
27380
  "main"
27381
27381
  ],
27382
27382
  "files": [
27383
- "89284.d15c283f899702d9.js"
27383
+ "89284.5a048e2e15df1801.js"
27384
27384
  ],
27385
27385
  "auxiliaryFiles": [
27386
- "89284.d15c283f899702d9.js.map"
27386
+ "89284.5a048e2e15df1801.js.map"
27387
27387
  ],
27388
- "hash": "f5687c0b08d45774",
27388
+ "hash": "c626c407e8880337",
27389
27389
  "childrenByOrder": {}
27390
27390
  },
27391
27391
  {
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":">=2.2.0","o3forms":"*"},"extensions":[{"name":"form-widget","component":"formWidget","slot":"form-widget-slot","online":true,"offline":true}],"version":"11.3.1-pre.9637"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":">=2.2.0","o3forms":"*"},"extensions":[{"name":"form-widget","component":"formWidget","slot":"form-widget-slot","online":true,"offline":true}],"version":"11.3.1-pre.9641"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-form-entry-app",
3
- "version": "11.3.1-pre.9637",
3
+ "version": "11.3.1-pre.9641",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Angular form engine for O3",
6
6
  "browser": "dist/openmrs-esm-form-entry-app.js",
@@ -36,18 +36,59 @@ describe('Service: FormDataSourceService', () => {
36
36
  expect(service).toBeTruthy();
37
37
  });
38
38
 
39
- it('should find for provider by search text', (done) => {
39
+ it('should find providers by search text after 300ms delay', fakeAsync(() => {
40
40
  const service: FormDataSourceService = TestBed.get(FormDataSourceService);
41
- const result = service.findProvider('text');
41
+ let actualResults: any[];
42
42
 
43
- result.subscribe((results) => {
44
- expect(results).toBeTruthy();
45
- expect(results.length).toBeGreaterThan(0);
46
- expect(results[0].value).toEqual('uuid');
43
+ service.findProvider('text').subscribe((results) => {
44
+ actualResults = results;
45
+ });
46
+
47
+ tick(300); // advance past the timer delay
48
+
49
+ expect(actualResults).toBeTruthy();
50
+ expect(actualResults.length).toBeGreaterThan(0);
51
+ expect(actualResults[0].value).toEqual('uuid');
52
+ }));
53
+
54
+ it('should return empty array for empty or whitespace search text', (done) => {
55
+ const service: FormDataSourceService = TestBed.get(FormDataSourceService);
56
+
57
+ service.findProvider('').subscribe((results) => {
58
+ expect(results).toEqual([]);
47
59
  done();
48
60
  });
49
61
  });
50
62
 
63
+ it('should return independent observables for each search', fakeAsync(() => {
64
+ const service: FormDataSourceService = TestBed.get(FormDataSourceService);
65
+ const providerResourceService = TestBed.get(ProviderResourceService);
66
+ const searchSpy = spyOn(providerResourceService, 'searchProvider').and.callThrough();
67
+
68
+ let firstResults: any[];
69
+ let secondResults: any[];
70
+
71
+ // Two independent searches - each gets its own observable
72
+ service.findProvider('first').subscribe((results) => {
73
+ firstResults = results;
74
+ });
75
+
76
+ service.findProvider('second').subscribe((results) => {
77
+ secondResults = results;
78
+ });
79
+
80
+ tick(300);
81
+
82
+ // Each call triggers its own API request (isolation maintained)
83
+ expect(searchSpy).toHaveBeenCalledTimes(2);
84
+ expect(searchSpy).toHaveBeenCalledWith('first');
85
+ expect(searchSpy).toHaveBeenCalledWith('second');
86
+
87
+ // Both should have results
88
+ expect(firstResults).toBeTruthy();
89
+ expect(secondResults).toBeTruthy();
90
+ }));
91
+
51
92
  it(
52
93
  'should find provider when getProviderByProviderUuid is called' + ' with a provider uuid',
53
94
  inject(
@@ -1,7 +1,7 @@
1
1
  import { Injectable } from '@angular/core';
2
2
 
3
- import { take, map, tap } from 'rxjs/operators';
4
- import { Observable, Subject } from 'rxjs';
3
+ import { take, map, tap, switchMap } from 'rxjs/operators';
4
+ import { Observable, Subject, of, timer } from 'rxjs';
5
5
 
6
6
  import { FetchResponse, fhirBaseUrl, FHIRResource, openmrsFetch } from '@openmrs/esm-framework';
7
7
 
@@ -136,10 +136,23 @@ export class FormDataSourceService {
136
136
  }
137
137
  }
138
138
 
139
- public findProvider(searchText): Observable<any[]> {
140
- return this.providerResourceService.searchProvider(searchText).pipe(
141
- map((providers) => providers.filter((p) => !!p.person).map(this.mapProvider)),
142
- tap((result) => this.setCachedProviderSearchResults(result)),
139
+ public findProvider(searchText: string): Observable<any[]> {
140
+ const trimmedSearchText = searchText?.trim() ?? '';
141
+
142
+ if (!trimmedSearchText) {
143
+ return of([]);
144
+ }
145
+
146
+ // Return a cold observable with 300ms delay
147
+ // Each call gets its own independent observable
148
+ // The component's switchMap cancels previous subscriptions for true debouncing
149
+ return timer(300).pipe(
150
+ switchMap(() =>
151
+ this.providerResourceService.searchProvider(trimmedSearchText).pipe(
152
+ map((providers) => providers.filter((provider) => !!provider.person).map(this.mapProvider)),
153
+ tap((result) => this.setCachedProviderSearchResults(result)),
154
+ ),
155
+ ),
143
156
  );
144
157
  }
145
158
 
@@ -45,24 +45,27 @@ describe('Service : ProviderResourceService Unit Tests', () => {
45
45
  const results = {
46
46
  results: [
47
47
  {
48
- uuid: 'uuid',
49
- display: 'test',
48
+ uuid: 'uuid-1',
49
+ display: 'test provider',
50
50
  },
51
51
  {
52
- uuid: 'uuid',
53
- display: 'other',
52
+ uuid: 'uuid-2',
53
+ display: 'another test provider',
54
54
  },
55
55
  ],
56
56
  };
57
57
 
58
58
  providerResourceService.searchProvider(searchText).subscribe((providers) => {
59
- for (const provider of providers) {
60
- expect(provider.display).toContain('test');
61
- }
59
+ expect(providers.length).toBe(2);
60
+ expect(providers[0].display).toBe('test provider');
61
+ expect(providers[1].display).toBe('another test provider');
62
62
  done();
63
63
  });
64
64
 
65
- const req = httpMock.expectOne(providerResourceService.getUrl());
65
+ const req = httpMock.expectOne((request) => {
66
+ return request.url.includes('provider') && request.params.get('q') === searchText;
67
+ });
68
+ expect(req.request.method).toBe('GET');
66
69
  req.flush(results);
67
70
  });
68
71
  });
@@ -1,8 +1,8 @@
1
1
  import { Injectable } from '@angular/core';
2
2
  import { HttpParams, HttpClient } from '@angular/common/http';
3
3
 
4
- import { Observable, ReplaySubject, of } from 'rxjs';
5
- import { take, map, catchError } from 'rxjs/operators';
4
+ import { Observable } from 'rxjs';
5
+ import { map, catchError } from 'rxjs/operators';
6
6
 
7
7
  import { PersonResourceService } from './person-resource.service';
8
8
  import { WindowRef } from '../window-ref';
@@ -19,11 +19,10 @@ export class ProviderResourceService {
19
19
  ) {}
20
20
 
21
21
  public searchProvider(searchText: string): Observable<Array<Provider>> {
22
- return this.getAllProviders().pipe(
23
- map((providers) =>
24
- providers.filter((provider) => provider.display.toLowerCase().includes(searchText.toLowerCase())),
25
- ),
26
- );
22
+ const params = new HttpParams().set('q', searchText);
23
+ const url = this.windowRef.openmrsRestBase + 'provider?v=' + ProviderResourceService.v;
24
+
25
+ return this.http.get<ListResult<Provider>>(url, { params }).pipe(map((r) => r.results));
27
26
  }
28
27
 
29
28
  public getProviderByUuid(uuid: string): Observable<Provider | undefined> {
@@ -36,13 +35,13 @@ export class ProviderResourceService {
36
35
  }
37
36
 
38
37
  private getAllProviders(): Observable<Array<Provider>> {
39
- const url = this.windowRef.openmrsRestBase + 'provider?q=&v=' + ProviderResourceService.v;
38
+ const url = this.windowRef.openmrsRestBase + 'provider?v=' + ProviderResourceService.v;
40
39
  return this.http.get<ListResult<Provider>>(url).pipe(map((r) => r.results));
41
40
  }
42
41
 
43
42
  public getUrl(uuid?: string) {
44
43
  return uuid
45
44
  ? this.windowRef.openmrsRestBase + 'provider/' + uuid + '?v=' + ProviderResourceService.v
46
- : this.windowRef.openmrsRestBase + 'provider?q=&v=' + ProviderResourceService.v;
45
+ : this.windowRef.openmrsRestBase + 'provider?v=' + ProviderResourceService.v;
47
46
  }
48
47
  }