mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-07-25 06:35:21 +00:00
chore(cucumber): add create_pdf_with_black_boxes and convert-pdf-to-image outline; remove duplicate split-pdf-by-sections (#3937)
# Description of Changes - **What was changed** - Introduced `create_pdf_with_black_boxes` helper function in `environment.py` for generating test PDFs with occluded content. - Added **Scenario Outline: Convert PDF to image** to `conversion.feature` to validate PDF→image conversion workflows. - Removed the duplicate **Scenario Outline: split-pdf-by-sections with different parameters** from `general.feature`. - **Why the change was made** - To enable testing of blacked-out content scenarios and ensure our suite covers image conversion. - To eliminate redundant tests and keep the feature files DRY and maintainable. --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
parent
b2f1404f68
commit
03f184ab2b
@ -65,17 +65,23 @@ premium:
|
|||||||
key: 00000000-0000-0000-0000-000000000000
|
key: 00000000-0000-0000-0000-000000000000
|
||||||
enabled: false # Enable license key checks for pro/enterprise features
|
enabled: false # Enable license key checks for pro/enterprise features
|
||||||
proFeatures:
|
proFeatures:
|
||||||
|
database: true # Enable database features
|
||||||
SSOAutoLogin: false
|
SSOAutoLogin: false
|
||||||
CustomMetadata:
|
CustomMetadata:
|
||||||
autoUpdateMetadata: false # set to 'true' to automatically update metadata with below values
|
autoUpdateMetadata: false
|
||||||
author: username # supports text such as 'John Doe' or types such as username to autopopulate with user's username
|
author: username
|
||||||
creator: Stirling-PDF # supports text such as 'Company-PDF'
|
creator: Stirling-PDF
|
||||||
producer: Stirling-PDF # supports text such as 'Company-PDF'
|
producer: Stirling-PDF
|
||||||
googleDrive:
|
googleDrive:
|
||||||
enabled: false
|
enabled: false
|
||||||
clientId: ''
|
clientId: ''
|
||||||
apiKey: ''
|
apiKey: ''
|
||||||
appId: ''
|
appId: ''
|
||||||
|
enterpriseFeatures:
|
||||||
|
audit:
|
||||||
|
enabled: true # Enable audit logging
|
||||||
|
level: 2 # Audit logging level: 0=OFF, 1=BASIC, 2=STANDARD, 3=VERBOSE
|
||||||
|
retentionDays: 90 # Number of days to retain audit logs
|
||||||
|
|
||||||
mail:
|
mail:
|
||||||
enabled: false # set to 'true' to enable sending emails
|
enabled: false # set to 'true' to enable sending emails
|
||||||
@ -86,7 +92,7 @@ mail:
|
|||||||
from: '' # sender email address
|
from: '' # sender email address
|
||||||
|
|
||||||
legal:
|
legal:
|
||||||
termsAndConditions: https://www.stirlingpdf.com/terms # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder
|
termsAndConditions: https://www.stirlingpdf.com/terms-and-conditions # URL to the terms and conditions of your application (e.g. https://example.com/terms). Empty string to disable or filename to load from local file in static folder
|
||||||
privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder
|
privacyPolicy: https://www.stirlingpdf.com/privacy-policy # URL to the privacy policy of your application (e.g. https://example.com/privacy). Empty string to disable or filename to load from local file in static folder
|
||||||
accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder
|
accessibilityStatement: '' # URL to the accessibility statement of your application (e.g. https://example.com/accessibility). Empty string to disable or filename to load from local file in static folder
|
||||||
cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder
|
cookiePolicy: '' # URL to the cookie policy of your application (e.g. https://example.com/cookie). Empty string to disable or filename to load from local file in static folder
|
||||||
@ -120,6 +126,15 @@ system:
|
|||||||
weasyprint: '' # Defaults to /opt/venv/bin/weasyprint
|
weasyprint: '' # Defaults to /opt/venv/bin/weasyprint
|
||||||
unoconvert: '' # Defaults to /opt/venv/bin/unoconvert
|
unoconvert: '' # Defaults to /opt/venv/bin/unoconvert
|
||||||
fileUploadLimit: '' # Defaults to "". No limit when string is empty. Set a number, between 0 and 999, followed by one of the following strings to set a limit. "KB", "MB", "GB".
|
fileUploadLimit: '' # Defaults to "". No limit when string is empty. Set a number, between 0 and 999, followed by one of the following strings to set a limit. "KB", "MB", "GB".
|
||||||
|
tempFileManagement:
|
||||||
|
baseTmpDir: '' # Defaults to java.io.tmpdir/stirling-pdf
|
||||||
|
libreofficeDir: '' # Defaults to tempFileManagement.baseTmpDir/libreoffice
|
||||||
|
systemTempDir: '' # Only used if cleanupSystemTemp is true
|
||||||
|
prefix: stirling-pdf- # Prefix for temp file names
|
||||||
|
maxAgeHours: 24 # Maximum age in hours before temp files are cleaned up
|
||||||
|
cleanupIntervalMinutes: 30 # How often to run cleanup (in minutes)
|
||||||
|
startupCleanup: true # Clean up old temp files on startup
|
||||||
|
cleanupSystemTemp: false # Whether to clean broader system temp directory
|
||||||
|
|
||||||
ui:
|
ui:
|
||||||
appName: '' # application's visible name
|
appName: '' # application's visible name
|
||||||
@ -150,6 +165,8 @@ processExecutor:
|
|||||||
weasyPrintSessionLimit: 16
|
weasyPrintSessionLimit: 16
|
||||||
installAppSessionLimit: 1
|
installAppSessionLimit: 1
|
||||||
calibreSessionLimit: 1
|
calibreSessionLimit: 1
|
||||||
|
ghostscriptSessionLimit: 8
|
||||||
|
ocrMyPdfSessionLimit: 2
|
||||||
timeoutMinutes: # Process executor timeout in minutes
|
timeoutMinutes: # Process executor timeout in minutes
|
||||||
libreOfficetimeoutMinutes: 30
|
libreOfficetimeoutMinutes: 30
|
||||||
pdfToHtmltimeoutMinutes: 20
|
pdfToHtmltimeoutMinutes: 20
|
||||||
@ -158,3 +175,6 @@ processExecutor:
|
|||||||
installApptimeoutMinutes: 60
|
installApptimeoutMinutes: 60
|
||||||
calibretimeoutMinutes: 30
|
calibretimeoutMinutes: 30
|
||||||
tesseractTimeoutMinutes: 30
|
tesseractTimeoutMinutes: 30
|
||||||
|
qpdfTimeoutMinutes: 30
|
||||||
|
ghostscriptTimeoutMinutes: 30
|
||||||
|
ocrMyPdfTimeoutMinutes: 30
|
||||||
|
@ -1,21 +1,25 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def before_all(context):
|
def before_all(context):
|
||||||
context.endpoint = None
|
context.endpoint = None
|
||||||
context.request_data = None
|
context.request_data = None
|
||||||
context.files = {}
|
context.files = {}
|
||||||
context.response = None
|
context.response = None
|
||||||
|
|
||||||
|
|
||||||
def after_scenario(context, scenario):
|
def after_scenario(context, scenario):
|
||||||
if hasattr(context, 'files'):
|
if hasattr(context, "files"):
|
||||||
for file in context.files.values():
|
for file in context.files.values():
|
||||||
file.close()
|
file.close()
|
||||||
if os.path.exists('response_file'):
|
if os.path.exists("response_file"):
|
||||||
os.remove('response_file')
|
os.remove("response_file")
|
||||||
if hasattr(context, 'file_name') and os.path.exists(context.file_name):
|
if hasattr(context, "file_name") and os.path.exists(context.file_name):
|
||||||
os.remove(context.file_name)
|
os.remove(context.file_name)
|
||||||
|
|
||||||
# Remove any temporary files
|
# Remove any temporary files
|
||||||
for temp_file in os.listdir('.'):
|
for temp_file in os.listdir("."):
|
||||||
if temp_file.startswith('genericNonCustomisableName') or temp_file.startswith('temp_image_'):
|
if temp_file.startswith("genericNonCustomisableName") or temp_file.startswith(
|
||||||
|
"temp_image_"
|
||||||
|
):
|
||||||
os.remove(temp_file)
|
os.remove(temp_file)
|
||||||
|
@ -1,132 +1,132 @@
|
|||||||
@example @general
|
@example @general
|
||||||
Feature: API Validation
|
Feature: API Validation
|
||||||
|
|
||||||
@positive @password
|
@positive @password
|
||||||
Scenario: Remove password
|
Scenario: Remove password
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 pages
|
And the pdf contains 3 pages
|
||||||
And the pdf is encrypted with password "password123"
|
And the pdf is encrypted with password "password123"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| password | password123 |
|
| password | password123 |
|
||||||
When I send the API request to the endpoint "/api/v1/security/remove-password"
|
When I send the API request to the endpoint "/api/v1/security/remove-password"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response PDF is not passworded
|
And the response PDF is not passworded
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
@negative @password
|
@negative @password
|
||||||
Scenario: Remove password wrong password
|
Scenario: Remove password wrong password
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 pages
|
And the pdf contains 3 pages
|
||||||
And the pdf is encrypted with password "password123"
|
And the pdf is encrypted with password "password123"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| password | wrongPassword |
|
| password | wrongPassword |
|
||||||
When I send the API request to the endpoint "/api/v1/security/remove-password"
|
When I send the API request to the endpoint "/api/v1/security/remove-password"
|
||||||
Then the response status code should be 500
|
Then the response status code should be 500
|
||||||
And the response should contain error message "Internal Server Error"
|
And the response should contain error message "Internal Server Error"
|
||||||
|
|
||||||
@positive @info
|
@positive @info
|
||||||
Scenario: Get info
|
Scenario: Get info
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
When I send the API request to the endpoint "/api/v1/security/get-info-on-pdf"
|
When I send the API request to the endpoint "/api/v1/security/get-info-on-pdf"
|
||||||
Then the response content type should be "application/json"
|
Then the response content type should be "application/json"
|
||||||
And the response file should have size greater than 100
|
And the response file should have size greater than 100
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
@positive @password
|
@positive @password
|
||||||
Scenario: Add password
|
Scenario: Add password
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 pages
|
And the pdf contains 3 pages
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| password | password123 |
|
| password | password123 |
|
||||||
When I send the API request to the endpoint "/api/v1/security/add-password"
|
When I send the API request to the endpoint "/api/v1/security/add-password"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 100
|
And the response file should have size greater than 100
|
||||||
And the response PDF is passworded
|
And the response PDF is passworded
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
@positive @password
|
@positive @password
|
||||||
Scenario: Add password with other params
|
Scenario: Add password with other params
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 pages
|
And the pdf contains 3 pages
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| ownerPassword | ownerPass |
|
| ownerPassword | ownerPass |
|
||||||
| password | password123 |
|
| password | password123 |
|
||||||
| keyLength | 256 |
|
| keyLength | 256 |
|
||||||
| canPrint | true |
|
| canPrint | true |
|
||||||
| canModify | false |
|
| canModify | false |
|
||||||
When I send the API request to the endpoint "/api/v1/security/add-password"
|
When I send the API request to the endpoint "/api/v1/security/add-password"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 100
|
And the response file should have size greater than 100
|
||||||
And the response PDF is passworded
|
And the response PDF is passworded
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
@positive @watermark
|
@positive @watermark
|
||||||
Scenario: Add watermark
|
Scenario: Add watermark
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 pages
|
And the pdf contains 3 pages
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| watermarkType | text |
|
| watermarkType | text |
|
||||||
| watermarkText | Sample Watermark |
|
| watermarkText | Sample Watermark |
|
||||||
| fontSize | 30 |
|
| fontSize | 30 |
|
||||||
| rotation | 45 |
|
| rotation | 45 |
|
||||||
| opacity | 0.5 |
|
| opacity | 0.5 |
|
||||||
| widthSpacer | 50 |
|
| widthSpacer | 50 |
|
||||||
| heightSpacer | 50 |
|
| heightSpacer | 50 |
|
||||||
| alphabet | roman |
|
| alphabet | roman |
|
||||||
| customColor | #d3d3d3 |
|
| customColor | #d3d3d3 |
|
||||||
When I send the API request to the endpoint "/api/v1/security/add-watermark"
|
When I send the API request to the endpoint "/api/v1/security/add-watermark"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 100
|
And the response file should have size greater than 100
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
@positive
|
@positive
|
||||||
Scenario: Remove blank pages
|
Scenario: Remove blank pages
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 blank pages
|
And the pdf contains 3 blank pages
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| threshold | 90 |
|
| threshold | 90 |
|
||||||
| whitePercent | 99.9 |
|
| whitePercent | 99.9 |
|
||||||
When I send the API request to the endpoint "/api/v1/misc/remove-blanks"
|
When I send the API request to the endpoint "/api/v1/misc/remove-blanks"
|
||||||
Then the response content type should be "application/octet-stream"
|
Then the response content type should be "application/octet-stream"
|
||||||
And the response file should have extension ".zip"
|
And the response file should have extension ".zip"
|
||||||
And the response ZIP should contain 1 files
|
And the response ZIP should contain 1 files
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
|
|
||||||
@positive @flatten
|
@positive @flatten
|
||||||
Scenario: Flatten PDF
|
Scenario: Flatten PDF
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| flattenOnlyForms | false |
|
| flattenOnlyForms | false |
|
||||||
When I send the API request to the endpoint "/api/v1/misc/flatten"
|
When I send the API request to the endpoint "/api/v1/misc/flatten"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
@positive @metadata
|
@positive @metadata
|
||||||
Scenario: Update metadata
|
Scenario: Update metadata
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| author | John Doe |
|
| author | John Doe |
|
||||||
| title | Sample Title |
|
| title | Sample Title |
|
||||||
| subject | Sample Subject |
|
| subject | Sample Subject |
|
||||||
| keywords | sample, test |
|
| keywords | sample, test |
|
||||||
| producer | Test Producer |
|
| producer | Test Producer |
|
||||||
When I send the API request to the endpoint "/api/v1/misc/update-metadata"
|
When I send the API request to the endpoint "/api/v1/misc/update-metadata"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response PDF metadata should include "Author" as "John Doe"
|
And the response PDF metadata should include "Author" as "John Doe"
|
||||||
And the response PDF metadata should include "Keywords" as "sample, test"
|
And the response PDF metadata should include "Keywords" as "sample, test"
|
||||||
And the response PDF metadata should include "Subject" as "Sample Subject"
|
And the response PDF metadata should include "Subject" as "Sample Subject"
|
||||||
And the response PDF metadata should include "Title" as "Sample Title"
|
And the response PDF metadata should include "Title" as "Sample Title"
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,230 +1,250 @@
|
|||||||
Feature: API Validation
|
Feature: API Validation
|
||||||
|
|
||||||
|
|
||||||
@libre @positive
|
@libre @positive
|
||||||
Scenario: Repair PDF
|
Scenario: Repair PDF
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
When I send the API request to the endpoint "/api/v1/misc/repair"
|
When I send the API request to the endpoint "/api/v1/misc/repair"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
|
|
||||||
@ocr @positive
|
|
||||||
Scenario: Process PDF with OCR
|
|
||||||
Given I generate a PDF file as "fileInput"
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| languages | eng |
|
|
||||||
| sidecar | false |
|
|
||||||
| deskew | true |
|
|
||||||
| clean | true |
|
|
||||||
| cleanFinal | true |
|
|
||||||
| ocrType | Normal |
|
|
||||||
| ocrRenderType | hocr |
|
|
||||||
| removeImagesAfter| false |
|
|
||||||
When I send the API request to the endpoint "/api/v1/misc/ocr-pdf"
|
|
||||||
Then the response content type should be "application/pdf"
|
|
||||||
And the response file should have size greater than 0
|
|
||||||
And the response status code should be 200
|
|
||||||
|
|
||||||
|
|
||||||
@ocr @positive
|
@ocr @positive
|
||||||
Scenario: Extract Image Scans
|
Scenario: Process PDF with OCR
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 images of size 300x300 on 2 pages
|
And the request data includes
|
||||||
And the request data includes
|
| parameter | value |
|
||||||
| parameter | value |
|
| languages | eng |
|
||||||
| angleThreshold | 5 |
|
| sidecar | false |
|
||||||
| tolerance | 20 |
|
| deskew | true |
|
||||||
| minArea | 8000 |
|
| clean | true |
|
||||||
| minContourArea | 500 |
|
| cleanFinal | true |
|
||||||
| borderSize | 1 |
|
| ocrType | Normal |
|
||||||
When I send the API request to the endpoint "/api/v1/misc/extract-image-scans"
|
| ocrRenderType | hocr |
|
||||||
Then the response content type should be "application/octet-stream"
|
| removeImagesAfter | false |
|
||||||
And the response file should have extension ".zip"
|
When I send the API request to the endpoint "/api/v1/misc/ocr-pdf"
|
||||||
And the response ZIP should contain 2 files
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
|
|
||||||
@ocr @positive
|
|
||||||
Scenario: Process PDF with OCR
|
|
||||||
Given I generate a PDF file as "fileInput"
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| languages | eng |
|
|
||||||
| sidecar | false |
|
|
||||||
| deskew | true |
|
|
||||||
| clean | true |
|
|
||||||
| cleanFinal | true |
|
|
||||||
| ocrType | Force |
|
|
||||||
| ocrRenderType | hocr |
|
|
||||||
| removeImagesAfter| false |
|
|
||||||
When I send the API request to the endpoint "/api/v1/misc/ocr-pdf"
|
|
||||||
Then the response content type should be "application/pdf"
|
|
||||||
And the response file should have size greater than 0
|
|
||||||
And the response status code should be 200
|
|
||||||
|
|
||||||
|
|
||||||
@libre @positive
|
@ocr @positive
|
||||||
Scenario Outline: Convert PDF to various word formats
|
Scenario: Extract Image Scans
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 3 pages with random text
|
And the pdf contains 3 images of size 300x300 on 2 pages
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| outputFormat | <format> |
|
| angleThreshold | 5 |
|
||||||
When I send the API request to the endpoint "/api/v1/convert/pdf/word"
|
| tolerance | 20 |
|
||||||
Then the response status code should be 200
|
| minArea | 8000 |
|
||||||
And the response file should have size greater than 100
|
| minContourArea | 500 |
|
||||||
And the response file should have extension "<extension>"
|
| borderSize | 1 |
|
||||||
|
When I send the API request to the endpoint "/api/v1/misc/extract-image-scans"
|
||||||
|
Then the response content type should be "application/octet-stream"
|
||||||
|
And the response file should have extension ".zip"
|
||||||
|
And the response ZIP should contain 2 files
|
||||||
|
And the response file should have size greater than 0
|
||||||
|
And the response status code should be 200
|
||||||
|
|
||||||
Examples:
|
|
||||||
| format | extension |
|
|
||||||
| docx | .docx |
|
|
||||||
| odt | .odt |
|
|
||||||
| doc | .doc |
|
|
||||||
|
|
||||||
@ocr @pdfa1
|
@ocr @positive
|
||||||
Scenario: PDFA
|
Scenario: Process PDF with OCR
|
||||||
Given I use an example file at "exampleFiles/pdfa2.pdf" as parameter "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| outputFormat | pdfa |
|
| languages | eng |
|
||||||
When I send the API request to the endpoint "/api/v1/convert/pdf/pdfa"
|
| sidecar | false |
|
||||||
Then the response status code should be 200
|
| deskew | true |
|
||||||
And the response file should have extension ".pdf"
|
| clean | true |
|
||||||
And the response file should have size greater than 100
|
| cleanFinal | true |
|
||||||
|
| ocrType | Force |
|
||||||
@ocr @pdfa2
|
| ocrRenderType | hocr |
|
||||||
Scenario: PDFA1
|
| removeImagesAfter | false |
|
||||||
Given I use an example file at "exampleFiles/pdfa1.pdf" as parameter "fileInput"
|
When I send the API request to the endpoint "/api/v1/misc/ocr-pdf"
|
||||||
And the request data includes
|
Then the response content type should be "application/pdf"
|
||||||
| parameter | value |
|
And the response file should have size greater than 0
|
||||||
| outputFormat | pdfa-1 |
|
And the response status code should be 200
|
||||||
When I send the API request to the endpoint "/api/v1/convert/pdf/pdfa"
|
|
||||||
Then the response status code should be 200
|
|
||||||
And the response file should have extension ".pdf"
|
|
||||||
And the response file should have size greater than 100
|
|
||||||
|
|
||||||
@compress @qpdf @positive
|
|
||||||
Scenario: Compress
|
|
||||||
Given I use an example file at "exampleFiles/ghost3.pdf" as parameter "fileInput"
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| optimizeLevel | 4 |
|
|
||||||
When I send the API request to the endpoint "/api/v1/misc/compress-pdf"
|
|
||||||
Then the response status code should be 200
|
|
||||||
And the response file should have extension ".pdf"
|
|
||||||
And the response file should have size greater than 100
|
|
||||||
|
|
||||||
@compress @qpdf @positive
|
|
||||||
Scenario: Compress
|
|
||||||
Given I use an example file at "exampleFiles/ghost2.pdf" as parameter "fileInput"
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| optimizeLevel | 1 |
|
|
||||||
| expectedOutputSize | 5KB |
|
|
||||||
When I send the API request to the endpoint "/api/v1/misc/compress-pdf"
|
|
||||||
Then the response status code should be 200
|
|
||||||
And the response file should have extension ".pdf"
|
|
||||||
And the response file should have size greater than 100
|
|
||||||
|
|
||||||
|
|
||||||
@compress @qpdf @positive
|
|
||||||
Scenario: Compress
|
|
||||||
Given I use an example file at "exampleFiles/ghost1.pdf" as parameter "fileInput"
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| optimizeLevel | 1 |
|
|
||||||
| expectedOutputSize | 5KB |
|
|
||||||
When I send the API request to the endpoint "/api/v1/misc/compress-pdf"
|
|
||||||
Then the response status code should be 200
|
|
||||||
And the response file should have extension ".pdf"
|
|
||||||
And the response file should have size greater than 100
|
|
||||||
|
|
||||||
@libre @positive
|
|
||||||
Scenario Outline: Convert PDF to various types
|
|
||||||
Given I generate a PDF file as "fileInput"
|
|
||||||
And the pdf contains 3 pages with random text
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| outputFormat | <format> |
|
|
||||||
When I send the API request to the endpoint "/api/v1/convert/pdf/<type>"
|
|
||||||
Then the response status code should be 200
|
|
||||||
And the response file should have size greater than 100
|
|
||||||
And the response file should have extension "<extension>"
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
| type | format | extension |
|
|
||||||
| text | rtf | .rtf |
|
|
||||||
| text | txt | .txt |
|
|
||||||
| presentation | ppt | .ppt |
|
|
||||||
| presentation | pptx | .pptx |
|
|
||||||
| presentation | odp | .odp |
|
|
||||||
| html | html | .zip |
|
|
||||||
|
|
||||||
|
@libre @positive
|
||||||
@libre @positive @topdf
|
Scenario Outline: Convert PDF to various word formats
|
||||||
Scenario Outline: Convert PDF to various types
|
Given I generate a PDF file as "fileInput"
|
||||||
Given I use an example file at "exampleFiles/example<extension>" as parameter "fileInput"
|
And the pdf contains 3 pages with random text
|
||||||
When I send the API request to the endpoint "/api/v1/convert/file/pdf"
|
And the request data includes
|
||||||
Then the response status code should be 200
|
| parameter | value |
|
||||||
And the response file should have size greater than 100
|
| outputFormat | <format> |
|
||||||
And the response file should have extension ".pdf"
|
When I send the API request to the endpoint "/api/v1/convert/pdf/word"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension "<extension>"
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
| extension |
|
| format | extension |
|
||||||
| .docx |
|
| docx | .docx |
|
||||||
| .odp |
|
| odt | .odt |
|
||||||
| .odt |
|
| doc | .doc |
|
||||||
| .pptx |
|
|
||||||
| .rtf |
|
@ocr @pdfa1
|
||||||
|
Scenario: PDFA
|
||||||
@calibre @positive @htmltopdf
|
Given I use an example file at "exampleFiles/pdfa2.pdf" as parameter "fileInput"
|
||||||
Scenario: Convert HTML to PDF
|
And the request data includes
|
||||||
Given I use an example file at "exampleFiles/example.html" as parameter "fileInput"
|
| parameter | value |
|
||||||
When I send the API request to the endpoint "/api/v1/convert/html/pdf"
|
| outputFormat | pdfa |
|
||||||
Then the response status code should be 200
|
When I send the API request to the endpoint "/api/v1/convert/pdf/pdfa"
|
||||||
And the response file should have size greater than 100
|
Then the response status code should be 200
|
||||||
And the response file should have extension ".pdf"
|
And the response file should have extension ".pdf"
|
||||||
|
And the response file should have size greater than 100
|
||||||
@calibre @positive @zippedhtmltopdf
|
|
||||||
Scenario: Convert zipped HTML to PDF
|
@ocr @pdfa2
|
||||||
Given I use an example file at "exampleFiles/example_html.zip" as parameter "fileInput"
|
Scenario: PDFA1
|
||||||
When I send the API request to the endpoint "/api/v1/convert/html/pdf"
|
Given I use an example file at "exampleFiles/pdfa1.pdf" as parameter "fileInput"
|
||||||
Then the response status code should be 200
|
And the request data includes
|
||||||
And the response file should have size greater than 100
|
| parameter | value |
|
||||||
And the response file should have extension ".pdf"
|
| outputFormat | pdfa-1 |
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/pdf/pdfa"
|
||||||
@calibre @positive @markdowntopdf
|
Then the response status code should be 200
|
||||||
Scenario: Convert Markdown to PDF
|
And the response file should have extension ".pdf"
|
||||||
Given I use an example file at "exampleFiles/example.md" as parameter "fileInput"
|
And the response file should have size greater than 100
|
||||||
When I send the API request to the endpoint "/api/v1/convert/markdown/pdf"
|
|
||||||
Then the response status code should be 200
|
@compress @qpdf @positive
|
||||||
And the response file should have size greater than 100
|
Scenario: Compress
|
||||||
And the response file should have extension ".pdf"
|
Given I use an example file at "exampleFiles/ghost3.pdf" as parameter "fileInput"
|
||||||
|
And the request data includes
|
||||||
@markdown @positive
|
| parameter | value |
|
||||||
Scenario: Convert PDF to Markdown format
|
| optimizeLevel | 4 |
|
||||||
Given I generate a PDF file as "fileInput"
|
When I send the API request to the endpoint "/api/v1/misc/compress-pdf"
|
||||||
And the pdf contains 3 pages with random text
|
Then the response status code should be 200
|
||||||
When I send the API request to the endpoint "/api/v1/convert/pdf/markdown"
|
And the response file should have extension ".pdf"
|
||||||
Then the response status code should be 200
|
And the response file should have size greater than 100
|
||||||
And the response file should have size greater than 100
|
|
||||||
And the response file should have extension ".md"
|
@compress @qpdf @positive
|
||||||
|
Scenario: Compress
|
||||||
|
Given I use an example file at "exampleFiles/ghost2.pdf" as parameter "fileInput"
|
||||||
@positive @pdftocsv
|
And the request data includes
|
||||||
Scenario: Convert PDF with tables to CSV format
|
| parameter | value |
|
||||||
Given I use an example file at "exampleFiles/tables.pdf" as parameter "fileInput"
|
| optimizeLevel | 1 |
|
||||||
And the request data includes
|
| expectedOutputSize | 5KB |
|
||||||
| parameter | value |
|
When I send the API request to the endpoint "/api/v1/misc/compress-pdf"
|
||||||
| outputFormat | csv |
|
Then the response status code should be 200
|
||||||
| pageNumbers | all |
|
And the response file should have extension ".pdf"
|
||||||
When I send the API request to the endpoint "/api/v1/convert/pdf/csv"
|
And the response file should have size greater than 100
|
||||||
Then the response status code should be 200
|
|
||||||
And the response file should have size greater than 200
|
|
||||||
And the response file should have extension ".zip"
|
@compress @qpdf @positive
|
||||||
And the response ZIP should contain 3 files
|
Scenario: Compress
|
||||||
|
Given I use an example file at "exampleFiles/ghost1.pdf" as parameter "fileInput"
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| optimizeLevel | 1 |
|
||||||
|
| expectedOutputSize | 5KB |
|
||||||
|
When I send the API request to the endpoint "/api/v1/misc/compress-pdf"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have extension ".pdf"
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
|
||||||
|
@libre @positive
|
||||||
|
Scenario Outline: Convert PDF to various types
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the pdf contains 3 pages with random text
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| outputFormat | <format> |
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/pdf/<type>"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension "<extension>"
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| type | format | extension |
|
||||||
|
| text | rtf | .rtf |
|
||||||
|
| text | txt | .txt |
|
||||||
|
| presentation | ppt | .ppt |
|
||||||
|
| presentation | pptx | .pptx |
|
||||||
|
| presentation | odp | .odp |
|
||||||
|
| html | html | .zip |
|
||||||
|
|
||||||
|
@image @positive
|
||||||
|
Scenario Outline: Convert PDF to image
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the pdf contains 3 pages with random text
|
||||||
|
And the pdf contains 3 images of size 300x300 on 3 pages
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| dpi | 300 |
|
||||||
|
| imageFormat | <format> |
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/pdf/img"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension ".zip"
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| format |
|
||||||
|
| webp |
|
||||||
|
| png |
|
||||||
|
| jpeg |
|
||||||
|
| jpg |
|
||||||
|
| gif |
|
||||||
|
|
||||||
|
@libre @positive @topdf
|
||||||
|
Scenario Outline: Convert PDF to various types
|
||||||
|
Given I use an example file at "exampleFiles/example<extension>" as parameter "fileInput"
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/file/pdf"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension ".pdf"
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
| extension |
|
||||||
|
| .docx |
|
||||||
|
| .odp |
|
||||||
|
| .odt |
|
||||||
|
| .pptx |
|
||||||
|
| .rtf |
|
||||||
|
|
||||||
|
@calibre @positive @htmltopdf
|
||||||
|
Scenario: Convert HTML to PDF
|
||||||
|
Given I use an example file at "exampleFiles/example.html" as parameter "fileInput"
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/html/pdf"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension ".pdf"
|
||||||
|
|
||||||
|
@calibre @positive @zippedhtmltopdf
|
||||||
|
Scenario: Convert zipped HTML to PDF
|
||||||
|
Given I use an example file at "exampleFiles/example_html.zip" as parameter "fileInput"
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/html/pdf"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension ".pdf"
|
||||||
|
|
||||||
|
@calibre @positive @markdowntopdf
|
||||||
|
Scenario: Convert Markdown to PDF
|
||||||
|
Given I use an example file at "exampleFiles/example.md" as parameter "fileInput"
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/markdown/pdf"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension ".pdf"
|
||||||
|
|
||||||
|
@markdown @positive
|
||||||
|
Scenario: Convert PDF to Markdown format
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the pdf contains 3 pages with random text
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/pdf/markdown"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 100
|
||||||
|
And the response file should have extension ".md"
|
||||||
|
|
||||||
|
|
||||||
|
@positive @pdftocsv
|
||||||
|
Scenario: Convert PDF with tables to CSV format
|
||||||
|
Given I use an example file at "exampleFiles/tables.pdf" as parameter "fileInput"
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| outputFormat | csv |
|
||||||
|
| pageNumbers | all |
|
||||||
|
When I send the API request to the endpoint "/api/v1/convert/pdf/csv"
|
||||||
|
Then the response status code should be 200
|
||||||
|
And the response file should have size greater than 200
|
||||||
|
And the response file should have extension ".zip"
|
||||||
|
And the response ZIP should contain 3 files
|
||||||
|
@ -2,113 +2,89 @@
|
|||||||
Feature: API Validation
|
Feature: API Validation
|
||||||
|
|
||||||
|
|
||||||
@split-pdf-by-sections @positive
|
@split-pdf-by-sections @positive
|
||||||
Scenario Outline: split-pdf-by-sections with different parameters
|
Scenario Outline: split-pdf-by-sections with different parameters
|
||||||
Given I generate a PDF file as "fileInput"
|
Given I generate a PDF file as "fileInput"
|
||||||
And the pdf contains 2 pages
|
And the pdf contains 2 pages
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| horizontalDivisions | <horizontalDivisions> |
|
| horizontalDivisions | <horizontalDivisions> |
|
||||||
| verticalDivisions | <verticalDivisions> |
|
| verticalDivisions | <verticalDivisions> |
|
||||||
| merge | true |
|
| merge | true |
|
||||||
When I send the API request to the endpoint "/api/v1/general/split-pdf-by-sections"
|
When I send the API request to the endpoint "/api/v1/general/split-pdf-by-sections"
|
||||||
Then the response content type should be "application/pdf"
|
Then the response content type should be "application/pdf"
|
||||||
And the response file should have size greater than 200
|
And the response file should have size greater than 200
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
And the response PDF should contain <page_count> pages
|
And the response PDF should contain <page_count> pages
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
| horizontalDivisions | verticalDivisions | page_count |
|
| horizontalDivisions | verticalDivisions | page_count |
|
||||||
| 0 | 1 | 4 |
|
| 0 | 1 | 4 |
|
||||||
| 1 | 1 | 8 |
|
| 1 | 1 | 8 |
|
||||||
| 1 | 2 | 12 |
|
| 1 | 2 | 12 |
|
||||||
| 2 | 2 | 18 |
|
| 2 | 2 | 18 |
|
||||||
|
|
||||||
@split-pdf-by-sections @positive
|
|
||||||
Scenario Outline: split-pdf-by-sections with different parameters
|
|
||||||
Given I generate a PDF file as "fileInput"
|
|
||||||
And the pdf contains 2 pages
|
|
||||||
And the request data includes
|
|
||||||
| parameter | value |
|
|
||||||
| horizontalDivisions | <horizontalDivisions> |
|
|
||||||
| verticalDivisions | <verticalDivisions> |
|
|
||||||
| merge | true |
|
|
||||||
When I send the API request to the endpoint "/api/v1/general/split-pdf-by-sections"
|
|
||||||
Then the response content type should be "application/pdf"
|
|
||||||
And the response file should have size greater than 200
|
|
||||||
And the response status code should be 200
|
|
||||||
And the response PDF should contain <page_count> pages
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
| horizontalDivisions | verticalDivisions | page_count |
|
|
||||||
| 0 | 1 | 4 |
|
|
||||||
| 1 | 1 | 8 |
|
|
||||||
| 1 | 2 | 12 |
|
|
||||||
| 2 | 2 | 18 |
|
|
||||||
|
|
||||||
|
|
||||||
|
@split-pdf-by-pages @positive
|
||||||
|
Scenario Outline: split-pdf-by-pages with different parameters
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the pdf contains 20 pages
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| fileInput | fileInput |
|
||||||
|
| pageNumbers | <pageNumbers> |
|
||||||
|
When I send the API request to the endpoint "/api/v1/general/split-pages"
|
||||||
|
Then the response content type should be "application/octet-stream"
|
||||||
|
And the response status code should be 200
|
||||||
|
And the response file should have size greater than 200
|
||||||
|
And the response ZIP should contain <file_count> files
|
||||||
|
|
||||||
@split-pdf-by-pages @positive
|
Examples:
|
||||||
Scenario Outline: split-pdf-by-pages with different parameters
|
| pageNumbers | file_count |
|
||||||
Given I generate a PDF file as "fileInput"
|
| 1,3,5-9 | 8 |
|
||||||
And the pdf contains 20 pages
|
| all | 20 |
|
||||||
And the request data includes
|
| 2n+1 | 10 |
|
||||||
| parameter | value |
|
| 3n | 7 |
|
||||||
| fileInput | fileInput |
|
|
||||||
| pageNumbers | <pageNumbers> |
|
|
||||||
When I send the API request to the endpoint "/api/v1/general/split-pages"
|
|
||||||
Then the response content type should be "application/octet-stream"
|
|
||||||
And the response status code should be 200
|
|
||||||
And the response file should have size greater than 200
|
|
||||||
And the response ZIP should contain <file_count> files
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
| pageNumbers | file_count |
|
|
||||||
| 1,3,5-9 | 8 |
|
|
||||||
| all | 20 |
|
|
||||||
| 2n+1 | 10 |
|
|
||||||
| 3n | 7 |
|
|
||||||
|
|
||||||
|
|
||||||
|
@split-pdf-by-size-or-count @positive
|
||||||
|
Scenario Outline: split-pdf-by-size-or-count with different parameters
|
||||||
|
Given I generate a PDF file as "fileInput"
|
||||||
|
And the pdf contains 20 pages
|
||||||
|
And the request data includes
|
||||||
|
| parameter | value |
|
||||||
|
| fileInput | fileInput |
|
||||||
|
| splitType | <splitType> |
|
||||||
|
| splitValue | <splitValue> |
|
||||||
|
When I send the API request to the endpoint "/api/v1/general/split-by-size-or-count"
|
||||||
|
Then the response content type should be "application/octet-stream"
|
||||||
|
And the response status code should be 200
|
||||||
|
And the response file should have size greater than 200
|
||||||
|
And the response ZIP file should contain <doc_count> documents each having <pages_per_doc> pages
|
||||||
|
|
||||||
@split-pdf-by-size-or-count @positive
|
Examples:
|
||||||
Scenario Outline: split-pdf-by-size-or-count with different parameters
|
| splitType | splitValue | doc_count | pages_per_doc |
|
||||||
Given I generate a PDF file as "fileInput"
|
| 1 | 5 | 4 | 5 |
|
||||||
And the pdf contains 20 pages
|
| 2 | 2 | 2 | 10 |
|
||||||
And the request data includes
|
| 2 | 4 | 4 | 5 |
|
||||||
| parameter | value |
|
| 1 | 10 | 2 | 10 |
|
||||||
| fileInput | fileInput |
|
|
||||||
| splitType | <splitType> |
|
|
||||||
| splitValue | <splitValue> |
|
|
||||||
When I send the API request to the endpoint "/api/v1/general/split-by-size-or-count"
|
|
||||||
Then the response content type should be "application/octet-stream"
|
|
||||||
And the response status code should be 200
|
|
||||||
And the response file should have size greater than 200
|
|
||||||
And the response ZIP file should contain <doc_count> documents each having <pages_per_doc> pages
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
| splitType | splitValue | doc_count | pages_per_doc |
|
|
||||||
| 1 | 5 | 4 | 5 |
|
|
||||||
| 2 | 2 | 2 | 10 |
|
|
||||||
| 2 | 4 | 4 | 5 |
|
|
||||||
| 1 | 10 | 2 | 10 |
|
|
||||||
|
|
||||||
|
|
||||||
@extract-images
|
@extract-images
|
||||||
Scenario Outline: Extract Image Scans duplicates
|
Scenario Outline: Extract Image Scans duplicates
|
||||||
Given I use an example file at "exampleFiles/images.pdf" as parameter "fileInput"
|
Given I use an example file at "exampleFiles/images.pdf" as parameter "fileInput"
|
||||||
And the request data includes
|
And the request data includes
|
||||||
| parameter | value |
|
| parameter | value |
|
||||||
| format | <format> |
|
| format | <format> |
|
||||||
When I send the API request to the endpoint "/api/v1/misc/extract-images"
|
When I send the API request to the endpoint "/api/v1/misc/extract-images"
|
||||||
Then the response content type should be "application/octet-stream"
|
Then the response content type should be "application/octet-stream"
|
||||||
And the response file should have extension ".zip"
|
And the response file should have extension ".zip"
|
||||||
And the response ZIP should contain 2 files
|
And the response ZIP should contain 2 files
|
||||||
And the response file should have size greater than 0
|
And the response file should have size greater than 0
|
||||||
And the response status code should be 200
|
And the response status code should be 200
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
| format |
|
| format |
|
||||||
| png |
|
| png |
|
||||||
| gif |
|
| gif |
|
||||||
| jpeg |
|
| jpeg |
|
||||||
|
@ -10,67 +10,67 @@ from reportlab.lib.pagesizes import letter
|
|||||||
from reportlab.lib.utils import ImageReader
|
from reportlab.lib.utils import ImageReader
|
||||||
from reportlab.pdfgen import canvas
|
from reportlab.pdfgen import canvas
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import requests
|
|
||||||
import zipfile
|
import zipfile
|
||||||
import shutil
|
|
||||||
import re
|
import re
|
||||||
from PIL import Image, ImageDraw
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
API_HEADERS = {
|
API_HEADERS = {"X-API-KEY": "123456789"}
|
||||||
'X-API-KEY': '123456789'
|
|
||||||
}
|
|
||||||
|
|
||||||
#########
|
#########
|
||||||
# GIVEN #
|
# GIVEN #
|
||||||
#########
|
#########
|
||||||
|
|
||||||
|
|
||||||
@given('I generate a PDF file as "{fileInput}"')
|
@given('I generate a PDF file as "{fileInput}"')
|
||||||
def step_generate_pdf(context, fileInput):
|
def step_generate_pdf(context, fileInput):
|
||||||
context.param_name = fileInput
|
context.param_name = fileInput
|
||||||
context.file_name = "genericNonCustomisableName.pdf"
|
context.file_name = "genericNonCustomisableName.pdf"
|
||||||
writer = PdfWriter()
|
writer = PdfWriter()
|
||||||
writer.add_blank_page(width=72, height=72) # Single blank page
|
writer.add_blank_page(width=72, height=72) # Single blank page
|
||||||
with open(context.file_name, 'wb') as f:
|
with open(context.file_name, "wb") as f:
|
||||||
writer.write(f)
|
writer.write(f)
|
||||||
if not hasattr(context, 'files'):
|
if not hasattr(context, "files"):
|
||||||
context.files = {}
|
context.files = {}
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
|
|
||||||
@given('I use an example file at "{filePath}" as parameter "{fileInput}"')
|
@given('I use an example file at "{filePath}" as parameter "{fileInput}"')
|
||||||
def step_use_example_file(context, filePath, fileInput):
|
def step_use_example_file(context, filePath, fileInput):
|
||||||
context.param_name = fileInput
|
context.param_name = fileInput
|
||||||
context.file_name = filePath.split('/')[-1]
|
context.file_name = filePath.split("/")[-1]
|
||||||
if not hasattr(context, 'files'):
|
if not hasattr(context, "files"):
|
||||||
context.files = {}
|
context.files = {}
|
||||||
|
|
||||||
# Ensure the file exists before opening
|
# Ensure the file exists before opening
|
||||||
try:
|
try:
|
||||||
example_file = open(filePath, 'rb')
|
example_file = open(filePath, "rb")
|
||||||
context.files[context.param_name] = example_file
|
context.files[context.param_name] = example_file
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
raise FileNotFoundError(f"The example file '{filePath}' does not exist.")
|
raise FileNotFoundError(f"The example file '{filePath}' does not exist.")
|
||||||
|
|
||||||
@given('the pdf contains {page_count:d} pages')
|
|
||||||
|
@given("the pdf contains {page_count:d} pages")
|
||||||
def step_pdf_contains_pages(context, page_count):
|
def step_pdf_contains_pages(context, page_count):
|
||||||
writer = PdfWriter()
|
writer = PdfWriter()
|
||||||
for i in range(page_count):
|
for i in range(page_count):
|
||||||
writer.add_blank_page(width=72, height=72)
|
writer.add_blank_page(width=72, height=72)
|
||||||
with open(context.file_name, 'wb') as f:
|
with open(context.file_name, "wb") as f:
|
||||||
writer.write(f)
|
writer.write(f)
|
||||||
context.files[context.param_name].close()
|
context.files[context.param_name].close()
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
|
|
||||||
# Duplicate for now...
|
# Duplicate for now...
|
||||||
@given('the pdf contains {page_count:d} blank pages')
|
@given("the pdf contains {page_count:d} blank pages")
|
||||||
def step_pdf_contains_blank_pages(context, page_count):
|
def step_pdf_contains_blank_pages(context, page_count):
|
||||||
writer = PdfWriter()
|
writer = PdfWriter()
|
||||||
for i in range(page_count):
|
for i in range(page_count):
|
||||||
writer.add_blank_page(width=72, height=72)
|
writer.add_blank_page(width=72, height=72)
|
||||||
with open(context.file_name, 'wb') as f:
|
with open(context.file_name, "wb") as f:
|
||||||
writer.write(f)
|
writer.write(f)
|
||||||
context.files[context.param_name].close()
|
context.files[context.param_name].close()
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
|
|
||||||
def create_black_box_image(file_name, size):
|
def create_black_box_image(file_name, size):
|
||||||
can = canvas.Canvas(file_name, pagesize=size)
|
can = canvas.Canvas(file_name, pagesize=size)
|
||||||
@ -80,14 +80,20 @@ def create_black_box_image(file_name, size):
|
|||||||
can.showPage()
|
can.showPage()
|
||||||
can.save()
|
can.save()
|
||||||
|
|
||||||
@given(u'the pdf contains {image_count:d} images of size {width:d}x{height:d} on {page_count:d} pages')
|
|
||||||
|
@given(
|
||||||
|
"the pdf contains {image_count:d} images of size {width:d}x{height:d} on {page_count:d} pages"
|
||||||
|
)
|
||||||
def step_impl(context, image_count, width, height, page_count):
|
def step_impl(context, image_count, width, height, page_count):
|
||||||
context.param_name = "fileInput"
|
context.param_name = "fileInput"
|
||||||
context.file_name = "genericNonCustomisableName.pdf"
|
context.file_name = "genericNonCustomisableName.pdf"
|
||||||
create_pdf_with_images_and_boxes(context.file_name, image_count, page_count, width, height)
|
create_pdf_with_images_and_boxes(
|
||||||
if not hasattr(context, 'files'):
|
context.file_name, image_count, page_count, width, height
|
||||||
|
)
|
||||||
|
if not hasattr(context, "files"):
|
||||||
context.files = {}
|
context.files = {}
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
|
|
||||||
def add_black_boxes_to_image(image):
|
def add_black_boxes_to_image(image):
|
||||||
if isinstance(image, str):
|
if isinstance(image, str):
|
||||||
@ -97,9 +103,14 @@ def add_black_boxes_to_image(image):
|
|||||||
draw.rectangle([(0, 0), image.size], fill=(0, 0, 0)) # Fill image with black
|
draw.rectangle([(0, 0), image.size], fill=(0, 0, 0)) # Fill image with black
|
||||||
return image
|
return image
|
||||||
|
|
||||||
def create_pdf_with_images_and_boxes(file_name, image_count, page_count, image_width, image_height):
|
|
||||||
|
def create_pdf_with_images_and_boxes(
|
||||||
|
file_name, image_count, page_count, image_width, image_height
|
||||||
|
):
|
||||||
page_width, page_height = max(letter[0], image_width), max(letter[1], image_height)
|
page_width, page_height = max(letter[0], image_width), max(letter[1], image_height)
|
||||||
boxes_per_page = image_count // page_count + (1 if image_count % page_count != 0 else 0)
|
boxes_per_page = image_count // page_count + (
|
||||||
|
1 if image_count % page_count != 0 else 0
|
||||||
|
)
|
||||||
|
|
||||||
writer = PdfWriter()
|
writer = PdfWriter()
|
||||||
box_counter = 0
|
box_counter = 0
|
||||||
@ -114,12 +125,14 @@ def create_pdf_with_images_and_boxes(file_name, image_count, page_count, image_w
|
|||||||
|
|
||||||
# Simulating a dynamic image creation (replace this with your actual image creation logic)
|
# Simulating a dynamic image creation (replace this with your actual image creation logic)
|
||||||
# For demonstration, we'll create a simple black image
|
# For demonstration, we'll create a simple black image
|
||||||
dummy_image = Image.new('RGB', (image_width, image_height), color='white') # Create a white image
|
dummy_image = Image.new(
|
||||||
|
"RGB", (image_width, image_height), color="white"
|
||||||
|
) # Create a white image
|
||||||
dummy_image = add_black_boxes_to_image(dummy_image) # Add black boxes
|
dummy_image = add_black_boxes_to_image(dummy_image) # Add black boxes
|
||||||
|
|
||||||
# Convert the PIL Image to bytes to pass to drawImage
|
# Convert the PIL Image to bytes to pass to drawImage
|
||||||
image_bytes = io.BytesIO()
|
image_bytes = io.BytesIO()
|
||||||
dummy_image.save(image_bytes, format='PNG')
|
dummy_image.save(image_bytes, format="PNG")
|
||||||
image_bytes.seek(0)
|
image_bytes.seek(0)
|
||||||
|
|
||||||
# Check if the image fits in the current page dimensions
|
# Check if the image fits in the current page dimensions
|
||||||
@ -130,7 +143,9 @@ def create_pdf_with_images_and_boxes(file_name, image_count, page_count, image_w
|
|||||||
break
|
break
|
||||||
|
|
||||||
# Add the image to the PDF
|
# Add the image to the PDF
|
||||||
can.drawImage(ImageReader(image_bytes), x, y, width=image_width, height=image_height)
|
can.drawImage(
|
||||||
|
ImageReader(image_bytes), x, y, width=image_width, height=image_height
|
||||||
|
)
|
||||||
box_counter += 1
|
box_counter += 1
|
||||||
|
|
||||||
can.showPage()
|
can.showPage()
|
||||||
@ -140,7 +155,7 @@ def create_pdf_with_images_and_boxes(file_name, image_count, page_count, image_w
|
|||||||
writer.add_page(new_pdf.pages[0])
|
writer.add_page(new_pdf.pages[0])
|
||||||
|
|
||||||
# Write the PDF to file
|
# Write the PDF to file
|
||||||
with open(file_name, 'wb') as f:
|
with open(file_name, "wb") as f:
|
||||||
writer.write(f)
|
writer.write(f)
|
||||||
|
|
||||||
# Clean up temporary image files
|
# Clean up temporary image files
|
||||||
@ -149,36 +164,81 @@ def create_pdf_with_images_and_boxes(file_name, image_count, page_count, image_w
|
|||||||
if os.path.exists(temp_image_path):
|
if os.path.exists(temp_image_path):
|
||||||
os.remove(temp_image_path)
|
os.remove(temp_image_path)
|
||||||
|
|
||||||
@given('the pdf contains {image_count:d} images on {page_count:d} pages')
|
|
||||||
|
@given("the pdf contains {image_count:d} images on {page_count:d} pages")
|
||||||
def step_pdf_contains_images(context, image_count, page_count):
|
def step_pdf_contains_images(context, image_count, page_count):
|
||||||
if not hasattr(context, 'param_name'):
|
if not hasattr(context, "param_name"):
|
||||||
context.param_name = "default"
|
context.param_name = "default"
|
||||||
context.file_name = "genericNonCustomisableName.pdf"
|
context.file_name = "genericNonCustomisableName.pdf"
|
||||||
create_pdf_with_black_boxes(context.file_name, image_count, page_count)
|
create_pdf_with_black_boxes(context.file_name, image_count, page_count)
|
||||||
if not hasattr(context, 'files'):
|
if not hasattr(context, "files"):
|
||||||
context.files = {}
|
context.files = {}
|
||||||
if context.param_name in context.files:
|
if context.param_name in context.files:
|
||||||
context.files[context.param_name].close()
|
context.files[context.param_name].close()
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
@given('the pdf contains {page_count:d} pages with random text')
|
|
||||||
|
def create_pdf_with_black_boxes(file_name, image_count, page_count):
|
||||||
|
|
||||||
|
page_width, page_height = letter
|
||||||
|
writer = PdfWriter()
|
||||||
|
box_counter = 0
|
||||||
|
|
||||||
|
for page in range(page_count):
|
||||||
|
packet = io.BytesIO()
|
||||||
|
can = canvas.Canvas(packet, pagesize=(page_width, page_height))
|
||||||
|
|
||||||
|
boxes_per_page = image_count // page_count + (
|
||||||
|
1 if image_count % page_count != 0 else 0
|
||||||
|
)
|
||||||
|
for i in range(boxes_per_page):
|
||||||
|
if box_counter >= image_count:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Create a black box image
|
||||||
|
dummy_image = Image.new("RGB", (100, 100), color="black")
|
||||||
|
image_bytes = io.BytesIO()
|
||||||
|
dummy_image.save(image_bytes, format="PNG")
|
||||||
|
image_bytes.seek(0)
|
||||||
|
|
||||||
|
x = (i % (page_width // 100)) * 100
|
||||||
|
y = page_height - (((i % (page_height // 100)) + 1) * 100)
|
||||||
|
|
||||||
|
if x + 100 > page_width or y < 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
can.drawImage(ImageReader(image_bytes), x, y, width=100, height=100)
|
||||||
|
box_counter += 1
|
||||||
|
|
||||||
|
can.showPage()
|
||||||
|
can.save()
|
||||||
|
packet.seek(0)
|
||||||
|
new_pdf = PdfReader(packet)
|
||||||
|
writer.add_page(new_pdf.pages[0])
|
||||||
|
|
||||||
|
with open(file_name, "wb") as f:
|
||||||
|
writer.write(f)
|
||||||
|
|
||||||
|
|
||||||
|
@given("the pdf contains {page_count:d} pages with random text")
|
||||||
def step_pdf_contains_pages_with_random_text(context, page_count):
|
def step_pdf_contains_pages_with_random_text(context, page_count):
|
||||||
buffer = io.BytesIO()
|
buffer = io.BytesIO()
|
||||||
c = canvas.Canvas(buffer, pagesize=letter)
|
c = canvas.Canvas(buffer, pagesize=letter)
|
||||||
width, height = letter
|
width, height = letter
|
||||||
|
|
||||||
for _ in range(page_count):
|
for _ in range(page_count):
|
||||||
text = ''.join(random.choices(string.ascii_letters + string.digits, k=100))
|
text = "".join(random.choices(string.ascii_letters + string.digits, k=100))
|
||||||
c.drawString(100, height - 100, text)
|
c.drawString(100, height - 100, text)
|
||||||
c.showPage()
|
c.showPage()
|
||||||
|
|
||||||
c.save()
|
c.save()
|
||||||
|
|
||||||
with open(context.file_name, 'wb') as f:
|
with open(context.file_name, "wb") as f:
|
||||||
f.write(buffer.getvalue())
|
f.write(buffer.getvalue())
|
||||||
|
|
||||||
context.files[context.param_name].close()
|
context.files[context.param_name].close()
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
|
|
||||||
@given('the pdf pages all contain the text "{text}"')
|
@given('the pdf pages all contain the text "{text}"')
|
||||||
def step_pdf_pages_contain_text(context, text):
|
def step_pdf_pages_contain_text(context, text):
|
||||||
@ -192,11 +252,12 @@ def step_pdf_pages_contain_text(context, text):
|
|||||||
|
|
||||||
c.save()
|
c.save()
|
||||||
|
|
||||||
with open(context.file_name, 'wb') as f:
|
with open(context.file_name, "wb") as f:
|
||||||
f.write(buffer.getvalue())
|
f.write(buffer.getvalue())
|
||||||
|
|
||||||
context.files[context.param_name].close()
|
context.files[context.param_name].close()
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
|
|
||||||
@given('the pdf is encrypted with password "{password}"')
|
@given('the pdf is encrypted with password "{password}"')
|
||||||
def step_encrypt_pdf(context, password):
|
def step_encrypt_pdf(context, password):
|
||||||
@ -205,29 +266,34 @@ def step_encrypt_pdf(context, password):
|
|||||||
for i in range(len(reader.pages)):
|
for i in range(len(reader.pages)):
|
||||||
writer.add_page(reader.pages[i])
|
writer.add_page(reader.pages[i])
|
||||||
writer.encrypt(password)
|
writer.encrypt(password)
|
||||||
with open(context.file_name, 'wb') as f:
|
with open(context.file_name, "wb") as f:
|
||||||
writer.write(f)
|
writer.write(f)
|
||||||
context.files[context.param_name].close()
|
context.files[context.param_name].close()
|
||||||
context.files[context.param_name] = open(context.file_name, 'rb')
|
context.files[context.param_name] = open(context.file_name, "rb")
|
||||||
|
|
||||||
@given('the request data is')
|
|
||||||
|
@given("the request data is")
|
||||||
def step_request_data(context):
|
def step_request_data(context):
|
||||||
context.request_data = eval(context.text)
|
context.request_data = eval(context.text)
|
||||||
|
|
||||||
@given('the request data includes')
|
|
||||||
|
@given("the request data includes")
|
||||||
def step_request_data_table(context):
|
def step_request_data_table(context):
|
||||||
context.request_data = {row['parameter']: row['value'] for row in context.table}
|
context.request_data = {row["parameter"]: row["value"] for row in context.table}
|
||||||
|
|
||||||
|
|
||||||
@given('save the generated PDF file as "{filename}" for debugging')
|
@given('save the generated PDF file as "{filename}" for debugging')
|
||||||
def save_generated_pdf(context, filename):
|
def save_generated_pdf(context, filename):
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(context.files[context.param_name].read())
|
f.write(context.files[context.param_name].read())
|
||||||
print(f"Saved generated PDF content to {filename}")
|
print(f"Saved generated PDF content to {filename}")
|
||||||
|
|
||||||
|
|
||||||
########
|
########
|
||||||
# WHEN #
|
# WHEN #
|
||||||
########
|
########
|
||||||
|
|
||||||
|
|
||||||
@when('I send a GET request to "{endpoint}"')
|
@when('I send a GET request to "{endpoint}"')
|
||||||
def step_send_get_request(context, endpoint):
|
def step_send_get_request(context, endpoint):
|
||||||
base_url = "http://localhost:8080"
|
base_url = "http://localhost:8080"
|
||||||
@ -235,20 +301,22 @@ def step_send_get_request(context, endpoint):
|
|||||||
response = requests.get(full_url, headers=API_HEADERS)
|
response = requests.get(full_url, headers=API_HEADERS)
|
||||||
context.response = response
|
context.response = response
|
||||||
|
|
||||||
|
|
||||||
@when('I send a GET request to "{endpoint}" with parameters')
|
@when('I send a GET request to "{endpoint}" with parameters')
|
||||||
def step_send_get_request_with_params(context, endpoint):
|
def step_send_get_request_with_params(context, endpoint):
|
||||||
base_url = "http://localhost:8080"
|
base_url = "http://localhost:8080"
|
||||||
params = {row['parameter']: row['value'] for row in context.table}
|
params = {row["parameter"]: row["value"] for row in context.table}
|
||||||
full_url = f"{base_url}{endpoint}"
|
full_url = f"{base_url}{endpoint}"
|
||||||
response = requests.get(full_url, params=params, headers=API_HEADERS)
|
response = requests.get(full_url, params=params, headers=API_HEADERS)
|
||||||
context.response = response
|
context.response = response
|
||||||
|
|
||||||
|
|
||||||
@when('I send the API request to the endpoint "{endpoint}"')
|
@when('I send the API request to the endpoint "{endpoint}"')
|
||||||
def step_send_api_request(context, endpoint):
|
def step_send_api_request(context, endpoint):
|
||||||
url = f"http://localhost:8080{endpoint}"
|
url = f"http://localhost:8080{endpoint}"
|
||||||
files = context.files if hasattr(context, 'files') else {}
|
files = context.files if hasattr(context, "files") else {}
|
||||||
|
|
||||||
if not hasattr(context, 'request_data') or context.request_data is None:
|
if not hasattr(context, "request_data") or context.request_data is None:
|
||||||
context.request_data = {}
|
context.request_data = {}
|
||||||
|
|
||||||
form_data = []
|
form_data = []
|
||||||
@ -257,130 +325,173 @@ def step_send_api_request(context, endpoint):
|
|||||||
|
|
||||||
for key, file in files.items():
|
for key, file in files.items():
|
||||||
mime_type, _ = mimetypes.guess_type(file.name)
|
mime_type, _ = mimetypes.guess_type(file.name)
|
||||||
mime_type = mime_type or 'application/octet-stream'
|
mime_type = mime_type or "application/octet-stream"
|
||||||
print(f"form_data {file.name} with {mime_type}")
|
print(f"form_data {file.name} with {mime_type}")
|
||||||
form_data.append((key, (file.name, file, mime_type)))
|
form_data.append((key, (file.name, file, mime_type)))
|
||||||
|
|
||||||
response = requests.post(url, files=form_data, headers=API_HEADERS)
|
response = requests.post(url, files=form_data, headers=API_HEADERS)
|
||||||
context.response = response
|
context.response = response
|
||||||
|
|
||||||
|
|
||||||
########
|
########
|
||||||
# THEN #
|
# THEN #
|
||||||
########
|
########
|
||||||
|
|
||||||
|
|
||||||
@then('the response content type should be "{content_type}"')
|
@then('the response content type should be "{content_type}"')
|
||||||
def step_check_response_content_type(context, content_type):
|
def step_check_response_content_type(context, content_type):
|
||||||
actual_content_type = context.response.headers.get('Content-Type', '')
|
actual_content_type = context.response.headers.get("Content-Type", "")
|
||||||
assert actual_content_type.startswith(content_type), f"Expected {content_type} but got {actual_content_type}. Response content: {context.response.content}"
|
assert actual_content_type.startswith(
|
||||||
|
content_type
|
||||||
|
), f"Expected {content_type} but got {actual_content_type}. Response content: {context.response.content}"
|
||||||
|
|
||||||
@then('the response file should have size greater than {size:d}')
|
|
||||||
|
@then("the response file should have size greater than {size:d}")
|
||||||
def step_check_response_file_size(context, size):
|
def step_check_response_file_size(context, size):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
assert len(response_file.getvalue()) > size
|
assert len(response_file.getvalue()) > size
|
||||||
|
|
||||||
@then('the response PDF is not passworded')
|
|
||||||
|
@then("the response PDF is not passworded")
|
||||||
def step_check_response_pdf_not_passworded(context):
|
def step_check_response_pdf_not_passworded(context):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
reader = PdfReader(response_file)
|
reader = PdfReader(response_file)
|
||||||
assert not reader.is_encrypted
|
assert not reader.is_encrypted
|
||||||
|
|
||||||
@then('the response PDF is passworded')
|
|
||||||
|
@then("the response PDF is passworded")
|
||||||
def step_check_response_pdf_passworded(context):
|
def step_check_response_pdf_passworded(context):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
try:
|
try:
|
||||||
reader = PdfReader(response_file)
|
reader = PdfReader(response_file)
|
||||||
assert reader.is_encrypted
|
assert reader.is_encrypted
|
||||||
except PdfReadError as e:
|
except PdfReadError as e:
|
||||||
raise AssertionError(f"Failed to read PDF: {str(e)}. Response content: {context.response.content}")
|
raise AssertionError(
|
||||||
|
f"Failed to read PDF: {str(e)}. Response content: {context.response.content}"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise AssertionError(f"An error occurred: {str(e)}. Response content: {context.response.content}")
|
raise AssertionError(
|
||||||
|
f"An error occurred: {str(e)}. Response content: {context.response.content}"
|
||||||
|
)
|
||||||
|
|
||||||
@then('the response status code should be {status_code:d}')
|
|
||||||
|
@then("the response status code should be {status_code:d}")
|
||||||
def step_check_response_status_code(context, status_code):
|
def step_check_response_status_code(context, status_code):
|
||||||
assert context.response.status_code == status_code, f"Expected status code {status_code} but got {context.response.status_code}"
|
assert (
|
||||||
|
context.response.status_code == status_code
|
||||||
|
), f"Expected status code {status_code} but got {context.response.status_code}"
|
||||||
|
|
||||||
|
|
||||||
@then('the response should contain error message "{message}"')
|
@then('the response should contain error message "{message}"')
|
||||||
def step_check_response_error_message(context, message):
|
def step_check_response_error_message(context, message):
|
||||||
response_json = context.response.json()
|
response_json = context.response.json()
|
||||||
assert response_json.get('error') == message, f"Expected error message '{message}' but got '{response_json.get('error')}'"
|
assert (
|
||||||
|
response_json.get("error") == message
|
||||||
|
), f"Expected error message '{message}' but got '{response_json.get('error')}'"
|
||||||
|
|
||||||
@then('the response PDF should contain {page_count:d} pages')
|
|
||||||
def step_check_response_pdf_page_count(context, page_count):
|
|
||||||
response_file = io.BytesIO(context.response.content)
|
|
||||||
reader = PdfReader(response_file)
|
|
||||||
assert len(reader.pages) == page_count, f"Expected {page_count} pages but got {len(reader.pages)} pages"
|
|
||||||
|
|
||||||
@then('the response PDF metadata should include "{metadata_key}" as "{metadata_value}"')
|
@then('the response PDF metadata should include "{metadata_key}" as "{metadata_value}"')
|
||||||
def step_check_response_pdf_metadata(context, metadata_key, metadata_value):
|
def step_check_response_pdf_metadata(context, metadata_key, metadata_value):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
reader = PdfReader(response_file)
|
reader = PdfReader(response_file)
|
||||||
metadata = reader.metadata
|
metadata = reader.metadata
|
||||||
assert metadata.get("/" + metadata_key) == metadata_value, f"Expected {metadata_key} to be '{metadata_value}' but got '{metadata.get(metadata_key)}'"
|
assert (
|
||||||
|
metadata.get("/" + metadata_key) == metadata_value
|
||||||
|
), f"Expected {metadata_key} to be '{metadata_value}' but got '{metadata.get(metadata_key)}'"
|
||||||
|
|
||||||
|
|
||||||
@then('the response file should have extension "{extension}"')
|
@then('the response file should have extension "{extension}"')
|
||||||
def step_check_response_file_extension(context, extension):
|
def step_check_response_file_extension(context, extension):
|
||||||
content_disposition = context.response.headers.get('Content-Disposition', '')
|
content_disposition = context.response.headers.get("Content-Disposition", "")
|
||||||
filename = ""
|
filename = ""
|
||||||
if content_disposition:
|
if content_disposition:
|
||||||
parts = content_disposition.split(';')
|
parts = content_disposition.split(";")
|
||||||
for part in parts:
|
for part in parts:
|
||||||
if part.strip().startswith('filename'):
|
if part.strip().startswith("filename"):
|
||||||
filename = part.split('=')[1].strip().strip('"')
|
filename = part.split("=")[1].strip().strip('"')
|
||||||
break
|
break
|
||||||
assert filename.endswith(extension), f"Expected file extension {extension} but got {filename}. Response content: {context.response.content}"
|
assert filename.endswith(
|
||||||
|
extension
|
||||||
|
), f"Expected file extension {extension} but got {filename}. Response content: {context.response.content}"
|
||||||
|
|
||||||
|
|
||||||
@then('save the response file as "{filename}" for debugging')
|
@then('save the response file as "{filename}" for debugging')
|
||||||
def step_save_response_file(context, filename):
|
def step_save_response_file(context, filename):
|
||||||
with open(filename, 'wb') as f:
|
with open(filename, "wb") as f:
|
||||||
f.write(context.response.content)
|
f.write(context.response.content)
|
||||||
print(f"Saved response content to {filename}")
|
print(f"Saved response content to {filename}")
|
||||||
|
|
||||||
@then('the response PDF should contain {page_count:d} pages')
|
|
||||||
|
@then("the response PDF should contain {page_count:d} pages")
|
||||||
def step_check_response_pdf_page_count(context, page_count):
|
def step_check_response_pdf_page_count(context, page_count):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
reader = PdfReader(io.BytesIO(response_file.getvalue()))
|
reader = PdfReader(io.BytesIO(response_file.getvalue()))
|
||||||
actual_page_count = len(reader.pages)
|
actual_page_count = len(reader.pages)
|
||||||
assert actual_page_count == page_count, f"Expected {page_count} pages but got {actual_page_count} pages"
|
assert (
|
||||||
|
actual_page_count == page_count
|
||||||
|
), f"Expected {page_count} pages but got {actual_page_count} pages"
|
||||||
|
|
||||||
@then('the response ZIP should contain {file_count:d} files')
|
|
||||||
|
@then("the response ZIP should contain {file_count:d} files")
|
||||||
def step_check_response_zip_file_count(context, file_count):
|
def step_check_response_zip_file_count(context, file_count):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
with zipfile.ZipFile(io.BytesIO(response_file.getvalue())) as zip_file:
|
with zipfile.ZipFile(io.BytesIO(response_file.getvalue())) as zip_file:
|
||||||
actual_file_count = len(zip_file.namelist())
|
actual_file_count = len(zip_file.namelist())
|
||||||
assert actual_file_count == file_count, f"Expected {file_count} files but got {actual_file_count} files"
|
assert (
|
||||||
|
actual_file_count == file_count
|
||||||
|
), f"Expected {file_count} files but got {actual_file_count} files"
|
||||||
|
|
||||||
@then('the response ZIP file should contain {doc_count:d} documents each having {pages_per_doc:d} pages')
|
|
||||||
|
@then(
|
||||||
|
"the response ZIP file should contain {doc_count:d} documents each having {pages_per_doc:d} pages"
|
||||||
|
)
|
||||||
def step_check_response_zip_doc_page_count(context, doc_count, pages_per_doc):
|
def step_check_response_zip_doc_page_count(context, doc_count, pages_per_doc):
|
||||||
response_file = io.BytesIO(context.response.content)
|
response_file = io.BytesIO(context.response.content)
|
||||||
with zipfile.ZipFile(io.BytesIO(response_file.getvalue())) as zip_file:
|
with zipfile.ZipFile(io.BytesIO(response_file.getvalue())) as zip_file:
|
||||||
actual_doc_count = len(zip_file.namelist())
|
actual_doc_count = len(zip_file.namelist())
|
||||||
assert actual_doc_count == doc_count, f"Expected {doc_count} documents but got {actual_doc_count} documents"
|
assert (
|
||||||
|
actual_doc_count == doc_count
|
||||||
|
), f"Expected {doc_count} documents but got {actual_doc_count} documents"
|
||||||
|
|
||||||
for file_name in zip_file.namelist():
|
for file_name in zip_file.namelist():
|
||||||
with zip_file.open(file_name) as pdf_file:
|
with zip_file.open(file_name) as pdf_file:
|
||||||
reader = PdfReader(pdf_file)
|
reader = PdfReader(pdf_file)
|
||||||
actual_pages_per_doc = len(reader.pages)
|
actual_pages_per_doc = len(reader.pages)
|
||||||
assert actual_pages_per_doc == pages_per_doc, f"Expected {pages_per_doc} pages per document but got {actual_pages_per_doc} pages in document {file_name}"
|
assert (
|
||||||
|
actual_pages_per_doc == pages_per_doc
|
||||||
|
), f"Expected {pages_per_doc} pages per document but got {actual_pages_per_doc} pages in document {file_name}"
|
||||||
|
|
||||||
|
|
||||||
@then('the JSON value of "{key}" should be "{expected_value}"')
|
@then('the JSON value of "{key}" should be "{expected_value}"')
|
||||||
def step_check_json_value(context, key, expected_value):
|
def step_check_json_value(context, key, expected_value):
|
||||||
actual_value = context.response.json().get(key)
|
actual_value = context.response.json().get(key)
|
||||||
assert actual_value == expected_value, \
|
assert (
|
||||||
f"Expected JSON value for '{key}' to be '{expected_value}' but got '{actual_value}'"
|
actual_value == expected_value
|
||||||
|
), f"Expected JSON value for '{key}' to be '{expected_value}' but got '{actual_value}'"
|
||||||
|
|
||||||
@then('JSON list entry containing "{identifier_key}" as "{identifier_value}" should have "{target_key}" as "{target_value}"')
|
|
||||||
def step_check_json_list_entry(context, identifier_key, identifier_self, target_key, target_value):
|
@then(
|
||||||
|
'JSON list entry containing "{identifier_key}" as "{identifier_value}" should have "{target_key}" as "{target_value}"'
|
||||||
|
)
|
||||||
|
def step_check_json_list_entry(
|
||||||
|
context, identifier_key, identifier_self, target_key, target_value
|
||||||
|
):
|
||||||
json_response = context.response.json()
|
json_response = context.response.json()
|
||||||
for entry in json_response:
|
for entry in json_response:
|
||||||
if entry.get(identifier_key) == identifier_value:
|
if entry.get(identifier_key) == identifier_value:
|
||||||
assert entry.get(target_key) == target_value, \
|
assert (
|
||||||
f"Expected {target_key} to be {target_value} in entry where {identifier_key} is {identifier_value}, but found {entry.get(target_key)}"
|
entry.get(target_key) == target_value
|
||||||
|
), f"Expected {target_key} to be {target_value} in entry where {identifier_key} is {identifier_value}, but found {entry.get(target_key)}"
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise AssertionError(f"No entry with {identifier_key} as {identifier_value} found")
|
raise AssertionError(
|
||||||
|
f"No entry with {identifier_key} as {identifier_value} found"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@then('the response should match the regex "{pattern}"')
|
@then('the response should match the regex "{pattern}"')
|
||||||
def step_response_matches_regex(context, pattern):
|
def step_response_matches_regex(context, pattern):
|
||||||
response_text = context.response.text
|
response_text = context.response.text
|
||||||
assert re.match(pattern, response_text), \
|
assert re.match(
|
||||||
f"Response '{response_text}' does not match the expected pattern '{pattern}'"
|
pattern, response_text
|
||||||
|
), f"Response '{response_text}' does not match the expected pattern '{pattern}'"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user