diff --git a/.gitignore b/.gitignore index da872c6..aadbc7f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ dist/ node_modules/ test/out/ playwright-report/ +test-results/ /index.js /yaml.worker.js *.log diff --git a/package-lock.json b/package-lock.json index 559434e..1d471a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "jsonc-parser": "^3.0.0", "monaco-languageserver-types": "^0.2.0", "monaco-marker-data-provider": "^1.0.0", + "monaco-types": "^0.1.0", "monaco-worker-manager": "^2.0.0", "path-browserify": "^1.0.0", "prettier": "^2.0.0", @@ -30,6 +31,7 @@ "eslint": "^8.0.0", "eslint-config-remcohaszing": "^9.0.0", "monaco-editor": "^0.41.0", + "playwright-monaco": "^1.0.0", "remark-cli": "^11.0.0", "remark-preset-remcohaszing": "^1.0.0", "typescript": "^5.0.0", @@ -2510,6 +2512,12 @@ "node": ">= 12.0.0" } }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -3000,7 +3008,6 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "peer": true, "dependencies": { "path-type": "^4.0.0" }, @@ -4075,7 +4082,6 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, - "peer": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -4092,7 +4098,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "peer": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4205,6 +4210,119 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/find-cache-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-5.0.0.tgz", + "integrity": "sha512-OuWNfjfP05JcpAP3JPgAKUhWefjMRfI5iAoSsvE24ANYWJaepAtlSgWECSVEuRgSXpyNEc9DJwG/TZpgcOqyig==", + "dev": true, + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -6211,7 +6329,6 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, - "peer": true, "engines": { "node": ">= 8" } @@ -7605,7 +7722,6 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -7697,6 +7813,55 @@ "node": ">=16" } }, + "node_modules/playwright-monaco": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/playwright-monaco/-/playwright-monaco-1.2.1.tgz", + "integrity": "sha512-ft6BTLOD+0dkTjr3uknYKmudD9eaBJcJF/xUne3GXdk4KYVtrwfQTqAaicMf5gwiZaidBEqO5vscdA92ppZiWA==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.0", + "find-cache-dir": "^5.0.0", + "globby": "^13.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + }, + "peerDependencies": { + "@playwright/test": "^1.0.0", + "monaco-editor": ">=0.33.0" + } + }, + "node_modules/playwright-monaco/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/playwright-monaco/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", diff --git a/package.json b/package.json index 8b32e1f..6d64a9f 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "eslint": "^8.0.0", "eslint-config-remcohaszing": "^9.0.0", "monaco-editor": "^0.41.0", + "playwright-monaco": "^1.0.0", "remark-cli": "^11.0.0", "remark-preset-remcohaszing": "^1.0.0", "typescript": "^5.0.0", diff --git a/playwright.config.ts b/playwright.config.ts index 4c47c98..9f60657 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,12 +1,14 @@ -import { type PlaywrightTestConfig } from '@playwright/test' +import { defineConfig } from '@playwright/test' +import { createServer } from 'playwright-monaco' -const config: PlaywrightTestConfig = { - reporter: 'html', - timeout: 120_000, - webServer: { - command: 'node test/serve.js', - port: 3000, - reuseExistingServer: !process.env.CI +export default defineConfig({ + expect: { timeout: 10_000 }, + timeout: 60_000, + use: { + baseURL: await createServer({ + setup: './test/setup', + yaml: './yaml.worker' + }), + colorScheme: 'dark' } -} -export default config +}) diff --git a/test/build.js b/test/build.js deleted file mode 100644 index 5387704..0000000 --- a/test/build.js +++ /dev/null @@ -1,17 +0,0 @@ -import { fileURLToPath } from 'node:url' - -import { build } from 'esbuild' - -await build({ - entryPoints: { - 'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js', - 'yaml.worker': fileURLToPath(new URL('../yaml.worker.js', import.meta.url)), - index: fileURLToPath(new URL('index.ts', import.meta.url)) - }, - bundle: true, - format: 'iife', - outdir: fileURLToPath(new URL('out/', import.meta.url)), - loader: { - '.ttf': 'file' - } -}) diff --git a/test/index.html b/test/index.html deleted file mode 100644 index 5cd02e6..0000000 --- a/test/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - -
- - - diff --git a/test/index.ts b/test/index.ts deleted file mode 100644 index 07a2e3e..0000000 --- a/test/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as monaco from 'monaco-editor' -import { type SchemasSettings, setDiagnosticsOptions } from 'monaco-yaml' - -self.MonacoEnvironment = { - getWorkerUrl(workerId, label) { - if (label === 'yaml') { - return 'out/yaml.worker.js' - } - return 'out/editor.worker.js' - } -} - -const schema: SchemasSettings = { - fileMatch: ['*'], - uri: 'http://schemas/my-schema.json', - schema: { - type: 'object', - properties: { - p1: { - description: 'number property', - type: 'number' - }, - p2: { - type: 'boolean' - } - } - } -} - -setDiagnosticsOptions({ - schemas: [schema] -}) -const value = 'p1: \np2: \n' - -monaco.editor.create(document.querySelector('#editor')!, { - language: 'yaml', - tabSize: 2, - value -}) diff --git a/test/marker-data.test.ts b/test/marker-data.test.ts index 932f751..2014ad6 100644 --- a/test/marker-data.test.ts +++ b/test/marker-data.test.ts @@ -1,24 +1,36 @@ -import { expect, type Page, test } from '@playwright/test' +import { expect } from '@playwright/test' +import { test } from 'playwright-monaco' -let page: Page - -test.beforeAll(async ({ browser }) => { - page = await browser.newPage() - await page.goto('') -}) - -test.afterAll(async () => { - await page.close() -}) - -test.describe('Marker data', () => { - test('should display warning when type is incorrect', async () => { - await page.locator('.view-lines').hover({ position: { x: 30, y: 10 } }) - const warn = page.locator('.marker.hover-contents > span:nth-child(1)') - await expect(warn).toHaveText('Incorrect type. Expected "number".') - }) - - test('should underline warning when type is incorrect', async () => { - await expect(page.locator('.cdr.squiggly-warning')).toHaveCount(2) - }) +test('schema validation', async ({ editor }) => { + await editor.createModel('p1: \np2: \n', 'file:///example.yaml', true) + // eslint-disable-next-line @typescript-eslint/no-empty-function + const markers = await editor.waitForMarkers('file:///example.yaml', async () => {}) + expect(markers).toStrictEqual([ + { + code: '0', + endColumn: 5, + endLineNumber: 1, + message: 'Incorrect type. Expected "number".', + owner: 'yaml', + resource: 'file:///example.yaml', + severity: 4, + source: 'yaml-schema: http://schemas/my-schema.json', + startColumn: 5, + startLineNumber: 1, + tags: undefined + }, + { + code: '0', + endColumn: 5, + endLineNumber: 2, + message: 'Incorrect type. Expected "boolean".', + owner: 'yaml', + resource: 'file:///example.yaml', + severity: 4, + source: 'yaml-schema: http://schemas/my-schema.json', + startColumn: 5, + startLineNumber: 2, + tags: undefined + } + ]) }) diff --git a/test/serve.js b/test/serve.js deleted file mode 100644 index 1294c12..0000000 --- a/test/serve.js +++ /dev/null @@ -1,33 +0,0 @@ -import { readFile } from 'node:fs/promises' -import http from 'node:http' -import { extname } from 'node:path' - -import './build.js' - -const contentTypes = { - '.html': 'text/html', - '.js': 'text/javascript', - '.css': 'text/css', - '.ttf': 'font/ttf' -} - -http - .createServer(async (req, res) => { - const file = req.url === '/' ? 'index.html' : req.url.slice(1) - const url = new URL(file, import.meta.url) - const ext = extname(url.pathname) - try { - const content = await readFile(url) - res.setHeader('Content-type', contentTypes[ext] ?? 'text/plain') - res.end(content) - } catch (err) { - if (err.code === 'ENOENT') { - res.writeHead(404, 'Not Found') - } else { - res.writeHead(500, 'Internal server error') - } - res.end(String(err)) - } - }) - // eslint-disable-next-line no-console - .listen(3000, () => console.log('listening...')) diff --git a/test/setup.ts b/test/setup.ts new file mode 100644 index 0000000..25a5ae1 --- /dev/null +++ b/test/setup.ts @@ -0,0 +1,23 @@ +import { configureMonacoYaml, type SchemasSettings } from 'monaco-yaml' +import { monaco } from 'playwright-monaco' + +const schema: SchemasSettings = { + fileMatch: ['*'], + uri: 'http://schemas/my-schema.json', + schema: { + type: 'object', + properties: { + p1: { + description: 'number property', + type: 'number' + }, + p2: { + type: 'boolean' + } + } + } +} + +configureMonacoYaml(monaco, { + schemas: [schema] +})