Skip to content

Commit 72ddce0

Browse files
committed
PB-2026: Fix error prioritization in file parser
When importing a KML file that is outside the extent, the parser was showing "Invalid file" error instead of the correct "out of bounds" error. The issue occurred because parseAll() threw the first rejected error from any parser, which was typically InvalidFileContentError from parsers that couldn't handle the file format. However, the KML parser correctly identified the file as KML and threw a more specific OutOfBoundsError. Fixed by prioritizing specific errors (OutOfBounds, Empty, UnknownProjection) over generic InvalidFileContentError, ensuring users see the most relevant error message. Also re-enabled the test cases for out-of-bounds and empty KML files.
1 parent c3c2883 commit 72ddce0

File tree

2 files changed

+78
-44
lines changed

2 files changed

+78
-44
lines changed

packages/viewer/src/modules/menu/components/advancedTools/ImportFile/parser/index.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import type { ParseOptions } from '@/modules/menu/components/advancedTools/Impor
88
import { getFileContentThroughServiceProxy } from '@/api/file-proxy.api'
99
import { checkOnlineFileCompliance, getFileContentFromUrl } from '@/api/files.api'
1010
import { CloudOptimizedGeoTIFFParser } from '@/modules/menu/components/advancedTools/ImportFile/parser/CloudOptimizedGeoTIFFParser.class'
11+
import EmptyFileContentError from '@/modules/menu/components/advancedTools/ImportFile/parser/errors/EmptyFileContentError.error'
12+
import InvalidFileContentError from '@/modules/menu/components/advancedTools/ImportFile/parser/errors/InvalidFileContentError.error'
13+
import OutOfBoundsError from '@/modules/menu/components/advancedTools/ImportFile/parser/errors/OutOfBoundsError.error'
14+
import UnknownProjectionError from '@/modules/menu/components/advancedTools/ImportFile/parser/errors/UnknownProjectionError.error'
1115
import GPXParser from '@/modules/menu/components/advancedTools/ImportFile/parser/GPXParser.class'
1216
import { KMLParser } from '@/modules/menu/components/advancedTools/ImportFile/parser/KMLParser.class'
1317
import KMZParser from '@/modules/menu/components/advancedTools/ImportFile/parser/KMZParser.class'
@@ -34,12 +38,42 @@ async function parseAll(config: ParseAllConfig, options?: ParseOptions): Promise
3438
if (firstFulfilled) {
3539
return (firstFulfilled as PromiseFulfilledResult<FileLayer>).value
3640
}
37-
const anyErrorRaised = allSettled.find(
41+
42+
// Prioritize specific errors over generic InvalidFileContentError
43+
// This ensures that if a parser successfully identifies the file format
44+
// but encounters a specific issue (e.g., out of bounds), that error is shown
45+
const rejectedResponses = allSettled.filter(
3846
(response) => response.status === 'rejected' && response.reason
47+
) as PromiseRejectedResult[]
48+
49+
// Priority order: OutOfBounds > Empty > UnknownProjection > Invalid > Other
50+
const outOfBoundsError = rejectedResponses.find(
51+
(response) => response.reason instanceof OutOfBoundsError
52+
)
53+
if (outOfBoundsError) {
54+
throw outOfBoundsError.reason
55+
}
56+
57+
const emptyFileError = rejectedResponses.find(
58+
(response) => response.reason instanceof EmptyFileContentError
3959
)
40-
if (anyErrorRaised) {
41-
throw (anyErrorRaised as PromiseRejectedResult).reason
60+
if (emptyFileError) {
61+
throw emptyFileError.reason
4262
}
63+
64+
const unknownProjectionError = rejectedResponses.find(
65+
(response) => response.reason instanceof UnknownProjectionError
66+
)
67+
if (unknownProjectionError) {
68+
throw unknownProjectionError.reason
69+
}
70+
71+
// Fall back to any error (including InvalidFileContentError)
72+
const firstError = rejectedResponses[0]
73+
if (firstError) {
74+
throw firstError.reason
75+
}
76+
4377
throw new Error('Could not parse file')
4478
}
4579

packages/viewer/tests/cypress/tests-e2e/importToolFile.cy.ts

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,47 +1054,47 @@ describe('The Import File Tool', () => {
10541054
.should('be.visible')
10551055
.should('contain', 'Invalid file, only KML, KMZ, GPX or COG file are supported')
10561056

1057-
// //----------------------------------------------------------------------
1058-
// // Attach a local KML file that is out of bounds
1059-
// cy.log('Test add a local KML file that is out of bounds')
1060-
// cy.fixture(outOfBoundKMLFile, undefined).as('outOfBoundKMLFileFixture')
1061-
// cy.get('[data-cy="file-input"]').selectFile('@outOfBoundKMLFileFixture', {
1062-
// force: true,
1063-
// })
1064-
// cy.get('[data-cy="import-file-load-button"]:visible').click()
1065-
1066-
// cy.get('[data-cy="file-input-text"]')
1067-
// .should('have.class', 'is-invalid')
1068-
// .should('not.have.class', 'is-valid')
1069-
// cy.get('[data-cy="file-input-invalid-feedback"]')
1070-
// .should('be.visible')
1071-
// .contains('out of projection bounds')
1072-
1073-
// //----------------------------------------------------------------------
1074-
// // Attach a local empty KML file
1075-
// cy.log('Test add a local invalid KML file')
1076-
// cy.fixture(emptyKMLFile, undefined).as('emptyKMLFileFixture')
1077-
// cy.get('[data-cy="file-input"]').selectFile('@emptyKMLFileFixture', {
1078-
// force: true,
1079-
// })
1080-
// cy.get('[data-cy="import-file-load-button"]:visible').click()
1081-
1082-
// cy.get('[data-cy="file-input-text"]')
1083-
// .should('have.class', 'is-invalid')
1084-
// .should('not.have.class', 'is-valid')
1085-
// cy.get('[data-cy="file-input-invalid-feedback"]')
1086-
// .should('be.visible')
1087-
// .contains('file is empty')
1088-
1089-
// //----------------------------------------------------------------------
1090-
// // Close the import tool
1091-
// cy.log('Test close import tool')
1092-
// cy.get('[data-cy="import-file-close-button"]:visible').click()
1093-
// cy.get('[data-cy="import-file-content"]').should('not.exist')
1094-
1095-
// cy.openMenuIfMobile()
1096-
// cy.get('[data-cy="menu-section-active-layers"]').should('not.be.visible')
1097-
// cy.get('[data-cy="menu-section-no-layers"]').should('be.visible')
1057+
//----------------------------------------------------------------------
1058+
// Attach a local KML file that is out of bounds
1059+
cy.log('Test add a local KML file that is out of bounds')
1060+
cy.fixture(outOfBoundKMLFile, undefined).as('outOfBoundKMLFileFixture')
1061+
cy.get('[data-cy="file-input"]').selectFile('@outOfBoundKMLFileFixture', {
1062+
force: true,
1063+
})
1064+
cy.get('[data-cy="import-file-load-button"]:visible').click()
1065+
1066+
cy.get('[data-cy="file-input-text"]')
1067+
.should('have.class', 'is-invalid')
1068+
.should('not.have.class', 'is-valid')
1069+
cy.get('[data-cy="file-input-invalid-feedback"]')
1070+
.should('be.visible')
1071+
.contains('out of projection bounds')
1072+
1073+
//----------------------------------------------------------------------
1074+
// Attach a local empty KML file
1075+
cy.log('Test add a local invalid KML file')
1076+
cy.fixture(emptyKMLFile, undefined).as('emptyKMLFileFixture')
1077+
cy.get('[data-cy="file-input"]').selectFile('@emptyKMLFileFixture', {
1078+
force: true,
1079+
})
1080+
cy.get('[data-cy="import-file-load-button"]:visible').click()
1081+
1082+
cy.get('[data-cy="file-input-text"]')
1083+
.should('have.class', 'is-invalid')
1084+
.should('not.have.class', 'is-valid')
1085+
cy.get('[data-cy="file-input-invalid-feedback"]')
1086+
.should('be.visible')
1087+
.contains('file is empty')
1088+
1089+
//----------------------------------------------------------------------
1090+
// Close the import tool
1091+
cy.log('Test close import tool')
1092+
cy.get('[data-cy="import-file-close-button"]:visible').click()
1093+
cy.get('[data-cy="import-file-content"]').should('not.exist')
1094+
1095+
cy.openMenuIfMobile()
1096+
cy.get('[data-cy="menu-section-active-layers"]').should('not.be.visible')
1097+
cy.get('[data-cy="menu-section-no-layers"]').should('be.visible')
10981098
})
10991099

11001100
it('Import GPX file', () => {

0 commit comments

Comments
 (0)