+ {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
{isNotAvailable ? "—" : formatPrice(intl, hotelPrice, currency)}
diff --git a/apps/scandic-web/jest.config.ts b/apps/scandic-web/jest.config.ts
index bf51303a6..06ae053e3 100644
--- a/apps/scandic-web/jest.config.ts
+++ b/apps/scandic-web/jest.config.ts
@@ -3,15 +3,18 @@
* https://jestjs.io/docs/configuration
*/
import nextJest from "next/jest.js"
+import { createJsWithTsEsmPreset } from "ts-jest"
import type { Config } from "jest"
+const presetConfig = createJsWithTsEsmPreset()
+
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: "./",
})
-const config: Config = {
+const config = {
// All imported modules in your tests should be mocked automatically
// automock: false,
@@ -202,6 +205,8 @@ const config: Config = {
// Whether to use watchman for file crawling
// watchman: true,
-}
+
+ ...presetConfig,
+} satisfies Config
export default createJestConfig(config)
diff --git a/apps/scandic-web/jest.setup.ts b/apps/scandic-web/jest.setup.ts
index 31fe0b102..ec0e23ec3 100644
--- a/apps/scandic-web/jest.setup.ts
+++ b/apps/scandic-web/jest.setup.ts
@@ -1,6 +1,8 @@
import "@testing-library/jest-dom/jest-globals"
import "@testing-library/jest-dom"
+import { jest } from "@jest/globals"
+
jest.mock("next/navigation", () => ({
useRouter: jest.fn(),
usePathname: jest.fn().mockReturnValue("/"),
diff --git a/apps/scandic-web/package.json b/apps/scandic-web/package.json
index e5a8c8b7e..475b61e7e 100644
--- a/apps/scandic-web/package.json
+++ b/apps/scandic-web/package.json
@@ -15,8 +15,8 @@
"test:e2e:headless": "start-server-and-test test:setup http://127.0.0.1:3000/en/sponsoring \"cypress run --e2e\"",
"test:setup": "yarn build && yarn start",
"preinstall": "/bin/sh -c \"export $(cat .env.local | grep -v '^#' | xargs)\"",
- "test": "jest",
- "test:watch": "jest --watch",
+ "test": "node --experimental-vm-modules $(yarn bin jest)",
+ "test:watch": "node --experimental-vm-modules $(yarn bin jest) --watch",
"ci:build": "yarn lint && yarn test && yarn build",
"clean": "rm -rf .next",
"i18n:extract": "formatjs extract \"{actions,app,components,constants,hooks,i18n,lib,middlewares,server,stores,utils}/**/*.{ts,tsx}\" --format i18n/tooling/formatter.mjs --out-file i18n/tooling/extracted.json",
@@ -76,6 +76,7 @@
"embla-carousel-react": "^8.5.2",
"fast-deep-equal": "^3.1.3",
"fetch-retry": "^6.0.0",
+ "flat": "^6.0.1",
"framer-motion": "^11.3.28",
"fuse.js": "^7.1.0",
"graphql": "^16.8.1",
@@ -88,6 +89,7 @@
"ioredis": "^5.5.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"libphonenumber-js": "^1.10.60",
+ "lodash-es": "^4.17.21",
"nanoid": "^5.0.9",
"next": "^14.2.25",
"next-auth": "5.0.0-beta.19",
@@ -101,7 +103,6 @@
"react-international-phone": "^4.2.6",
"react-intl": "^6.6.8",
"react-to-print": "^3.0.2",
- "secure-json-parse": "^4.0.0",
"server-only": "^0.0.1",
"slugify": "^1.6.6",
"sonner": "^1.7.0",
@@ -124,6 +125,7 @@
"@types/adm-zip": "^0.5.7",
"@types/jest": "^29.5.12",
"@types/json-stable-stringify-without-jsonify": "^1.0.2",
+ "@types/lodash-es": "^4",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
@@ -148,6 +150,7 @@
"react-material-symbols": "^4.4.0",
"schema-dts": "^1.1.2",
"start-server-and-test": "^2.0.3",
+ "ts-jest": "^29.3.2",
"ts-morph": "^25.0.1",
"ts-node": "^10.9.2",
"typescript": "5.4.5",
diff --git a/apps/scandic-web/server/routers/booking/mutation.ts b/apps/scandic-web/server/routers/booking/mutation.ts
index 2a6225f43..4b50a87e9 100644
--- a/apps/scandic-web/server/routers/booking/mutation.ts
+++ b/apps/scandic-web/server/routers/booking/mutation.ts
@@ -1,12 +1,8 @@
-import { metrics } from "@opentelemetry/api"
-import sjson from "secure-json-parse"
-
import * as api from "@/lib/api"
-import { getVerifiedUser } from "@/server/routers/user/query"
+import { getMembershipNumber } from "@/server/routers/user/utils"
+import { createCounter } from "@/server/telemetry"
import { router, safeProtectedServiceProcedure } from "@/server/trpc"
-import { isValidSession } from "@/utils/session"
-
import {
addPackageInput,
cancelBookingInput,
@@ -18,75 +14,6 @@ import {
} from "./input"
import { bookingConfirmationSchema, createBookingSchema } from "./output"
-import type { Session } from "next-auth"
-
-const meter = metrics.getMeter("trpc.bookings")
-const createBookingCounter = meter.createCounter("trpc.bookings.create")
-const createBookingSuccessCounter = meter.createCounter(
- "trpc.bookings.create-success"
-)
-const createBookingFailCounter = meter.createCounter(
- "trpc.bookings.create-fail"
-)
-
-const priceChangeCounter = meter.createCounter("trpc.bookings.price-change")
-const priceChangeSuccessCounter = meter.createCounter(
- "trpc.bookings.price-change-success"
-)
-const priceChangeFailCounter = meter.createCounter(
- "trpc.bookings.price-change-fail"
-)
-const cancelBookingCounter = meter.createCounter("trpc.bookings.cancel")
-const cancelBookingSuccessCounter = meter.createCounter(
- "trpc.bookings.cancel-success"
-)
-const cancelBookingFailCounter = meter.createCounter(
- "trpc.bookings.cancel-fail"
-)
-
-const addPackageCounter = meter.createCounter("trpc.bookings.add-package")
-const addPackageSuccessCounter = meter.createCounter(
- "trpc.bookings.add-package-success"
-)
-const addPackageFailCounter = meter.createCounter(
- "trpc.bookings.add-package-fail"
-)
-const guaranteeBookingCounter = meter.createCounter("trpc.bookings.guarantee")
-const guaranteeBookingSuccessCounter = meter.createCounter(
- "trpc.bookings.guarantee-success"
-)
-const guaranteeBookingFailCounter = meter.createCounter(
- "trpc.bookings.guarantee-fail"
-)
-const updateBookingCounter = meter.createCounter("trpc.bookings.update-booking")
-const updateBookingSuccessCounter = meter.createCounter(
- "trpc.bookings.update-booking-success"
-)
-const updateBookingFailCounter = meter.createCounter(
- "trpc.bookings.update-booking-fail"
-)
-
-const removePackageCounter = meter.createCounter("trpc.bookings.remove-package")
-const removePackageSuccessCounter = meter.createCounter(
- "trpc.bookings.remove-package-success"
-)
-const removePackageFailCounter = meter.createCounter(
- "trpc.bookings.remove-package-fail"
-)
-
-async function getMembershipNumber(
- session: Session | null
-): Promise