Skip to content

Latest commit

 

History

History
372 lines (282 loc) · 14.2 KB

development.md

File metadata and controls

372 lines (282 loc) · 14.2 KB

Development & Testing

Part of the Crispy Print documentation.

Testing

This app includes comprehensive test coverage:

  • 293 default frontend tests across 69 Vitest files (plus opt-in Typst integration tests)
  • 467 backend tests in the complete Frappe application suite (5 optional integration tests skipped)
  • Test frameworks: Vitest (frontend), Frappe Test Runner (backend)

Some backend integration tests depend on site fixtures and optional Typst CLI integration settings.

RTL browser and PDF checks

The Playwright suite uses deterministic Chromium, a 1440×1000 viewport, and Asia/Kuwait. Seed or prepare the named RTL format, then run:

yarn --cwd e2e install
yarn --cwd e2e playwright install chromium

bench --site your-site execute crispy_print.dev_utils.rtl_e2e.seed

CRISPY_E2E_BASE_URL=http://fdev.local:8000 \
CRISPY_E2E_USER=Administrator \
CRISPY_E2E_PASSWORD=admin \
CRISPY_E2E_FORMAT_AR="Crispy RTL E2E Arabic" \
CRISPY_E2E_FORMAT_FA="Crispy RTL E2E Persian" \
CRISPY_E2E_FORMAT_EN="Crispy RTL E2E English" \
CRISPY_E2E_FORMAT_MULTIPAGE="Crispy RTL E2E Multipage" \
CRISPY_E2E_FORMAT_REPORT="Crispy RTL E2E Report" \
CRISPY_E2E_DOCNAME="ACC-SINV-..." \
yarn test:e2e

The default seed creates language-specific Arabic, Persian, and English formats, plus deterministic multipage and General Ledger report formats. It also configures a basic QR payload. It never combines Arabic and Persian labels in one document.

For a disposable test site, the seed can create or refresh a dedicated least-surprise browser user without placing credentials in the repository:

bench --site your-site execute crispy_print.dev_utils.rtl_e2e.seed \
  --kwargs '{"test_user_password": "local-secret"}'

# After the browser run:
bench --site your-site execute crispy_print.dev_utils.rtl_e2e.disable_test_user

The dedicated user is opt-in and is never created during app installation or a normal seed run.

The seed does not activate a frozen Crispy Template by default. On a disposable acceptance site only, pass --kwargs '{"publish": 1}' to publish the Arabic fixture and supply its returned template ID through CRISPY_E2E_TEMPLATE. Publishing may supersede another active Sales Invoice template for the same company, so never enable this on a production or shared-authoring site.

The isolated e2e/package.json is intentionally not installed by Bench during normal Crispy Print installation. Chromium is downloaded only by the explicit yarn playwright install chromium command. Screenshots, reports, traces, and other browser output are local ignored artifacts rather than application assets.

Custom and Regulatory QR acceptance

Run this only on a disposable development site. The seed is idempotent, uses existing draft/submitted ERPNext documents, creates isolated Crispy Formats, and labels its ZATCA profile as non-certifying:

bench --site your-site execute \
  crispy_print.dev_utils.rtl_e2e.seed_qr_acceptance \
  --kwargs '{"publish": 1, "test_user_password": "local-secret"}'

Copy the returned document names into the browser matrix:

CRISPY_E2E_BASE_URL=https://your-site \
CRISPY_E2E_USER=crispy-rtl-e2e@local.test \
CRISPY_E2E_PASSWORD=local-secret \
CRISPY_QR_E2E_SALES_INVOICE=ACC-SINV-... \
CRISPY_QR_E2E_PURCHASE_INVOICE=ACC-PINV-... \
CRISPY_QR_E2E_DELIVERY_NOTE=MAT-DN-... \
CRISPY_QR_E2E_PAYMENT_ENTRY=ACC-PAY-... \
yarn --cwd e2e playwright test qr.spec.ts

The suite verifies exact field order, English/Arabic/Persian editor behavior, cross-DocType rendering, legacy save blocking, live regulatory-profile resolution, real QR decoding, and preview-source/final-PDF payload equality. It uses @zxing/library, pngjs, and pdftoppm only inside the isolated E2E toolchain. PDFs, rendered PNGs, traces, and failure screenshots remain under ignored test-results/ paths. Disable the test user afterward with crispy_print.dev_utils.rtl_e2e.disable_test_user.

The bundled ZATCA registry/profile fixture proves the implementation path; it does not constitute jurisdictional certification.

Core v1 business-format acceptance

On a disposable site, create the ten company-scoped formats and discover or create their representative ERPNext documents:

bench --site your-site execute \
  crispy_print.dev_utils.business_formats_e2e.seed \
  --kwargs '{"test_user_password":"local-secret"}'

Supply the returned Payment Entry, Stock Entry, Material Request, ordinary and cash Journal Entry, and POS Invoice names as CRISPY_V1_E2E_* environment variables, then run:

yarn --cwd e2e playwright test business-formats.spec.ts

The matrix also executes General Ledger, Accounts Receivable, and Accounts Payable previews. It accepts rendered PDF.js canvases and rejects explicit report errors. See Core v1 Business-Format Acceptance for the full catalog and boundary.

Afterward, delete only the fixed-name formats and disposable draft documents and disable the browser user:

bench --site your-site execute crispy_print.dev_utils.business_formats_e2e.cleanup
bench --site your-site execute crispy_print.dev_utils.rtl_e2e.disable_test_user

Use yarn test:e2e:update to generate local screenshots for visual review. The acceptance matrix covers Arabic and Persian UI roots, localized fixture labels, portal direction, keyboard and drag interaction, physical LTR canvas/editor islands, multipage output, a deterministic RTL report, and an optional published-template final preview. Typst integration tests assert negative-sign order, document metadata, mixed-direction values, font fallbacks, schema compatibility, and DocType/Report parity. Native Arabic review was completed by Agathodaemon on 2026-07-28; changes affecting Arabic wording or presentation surfaces require renewed review. Native Persian review remains required.

Sample Crispy Formats are not exported through Frappe fixtures. Keep curated examples as company-neutral JSON files under crispy_print/examples/formats/ and load them through the Sample Format Catalog APIs. Do not re-add fixtures = [{"dt": "Crispy Format"}] or a production fixtures/crispy_format.json file for demo data; rich local demo generation belongs in crispy_print/dev_utils/.

Development

Required Toolchain

  • Node.js 24.18.0 LTS (pinned by .node-version)
  • Yarn 1.22.22 Classic
  • Python 3.10+
  • Typst CLI 0.15.0+

Yarn Modern is not supported by the Frappe v15 build workflow used for Beta 2.

Frontend Dependencies

For TypeScript/Vue IntelliSense in VS Code and the color picker bundle (@simonwep/pickr):

cd apps/crispy_print/crispy_print/public/js
yarn install

This installs local dependencies used by the frontend bundle:

  • package.json, yarn.lock - Type dependencies
  • tsconfig.json - TypeScript configuration
  • node_modules/ - Type definitions

Note: Required for building.

Building

# Build the app
bench build --app crispy_print

# Clear cache after changes
bench clear-cache && bench clear-website-cache

# Development workflow
bench start  # Run with auto-reload enabled

Running Tests

Frontend Tests (TypeScript/Vue):

cd apps/crispy_print/crispy_print/public/js

# Run all tests
yarn test:unit

# Run specific batch
yarn test:unit:batch6

# Watch mode
yarn test:unit -- --watch

Backend Tests (Python):

# Run all tests
bench --site your-site run-tests --app crispy_print

# Run specific module
bench --site your-site run-tests --module crispy_print.tests.test_api

# Run DocType tests
bench --site your-site run-tests --doctype "Crispy Format"

Current release validation:

  • Frontend: 293 default tests passed across 69 files, plus opt-in real-Typst RTL/PDF and business-format compilation tests
  • Backend: 467 tests passed, with 5 optional integration tests skipped
  • Browser: authenticated RTL DocType/Report and Custom/Regulatory QR Playwright matrices, including real QR decoding and final-PDF parity
  • Additional gates: strict TypeScript, pre-commit, ESLint, Prettier, repeated migrations, and a complete production Bench asset build

Every release candidate must also pass the explicit Frappe/ERPNext v15/v16/current-dev-17 clean-install CI matrix. See Release and Compatibility Gates.

The clean-site backend gate installs the official Payments companion app before ERPNext (version-15, version-16, or develop to match the target). Payments is not declared as a Crispy Print dependency and normal Crispy Print installation does not fetch or install it.

Some backend integration tests depend on site fixtures and optional Typst CLI integration settings.

Translation Catalog Checks

Crispy Print stores its source catalog and translated catalogs under crispy_print/locale/. After changing translatable source strings, regenerate the POT file and synchronize every PO catalog:

bench generate-pot-file --app crispy_print
bench update-po-files --app crispy_print

Validate gettext syntax and runtime formatting before committing translation changes:

find apps/crispy_print/crispy_print/locale -maxdepth 1 -name '*.po' -print0 \
  | xargs -0 -n 1 msgfmt --check --check-format -o /dev/null
bench compile-po-to-mo --app crispy_print --force

PO changes must preserve runtime placeholders, HTML tags, and the contents of <code> elements. See the translation guide for the included locales, contribution policy, and native-review expectations.

Sample format catalog checks:

bench --site your-site run-tests --app crispy_print --module crispy_print.tests.api.test_sample_formats
cd apps/crispy_print/crispy_print/public/js
yarn vitest run tests/batch15/formatImportExportApi.test.ts tests/batch16/crispyPFBLayout.test.ts tests/batch18/sampleFormatsDialog.test.ts

QR Field Registry Checks

QR/document-code selected fields use a repo-owned backend registry and Frappe child rows. After registry or selected-field model changes, run:

bench --site your-site execute crispy_print.dev_utils.qr_registry_smoke.run
bench --site your-site run-tests --app crispy_print --module crispy_print.tests.qr_registry.test_loader
bench --site your-site run-tests --app crispy_print --module crispy_print.crispy_print.doctype.crispy_document_code_profile.test_crispy_document_code_profile
bench --site your-site run-tests --app crispy_print --module crispy_print.tests.api.test_document_codes

Run bench migrate when DocType metadata or migration patches change. The selected-fields migration converts safe legacy selected_fields_json values into Crispy Document Code Field child rows when a single target DocType can be inferred.

Vue Component Guidelines

All Vue components use <style scoped> blocks. CSS is automatically extracted and inlined:

<template>
  <div class="my-component">Content</div>
</template>

<script setup lang="ts">
// Component logic with Composition API
</script>

<style scoped>
/* Scoped styles - automatically inlined */
.my-component {
  padding: 1rem;
}
</style>

For dynamically created DOM (e.g., .typst-page elements), apply styles via JavaScript:

const page = document.createElement("div");
page.className = "typst-page";
page.style.marginBottom = "1.5rem";
page.style.boxShadow = "0 4px 12px rgba(148, 163, 184, 0.25)";

Updating the vendored PDF.js assets

The PDF.js module, worker, and license are committed deployment assets. Normal Bench builds do not copy or modify them. Upgrade them with these developer commands from the Crispy Print repository, using the supported Node version:

  1. Set pdfjs-dist in crispy_print/public/js/package.json to an exact stable three-part version and update the nested yarn.lock. Ranges, tags, pre-release versions, and build metadata are not accepted.
  2. Install the locked dependencies with yarn --cwd crispy_print/public/js install --frozen-lockfile.
  3. Run yarn sync:pdfjs.
  4. Run yarn check:pdfjs.
  5. Run yarn test:pdfjs and the relevant unit tests.
  6. Run bench build --app crispy_print from the active Bench.
  7. Verify real PDF.js worker startup and PDF rendering in both complete print and format-builder previews with the built-in browser.
  8. Review and commit the dependency pin, lockfile, and synchronized vendor files.

sync:pdfjs copies both legacy minified modules and LICENSE from the same installed pdfjs-dist package. It preserves their bytes and publishes versioned .js names, such as pdf-6.1.200.min.js and pdf.worker-6.1.200.min.js. The loader derives both URLs from the package pin through a JSON import; there is no generated TypeScript or second version constant.

The script validates all source files, version headers, and destination paths before writing. It stages the complete replacement set, then renames files into place. Each rename is atomic; the complete update is not. A partial failure reports which managed files changed. Rerun yarn sync:pdfjs to repair the set. Inspect the diff before any targeted recovery; do not use a blanket git restore. A second successful run makes no writes.

The script owns only LICENSE and filenames matching pdf-<version>.min.js or pdf.worker-<version>.min.js in crispy_print/public/vendor/pdfjs/. It preserves unrelated files and rejects managed symlinks. It removes previous managed versions after replacements succeed. Since deployment assets can point directly at this folder, an open browser tab may need a reload after an upgrade. Old deployed URLs are not retained.

check:pdfjs is read-only. It verifies the exact stable pin, installed package version, expected managed file set, and byte-for-byte module, worker, and license contents. Continuous integration runs it after installing the locked nested dependencies. CI never synchronizes or silently repairs stale assets. The tooling acceptance tests use disposable fixture directories; the loader unit test checks URL construction separately.

The .js extension avoids requiring an additional .mjs content-type mapping. When changing the asset-loading contract, also test through isolated Nginx without an .mjs mapping; the Bench development server alone cannot reproduce that fault. Use a separate loopback port, stop the test instance afterward, and preserve the normal Caddy configuration. Browser testing remains required after each PDF.js upgrade, even when all file checks pass.