From 9ff965704d8c2aaf41223016b9799f7cad218603 Mon Sep 17 00:00:00 2001 From: Nicholas Rice <3213292+nicholasrice@users.noreply.github.com> Date: Thu, 17 Feb 2022 10:17:41 -0800 Subject: [PATCH] feat: adds FASTElementRenderer to fast-ssr (#5613) * adds FASTElementRenderer as a ElementRenderer implementation * adding test * adding eslint for file extensions * re-structure tests to better support dependency structures * Fixing tests for FASTElementRenderer.matchesClass * adding code comments * Update packages/web-components/fast-ssr/src/element-renderer/element-renderer.ts Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com> Co-authored-by: nicholasrice Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com> --- .../web-components/fast-ssr/.eslintrc.cjs | 6 ++ packages/web-components/fast-ssr/package.json | 9 ++- ...wright.config.ts => playwright.config.cjs} | 6 +- .../web-components/fast-ssr/server/server.ts | 2 +- .../elemenent-renderer.spec.ts | 17 +++++ .../src/element-renderer/element-renderer.ts | 74 +++++++++++++++++++ .../fast-style}/fast-style.spec.ts | 0 packages/web-components/fast-ssr/src/index.ts | 2 +- .../web-components/fast-ssr/src/tsconfig.json | 3 +- .../fast-ssr/test/example.spec.ts | 10 --- .../web-components/fast-ssr/test/package.json | 5 -- .../fast-ssr/test/tsconfig.json | 9 --- .../web-components/fast-ssr/tsconfig.json | 1 + 13 files changed, 110 insertions(+), 34 deletions(-) create mode 100644 packages/web-components/fast-ssr/.eslintrc.cjs rename packages/web-components/fast-ssr/{test/playwright.config.ts => playwright.config.cjs} (51%) create mode 100644 packages/web-components/fast-ssr/src/element-renderer/elemenent-renderer.spec.ts create mode 100644 packages/web-components/fast-ssr/src/element-renderer/element-renderer.ts rename packages/web-components/fast-ssr/{test => src/fast-style}/fast-style.spec.ts (100%) delete mode 100644 packages/web-components/fast-ssr/test/example.spec.ts delete mode 100644 packages/web-components/fast-ssr/test/package.json delete mode 100644 packages/web-components/fast-ssr/test/tsconfig.json diff --git a/packages/web-components/fast-ssr/.eslintrc.cjs b/packages/web-components/fast-ssr/.eslintrc.cjs new file mode 100644 index 00000000000..82074b3cb5e --- /dev/null +++ b/packages/web-components/fast-ssr/.eslintrc.cjs @@ -0,0 +1,6 @@ +module.exports = { + extends: ["@microsoft/eslint-config-fast-dna", "prettier"], + rules: { + "import/extensions": ["error", "always"], + }, +}; diff --git a/packages/web-components/fast-ssr/package.json b/packages/web-components/fast-ssr/package.json index cdcb62fa1ec..a9cf3c7a1d3 100644 --- a/packages/web-components/fast-ssr/package.json +++ b/packages/web-components/fast-ssr/package.json @@ -17,13 +17,16 @@ "scripts": { "build": "tsc -b --clean src && tsc -b src", "build-server": "tsc -b server", - "pretest": "npm run build-server", - "test": "playwright test -c test", + "eslint": "eslint . --ext .ts", + "eslint:fix": "eslint . --ext .ts --fix", + "pretest": "npm run build-server && npm run build", + "test": "playwright test --config=playwright.config.cjs", "test-server": "node server/dist/server.js", "install-playwright-browsers": "npx playwright install" }, "description": "A package for rendering FAST components outside the browser.", - "main": "index.js", + "main": "./dist/esm/index.js", + "types": "./dist/dts/index.d.ts", "private": true, "dependencies": { "@lit-labs/ssr": "^1.0.0-rc.2", diff --git a/packages/web-components/fast-ssr/test/playwright.config.ts b/packages/web-components/fast-ssr/playwright.config.cjs similarity index 51% rename from packages/web-components/fast-ssr/test/playwright.config.ts rename to packages/web-components/fast-ssr/playwright.config.cjs index 4b048b7ff22..3bd6075cf09 100644 --- a/packages/web-components/fast-ssr/test/playwright.config.ts +++ b/packages/web-components/fast-ssr/playwright.config.cjs @@ -1,6 +1,5 @@ -// playwright.config.ts -import { PlaywrightTestConfig } from "@playwright/test"; -const config: PlaywrightTestConfig = { +module.exports = { + testDir: "./dist/esm", webServer: { command: "npm run test-server", port: 8080, @@ -8,4 +7,3 @@ const config: PlaywrightTestConfig = { reuseExistingServer: false, }, }; -export default config; diff --git a/packages/web-components/fast-ssr/server/server.ts b/packages/web-components/fast-ssr/server/server.ts index 866fa10b5e8..0507d622326 100644 --- a/packages/web-components/fast-ssr/server/server.ts +++ b/packages/web-components/fast-ssr/server/server.ts @@ -47,7 +47,7 @@ function handleStyleRequest(req: Request, res: Response) { function handleStyleScriptRequest(req: Request, res: Response) { res.set("Content-Type", "application/javascript"); fs.readFile( - path.resolve(__dirname, "./dist/fast-style/index.js"), + path.resolve(__dirname, "./dist/esm/fast-style/index.js"), { encoding: "utf8" }, (err, data) => { const stream = (Readable as any).from(data); diff --git a/packages/web-components/fast-ssr/src/element-renderer/elemenent-renderer.spec.ts b/packages/web-components/fast-ssr/src/element-renderer/elemenent-renderer.spec.ts new file mode 100644 index 00000000000..717eb76599f --- /dev/null +++ b/packages/web-components/fast-ssr/src/element-renderer/elemenent-renderer.spec.ts @@ -0,0 +1,17 @@ +import "@lit-labs/ssr/lib/install-global-dom-shim.js"; +import { FASTElement } from "@microsoft/fast-element"; +import { expect, test } from '@playwright/test'; +import { FASTElementRenderer } from "./element-renderer.js"; + +test.describe("FASTElementRenderer", () => { + test.describe("should have a 'matchesClass' method", () => { + test("that returns true when invoked with a class that extends FASTElement ", () => { + class MyElement extends FASTElement {} + expect(FASTElementRenderer.matchesClass(MyElement)).toBe(true); + }); + test("that returns false when invoked with a class that does not extend FASTElement ", () => { + class MyElement extends HTMLElement {} + expect(FASTElementRenderer.matchesClass(MyElement)).toBe(false); + }); + }) +}) diff --git a/packages/web-components/fast-ssr/src/element-renderer/element-renderer.ts b/packages/web-components/fast-ssr/src/element-renderer/element-renderer.ts new file mode 100644 index 00000000000..11980a038f7 --- /dev/null +++ b/packages/web-components/fast-ssr/src/element-renderer/element-renderer.ts @@ -0,0 +1,74 @@ +import { ElementRenderer, RenderInfo } from "@lit-labs/ssr"; +import { FASTElement } from "@microsoft/fast-element"; + +export class FASTElementRenderer extends ElementRenderer { + /** + * The element instance represented by the {@link FASTElementRenderer}. + */ + public readonly element!: FASTElement; + + /** + * Tests a constructor to determine if it should be managed by a {@link FASTElementRenderer}. + * @param ctor - The constructor to test. + */ + public static matchesClass(ctor: typeof HTMLElement): boolean { + return ctor.prototype instanceof FASTElement; + } + + /** + * Indicate to the {@link FASTElementRenderer} that the instance should execute DOM connection behavior. + */ + public connectedCallback(): void { + this.element.connectedCallback(); + } + + /** + * Constructs a new {@link FASTElementRenderer}. + * @param tagName - the tag-name of the element to create. + */ + constructor(tagName: string) { + super(tagName); + + const ctor: typeof FASTElement | null = customElements.get(this.tagName); + + if (ctor) { + this.element = new ctor(); + } else { + throw new Error( + `FASTElementRenderer was unable to find a constructor for a custom element with the tag name '${tagName}'.` + ); + } + } + + /** + * Renders the component internals to light DOM instead of shadow DOM. + * @param renderInfo - information about the current rendering context. + */ + *renderLight(renderInfo: RenderInfo): IterableIterator { + // TODO - this will yield out the element's template using the template renderer, skipping any shadow-DOM specific emission. + yield ""; + } + + /** + * Render the component internals to shadow DOM. + * @param renderInfo - information about the current rendering context. + */ + *renderShadow(renderInfo: RenderInfo): IterableIterator { + // TODO - this will yield out the element's template using the template renderer + yield ""; + } + + /** + * Indicate to the {@link FASTElementRenderer} that an attribute has been changed. + * @param name - The name of the changed attribute + * @param old - The old attribute value + * @param value - The new attribute value + */ + attributeChangedCallback( + name: string, + old: string | null, + value: string | null + ): void { + this.element.attributeChangedCallback(name, old, value); + } +} diff --git a/packages/web-components/fast-ssr/test/fast-style.spec.ts b/packages/web-components/fast-ssr/src/fast-style/fast-style.spec.ts similarity index 100% rename from packages/web-components/fast-ssr/test/fast-style.spec.ts rename to packages/web-components/fast-ssr/src/fast-style/fast-style.spec.ts diff --git a/packages/web-components/fast-ssr/src/index.ts b/packages/web-components/fast-ssr/src/index.ts index 62073af2a0f..09491d50f08 100644 --- a/packages/web-components/fast-ssr/src/index.ts +++ b/packages/web-components/fast-ssr/src/index.ts @@ -1 +1 @@ -export default "fast-ssr"; +export { FASTElementRenderer } from "./element-renderer/element-renderer.js"; diff --git a/packages/web-components/fast-ssr/src/tsconfig.json b/packages/web-components/fast-ssr/src/tsconfig.json index 8b2f5bed380..d7363176aab 100644 --- a/packages/web-components/fast-ssr/src/tsconfig.json +++ b/packages/web-components/fast-ssr/src/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "composite": true, "rootDir": ".", - "outDir": "../dist", + "outDir": "../dist/esm", + "declarationDir": "../dist/dts", "lib": [ "dom", "esnext" diff --git a/packages/web-components/fast-ssr/test/example.spec.ts b/packages/web-components/fast-ssr/test/example.spec.ts deleted file mode 100644 index 73c85108fa9..00000000000 --- a/packages/web-components/fast-ssr/test/example.spec.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { test, expect, ElementHandle } from '@playwright/test'; -import fastSSR from "../src"; - -test("example module test", async () => { - expect(fastSSR).toBe("fast-ssr"); -}) -test("example server test", async ({ page }) => { - await page.goto("/"); - expect(await page.innerText('body')).toBe("hello world"); -}); diff --git a/packages/web-components/fast-ssr/test/package.json b/packages/web-components/fast-ssr/test/package.json deleted file mode 100644 index 890f891f972..00000000000 --- a/packages/web-components/fast-ssr/test/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "commonjs", - "comment": "This allows Playwright to handle TS compilation for us", - "private": true -} \ No newline at end of file diff --git a/packages/web-components/fast-ssr/test/tsconfig.json b/packages/web-components/fast-ssr/test/tsconfig.json deleted file mode 100644 index 2ba585452cf..00000000000 --- a/packages/web-components/fast-ssr/test/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "rootDir": ".", - "outDir": "dist", - "declaration": false - }, - "references": [{ "path": "../src"}] -} diff --git a/packages/web-components/fast-ssr/tsconfig.json b/packages/web-components/fast-ssr/tsconfig.json index cf4cd344bc2..4cd3f5779d5 100644 --- a/packages/web-components/fast-ssr/tsconfig.json +++ b/packages/web-components/fast-ssr/tsconfig.json @@ -9,6 +9,7 @@ "emitDecoratorMetadata": true, "noEmitOnError": true, "strict": true, + "skipLibCheck": true, "lib": [ "dom", "esnext"