github.com/moov-io/imagecashletter@v0.10.1/writer_test.go (about) 1 // Copyright 2020 The Moov Authors 2 // Use of this source code is governed by an Apache License 3 // license that can be found in the LICENSE file. 4 5 package imagecashletter 6 7 import ( 8 "bytes" 9 "os" 10 "path/filepath" 11 "strings" 12 "testing" 13 14 "github.com/stretchr/testify/require" 15 ) 16 17 // TestICLWrite writes an ICL File 18 func TestICLWrite(t *testing.T) { 19 file := NewFile().SetHeader(mockFileHeader()) 20 21 // Create CheckDetail 22 cd := mockCheckDetail() 23 cd.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 24 cd.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 25 cd.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 26 cd.AddImageViewDetail(mockImageViewDetail()) 27 cd.AddImageViewData(mockImageViewData()) 28 cd.AddImageViewAnalysis(mockImageViewAnalysis()) 29 bundle := NewBundle(mockBundleHeader()) 30 bundle.AddCheckDetail(cd) 31 32 // CheckDetail 2 33 cdTwo := mockCheckDetail() 34 cdTwo.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 35 cdTwo.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 36 cdTwo.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 37 cdTwo.AddImageViewDetail(mockImageViewDetail()) 38 cdTwo.AddImageViewData(mockImageViewData()) 39 cdTwo.AddImageViewAnalysis(mockImageViewAnalysis()) 40 bundle.AddCheckDetail(cdTwo) 41 42 // Create ReturnDetail 43 rd := mockReturnDetail() 44 rd.AddReturnDetailAddendumA(mockReturnDetailAddendumA()) 45 rd.AddReturnDetailAddendumB(mockReturnDetailAddendumB()) 46 rd.AddReturnDetailAddendumC(mockReturnDetailAddendumC()) 47 rd.AddReturnDetailAddendumD(mockReturnDetailAddendumD()) 48 rd.AddImageViewDetail(mockImageViewDetail()) 49 rd.AddImageViewData(mockImageViewData()) 50 rd.AddImageViewAnalysis(mockImageViewAnalysis()) 51 returnBundle := NewBundle(mockBundleHeader()) 52 returnBundle.BundleHeader.BundleSequenceNumber = "2" 53 returnBundle.AddReturnDetail(rd) 54 55 rdTwo := mockReturnDetail() 56 rdTwo.AddReturnDetailAddendumA(mockReturnDetailAddendumA()) 57 rdTwo.AddReturnDetailAddendumB(mockReturnDetailAddendumB()) 58 rdTwo.AddReturnDetailAddendumC(mockReturnDetailAddendumC()) 59 rdTwo.AddReturnDetailAddendumD(mockReturnDetailAddendumD()) 60 rdTwo.AddImageViewDetail(mockImageViewDetail()) 61 rdTwo.AddImageViewData(mockImageViewData()) 62 rdTwo.AddImageViewAnalysis(mockImageViewAnalysis()) 63 returnBundle.AddReturnDetail(rdTwo) 64 65 // Create CashLetter 66 cl := NewCashLetter(mockCashLetterHeader()) 67 cl.AddBundle(bundle) 68 cl.AddBundle(returnBundle) 69 require.NoError(t, cl.Create()) 70 file.AddCashLetter(cl) 71 72 clTwo := NewCashLetter(mockCashLetterHeader()) 73 clTwo.CashLetterHeader.CashLetterID = "A2" 74 clTwo.AddBundle(bundle) 75 clTwo.AddBundle(returnBundle) 76 require.NoError(t, clTwo.Create()) 77 file.AddCashLetter(clTwo) 78 79 // Create file 80 require.NoError(t, file.Create()) 81 require.NoError(t, file.Validate()) 82 83 b := &bytes.Buffer{} 84 f := NewWriter(b) 85 require.NoError(t, f.Write(file)) 86 87 r := NewReader(strings.NewReader(b.String())) 88 _, err := r.Read() 89 require.NoError(t, err) 90 require.NoError(t, r.File.Validate()) 91 } 92 93 // TestICLWriteCreditItem writes an ICL file with a CreditItem 94 func TestICLWriteCreditItem(t *testing.T) { 95 file := NewFile().SetHeader(mockFileHeader()) 96 97 // CreditItem 98 ci := mockCreditItem() 99 100 // Create CheckDetail 101 cd := mockCheckDetail() 102 cd.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 103 cd.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 104 cd.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 105 cd.AddImageViewDetail(mockImageViewDetail()) 106 cd.AddImageViewData(mockImageViewData()) 107 cd.AddImageViewAnalysis(mockImageViewAnalysis()) 108 bundle := NewBundle(mockBundleHeader()) 109 bundle.AddCheckDetail(cd) 110 111 // CheckDetail 2 112 cdTwo := mockCheckDetail() 113 cdTwo.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 114 cdTwo.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 115 cdTwo.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 116 cdTwo.AddImageViewDetail(mockImageViewDetail()) 117 cdTwo.AddImageViewData(mockImageViewData()) 118 cdTwo.AddImageViewAnalysis(mockImageViewAnalysis()) 119 bundle.AddCheckDetail(cdTwo) 120 121 // Create CashLetter 122 cl := NewCashLetter(mockCashLetterHeader()) 123 cl.AddCreditItem(ci) 124 cl.AddBundle(bundle) 125 require.NoError(t, cl.Create()) 126 file.AddCashLetter(cl) 127 128 clTwo := NewCashLetter(mockCashLetterHeader()) 129 clTwo.CashLetterHeader.CashLetterID = "A2" 130 clTwo.AddBundle(bundle) 131 132 require.NoError(t, clTwo.Create()) 133 file.AddCashLetter(clTwo) 134 135 // Create file 136 require.NoError(t, file.Create()) 137 require.NoError(t, file.Validate()) 138 139 b := &bytes.Buffer{} 140 f := NewWriter(b) 141 require.NoError(t, f.Write(file)) 142 143 r := NewReader(strings.NewReader(b.String())) 144 _, err := r.Read() 145 require.NoError(t, err) 146 require.NoError(t, r.File.Validate()) 147 } 148 149 // TestICLWriteCreditRecord writes an ICL file with a Credit record 150 func TestICLWriteCreditRecord(t *testing.T) { 151 file := NewFile().SetHeader(mockFileHeader()) 152 153 // CreditItem 154 ci := mockCredit() 155 156 // Create CheckDetail 157 cd := mockCheckDetail() 158 cd.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 159 cd.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 160 cd.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 161 cd.AddImageViewDetail(mockImageViewDetail()) 162 cd.AddImageViewData(mockImageViewData()) 163 cd.AddImageViewAnalysis(mockImageViewAnalysis()) 164 bundle := NewBundle(mockBundleHeader()) 165 bundle.AddCheckDetail(cd) 166 167 // CheckDetail 2 168 cdTwo := mockCheckDetail() 169 cdTwo.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 170 cdTwo.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 171 cdTwo.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 172 cdTwo.AddImageViewDetail(mockImageViewDetail()) 173 cdTwo.AddImageViewData(mockImageViewData()) 174 cdTwo.AddImageViewAnalysis(mockImageViewAnalysis()) 175 bundle.AddCheckDetail(cdTwo) 176 177 // Create CashLetter 178 cl := NewCashLetter(mockCashLetterHeader()) 179 cl.AddCredit(ci) 180 cl.AddBundle(bundle) 181 require.NoError(t, cl.Create()) 182 file.AddCashLetter(cl) 183 184 clTwo := NewCashLetter(mockCashLetterHeader()) 185 clTwo.CashLetterHeader.CashLetterID = "A2" 186 clTwo.AddBundle(bundle) 187 188 require.NoError(t, clTwo.Create()) 189 file.AddCashLetter(clTwo) 190 191 // Create file 192 require.NoError(t, file.Create()) 193 require.NoError(t, file.Validate()) 194 195 b := &bytes.Buffer{} 196 f := NewWriter(b) 197 require.NoError(t, f.Write(file)) 198 199 r := NewReader(strings.NewReader(b.String())) 200 _, err := r.Read() 201 require.NoError(t, err) 202 require.NoError(t, r.File.Validate()) 203 } 204 205 // TestICLWriteRoutingNumberSummary writes an ICL file with a RoutingNumberSummary 206 func TestICLWriteRoutingNumber(t *testing.T) { 207 file := NewFile().SetHeader(mockFileHeader()) 208 209 // RoutingNumberSummary 210 rns := mockRoutingNumberSummary() 211 212 // Create CheckDetail 213 cd := mockCheckDetail() 214 cd.AddCheckDetailAddendumA(mockCheckDetailAddendumA()) 215 cd.AddCheckDetailAddendumB(mockCheckDetailAddendumB()) 216 cd.AddCheckDetailAddendumC(mockCheckDetailAddendumC()) 217 cd.AddImageViewDetail(mockImageViewDetail()) 218 cd.AddImageViewData(mockImageViewData()) 219 cd.AddImageViewAnalysis(mockImageViewAnalysis()) 220 bundle := NewBundle(mockBundleHeader()) 221 bundle.AddCheckDetail(cd) 222 223 // Create CashLetter 224 cl := NewCashLetter(mockCashLetterHeader()) 225 cl.AddBundle(bundle) 226 cl.AddRoutingNumberSummary(rns) 227 require.NoError(t, cl.Create()) 228 file.AddCashLetter(cl) 229 230 // Create file 231 require.NoError(t, file.Create()) 232 require.NoError(t, file.Validate()) 233 234 b := &bytes.Buffer{} 235 f := NewWriter(b) 236 require.NoError(t, f.Write(file)) 237 238 r := NewReader(strings.NewReader(b.String())) 239 _, err := r.Read() 240 require.NoError(t, err) 241 require.NoError(t, r.File.Validate()) 242 } 243 244 func TestICLWrite_VariableLengthOption(t *testing.T) { 245 fileBytes, err := os.ReadFile(filepath.Join("test", "testdata", "valid-ascii.x937")) 246 require.NoError(t, err) 247 248 fd := bytes.NewReader(fileBytes) 249 r := NewReader(fd, ReadVariableLineLengthOption()) 250 file, err := r.Read() 251 require.NoError(t, err) 252 253 b := &bytes.Buffer{} 254 w := NewWriter(b, WriteVariableLineLengthOption()) 255 require.NoError(t, w.Write(&file)) 256 require.Equal(t, fileBytes, b.Bytes()) 257 } 258 259 func TestICLWrite_EbcdicEncodingOption(t *testing.T) { 260 fileBytes, err := os.ReadFile(filepath.Join("test", "testdata", "valid-ebcdic.x937")) 261 require.NoError(t, err) 262 263 fd := bytes.NewReader(fileBytes) 264 r := NewReader(fd, ReadVariableLineLengthOption(), ReadEbcdicEncodingOption()) 265 file, err := r.Read() 266 require.NoError(t, err) 267 268 b := &bytes.Buffer{} 269 w := NewWriter(b, WriteVariableLineLengthOption(), WriteEbcdicEncodingOption()) 270 require.NoError(t, w.Write(&file)) 271 require.Equal(t, fileBytes, b.Bytes()) 272 } 273 274 func TestWriter_CollateErr(t *testing.T) { 275 cd := &CheckDetail{ 276 // Create a CheckDetail without a corresponding ImageData or ImageViewAnalysis 277 // so when we attempt to collate them it doesn't crash. 278 ImageViewDetail: []ImageViewDetail{ 279 mockImageViewDetail(), 280 mockImageViewDetail(), 281 }, 282 // To trigger the crash this issue fixes we need two ImageViewDetails, and one ImageData. 283 // Having one ImageViewAnalysis would work as well 284 ImageViewData: []ImageViewData{ 285 mockImageViewData(), 286 }, 287 ImageViewAnalysis: []ImageViewAnalysis{ 288 mockImageViewAnalysis(), 289 }, 290 } 291 292 var buf bytes.Buffer 293 w := NewWriter(&buf) 294 require.ErrorContains(t, w.writeCheckImageView(cd), "ImageViewData does not match Image View Detail count of 1") 295 }