From 1bc883906fe6c7912144e8874a9d53feb1ee7313 Mon Sep 17 00:00:00 2001 From: CropWatch <111664979+CropWatchDevelopment@users.noreply.github.com> Date: Sat, 14 Jun 2025 13:03:07 +0900 Subject: [PATCH 1/2] add basic unit and e2e tests --- e2e/routes.test.ts | 30 ++++++++++++++++++ .../components/vendor/animated-lines.spec.ts | 31 +++++++++++++++++++ src/lib/data/products/cw-air-th.spec.ts | 13 ++++++++ src/lib/data/products/cw-ss.spec.ts | 13 ++++++++ 4 files changed, 87 insertions(+) create mode 100644 e2e/routes.test.ts create mode 100644 src/lib/components/vendor/animated-lines.spec.ts create mode 100644 src/lib/data/products/cw-air-th.spec.ts create mode 100644 src/lib/data/products/cw-ss.spec.ts diff --git a/e2e/routes.test.ts b/e2e/routes.test.ts new file mode 100644 index 0000000..57b78e1 --- /dev/null +++ b/e2e/routes.test.ts @@ -0,0 +1,30 @@ +import { test, expect } from '@playwright/test'; + +test.describe('static pages', () => { + test('about page loads', async ({ page }) => { + await page.goto('/about-us'); + await expect(page.locator('h1')).toContainText('About Us'); + }); + + test('contact page displays form', async ({ page }) => { + await page.goto('/contact-us'); + await expect(page.locator('form')).toBeVisible(); + }); + + test('privacy policy page loads', async ({ page }) => { + await page.goto('/privacy-policy'); + await expect(page.locator('h1')).toBeVisible(); + }); +}); + +test.describe('product pages', () => { + test('cw-air-th product page', async ({ page }) => { + await page.goto('/product/cw-air-th'); + await expect(page.locator('h1')).toContainText('CropWatch Air Temperature'); + }); + + test('cw-ss product page', async ({ page }) => { + await page.goto('/product/cw-ss'); + await expect(page.locator('h1')).toContainText('CropWatch Soil Sensor'); + }); +}); diff --git a/src/lib/components/vendor/animated-lines.spec.ts b/src/lib/components/vendor/animated-lines.spec.ts new file mode 100644 index 0000000..bb3a34a --- /dev/null +++ b/src/lib/components/vendor/animated-lines.spec.ts @@ -0,0 +1,31 @@ +const globalAny: any = globalThis as any; +if (!globalAny.window) { globalAny.window = { addEventListener() {}, removeEventListener() {} }; } + +import { describe, it, expect } from 'vitest'; +import LinkedParticles from './animated-lines.js'; + +describe('LinkedParticles', () => { + it('initializes with the correct number of points', () => { + const ctx = { + canvas: { + width: 100, + height: 100, + addEventListener() {}, + removeEventListener() {} + }, + clearRect() {}, + fillRect() {}, + beginPath() {}, + moveTo() {}, + lineTo() {}, + stroke() {}, + closePath() {}, + fill() {}, + arc() {}, + createLinearGradient() { return { addColorStop() {} }; } + } as unknown as CanvasRenderingContext2D; + + const lp = new (LinkedParticles as any)(ctx); + expect(lp.points.length).toBe(lp.points_count); + }); +}); diff --git a/src/lib/data/products/cw-air-th.spec.ts b/src/lib/data/products/cw-air-th.spec.ts new file mode 100644 index 0000000..e8857bf --- /dev/null +++ b/src/lib/data/products/cw-air-th.spec.ts @@ -0,0 +1,13 @@ +import { describe, it, expect } from 'vitest'; +import cwAirThProduct from './cw-air-th'; + +describe('cwAirThProduct', () => { + it('includes basic product info', () => { + expect(cwAirThProduct.name).toBe('CropWatch Air Temperature & Humidity Sensor'); + expect(cwAirThProduct.models[0].id).toBe('CW-AIR-TH'); + }); + + it('lists standout features', () => { + expect(cwAirThProduct.standoutFeatures.length).toBeGreaterThan(0); + }); +}); diff --git a/src/lib/data/products/cw-ss.spec.ts b/src/lib/data/products/cw-ss.spec.ts new file mode 100644 index 0000000..4995275 --- /dev/null +++ b/src/lib/data/products/cw-ss.spec.ts @@ -0,0 +1,13 @@ +import { describe, it, expect } from 'vitest'; +import cwSSProduct from './cw-ss'; + +describe('cwSSProduct', () => { + it('includes basic product info', () => { + expect(cwSSProduct.name).toBe('CropWatch Soil Sensor'); + expect(cwSSProduct.models[0].id).toBe('CW-SS-TMEPNPK'); + }); + + it('lists standout features', () => { + expect(cwSSProduct.standoutFeatures.length).toBeGreaterThan(0); + }); +}); From e66ca67c2c26008f4264887c681959aaa5ad155b Mon Sep 17 00:00:00 2001 From: CropWatch <111664979+CropWatchDevelopment@users.noreply.github.com> Date: Sat, 14 Jun 2025 13:36:47 +0900 Subject: [PATCH 2/2] vendor modules locally --- package.json | 7 +++ playwright.config.ts | 10 ++--- pnpm-lock.yaml | 83 ++++++++++++++++++++++++++++++++++++ project.inlang/settings.json | 18 ++++---- 4 files changed, 104 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 8e4316e..52c9184 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,13 @@ "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", "@fontsource/fira-mono": "^5.0.0", + "@inlang/message-lint-rule-empty-pattern": "1", + "@inlang/message-lint-rule-identical-pattern": "1", + "@inlang/message-lint-rule-missing-translation": "1", + "@inlang/message-lint-rule-valid-js-identifier": "1", + "@inlang/message-lint-rule-without-source": "1", + "@inlang/plugin-m-function-matcher": "0", + "@inlang/plugin-message-format": "2", "@neoconfetti/svelte": "^2.0.0", "@playwright/test": "^1.49.1", "@sveltejs/adapter-vercel": "^5.5.2", diff --git a/playwright.config.ts b/playwright.config.ts index d76ea26..ba07d25 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,10 +1,10 @@ import { defineConfig } from '@playwright/test'; export default defineConfig({ - webServer: { - command: 'npm run build && npm run preview', - port: 4173 - }, + webServer: { + command: 'PUBLIC_RECAPTCHA_SITE_KEY=test PRIVATE_GOOGLE_RECAPTCHA_SECRET_KEY=test PRIVATE_EMAIL_HOST=localhost PRIVATE_EMAIL_PORT=1025 PRIVATE_EMAIL_USERNAME=user PRIVATE_EMAIL_PASSWORD=pass npm run build && npm run preview', + port: 4173 + }, - testDir: 'e2e' + testDir: 'e2e' }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74230ca..d4697a8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,27 @@ importers: '@fontsource/fira-mono': specifier: ^5.0.0 version: 5.1.1 + '@inlang/message-lint-rule-empty-pattern': + specifier: '1' + version: 1.4.8(@sinclair/typebox@0.31.28) + '@inlang/message-lint-rule-identical-pattern': + specifier: '1' + version: 1.5.9 + '@inlang/message-lint-rule-missing-translation': + specifier: '1' + version: 1.4.8(@sinclair/typebox@0.31.28) + '@inlang/message-lint-rule-valid-js-identifier': + specifier: '1' + version: 1.0.8(@sinclair/typebox@0.31.28) + '@inlang/message-lint-rule-without-source': + specifier: '1' + version: 1.4.8(@sinclair/typebox@0.31.28) + '@inlang/plugin-m-function-matcher': + specifier: '0' + version: 0.9.36(@sinclair/typebox@0.31.28) + '@inlang/plugin-message-format': + specifier: '2' + version: 2.2.0 '@neoconfetti/svelte': specifier: ^2.0.0 version: 2.2.1 @@ -469,19 +490,38 @@ packages: '@inlang/json-types@1.1.0': resolution: {integrity: sha512-n6vS6AqETsCFbV4TdBvR/EH57waVXzKsMqeUQ+eH2Q6NUATfKhfLabgNms2A+QV3aedH/hLtb1pRmjl2ykBVZg==} + deprecated: no longer used peerDependencies: '@sinclair/typebox': ^0.31.0 '@inlang/language-tag@1.5.1': resolution: {integrity: sha512-+NlYDxDvN5h/TKUmkuQv+Ct1flxaVRousCbek7oFEk3/afZPVLNTJhm+cX2xiOg3tmi2KKrBLfy/V9oUDHj6GQ==} + deprecated: use the inlang sdk directly https://www.npmjs.com/package/@inlang/sdk + + '@inlang/message-lint-rule-empty-pattern@1.4.8': + resolution: {integrity: sha512-2svMrCYsvIn/GT9mclhLPnZfkftxaHt2yFuIfgvSyfwge64xjm+mO4x0YdfFTh2Xt7Kc8Y4GJZwbmNu8iYDZWg==} + + '@inlang/message-lint-rule-identical-pattern@1.5.9': + resolution: {integrity: sha512-87ZDHyjYuHw/uAPATtrRgppU7AmTmhO3DZhzM8MO0H3hDg2pw2XJiwOAUI2zGuX5ZBHPmwU4d/L9HHP0rlSciQ==} + + '@inlang/message-lint-rule-missing-translation@1.4.8': + resolution: {integrity: sha512-TS2g9giH04BIDgUyvY66R5JP5yG8aGfjufV7GAUHlkg1cv5bSDErsyQ7lRl3UI2tIklm6/i8m8sRkHJngS3CXA==} + + '@inlang/message-lint-rule-valid-js-identifier@1.0.8': + resolution: {integrity: sha512-qSr5jvEsF957Zb/m5W6UsBT0PtRaSJ2cfk8J+3CULgrRYOOBk3trPspW8UapakrxMFlKVZk4A+2HxHO0ISG8kg==} + + '@inlang/message-lint-rule-without-source@1.4.8': + resolution: {integrity: sha512-S19cJVsSo66tWjWYeXt9FN1n2FjdpPCDJqThMxtXQWsPB9HN7uFkWy10vyXLGIzBmn2uxEpl6nhGFB9TuPnNmw==} '@inlang/message-lint-rule@1.4.7': resolution: {integrity: sha512-FCiFe/H25fqhsIb/YTb0K7eDJqEYzdr6ectF0xG4zARiS7nXz0FHxk2niJrIO8kFkB4mx6tszsgQ0xqD5cHQag==} + deprecated: use the inlang sdk directly https://www.npmjs.com/package/@inlang/sdk peerDependencies: '@sinclair/typebox': ^0.31.17 '@inlang/message@2.1.0': resolution: {integrity: sha512-Gr3wiErI7fW4iW11xgZzsJEUTjlZuz02fB/EO+ENTBlSHGyI1kzbCCeNqLr1mnGdQYiOxfuZxY0S4G5C6Pju3Q==} + deprecated: use the inlang sdk directly https://www.npmjs.com/package/@inlang/sdk peerDependencies: '@sinclair/typebox': ^0.31.17 @@ -506,11 +546,15 @@ packages: '@inlang/paraglide-vite@1.3.5': resolution: {integrity: sha512-yLa+gxA8el6RXXneeiqTnV9Od4Yh389lA+wSfiS+jDXY5vV/2j7Lpk2yuATLmxwI9i2nMP6c6yu8L0X77PA9dg==} + '@inlang/plugin-m-function-matcher@0.9.36': + resolution: {integrity: sha512-TDZlnc/wm7VQ31fvwqx4smtc/j3cAK9bKxq0pu+Ue+ONj/seDnqTGgFXQSzWgDMTzjnmD4jYK9+ZVrTPiJX3tw==} + '@inlang/plugin-message-format@2.2.0': resolution: {integrity: sha512-6MJLExr3OLqbR8gCP4UEgNMgdaJFFCug2GLmFwid7Ana4kObnbCA33YN3m3eN8p+lmnv7zpfW7oeyTZXZLoptg==} '@inlang/plugin@2.4.14': resolution: {integrity: sha512-HFI1t1tKs6jXqwKVl59vvt7kvMgg2Po7xA3IFijfJTZCt0tTI8txqeXCUV9jhUop29Hqj6a5zQd32BYv33Dulw==} + deprecated: use the inlang sdk directly https://www.npmjs.com/package/@inlang/sdk peerDependencies: '@sinclair/typebox': ^0.31.17 @@ -542,6 +586,7 @@ packages: '@inlang/translatable@1.3.1': resolution: {integrity: sha512-VAtle21vRpIrB+axtHFrFB0d1HtDaaNj+lV77eZQTJyOWbTFYTVIQJ8WAbyw9eu4F6h6QC2FutLyxjMomxfpcQ==} + deprecated: no longer used '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -2659,6 +2704,35 @@ snapshots: dependencies: '@sinclair/typebox': 0.31.28 + '@inlang/message-lint-rule-empty-pattern@1.4.8(@sinclair/typebox@0.31.28)': + dependencies: + '@inlang/message-lint-rule': 1.4.7(@sinclair/typebox@0.31.28) + transitivePeerDependencies: + - '@sinclair/typebox' + + '@inlang/message-lint-rule-identical-pattern@1.5.9': + dependencies: + '@inlang/message-lint-rule': 1.4.7(@sinclair/typebox@0.31.28) + '@sinclair/typebox': 0.31.28 + + '@inlang/message-lint-rule-missing-translation@1.4.8(@sinclair/typebox@0.31.28)': + dependencies: + '@inlang/message-lint-rule': 1.4.7(@sinclair/typebox@0.31.28) + transitivePeerDependencies: + - '@sinclair/typebox' + + '@inlang/message-lint-rule-valid-js-identifier@1.0.8(@sinclair/typebox@0.31.28)': + dependencies: + '@inlang/message-lint-rule': 1.4.7(@sinclair/typebox@0.31.28) + transitivePeerDependencies: + - '@sinclair/typebox' + + '@inlang/message-lint-rule-without-source@1.4.8(@sinclair/typebox@0.31.28)': + dependencies: + '@inlang/message-lint-rule': 1.4.7(@sinclair/typebox@0.31.28) + transitivePeerDependencies: + - '@sinclair/typebox' + '@inlang/message-lint-rule@1.4.7(@sinclair/typebox@0.31.28)': dependencies: '@inlang/json-types': 1.1.0(@sinclair/typebox@0.31.28) @@ -2735,6 +2809,15 @@ snapshots: - debug - supports-color + '@inlang/plugin-m-function-matcher@0.9.36(@sinclair/typebox@0.31.28)': + dependencies: + '@inlang/plugin': 2.4.14(@sinclair/typebox@0.31.28) + '@inlang/sdk': 0.36.3 + transitivePeerDependencies: + - '@sinclair/typebox' + - babel-plugin-macros + - supports-color + '@inlang/plugin-message-format@2.2.0': {} '@inlang/plugin@2.4.14(@sinclair/typebox@0.31.28)': diff --git a/project.inlang/settings.json b/project.inlang/settings.json index 3c4d8ee..a99f2c9 100644 --- a/project.inlang/settings.json +++ b/project.inlang/settings.json @@ -1,14 +1,14 @@ { "$schema": "https://inlang.com/schema/project-settings", - "modules": [ - "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@1/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-identical-pattern@1/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@1/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@1/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-valid-js-identifier@1/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@2/dist/index.js", - "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@0/dist/index.js" - ], + "modules": [ + "./node_modules/@inlang/message-lint-rule-empty-pattern/dist/index.js", + "./node_modules/@inlang/message-lint-rule-identical-pattern/dist/index.js", + "./node_modules/@inlang/message-lint-rule-missing-translation/dist/index.js", + "./node_modules/@inlang/message-lint-rule-without-source/dist/index.js", + "./node_modules/@inlang/message-lint-rule-valid-js-identifier/dist/index.js", + "./node_modules/@inlang/plugin-message-format/dist/index.js", + "./node_modules/@inlang/plugin-m-function-matcher/dist/index.js" + ], "plugin.inlang.messageFormat": { "pathPattern": "./messages/{languageTag}.json" },