1+ import React from 'react' ;
2+ import { screen } from '@testing-library/react' ;
3+
4+ import UnitHistory from '../../src/components/UnitHistory' ;
5+ import { renderWithRoute } from '../testUtils' ;
6+ import * as actions from '../../src/actions/index' ;
7+
8+ // Mock the actions
9+ jest . mock ( '../../src/actions/index' , ( ) => ( {
10+ fetchUnitObservations : jest . fn ( )
11+ } ) ) ;
12+
13+ const mockFetchUnitObservations = actions . fetchUnitObservations as jest . MockedFunction < typeof actions . fetchUnitObservations > ;
14+
15+ const mockUnit = {
16+ id : 123 ,
17+ name : { fi : 'Test Unit' } ,
18+ services : [ 1 , 2 ]
19+ } ;
20+
21+ const mockObservations = [
22+ {
23+ id : 1 ,
24+ unit : 123 ,
25+ property : 'test_property_1' ,
26+ time : '2024-01-01T12:00:00Z' ,
27+ expiration_time : null ,
28+ name : { fi : 'Test Property 1' } ,
29+ quality : 'good' ,
30+ value : 'test_value_1' ,
31+ primary : true
32+ } ,
33+ {
34+ id : 2 ,
35+ unit : 123 ,
36+ property : 'test_property_2' ,
37+ time : '2024-01-02T12:00:00Z' ,
38+ expiration_time : null ,
39+ name : { fi : 'Test Property 2' } ,
40+ quality : 'good' ,
41+ value : 'test_value_2' ,
42+ primary : false
43+ }
44+ ] ;
45+
46+ const defaultState = {
47+ data : {
48+ unit : { 123 : mockUnit } ,
49+ observation : {
50+ 1 : mockObservations [ 0 ] ,
51+ 2 : mockObservations [ 1 ]
52+ } ,
53+ unitsByDistance : [ ] ,
54+ observable_property : { } ,
55+ service : { } ,
56+ loading : { }
57+ } ,
58+ auth : {
59+ token : null ,
60+ maintenance_organization : 'test-org' ,
61+ login_id : null
62+ } ,
63+ authError : null ,
64+ updateQueue : { } ,
65+ updateFlush : false ,
66+ serviceGroup : 'skiing' ,
67+ userLocation : null ,
68+ unitsByUpdateTime : [ ] ,
69+ unitsByUpdateCount : { } ,
70+ selectedUnits : [ ] ,
71+ observationsByPropertyByUnit : { } ,
72+ allowedValuesByProperty : { } ,
73+ massEdit : {
74+ selectedUnits : [ ] ,
75+ isEditing : false ,
76+ property : null ,
77+ value : null
78+ }
79+ } ;
80+
81+ const renderComponent = ( unitId = '123' , initialState = defaultState ) => {
82+ return renderWithRoute ( < UnitHistory /> , {
83+ route : `/unit/${ unitId } /history` ,
84+ path : '/unit/:unitId/history' ,
85+ initialState
86+ } ) ;
87+ } ;
88+
89+ describe ( 'UnitHistory' , ( ) => {
90+ beforeEach ( ( ) => {
91+ mockFetchUnitObservations . mockClear ( ) ;
92+ mockFetchUnitObservations . mockReturnValue ( { type : 'FETCH_UNIT_OBSERVATIONS' } ) ;
93+ } ) ;
94+
95+ it ( 'renders loading state when unit is undefined' , ( ) => {
96+ const stateWithoutUnit = {
97+ ...defaultState ,
98+ data : {
99+ ...defaultState . data ,
100+ unit : { }
101+ }
102+ } ;
103+
104+ renderComponent ( '123' , stateWithoutUnit ) ;
105+ expect ( screen . getByText ( 'Ladataan...' ) ) . toBeInTheDocument ( ) ;
106+ } ) ;
107+
108+ it ( 'renders unit name and back link when unit is loaded' , ( ) => {
109+ renderComponent ( ) ;
110+
111+ expect ( screen . getByText ( 'Test Unit' ) ) . toBeInTheDocument ( ) ;
112+ expect ( screen . getByText ( 'Takaisin' ) ) . toBeInTheDocument ( ) ;
113+
114+ const backLink = screen . getByRole ( 'link' , { name : / t a k a i s i n / i } ) ;
115+ expect ( backLink ) . toHaveAttribute ( 'href' , '/unit/123' ) ;
116+ } ) ;
117+
118+ it ( 'dispatches fetchUnitObservations on component mount' , ( ) => {
119+ renderComponent ( ) ;
120+
121+ expect ( mockFetchUnitObservations ) . toHaveBeenCalledWith ( '123' ) ;
122+ expect ( mockFetchUnitObservations ) . toHaveBeenCalledTimes ( 1 ) ;
123+ } ) ;
124+
125+ it ( 'renders observations when they exist' , ( ) => {
126+ renderComponent ( ) ;
127+
128+ expect ( screen . getByText ( 'Historia' ) ) . toBeInTheDocument ( ) ;
129+ // Check that observation components are rendered (they contain the property names)
130+ expect ( screen . getByText ( 'Test Property 1' ) ) . toBeInTheDocument ( ) ;
131+ expect ( screen . getByText ( 'Test Property 2' ) ) . toBeInTheDocument ( ) ;
132+ } ) ;
133+
134+ it ( 'renders "no history" message when observations are empty' , ( ) => {
135+ const stateWithoutObservations = {
136+ ...defaultState ,
137+ data : {
138+ ...defaultState . data ,
139+ observation : { }
140+ }
141+ } ;
142+
143+ renderComponent ( '123' , stateWithoutObservations ) ;
144+
145+ expect ( screen . getByText ( 'Historia' ) ) . toBeInTheDocument ( ) ;
146+ expect ( screen . getByText ( 'Ei historiatietoja' ) ) . toBeInTheDocument ( ) ;
147+ expect ( screen . queryByText ( 'Test Property' ) ) . not . toBeInTheDocument ( ) ;
148+ } ) ;
149+
150+ it ( 'filters observations by unit id' , ( ) => {
151+ const stateWithMultipleObservations = {
152+ ...defaultState ,
153+ data : {
154+ ...defaultState . data ,
155+ observation : {
156+ 1 : { ...mockObservations [ 0 ] , unit : 123 } ,
157+ 2 : { ...mockObservations [ 1 ] , unit : 123 } ,
158+ 3 : {
159+ id : 3 ,
160+ unit : 456 ,
161+ property : 'other_property' ,
162+ time : '2024-01-03T12:00:00Z' ,
163+ expiration_time : null ,
164+ name : { fi : 'Other Property' } ,
165+ quality : 'good' ,
166+ value : 'other_value' ,
167+ primary : false
168+ }
169+ }
170+ }
171+ } ;
172+
173+ renderComponent ( '123' , stateWithMultipleObservations ) ;
174+
175+ expect ( screen . getByText ( 'Test Property 1' ) ) . toBeInTheDocument ( ) ;
176+ expect ( screen . getByText ( 'Test Property 2' ) ) . toBeInTheDocument ( ) ;
177+ expect ( screen . queryByText ( 'Other Property' ) ) . not . toBeInTheDocument ( ) ;
178+ } ) ;
179+
180+ it ( 'handles different unit ids correctly' , ( ) => {
181+ const stateWithDifferentUnit = {
182+ ...defaultState ,
183+ data : {
184+ ...defaultState . data ,
185+ unit : { 456 : { ...mockUnit , id : 456 , name : { fi : 'Different Unit' } } } ,
186+ observation : {
187+ 3 : { ...mockObservations [ 0 ] , id : 3 , unit : 456 }
188+ }
189+ }
190+ } ;
191+
192+ renderComponent ( '456' , stateWithDifferentUnit ) ;
193+
194+ expect ( screen . getByText ( 'Different Unit' ) ) . toBeInTheDocument ( ) ;
195+ expect ( mockFetchUnitObservations ) . toHaveBeenCalledWith ( '456' ) ;
196+
197+ const backLink = screen . getByRole ( 'link' , { name : / t a k a i s i n / i } ) ;
198+ expect ( backLink ) . toHaveAttribute ( 'href' , '/unit/456' ) ;
199+ } ) ;
200+
201+ it ( 'handles missing observations gracefully' , ( ) => {
202+ const stateWithNullObservations = {
203+ ...defaultState ,
204+ data : {
205+ ...defaultState . data ,
206+ observation : null as any
207+ }
208+ } ;
209+
210+ renderComponent ( '123' , stateWithNullObservations ) ;
211+
212+ expect ( screen . getByText ( 'Test Unit' ) ) . toBeInTheDocument ( ) ;
213+ expect ( screen . getByText ( 'Ei historiatietoja' ) ) . toBeInTheDocument ( ) ;
214+ } ) ;
215+
216+ it ( 'renders correct DOM structure' , ( ) => {
217+ renderComponent ( ) ;
218+
219+ // Check main container structure
220+ expect ( document . querySelector ( '.row' ) ) . toBeInTheDocument ( ) ;
221+ expect ( document . querySelector ( '.col-xs-12' ) ) . toBeInTheDocument ( ) ;
222+ expect ( document . querySelector ( '.list-group.facility-return' ) ) . toBeInTheDocument ( ) ;
223+ expect ( document . querySelector ( '.well' ) ) . toBeInTheDocument ( ) ;
224+ expect ( document . querySelector ( '.unit-observations' ) ) . toBeInTheDocument ( ) ;
225+ } ) ;
226+
227+ it ( 'renders glyphicon for back link' , ( ) => {
228+ renderComponent ( ) ;
229+
230+ const glyphicon = document . querySelector ( '.glyphicon-chevron-left' ) ;
231+ expect ( glyphicon ) . toBeInTheDocument ( ) ;
232+ } ) ;
233+ } ) ;
0 commit comments