Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PB-878: Filter out KML outside print extent #1055

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bc48303
PB-878: Use print extent to filter out features to be printed.
ismailsunni Sep 2, 2024
997fa6a
PB-878: Fix unit test by using higher zoom level so that layer can be…
ismailsunni Sep 4, 2024
4df8b3e
PB-878: Fix unit test on importing router.
ismailsunni Sep 4, 2024
f07d4c0
PB-878: Add JSDoc for GeoAdminCustomizer.
ismailsunni Sep 4, 2024
dedf1a9
PB-878: Add comment and try to fix failed CI build.
ismailsunni Sep 4, 2024
ec63949
PB-878: Ignore simple-import-sort/imports to fix import issue.
ismailsunni Sep 4, 2024
d5de3e4
PB-878: Use different zoom level for failed test in CI.
ismailsunni Sep 4, 2024
b7a8d66
PB-878: Set center to fix failed test in CI.
ismailsunni Sep 4, 2024
296c2b7
PB-878: Check center and zoom level for failed test.
ismailsunni Sep 4, 2024
fb56a9c
PB-878: Also test the zoom level
ismailsunni Sep 4, 2024
6851bb9
PB-878: Add check for layers loaded in OpenLayers.
ismailsunni Sep 19, 2024
6e44ca5
PB-878: Add wait (test only, removed later).
ismailsunni Sep 19, 2024
a75cdc2
PB-878: Add render check on checkOlLayer.
ismailsunni Sep 19, 2024
b4c8e60
PB-878: Check if there are features and the extent is correct.
ismailsunni Sep 19, 2024
aafb7ae
PB-878: remove check on rendering.
ismailsunni Sep 19, 2024
252fe6a
PB-878: Log the layer type.
ismailsunni Oct 2, 2024
d423300
PB-878: More cy.log to see the failed layer.
ismailsunni Oct 2, 2024
487ff1e
PB-878: Try with import file to load KML.
ismailsunni Oct 7, 2024
d508afa
PB-878: Skip duplicated test.
ismailsunni Oct 7, 2024
25fcbc6
PB-878: Fix import issue on runt unit test.
ismailsunni Oct 7, 2024
4f8316e
PB-878: Tidy up code.
ismailsunni Oct 7, 2024
70eb9d9
PB-878: Re-enable test with import layer.
ismailsunni Oct 7, 2024
2f20e4a
PB-878: Remove unused comment.
ismailsunni Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/api/__tests__/print.api.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
// eslint-disable-next-line simple-import-sort/imports
import { expect } from 'chai'
import { describe, it } from 'vitest'

// We need to import the router here to avoid error when initializing router plugins, this is
// needed since some store plugins might require access to router to get the query parameters
// (e.g. topic management plugin)
import router from '@/router' // eslint-disable-line no-unused-vars
import store from '@/store' // eslint-disable-line no-unused-vars

import { PrintLayout, PrintLayoutAttribute } from '@/api/print.api.js'
import { PRINT_DPI_COMPENSATION } from '@/config/print.config'
import { adjustWidth } from '@/utils/styleUtils'
Expand Down
22 changes: 18 additions & 4 deletions src/api/print.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
getWmsBaseUrl,
} from '@/config/baseUrl.config'
import i18n from '@/modules/i18n'
import store from '@/store'
import log from '@/utils/logging'
import { adjustWidth } from '@/utils/styleUtils'

Expand All @@ -24,13 +25,24 @@ const PRINTING_DEFAULT_POLL_TIMEOUT = 600000 // ms (10 minutes)
const SERVICE_PRINT_URL = `${getViewerDedicatedServicesBaseUrl()}print3/print/mapviewer`
const MAX_PRINT_SPEC_SIZE = 1 * 1024 * 1024 // 1MB in bytes (should be in sync with the backend)

/**
* Customizes the printing behavior for GeoAdmin.
*
* @extends BaseCustomizer
*/
class GeoAdminCustomizer extends BaseCustomizer {
/** @param {string[]} layerIDsToExclude List of layer names to exclude from the print */
constructor(layerIDsToExclude, printResolution) {
super()
/**
* @param {number[]} printExtent - The extent of the area to be printed.
* @param {string[]} layerIDsToExclude - An array of layer IDs to exclude from the print.
* @param {number} printResolution - The resolution for the print.
*/
constructor(printExtent, layerIDsToExclude, printResolution) {
ismailsunni marked this conversation as resolved.
Show resolved Hide resolved
super(printExtent)
this.layerIDsToExclude = layerIDsToExclude
this.printResolution = printResolution

this.layerFilter = this.layerFilter.bind(this)
this.geometryFilter = this.geometryFilter.bind(this)
this.line = this.line.bind(this)
this.text = this.text.bind(this)
this.point = this.point.bind(this)
Expand Down Expand Up @@ -350,7 +362,9 @@ async function transformOlMapToPrintParams(olMap, config) {
if (!dpi) {
throw new PrintError('Missing DPI for printing')
}
const customizer = new GeoAdminCustomizer(excludedLayerIDs, dpi)
const printExtent = store.state.print.printExtent
const customizer = new GeoAdminCustomizer(printExtent, excludedLayerIDs, dpi)

const attributionsOneLine = attributions.length > 0 ? `© ${attributions.join(', ')}` : ''

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ export default function usePrintAreaRenderer(map) {
const width = size[0]

const printRectangle = calculatePageBoundsPixels(selectedScale.value, printLayoutSize.value)
const topLeftCoordinate = map.getCoordinateFromPixel([printRectangle[0], printRectangle[1]])
const rightBottomCoordinate = map.getCoordinateFromPixel([
printRectangle[2],
printRectangle[3],
])

store.commit('setPrintExtent', {
printExtent: [
topLeftCoordinate[0], // minX
rightBottomCoordinate[1], // minY
rightBottomCoordinate[0], // maxX
topLeftCoordinate[1], // maxY
],
dispatcher,
})

const minx = printRectangle[0]
const miny = printRectangle[1]
Expand Down
5 changes: 5 additions & 0 deletions src/store/modules/print.store.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default {
selectedLayout: null,
selectedScale: null,
printSectionShown: false,
printExtent: [],
},
getters: {
printLayoutSize(state) {
Expand Down Expand Up @@ -44,11 +45,15 @@ export default {
setPrintSectionShown({ commit }, { show, dispatcher }) {
commit('setPrintSectionShown', { show, dispatcher })
},
setPrintExtent({ commit }, { printExtent, dispatcher }) {
commit('setPrintExtent', { printExtent, dispatcher })
},
},
mutations: {
setPrintLayouts: (state, { layouts }) => (state.layouts = layouts),
setSelectedLayout: (state, { layout }) => (state.selectedLayout = layout),
setSelectedScale: (state, { scale }) => (state.selectedScale = scale),
setPrintSectionShown: (state, { show }) => (state.printSectionShown = show),
setPrintExtent: (state, { printExtent }) => (state.printExtent = printExtent),
},
}
1 change: 1 addition & 0 deletions tests/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ Cypress.Commands.add('checkOlLayer', (args = null) => {
description: `[${layer.id}] waitUntil layer.rendered`,
errorMsg: `[${layer.id}] layer.rendered is not true`,
})
cy.log(`[${layer.id}] layer at index ${index} is rendered ${olLayer.rendered}`)
})
})
invisibleLayers.forEach((layer) => {
Expand Down
153 changes: 144 additions & 9 deletions tests/cypress/tests-e2e/print.cy.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
/// <reference types="cypress" />

import { getServiceKmlBaseUrl } from '@/config/baseUrl.config'
import { formatThousand } from '@/utils/numberUtils.js'

const printID = 'print-123456789'

function checkZoom(customZoom) {
cy.readStoreValue('state.position.zoom').should((zoom) => {
expect(zoom).to.equal(customZoom)
})
}

describe('Testing print', () => {
beforeEach(() => {
cy.viewport(1920, 1080)
Expand Down Expand Up @@ -175,16 +182,17 @@ describe('Testing print', () => {
})
})
context('Send print request with layers', () => {
function startPrintWithKml(kmlFixture) {
function startPrintWithKml(kmlFixture, zoom, center) {
interceptPrintRequest()
interceptPrintStatus()
interceptDownloadReport()
interceptKml(kmlFixture)

const kmlID = `${getServiceKmlBaseUrl()}some-kml-file.kml`
cy.goToMapView(
{
layers: `KML|${getServiceKmlBaseUrl()}some-kml-file.kml`,
z: 9,
layers: `KML|${kmlID}`,
z: zoom || 9,
center: center || '2655000,1203250',
},
true
)
Expand All @@ -199,6 +207,7 @@ describe('Testing print', () => {

cy.get('[data-cy="print-map-button"]').should('be.visible').click()
cy.get('[data-cy="abort-print-button"]').should('be.visible')
return kmlID
}

it('should send a print request to mapfishprint (with layers added)', () => {
Expand Down Expand Up @@ -294,8 +303,11 @@ describe('Testing print', () => {
expect(layers[0]['matrices'][0]['matrixSize']).to.deep.eq([1, 1])
})
})
it('should send a print request correctly to mapfishprint (with KML layer)', () => {
startPrintWithKml('import-tool/external-kml-file.kml')
it.skip('should send a print request correctly to mapfishprint (with KML layer)', () => {
const customZoom = 13
const kmlID = startPrintWithKml('import-tool/external-kml-file.kml', customZoom)
checkZoom(customZoom)
cy.checkOlLayer(['test.background.layer2', kmlID])

cy.wait('@printRequest').then((interception) => {
expect(interception.request.body).to.haveOwnProperty('layout')
Expand All @@ -312,12 +324,105 @@ describe('Testing print', () => {
)

const mapAttributes = attributes.map
expect(mapAttributes['scale']).to.equals(5000)
expect(mapAttributes['scale']).to.equals(2500000)
expect(mapAttributes['dpi']).to.equals(254)
expect(mapAttributes['projection']).to.equals('EPSG:2056')

const layers = mapAttributes.layers
expect(layers).to.be.an('array')
cy.log('Layers:', layers)
cy.log('Layer 0:', layers[0]['type'])

expect(layers).to.have.length(2)
expect(layers[0]['type']).to.equals('geojson')
expect(layers[0]['geoJson']['features']).to.have.length(1)
expect(layers[0]['geoJson']['features'][0]['properties']).to.haveOwnProperty(
'_mfp_style'
)
expect(layers[0]['geoJson']['features'][0]['properties']['_mfp_style']).to.equal(
'1'
)
expect(layers[0]['style']).to.haveOwnProperty("[_mfp_style = '1']")
})
})
it('should send a print request correctly to mapfishprint (with KML layer) - with import layer', () => {
interceptPrintRequest()
interceptPrintStatus()
interceptDownloadReport()

cy.goToMapView({}, true)
cy.readStoreValue('state.layers.activeLayers').should('be.empty')
cy.openMenuIfMobile()
cy.get('[data-cy="menu-tray-tool-section"]:visible').click()
cy.get('[data-cy="menu-advanced-tools-import-file"]:visible').click()

cy.get('[data-cy="import-file-content"]').should('be.visible')
cy.get('[data-cy="import-file-online-content"]').should('be.visible')

const localKmlFileName = 'external-kml-file.kml'
const localKmlFile = `import-tool/${localKmlFileName}`

// Test local import
cy.log('Switch to local import')
cy.get('[data-cy="import-file-local-btn"]:visible').click()
cy.get('[data-cy="import-file-local-content"]').should('be.visible')

// Attach a local KML file
cy.log('Test add a local KML file')
cy.fixture(localKmlFile, null).as('kmlFixture')
cy.get('[data-cy="file-input"]').selectFile('@kmlFixture', {
force: true,
})
cy.get('[data-cy="import-file-load-button"]:visible').click()

// Assertions for successful import
cy.get('[data-cy="file-input-text"]')
.should('have.class', 'is-valid')
.should('not.have.class', 'is-invalid')
cy.get('[data-cy="file-input-valid-feedback"]')
.should('be.visible')
.contains('File successfully imported')
cy.get('[data-cy="import-file-load-button"]').should('be.visible').contains('Import')
cy.get('[data-cy="import-file-online-content"]').should('not.be.visible')
cy.readStoreValue('state.layers.activeLayers').should('have.length', 1)

// Close the import tool
cy.get('[data-cy="import-file-close-button"]:visible').click()
cy.get('[data-cy="import-file-content"]').should('not.exist')

// Print
cy.get('[data-cy="menu-print-section"]').should('be.visible').click()
cy.get('[data-cy="menu-print-form"]').should('be.visible')

cy.get('[data-cy="print-map-button"]').should('be.visible').click()
cy.get('[data-cy="abort-print-button"]').should('be.visible')

cy.checkOlLayer(['test.background.layer2', localKmlFileName])

cy.wait('@printRequest').then((interception) => {
expect(interception.request.body).to.haveOwnProperty('layout')
expect(interception.request.body['layout']).to.equal('1. A4 landscape')
expect(interception.request.body).to.haveOwnProperty('format')
expect(interception.request.body['format']).to.equal('pdf')

const attributes = interception.request.body.attributes
expect(attributes).to.haveOwnProperty('printLegend')
expect(attributes['printLegend']).to.equals(0)
expect(attributes).to.haveOwnProperty('qrimage')
expect(attributes['qrimage']).to.contains(
encodeURIComponent('https://s.geo.admin.ch/0000000')
)

const mapAttributes = attributes.map
expect(mapAttributes['scale']).to.equals(10000)
expect(mapAttributes['dpi']).to.equals(254)
expect(mapAttributes['projection']).to.equals('EPSG:2056')

const layers = mapAttributes.layers
expect(layers).to.be.an('array')
cy.log('Layers:', layers)
cy.log('Layer 0:', layers[0]['type'])

expect(layers).to.have.length(2)
expect(layers[0]['type']).to.equals('geojson')
expect(layers[0]['geoJson']['features']).to.have.length(1)
Expand Down Expand Up @@ -402,6 +507,8 @@ describe('Testing print', () => {

const layers = mapAttributes.layers
expect(layers).to.be.an('array')
cy.log('Layers:', layers)
cy.log('Layer 0:', layers[0]['type'])
expect(layers).to.have.length(2)

// In this GPX layer, htere are two features (a line and a point).
Expand All @@ -428,7 +535,10 @@ describe('Testing print', () => {
})
/** We need to ensure the structure of the query sent is correct */
it('should send a print request correctly to mapfishprint (icon and label)', () => {
startPrintWithKml('print/label.kml')
const customZoom = 13
const kmlID = startPrintWithKml('print/label.kml', customZoom)
checkZoom(customZoom)
cy.checkOlLayer(['test.background.layer2', kmlID])

cy.wait('@printRequest').then((interception) => {
expect(interception.request.body).to.haveOwnProperty('layout')
Expand All @@ -446,10 +556,15 @@ describe('Testing print', () => {
expect(mapAttributes).to.haveOwnProperty('projection')

expect(mapAttributes).to.haveOwnProperty('layers')
expect(mapAttributes['scale']).to.equals(2500000)
expect(mapAttributes['dpi']).to.equals(254)
expect(mapAttributes['projection']).to.equals('EPSG:2056')

const layers = mapAttributes.layers

expect(layers).to.be.an('array')
cy.log('Layers:', layers)
cy.log('Layer 0:', layers[0]['type'])
expect(layers).to.have.length(2)

const geoJsonLayer = layers[0]
Expand Down Expand Up @@ -497,7 +612,22 @@ describe('Testing print', () => {
})
})
it('should send a print request correctly to mapfishprint (KML from old geoadmin)', () => {
startPrintWithKml('print/old-geoadmin-label.kml')
const customZoom = 13
const kmlID = startPrintWithKml('print/old-geoadmin-label.kml', customZoom)

checkZoom(customZoom)

cy.readStoreValue('getters.centerEpsg4326').should((center) => {
expect(center[0]).to.eq(8.161492)
expect(center[1]).to.eq(46.978042)
})

cy.readStoreValue('state.position.center').should((center) => {
expect(center[0]).to.eq(2655000)
expect(center[1]).to.eq(1203250)
})

cy.checkOlLayer(['test.background.layer2', kmlID])

cy.wait('@printRequest').then((interception) => {
expect(interception.request.body).to.haveOwnProperty('layout')
Expand All @@ -515,10 +645,15 @@ describe('Testing print', () => {
expect(mapAttributes).to.haveOwnProperty('projection')

expect(mapAttributes).to.haveOwnProperty('layers')
expect(mapAttributes['scale']).to.equals(2500000)
expect(mapAttributes['dpi']).to.equals(254)
expect(mapAttributes['projection']).to.equals('EPSG:2056')

const layers = mapAttributes.layers

expect(layers).to.be.an('array')
cy.log('Layers:', layers)
cy.log('Layer 0:', layers[0]['type'])
expect(layers).to.have.length(2)

const geoJsonLayer = layers[0]
Expand Down
Loading